Automação com GENUINO

Introdução

A plataforma Genuino, tornou-se bastante popular ao longo dos anos, sendo uma das plataformas mais usadas em projectos de IoT e automação, tanto pelo seu baixo custo como pela sua capacidade de processamento e de I/O (input/output). Para os leitores que estão menos familiarizados com este tema, o Genuino é análogo da marca Arduino.cc, tendo sido criado pelos co-fundadores do Arduino Massimo Banzi, David Cuartielles, Tom Igoe e David Mellis. Na prática, o Genuino é usado para as boards vendidas fora dos EUA.

Isto é, a marca Genuino certifica também a sua autenticidade com a filosofia de hardware aberto e de código aberto que sempre caracterizou os valores do Arduino. As placas Genuino e Arduino partilham os mesmos componentes e as mesmas características. São as mesmas boards, mas a “marca” do circuito é determinada pelo país. O Arduino é comercializado dentro dos EUA e o Genuino fora dos EUA.

Uma das tarefas mais simples que podemos realizar com o Genuino, consiste no “sentir” o mundo exterior! Sentir no sentido figurado, obviamente, pois as máquinas não sentem, “apenas” executam leituras, processamento e escrita. Sentir, neste caso, quer dizer “obter informação sobre o meio ambiente”. Ora como podemos fazê-lo? De diversas formas, usando para este fim sensores que comunicam recorrendo a diferentes protocolos de comunicação que executam leituras de diferentes parâmetros. Mais adiante no artigo faremos essa abordagem. Em suma, este artigo foca-se na comunicação entre o Genuino e sensores, tendo como projecto final um circuito que executa algumas tarefas simples de interacção com o mundo exterior.

Sensores

Como referido na introdução, utilizam-se sensores para obter dados sobre o mundo “exterior”, recorrendo a dispositivos que efectuam leituras. Para ligar estes sensores ao Genuino, recorremos ao GPIO (General Purpose Input Output). Dependendo do tipo de sensores, podemos usar entradas analógicas (que recebem informação em formato de voltagem), entradas digitais (que recebem informação em formato binário) e entradas dedicadas a determinados protocolos, como por exemplo I2C, PWM, etc.

Nota: No caso de se querer ligar um sensor analógico a uma porta analógica, pode ser usado um circuito ADC (Conversor Analógico Digital) tipo MCP3008.

Aqui surge o primeiro desafio: quando o sensor trabalha com uma voltagem diferente da do circuito. Neste caso recorremos a resistências pull-up e/ou pull-down ou a reguladores de tensão, conforme o que o leitor desejar executar. A resistência deve sempre ser calculada de acordo com a especificação do sensor que estamos a usar. Neste artigo serão usados sensores de Humidade e Temperatura DHT-11, ligados a portas digitais, bem como sensores de humidade ligados a portas analógicas.

É importante que o leitor tenha presente que existem diversos tipos de sensores, para as mais diversas finalidades, propósitos, dados, valores, leituras, etc. No caso específico deste artigo, serão usados sensores de humidade e temperatura do ar, humidade do solo, luminosidade e pressão barométrica de forma a ler dados do mundo “exterior”.

Actuadores

Contrariamente aos sensores, estes dispositivos não efectuam leituras de informação do mundo real. Os actuadores interagem com o mundo real, executando alguma tarefa. Um exemplo deste tipo de circuito é o tradicional relé, que tem dois estados possíveis (ligado / desligado), permitindo por exemplo, ligar ou desligar um equipamento eléctrico (até mesmo uma maquina de café!, fica o desafio ao critério da imaginação do leitor, fazer um circuito que tire café sozinho).

O protocolo

Uma grande parte dos sensores disponíveis comunica com o circuito por I2C e UART (Universal Asynchronous Receiver-Transmitter). O protocolo UART permite a transmissão de dados em stream de bits, de forma sequencial de maneira a que no destino os conjuntos sejam reunidos em bytes completos. Cada pacote UART usa um shift register que é fundamental para a conversão entre a forma série e a paralela. A transmissão em série por um único condutor é mais fácil que a transmissão paralela recorrendo a múltiplos condutores. Neste caso concreto iremos apenas usar UART para comunicar com o computador, apesar de o podermos usar por exemplo, para comunicar com um circuito wifi 802.11b/g.

Na figura seguinte, encontra-se representada uma frame UART, para facilitar a compreensão do leitor.

GENUINO: frame UART

A comunicação entre os sensores e o Genuino será feita com recurso a outros protocolos, nomeadamente I2C (Inter-Integrated Circuit).

