terça-feira, 6 de maio de 2014

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.

 Manual de Setup Básico para Programação *.CPP (código c++) do AVR via comando de linha e sem IDE do Arduino.


Este post visa demonstrar uma forma de programar a Arduíno sem utilizar sua IDE e baseado em comando de linha (CLI) do Linux. Eu me inspirei nos seguintes posts:

Tutorial: Utilizando código .CPP na programação da Arduino
 
Compiling Arduino sketches using Makefile

 Se você tiver alguma sugestão, fique a vontade em adicionar comentário.

 

Pré-Requisitos:

[1] Linux Ubunt versão 14.04 - instalado conforme requisitos mínimos do fabricante;
          Nesta desmonstração utilizou-se uma CPU com 2GB RAM e processador dual core;
[2] Programador de AVR, USBtinyISP com cabo de 6 pinos adequado;
[3] Arduino Uno R3 (ou compatível) com chip AVR Atmega328 (ou compatível);
[4] IDE do Arduino versão 1:1.0.5+dfsg2-2
      (instalado via "Central de Programas do Ubuntu" ou gerenciador de pacotes "dpkg") funcionando e com a comunicação com programador de AVR (USBtinyISP) em funcionamento;

Imagens: 

Arduino Uno

 

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

 

Recomendações:

Utilizou-se uma instalação do Linux em CPU "baremetal", ou seja, direto em hardware para evitar problemas com drivers ou interfaces usb ou serial, uma vez que o USBtinyISP faz um uso não padrão da interface USB, utilizando-se dos pinos da USB de uma forma própria.

O uso de máquinas virtuais não é recomendado e, nas tentativas feitas em laboratório, houveram muitos problemas no reconhecimento da porta serial/usb para uso com o programador USBtinyISP.

 

Racional e Motivações:

Racional:

    O principal racional deste artigo é explicar como utilizar código C++ (arquivos tipo *.CPP) para programar o Arduino sem utilizar a interface gráfica de usuário e a partir de interface de comando de linha (CLI - command line interface) do Linux, buscando-se flexibilidade, leveza no gerenciamento do ciclo de vida do software.
    Explicar o uso da cadeia de ferramentas do compilador AVR-GGC ("AVR-GCC toolchain") sem uso da IDE (ambiente integrado de desenvolvimento) do Arduino. Também abordar como carregar o bootloader e um programa de testes básico de "led piscante" (led blink) em conjunto com uso de biblioteca para gravação de mémoria EEPROM (específica para AVR ATMEGA 328).


Motivações

    A necessidade de uma configuração de tool chain flexível e leve para um projeto envolvendo uso de Arduino.
    Para isso, buscou-se utilizar a cadeia de ferramenta debaixo da IDE do Arduíno inteiramente pelo uso de comandos de linha (CLI). Com isso ganha-se inumeras vantagens, principalmente flexibilidade no gerenciamento do ciclo de vida de produção do software e programação do hardware. Outra vantagem é que CLI é bastante leve, o que permite seu uso em computadores extremamente compactos, tais como em "single board computer".


ETAPAS:

As seguintes etapas serão detalhas a seguir:

[1] Configurações Básica;
[2] Testar o AVR Makefile ; Leds Blink a partir de arquivo *.INO; Carga via cabo USB direto no Arduino;
[3] Testar o AVR Makefile ; Leds Blink a partir de arquivo *.CPP; Carga via cabo USB direto no Arduino;
[4] Teste o AVR Makefile  com uso de arquivos *.CPP e bliblioteca externas; "Blink" + EPROM  a partir de arquivo *.CPP; Carga via cabo USB direto no Arduino;
[5] Carregar o codigo compilado *.HEX via programador (USBtinyISP);
[6] Teste por um emulador de terminal SERIAL (Minicom) em Ubuntu para verificar a saida de dados serial do teste "Blink + EEPROM + Serial *.CPP";
[7] Comando de linha (CLI) para carregar o bootloader do Arduino no AVR via programador USBtinyISP;


