UltraSonic Sensor + Simulino



Vamos simular o UltraSonic Sensor?










Olá, seja bem vindo.

 Hoje irei demonstrar como simular um sensor ultrasônico (UltraSonic Sensor), aquele mesmo que serve para medir distância entre objetos, ou mesmo usado em robôs para que os mesmos não venham à colidir com algum obstáculo, dentre tantas outras aplicações.

Segue imagem do sensor abaixo:



Agora temos nosso sensor simulador no Proteus:




Para quem não conhece ainda este sensor, é bem fácil de entender o seu funcionamento.

Conforme diagrama mais adiante, o que acontece é que este sensor possui um microcontrolador responsável por gerar os pulsos ultrassônicos  que serão emitidos através de um destes transdutores instalados no shield do sensor. E após a emissão deste pulso, ele fica aguardando o retorno do mesmo, para que seja interpretada a distância que este pulso percorreu até o objeto.
Dependendo do tempo entre o pulso emitido e o pulso recebido pelo outro transdutor, o microcontrolador do sensor vai gerar outro pulso chamado de ECHO para a placa de controle.







O segredo está na duração do pulso que o sensor gera para a placa de controle.
Como alguns sensores tem características muito semelhantes, resolvi criar um programa para um microcontrolador (PIC nesta primeira versão) ,a simulação deste pulso de ECHO.




Explicando um pouco sobre  o funcionamento, o sensor Ultrassônico fica aguardando um pulso de Trigger (gatilho) para simular a recepção do pulso e então envia um pulso de ECHO para a placa de controle por um período de tempo. A placa de controle é responsável por interpretar a distância. Então para isto ela efetua a medição da duração do pulso de ECHO, que entra na seguinte fórmula:

Distância em cm = ( Duração do Pulso em microssegundos) / 58

ou

Distância em polegadas = (Duração do Pulso em microssegundos) / 148

Pegando o exemplo da figura acima, vemos que o pulso teve duração de 4,93ms, ou seja, esse pulso corresponde a 4930us. 

Para termos o valor em centímetros, devemos dividir este valor por 58, resultando em: 85 cm

Então alguém me pergunta: "Mas no diagrama não está 84cm?" Responderei: "Sim meu caro Sherlock Holmes!rs", o que acontece é que esta pequena diferença é devido aos erros de aproximação nos cálculos e também pelo fato de que para a medição do pulso de entrada no microcontrolador na placa de controle, existe uma precisão agregada à configuração dos timers internos e também ao sistema de clock do mesmo.
Examinando o programa de exemplo, vemos a seguinte chamada de função:


duration = pulseIn(echoPin, HIGH);

Sendo que para saber qual será o erro agregado ao valor dado pela função "pulseIn", devemos abrir a biblioteca do mesmo e estudar a configuração de timer e clock.



Vamos simular? 




Funcionamento do Sensor Simulado:

Para facilitar o uso deste simulador no Proteus, e para que possamos ajustar a distância do nosso objeto simulado, fiz nesta primeira versão a referência como sendo um valor de tensão ou sinal analógico diretamente acoplado em um dos pinos do microcontrolador PIC16.

Basicamente o que ele faz é transformar a referência em volts para um valor de distância, gerando um pulso de ECHO proporcional na saída. Sendo que para ele emitir esse pulso de ECHO é necessário manter o pino de Trigger em nível alto por pelo menos 10us (microssegundos), conforme sensores comuns.


Para sabermos o valor de tensão que deve ser aplicado, existe uma pequena fórmula:

Valor de tensão em Volts = ( Valor da distância em cm ) / 225,76

Por exemplo, queremos simular uma distância de 5m (metros), que corresponde a 500cm (centímetros).
Para ter-se o valor de tensão, faremos: 500 / 225,76 = 2,21 V (volts)

Ou seja, tem-se que colocar o valor de 2,21V na entrada do pino RA0 (pino 2) do microcontrolador do sensor.
O interessante é que como é um valor analógico, fica fácil de criar diversas configurações de entrada, para simular por exemplo um objeto se afastando ou se aproximando da sua placa de controle ou robô. Que é o mais desejado.

Então, após configurado o valor de tensão para a distância do objeto, basta carregar no microcontrolador PIC16F1936 do sensor o arquivo UltraSonicSensorPIC16F.HEX que está dentro da pasta Source do projeto.
E na placa do simulino, pode ser utilizado o programa de exemplo incluído no projeto, devendo o mesmo ser compilado, ou então utilizado o arquivo UltraSonic_Shield.cpp.hex. Devendo o mesmo ser carregado no microcontrolador ATmega do Simulino.

Logo estarei postando o vídeo tutorial.

Até o próximo post.






LCD Keypad Shield + Simulino


Vamos simular o LCD Keypad Shield?


 Tutorial no Youtube: http://youtu.be/Xzee937xzaE



[DOWNLOAD]

Hoje irei demonstrar mais um modo para simularmos nossos queridos projetos, e em especial aquele shield bem conhecido por nós hobbistas das plataforma Arduino, que é o KEYPAD SHIELD, aquele que possui
um display LCD 16x2 e alguns botões.

Segue imagem do mesmo abaixo:

Para quem explorou seu esquema elétrico, pode perceber que ele é bastante otimizado. Proporcionando uma boa otimização quanto à quantidade de pinos necessárias para seu funcionamento.

 Observando apenas o conjunto do Display LCD, são utilizados apenas 6 pinos, sendo eles o sinal de EN, RS, D7,D6,D5 e D4. Ou seja, ele utiliza 2 pinos para o controle padrão destes displays ( EN e RS), e mais 4 pinos para o envio de dados e comandos, que são:  D7, D6, D5 e D4.

Agora para o conjunto de botões, temos uma implementação bem interessante, pois para a maioria deles é utilizado uma cadeia de divisores de tensão, para assim permitir que seja utilizado apenas "1" pino da nossa placa do Arduino. Ou seja, ao invés de utilizarmos 5 pinos para controlar 5 botões, são necessários apenas 1 pino, tendo como premissa que não estaremos lendo um sinal digital e sim um sinal analógico para podermos indentificar qual foi o botão pressionado.

