segunda-feira, 20 de janeiro de 2014

Tutorial: Utilizando código .CPP na programação da Arduino

Este post visa demonstrar uma forma de programar a Arduíno sem utilizar sua IDE. Eu me inspirei no post deste link:

Tutorial: Using Atmel Studio 6 with Arduino projects

Se você tiver alguma sugestão, por favor, adicione nos comentários.

Se você estiver usando Linux, veja este post:
Programar o Arduino em linguagem C++ via comando de linha (em Linux) e sem uso da IDE ou qualquer interface gráfica de usuário

A IDE da Arduíno funciona muito bem, para que, então ter todo este trabalho?

Organização, quando seu projeto começa a ficar grande é importante você organizar o seu código em arquivos diferente com classes, etc. Essa não é a forma que os arquivos .PDE ou .INO funcionam, logo o ideal é trabalhar com os arquivos .h .c .cpp padrões do código C ou C++.

Não carregar o Arduíno bootloader, a Arduíno inclui junto com o seu código o bootloader (mais informações aqui), isto pode ser um problema se você está com o processador embarcado (sem uma Arduíno), pois podem ser produzidos sinais nas diversas portas I/O que podem provocar comportamentos não esperados do seu circuíto.

Se você está procurando esta alternativa para ter acesso ao arquivo .HEX, não é necessário! Quando você compila seu código na IDE da Arduíno o arquivo .HEX é gerado no diretório:

C:\Users\nome do usuário\AppData\Local\Temp\build.tmp

Com o arquivo .HEX basta utilizar a USBtinyISP para transferir os binários para o processador usado na sua placa. IMPORTANTE - Sempre que você transfere o .HEX através do USBtiny, você perde o bootloader se este é o seu objetivo tudo bem. Se você perdeu o bootloader e quer restaurá-lo basta usar a própria USBtiny e a IDE da Arduíno (recomendo fazer isso com uma conta de administrador do Windows, se você estiver usando Windows):

Tools->Board
Tools->Programmer->USBtinyISP
Tools->Burn Bootloader


Se você quer trabalhar os seu código da Arduíno arquivos .INO no Atmel Studio, basta instalar a Extensão Arduino Ide for Atmel Studio no Extention Manager no AtmelStudio, e não precisa seguir este tutorial.



Passo a Passo


Estou trabalhando com Windows 7 

Material necessário:


Arduíno UNO





USBtinyISP



Você pode fazer uma com as instruções contida neste link. Caso você faça uma USBtinyISP lembre-se de garantir que o cabo (que você fizer) conecte o pino 1 dela com o pino 1 da outra placa.






Atmel Studio 6

Baixe instale e execute o update. (você precisa fazer isso com uma conta com direitos de administrador no Windows)

Eu usei o Atmel Studio 6.1 update 2.0 (build 2730)
E o update recomendado foi o Atmel Kits




IDE Arduíno

Baixe e instale a versão compatível com o processador que você vai usar, eu recomendo que você use a última versão estável.

Eu usei a versão 1.05






Copiando a biblioteca Arduíno Core


Abra a IDE da Arduíno.
Selecione a placa Arduíno que possui o mesmo processador que você usa, no meu caso escolhi a Arduíno Uno, pois eu uso o processador ATmega328P.

IMPORTANTE: A IDE da Arduíno vai gerar uma biblioteca Arduíno Core considerando o processador da Arduíno que você escolheu.

Abra um exemplo (eu usei o Blink), clique em Verify (para compilar).





Vá ao diretório:

C:\Users\nome do usuário\AppData\Local\Temp\build.tmp

Se existirem vários parecidos, escolha aquele que foi criado na data e hora que você compilou o código.

Copie o arquivo core.a que está neste diretório e renomeie para libcore.a e guarde para passos futuros.

Criando o Projeto

Abra o Atmel Studio.

Crie um novo projeto:



Escolha GCC c++ Executable Project.

Coloque o nome que desejar.




Escolha o seu processador, eu trabalho com o ATmega328P (lembre-se que tem que ser o mesmo que foi escolhido para gerar a core.a na IDE da Arduíno).






Configurando o Projeto


Entre nas propriedades do projeto



Neste ponto, o ideal seria fazer as modificações em  All Configurations, mas (na minha instalação) ocorreu o erro abaixo, então eu fiz as configurações em Debug e Release.





Telas das Configurações (as duas Release e Debug):

Para 16MHz use:             
F_CPU=16000000L  

Para 8MHz use:               
F_CPU=8000000L

Versão da IDE da Arduino, no meu caso 1.05, logo:
ARDUINO=105


AVR/GNU C++ Compiler - Symbols




