Está na moda o conceito Internet of Things, que se refere à capacidade de interagir com dispositivos físicos, obtendo informação/métricas (e.g., temperatura, humidade, etc.) e enviando comandos/acções (e.g., abrir porta, ligar ar condicionado, etc.).
O conceito, que não é novo, implica colaboração entre profissionais de electrónica, programadores e até DBAs. Este workshop é adequado para programadores e DBAs que têm poucos conhecimentos de electrónica, dando-lhes uma introdução à utilização de Arduino (actualmente referido como Genuino na Europa), uma das mais conhecidas plataformas de electrónica utilizada nesta área.
Após termos apresentado este workshop no Genuino Day Lisbon 2016 (em 2016-04-02, na Microsoft Lisbon Experience), e também no IoT Summit 2016 (em 2016-05-05, também na Microsoft Lisbon Experience), decidimos publicar o guião utilizado. Queremos também deixar um agradecimento especial ao João Antunes (do CERN) e ao António Lourenço, pelo apoio pedagógico durante os workshops.
Conhecer o hardware
Existem vários modelos de Arduino/Genuino. Aqui vamos apenas trabalhar com os modelos Uno e Mega.
As maiores diferenças entre eles são a velocidade, a quantidade de memória, e o número e tipo de pinos. Alguns são conectados via USB por ligação USB do tipo B, e outros por uma ligação Micro-USB do tipo B. As posições do botão de Reset e dos LEDs também variam conforme o modelo e versão.
Para efeitos deste workshop, utilizaremos pinos e funcionalidades que são comuns a todos.
Arduino Uno
- USB para alimentação e comunicação;
- Alimentação alternativa (de 9V a 12V, pino central é + );
- Pinos de alimentação (saídas e entradas);
- Pinos de entrada analógica (podem ser usados como digitais);
- Pinos de entrada/saída digital ( ~ significa saída digital PWM)
- Processador;
- Botão de Reset;
- LEDs: RX e TX indicam comunicação série (porta USB), L apresenta o valor do pino 13.
Breadboards
Hello World com o LED integrado
Após instalar o IDE do Arduino (https://Arduino.CC/en/Main/Software) e conectá-lo através do cabo USB, é necessário configurá-lo. Começamos por escolher a porta série onde está ligado (normalmente só haverá uma).
De seguida, é necessário escolher o modelo do Arduino.
Em alguns casos (como o Arduino Mega) é também necessário escolher a versão.
O IDE do Arduino já vem com alguns exemplos. Vamos começar por utilizar o exemplo Blink, para piscar o LED integrado na board (L), que está ligado ao pino 13.
O exemplo mostra duas funções:
setup()
Nesta função inicializamos o hardware que estamos a utilizar. Esta função corre uma única vez quando o Arduino é alimentado.loop()
Nesta função colocamos o programa que realiza a função pretendida. Chegando ao fim desta função, é novamente chamada (repete-se indefinidamente).
Após criar o programa, devemos validá-lo. Para isso, utilizamos o primeiro botão da barra de ferramentas (√).
Para enviar o programa para o Arduino, utilizamos o segundo botão (→). Durante o upload, veremos várias mensagens na parte inferior do IDE, assim como os LEDs RX e TX da placa a piscar. Uma vez concluído o upload, o programa inicia-se automaticamente. Neste caso, piscará o LED L integrado na placa. Poderá ajustar o delay()
para alterar a duração de cada estado (ligado ou desligado) do LED. O delay()
utiliza milissegundos. Começamos por implementar o seguinte esquema, com um botão e uma resistência elevada (e.g. 10 kΩ).
Este esquema, que enquanto o botão não é carregado está a enviar 0V para a entrada, chama-se “pull-down”. Existe também o “pull-up”, mas aí por omissão a entrada recebe +5V (ou +3,3V, conforme o tipo de placa).
De seguida, carregamos o exemplo Button. Após o upload, o botão funcionará para activar o LED. Utilizando o esquema do laboratório anterior, vamos enviar o estado do botão pela ligação USB/série para o computador. Vamos abrir o exemplo DigitalReadSerial.
Após enviar o programa para o Arduino, vamos ver o que é enviado para a porta USB/série, usando o Serial Monitor.
Nota: Antes de ligar o Serial Monitor, em alguns o buffer da saída série enche rapidamente, e aí LED começa a piscar aleatoriamente e o programa fica suspenso na linha de Serial.println()
.
Podemos também enviar texto personalizado de debug. Por exemplo, acrescentamos a linha (respeitar sempre maiúsculas/minúsculas).
[...] Serial.println(buttonState); if (buttonState) Serial.println("LIGADO"); else Serial.println("DESLIGADO"); delay(1); // delay in between reads for stability [...]
Aproveitando o esquema dos laboratórios anteriores, vamos acrescentar um relé (que age como um interruptor que pode controlar equipamentos externos).
Acrescentamos ao final da função setup()
:
pinMode(13, OUTPUT); pinMode(12, OUTPUT);
Acrescentamos ao final da função loop()
:
digitalWrite(13, buttonState); digitalWrite(12, !buttonState);
Porque é que o valor do pino 12 (relé) está invertido? Os relés que vamos utilizar ficam activos se no seu pino de sinal receberem 0V, e ficam inactivos se receberem 5V (ou não forem ligados). Nem todos os relés são assim, convém testar antes de utilizar.
Utilizando o esquema dos laboratórios anteriores, vamos acrescentar um sensor de temperatura ou luminosidade analógico ao pino A0.
De seguida, carregamos o exemplo AnalogReadSerial.
Abrimos novamente o Serial Monitor para ver os valores do sensor. A leitura de pinos analógicos (A0, A1, etc.) retorna valores entre 0 e 1023 (ou seja, linearmente entre 0V e 5V). No entanto, é provável que o sensor escolhido só apresente valores em parte desta gama. Registe os valores mínimos e máximos dos sensor para utilizar no laboratório seguinte.
Utilizando o esquema dos laboratórios anteriores, vamos definir regras para activar o relé. Por exemplo, se usarmos um sensor de luminosidade, quando deixarmos de ter luminosidade, queremos activar o relé para ligar uma lâmpada.
Acrescentamos ao final da função setup()
:
pinMode(13, OUTPUT); pinMode(12, OUTPUT); pinMode(2, INPUT);
Acrescentamos ao final da função loop()
:
if (sensorValue > 500 || digitalRead(2)) { // Rele ligado digitalWrite(13, HIGH); digitalWrite(12, LOW); } else { // Rele desligado digitalWrite(13, LOW); digitalWrite(12, HIGH); }
O valor exacto (aqui 500) e o operador (>
ou <
) podem variar conforme o sensor. Utilize os valores obtidos no laboratório anterior para calibrar.