Mas agora alguém me pergunta: "Mas não existem 6 botões?" Responderei: "Sim meu caro Sherlock Holmes!rs", o que acontece é que o Botão de Reset não pode ser adicionado à estes divisores de tensão, pois ele precisa ir diretamente acoplado no pino de reset, por isso ele se encontra em um pino separado.

Vendo o esquema elétrico, podemos observar isto:



Vamos simular? 



Como este shield é acoplado em nossas placas do Arduino, vamos nos utilizar do nosso simulador do Arduino, o SIMULINO, e dentro deste projeto eu adicionei mais um bloco de circuitos referentes ao Keypad Shield, já com seus botões de controle e LCD.

Segue um exemplo da ligação entre as placas.:


Onde são interconectados os sinais de terra (Gnd), Reset, AN0 (sinal analógico dos botões), e os sinais do Display LCD (EN,RS,D7,D6,D5 e D4).

Foi adicionado um Terminal Serial, para que sejam exibidas nossas mensagens de debug. Ele não precisa ser retirado, e funciona como nosso debug utilizado através da Serial Virtual da nossa IDE (ou plataforma de programação ).


 Dentro do Keypad Shield, nos deparamos com o seguinte esquema:


 Tendo a disposição dos botões parecidas com a que utilizamos em nosso shield, para ficar bem familiar.

Aqui você só precisa controlar conforme  o shield, apertando os botões e verificando o seu funcionamento.

;-----------------------------------------------------------------------------------
 Observação:

Existe um possível "bug" no simulador Proteus, mas tenham calma, é fácil para contorná-lo. 
Ainda estou verificando se acontece em outros microcomputadores ou se é apenas no meu.
O que acontece é que quando iniciamos o simulador, devemos estar com o bloco do Keypad Shield aberto, ou seja, devemos estar dentro da planta do shield, tendo tal visão:

 
Pois se o simulador for aberto fora deste bloco, aparentemente a simulação referente ao Display LCD não funciona de modo à liga-lo. Aparentemente ele não liga se não estivermos vendo ele.
Então é simples, basta iniciar a simulação com esta janela aberta que tudo irá funcionar.
;-----------------------------------------------------------------------------------


Logo estarei fazendo um vídeo para mostrar como fica a simulação.

Os arquivos estão dividos em pastas, com os esquemas e a imagem do Shield.
Dentro da pasta dos fontes (source), foram adicionados dois projetos: um para as placas do Arduino com o compilador padrão dele, onde os arquivos terminam com *.ino , e outro para as placas do Chipkit, pois para o compilador deles a extensão do arquivo é o *.pde .  

Observem bem antes de abri-los. ^^ 

;-----------------------------------------------------------------------------------
 Observação:
 Dentro do código fonte, foram adicionados 3 tipos de configurações de pinos para o shield
porque já me deparei com 3 tipos de pinagens diferentes.
Caso o shield não funcione da primeira vez, tenha calma, provavelmente você precisa
verificar qual é a configuração correta para o seu shield. 
As mais utilizadas já estão dentro do arquivo fonte.    
;-----------------------------------------------------------------------------------


Foram adicionados os *.hex e o *.elf, para quem quiser apenas simular sem compilar, e quem sabe fazer o disassembler do projeto.

Estamos esperando seus comentários. Não deixem de comentar.

Até o próximo post.


  [DOWNLOAD]







chipKIT: adicionando I/O ao Max32



Inclusão de mais um pino de I/O para a PCI Chipkit Max32.

Olá pessoal, neste post estarei indicando como adicionar mais um pino de I/O para o Chipkit Max32.
Após estudar o esquema elétrico da placa e o datasheet do microcontrolador, me deparei com um pino que não estava sendo utilizado.
Claro, para este kit já existe uma quantidade enorme de pinos para serem utilizados, e muitos dos quais já estão compatibilizados com as bibliotecas existentes para a IDE do Arduino. Ficando a opção de incluir este novo pino para soluções onde os demais ports já estariam sendo totalmente utilizados.

A seguir imagens do port em questão no datasheet:


Imagens do port no microcontrolador:

1º) Deve- se alterar os seguintes arquivos existentes no diretório do MPIDE: 

1.1) Adicione as seguintes configurações para o 86º pino.

..\hardware\pic32\variants\Max32\Board_Data.c

-> const uint8_t digital_pin_to_port_PGM[];
                     linha para adicionar :   _IOPORT_PC,        //    86 RC1    T2CK/RC1

-> const uint16_t digital_pin_to_bit_mask_PGM[];
                     linha para adicionar :  _BV( 1 ),        //    86 RC1    T2CK/RC1

-> const uint16_t digital_pin_to_timer_PGM[];
                     linha para adicionar :   NOT_ON_TIMER,        //    86 RC1    T2CK/RC1



1.2) Ou substitua as tabelas por estas já com as linhas inclusas.:
 