A seguir, o detalhamento de cada etapa:


[1] Configurações Básica

Instalar a IDE do Arduino no Linux Ubuntu:

 - Instalar via comando de linha:
     Digite o seguinte comando:
    
$ sudo apt-get update && sudo apt-get install arduino arduino-core

 -Instalar Arduino IDE via "Central de Programas do Ubuntu";
       Clicar sobre o icone "Central de Programas do Ubuntu"; 
       Ubuntu MENU > Search "Arduino"  ;

Aduino IDE v.1:1.0.5+dfsg2-1;  72.3MB para baixar; 163.5MB  quando instalado;

Depois de instalado, clique sobre o icone de IDE do Arduino. Deve aparecer a janela com uma mensagem de "Arduino Permission Checker - "dialout" group
                    ----------------------------------------------------
                      You need to be added to the "dial out" group to
                      upload code to an Arduino micro controller over
                      the USB or serial ports.

                       Click "Add" below to be added.
                    ----------------------------------------------------
                      You must log out and log in again before any
                      group changes will take effect.

Clique em "Add" para permitir o uso de portas de comunicações serial (tal como USB) pela IDE do Arduino.

 Permissão de Acesso para Porta USB (serial) para o programa"AVRDUDE" usada pela IDE do Arduino acessar o USBtinyISP diretamente como usuário normal:Conforme Ref.[5];
(esta opção foi testada no Ubuntu Desktop 64bit versão 13.10 e versão 14.04):


  •  Edite o seguinte arquivo:

 $ sudo vi /lib/udev/rules.d/10-usbtinyisp.rules
      ------------------------------------------------------------
              SUBSYSTEM=="usb", ATTR{product}=="USBtiny",
              ATTR{idProduct}=="0c9f", ATTRS{idVendor}=="1781",
              MODE="0660", GROUP="dialout"
      ------------------------------------------------------------
  •  Execute os seguintes comandos para ativar a nova regra:  

$ sudo udevadm trigger
$ /usr/bin/arduino


  •  Testar se a configuração funcionou através da IDE do Arduino:

   > MENU > Tools > Board > Arduino Uno
   > MENU > Tools > Burn Bootloader

OBS.:  Em outras versões de Linux, a configuração mostrada enteriormente poderá ser diferente. Outras possibilidades são:

$ sudo vi /etc/udev/rules.d/10-usbtinyisp.rules
      ------------------------------------------------------------
              SUBSYSTEM=="usb", ATTR{product}=="USBtiny",
              ATTR{idProduct}=="0c9f", ATTRS{idVendor}=="1781",
              MODE="0666"
      ------------------------------------------------------------
              ou
      ------------------------------------------------------------
              SUBSYSTEM=="usb", SYSFS{idVendor}=="1781",
              SYSFS{idProduct}=="0c9f", GROUP="adm", MODE="0666"
      ------------------------------------------------------------

OBS.:  Em outras versões de Linux pode haver outra forma de exercutar os comandos para ativar a nova regra, tais como o exemplo a seguir: 

$ sudo restart udev 
$ /usr/bin/arduino

 

Observação sobre os testes a seguir que utilizam IDE do Arduino: 


O objetivo destes testes é verificar o funcionamento da comunicação do programa "AVRDUDE" com a interface de comunicação serial subjacente. O uso da IDE do Arduino neste caso é por mera conveniencia, uma vez que, posteriormente, tudo será feito via comando de linha (CLI). A IDE do Arduino faz uso do AVRDUDE para sua comunicação serial com a placa (board) do Arduino.

 

(Teste) Programar o programa de led piscante (led blink) via IDE do Arduino com Placa Arduino com Bootloader Previamente Carregado e Testado. - como usuário (não root): 

- Conectar a placa arduino via USB na CPU (baremetal) com Linux Ubuntu v.13.10 ou v.14.04 (ou compatível);
-Fechar a IDE Arduino , caso já esteja aberta;
- Inicializar a IDE Arduino;
- Selecionar MENU >Tools > Board > Arduino Uno
- Selecionar MENU >Tools > Serial Port >      /dev/ttyACM0
- Carregar o exemplo básico do blink;  MENU > File > Examples > 01.Basics > Blink
- Rodar "PLAY" > Binary uploading;


 