AVR/GNU C++ Compiler - Directories

Estes dois são obrigatórios, pois apontam para a Arduino.h e pins_arduino.h

Direcione para os diretórios da instalação da sua IDE da Arduíno, no meu caso são estes.

C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino
C:\Program Files (x86)\Arduino\hardware\arduino\variants\standard

Vou incluir mais um apontando para uma biblioteca, a EEPROM se você não for usá-la não precisa incluir, mas neste post eu vou fornecer um código que utiliza esta biblioteca

C:\Program Files (x86)\Arduino\libraries\EEPROM





Preste bem a atenção se você está configurando em C++ e não em C por engano, caso você erre irá receber este erro quando for gerar o .HEX, o erro:

Error 1 Arduino.h: No such file or directory

Especificamente se refere ao diretório:
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino



AVR/GNU C++ Compiler - Optimization

-fdata-sections

Selecione “prepare functions for garbage collection”
no meu caso já estava selecionado




AVR/GNU C++ Compiler - Miscellaneous
-fno-exceptions




AVR/GNU Linker - Optimization
Selecione “Garbage Collect unused sections (-Wl, –gc-sections)”no meu caso já estava selecionado



Resumo das configurações para você copiar-e-colar:



Atenção é no AVR/GNU C++

AVR/GNU C++ Compiler - Symbols
F_CPU=16000000L
ARDUINO=105

AVR/GNU C++ Compiler - Directories
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino
C:\Program Files (x86)\Arduino\hardware\arduino\variants\standard
C:\Program Files (x86)\Arduino\libraries\EEPROM

AVR/GNU C++ Compiler - Optimization
-fdata-sections

Selecione “prepare functions for garbage collection”
no meu caso já estava selecionado

AVR/GNU C++ Compiler - Miscellaneous
-fno-exceptions


AVR/GNU Linker - Optimization
Selecione “Garbage Collect unused sections (-Wl, –gc-sections)” no meu caso já estava selecionado

Clique em Save All

Adicionando a biblioteca libcore.a

Copie a libcore.a (que você separou no começo do tutorial) e cole no diretório do seu projeto, junto como o arquivo .cpp.

C:\Users\nome do usuário\Documents\Atmel Studio\6.1\nome do projeto\nome do projeto\


Abra o Solution Explorer



Clique com o botão direito do mouse em Libraries e Selecione Add Library



Clique em Browse Libraries e procure a libcore.a no diretório:
C:\Users\nome do usuário\Documents\Atmel Studio\6.1\nome do projeto\nome do projeto\







IMPORTANTE: Esta libcore.a deve ser gerada para o mesmo processador

que você escolheu na criação do projeto no AtmelStudio, caso o processador seja diferente (quando for compilar) você receberá o erro:

Error 12 skipping incompatible 

Caso isto ocorra, basta gerar a core.a novamente (selecionando a Arduíno que possui o mesmo processador), renomeie ela para libcore.a, remova a errada e adicione a nova.


Vamos compilar algum código....não, hahahaha, ainda não.


Vamos configurar as ferramentas para transferir o .HEX para o processador



Adicionando a biblioteca EEPROM


Se você não for usá-la não precisa incluir, mas neste post eu vou fornecer um código que utiliza esta biblioteca

Clicando como botão direito do mouse no projeto, crie uma pasta para organizar as bibliotecas:



Coloque o nome EEPROM





 Clicando como botão direito do mouse na pasta, adicione um item existente.




Direcione para o arquivo cpp da biblioteca, no meu caso a biblioteca EEPROM fica no diretório:

C:\Program Files (x86)\Arduino\libraries\EEPROM\EEPROM.cpp





AVRDUDE

Clique em Tool -> External Tools ...






Baixe e instale a última versão do AVRdude

Tem no diretório da Arduíno IDE (no meu caso 1.05)
 C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avrdude.exe  
mas ele não aceitava a opção -c (interpretava como -C), por este motivo estou instruindo a usar a versão no link acima. Se a versão que veio junto com a sua IDE da Arduíno funcionar, pode usá-la.


Vamos adicionar quatro ferramentas usando o Avrdude.exe:

Duas ferramentas usam o Serial-USB para você transferir o .HEX para uma Arduino, você precisa saber em que COM está sua Arduíno, no meu caso é COM17. Nestas duas eu uso o AVRdude que vem junto com a IDE da Arduíno.

Duas ferramentas usam a placa USBtiny  para você transferir o .HEX através da conexão ICSP, para isso você precisa ter (comprar ou montar) uma USBtiny e instalar os driversNestas duas eu uso o AVRdude que foi baixado à parte.