/* ------------------------------------------------------------ */
/* This table is used to map the digital pin number to the port
** containing that pin.
*/
const uint8_t digital_pin_to_port_PGM[] = {
    _IOPORT_PF,        //    0 RF2    SDA1A/SDI1A/U1ARX/RF2
    _IOPORT_PF,        //    1 RF8    SCL1A/SDO1A/U1ATX/RF8
    _IOPORT_PE,        //    2 RE8    AERXD0/INT1/RE8
    _IOPORT_PD,        //    3 RD0    SDO1/OC1/INT0/RD0
    _IOPORT_PC,        //    4 RC14    SOSCO/T1CK/CN0/RC14
    _IOPORT_PD,        //    5 RD1    OC2/RD1
    _IOPORT_PD,        //    6 RD2    OC3/RD2
    _IOPORT_PE,        //    7 RE9    AERXD1/INT2/RE9
    _IOPORT_PD,        //    8 RD12    ETXD2/IC5/PMD12/RD12
    _IOPORT_PD,        //    9 RD3    OC4/RD3
    _IOPORT_PD,        //    10 RD4    OC5/PMWR/CN13/RD4
    _IOPORT_PC,        //    11 RC4    T5CK/SDI1/RC4
    _IOPORT_PA,        //    12 RA2    SCL2/RA2
    _IOPORT_PA,        //    13 RA3    SDA2/RA3
    _IOPORT_PF,        //    14 RF13    AC1TX/SCK3A/U3BTX/U3ARTS/RF13
    _IOPORT_PF,        //    15 RF12    AC1RX/SS3A/U3BRX/U3ACTS/RF12
    _IOPORT_PF,        //    16 RF5    SCL3A/SDO3A/U3ATX/PMA8/CN18/RF5
    _IOPORT_PF,        //    17 RF4    SDA3A/SDI3A/U3ARX/PMA9/CN17/RF4
    _IOPORT_PD,        //    18 RD15    AETXD1/SCK1A/U1BTX/U1ARTS/CN21/RD15
    _IOPORT_PD,        //    19 RD14    AETXD0/SS1A/U1BRX/U1ACTS/CN20/RD14
    _IOPORT_PA,        //    20 RA15    AETXEN/SDA1/INT4/RA15
    _IOPORT_PA,        //    21 RA14    AETXCLK/SCL1/INT3/RA14
    _IOPORT_PC,        //    22 RC2    T3CK/AC2TX/RC2
    _IOPORT_PC,        //    23 RC3    T4CK/AC2RX/RC3
    _IOPORT_PC,        //    24 VBUS
    _IOPORT_PF,        //    25 RF3    USBID/RF3
    _IOPORT_PG,        //    26 RG3    D-/RG3
    _IOPORT_PG,        //    27 RG2    D+/RG2
    _IOPORT_PG,        //    28 RG15
    _IOPORT_PG,        //    29 RG7    ECRS/SDA2A/SDI2A/U2ARX/PMA4/CN9/RG7
    _IOPORT_PE,        //    30 RE7    PMD7/RE7
    _IOPORT_PE,        //    31 RE6    PMD6/RE6
    _IOPORT_PE,        //    32 RE5    PMD5/RE5
    _IOPORT_PE,        //    33 RE4    PMD4/RE4
    _IOPORT_PE,        //    34 RE3    PMD3/RE3
    _IOPORT_PE,        //    35 RE2    PMD2/RE2
    _IOPORT_PE,        //    36 RE1    PMD1/RE1
    _IOPORT_PE,        //    37 RE0    PMD0/RE0
    _IOPORT_PD,        //    38 RD10    SCK1/IC3/PMCS2/PMA15/RD10
    _IOPORT_PD,        //    39 RD5    PMRD/CN14/RD5
    _IOPORT_PB,        //    40 RB11    AN11/EREXERR/AETXERR/PMA12/RB11
    _IOPORT_PB,        //    41 RB13    AN13/ERXD1/AECOL/PMA10/RB13
    _IOPORT_PB,        //    42 RB12    AN12/ERXD0/AECRS/PMA11/RB12
    _IOPORT_PG,        //    43 RG8    ERXDV/AERXDV/ECRSDV/AECRSDV/SCL2A/SDO2A/U2ATX/PMA3/CN10/RG8
    _IOPORT_PA,        //    44 RA10    VREF+/CVREF+/AERXD3/PMA6/RA10
    _IOPORT_PF,        //    45 RF0    C1RX/ETXD1/PMD11/RF0
    _IOPORT_PF,        //    46 RF1    C1TX/ETXD0/RMD10/RF1
    _IOPORT_PD,        //    47 RD6    ETXEN/PMD14/CN15/RD6
    _IOPORT_PD,        //    48 RD8    PTCC/EMDIO/AEMDIO/IC1/RD8
    _IOPORT_PD,        //    49 RD11    EMDC/AEMDC/IC4/PMCS1/PMA14/RD11
    _IOPORT_PG,        //    50 RG7    ECRS/SDA2/SDI2A/U2ARX/PMA4/CN9/RG7
    _IOPORT_PG,        //    51 RG8
    _IOPORT_PG,        //    52 RG6    ECOL/SCK2A/U2BTX/U2ARTS/PMA5/CN8/RG6
    _IOPORT_PG,        //    53 RG9    ERXCLK/AERXCLK/EREFCLK/AEREFCLK/SS2A/U2BRX/U2ACTS/PMA2/CN11/RG9
    //*    the analog ports start with 54
    _IOPORT_PB,        //    54    RB0    PGED1/AN0/CN2/RB0
    _IOPORT_PB,        //    55    RB1    PGEC1/AN1/CN3/RB1
    _IOPORT_PB,        //    56    RB2    AN2/C2IN-/CN4/RB2
    _IOPORT_PB,        //    57    RB3    AN3/C2IN+/CN5/RB3
    _IOPORT_PB,        //    58    RB4    AN4/C1IN-/CN6/RB4
    _IOPORT_PB,        //    59    RB5    AN5/C1IN+/VBUSON/CN7/RB5
    _IOPORT_PB,        //    60    RB6    PGEC2/AN6/OCFA/RB6
    _IOPORT_PB,        //    61    RB7    PGED2/AN7/RB7
    _IOPORT_PB,        //    62    RB8    AN8/C1OUT/RB8
    _IOPORT_PB,        //    63    RB9    AN9/C2OUT/RB9
    _IOPORT_PB,        //    64    RB10    AN10/CVREFOUT/PMA13/RB10
    _IOPORT_PB,        //    65    RB11    AN11/EREXERR/AETXERR/PMA12/RB11
    _IOPORT_PB,        //    66    RB12    AN13/ERXD1/AECOL/PMA10/RB13
    _IOPORT_PB,        //    67    RB13    AN12/ERXD0/AECRS/PMA11/RB12
    _IOPORT_PB,        //    68    RB14    AN14/ERXD2/AETXD3/PMALH/PMA1/RB14
    _IOPORT_PB,        //    69    RB15    AN15/ERXD3/AETXD2/OCFB/PMALL/PMA0/CN12/RB15

    //*    Pic32 EXTRAS start here (with #70)
    _IOPORT_PA,        //    70 RA0    TMS/RA0
    _IOPORT_PA,        //    71 RA1    TCK/RA1
    _IOPORT_PA,        //    72 RA4    TDI/RA4
    _IOPORT_PA,        //    73 RA5    TDO/RA5
    _IOPORT_PD,        //    74 RD9    SS1/IC2/RD9
    _IOPORT_PC,        //    75 RC13    SOSCI/CN1/RC13
    _IOPORT_PD,        //    76 RD13    ETXD3/PMD13/CN19/RD13
    _IOPORT_PD,        //    77 RD7    ETXCLK/PMD15/CN16/RD7
    _IOPORT_PG,        //    78 RG1    C2TX/ETXERR/PMD9/RG1
    _IOPORT_PG,        //    79 RG0    C2RX/PMD8/RG0
    _IOPORT_PA,        //    80 RA6    TRCLK/RA6
    _IOPORT_PA,        //    81 RA7    TRD3/RA7
    _IOPORT_PG,        //    82 RG14    TRD2/RG14
    _IOPORT_PG,        //    83 RG12    TRD1/RG12
    _IOPORT_PG,        //    84 RG13    TRD0/RG13
    _IOPORT_PA,        //    85 RA9    VREF-/CVREF0/AERXD2/PMA7/RA9
    _IOPORT_PC,        //    86 RC1    T2CK/RC1
};