(Teste) Carregar de um BootLoader em um Chip sem bootloader em um Arduíno (válido também para reprogramar Chips já previamente programados):

  •  Como programar o bootloader em um Arduino?
  1. Coloque um chip AVR novo (tal como o Atmega328)  no Arduino com a correta orientação;
  2. Remova o jumper do USBtinyISP
  3. Plugue o USBtiny na USB
  4. Plugue o Arduino em uma fonte de corrente direta (DC) ou cabo USB de forma a suprir energia
  5. Plugue o cabo de 6 pinos do USBtinyISP no Arduino de forma que a marca do pino 1 esteja alinhada com o fio vermelho do cabo
  6. Inicialize a IDE do Arduino
  7. Selecione o chip/arduino que esteja em uso (neste caso é o Uno) no menu: Tools->Board menu
  8. Não selecione porta COM/Serial
  9. Selecione Tools->Burn Bootloader->w/USBtinyISP
  10. A luz do led vermelho do USBtinyISP deve acender. Deve levar algum tempo, poucos segundos no Ubuntu v.14.04 a cerca de 2 minutos no Ubuntu v.13.10, para programar o chip.
  11. Quando terminar, a IDE irá informá-lo que foi completado e o led vermelho deve estar apagar.

 

Instalar a cadeia de ferramentas AVR-GCC AVR-LIBC e AVRDUDE:

Conforme Ref.[3]:

$ apt-get install gcc-avr avr-libc avrdude

 ou instalar separadamente:

$ sudo apt-get install gcc-avr
$ sudo apt-get install avrdude


Unix Setup - Paths

-99% das distribuições Unix tem a pasta  /usr/local/bin na variavel de ambiente padronizada  $PATH. Mas mesmo que não, é possivel usar a seguinte técnica para adicionar o caminho (diretório) na variável:
             
Abre o programa  Terminal ou xterm, este programa será usado para fazer a maioria das coisas neste texto.  Em Ubuntu está em "Applications"

Na nova janela do Terminal, entre com

$ echo $SHELL 
and press return

Se a saída for  /bin/bash então entre com o seguinte comando:

$ echo 'PATH=$PATH:/usr/local/bin' >> ~/.bash_profile

tudo em uma mesma linha. Tecle [return]


Instalar o AVR Makefile

 Conforme Ref.[1] , baixar o arquivo ZIP em Ref.[2]

Instalação
        Através de gerenciador de pacotes
                 
        Se é utilizido FreeBSD, Debian ou Ubuntu, pode achar isto no pacote "arduino-mk " e pode ser instalado pelo uso de apt-get ou aptide. Aqui, optou-se pelo apt-get.

 Requisitos

É necessário ter já instalado a IDE do Arduino. Você pode tanto instala-lo através do instalador ou pelo download do arquivo zip distribuito e extraí-lo. Aqui, optou-se pela instalação pelo gerenciador de pacote.

O Makefile também deleta a resetagem (resetting) da placa para um pequeno programa em Python. Portanto, é necessário instalar  pySerial para poder usar este código Python.

Em Debian ou Ubuntu:

$ apt-get install python-serial

  Instalar as dependências

O Makefile delega a resetagem (resetting) da placa a um pequeno programa em Perl. Portanto, é necessário instalar as bibliotecas  Device::SerialPort e YAML

Em Debian ou Ubuntu:

$ apt-get install libdevice-serialport-perl
$ apt-get install libyaml-perl

-Uso
 (baseado em  Ref.[2])


Instalação
        Através de gerenciador de arquivo ZIP.

 Baixar o arquivo zip:
 $ github.com—master.zip <https://github.com/sudar/Arduino-Makefile/archive/master.zip>