Para todas você vai precisar colocar o código correspondente ao processador que você usa (o mesmo que você selecionou no projeto (no meu caso é o Atmega328P) o código é m328p você pode encontrar os códigos aqui, ou procure na internet as palavras "avrdude options").



External Tools

Troque o processador em todos argumentos e a Com no dois primeiros.



Release:
Title: Release - USB-Serial Programmer: COM17
Command: C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avrdude.exe
Arguments: -C"C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf" -v -v -v -v -pm328p -carduino -P\\.\COM17 -b115200 -D -Uflash:w:"$(ProjectDir)Release\$(ItemFileName).hex":i

Selecione “Use Output window”






Debug
Title: Debug - USB-Serial Programmer: COM17
Command: C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avrdude.exe
Arguments: -C"C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf" -v -v -v -v -pm328p -carduino -P\\.\COM17 -b115200 -D -Uflash:w:"$(ProjectDir)Release\$(ItemFileName).hex":i

Selecione “Use Output window”







Title: Release - USBtiny Programmer
Command: C:\WinAVR-20100110\bin\avrdude.exe
Arguments: -c usbtiny -p m328p -U flash:w:"$(ProjectDir)Release\$(ItemFileName).hex":i

Selecione “Use Output window”





Title: Debug - USBtiny Programmer
Command: C:\WinAVR-20100110\bin\avrdude.exe
Arguments:-c usbtiny -p m328p -U flash:w:"$(ProjectDir)Debug\$(ItemFileName).hex":i

Selecione “Use Output window”






Compilando Código


Quando você criou o projeto foi criado automaticamente um código:

#include <avr/io.h>

int main(void)
{
    while(1)
    {
        //TODO:: Please write your application code 
    }

}
Como a ideia é mostrar o funcionamento do AtmelStudio com pelo menos um biblioteca eu escolhi, a EEPROM.

O código abaixo é muito simples ele grava 0 na EEPROM, depois lê e apresenta na serial (o led pin13 fica apagado), grava 1 (led aceso), lê e apresenta na serial (led apagado), grava 1 (led aceso) e assim por diante.

Desta forma você pode abrir o serial monitor (9600) e ver a leitura.

Sobrescreva o código acima com este código abaixo:
#include <Arduino.h> /* IMPORTANTE */
#include <EEPROM.h>

void setup();
void loop();
#line 10
int led = 13;
int address = 0;
int count = 0;
byte value;


int main(void)
{
 init();

  #if defined(USBCON)
 USBDevice.attach();
 #endif
 
 setup();
 
 for (;;) {
  loop();
  if (serialEventRun) serialEventRun();
 }
 
 return 0;
}


void setup()
{
 Serial.begin(9600);
 while (!Serial) {
  ; // wait for serial port to connect. Needed for Leonardo only
 }
 // write a 0 to all 512 bytes of the EEPROM
 for (int i = 0; i < 512; i++)
  EEPROM.write(i, count);
 
 pinMode(led, OUTPUT);
}

void loop()
{
 
 // read a byte from the current address of the EEPROM
 value = EEPROM.read(address);
 
 Serial.print(address);
 Serial.print("\t");
 Serial.print(value, DEC);
 Serial.println();
 
 // advance to the next address of the EEPROM
 address = address + 1;
 
 // there are only 512 bytes of EEPROM, from 0 to 511, so if we're
 // on address 512, wrap around to address 0
 if (address == 512)
  {
  digitalWrite(led, HIGH);
  address = 0; 
  count++; 
  if(count == 256) count=0;
  
  for (int i = 0; i < 512; i++)
   EEPROM.write(i,count);
   
  
  }
 
 
 delay(3);
 digitalWrite(led, LOW);
}




Você pode compilar pressionando o F7 e transferir o código usando a External Tool, se você estiver trabalhando na versão Release e com uma Arduíno conectada na USB:


Tools-> Release - USB-Serial Programmer: COM17

Para a versão Debug use:
Tools-> Debug - USB-Serial Programmer: COM17


Mas o objetivo é transferir o código através da USBtinyISP, então conecte ela no micro e conecte no seu circuito (ou uma Arduíno pela pora ICSP nela), se for porta ICSP da Arduíno, lembre-se que você irá perder o bootloader.


Tools-> Release - USBtiny Programmer

Para a versão Debug use:

Tools-> Debug - USBtiny Programmer

Pronto !!!

Se você perdeu o bootloader e quer restaurá-lo basta usar a própria USBtiny e a IDE da Arduíno (recomendo fazer isso com uma conta de administrador do Windows, se você estiver usando Windows):

Tools->Board
Tools->Programmer->USBtinyISP
Tools->Burn Bootloader