Este protocolo caracteriza-se por ser um protocolo de comunicação em série síncrono, por partilhar o clock e proporcionar a utilização de múltiplos mestres (masters) e escravos (slaves). O comprimento de bits é fixo, independentemente do número de escravos (slaves) utilizados.

O I2C recorre apenas a dois fios condutores (SDA Serial Data e SCL Serial Clock). Se ambas as linhas de comunicação estão abertas, o estado do barramento é sempre conhecido do software e encontra-se em estado “high”, por padrão. Neste protocolo o mestre (master) inicia e termina a transmissão, bem como gera o sinal SCL (clock), os escravos “slaves”, são endereçados pelo mestre “master”, o transmissor é quem coloca os dados na linha e o receptor recebe os dados da linha.

Quer o SDA, como o SCL são bidireccionais.

Genuino: circuito

O circuito

Chegados à parte prática do nosso artigo, e como o objectivo deste não é um circuito de grande complexidade, vamos usar um sensor de humidade e temperatura, DHT-11, um sensor de luminosidade e um sensor de humidade do solo. Os sensores estarão ligados ao Genuino de forma simples. No caso do DHT-11 usaremos uma resistência pull-up e todo o circuito agirá de forma autónoma, mesmo quando desligado do computador.

Sempre que a humidade do solo desça abaixo de um valor de 40%, é accionado um relé, que em teoria estaria ligado a uma bomba de água que procederia à irrigação dos solos, até que o valor da humidade do solo retomasse os 40%.

As ligações são, todas elas, relativamente simples. No caso do DHT-11 é ligado à porta digital D2 do Genuíno, os relés, ficarão nas portas D4 e D5 do Genuíno e o sensor de luminosidade nas portas destinadas a I2C.

Posto isto, no código iremos fazer todas as operações de comunicação e processamento, bem como para efeitos de depuração de erros, colocar mensagens a serem transmitidas via série para um computador. Estas mensagens podem ser removidas ou utilizadas para por exemplo gerar gráficos, como referido no artigo da edição passada da PROGRAMAR.

#include "DHT.h"
#include <SparkFunTSL2561.h>
#include <Wire.h>

#define DHTPIN1 2 // define o pino de dados do sensor, neste caso 2
#define DHTPIN2 7 // define o pino de dados do sensor, neste caso 7
#define DHTTYPE DHT11 // DHT 11 (basta uma constante para dois sensores)
//main time delay before first run
#define mainTimeDelay 2000

//light sensor initial code
SFE_TSL2561 light;
boolean gain; // Gain setting, 0 = X1, 1 = X16;
unsigned int ms; // Integration ("shutter") time in milliseconds
//alterar conforme o sensor que se use (DHT 11,
//DHT 22 (AM2302), DHT 21 (AM2301) )
// Initializa DHT.
DHT dht1(DHTPIN1, DHTTYPE);
DHT dht2(DHTPIN2, DHTTYPE);
//define relé
int Relay1 = 4;
int Relay2 = 5;

int humidade;

//general setup ops
void setup()
{
  Serial.begin(9600);
  Serial.println("Serial Port OKay");
  dht1.begin();
  dht2.begin();

//light setup ops
  light.begin();
  unsigned char ID;
  if (light.getID(ID))
  {
    Serial.print("Got factory ID: 0X");
    Serial.print(ID,HEX);
    Serial.println(", should be 0X5X");
  }
  else
  {
    byte error = light.getError();
    printError(error);
  }
  gain = 0;
  unsigned char time = 2;
  Serial.println("Definindo intervalo...");
  light.setTiming(gain,time,ms);
  Serial.println("Power up...");
  light.setPowerUp();
//end of ligh sensor ops

//relay ops
  pinMode(Relay1, OUTPUT); //Set Pin4 as output
  pinMode(Relay2, OUTPUT); //Set Pin5 as output
  digitalWrite(Relay1, HIGH); //inicia o relay1 como desligado
  digitalWrite(Relay2, HIGH); //inicia o relay2 como desligado
}

void loop() {
  //delay(mainTimeDelay);
  dhtTemp1();
  dhtTemp2();
  lightSaber();
  moisture();
}

void dhtTemp1()
{
  // Aguarda um pouco antes de iniciar medicoes
  delay(2000); //pode ser um delay inicial

  //as leituras demoram cerca de 250ms,
  //logo as leituras serão 2 segundos e meio "atrasadas"
  float h = dht1.readHumidity();
  // le a temperatura em graus Celcius
  float t = dht1.readTemperature();
  // verifica se alguma leitura falhou e sai para recomecar
  if (isnan(h) || isnan(t)) {
    Serial.println("Falha na aquisição de dados do sensor DHT11-1!");
    return;
  }
  float hic = dht1.computeHeatIndex(t, h, false);
  Serial.print("Humidade do ar (sensor1): ");
  Serial.print(h);
  Serial.print(" %\t");
  Serial.print("Temperatura do ar (sensor1): ");
  Serial.print(t);
  Serial.print(" *C \n");
  //Serial.print("Indice de calor: ");
  /* HI = c1+c2T+c3R+C4TR+C5T^2+c6R^2+c7T^2R+c8TR^2+c9T^2R^2
  ver wikipédia https://en.wikipedia.org/wiki/Heat_index */
  Serial.println();
}

void dhtTemp2()
{
  // Aguarda um pouco antes de iniciar medicoes
  delay(2000); //pode ser acumulado no delay inicial

  //as leituras demoram cerca de 250ms,
  //logo as leituras serão 2 segundos e meio "atrasadas"
  float h = dht2.readHumidity();
  // le a temperatura em graus Celcius
  float t = dht2.readTemperature();
  // verifica se alguma leitura falhou e sai para
  //recomecar
  if (isnan(h) || isnan(t)) {
    Serial.println("Falha na aquisição de dados do sensor DHT11-2!");
    return;
  }
  float hic = dht2.computeHeatIndex(t, h, false);
  Serial.print("Humidade do ar (sensor 2): ");
  Serial.print(h);
  Serial.print(" %\t");
  Serial.print("Temperatura do ar (sensor 2): ");
  Serial.print(t);
  Serial.print(" *C \n");
  //Serial.print("Indice de calor: ");
  /*HI = c1+c2T+c3R+C4TR+C5T^2+c6R^2+c7T^2R+c8TR^2+c9T^2R^2
  ver wikipédia https://en.wikipedia.org/wiki/Heat_index */
  Serial.println();
}

void moisture()
{
  humidade = analogRead(A0); //pino analógico A0
  int Porcento = map(humidade, 1023, 0, 0, 100);
  Serial.print(Porcento);
  Serial.println("% humidade do solo");
  if (Porcento <= 10)
  {
    Serial.println("Humidade do solo abaixo dos 70%");
    digitalWrite (Relay1, !digitalRead(Relay1));
    digitalWrite(Relay1, HIGH); //Turn on relay
  }
  else
  {
    digitalWrite(Relay1, LOW); //desactuiva o sinal no pino 13 (desliga relé)
    digitalWrite (Relay1, !digitalRead(Relay1)); //Turn off relay
  }
  // delay(1000); //pode e deve ser acomulado no
  //main time delay
}

//light sensor functions:
void printError(byte error)
{
  Serial.print("I2C error: ");
  Serial.print(error,DEC);
  Serial.print(", ");
  switch(error)
  {
    case 0:
      Serial.println("success");
      break;
    case 1:
      Serial.println("data too long for transmit buffer");
      break;
    case 2:
      Serial.println("received NACK on address (disconnected?)");
      break;
    case 3:
      Serial.println("received NACK on data");
      break;
    case 4:
      Serial.println("other error");
      break;
    default:
      Serial.println("unknown error");
  }
}

// funcao principal do sensor de luz
void lightSaber()
{
  delay(ms);
  unsigned int data0, data1;
  if (light.getData(data0,data1))
  {
    /*Serial.print("Luminosidade data0: ");
    Serial.print(data0);
    Serial.print("\n Luminosidade data1: ");
    Serial.print(data1);*/
    double lux;
    boolean good;
    //calculo de Lux
    good = light.getLux(gain,ms,data0,data1,lux);
    Serial.print(" lux: ");
    Serial.print(lux);
    if (good) Serial.println(" (good) \n");
    else Serial.println(" (BAD) \n");
  }
  else
  {
    byte error = light.getError();
    printError(error);
  }
}

Conclusão

Este artigo pretendeu apresentar uma breve introdução à automação com o Genuino, realizando tarefas bastante básicas e primitivas, explicando os dois protocolos mais utilizados bem como uma breve explicação sobre as ligações feitas ao Genuino e o código que será carregado no mesmo.

As potencialidades são imensas, pelo que deixamos ao critério do leitor, explorar mais um pouco este tema. Para a próxima edição, apresentaremos um projecto um pouco mais complexo, usando conceitos dos artigos da edição 51 e desta edição! Até lá!!!

Publicado na edição 52 (PDF) da Revista PROGRAMAR.