Extrair o conteudo do arquivo ZIP baixado. No arquivo  "README.md" há mais instruções:

              ## Installation

 $ sudo apt-get install arduino-mk

              ## Requirements

 $ sudo apt-get install python-serial

              ## Usage
Pode-se achar mais instruções detalhadas sobre isto no seguinte guia:
Ref.[1] (hardwarefun.com—compiling-arduino-sketches-using-makefile).
<http://hardwarefun.com/tutorials/compiling-arduino-sketches-using-makefile).>

$ sudo apt-get install libdevice-serialport-perl
$ sudo apt-get install libyaml-perl
       
Instalar MINICOM          
Instalação

No Terminal  (ir em  "Aplicações" >  Applications > Accessories > Terminal) atualize o cache do apt com o seguinte comando:

$ sudo apt-get update

Instalar o programa através do seguinte comando:

$ sudo apt-get install minicom


[2] Testar o AVR Makefile ; Leds Blink a partir de arquivo *.INO; Carga via cabo USB direto no Arduino;

    - Local: ./examples/Blink/Blink.ino
    - Exemplo Blink.ino sem alteração na pasta de exemplos do AVR Makefile Project.

    - Arquivo "Blink.ino"
/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.
 
  This example code is in the public domain.
 */

void setup() {                
  // initialize the digital pin as an output.
  // Pin 13 has an LED connected on most Arduino boards:
  pinMode(13, OUTPUT);     
}

void loop() {
  digitalWrite(13, HIGH);   // set the LED on
  delay(1000);              // wait for a second
  digitalWrite(13, LOW);    // set the LED off
  delay(1000);              // wait for a second
}

    - Arquivo "Makefile"
BOARD_TAG    = uno
MONITOR_PORT  = /dev/ttyACM0
ARDUINO_LIBS = Wire SoftwareSerial

include ../../Arduino.mk

AVRDDUDE     = /usr/bin/avrdude
AVRDUDE_CONF = /etc/avrdude.conf


    - Usage
        - Ir para a pasta. Digitar make.
        - Plugar o Arduino com cabo USB
        - Digitar make install


[3] Testar o AVR Makefile ; Leds Blink a partir de arquivo *.CPP; Carga via cabo USB direto no Arduino;

    - Arquivo "blink.cpp"
// Comment
#include 
#include 
 
 
int main (void)
{
  unsigned char counter;
  /* set PORTB for output*/
  DDRB = 0xFF;
 
  while (1)
    {
      /* set PORTB.2 high */
      PORTB = 0xFF;
 
      /* wait (10 * 120000) cycles = wait 1200000 cycles */
      counter = 0;
      while (counter != 50)
 {
   /* wait (30000 x 4) cycles = wait 120000 cycles */
   _delay_loop_2(30000);
   counter++;
 }
 
      /* set PORTB.2 low */
      PORTB = 0x00;
 
      /* wait (10 * 120000) cycles = wait 1200000 cycles */
      counter = 0;
      while (counter != 50)
 {
   /* wait (30000 x 4) cycles = wait 120000 cycles */
   _delay_loop_2(30000);
   counter++;
 }
    }
 
  return 1;

}


    - Arquivo "Makefile"
// Comment
BOARD_TAG    = uno
ARDUINO_LIBS = LiquidCrystal
MONITOR_PORT  = /dev/ttyACM0

AVRDDUDE     = /usr/bin/avrdude
AVRDUDE_CONF = /etc/avrdude.conf

include ../../Arduino.mk


    - Usage
        - Ir para a pasta. Digitar make.
        - Plugar o Arduino com cabo USB
        - Digitar make install



[4] Teste o AVR Makefile  com uso de arquivos *.CPP e bliblioteca externas; "Blink" + EPROM  a partir de arquivo *.CPP;

      Carga via cabo USB direto no Arduino;

 Arquivo "blinkeeprom.cpp"

#include 
#include 

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);
}



    Arquivo "Makefile"

BOARD_TAG    = uno
MONITOR_PORT  = /dev/ttyACM0
ARDUINO_LIBS = Wire SoftwareSerial EEPROM

