Nesta página vamos criar um primeiro projeto destinado a controlar um LED ligado externamente à placa e obter o estado dum botão de pressão também a ela ligado. Isto será feito a partir da aplicação PuTTY a correr no computador onde a placa se encontra ligada (via cabo USB), pelo envio/receção de mensagens de texto.
Esquemático
O esquemático do circuito pode ser visto de seguida, sendo que o LED está ligado no porto 13 e o botão no porto 8, portos a configurar respetivamente como de saída e entrada:
Mensagens
O ligar/desligar do LED será feito pelo envio das mensagens (comandos) “l1” e “l0” seguidas de <enter> (código ASCII 13 que servirá de marcador de fim de mensagem).
O envio do comando “b” fará a placa responder com uma mensagem (resposta) com o estado do botão: “b1” se ele estiver premido, “b0” se estiver despremido. Estas mesmas respostas serão enviadas pela placa caso o botão sofra uma mudança no seu estado.
Template
Este projeto como todos os que se seguirão partem dum projeto base que implementa todo o mecanismo de receção dos comandos. Esse “template” está já disponível num repositório GitHub e pode ser usado para a criação do projeto no Eclipse.
Quando da primeira utilização desta funcionalidade, há que fazer algumas configurações iniciais:
- Em Windows > Preferences > Team > Git > Default repository folder, indicar a mesma pasta escolhida para o workspace. Para isso basta carregar no botão “Variable…” e escolher a última: ${workspace_loc}
- Em Windows > Preferences > Team > Git > Configuration > User Settings, adicionar duas entradas (Add Entry…) ao ficheiro de configuração .gitconfig, por exemplo:
– Key: user.email; Value: [email protected]
– Key: user.name; Value: Helio Mendonca
Seguem-se depois os passos para a clonagem do repositório que contem o template:
- Project Explorer < Import… > Git > Projects from Git > Next
- Clone URl > Next
- URl: https://github.com/hsm-feup/Duino > Next > Next
- Directory: D:\workspace\ledbut > Next
- Use the New Project wizard > Finish
- Arduino > New Arduino sketch > Next
- Project name: ledbut
- Location: D:\workspace\ledbut > Next
- No caso duma placa Arduino Uno, escolher:
Boards.txt file: C:\eclipseArduino\arduino\hardware\arduino\avr\boards.txt
Board: Arduino Uno
Port: COM7 - No caso duma placa Teensy 3.1, escolher:
Boards.txt file: C:\eclipseArduino\arduino\hardware\teensy\all\boards.txt
Board: Teensy 3.1
Port: COM3
USB type: Serial
CPU Speed: 96 MHz (overclock)
Keyboard Layout: Portuguese - Next > Next > Finish
- Apagar o conteúdo dos ficheiros ledbut.cpp e ledbut.h pois serão editados mais tarde!
Este projeto base é constituído pelos ficheiros main.cpp e server.cpp (e respetivos ficheiros .h).
No caso do ficheiro server.cpp, ele é constituído pelas rotinas:
- initServer – que inicializa a comunicação série a 115200 bits por segundo) e envia uma mensagem inicial
- getCmd – que retorna um apontador para a mensagem recebida ou 0 caso isso ainda não tenha ocorrido
- sendMsg – a rotina a usar quando a placa pretende enviar uma mensagem ao computador
#include "main.h" void initServer() { Serial.begin(115200); Serial.println("Arduino v1.0"); } #define CMD_SIZE 10 char *getMsg(void) { int c; int static index; char static cmd[CMD_SIZE+1]; if ((c = Serial.read()) != -1) { if (index && ((char) c == '\r')) { cmd[index] = '\0'; index = 0; return cmd; } else { if (index < CMD_SIZE) cmd[index++] = (char) c; return 0; } } return 0; } void sendMsg(char *msg) { Serial.println(msg); }
No caso do ficheiro main.cpp, ele é constituído pelas rotinas:
- setup – a ser executada apenas no início e onde se colocam as chamadas às rotinas de inicialização como por exemplo a initServer
- loop – rotina a ser executada ciclicamente e onde se começa por confirmar se foram recebidas mensagens, e em caso afirmativo são chamadas as rotinas correspondentes
#include "main.h" void setup() { initServer(); // introduza aqui as rotinas de inicializacao } void loop() { char *msg; if ((msg = getMsg()) != 0) { switch(msg[0]) { case 'v': sendMsg("Arduino v1.0"); break; } } // introduza aqui as rotinas a executar ciclicamente }
Desde já é possível compilar o projecto e programar a placa . Mesmo ainda não tendo as funcionalidades de controlo do LED e do botão, é possível testar a comunicação com a placa através do envio do único comando para já existente: o comando v que solicita o envio duma resposta com a versão do programa.
Projeto ledbut
Caso se pretenda fazer o controlo de versões deste projeto é necessário criar um repositório próprio no GitHub:
- https://github.com > New repository
- Repository name: ledbut
- Create repository
- Eclipse > Project Explorer > ledbut > Team > Remote > Configure Push to Upstream
- Change… > URl: https://github.com/<user>/ledbut > Finish
- Save and Push
Inroduzir credenciais (User e Password)
Selecionar “Store in Secure Store” para memorizar as credenciais
OK > OK
Finalmente as funcionalidades pretendidas (controlo do LED e do botão) são adicionadas aos ficheiros ledbut.cpp e ledbut.h a acrescentar ao projeto:
- Criar o ficheiro ledbut.h:
ledbut > New > Header File
Header file: ledbut.h
Finish
O ficheiro ledbut.h contem os cabeçalhos das seguintes funções:
- initLedBut, faz determinadas inicializações necessárias à funcionalidade pretendida, neste caso a configiração dos pinos de entrada e saída
- cmdLed, faz as ações necessárias ao comando destinado a (des)ligar o LED
- cmdBut, pede o estado do botão
- procBut, é a função que é chamada ciclicamente e que informa se houve alteração no estado do botão
#ifndef LEDBUT_H_ #define LEDBUT_H_ #define LED 13 #define BUT 8 void initLedBut(); void cmdLed(char *msg); void cmdBut(char *msg); void procBut(); #endif /* LEDBUT_H_ */
- ledbut > New > Source File
- Source file: ledbut.cpp
- Finish
- Editar ledbut.cpp
#include "main.h" int but; void initLedBut() { pinMode(BUT, INPUT); digitalWrite(BUT, HIGH); but = digitalRead(BUT); pinMode(LED, OUTPUT); digitalWrite(LED, LOW); } void cmdLed(char *msg) { if (msg[1] == '1') { digitalWrite(LED, HIGH); } else { digitalWrite(LED, LOW); } } void cmdBut(char *msg) { if (!but) sendMsg("b1"); else sendMsg("b0"); } void procBut() { int b = digitalRead(BUT); if (b != but) { but = b; if (!but) sendMsg("b1"); else sendMsg("b0"); } }
- Editar main.cpp
#include "main.h" void setup() { initServer(); initLedBut(); } void loop() { char *msg; if ((msg = getMsg()) != 0) { switch(msg[0]) { case 'v': sendMsg("ledbut v1.0"); break; case 'l': cmdLed(msg); break; case 'b': cmdBut(msg); break; } } procBut(); }
- Editar main.h
// Only modify this file to include // - function definitions (prototypes) // - include files // - extern variable definitions // In the appropriate section #ifndef _main_H_ #define _main_H_ #include "Arduino.h" //add your includes for the project here #include "server.h" #include "ledbut.h" //end of add your includes here #ifdef __cplusplus extern "C" { #endif void loop(); void setup(); #ifdef __cplusplus } // extern "C" #endif //add your function definitions for the project here //Do not add code below this line #endif /* _main_H_ */
Bibliotecas
Para adicionar uma biblioteca teremos com o projeto selecionado fazer:
Arduino > Add a library to the selected project
Os endereços são os seguintes:
- 1Eh – HMC5883L (compasso)
- 24h – PN532 (NFC)
- 53h – ADXL345 (acelerómetro)
- 69h – L3G4200D (giroscópio)
- 77h – BMP085 (barómetro)