/* ------------------------------------------------------------ */
/* This table is used to map from digital pin number to a bit mask
** for the corresponding bit within the port.
*/
const uint16_t digital_pin_to_bit_mask_PGM[] = {
    _BV( 2 ),        //    0 RF2    SDA1A/SDI1A/U1ARX/RF2
    _BV( 8 ),        //    1 RF8    SCL1A/SDO1A/U1ATX/RF8
    _BV( 8 ),        //    2 RE8    AERXD0/INT1/RE8
    _BV( 0 ),        //    3 RD0    SDO1/OC1/INT0/RD0
    _BV( 14 ),        //    4 RC14    SOSCO/T1CK/CN0/RC14
    _BV( 1 ),        //    5 RD1    OC2/RD1
    _BV( 2 ),        //    6 RD2    OC3/RD2
    _BV( 9 ),        //    7 RE9    AERXD1/INT2/RE9
    _BV( 12 ),        //    8 RD12    ETXD2/IC5/PMD12/RD12
    _BV( 3 ),        //    9 RD3    OC4/RD3
    _BV( 4 ),        //    10 RD4    OC5/PMWR/CN13/RD4
    _BV( 4 ),        //    11 RC4    T5CK/SDI1/RC4
    _BV( 2 ),        //    12 RA2    SCL2/RA2
    _BV( 3 ),        //    13 RA3    SDA2/RA3
    _BV( 13 ),        //    14 RF13    AC1TX/SCK3A/U3BTX/U3ARTS/RF13
    _BV( 12 ),        //    15 RF12    AC1RX/SS3A/U3BRX/U3ACTS/RF12
    _BV( 5 ),        //    16 RF5    SCL3A/SDO3A/U3ATX/PMA8/CN18/RF5
    _BV( 4 ),        //    17 RF4    SDA3A/SDI3A/U3ARX/PMA9/CN17/RF4
    _BV( 15 ),        //    18 RD15    AETXD1/SCK1A/U1BTX/U1ARTS/CN21/RD15
    _BV( 14 ),        //    19 RD14    AETXD0/SS1A/U1BRX/U1ACTS/CN20/RD14
    _BV( 15 ),        //    20 RA15    AETXEN/SDA1/INT4/RA15
    _BV( 14 ),        //    21 RA14    AETXCLK/SCL1/INT3/RA14
    _BV( 2 ),        //    22 RC2    T3CK/AC2TX/RC2
    _BV( 3 ),        //    23 RC3    T4CK/AC2RX/RC3
    _BV( 0 ),        //    24 VBUS
    _BV( 3 ),        //    25 RF3    USBID/RF3
    _BV( 3 ),        //    26 RG3    D-/RG3
    _BV( 2 ),        //    27 RG2    D+/RG2
    _BV( 15 ),        //    28 RG15
    _BV( 7 ),        //    29 RG7    ECRS/SDA2A/SDI2A/U2ARX/PMA4/CN9/RG7
    _BV( 7 ),        //    30 RE7    PMD7/RE7
    _BV( 6 ),        //    31 RE6    PMD6/RE6
    _BV( 5 ),        //    32 RE5    PMD5/RE5
    _BV( 4 ),        //    33 RE4    PMD4/RE4
    _BV( 3 ),        //    34 RE3    PMD3/RE3
    _BV( 2 ),        //    35 RE2    PMD2/RE2
    _BV( 1 ),        //    36 RE1    PMD1/RE1
    _BV( 0 ),        //    37 RE0    PMD0/RE0
    _BV( 10 ),        //    38 RD10    SCK1/IC3/PMCS2/PMA15/RD10
    _BV( 5 ),        //    39 RD5    PMRD/CN14/RD5
    _BV( 11 ),        //    40 RB11    AN11/EREXERR/AETXERR/PMA12/RB11
    _BV( 13 ),        //    41 RB13    AN13/ERXD1/AECOL/PMA10/RB13
    _BV( 12 ),        //    42 RB12    AN12/ERXD0/AECRS/PMA11/RB12
    _BV( 8 ),        //    43 RG8    ERXDV/AERXDV/ECRSDV/AECRSDV/SCL2A/SDO2A/U2ATX/PMA3/CN10/RG8
    _BV( 10 ),        //    44 RA10    VREF+/CVREF+/AERXD3/PMA6/RA10
    _BV( 0 ),        //    45 RF0    C1RX/ETXD1/PMD11/RF0
    _BV( 1 ),        //    46 RF1    C1TX/ETXD0/RMD10/RF1
    _BV( 6 ),        //    47 RD6    ETXEN/PMD14/CN15/RD6
    _BV( 8 ),        //    48 RD8    RTCC/EMDIO/AEMDIO/IC1/RD8
    _BV( 11 ),        //    49 RD11    EMDC/AEMDC/IC4/PMCS1/PMA14/RD11
    _BV( 7 ),        //    50 RG7    ECRX/SDA2/SDI2A/U2ARX/PMA4/CN9/RG7
    _BV( 8 ),        //    51 RG8
    _BV( 6 ),        //    52 RG6    ECOL/SCK2A/U2BTX/U2ARTS/PMA5/CN8/RG6
    _BV( 9 ),        //    53 RG9    ERXCLK/AERXCLK/EREFCLK/AEREFCLK/SS2A/U2BRX/U2ACTS/PMA2/CN11/RG9

    //*    the analog ports start with 54
    _BV( 0 ),        //    54    RB0    PGED1/AN0/CN2/RB0
    _BV( 1 ),        //    55    RB1    PGEC1/AN1/CN3/RB1
    _BV( 2 ),        //    56    RB2    AN2/C2IN-/CN4/RB2
    _BV( 3 ),        //    57    RB3    AN3/C2IN+/CN5/RB3
    _BV( 4 ),        //    58    RB4    AN4/C1IN-/CN6/RB4
    _BV( 5 ),        //    59    RB5    AN5/C1IN+/VBUSON/CN7/RB5
    _BV( 6 ),        //    60    RB6    PGEC2/AN6/OCFA/RB6
    _BV( 7 ),        //    61    RB7    PGED2/AN7/RB7
    _BV( 8 ),        //    62    RB8    AN8/C1OUT/RB8
    _BV( 9 ),        //    63    RB9    AN9/C2OUT/RB9
    _BV( 10 ),        //    64    RB10    AN10/CVREFOUT/PMA13/RB10
    _BV( 11 ),        //    65    RB11    AN11/EREXERR/AETXERR/PMA12/RB11
    _BV( 12 ),        //    66    RB12    AN13/ERXD1/AECOL/PMA10/RB13
    _BV( 13 ),        //    67    RB13    AN12/ERXD0/AECRS/PMA11/RB12
    _BV( 14 ),        //    68    RB14    AN14/ERXD2/AETXD3/PMALH/PMA1/RB14
    _BV( 15 ),        //    69    RB15    AN15/ERXD3/AETXD2/OCFB/PMALL/PMA0/CN12/RB15
    //*    Pic32 EXTRAS start here (with #70)

    //*    Pic32 EXTRAS start here (with #70)
    _BV( 0 ),        //    70 RA0    TMS/RA0
    _BV( 1 ),        //    71 RA1    TCK/RA1
    _BV( 4 ),        //    72 RA4    TDI/RA4
    _BV( 5 ),        //    73 RA5    TDO/RA5
    _BV( 9 ),        //    74 RD9    SS1/IC2/RD9
    _BV( 13 ),        //    75 RC13    SOSCI/CN1/RC13
    _BV( 13 ),        //    76 RD13    ETXD3/PMD13/CN19/RD13
    _BV( 7 ),        //    77 RD7    ETXCLK/PMD15/CN16/RD7
    _BV( 1 ),        //    78 RG1    C2TX/ETXERR/PMD9/RG1
    _BV( 0 ),        //    79 RG0    C2RX/PMD8/RG0
    _BV( 6 ),        //    80 RA6    TRCLK/RA6
    _BV( 7 ),        //    81 RA7    TRD3/RA7
    _BV( 14 ),        //    82 RG14    TRD2/RG14
    _BV( 12 ),        //    83 RG12    TRD1/RG12
    _BV( 13 ),        //    84 RG13    TRD0/RG13
    _BV( 9 ),        //    85 RA9    VREF-/CVREF0/AERXD2/PMA7/RA9
    _BV( 1 ),        //    86 RC1    T2CK/RC1
};

/* ------------------------------------------------------------ */
/* This table is used to map from digital pin number to the output
** compare number, input capture number, and timer external clock
** input associated with that pin.
*/
const uint16_t digital_pin_to_timer_PGM[] = {
    NOT_ON_TIMER,        //    0 RF2    SDA1A/SDI1A/U1ARX/RF2
    NOT_ON_TIMER,        //    1 RF8    SCL1A/SDO1A/U1ATX/RF8
    NOT_ON_TIMER,        //    2 RE8    AERXD0/INT1/RE8
    _TIMER_OC1,            //    3 RD0    SDO1/OC1/INT0/RD0
    _TIMER_TCK1,        //    4 RC14    SOSCO/T1CK/CN0/RC14
    _TIMER_OC2,            //    5 RD1    OC2/RD1
    _TIMER_OC3,            //    6 RD2    OC3/RD2
    NOT_ON_TIMER,        //    7 RE9    AERXD1/INT2/RE9
    _TIMER_IC5,            //    8 RD12    ETXD2/IC5/PMD12/RD12
    _TIMER_OC4,            //    9 RD3    OC4/RD3
    _TIMER_OC5,            //    10 RD4    OC5/PMWR/CN13/RD4
    _TIMER_TCK5,        //    11 RC4    T5CK/SDI1/RC4
    NOT_ON_TIMER,        //    12 RA2    SCL2/RA2
    NOT_ON_TIMER,        //    13 RA3    SDA2/RA3
    NOT_ON_TIMER,        //    14 RF13    AC1TX/SCK3A/U3BTX/U3ARTS/RF13
    NOT_ON_TIMER,        //    15 RF12    AC1RX/SS3A/U3BRX/U3ACTS/RF12
    NOT_ON_TIMER,        //    16 RF5    SCL3A/SDO3A/U3ATX/PMA8/CN18/RF5
    NOT_ON_TIMER,        //    17 RF4    SDA3A/SDI3A/U3ARX/PMA9/CN17/RF4
    NOT_ON_TIMER,        //    18 RD15    AETXD1/SCK1A/U1BTX/U1ARTS/CN21/RD15
    NOT_ON_TIMER,        //    19 RD14    AETXD0/SS1A/U1BRX/U1ACTS/CN20/RD14
    NOT_ON_TIMER,        //    20 RA15    AETXEN/SDA1/INT4/RA15
    NOT_ON_TIMER,        //    21 RA14    AETXCLK/SCL1/INT3/RA14
    _TIMER_TCK3,        //    22 RC2    T3CK/AC2TX/RC2
    _TIMER_TCK4,        //    23 RC3    T4CK/AC2RX/RC3
    NOT_ON_TIMER,        //    24 VBUS
    NOT_ON_TIMER,        //    25 RF3    USBID/RF3
    NOT_ON_TIMER,        //    26 RG3    D-/RG3
    NOT_ON_TIMER,        //    27 RG2    D+/RG2
    NOT_ON_TIMER,        //    28 RG15
    NOT_ON_TIMER,        //    29 RG7    ECRS/SDA2A/SDI2A/U2ARX/PMA4/CN9/RG7
    NOT_ON_TIMER,        //    30 RE7    PMD7/RE7
    NOT_ON_TIMER,        //    31 RE6    PMD6/RE6
    NOT_ON_TIMER,        //    32 RE5    PMD5/RE5
    NOT_ON_TIMER,        //    33 RE4    PMD4/RE4
    NOT_ON_TIMER,        //    34 RE3    PMD3/RE3
    NOT_ON_TIMER,        //    35 RE2    PMD2/RE2
    NOT_ON_TIMER,        //    36 RE1    PMD1/RE1
    NOT_ON_TIMER,        //    37 RE0    PMD0/RE0
    _TIMER_IC3,            //    38 RD10    SCK1/IC3/PMCS2/PMA15/RD10
    NOT_ON_TIMER,        //    39 RD5    PMRD/CN14/RD5
    NOT_ON_TIMER,        //    40 RB11    AN11/EREXERR/AETXERR/PMA12/RB11
    NOT_ON_TIMER,        //    41 RB13    AN13/ERXD1/AECOL/PMA10/RB13
    NOT_ON_TIMER,        //    42 RB12    AN12/ERXD0/AECRS/PMA11/RB12
    NOT_ON_TIMER,        //    43 RG8    ERXDV/AERXDV/ECRSDV/AECRSDV/SCL2A/SDO2A/U2ATX/PMA3/CN10/RG8
    NOT_ON_TIMER,        //    44 RA10    VREF+/CVREF+/AERXD3/PMA6/RA10
    NOT_ON_TIMER,        //    45 RF0    C1RX/ETXD1/PMD11/RF0
    NOT_ON_TIMER,        //    46 RF1    C1TX/ETXD0/RMD10/RF1
    NOT_ON_TIMER,        //    47 RD6    ETXEN/PMD14/CN15/RD6
    _TIMER_IC1,            //    48 RD8    PTCC/EMDIO/AEMDIO/IC1/RD8
    _TIMER_IC4,            //    49 RD11    EMDC/AEMDC/IC4/PMCS1/PMA14/RD11
    NOT_ON_TIMER,        //    50 RG7    ECRX/SDA2/SDI2A/U2ARX/PMA4/CN9/RG7
    NOT_ON_TIMER,        //    51 RG8
    NOT_ON_TIMER,        //    52 RG6    ECOL/SCK2A/U2BTX/U2ARTS/PMA5/CN8/RG6
    NOT_ON_TIMER,        //    53 RG9    ERXCLK/AERXCLK/EREFCLK/AEREFCLK/SS2A/U2BRX/U2ACTS/PMA2/CN11/RG9
    //*    the analog ports start with 54
    NOT_ON_TIMER,        //    54    RB0    PGED1/AN0/CN2/RB0
    NOT_ON_TIMER,        //    55    RB1    PGEC1/AN1/CN3/RB1
    NOT_ON_TIMER,        //    56    RB2    AN2/C2IN-/CN4/RB2
    NOT_ON_TIMER,        //    57    RB3    AN3/C2IN+/CN5/RB3
    NOT_ON_TIMER,        //    58    RB4    AN4/C1IN-/CN6/RB4
    NOT_ON_TIMER,        //    59    RB5    AN5/C1IN+/VBUSON/CN7/RB5
    NOT_ON_TIMER,        //    60    RB6    PGEC2/AN6/OCFA/RB6
    NOT_ON_TIMER,        //    61    RB7    PGED2/AN7/RB7
    NOT_ON_TIMER,        //    62    RB8    AN8/C1OUT/RB8
    NOT_ON_TIMER,        //    63    RB9    AN9/C2OUT/RB9
    NOT_ON_TIMER,        //    64    RB10    AN10/CVREFOUT/PMA13/RB10
    NOT_ON_TIMER,        //    65    RB11    AN11/EREXERR/AETXERR/PMA12/RB11
    NOT_ON_TIMER,        //    66    RB12    AN13/ERXD1/AECOL/PMA10/RB13
    NOT_ON_TIMER,        //    67    RB13    AN12/ERXD0/AECRS/PMA11/RB12
    NOT_ON_TIMER,        //    68    RB14    AN14/ERXD2/AETXD3/PMALH/PMA1/RB14
    NOT_ON_TIMER,        //    69    RB15    AN15/ERXD3/AETXD2/OCFB/PMALL/PMA0/CN12/RB15

    //*    Pic32 EXTRAS start here (with #70)
    NOT_ON_TIMER,        //    70 RA0    TMS/RA0
    NOT_ON_TIMER,        //    71 RA1    TCK/RA1
    NOT_ON_TIMER,        //    72 RA4    TDI/RA4
    NOT_ON_TIMER,        //    73 RA5    TDO/RA5
    _TIMER_IC2,            //    74 RD9    SS1/IC2/RD9
    NOT_ON_TIMER,        //    75 RC13    SOSCI/CN1/RC13
    NOT_ON_TIMER,        //    76 RD13    ETXD3/PMD13/CN19/RD13
    NOT_ON_TIMER,        //    77 RD7    ETXCLK/PMD15/CN16/RD7
    NOT_ON_TIMER,        //    78 RG1    C2TX/ETXERR/PMD9/RG1
    NOT_ON_TIMER,        //    79 RG0    C2RX/PMD8/RG0
    NOT_ON_TIMER,        //    80 RA6    TRCLK/RA6
    NOT_ON_TIMER,        //    81 RA7    TRD3/RA7
    NOT_ON_TIMER,        //    82 RG14    TRD2/RG14
    NOT_ON_TIMER,        //    83 RG12    TRD1/RG12
    NOT_ON_TIMER,        //    84 RG13    TRD0/RG13
    NOT_ON_TIMER,        //    85 RA9    VREF-/CVREF0/AERXD2/PMA7/RA9
    NOT_ON_TIMER,        //    86 RC1    T2CK/RC1
};