AVRDDUDE     = /usr/bin/avrdude
AVRDUDE_CONF = /etc/avrdude.conf


ARDUINO_HEADER := /usr/share/arduino/hardware/arduino/cores/arduino/Arduino.h
ARDUINO_CORE_PATH :=  /usr/share/arduino/hardware/arduino/cores/arduino/

USER_LIB_PATH     := /usr/share/arduino/hardware/arduino/variants/standard

LIB_DIRS =  $(ARDUINO_DIR)/libraries/LiquidCrystal $(ARDUINO_DIR)/libraries/Wire $(ARDUINO_DIR)/libraries/Wire/utility $(ARDUINO_DIR)/libraries/EEPROM .


# Separate each function and data into its own separate section to allow
# garbage collection of unused sections.
cflags-gnu-y += -ffunction-sections -fdata-sections
cxxflags-gnu-y += -ffunction-sections -fdata-sections

# Garbage collect unreferred sections when linking.
ldflags-gnu-y += -Wl,--gc-sections


# Don't use strict aliasing (very common in embedded applications).
cflags-gnu-y += -fno-strict-aliasing
cxxflags-gnu-y += -fno-strict-aliasing


HDRS = Arduino.h binary.h Client.h HardwareSerial.h IPAddress.h new.h pins_arduino.h Platform.h Printable.h Print.h \
    Server.h Stream.h Udp.h USBAPI.h USBCore.h USBDesc.h WCharacter.h wiring_private.h WString.h

include ../../Arduino.mk

-Uso

        -  Ir para a pasta. Digitar make.
        - Plugar o Arduino com cabo USB
        - Digitar make install

[5] Carregar o codigo compilado *.HEX via programador (USBtinyISP);


Comando de linha para carregar o programa compilado *.HEX via programador USBtinyISP:
    -Ir para a pasta onde está compilado o arquivo *.HEX
   
 $ cd <PATH>/examples/Blink+EPROM_CPP
           onde <PATH> é o diretorio onde foi instalado o projeto "AVR Makeline".

Digitar o seguinte comando de linha para carregar o programa compilado *.HEX via programador USBtinyISP:
      
$   /usr/bin/avrdude -q -V -D -p atmega328p -C /etc/avrdude.conf -c arduino -b 115200 -cusbtiny -U flash:w:build-uno/Blink+EPROM_CPP.hex:i

OBSERVACAO: copiado diretamento do LOG da IDE do Arduino COM alteração - Retirado "-P /dev/ttyACM0" e adicionado "-cusbtiny" ;


Fonte: LOG (verbose) de upload do Arduino IDE; Mescados os comandos de bootloader e de codigo;

[6] Teste por um emulador de terminal SERIAL em Ubuntu para verificar a saida de dados serial do teste "Blink + EEPROM + Serial *.CPP"; 10h56 - Inicio de Teste c/ MINICOM;

Uso de MINICOM para testes de porta serial em Ubuntu v14.04 Uso do programa

   Selecione Applications-Accessories-Terminal.

   Para achar o nome da(s) porta(s) entre este comando de linha no Terminal:

              $ dmesg | grep tty

              ----------------------------------------------
  A saída deve ser algo como a seguir:

[   22.587279] console [tty0] enabled
[   24.186230] serial8250: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[   24.186860] 00:08: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[   51.598012] audit(1243322582.732:2): type=1503 operation="inode_permission" requested_mask="a::" denied_mask="a::" name="/dev/tty" pid=5705 profile="/usr/sbin/cupsd" namespace="default"



[   22.587279] console [tty0] enabled
[   24.186230] serial8250: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[   24.186860] 00:08: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[   51.598012] audit(1243322582.732:2): type=1503 operation="inode_permission" requested_mask="a::" denied_mask="a::" name="/dev/tty" pid=5705 profile="/usr/sbin/cupsd" namespace="default"
              ----------------------------------------------
              O que interessa é o nome da porta serial , neste caso ttyS0, que será necessário para usar no Minicom. No terminal entre:
              ----------------------------------------------
             $ sudo minicom -s
              ----------------------------------------------

 

