ÍNDICE DE CONTEÚDO
Quando comecei a brincar com microcontroladores, alguns anos atrás, não havia o Arduino, havia somente os embriões de toda essa corrente maker que agora flui para alçar voos maiores e com um monte de projetos bacanas possibilitando a execução rápida e com cada vez mais recursos. Isso faz com que eu me sinta um tanto “old school”. Mas não me tome por tão velho assim. Comecei a estudar/brincar com sistemas embarcados por volta de 2001, não é tanto tempo assim.
Desde então muita coisa mudou. Naqueles tempos o pessoal por aqui no Brasil praticamente só falava em PIC, do mesmo modo que hoje muita gente só conhece o Arduino. Bem o ponto deste post é justamente esse: existe um mundo imenso fora dessas plataformas a ser explorado e é um mundo bem divertido. As plataformas como o Arduino são sensacionais dentro da sua proposta mas não são tudo o que há ou sempre houve. Então, e se não houvesse o Arduino no mundo, como fazer?
Os alicerces para o desenvolvimento
Quando desenvolvemos um sistema embarcado a tarefa resumida consiste em:
- Escrever o código do programa;
- Cross-compilar para o processador em uso;
- Gravar o microcontrolador;
- Testar/Debugar;
- Repetir exaustivamente até o resultado desejado, com ênfase na etapa 4.
Para executar essa lista de tarefas, um conjunto de ferramentas é necessário. A primeira tarefa exige um bom editor de texto, voltado para a programação. Eu já usei bastante coisa mas hoje trabalho basicamente no vim. Muitos editores de texto bons são produzidos para programadores então não vou nem tentar construir uma lista deles. Há muitos pela internet afora.
Embarcados Experience 2024: Evento Presencial
Participe do Embarcados Experience 2024 em São Paulo. Conhecimento técnico, palestras, workshops e oportunidade de networking com profissionais experientes.
Para traduzir o código, usualmente escrito em C ou seus dialetos, é necessário o uso de um compilador para levar o seu texto a um idioma conhecido pelo processador, as suas instruções. No caso do Arduino, que usa um microcontrolador com núcleo AVR, o compilador utilizado é o avr-gcc.
Após compilado o código, a imagem gerada deve ser gravada no microcontrolador. O microcontrolador possui uma memória que não é apagada a cada vez que ele é reiniciado. Nos dias de hoje o tipo de memória é usualmente flash. Os microcontroladores proveem interfaces para realizar essa gravação, nos AVR um caminho possível é a interface de ISP (In-System Programming) através de um protocolo via SPI.
Alguns microcontroladores oferecem também uma interface que permite executar o código linha a linha a fim de identificar possíveis problemas. No caso do AVR nem todos os microcontroladores possuem a interface específica para debug e então se faz necessário o uso de interfaces seriais, LED’s e outros subterfúgios para localizar e corrigir os erros.
Para resolver estes problemas básicos o Arduino provê uma IDE (ambiente integrado de desenvolvimento), a interface de gravação é feita através de um bootloader serial (UART) e uma interface USB-Serial é disponibilizada nas placas. Para executar seções de debug no atmega328p é necessário um conjunto específico de ferramentas (AVR Dragon, por exemplo) que utilizarão a interface debugWire. O Arduino tem uma IDE que não está preparada para executar seções de debug.
Executando um projeto sem usar o Arduino (com Makefile)
Deixando de lado a conversa e partindo pra ação. Serão necessárias as seguintes ferramentas:
- Um editor de texto (kate, notepad++, SublimeText, vim);
- avr-gcc (winavr no windows);
- avrdude.
Supondo que tudo está instalado, comecemos um repositório. Um repositório é um local onde o seu código ficará armazenado e será versionado (nada de versao_de_sexta ou essefunciona). Para isso o github é uma boa opção. Não entrarei em detalhes sobre como criar um repositório no github já que isso é bem documentado na internet. Veja também o artigo do Marcelo Jo, sobre git.
Utilizaremos como receita de build um Makefile. O Makefile é um conjunto de instruções para realizar as tarefas necessárias para que o código em C se transforme em binário. Para a criação do makefile pode ser usada a ferramenta mfile. No meu caso estou usando um at90usb162 de uma placa chamada Micropendous1 que tenho por aqui.
Trecho do Makefile que determina o microcontrolador:
1 2 3 4 5 6 |
MCU = at90usb162 FORMAT = ihex TARGET = main SRC = src/$(TARGET).c ASRC = OPT = s |
Sem entrar muito em detalhes o primeiro parâmetro seleciona o microcontrolador em uso, SRC diz onde estão os fontes e OPT o nível de otimização do compilador. São os parâmetros que mais provavelmente será preciso mudar.
Gerado o Makefile é preciso criar o arquivo main.c, no diretório src (que deverá ser criado).
Main original:
1 2 3 |
int main(void) { } |
O código acima é o básico pra compilar, entretanto ele não faz absolutamente nada além de prover a função main, necessária no C. Mesmo o Arduino usa uma e reflete inclusive a estrutura que vou explorar na sequência.
Ao executar um projeto é importante selecionar uma estrutura. Nesse caso será implementada a estrutura mais básica em um projeto de sistema embarcado: o Powerloop.
The mighty PowerLoop!
Em um sistema embarcado, uma vez iniciada a execução, a tendência é que o mesmo fique funcionando o tempo todo aguardando a ocorrência de um evento para responder ao mesmo. Assim é quase certeza que você encontrará um loop infinito em algum lugar.
Assim vou modificar o código pra fazer o simples pisca led.
Configurando o hardware ( o Arduino setup() )
Uma coisa que eu gosto no Arduino é a ideia de separar as duas funções, setup() e loop() reforçando bem a ideia de que há a necessidade de executar de modo infinito e que é necessário antes de tudo configurar o setup. Podemos encarar essa etapa inicial como sendo o equivalente à inicialização da BIOS de um computador desktop.
Para que o LED pisque é preciso que um pino seja utilizado como saída. Pra isso vamos acrescentar uma seção de configuração do hardware e registradores no projeto, mas primeiro selecionaremos um pino.
O microcontrolador que estou utilizando é um at90usb162, um microcontrolador com USB integrada (com bootloader, que é uma mão na roda), alguns timers, um comparador e mais algumas interfaces. O datasheet lista com mais detalhes.
Para configurar um pino como saída vamos escolher PC5. A forma como os periféricos estão organizados faz que cada um deles possua um endereço reservado, um registrador. Estou utilizando o avr-gcc em conjunto com a avr-libc (o mesmo utilizado nas bibliotecas do Arduino) e assim vamos precisar incluir no código a lib avr/io.h. Não entrarei nos detalhes dela agora mas navegar no código pode ser uma boa pra entender o que eu disse sobre registradores e endereços.
Código para ligar o LED:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#include <avr/io.h> #define PIN_USED 5 int main(void){ // Configuração do PC5 como saída DDRC |= (1<<PIN_USED); //loop infinito while(1){ //Escrevendo 1 no pino 5 PORTC |= (1<<PIN_USED); } } |
O código apresenta os registradores que controlam a porta digital. Quando a função pinMode é chamada ao escrever código para o Arduino no fim das contas o que será feito é setar esse registrador DDRx que é quem define qual a direção que o pino será utilizado. O mesmo podemos dizer da função digitalWrite, ela irá realizar a escrita nesse registrador, PORTx. É possível checar o código dessas funções no repositório do Arduino no github.
Na linha 11 do código que liga o LED temos a escrita exclusiva no bit PIN_USED do registrador PORTC. Do modo que o código foi escrito a operação será realizada aplicando a máscara de bits gerada pelo deslocamento do valor 1 de PIN_USED posições e efetuando a operação ou bit a bit. O resultado é que somente o bit desejado é alterado.
Para que o LED pisque é preciso que ele seja apagado. Entretanto antes de apagar o LED é necessário aguardar algum tempo pois o microcontrolador executa as instruções em uma taxa que tornaria imperceptível o acender do LED.
Pisca LED sem as libs do Arduino:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include <avr/io.h> #include <util/delay.h> #define PIN_USED 5 int main(void){ // Configuração do PC5 como saída DDRC |= (1<<PIN_USED); double ms_delay = 100; //loop infinito while(1){ //Escrevendo 1 no pino escolhido PORTC |= (1<<PIN_USED); _delay_ms(ms_delay); PORTC &= ~(1<<PIN_USED); } } |
Na linha 19 temos a operação inversa zerando o bit da porta e apagando o LED. Há ainda o uso da função _delay_ms disponibilizada pela avr-libc.
Propositalmente deixei não definida a macro F_CPU. A não definição e uso da função _delay_ms levou ao seguinte warning como resultado da compilação:
1 |
# warning "F_CPU not defined for <util/delay.h>" |
Houve sucesso e o código foi gerado mas não funcionaria corretamente dada a ausência do define. Isso serve pra ilustrar que nem sempre gerar o código sem erros é sinal de que não há problemas e certamente a ausência de um símbolo desses leva a problemas difíceis de localizar. Vale como dica de que a presença de warnings deve ser tradada com cuidado.
A solução do problema se dá com a modificação do Makefile e acrescentando F_CPU no valor da frequência e modificando a linha contendo CDEFS, que é passado ao compilador.
Inserção de define no makefile:
1 |
CDEFS = -DF_CPU=$(F_CPU) |
Assim o código é compilado e o hex é gerado sem warnings e executará conforme planejado. O resultado da compilação após o comando make é:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
avr-gcc -c -mmcu=at90usb162 -I. -gstabs -DF_CPU=8000000UL -Os -Wall -Wstrict-prototypes -std=gnu99 src/main.c -o src/main.o avr-gcc -mmcu=at90usb162 -I. -gstabs -DF_CPU=8000000UL -Os -Wall -Wstrict-prototypes -std=gnu99 src/main.o --output main.elf -lm avr-objcopy -O ihex -R .eeprom main.elf main.hex avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ --change-section-lma .eeprom=0 -O ihex main.elf main.eep avr-objcopy: --change-section-lma .eeprom=0x0000000000000000 never used Size after: AVR Memory Usage ---------------- Device: at90usb162 Program: 170 bytes (1.0% Full) (.text + .data + .bootloader) Data: 0 bytes (0.0% Full) (.data + .bss + .noinit) |
O objetivo desse texto é dar uma visão de como é o desenvolvimento utilizando o AVR sem utilizar as bibliotecas do Arduino. Naturalmente é possível, inclusive aconselhável, a escrita de funções para reaproveitar código e mesmo organizar melhor o projeto e acelerar o desenvolvimento.
Outro ponto que é importante destacar é que não há qualquer intensão em defender o não uso do Arduino. A ideia é simplesmente ilustrar outras opções.
Para quem quiser os arquivos utilizados neste artigo, utilize o repositório.
Referências
Créditos da imagem destacada: https://commons.wikimedia.org/wiki/File:Arduino_avr_atmega8-1.jpg
Kra, legal teu post. Meu tcc será sobre arduino, e estou muito empolgado.
Ótima matéria. Apesar do Arduino e o Raspberry Pi, estarem ai justamente para facilitar o processo de introdução nesse mundo dos embarcados para as pessoas no geral, tento o proposito primário de servi como ferramentas de estudo e aprendizado, por causa do comodismo muitas vezes em parte, as pessoas acabam ficando presa a essas ferramentas criando assim um paradigma nessas plataformas. É interessante isso ser evitado e se explorar mais o que esse mundo dos embarcados tem a oferecer, pois assim, isso irá acabar até expandindo seus horizontes e possibilidades. Isso até me lembra o que um professor da area,… Leia mais »
Um dos melhores Post do Embarcados que eu ví até o momento, quando falamos em Arduino na maioria das vezes somente programamos utilizando sua IDE padrão, sempre tentei achar algo semelhante e feito por BR´s, e emfim, algo como sair do mundo Arduino e realmente programar um microcontrolador e não uma plataforma de prototipagem, Parabéns pelo post, se possível, me indique alguns materiais relacionados, valeu !!!
sem dúvidas o Arduino faz o pessoal ganhar tempo e descomplica um séria de coisas… Mas estou notando que alguns cursos de engenharia estão adotando SOMENTE o arduino e o pessoal está se afastando demais do hardware…. Já co-orientei alunos formandos que não sabiam olhar um datasheet e eu acho isso perigoso…. Se continuar assim, daqui alguns anos os novos engenheiros não saberão trabalhar sem ferramentas prontas… e o mercado de trabalho é bem diferente disso….
Eu comecei com Aduino e agora estou estudando (e correndo atrás com alguns projetos em PIC). Alguns dirão que é um atraso, mas se for pensar em produto e custos, é necessário pensar seriamente em PICs e Haltecs. Fica a dica: Arduino para aprendizado e facilidade/rapidez de prototipagem ou produtos “que paguem” para as outras situações:Apertem os cintos.Txau!!!
Euclides, talvez um passo mais natural seja explorar o próprio AVR. Em um opinião pessoal as ferramentas da Microchip deixam um pouco a desejar e acabam custando ao projeto um tempo. A discussão sobre usar o Arduino ou não(as bibliotecas não a placa) é muito longa e no fim de tudo dependerá do contexto. Não defendo também o desenvolvimento bare-metal do zero o tempo todo. É bom se aproveitar de bibliotecas já testadas e maduras, em contrapartida a natureza dos sistemas embarcados acaba nos levando a explorar sempre aquela única bendita funcionalidade que ainda não foi implementada.
Sim. Para tudo o que disse tambem. As ferramentas da linha Mikro (MikroC, Mikrobasic, Mikropascal, etc…) fornecem as principais bibliotecas para os principais sensores e atuadores encontrados para Arduino e que assim podem ser usados no PIC, sem o inconveniente da curva de aprendizado, quando quem está aprendendo já conhece ou vem dessas linguagens, isso é um diferencial que gera economia de tempo. Pode não ser gratuítas mas não são tão caras e fornecem um bom material de consulta e suporte.
Haltecs eu ate concordo, agora PIC é correr contra a maré, substituto ao pic já olhou os controladores da Texas, são muito baratos e funcionalidades a funcionalidade então nem se fala.
https://www.ti.com/ww/en/launchpad/launchpads-msp430.html
Pelas pesquisas que fiz à tempos, sem dúvida a Texas tem excelentes produtos, um dos problemas é a mão de obra ou material de exemplos encontrados na internet (que achei poucos). Vou dar uma olhada e voltamos. T+
Muito legal. Há um universo fora do arduino, ou dessas ferramentas para universalizar o mundo maker, para ser explorado.
Para entrar neste mundo desarduinizado tem que dominar, ou compreender muito bem, o funcionamento do hardware, como fazer do compilador o seu amigo de todas as manhãs e tentar sempre tirar o máximo da sua plataforma de desenvolvimento. Para isso gasta-se horas e horas de leitura do manual do compilador, entender algumas construções de C (ou da linguagem que está usando), muita leitura de datasheet e muita pesquisa…
Diversão garantida!
Pois é Rafael… Percebo isso tambem. Eu não estudei formalmente. Tudo que sei foi na “raça”…mas se existe uma deficiência nas escolas, e que podem ser sanadas em 5 minutos (isso mesmo!!! 5 mínimos minutos!!!…e para mim a culpa é dos próprios professores que são capazes de “ensinar” integral, mas completamente incapazes de baixar meia dúzia de datasheets e explicar o que deve ser encontrado dentro desse material). A impressão que dá é que não querem que os alunos aprendam “a se virar” e não dependam mais deles para descobrirem o “mundo”. Eu não tive opção, tive que me virar… Leia mais »
Precisa de mais exemplos para programar do que a própria Texas fornece? dá uma olhada na página da ti do mcu que você quer trabalhar, é normal ter um arquivo zipado na página com exemplos de uso de todos os periféricos do modelo em questão.
Estou criando um grupo no whatsapp para desenvolvedores, engenheiros, técnicos e hobbistas de programação em linguagem C sem Arduíno no AVR (AVRStudio ou WinAVR). Quem quiser manda uma msg pra mim 11 977115082
Legal! Meu foco não é AVR mas fiquei curioso com esse grupo! Adiciona aí: 53 984092049
Excelente iniciativa. Gostaria de participar e aprender sobre este assunto, obrigado. 22-999257985