2)Altere o próximo arquivo.

..\hardware\pic32\variants\Max32\Board_Defs.h

Altere o seguinte define:

#define    NUM_DIGITAL_PINS    87                                                                                                        


3.1) Altere o próximo arquivo.

..\hardware\pic32\libraries\Firmata\Boards.h

Altere o seguinte define para o (_BOARD_MEGA_):

#define TOTAL_PINS              86

3.2) Ou substitua os seguintes defines:
#elif defined(_BOARD_MEGA_)
#define TOTAL_ANALOG_PINS       16
#define TOTAL_PINS              86 //  69 digital + 16 analog
#define VERSION_BLINK_PIN       13
#define IS_PIN_DIGITAL(p)       (((p) >= 2 && (p) <= 23) || ((p) >= 28 && (p) <= 39) || ((p) >= 43 && (p) <= 84))
#define IS_PIN_ANALOG(p)        ((p) >= 54 && (p) <= 69)
#define IS_PIN_PWM(p)           IS_PIN_DIGITAL(p)
#define IS_PIN_SERVO(p)         (((p) >= 2 && (p) <= 23 && (p) - 2 < MAX_SERVOS) || (((p) >= 28 && (p) <= 29 && (p) - 6 < MAX_SERVOS)))
#define IS_PIN_I2C(p)           (0)
#define PIN_TO_DIGITAL(p)       (p)
#define PIN_TO_ANALOG(p)        ((p)-54)
#define PIN_TO_PWM(p)           PIN_TO_DIGITAL(p)
#define PIN_TO_SERVO(p)         (p)<=23 ? (p)-2 : (p)-6
     
                                                                                                                 


4) Programa de teste: a cada 50mseg este pino irá mudar de estado.

/* Blink 86º pin  */

int ledState = LOW;
 
void setup() {
  // set the digital pin as output
  pinMode(86, OUTPUT);  
}

void loop()
{
    if (ledState == LOW){
      ledState = HIGH;
    }else{
      ledState = LOW;
    }
   
    // set the LED with the ledState of the variable
    digitalWrite(86, ledState);
   
    delay(50);
}


Qualquer dúvida, não deixem de comentar.

Até o próximo post.


Disassembler Arduino

Software para disassembler do arquivo *.elf do Arduino.

Neste post estarei demonstrando como utilizar uma pequena ferramenta que estou desenvolvendo, para auxiliar nossos estudos, otimizações e/ou debug de possíveis problemas durante o desenvolvimento do seu software para a plataforma Arduino.

Creio que muitos que utilizam a Ide para o Arduino, já sentiram falta de ver o código que é gerado em assembly. Não havendo até o momento uma interface que facilite a visualização destas informações.
Para os que não sabem, é possível gerar este código através de algumas linhas de comando em prompt, onde são passados alguns parâmetros para os arquivos 'avr-objdump.exe' (Plataforma AVR), ou 'pic32-objdump.exe' (Plataforma PIC32). Sendo que estes arquivos já estão contidos nos diretórios do compilador para a Ide do Arduino.
Vale lembrar, que não estamos fazendo 'engenharia reversa'. Estamos na verdade utilizando as ferramentas que já estão disponíveis para obter algumas informações com maior facilidade. Onde não é preciso ficar digitando nome de arquivos e diretórios "imensos" à cada vez que se deseja utilizar destas ferramentas.
É possível também utilizar-se das variáveis de ambiente, acrescentando a localização destas ferramentas no 'PATH" do windows, mas este não é o foco do post no momento.
Pensando na facilidade de uso, desenvolvi um software que é apenas uma interface amigável para ver algumas informações de forma rápida. Sendo possível salvar o arquivo e utilizá-lo em outras ferramentas de edição.

Segue um pequeno tutorial para uso do software Disassembler_Arduino_Tool.

1) Faça o download do arquivo zipado do software.  [ DOWNLOAD ]

2) Execute o arquivo 'Disassembler_Arduino_Tool.exe' .



3) Escolha a plataforma para qual foi compilado o seu projeto, sendo ele para o AVR ou PIC32.



4) Depois escolha o tipo de informação que gostaria de obter do seu código compilado.

Fica uma pequena observação: efetuei os testes em todos os itens, e observei que alguns podem não funcionar para a plataforma AVR, como alguns outros para a plataforma PIC32. Isso pode acontecer devido à versão dos arquivos 'avr-objdump.exe' e 'pic32-objdump.exe'.
Caso alguém encontre algum bug relacionado à isto, entre em contato conosco, e o quanto antes obtermos informações à respeito, estaremos entrando em contato ou criando um novo post com as devidas atualizações.



5) Abra a janela de abertura de arquivos:  File -> Open *.elf .





6) Navegue até o diretório onde se encontra o arquivo *.elf. Selecione o mesmo e confirme.

Caso não encontrarem o arquivo *.elf , é possível através da Ide obter a localização do arquivo, que geralmente se encontra em uma pasta temporária de trabalho no diretório de usuário no windows.



7) Caso esteja tudo correto, deverá aparecer a janela com as informações requeridas sobre o arquivo.

Lembrando que deve ter sido escolhido corretamente a plataforma para qual foi efetuada a compilação do projeto.



Com isto encerro o pequeno tutorial sobre o software. Espero que seja de grande ajuda, uma vez que o foco é facilitar a vida de qualquer desenvolvedor.
Aguardo comentários e sugestões para a melhoria desta pequena ferramenta.

Até a próxima.

[ DOWNLOAD ]


RTC on chipKIT Max32 [Arduino PIC32]


Utilizando o RTC na placa do Chipkit Max32 [Arduino PIC32]

Seja bem vindo a este post, onde estarei demonstrando uma solução para o uso do periférico RTC na placa ChipKit Max32, que utiliza várias bibliotecas portadas, desenvolvidas para a plataforma Arduino.
E para quem quiser acompanhar o desenvolvimento destas bibliotecas, segue o link para a página wiki do ChipKit.

É comum para os desenvolvedores e hobbystas criarem aplicações onde possam colocar os diversos periféricos dos kits de desenvolvimento, especialmente dos microcontroladores para funcionar. Seja em aplicações isoladas para testar apenas alguns módulos, ou em aplicações mais amplas, onde é interessante se utilizar da maioria dos periféricos existentes no hardware utilizado.
Após a aquisição do ChipKit Max32, comigo não foi diferente. E uma das minhas primeiras idéias era utilizar o módulo RTC nativo do microcontrolador PIC32 existente nesta placa. E após várias pesquisas como: datasheet do microcontrolador, esquema elétrico da placa, amigos e páginas na internet, percebi que a maioria das pessoas que tinham esta mesma idéia, não encontraram uma forma para utilizar o RTC, ou mesmo as que estavam no caminho certo, não haviam de fato realizado os procedimentos necessários para colocar o RTC na placa MAX32 para funcionar.
É interessante saber que em outra solução oferecida para o ChipKit, que é a plataforma Chipkit UNO32, existe na placa os terminais acessíveis para a inserção do cristal de 32.768KHz necessário para o clock do RTC, e na plataforma do Max32 não existe.
Vale dizer que o propósito do post é solucionar um possível problema que encontrei na placa Max32, não sabendo até o momento se é algo que pode ocorrer em todas, ou se eu fui o sortudo por me deparar com ele.
Para os que possuem a placa UNO32, até o momento podem ficar tranquilos.Pois eu e o Cesar fizemos o teste de inserir um cristal de 32.768KHz  nos terminais do periférico do RTC, e ele funcionou perfeitamente. Segue a imagem da placa montada:

Foto da placa UNO32 com cristal do RTC:

Para quem possui esta placa, a montagem é tranquila, uma vez que já existe na placa os terminais para a inserção do cristal do RTC. Bastando apenas que incluam em seus projetos a biblioteca RTC, e que escolham corretamente o board utilizado.


Para quem possui o Max32, descrevo à seguir os problemas e soluções que encontrei. E espero que ninguém mais tenha este problema, tornando o uso deste periférico o mais fácil possível.

A primeira tentativa, foi utilizar algumas idéias encontradas em alguns posts, que citavam a inserção do cristal, juntamente com os capacitores acoplados ao mesmo, diretamente nos pinos do microcontrolador SOSCI e SOSCO, responsáveis pelo clock do RTC. Observando o esquema elétrico da placa e o meio físico, encontramos o seguinte:


Esquema Elétrico do ChikiptKit Max32:


Foto da placa onde estão ligados os pinos do microcontrolador:


Aparentemente seria uma tarefa fácil. Tendo apenas que ter um pouco de cuidado ao lidar com o ferro de solda e saber trabalhar com componentes SMD. A primeira dúvida seria a interferência do duplo-diodo e dos resistores na oscilação do cristal. Como eu não pretendia utilizar os pinos para outra tarefa, resolvi retirar este componentes. Caso fosse necessário, eu os colocaria de volta na placa.
Seguindo com esta idéia. Retirei o diodo D7G2, o R5 e o R6. E nos terminais do PIC32, SOSCI e SOSCO, coloquei o cristal de 32.768KHz + 2 capacitores de 22pF. Sendo que mais tarde alterei estes valores para 30pF.
Observando as bibliotecas existentes na wiki do ChipKit, encontrei um link para a biblioteca do RTC. E após ler as observações e tendo visto a implementação de exemplo que vem inclusa, coloquei a placa do Max32 para funcionar. Para minha surpresa ela funcionou de primeira, tendo como indicação o timer que estava constantemente sendo incrementado, e sendo enviado pela console serial da MPIDE do Arduino.
Porém, tive problemas com a contagem do tempo, onde observei que a cada 1 segundo do relógio, a contagem efetiva era de 6 segundos no módulo RTC. Tendo este problema em mente, resolvi observar o circuito oscilador com um osciloscópio, e constatei que a frequência de oscilação nos pinos SOSCI e SOSCO era de aproximadamente 196KHz, o que indicava que a frequência do cristal de 32.768KHz estava 6 vezes acima do normal. Primeira tentativa para solucionar foi alterar os valores dos capacitores ligados ao cristal. Efetuando mudanças desde 15pF até 33pF, obtive a mesma frequência de aprox. 196KHz.
Então comecei a concluir que poderia ser alguma configuração das bibliotecas portadas utilizadas no ChipKit. Após estudá-las, não consegui encontrar nada que pudesse gerar este problema. Então teria que encontrar outra solução.
Coloquei novamente o diodo D7G2 e os resistores R5 e R6 na placa. Retirei o cristal e os capacitores. E resolvi montar um oscilador externo. De modo à ter pouco impacto sobre o hardware, além de não ter que encontrar outro tipo de solução por software, pois neste caso estaria retirando a compatibilidade de projetos desenvolvidos para a plataforma do Arduino. A melhor solução foi fazer um oscilador CMOS com portas inversoras, como as existentes no CI 4069. Sendo que para este tipo de solução é possível utilizar portas NAND ou NOR, sendo de extrema importância serem da família CMOS.
Devido à sua impedância de entrada e algumas características elétricas, este tipo de tecnologia é capaz de fazer com que um cristal possa ser utilizado em conjunto para gerar um oscilador em uma enorme faixa de frequência.Tendo em mãos o esquema, resolvi fazer a seguinte montagem:


Esquema do PIC32 com o Oscilador CMOS:



Este tipo de oscilador tem uma configuração bem fácil para montagem. Utilizei mais uma porta inversora ao final do estágio oscilador, para que sirva como buffer. Além de não influênciar na frequência em questão, pois na aplicação de RTC, é uma questão importante não haver mudanças nesta frequência.Após a montagem, fiz a seguinte ligação na placa do ChipKit Max32:

Ligação do Circuito Oscilador RTC Externo:



 Verifiquei se a frequência do oscilador não sofria nenhuma interferência após a montagem na placa. E com um osciloscópio constatei que estava tudo normal.


Frequência de 32.768KHz do Oscilador CMOS:





Próximo passo seria verificar novamente o funcionamento do periférico do RTC através do software. Para isto utilizei o projeto que estará disponível ao final deste post.Mas tirei um screenshot do resultado obtido:

Teste da biblioteca do RTC e software:


Após isto conclui que o oscilador externo acabou sendo uma alternativa válida para o problema ocorrido com o cristal ligado diretamente aos pinos do microcontrolador, como seriam nos esquemas usuais para o periférico do RTC.

Caso, alguém tenha tido o mesmo tipo de problema, ou esteja querendo implementar esta solução ou alguma outra para o módulo RTC, gostaria de saber das idéias e/ou seus resultados obtidos. Assim podemos contribuir para todos que estejam utilizando esta plataforma em seus projetos.

Até a próxima.

Daniel Cezar.

[ DOWNLOAD ]