Instruções gerais de uso do "Minicom":

's' é a opção para "setup", pois é necessário configurar parâmetros tais como velocidade da porta, paridade da porta e alguns outros itens. É possível editar os valores padrões em amplo escopo do sistema (system-wide) no arquivo /etc/mini‐com/minirc.dfl com essa opção.Um novo menu será mostrado, de forma que as teclas de "setas" podem selecionar o item com label "Serial Port Setup" e então tecla 'Enter'.

Isto irá abrir um novo menu no qual você precisa fazer algumas mudanças. Digite 'A' e definir o nome do dispositivo serial, no nosso caso / dev/ttyS0 Agora pressione "Enter" para definir as alterações . Digite 'E' para definir a velocidade da porta , paridade, etc ( esta informação será no manual do usuário do dispositivo que você deseja conectar . O novo menu vai dar -lhe um número de opções que você pode usar 'A' e 'B " para alternar entre as velocidades de porta ou 'C' , 'D' e 'E' para velocidades pré-selecionadas . O próximo valor é o número de bits de dados ( normalmente 8) use as teclas de SV para definir isso. seguida, vem a paridade ( normalmente Odd ) use chaves LP . Finalmente temos stop bits ( normalmente 1), estabelecidos pela 'W' chaves 'X'. Se você não tiver certeza das configurações pressione as teclas " C " e " Q " como estas são as configurações padrão para muitos dispositivos . Pressione ' Enter' para manter essas novas configurações. a configuração final é Hardware ou Software de controle (consulte o manual do usuário ), pressione 'F' e 'G' para alternar -los dentro e fora , conforme necessário. Pressione ' Enter' para salvar as configurações . para salvar todas as configurações para o etc / mini- com / minirc.dfl arquivo / selecione " salvar configurações como dfl ' . Outra opção útil é para registrar todas as informações em um arquivo que será salvo no seu diretório Home. Selecione" Nomes de arquivos e caminhos 'e pressione ' F ' ( opções de log ) . Por padrão, esse será salvo como ' minicom.log ' , mas alterá-lo para o que quiser com a tecla ' A'. Pressione "Enter" para salvar as alterações .

Para sair do Minicom quando está no modo terminal, pressione 'Ctrl-A' para obter uma barra de mensagens na parte inferior da janela do terminal e então pressione 'X'.


  [7] Comando de linha (CLI) para carregar o bootloader do Arduino no AVR via programador USBtinyISP;

     
Segue o seguinte comando:

/usr/share/arduino/hardware/tools/avrdude -C/usr/share/arduino/hardware/tools/avrdude.conf -v -v -v -v -patmega328p -cusbtiny -Uflash:w:/usr/share/arduino/hardware/arduino/bootloaders/ optiboot/optiboot_atmega328.hex:i -Ulock:w:0x0F:m

Fonte: LOG (verbose) de upload do Arduino IDE;  Obtido copiado diretamento do LOG da IDE do Arduino sem alteração;


Referencias para este post:

  • Ref.[0] marchanjo.blogspot.com.br  <http://marchanjo.blogspot.com.br/>
  • Ref.[1] hardwarefun.com—compiling-arduino-sketches-using-makefile  <http://hardwarefun.com/tutorials/compiling-arduino-sketches-using-makefile>
  • Ref.[2] github.com—Arduino-Makefile  <https://github.com/sudar/Arduino-Makefile>
  • Ref.[3] www.javiervalcarce.eu—Program_Arduino_with_AVR-GCC    <http://www.javiervalcarce.eu/wiki/Program_Arduino_with_AVR-GCC>
  • Ref.[4] playground.arduino.cc—Ubuntu    <http://playground.arduino.cc/Linux/Ubuntu>
  • Ref.[5] learn.adafruit.com—avrdude     <https://learn.adafruit.com/usbtinyisp/avrdude>

Nenhum comentário: