IoT feito simples: Estação meteorológica doméstica com NodeMCU e OLED

Continuemos nossa exploração pelo mundo do IoT, nas asas do NodeMCU! Neste tutorial, desenvolveremos uma estação meteorológica doméstica, onde se exibirá informações tais como temperatura e condições climáticas, tanto para o dia corrente quanto para os próximos 3 dias. Nossa estação também exibirá informações internas da casa, como temperatura e umidade relativa do ar.

O diagrama em blocos abaixo, nos dá uma visão geral sobre o projeto:

No vídeo abaixo, você pode ver como ficará o projeto final:

1: Lista de materiais (BoM)

Valores referenciais em USD

  • Fonte externa de 5V ou bateria

2: Instalando o OLED no NodeMCU

Suponho que você já tenha o IDE do Arduino preparado com todas as bibliotecas necessárias para executar o código NodeMCU. Caso não, leia as instruções em meu tutorial premiado: Do “blink” ao BLYNK, uma viagem pela “Internet das coisas” nas asas do NodeMCU ESP-12E

Agora é hora de instalar nosso velho conhecido, o display OLED SSD1306, cujas principais características são:

  • Tamanho da tela: 0.96 “
  • Comunicação Serial I2C IIC SPI
  • 128X64
  • Display de caracteres na cor branca

Conecte os pinos do OLED ao NodeMCU, conforme descritos abaixo e no diagrama elétrico acima:

  • SDA    ==> D1 (5)
  • SCL * ==> D2 (4) * Você também poderá encontrar “SDC” ao invés de SCL
  • VCC   ==> 3.3V ou 5V
    GND ==> GND

O SSD1306 pode ser alimentado tanto com 5V (externo) quanto com 3.3V fornecidos diretamente do módulo NodeMCU.

Depois de conectar o OLED,devemos baixar e instalar sua biblioteca no IDE do Arduino. Usamos em projetos anteriores a biblioteca desenvolvida pela ACROBOT, que apesar de fácil de usar, é mais limitada. Desta vez exploraremos a poderosa biblioteca gráfica desenvolvida por Daniel Eichhorn.  Entre no link abaixo e faça o descarregue a biblioteca, instalando-a no IDE do Arduino:

https://github.com/squix78/esp8266-oled-ssd1306

Certifique-se de usar a versão 3.0.0 ou maior!

Depois de reiniciado o IDE, a biblioteca já deverá estar instalada.

A biblioteca suporta o protocolo I2C para acessar a modulo OLED, usando a biblioteca Wire.h:

#include <Wire.h>   
#include "SSD1306.h"
SSD1306  display(ADDRESS, SDA, SDC);

Listaremos apenas algumas API mais importantes, as quais serão utilizadas com o OLED.

A lista completa poderá ser encontrada no GITHub fornecido anteriormente neste tópico.

A. Controle de exibição do display:

void init(); // Initialise the display
void resetDisplay(void); // Cycle through the initialisation
void displayOn(void); // Turn the display on
void displayOff(void); // Turn the display offs
void clear(void); // Clear the local pixel buffer
void invertDisplay(void); // Inverted display mode
void normalDisplay(void); // Normal display mode
void setContrast(char contrast); // Set display contrast
void flipScreenVertically(); // Turn the display upside down

B. Desenho gráfico

void setColor(OLEDDISPLAY_COLOR color); // Sets the color of all pixel operations
void setPixel(int16_t x, int16_t y); // Draw a pixel at given position
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1); // Draw a line from pos 0 to pos 1
void drawHorizontalLine(int16_t x, int16_t y, int16_t length); // Draw a line horizontally
void drawVerticalLine(int16_t x, int16_t y, int16_t length); // Draw a lin vertically
void drawFastImage(int16_t x, int16_t y, int16_t width, int16_t height, const char *image); // Draw a bitmap in the internal image format

C. Operações com texto:

void drawString(int16_t x, int16_t y, String text); 
// Write the text at given position
uint16_t getStringWidth(const char* text, uint16_t length); 
// Returns the width of the const char* with the current font settings
uint16_t getStringWidth(String text); 
// Convenience method for the const char version
void setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment); 
// TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER_BOTH
void setFont(const char* fontData); 
// Sets the current font. 

// Available default fonts: ArialMT_Plain_10, ArialMT_Plain_16, ArialMT_Plain_24

D. Frames (“Ui Library”)

A Ui Library é utilizada para fornecer um conjunto básico de elementos Ui chamados, Frames e Overlays. Um Frame é usado para fornecer informações onde o comportamento padrão é exibir um Frame por um tempo definido e passar para o próximo (como “Paginas”). A biblioteca também fornece um Indicador de qual frame (ou página) está sendo mostrada. Um overlay, por outro lado, é uma informação (por exemplo, um relógio) que é exibido sempre na mesma posição.

void init(); // Initialise the display
void setTargetFPS(uint8_t fps); //Configure the internal used target FPS
void enableAutoTransition(); //Enable automatic transition to next frame
void disableAutoTransition(); // Disable automatic transition to next frame.
void setAutoTransitionForwards(); // Set the direction if the automatic transitioning
void setAutoTransitionBackwards(); // Set the direction if the automatic transitioning
void setTimePerFrame(uint16_t time); //Set the approx. time a frame is displayed
void setTimePerTransition(uint16_t time); //Set the approx. time a transition will take
void setFrameAnimation(AnimationDirection dir); //Configure what animation is used to transition
void setFrames(FrameCallback* frameFunctions, uint8_t frameCount); //Add frame drawing functions
int8_t update();  // This needs to be called in the main loop

Uma vez que o OLED e sua biblioteca estejam instalados, escreveremos um simples programa, o “Hello World” para testá-los. Entre com o código abaixo em seu IDE, o resultado deverá ser algo como mostrado na foto:

/* Hello World OLED Test */
#include   // Only needed for Arduino 1.6.5 and earlier
#include "SSD1306.h" // alias for `#include "SSD1306Wire.h"`
SSD1306  display(0x3c, 5, 4); // Initialise the OLED display using Wire library
void setup() 
{
  Serial.begin(115200);
  display.init(); // Initialising the UI will init the display too.
  display.flipScreenVertically();
  
  display.clear();
  drawHelloWorld(); 
  display.display();
}
void loop() 
{
  
}
void drawHelloWorld() 
{
    display.setTextAlignment(TEXT_ALIGN_LEFT);
    display.setFont(ArialMT_Plain_10);
    display.drawString(0, 0, "Hello world");
    display.setFont(ArialMT_Plain_16);
    display.drawString(0, 10, "Hello world");
    display.setFont(ArialMT_Plain_24);
    display.drawString(0, 26, "Hello world");
}

Agora, carregue a sketch: SSD1306SimpleDemo.ino, a qual faz parte dos EXEMPLOS incluídos com biblioteca.

Antes de executar o código, altere a conexão OLED pinos em conformidade:

// Initialise the OLED display using Wire library
SSD1306  display(0x3c, 5, 4);

O vídeo abaixo mostra o OLED executando o código de teste:

3: Obtendo os dados internos (“Indoor”)

Neste momento, nosso NodeMCU já pode se comunicar com o mundo pelo display! Instalemos agora um sensor digital de Temperature  e umidade, nosso bom e velho DHTxx (DHT11 ou DHT22). O site da ADAFRUIT fornece ótimas informações sobre esses sensores. Abaixo, algumas informações retiradas do site:

Visão geral

Os sensores de temperatura e umidade de baixo custo da família DHT, são muito básicos e lentos, mas ótimos para hobbyists que querem fazer algum registro de dados básico. Os sensores DHT são construídos em duas partes, um sensor de umidade capacitiva e um termistor. Há também um chip muito básico no interior que faz a conversão analógica para digital. O sinal digital gerado é bastante simples de ser lido usando-se qualquer micro controlador.

DHT11 vs DHT22

Temos duas versões do sensor DHT, eles se parecem e têm a mesma pinagem, mas possuem algumas características diferentes. Aqui estão as especificações:

DHT11

  • Bom para leituras de 20-80% de humidade com 5% de precisão
  • Bom para leituras de temperatura de 0-50 ° C ± 2 ° C de precisão
  • Não mais de 1 Hz taxa de amostragem (uma vez por segundo)
  • Ultra baixo custo
  • Alimentação: 3 a 5V
  • Consumo: 2.5mA max (durante a conversão de dados)
  • Tamanho do corpo 15.5mm x 12mm x 5.5mm
  • 4 pinos com espaçamento de 0,1 “

DHT22

  • Bom para leituras de 0-100% de humidade com precisão de 2 a 5%
  • Bom para leituras de temperatura de -40 a 125 ° C Precisão de ± 0,5 ° C
  • Não mais de 0,5 Hz taxa de amostragem (uma vez a cada 2 segundos)
  • Baixo custo
  • Alimentação: 3 a 5V
  • Consumo: 2.5mA max (durante a conversão de dados)
  • Tamanho do corpo 15.1mm x 25mm x 7.7mm
  • 4 pinos com espaçamento de 0,1 “

Como você pode ver, o DHT22 é um pouco mais preciso e melhor sobre um intervalo ligeiramente maior. Ambos usam um único pino digital e são “lentos”, pois você não pode consultá-los mais de uma vez a cada segundo (DHT11) ou dois (DHT22).

Ambos os sensores funcionam bem para obter informações sobre o interior da casa a serem exibidas em nossa Estação Meteorológica Doméstica.

O DHTxx tem 4 pinos (olhando para o sensor, como mostra a foto, o pino 1 é o mais à esquerda):

  1. VCC (conectado a 5V externo ou a 3.3V de NodeMCU)
  2. Dados
  3. Não conectado
  4. Terra.

Uma vez que normalmente você usará o sensor em distâncias inferiores a 20m, um resistor de 10K ohms deve ser conectado entre os pinos Data e VCC. O pino de saída será conectado ao pino D3 do NodeMCU (veja o diagrama acima).

Uma vez instalado o sensor em nosso módulo, faça o download da biblioteca DHT do repositório GitHub da Adafruit e instale-o no arquivo de bibliotecas do Arduino.

Uma vez recarregado o IDE do Arduino, a “biblioteca de sensores DHT” deverá estar instalada.

Definamos os parâmetros e variáveis associadas para o sensor  (usaremos em primeiro lugar oDHT22):

/* DHT22 */
#include "DHT.h"
#define DHTPIN D3  
#define DHTTYPE DHT22 
DHT dht(DHTPIN, DHTTYPE);
int localHum = 0;
int localTemp = 0;

Agora criaremos uma função para leitura dos dados:

/***************************************************
* Get indoor Temp/Hum data
****************************************************/
void getDHT()
{
  float tempIni = localTemp;
  float humIni = localHum;
  localTemp = dht.readTemperature();
  localHum = dht.readHumidity();
  if (isnan(localHum) || isnan(localTemp))   // Check if any reads failed and exit early (to try again).
  {
    Serial.println("Failed to read from DHT sensor!");
    localTemp = tempIni;
    localHum = humIni;
    return;
  }
}

Uma vez de posse dos dados, usemos o OLED para mostrá-los :

/***************************************************
* Draw Indoor Page
****************************************************/
void drawDHT() 
{
  int x=0;
  int y=0;
  display.setFont(ArialMT_Plain_10);
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.drawString(0 + x, 5 + y, "Hum");
  
  display.setFont(ArialMT_Plain_10);
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.drawString(43 + x, y, "INDOOR");

  display.setFont(ArialMT_Plain_24);
  String hum = String(localHum) + "%";
  display.drawString(0 + x, 15 + y, hum);
  int humWidth = display.getStringWidth(hum);

  display.setFont(ArialMT_Plain_10);
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.drawString(95 + x, 5 + y, "Temp");

  display.setFont(ArialMT_Plain_24);
  String temp = String(localTemp) + "°C";
  display.drawString(70 + x, 15 + y, temp);
  int tempWidth = display.getStringWidth(temp);
}

A foto abaixo mostra como os dados serão apresentados no display:

Você poderá fazer o download do código completo para operação “indoor” á partir de meu GitHub:

Home Weather Station Indoor code

4: Obtendo os dados externos (“Outdoor”):

Depois de ter as bibliotecas instaladas e o IDE reiniciado, baixe o programa completo a partir de meu GitHub:

MJRoBot Home Weather Station code

Depois de ter o código carregado no IDE do Arduino, abra o arquivo stationCredentials.h e entre com seus dados pessoais:

/* WIFI */
const char* WIFI_SSID = "YOUR SSID";
const char* WIFI_PWD = "YOUR PASSWORD";

/* Wunderground Settings */
const boolean IS_METRIC = true;
const String WUNDERGRROUND_API_KEY = "YOUR KEY";
const String WUNDERGRROUND_LANGUAGE = "EN";
const String WUNDERGROUND_COUNTRY = "CL";
const String WUNDERGROUND_CITY = "Santiago";

Observe que as informações meteorológicas que iremos recuperar do serviço W.Underground serão sobre Santiago (“city”) e CL (“country”: Chile). Você também deve alterá-las com os dados de sua cidade.

E é isso aí, pessoal!

Sua estação meteorológica doméstica deverá estar funcionando agora! Nas fotos abaixo, você pode ver meu protótipo funcionando:

5: Colocando a estação “na caixa”

A última etapa é montar nossa estação em uma caixa. Fiz duas montagens diferentes em caixas plásticas. Você decide a melhor maneira de “empacotar” seu projeto!

in the box 2

Em outra montagem, aproveitei e também testei a estação com o DHT11.

Não se esqueça de alterar os dados do DHT no arquivo “stationDefines.h”.

6: Conclusão

Como sempre, espero que este projecto possa ajudar outros a encontrarem o seu caminho no emocionante mundo da electrónica e do IoT!

Visite o meu depositário no GitHub para obter os arquivos atualizados:

MJRoBot Home Weather Station depository

Não deixem de visitar e seguir minha página: MJRoBot.org no Facebook

Saludos desde el sur del mundo!

Até o próximo tutorial!

Obrigado

Marcelo

Anúncios

ArduFarmBot, o livro!

Acaba de sair do forno o primeiro livro da série “Tutoriais MJRoBot”, o “ArduFarmBot: Automatizando uma horta de tomates com a ajuda da Internet das Coisas – IoT”.

O livro pode ser adquirido nas lojas do Kindle na Amazon:

book amazon

Por favor divulguem o livro e se gostaram, deixem um comentário na página da: Amazon.com.br

Caso encontrem erros ou tenham sugestões, por favor usem a area de mensagens aqui no blog, que procurarei corrigir nas próximas edições.

O livro usa o controlador eletrônico “ArduFarmBot” como base para o aprendizado de como se trabalhar tanto em HW quanto em SW, com: a) Displays do tipo LCD e OLED; b) LEDs e botões; c) Acionamento de bombas e lâmpadas via relés e d) Leitura de sensores tais como: DHT22 (temperatura e umidade relativa do ar), DS18B20 (temperatura do solo), YL69 (umidade do solo) e LDR (luminosidade).

Todas as principais etapas dos projetos são detalhadamente documentadas através de textos explicativos, diagramas de blocos, fotos coloridas de alta resolução, diagramas elétricos utilizando-se do aplicativo “Fritzing”, códigos completos armazenados no “GitHub” e vídeos do “YouTube”.

No livro, são desenvolvidas duas versões do controlador eletrônico “ArduFarmBot”, que a partir da captura de dados provenientes de uma horta de tomates, tais como temperatura do ar e solo, umidade relativa do ar, umidade do solo e luminosidade, decidem autonomamente a quantidade certa (e quando) uma plantação deve receber calor e água. O ArduFarmBot também permite a intervenção manual, tanto em forma local quanto remota via Internet, a fim de controlar o acionamento de uma bomba de água e de uma lâmpada elétrica, esta última para ser usada na geração de calor para as plantas.

O livro está dividido em 3 partes.

Na primeira parte, a partir do “Arduino Nano” de desenvolve uma versão tanto manual operada por botões, quanto automática do “ArduFarmBot”.

book1

Na segunda parte, se aprofunda no projeto da automação e introduz a operação remota através da criação de uma página na internet. O “ESP8266-01” é utilizado para a conexão “Wifi”, enviando dados para o serviço especializado em IoT, “ThingSpeak.com“.

book2

Na terceira parte, uma segunda versão do “ArduFarmBot” é desenvolvida, introduzindo o “NodeMCU ESP8266-12E”, um poderoso e versátil dispositivo para projetos em IoT, que substitui de forma integrada tanto o “Arduino Nano” quanto o “ESP8266-01”, utilizados nas partes anteriores do livro. Nesta última, se explora também uma nova plataforma de serviços do universo IoT, o “Blynk”.

book4

Espero que gostem! E se preparem para o Tutoriais MJRoBot 2: “Brincando com robôs”.

Não deixem de visitar e seguir minha página: MJRoBot.org no Facebook

Saludos desde el sur del mundo!

Nos vemos em meu próximo post!

Obrigado e um abração,

Marcelo

 

“ArduFarmBot 2” – Sistema automático para irrigação e calor, agora com o NodeMCU e Blynk

Algum tempo atrás, desenvolvemos aqui o projeto de um sistema de jardinagem totalmente automatizado: “ArduFarmBot: Controlando um tomateiro com a ajuda de um Arduino e Internet das coisas (IoT)“. As principais especificações originais serão mantidas nesta nova versão, o ArduFarmBot 2, porém agora o projeto será baseado nas plataformas de IoT: NodeMCU ESP8266BLYNK.

Com base em dados coletados de uma plantação qualquer tais como, temperatura e umidade, tanto do ar quanto do solo, o ArduFarmBot 2 decidirá a quantidade certa (e quando) o plantio deve receber calor e água. O sistema deverá também permitir a intervenção manual de um operador para controlar uma bomba de água e uma lâmpada elétrica para gerar calor para a plantação. Esta intervenção manual deverá ser possível de ser executada tanto no local como remotamente via Internet.

Em suma, o sistema deve receber como

A. ENTRADA

  • Sensores:
    • Temperatura do ar
    • Umidade Relativa ao Ar
    • Temperatura do solo
    • Umidade do solo
  • Botões:
    • Bomba ON / OFF
    • Lâmpada ON / OFF

B. SAÍDA:

  • Atuadores:
    • Relé para controle da bomba
    • Relé para controle de lâmpada
  • Mensagens automáticas devem ser enviadas na ocorrência de eventos, tais como:
    • Bomba LIGADA
    • Lâmpada LIGADA
    • Sistema off-line
  • Exibição de dados
    • Todos os dados analógicos e digitais devem estar disponíveis para avaliação imediata
  • Armazenamento de dados
    • Dados históricos devem ser armazenados remotamente

O diagrama de blocos abaixo mostra os principais componentes do projeto.

1: Bill of Material (BoM)

  • 4.7K Ohms resistor – ($0.03)
  • 10K Ohms resistor – ($0.03)
  • 220 Ohms resistor – ($0.03)

2: O NodeMCU

Picture of The NodeMCU

O NodeMCU ESP-12E é a versão integrada do popular ESP8266, um Serial to Wi-Fi System On a Chip (SoC), que apareceu pela primeira vez em 2013 e lançado no mercado já no ano seguinte. O ESP8266 foi desenvolvido pela empresa chinesa com sede em Shangai, Espressif Systems, uma fabricante de circuitos integrados focada no desenvolvimento de chips de RF, particularmente Wi-Fi.

Existem vários módulos no mercado que se utilizam do chip ESP8266, Eles são nomeados ESP-NN, onde NN é um número 01, 02, … .. 12, etc. e as vezes seguido de uma letra. Estes módulos tipicamente possuem: o ESP8266 SoC, memória flash, um cristal e na maioria dos casos, uma antena. No link você pode encontrar a lista completa de dispositivos baseados  no ESP8266 encontradas no mercado: Família ESP8266 .

Os 2 módulos mais importantes são sem dúvida, a ESP-01 e o ESP-12E. No ArduFarmBot 2, usaremos o: ESP-12E Development Board (NodeMCU DevKit 1.0)

Para aumentar ainda mais a capacidade de utilização do módulo ESP-12E, foram adicionados regulação de potência e conectividade USB. O ESP-12E inclui:

  • Adaptador USB para UART: Silicon Labs CP2102,
  • NCP1117 3,3VDC Voltage Regulator,
  • Conector micro-USB,
  • Pinos adicionais com GND, Vin, 3,3VDC para facilitar o acesso durante o desenvolvimento.

Em suma, o NodeMCU ESP-12E é um dispositivo pronto para ser usado, bastando que você instale os drivers USB ao seu computador e comece a escrever programas que se conectam à sua rede Wi-Fi !

Especificações Técnicas:

  • Support STA/AP/STA+AP 3 working modes;
  • Built-in TCP/IP protocol stack, support multiple-channel TCP Client connection (max 5);
  • 0~D8, SD1~SD3: used for GPIO, PWM (D1-D8), IIC, ect; the driven ability can be arrived at 15mA;
  • AD0: one-way 10 bits ADC;
  • Power input: 4.5V~9V(10VMAX), support USB powered and USB debug;
  • Working current: ≈70mA(200mA MAX, continue), standby<200uA;
  • Transmission data rate: 110-460800bps;
  • Support UART/GPIO data communication interface;
  • Support update firmware remotely (OTA);
  • Support Smart Link;
  • Working temperature:-40℃~+125℃;
  • Driven mode: double large-power H bridge driven
  • Weight: 7g.

3: Instalando o NodeMCU com o Arduino IDE

Se você já tiver o NodeMCU instalado com o IDE, ignore esta etapa

Se você deseja programar e usar o NodeMCU como se fosse um Arduino, a boa notícia é que é possível escrever-se firmwares personalizados e carregá-los no chip (“flash-it”). É importante lembrar que qualquer novo “firmware personalizado” irá substituir qualquer coisa previamente armazenada na memória flash do chip, incluindo o firmware original carregado em fábrica (aquele que aceita os comandos AT). Embora possamos usar o SDK do fabricante para o desenvolvimento de firmwares personalizados, é muito mais fácil usar o bom e velho Arduino IDE.

Comecemos:

No Arduino IDE,  abra a janela de preferências e digite a URL (marcado em vermelho na foto abaixo) no campo Additional Boards Manager URLs e selecione OK.

http://arduino.esp8266.com/stable/package_esp8266com_index.json

Picture of Installing the NodeMCU board at Arduino IDE

  • Selecione MENU  Tools → Board → Boards Manager…e vá rolando até encontrar a opção: esp8266 by ESP8266 Community , a qual deverá ser o último item da lista e clique INSTALL

arduino_ide_boards_esp8266

  • Instalando USB Drivers: O USB to Serial UART module incluído no dispositivo, é o  Silicon Labs’ CP2102, para o qual deveremos instalar o driver Virtual COM Port (VCP). No caso de meu MAC, o arquivo criado para comunicar com o CP2102 foi:  /dev/cu.SLAB_USBtoUART. Você pode encontrar o driver apropriado ao seu computador no seguinte link: CP210x USB to UART Bridge VCP Drivers
  • Depois de restartar o Arduino IDE , poderemos selecionar a placa no menu: Option Tools → Board → NodeMCU 1.0 (ESP-12E Module). Em seguida, especificar a correta frequência de operação da CPU: (Tools → CPU Frequency: “” → 80MHz) e velocidade de comunicação (Tools → Upload Speed: “” → 115,200). Finalmente, selecionar o port apropriado ao seu computador: (Tools → Port → /dev/cu.SLAB_USBtoUART).

nodemcu-ide-setup-3

Neste ponto estamos prontos para escrever nosso próprio firmware e enviá-lo ao dispositivo, mas vamos primeiramente tentar um dos exemplos incluídos com a biblioteca: File → Examples → ESP8266WiFi → WiFiScan. Após o upload, podemos abrir a janela do Serial Monitor e observar os resultados. Verifique que 115,200 baud é a velocidade selecionada no menu do canto inferior direito do Serial Monitor.

nodemcu-ide-setup-4

4: Instalando o Display OLED

Um grande companheiro para o nosso ESP-12E é o pequeno display do tipo OLED: SSD 1306. Ele será muito útil ao projeto, mostrando localmente os dados capturados, mensagens, etc. O modelo usado é um display de 128 x 64 pixels que se comunica via I2C, o SSD 1306, cujas principais características são:

  • 128 pixels na horizontal por 64 pixels na vertical. Assim se você usar por exemplo, caracteres de  8×8 pixels, obteremos um display de “16X8” (8 linhas de 16 caracteres cada).
  • Comunicação via I2C : se deve conectar ao NodeMCU I2C pins, usando:
    • SCL ==> D1 (equ. Arduino 5)
    • SDA ==> D2 (equ. Arduino 4)

Outra característica importante do SSD1306 é que você pode tanto alimentar-lo com 3.3V gerado diretamente pelo módulo nodeMCU, como via um Power Suppley externo de 5V, que será como faremos no projeto.

Uma vez conectado o display, você deve baixar e instalar sua biblioteca ao Arduino IDE. Nós usaremos a versão ACROBOT abaixo:

SSD1306 Arduino Library

Depois de ter reiniciado o IDE, a biblioteca deverá estar instalada. Carreguemos o sketch abaixo para testar o display OLED:


/***********************************************************************
* NodeMCU and OLED display "Hello World"
* Based on original code developed by: Makerbro at https://acrobotic.com/
* MJRoBot 12Oct16
************************************************************************/

#include 
#include 

void setup()
{
 Wire.begin(); 
 oled.init(); // Initialze SSD1306 OLED display
 oled.clearDisplay(); // Clear screen
 oled.setTextXY(0,0); // Set cursor position, start of line 0
 oled.putString(" MJRoBot.org");
 oled.setTextXY(4,0); // Set cursor position, start of line 4
 oled.putString(" HELLO, WORLD");
}

void loop()
{
}

Observe que quando você não definir um tamanho em pixels para os caracteres de texto, o padrão será 8X8. Para se definir um tamanho diferente, por exemplo,5X7, você poderá utilizar: oled.setFont(font5x7);

Abaixo o código para o “Hello World”:

5: Capturing Air Temperature and Humidity

Um dos sensores mais utilizados para a captura de dados meteorológicos é o DHT22 (ou seu irmão, o  DHT11), um sensor digital de humidade relativa do ar e temperatura. Ele usa internamente um sensor capacitivo de humidade e um termistor para medir o ar circundante, gerando um sinal digital em sua saída de dados. 

De acordo com a sua folha de dados (Datasheet), o sensor deve ser alimentado entre 3.3V e 5V (algumas especificações falam em até 6V max). Ele trabalha a partir de -40  a + 80 graus centígraods (algumas especs falam em + 125 ° C) com uma precisão de +/- 0,5 ° C de temperatura e +/-2% de umidade relativa. É importante ter em mente que o seu (“sencing period”) é em média de dois segundo (tempo mínimo entre leituras).

O site da Adafruit fornece uma série de informações sobre ambos, DHT22 e seu irmão DHT11. Para mais detalhes, visite a página:  Tutorial DHT22 / 11 .

O DHT22 tem 4 pinos (de frente para o sensor, o pino 1 é o mais esquerda):

    1. VCC (5V externo)
    2. Saída de dados
    3. Não conectado
    4. GND (Terra)

Uma vez que normalmente você usará o sensor em distâncias inferiores a 20m, um resistor de 10K deve ser conectado entre os pinos de dados e o VCC. O pino de saída deve ser conectado ao pino D3 do ESP-12E (veja o diagrama acima).

Uma vez que o sensor esteja instalado fisicamente no NodeMCU, baixe a biblioteca DHT a partir do repositório de programas:  Adafruit github e a instale junto as outras  bibliotecas de seu IDE (ambiente de desenvolvimento de programas do Arduino).

Uma vez que você recarregue o IDE, a biblioteca para o  sensor de DHT deverá aparecer como instalada. Execute o código abaixo para verificar se tudo está funcionando OK:

6: Capturando a humidade do solo

  • LM393 A0:    ao NodeMCU A0
  • LM393 VCC:  ao  VCC  5V externo (ou ao NodeMCU D8) Vide Nota abaixo *
  • LM393 GND: ao NodeMCU GND
  • LM393 D0:    Não conectado

(*) É importante destacar que o correto é conectar-se o VCC do Sensor a um Pino Digital do NodeMCU, definido como saída, de maneira a que o LM393 seja “alimentado” somente quando precisemos de uma leitura. Isto é importante não apenas para economizar energia, mas também para evitar a corrosão das sondas. Utilizando-se um sensor caseiro como foi o caso no projeto ArduFarmBot original, o sensor funcionaría sem problemas, mas tendo-se que alimentar o módulo comparador, o NodeMCU apresentou problemas com o  “soilMoisterVcc” conectado. Assim, conectei o LM393 direto a VCC (5V) externo como mostrado no diagrama elétrico acima  o código não precisa ser alterado).

Abaixo, rotina para ler o sensor conectado à porta analógica:

/***************************************************
 * Get Soil Moister Sensor data
 **************************************************/
void getSoilMoisterData(void)
{
  soilMoister = 0;
  digitalWrite (soilMoisterVcc, HIGH);
  delay (500);
  int N = 3;
  for(int i = 0; i < N; i++) // read sensor "N" times and get the average
  {
    soilMoister += analogRead(soilMoisterPin);   
    delay(150);
  }
  digitalWrite (soilMoisterVcc, LOW);
  soilMoister = soilMoister/N; 
  Serial.println(soilMoister);
  soilMoister = map(soilMoister, 600, 0, 0, 100); 
}

Alguns comentários sobre a rotina acima:

  • O dado do sensor é capturado 3 vezes, tirando-se uma média das mesmas.
  • Usamos MAP para configurar o intervalo em percentagem. Para definir os valores extremos, procedemos como abaixo:
    • Fazer um “curto-circuito” nas pontas de prova do higrômetro, isso equivalente a “100% de umidade”, o que gerará um valor de cerca de 0 na saída do ADC
    • Colocar o higrômetro”no ar”, se observa que o valor exibido no Serial Monitor, que em meu caso foi em torno de 600.
 Abaixo um codigo parcial para os testes até esta etapa do projeto:

7: Capturando a temperatura do solo

O DS18B20 é um sensor digital, o que o torna ideal para o uso em longas distâncias! Estes sensores digitais de temperatura  tipo “1-Wire” são bastante precisos (± 0,5 ° C em grande parte da gama) e podem fornecer até 12 bits de precisão à partir de seu conversor digital-analógico integrado. Eles funcionam muito bem com o NodeMCU usando um único pino digital, e você pode até mesmo conectar vários sensores no mesmo pino, pois cada um possui um ID único de 64 bits gravado de fábrica, para poder diferenciár-los.

  • O sensor funciona de 3,0 a 5,0V.
  • O sensor tem 3 fios:
    • Preto: GND
    • Vermelho: VCC
    • Amarelo: dados de 1 fio

Aqui, você pode encontrar os dados completos: DS18B20 Datasheet

Para usar o DS18B20 com o IDE do Arduino, importe as bibliotecas abaixo e a s instale em seu IDE:

Para testar o sensor, você pode usar o código “Simple.ino” incluído nos Exemplos da Biblioteca, como mostrado na foto acima. Carregue o código no seu NodeMCU e monitore a temperatura usando o Monitor Serial.

fp44q1eixkpxu98-large

A foto acima mostra o resultado esperado. Segure o sensor em sua mão, você deve ver a temperatura mudar para cerca de 32 / 34oC.

NOTA1: A biblioteca OneWire DEVE ser uma versão especial, modificada para ser usada com o ESP8266, caso contrário você receberá um erro durante a compilação. Você encontrará a última versão no link acima ou no arquivo zip abaixo:

8: Completando o HW

Para verificar se existe um “comando local”, ou seja se um botão foi pressionado, a função readLocalCmd() deve ser executada. Esta função lê cada botão, atualizando o status das variáveis correspondentes aos estados dos atuadores (pumpStatus e lampStatus). Observe que em vez de executar diretamente um comando digitalRead (pin), a função debounce(pin) é chamada. Isso é para evitar leituras falsas do botão. Se você quiser saber mais sobre o “debouncing”, visite o link:  Debouncing Tutorial.

/****************************************************************
* Read local commands (Pump and Lamp buttons are normally "HIGH"):
****************************************************************/
void readLocalCmd() 
{  
  boolean digiValue = debounce(PUMP_ON_BUTTON);
  if (!digiValue) 
  {
    pumpStatus = !pumpStatus;
    aplyCmd();
  }

  digiValue = debounce(LAMP_ON_BUTTON);
  if (!digiValue) 
  {
    lampStatus = !lampStatus;
    aplyCmd();
  }
}

No caso em que um botão é pressionado, outra função será chamada: aplyCmd (). E como o nome diz, esta aplicará o comando correspondente, ativando ou desativando os atuadores:

/***************************************************
* Receive Commands and act on actuators
****************************************************/
void aplyCmd()
{
  if (pumpStatus == 1) 
  {
    digitalWrite(PUMP_PIN, HIGH);
    displayData();
  }
  else
      {
        digitalWrite(PUMP_PIN, LOW);
        displayData();
      }
  
  if (lampStatus == 1) 
  {
    digitalWrite(LAMP_PIN, HIGH);
    displayData();
  }
  else
      {
        digitalWrite(LAMP_PIN, LOW);
        displayData();
      }
}

Considerações acerca do código:

Quando pensamos sobre o 4 grandes “grupo de tarefas” desenvolvidos até agora, podemos resumir-los em:

  • Ler Sensores
  • Ler Botões (comando local)
  • Atuar na bomba / lâmpada
  • Exibir dados

Perceberemos que o momento em que devemos realizar essas tarefas não são necessariamente os mesmos. Por exemplo, para ler os dados de temperatura e umidade do DHT 22, teremos que esperar pelo menos 2 segundos entre uma medida e outra, mas se esperamos alguns minutos, isto não fará diferença no projeto final. Para o sensor de umidade do solo, quanto menos medições fizermos, melhor (diminui a corrosão das sondas geradas por eletrólise). Mas quando pensamos nos atuadores, logo que pressionamos um botão, gostaríamos (e possivelmente precisaremos) de uma reação rápida.

Portanto, devemos usar aqui um “timer” para controlar corretamente o timing correto dessas tarefas. Poderíamos fazer isso usando o millis (), como fizemos no projeto ArdFarmBot original, mas aproveitaremos para conhecer outra ótima ferramenta, o SimpleTimer.h (siga as instruções no link ao lado para instalar a Biblioteca: SimpleTimer)

A biblioteca deve ser incluída no corpo principal do seu código, seguido de uma definição para o Timer do projeto:

  SimpleTimer timer;

Em seguida, defina os temporizadores:

  timer.setInterval(1000L, readLocalCmd);       // Read buttons at every 1 second
  timer.setInterval(2000L, getSoilTempData);    // Read Soil Temp at every 2 seconds
  timer.setInterval(2000L, getDhtData);         // Read DHT Sensor at every 2 seconds
  timer.setInterval(10000, getSoilMoisterData); // Read Soil Humidity at every 10 seconds
  timer.setInterval(10000, displayData);        // Display Data at OLED at every 10 seconds

9: ArduFarmBot 2,  “Contrôle Local”- Concluindo o código

Apresentando o Botão para Leitura dos sensores (“O amarelo”)

Como observamos na última etapa, precisaremos aguardar ciclos longos entre as medições do sensor de umidade do solo. Isto está bem para as nossas necessidades automáticas, mas para uma operação manual não vamos querer “esperar” 10, 15 ou mais segundos (ou mesmo minutos no caso real) para atualizar a leitura de um sensor. Também no mundo real, não faz sentido manter o display OLED “ACESO” ou “ON”, o tempo todo. Assim, o normal será “APAGADO” ou “OFF”.

Introduziremos esse 3 ª botão ao nosso projeto, o qual permitirá exibir os dados de leitura dos sensores a qualquer momento que quisermos, independentemente do tempo das leituras automáticas. Além disso, usaremos este mesmo botão para exibir dados no OLED quando os sensores forem atualizados. Abaixo da função readLocaCmd () alterada para interação com o novo botão:

/**************************************************************************
* Read local commands (Pump, Lamp and Sensor buttons are normally "HIGH"):
**************************************************************************/
void readLocalCmd() 
{  
  boolean digiValue = debounce(PUMP_ON_BUTTON);
  if (!digiValue) 
  {
    pumpStatus = !pumpStatus;
    aplyCmd();
  }

  digiValue = debounce(LAMP_ON_BUTTON);
  if (!digiValue) 
  {
    lampStatus = !lampStatus;
    aplyCmd();
  }

  digiValue = debounce(SENSORS_READ_BUTTON);
  if (!digiValue) 
  {
    turnOffOLED = !turnOffOLED;
    if (!turnOffOLED)
    {
      oled.setTextXY(0,0); oled.putString("UPDATING SENSORS");
      getDhtData();
      getSoilMoisterData();
      getSoilTempData();
      oledStart();
      displayData();
    }else oled.clearDisplay(); //turn off OLED
  }
}

Neste ponto, todo o HW está completado (usando-se LEDs como atuadores) e temos portanto todas as peças de SW à serem montadas.

O vídeo mostra o ArduFarmBot 2, operando em modo Local e Manual:

Você poderá fazer o download do código a ser utilizado na versão “Controle local”, diretamente em meu repositório:  GitHub: ArduFarmBot2_Local_Manual_Ctrl_V1

10: Automatizando nosso sistema de jardinagem

Neste ponto, todos os componentes do HW estão no lugar e como se viu na etapa anterior, o ArduFarmBot 2 pode ser controlado localmente por um operador através dos botões. O que falta agora é definir-se a “lógica” que permitirá ao nosso sistema realizar a tarefa de irrigar a plantação automaticamente! Para isto, precisamos incluir algum “cérebro” ao nosso projeto.

Para começar, definamos o intervalo inicial onde funcionarão os sensores. Esses valores devem ser alterados mais tarde usando-se valores práticos a serem obtidos em uma plantação real:

Umidade do solo:

  • “HÚMIDO”: Mais de 88% (não regar)
  • “IDEAL”: Entre 66% e 88% (Onde queremos trabalhar) e
  • “SECO”: abaixo de 66% (necessário ligar a bomba para aumentar a umidade)

Temperatura do ar:

  • “FRIO”: Abaixo de 12oC (Ligar a lâmpada para gerar calor)
  • “IDEAL”: entre 12oC e 22oC
  • “QUENTE”: Acima d 22oC (não ligar a lâmpada)

Você deve levar em conta que cada tipo de semente possui um intervalo ótimo de temperatura onde germinarão mais rapidamente. Por exemplo, para tomates o tempo mínimo para germinar as sementes será de 6 dias em temperaturas entre 20 e 25 oC, sendo que esta quantidade de dias aumentará para temperaturas inferiores ou superiores (mais de 43 dias para temperaturas inferiores a 10oC e 9 dias para temperaturas superiores a 35oC.

Você poderá verificar mais informações sobre este relacionamento (Temp / dias de germinação) no link abaixo:

The effect of soil temperature on seeds germination

Uma vez de posse desses dados: temperatura do ar, umidade do ar, umidade do solo e temperatura do solo, poderemos construir uma matriz complexa definindo como queremos que o nosso sistema de jardinagem automático funcione. Na Etapa 7 do ArduFarmBot: Part 2 – “Estação Remota” – IoT, se desenvolveu uma abordagem em profundidade sobre a relação Sensor-Matrix. Nesta etapa porém, utlizaremos apenas relações simples para facilidade de entendimento.

Definamos os parâmetros à serem usados em nosso código:

/* Automatic Control Parameters Definition */
#define DRY_SOIL      66
#define WET_SOIL      85
#define COLD_TEMP     12
#define HOT_TEMP      22
#define TIME_PUMP_ON  15
#define TIME_LAMP_ON  15

TIME_PUMP_ON e TIME_LAMP_ON são definidos como o tempo em segundos que a bomba e a lâmpada devem permanecer LIGADAS durante a operação automática.

Com base nos parâmetros acima, pensemos em algumas suposições muito simples a serem implementadas no código:

  • Se o solo estiver seco: (DRY) ==> Ligar a bomba (PUMP = ON)
  • Se a temperatura estiver fria (COLD) ==> Ligar a lâmpada (LAMP = ON)

Manteremos a coisa simples e não exploraremos todas as possíveis combinações bem como o  papel dos demais sensores como a umidade do ar ou temperatura do solo na equação, como fizemos no projeto original. Isto ficará como “lição de casa”! 😉

O código:

Criemos uma nova função, que com base na leitura dos sensores lidará automaticamente com os atuadores, ligando / desligando a bomba e a lâmpada: autoControlPlantation (). Esta função conforme mostrado abaixo, será chamada em todas os ciclos de leitura de sensores:

/**************************************************************
* Automatically Control the Plantation based on sensors reading
**************************************************************/
void autoControlPlantation(void)
{ 
  if (soilMoister < DRY_SOIL) 
  {
    turnPumpOn();
  }

  if (airTemp < COLD_TEMP) 
  {
    turnLampOn();
  }
}

A função tem duas tarefas básicas:

  • Controlar a bomba
  • Controlar a lâmpada

Abaixo as duas funções de controle chamadas a partir da função autoControlPlantation ():

***************************************************
* Turn Pump On for a certain amount of time
****************************************************/
void turnPumpOn()
{
  pumpStatus = 1;
  aplyCmd();
  delay (TIME_PUMP_ON*1000);
  pumpStatus = 0;
  aplyCmd();
}

/***************************************************
* Turn Lamp On for a certain amount of time 
****************************************************/
void turnLampOn()
{
  lampStatus = 1;
  aplyCmd();
  delay (TIME_LAMP_ON*1000);
  lampStatus = 0;
  aplyCmd();
}

Por fim, usemos o botão Sensor Read (“amarelo”) para não só interromper o programa durante um certo tempo durante a inicialização, mas também para exibir os parâmetros iniciais mais importantes, como mostrado na foto acima.

Neste ponto, o ArduFarmBot está totalmente funcional em termos de HW e SW.

O vídeo mostra o ArduFarmBot 2, operando em modo Local e Automático:

O código para a versão  “Local e Automático” do ArduFarmBot2 pode ser descarregada  de meu depositário:  GitHub: ArduFarmBot2_Local_Automatic_Ctrl_V2.

11: Criando a App BLYNK

É realmente muito fácil de se construir projetos IoT usando o BLYNK. A primeira coisa que você precisará, é ter a aplicação BLINK instalada no telefone e sua biblioteca instalada no IDE do Arduino. Se ainda não as tiver, siga os passos abaixo:

Uma vez que o Arduino IDE é recarregado, você deve estar OK para começar a usar BLINK em seu projeto IoT.

Agora, vamos abrir o aplicativo “Blynk”  no smartphone:

  1. Clique na tela Create New Project
  2. De um nome para seu projeto (Por exemplo: “ArduFarmBot 2”)
  3. Selecione o HW apropriado: NodeMCU
  4. Anote seu código do Authorization Token (você pode enviar-lo por e-mail e copiar-lo em seu código):
    char auth[] = "YourAuthToken";
  5. Pressione OK. Uma tela vazia cheia de pontos irá aparecer.
  6. Clique na tela para abrir o Widget Box

OK, vamos tomar um momento e pensar sobre o nosso ArduFarmBot 2 Blynk App e definir quais serão os Widgets a serem instalados. Revisitando a especificação geral descrita na introdução do projeto, podemos resumir que o nosso aplicativo precisará:

  • Ler todos os sensores e verificar o status dos atuadores
  • Tomar ações remotas, como “ligar / desligar” a bomba e a lâmpada
  • Enviar mensagens quando o sistema estiver “off-line” e / ou um atuador for ligado
  • Registrar a história de leitura dos sensores

De maneira a organizar as coisa, vamos dividir as tarefas descritas acima em 3 Tabs:

  • SENSORS
  • ACTUATORS / CONTROL
  • GRAPHICS

“Tabs” será o primeiro Widget a ser instalado. Uma vez selecionado, defina “Tab names” como acima.

Em seguida, entre em cada um dos Tabs criados e instale os Widgets como descritos abaixo:

SENSORS

  • Gauge: “Temp Air [oC]” Blue; input: V10 0 to 50; frequency: 5 sec
  • Gauge: “Humidity Air [%]” Green; input: V11 0 to 100; frequency: 5 sec
  • Gauge: “Soil Humidity [%]” Red; input: V12 0 to 100; frequency: 5 sec
  • Gauge: “Soil Temperature[oC]” Yellow; input: V13 -10 to 50; frequency: 5 sec
  • LED: “PUMP” Red; V0
  • LED: “LAMP” Green; V1

ACTUATORS / CONTROL

  • Button: “PUMP” Red; output: V3 0 to 1; mode: Switch; label: on: ACT, off: OK
  • Button: “LAMP” Green; output: V4 0 to 1; mode: Switch; label: on: ACT, off: OK
  • LED: “PUMP” Red; V0
  • LED: “LAMP” Green; V6
  • Notifications: Notify When HW goes offline: ON

GRAPHICS

  • Data to Show:
  • V10 “Temp Air”
  • V11 “Humidity Air”
  • V12 “Soil Humidity “
  • V13 “Soil Temp”

12: Alterando o código para introduzir as funcionalidades do Blynk

Para executar um aplicativo Blynk juntamente com seu código, você precisará:

  • Incluir a biblioteca BlynkSimpleEsp8266 no início do seu código
  • Durante o setup(), inicie com as credenciais do Blynk: Blynk.begin (auth, ssid, pass);
  • Defina uma temporização para enviar dados locais para o servidor Blynk: timer.setInterval (5000L, sendUptime);
  • Dentro do loop (), execute a função Blynk.run();
  • Crie a função sendUptime (); Onde você introduzirá os dados do sensor a serem enviados ao Blynk Server: Blynk.virtualWrite (VirtualPin, dados do sensor);

O código final deverá incluir agora um novo arquivo: “StationCredentials.h”:

char auth[] = "YOUR PROJECT TOKEN"; // Blynk project: "ArduFarmBot2"
char ssid[] = "YOUR LOCAL WIFI NAME";
char pass[] = "YOUR WIFI PASSWORD";

Other considerations:

Para usar um Widget do tipo: “Virtual LED” na app do Blynk, você necessitará definir-lo no início do código:

WidgetLED PUMPs(V0);  // Echo signal to Sensors Tab at Blynk App
WidgetLED PUMPa(V5); // Echo signal to Actuators Tab at Blynk App
WidgetLED LAMPs(V1);  // Echo signal to Sensors Tab at Blynk App
WidgetLED LAMPa(V6); // Echo signal to Actuators Tab at Blynk App

Para acender ou apagar o LED relacionado com a Bomba (PUMPs LED) que está conectado ao virtual PIN V0 por exemplo, chame as funções correspondentes abaixo:

  • PUMPs.on() ou
  • PUMPs.off()

Incluiremos os comandos na função applyCmd (), de maneira que os LEDs na app Blynk irão imitar os LEDs reais de nosso projeto. Também deveremos incluir o comando: Blynk.notify (“Mensagem a ser enviada”); na mesma função applyCmd (), uma para a Bomba e outra para a Lâmpada. Abaixo, a nova função:

/***************************************************
* Receive Commands and act on actuators
****************************************************/
void aplyCmd()
{
  if (pumpStatus == 1) 
  {
    Blynk.notify("ArduFarmBot2: Warning ==>> Pump ON"); 
    digitalWrite(PUMP_PIN, HIGH);
    if (!turnOffOLED) displayData();
    PUMPs.on();
    PUMPa.on();
  }
  else
      {
        digitalWrite(PUMP_PIN, LOW);
        if (!turnOffOLED) displayData();
        PUMPs.off();
        PUMPa.off();
      }
  
  if (lampStatus == 1) 
  {
    Blynk.notify("ArduFarmBot2: Warning ==>> Lamp ON");
    digitalWrite(LAMP_PIN, HIGH);
    if (!turnOffOLED) displayData();
    LAMPs.on();
    LAMPa.on();
  }
  else
      {
        digitalWrite(LAMP_PIN, LOW);
        if (!turnOffOLED) displayData();
        LAMPs.off();
        LAMPa.off();
      }
}

Para receber um comando a partir de um botão (Widget button) incluído na app Blynk, uma função BLYNK_WRITE () deve ser definida fora de uma função, loop () ou setup (). Para isso foi criado o código abaixo, um para cada Botão Blynk (PUMP e LAMP):

/****************************************************************
* Read remote commands 
****************************************************************/
BLYNK_WRITE(3) // Pump remote control
{
  int i=param.asInt();
  if (i==1) 
  {
    pumpStatus = !pumpStatus;
    aplyCmd();
  }
}

BLYNK_WRITE(4) // Lamp remote control
{
  int i=param.asInt();
  if (i==1) 
  {
    lampStatus = !lampStatus;
    aplyCmd();
  }
}

Abaixo, o vídeo mostra a operação automática do ArduFarmBot 2, agora incluíndo o Blynk:

O código para o ArduFarmBot2 em sua versão “Remote and Automatic control”, usando o Blynk pode ser descarregada de meu repositório:  GitHub: ArduFarmBot2_Ext_Auto_Ctrl__V3_0

13: Relés como atuadores

Como discutido na introdução, nosso objetivo final será cuidar de uma plantação. Com os dados fornecidos pelos sensores, vamos saber a temperatura do ar e do solo, umidade relativa do ar e o mais importante, quão “seco” está o solo. Com esses dados na mão, o nosso programa deve calcular se é necessário irrigar a plantação ligando uma bomba de água ou acender uma lâmpada elétrica para fornecer o calor adequado para a cultura.

Para isso, usaremos um pequeno módulo de relé de 5V tanto para a ativação da bomba quanto da lâmpada.

O circuito do diagrama do módulo de relé pode ser visto abaixo:

Pelo diagrama, devemos conectar :

  • Power Supply 5V ==> (4) “Vcc”
  • NodeMCU D6 ==> (3) “IN1” (Pump)
  • NodeMCU D7 ==> (2) “IN2” (Lamp)
  • NodeMCU GND ==> (1) “GND”

Dependendo do módulo de relés escolhido, os labels podem ser diferentes

Normalmente encontramos como saída, 3 pinos para cada relé: “NO” (“Normal Open“), “Ref” or “COM” (“Reference” or “Common“) and “NC” (“Normal Closed“). Usaremos o NO e o COM para cada relé.

No exemplo abaixo, o “COM” é o terminal para conectar ao pino positivo externo da fonte de alimentação de 5V(no caso da bomba (ou do 220VAC para a lâmpada). O “NO” será conectado à Bomba (ou Lâmpada).

No caso do relé escolhido e confirmado pelo diagrama acima, normalmente o IN1 e o IN2 devem estar em ALTO e sua ativação acontecerá com um nível BAIXO (menos de 2V). Com um nível BAIXO na saída do NodeMCU, a corrente fluirá de VCC para o pino D6 do NodeMCU, ativando a entrada do optoacoplador. O solenóide será acionado, “fechando” a saída NO (normalmente aberta) do relé, o que ligará a bomba.

Em relação a versão V3.0 do código desenvolvida na etapa anterior,  deveremos “inverter”a logica de acionamento dos atuadores (ou pinos digitais como saída). Os pinos D6 e D7 do NodeMCU deverão estar normalmente em HIGH. Assim a função de setup(), deverá ser alterada:

digitalWrite(PUMP_PIN, HIGH); // To be used with Relay module (inverted logic: normally HIGH)
digitalWrite(LAMP_PIN, HIGH); // To be used with Relay module (inverted logic: normally HIGH)

Também deveremos  alterar a função applyCmd():

/***************************************************
* Receive Commands and act on actuators
****************************************************/
void aplyCmd()
{
  if (pumpStatus == 1) 
  {
    Blynk.notify("ArduFarmBot2: Warning ==>> Pump ON"); 
    digitalWrite(PUMP_PIN, LOW); // To be used with Relay module (inverted logic: activate with LOW)
    if (!turnOffOLED) displayData();
    PUMPs.on();
    PUMPa.on();
  }
  else
      {
        digitalWrite(PUMP_PIN, HIGH); // To be used with Relay module (inverted logic: normally HIGH)
        if (!turnOffOLED) displayData();
        PUMPs.off();
        PUMPa.off();
      }
  
  if (lampStatus == 1) 
  {
    Blynk.notify("ArduFarmBot2: Warning ==>> Lamp ON");
    digitalWrite(LAMP_PIN, LOW); // To be used with Relay module (inverted logic: activate with LOW)
    if (!turnOffOLED) displayData();
    LAMPs.on();
    LAMPa.on();
  }
  else
      {
        digitalWrite(LAMP_PIN, HIGH); // To be used with Relay module (inverted logic: normally HIGH)
        if (!turnOffOLED) displayData();
        LAMPs.off();
        LAMPa.off();
      }
}

O código para o ArduFarmBot2 em sua versão “Remote and Automatic control”, usando o Blynk e relés (ativos com “LOW”)pode ser baixado desde meu repositório:  Github: ArduFarmBot2_Ext_Auto_Ctrl__V4_0

14: Teste real com o ArduFarmBot 2

Você pode instalá-lo submerso em água ou “inline”. Usaremos o segundo método.

Ligue um dos fios da bomba ao relé IN1 e o outro ao pino de alimentação externa de 5V (+). Pegue o pino de alimentação (-) e ligue-o ao relé COM1.

O filme abaixo mostra o ArduFarmBot 2 operando em modo manual (local e remoto):

E finalmente, o vídeo abaixo mostra sua operação em modo automático:

15: Conclusão

Como sempre, espero que este projecto possa ajudar outros a encontrarem o seu caminho no emocionante mundo da eletrônica e do IoT!

Para obter os arquivos atualizados, consulte meu repositório: ArduFarmBot2 GitHub

Não deixe de visitar e seguir minha página: MJRoBot.org no Facebook

Saludos desde el sur del mundo!

Nos vemos em meu próximo post!

Obrigado

Marcelo

Do “blink” ao BLYNK, uma viagem pela “Internet das coisas” nas asas do NodeMCU ESP-12E

Neste tutorial, aprenderemos a lidar com este fantástico dispositivo, o NodeMCU ESP-12E Development Kit V. 1.0, onde aprenderemos como:

  • Fazer piscar um LED pela internet
  • Ligar o ESP a um display LCD do tipo “OLED”
  • Capturar dados gerados por sensores tanto analógicos como digitais
  • Subir dados a um serviço de Internet das coisas tal como o Thinkspeak
  • Controlar “coisas” pela internet, utilisando-se aplicativos para smartphones como o BLINK

2: O NodeMCU

nodeMCU.jpg

O NodeMCU ESP-12E é a versão integrada do popular ESP8266, um Serial to Wi-Fi System On a Chip (SoC), que apareceu pela primeira vez em 2013 e lançado no mercado já no ano seguinte. O ESP8266 foi desenvolvido pela empresa chinesa com sede em Shangai, Espressif Systems, uma fabricante de circuitos integrados focada no desenvolvimento de chips de RF, particularmente Wi-Fi.

Existem vários módulos no mercado que se utilizam do chip ESP8266, Eles são nomeados ESP-NN, onde NN é um número 01, 02, … .. 12, etc. e as vezes seguido de uma letra. Estes módulos tipicamente possuem: o ESP8266 SoC, memória flash, um cristal e na maioria dos casos, uma antena. No link você pode encontrar a lista completa de dispositivos baseados  no ESP8266 encontradas no mercado: Família ESP8266 .

Os 2 módulos mais importantes são sem dúvida, a ESP-01 e o ESP-12E.

O ESP-01 têm sido amplamente utilizado em projetos da Internet das coisas onde tamanho e custo, mas não número de GPIOs (há apenas 2 do tipo digital disponíveis) são importantes. Exploramos este módulo em vários outros tutoriais aqui no Blog:

O ESP8266 – Parte 1Parte 2Parte 3

O ESP-12E Development Board (NodeMCU DevKit 1.0)

Para aumentar ainda mais a capacidade de utilização do módulo ESP-12E, foram adicionados regulação de potência e conectividade USB. O ESP-12E inclui:

  • Adaptador USB para UART: Silicon Labs CP2102,
  • NCP1117 3,3VDC Voltage Regulator,
  • Conector micro-USB,
  • Pinos adicionais com GND, Vin, 3,3VDC para facilitar o acesso durante o desenvolvimento.

Em suma, o NodeMCU ESP-12E é um dispositivo pronto para ser usado, bastando que você instale os drivers USB ao seu computador e comece a escrever programas que se conectam à sua rede Wi-Fi !

Especificações Técnicas:

  • Support STA/AP/STA+AP 3 working modes;
  • Built-in TCP/IP protocol stack, support multiple-channel TCP Client connection (max 5);
  • 0~D8, SD1~SD3: used for GPIO, PWM (D1-D8), IIC, ect; the driven ability can be arrived at 15mA;
  • AD0: one-way 10 bits ADC;
  • Power input: 4.5V~9V(10VMAX), support USB powered and USB debug;
  • Working current: ≈70mA(200mA MAX, continue), standby<200uA;
  • Transmission data rate: 110-460800bps;
  • Support UART/GPIO data communication interface;
  • Support update firmware remotely (OTA);
  • Support Smart Link;
  • Working temperature:-40℃~+125℃;
  • Driven mode: double large-power H bridge driven
  • Weight: 7g.

Picture of The NodeMCU

Um excelente site para se aprender mais sobre a família do ESP 8266 é: What Is The ESP8266 And Why Is It So Popular?

3: Instalando o NodeMCU ao IDE do Arduino

Se você deseja programar e usar o NodeMCU como se fosse um Arduino, a boa notícia é que é possível escrever-se firmwares personalizados e carregá-los no chip (“flash-it”). É importante lembrar que qualquer novo “firmware personalizado” irá substituir qualquer coisa previamente armazenada na memória flash do chip, incluindo o firmware original carregado em fábrica (aquele que aceita os comandos AT). Embora possamos usar o SDK do fabricante para o desenvolvimento de firmwares personalizados, é muito mais fácil usar o bom e velho Arduino IDE.

Comecemos:

No Arduino IDE,  abra a janela de preferências e digite a URL (marcado em vermelho na foto abaixo) no campo Additional Boards Manager URLs e selecione OK.

http://arduino.esp8266.com/stable/package_esp8266com_index.json

Picture of Installing the NodeMCU board at Arduino IDE

  • Selecione MENU  Tools → Board → Boards Manager…e vá rolando até encontrar a opção: esp8266 by ESP8266 Community , a qual deverá ser o último item da lista e clique INSTALL

arduino_ide_boards_esp8266

  • Instalando USB Drivers: O USB to Serial UART module incluído no dispositivo, é o  Silicon Labs’ CP2102, para o qual deveremos instalar o driver Virtual COM Port (VCP). No caso de meu MAC, o arquivo criado para comunicar com o CP2102 foi:  /dev/cu.SLAB_USBtoUART. Você pode encontrar o driver apropriado ao seu computador no seguinte link: CP210x USB to UART Bridge VCP Drivers
  • Depois de restartar o Arduino IDE , poderemos selecionar a placa no menu: Option Tools → Board → NodeMCU 1.0 (ESP-12E Module). Em seguida, especificar a correta frequência de operação da CPU: (Tools → CPU Frequency: “” → 80MHz) e velocidade de comunicação (Tools → Upload Speed: “” → 115,200). Finalmente, selecionar o port apropriado ao seu computador: (Tools → Port → /dev/cu.SLAB_USBtoUART).

nodemcu-ide-setup-3

Neste ponto estamos prontos para escrever nosso próprio firmware e enviá-lo ao dispositivo, mas vamos primeiramente tentar um dos exemplos incluídos com a biblioteca: File → Examples → ESP8266WiFi → WiFiScan. Após o upload, podemos abrir a janela do Serial Monitor e observar os resultados. Verifique que 115,200 baud é a velocidade selecionada no menu do canto inferior direito do Serial Monitor.

nodemcu-ide-setup-4

4: Piscando (“Blinking”) o LED

FullSizeRender 24.jpg

O “Olá Mundo” de qualquer novo projeto de HW é sem dúvida alguma, um LED piscando. Para conectar-se um LED em seu ESP-12E, você poderá usar qualquer um dos seus GPIO digitais.

Picture of Blinking a LED

O diagrama de pinos acima mostra o layout da 2ª geração do NodeMCU ESP8266 . Em nosso caso, usaremos o pino D7 ou seu equivalente para Arduino: GPIO13.

blink.png

Você poderá testar o código usando tanto “D7” quanto “13”. ambas formas funcionarão. O pino D7 não precisa de um resistor externo para alimentar o LED, pois possui um internamente. Abaixo um código simples para piscar o LED:

/**********************************************
  Blink
  Connected to pin D7 (GPIO13) ESP8266 NODEMCU
 **********************************************/

#define ledPin 13
// #define ledPin D7

void setup() 
{
  pinMode(ledPin, OUTPUT);
}

void loop() 
{
  digitalWrite(ledPin, HIGH);   
  delay(1000);              
  digitalWrite(ledPin, LOW);    
  delay(1000);             
}

Há uma relação entre alguns dos pinos do NodeMCU e do Arduino, automaticamante identificados pelo IDE, tal como descrito abaixo:

  • ESP ==> Arduino
  • D0 ==> 16
  • D1 ==> 5
  • D2 ==> 4
  • D3 ==> 0
  • D4 ==> 2
  • D5 ==> 14
  • D6 ==> 12
  • D7 ==> 13
  • D8 ==> 15
  • D9 ==> 3
  • D10 ==> 1

Abaixo o código pronto para ser executado no IDE do Arduino:

5: Instalando o display de 0.96″ (OLED)

FullSizeRender 25.jpg

Um grande companheiro para o nosso ESP-12E é o pequeno display do tipo OLED: SSD 1306. Ele pode ser muito útil em projetos tanto para mostrar seus dados ou mensagens, quanto para depurar seus programas em campo. O modelo que usei aqui é um display de 128 x 64 pixels que se comunica via I2C, o SSD 1306, cujas principais características são:

  • 128 pixels na horizontal por 64 pixels na vertical. Assim se você usar por exemplo, caracteres de  8×8 pixels, obteremos um display de “16X8” (8 linhas de 16 caracteres cada).
  • Comunicação via I2C : se deve conectar ao NodeMCU I2C pins, usando:
    • SCL ==> D1 (equ. Arduino 5)
    • SDA ==> D2 (equ. Arduino 4)

Outra característica importante do SSD1306 é que você deve alimentar-lo com 3.3V, pelo que é possível conectar-lo diretamente ao módulo nodeMCU, como mostra o diagrama eléctrico abaixo:

Picture of Using the 0.96

Uma vez conectado o display, baixar e instalar a sua biblioteca em nosso Arduino IDE. Nós usaremos a versão ACROBOT abaixo:

SSD1306 Arduino Library

Depois de ter reiniciado o IDE, a biblioteca deverá estar instalada. Carreguemos o sketch abaixo para testar o display OLED:

/***********************************************************************
*  NodeMCU and OLED display "Hello World"
*  Based on original code developed by: Makerbro at  https://acrobotic.com/

*  MJRoBot 12Oct16
************************************************************************/

#include 
#include 

void setup()
{
  Wire.begin();  
  oled.init();                      // Initialze SSD1306 OLED display
  oled.clearDisplay();              // Clear screen
  oled.setTextXY(0,0);              // Set cursor position, start of line 0
  oled.putString("  MJRoBot.org");
  oled.setTextXY(4,0);              // Set cursor position, start of line 4
  oled.putString("  HELLO, WORLD");
}

void loop()
{
}

Observe que quando você não definir um tamanho em pixels para os caracteres de texto, o padrão será 8X8. Para se definir um tamanho diferente, por exemplo,5X7, você poderá utilizar: oled.setFont(font5x7);

Abaixo o código para o “Hello World”:

6: O NodeMCU e o DHT22 como uma estação climática

57fe5c32937ddb5b790007f3.jpegPicture of NodeMCU as a local weather station using DHT22

Um dos sensores mais utilizados normalmente para se captar dados meteorológicos é o DHT22 (ou seu irmão, o  DHT11), um sensor digital de humidade relativa do ar e temperatura. Ele usa internamente um sensor capacitivo de humidade e um termistor para medir o ar circundante, gerando um sinal digital em sua saída de dados. 

De acordo com a sua folha de dados (Datasheet), o sensor deve ser alimentado entre 3.3V e 5V (algumas especificações falam em até 6V max). Ele trabalha a partir de -40  a + 80 graus centígraods (algumas especs falam em + 125 ° C) com uma precisão de +/- 0,5 ° C de temperatura e +/-2% de umidade relativa. É importante ter em mente que o seu (“sencing period”) é em média de dois segundo (tempo mínimo entre leituras).

O site da Adafruit fornece uma série de informações sobre ambos, DHT22 e seu irmão DHT11. Para mais detalhes, visite a página:  Tutorial DHT22 / 11 .

O DHT22 tem 4 pinos (de frente para o sensor, o pino 1 é o mais esquerda):

  1. VCC (3 a 5V)
  2. saída de dados
  3. Não conectado
  4. GND (Terra)

OLED_DHT22.png

Uma vez que normalmente você usará o sensor em distâncias inferiores a 20m, um resistor de 10K deve ser conectado entre os pinos de dados e o VCC. O pino de saída deve ser conectado ao pino D3 do ESP-12E (veja o diagrama acima).

Uma vez que o sensor esteja instalado fisicamente no NodeMCU, baixe a biblioteca DHT a partir do repositório de programas:  Adafruit github e a instale junto as outras  bibliotecas de seu IDE (ambiente de desenvolvimento de programas do Arduino).

Uma vez que você recarregue o IDE, a biblioteca para o  sensor de DHT deverá aparecer como instalada. Execute o código abaixo para verificar se tudo está funcionando OK:

7: Instalando sensores analógicos

57fe81bf50e1b6b8d60002fc.jpeg

O NodeMCU possui um Analog Digital Converter (ADC) de 10 bits integrado. Quando comparado com um Arduino UNO que tem 6 ADCs “portas” ou o Nano que tem 8, parece que o NodeMCU sai perdendo aqui. Mas isto não é necessariamente verdade. Primeiro, os Arduinos UNO ou Nano em realidade, possuem apenas um ADC integrado internamente o qual deve ser multiplexado para se poder ler suas múltiplas entradas analógicas. Então, podemos fazer exatamente o mesmo com o NodeMCU.

Por exemplo, suponha que você necessite ler 2 sensores analógicos:

  • LDR: para se medir a intencidade da luz
  • Higrômetro (Soil Moisture) para se medir a umidade do solo

O que devemos fazer é “alimentar” individualmente cada um desses sensores cada vez que precisemos ler um deles. Para isso você deve definir para cada sensor, uma das GPIOs digitais como saída, colocando-as em nível ALTO em cada leitura. Para saber mais sobre múltiplas entradas analógicas, consulte o site:

Multiple analog inputs using one analoge pin

Higrômetro:

Picture of Using Analog sensors No Projeto ArduFarmBot, exploramos como trabalhar com um higrômetro para medir a umidade do solo. Lá, desenvolvemos um sensor do tipo DIY (“Do it yourself” – “Faça você mesmo”), mas aqui vamos usar um eletrônico, muito comum no mercado: o par sensor YL-69 e o comparador LM393.

O módulo LM393 possui 2 saídas, uma digital (D0), que pode ser configurada usando-se o potenciômetro que existe integrado ao módulo e um analógico (A0). Este módulo pode ser alimantado com 3.3V, o que é muito conveniente quando se trabalha com um NodeMCU. O que vamos fazer, é instalar os 4 pinos do LM393  como descrito abaixo:

  • LM393 A0:    to NodeMCU A0 input
  • LM393 VCC: to NodeMCU VCC or to NodeMCU GPIO D3*
  • LM393 GND: to NodeMCU GND
  • LM393 D0:    Não conectado

NodeMCU WS V2.png

Note que no diagrama acima, um sensor de humidade equivalente de 3 pinos  foi usada apenas para referência (não encontrou o módulo apropriado para desenha-lo com o Fritzing). Também é importante notar que o o “VCC do Sensor” deve ser conectado a um pino digital como saída, de modo que o LM393 seja alimentado apenas quando precisemos fazer uma leitura. Isto é importante não só para poupar energia, mas também para proteger as sondas de corrosão.

* Eu deixei aqui as 2 opções para alimentar sensor, porque pelo menos no caso de meu sensor e módulo, percebi que o NodeMCU não carregava o sketch com o D3 conectado. Também tive eventuais erros devido ao consumo de energia. Se você alimentar o LM393 diretamente ao 3.3V, o código não precisa ser alterado.

Uma rotina simples pode ser escrita para se ler a porta analógica:

/***************************************************
 * Get Soil Moister Sensor data
 **************************************************/
void getSoilMoisterData(void)
{
  soilMoister = 0;
  digitalWrite (soilMoisterVcc, HIGH);
  delay (500);
  int N = 3;
  for(int i = 0; i < N; i++) // read sensor "N" times and get the average
  {
    soilMoister += analogRead(soilMoisterPin);   
    delay(150);
  }
  digitalWrite (soilMoisterVcc, LOW);
  soilMoister = soilMoister/N; 
  Serial.println(soilMoister);
  soilMoister = map(soilMoister, 380, 0, 0, 100); 
}

Alguns comentários sobre a rotina acima:

  • Os dados do sensor é capturado 3 vezes, tirando-se uma média das mesmas.
  • Usamos MAP para configurar o intervalo em percentagem. Para definir os valores extremos, procedemos como abaixo:
    • Fazer um “curto-circuito” nas pontas de prova do higrômetro, isso equivalente a “100% de umidade”, o que gerará um valor de cerca de 0 na saída do ADC
    • Colocar o higrômetro”no ar”, se observa que o valor exibido no Serial Monitor é em torno de 380.

Abaixo o código completo para esta fase do projeto:

8: Subindo os dados para a nuvem: ThinkSpeak.com

Até agora, utilizamos o NodeMCU ESP12-E como se fosse uma placa normal de Arduino. É claro que apenas “tocamos” o verdadeiro potencial deste espectacular chip e agora é a hora de decolarmos rumo as estrelas! Quer dizer, para a nuvem! 😉

Picture of Uploading the sensor data to ThinkSpeak.comComecemos!

  • Primeiro você deve abrir uma conta no ThinkSpeak.com
  • Siga as instruções para criar um canal e tome nota do seu Channel ID e Write API Key
  • Atualize o código abaixo com as credenciais de sua rede Wi-Fi e Thinkspeak
  • Execute o programa no IDE

Comentemos as partes mais importantes do código:

Primeiro:

  • Incorporamos a biblioteca do ESP8266,
  • Definimos o cliente WiFi
  • Entramos com as credenciais do roteador WiFi e do Thingspeak :
/* ESP12-E & Thinkspeak*/
#include 
WiFiClient client;
const char* MY_SSID = "YOUR SSD ID HERE";
const char* MY_PWD = "YOUR PASSWORD HERE";
const char* TS_SERVER = "api.thingspeak.com";
String TS_API_KEY ="YOUR CHANNEL WRITE API KEY";

Segundo, incluamos uma nova biblioteca, muito importante em projetos de IoT: SimpleTimer.h:

/* TIMER */
#include 
SimpleTimer timer;

Em terceiro lugar, durante o setup(), iniciar a comunicação serial, connectar o WiFi atarvés da função connectWiFi() e definir os temporizadores. Note-se que a linha de código: timer.setInterval (19000L, sendDataTS);  chamará a função functionsendDataTS () a cada 19 segundos, a fim de transferir dados para o canal do ThinkSpeak.

void setup() 
{
  ...
  Serial.begin(115200);
  delay(10);
  ...
  connectWifi();
  timer.setInterval(19000L, sendDataTS);
  ...
}

Por último mas não menos importante, durante o loop (), a única ação necessária é iniciar o temporizador e pronto!

void loop() 
{
  ...
  timer.run(); // Initiates SimpleTimer
}

Abaixo em detalhes, as duas funções utilizadas para se comunicar com o ThinkSpeak.com:

ESP12-E conectando-se com a rede WiFi:

/***************************************************
 * Connecting WiFi
 **************************************************/
void connectWifi()
{
  Serial.print("Connecting to "+ *MY_SSID);
  WiFi.begin(MY_SSID, MY_PWD);
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi Connected");
  Serial.println("");  
}

ESP12-E enviando dados ao ThinkSpeak:

/***************************************************
 * Sending Data to Thinkspeak Channel
 **************************************************/
void sendDataTS(void)
{
   if (client.connect(TS_SERVER, 80)) 
   { 
     String postStr = TS_API_KEY;
     postStr += "&field1=";
     postStr += String(temp);
     postStr += "&field2=";
     postStr += String(hum);
     postStr += "&field3=";
     postStr += String(soilMoister);
     postStr += "\r\n\r\n";
   
     client.print("POST /update HTTP/1.1\n");
     client.print("Host: api.thingspeak.com\n");
     client.print("Connection: close\n");
     client.print("X-THINGSPEAKAPIKEY: " + TS_API_KEY + "\n");
     client.print("Content-Type: application/x-www-form-urlencoded\n");
     client.print("Content-Length: ");
     client.print(postStr.length());
     client.print("\n\n");
     client.print(postStr);
     delay(1000); 
   }
   sent++;
   client.stop();
}

9: Introduzindo o BLYNK

 Mas o que é BLYNK? Pelo Blynk website podemos entender que :

Blynk é uma plataforma baseada em Apps para iOS e Android, utilizada para controlar-se Arduino, Raspberry Pi e outros dispositivos através da Internet. É um painel digital (“Dashboard”) onde você pode construir uma interface gráfica para o seu projeto, simplesmente arrastando e soltando “widgets”.

É realmente muito fácil desenvolver projectos de IoT utilizando-se o BLYNK.

Para começar, aprendamos a controlar nosso velho LED conectado a porta D7, utilisando-se de um smartphone. Para isso, sigamos os passos abaixo:

  • Baixar o BLYNK app para o iPhone da Apple ou o Google Android
  • Instale a Biblioteca do BLYNK para Arduino. Note que você vai baixar um arquivo zip (Há 5 arquivos lá que você deverá instalar manualmente em sua Biblioteca do Arduino).
  • Uma vez que o Arduino IDE é recarregado, abra o sketch: Exemples ==> Blynk ==> Boards_WiFi ==> ESP8266_Standalone
#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space
#include 
#include 

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "YourAuthToken";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "YourNetworkName";
char pass[] = "YourPassword";

void setup()
{
  Serial.begin(9600);
  Blynk.begin(auth, ssid, pass);
}

void loop()
{
  Blynk.run();
}

O código acima é basicamente tudo o que você precisa instalar em seu ESP12-E para executar seus projetos de IoT com o BLYNK. Não se esqueça de alterar a velocidade de comunicação para 115.200 bauds e entrar com as credenciais de seu roteador local e de seu projeto no BLYNK.

Agora, vamos abrir o aplicativo “Blynk”  no smartphone:

blynk_led_ctrl

  1. Clique na tela Create New Project
  2. De um nome para seu projeto (Por exemplo: “LED Control”)
  3. Selecione o HW apropriado: NodeMCU
  4. Anote seu código do Authorization Token (você pode enviar-lo por e-mail e copiar-lo no código anterior:
    char auth[] = "YourAuthToken";
  5. Pressione OK. Uma tela vazia cheia de pontos irá aparecer.
  6. Clique na tela para abrir o Widget Box
  7. Adicione o Button widget.
  8. Clique no ícone do botão para abrir o Widget Settings. A principal coisa a definir é o PIN number (Como nosso LED está conectado ao pino D7 – escolha pin D7). É bom dar um nome para o widget: “LED”. Pressione OK
  9. Caso ainda não o tenha feito, volte para o seu código e atualize-o com o código de autorização que você obteve no aplicativo: char auth[] = “YourAuthToken”;

Uma vez que o código seja carregado em seu ESP12-E e o programa seja executado, o Serial Monitor deve apresentar algo semelhante ao meu abaixo:

blynk-serial-monitor

Agora basta executar o projecto Blynk (use o botão “play” no canto superior direito do aplicativo em seu smartphone) e isto é tudo! Você estará controlando seu HW através da Internet !!!!! 😉

Blynk_LED.png

10: Running our Weather Station on Blynk

Podemos também enviar os dados que estamos coletando de sensores para o Blynk, da mesma maneira que fizemos com o ThingSpeak.

Criemos um novo projeto Blink em nosso aplicativo (ou atualizar o que já foi criado):

Blynk 2.png

  1. Clique na tela e crie  3 novos Widgets. Em nosso caso: “Gauge”
  2. Para cada um desses widgets, defina: name, input type, range e frequency para atualização dos dados

Para os nossos sensores, definamos os seguintes “Virtual Ports”:

  • V10: Temperature, range 0-50oC, 5s of pooling frequency
  • V11: Humidity, range 0-100%, 5 s
  • V12: Soil Moisture, range 0-100%, 5 s

Em nosso código para o ESP12-E teremos de introduzir os valores acima. Comecemos a partir do código anterior e adicionemos os novos sensores e timer. A linha abaixo de código incluída no setup (), da mesma maneira que vimos com a versão Thinkspeak, forçará o programa para executar a função sendUptime () a cada 5 segundos.

  timer.setInterval(5000L, sendUptime);

Abaixo a função completa:

/***************************************************
 * Send DHT data to Blynk
 **************************************************/
void sendUptime()
{
  // You can send any value at any time.
  // Please don't send more that 10 values per second.
  Blynk.virtualWrite(10, temp); //virtual pin V10
  Blynk.virtualWrite(11, hum); // virtual pin V11
  Blynk.virtualWrite(12, soilMoister); // virtual pin V12
}

E, Voilá! O seu aplicativo Blynk estará recebendo informações atualizadas a respeito de seus sensores e você também poderá controlar o LED pela internet.

FullSizeRender 27.jpg

Abaixo o código completo para nosso Blynk Weather Station Control app:

11: Utilizando-se o  Blynk e o ThinkSpeak simultaneamente

Picture of Running Blynk and ThinkSpeak simustanealy

É claro que podemos ter nossos dados em ambas plataformas:

  • Blynk app (que é ótimo para o controle e mobilidade) e
  • ThinkSpeak que é muito bom para armazenamento de histórico e análise de dados.

NOTA: O Blynk possui um Widget: Webhook, onde voce pode comandar o envio automático dos dados ao ThinkSpeak sem necessidade de código adicional. O problema é que este widget só está disponível para Android. Assim fica aqui o código para fazer-lo por SW.

O arquivo abaixo mostra o código completo:

Conclusão

Como sempre, espero que este projeto ajude outras pessoas a encontrar seu caminho no apaixonante mundo da eletrônica e do IoT!

Não deixe de visitar e seguir minha página: MJRoBot.org no Facebook

Saludos desde el sur del mundo! 😉

Um abraço e até o próximo post!

Obrigado

Marcelo

ArduFarmBot: Part 2 – “Estação Remota” – IoT

Este post é uma continuação do ArduFarmBot: Controlando um tomateiro com a ajuda de um Arduino e Internet das coisas (IoT)

Na primeira parte do projeto, criamos uma estação local de controle e captura de informações, tais como temperatura, umidade relativa do ar, luminosidade e umidade do solo. Com base nesses dados, o ArduFarmBot decidia automaticamente a quantidade certa (e quando) o tomateiro deveria receber calor e água. A estação local de controle desenvolvida na Parte 1, também permitia a intervenção manual de um operador a fim de controlar tanto a bomba de água quanto a lâmpada elétrica. Nesta  segunda parte, implementaremos uma abordagem “IoT” onde a”intervenção manual” também poderá ser feita remotamente via Internet. O diagrama de blocos mostra como faremos isso:

ardufarmbot_gal_block_diagram

Note-se que os dados capturados serão enviados a um “serviço de armazenamento na nuvem” (no nosso caso Thinkspeak.com). Além disso, um website dedicado, o “Remote Control Page” mostrado no diagrama,  irá monitorar e exibir esses dados em tempo quase real. Esta página também permitirá a ativação remota da bomba e  da lâmpada.

2.1: Lista de materiais

2.2: Completando o Hardware

Para conectar-se o ArduFarmBot à Internet, utilizaremos o ESP8266, um módulo simples, barato e fácil de programar para os projectos envolvendo a Internet das coisas (IoT). A partir da estação local desenvolvida na Parte 1, o único HW adicional necessário é o próprio ESP8266. O diagrama de blocos abaixo, mostra todas as conexões com os pinos do Arduino e dos componentes principais.

ardufarmbot_pin_diagram

O único cuidado que você deve ter é relacionado com o nível de tensão do pino RX do ESP8266, pois ele funciona com 3.3V. Assim, o Pin Rx não deve ser conectado diretamente ao pino Tx do Nano (D3). Um nívelador de tensão deve ser usado. No nosso caso, vamos construir um divisor de tensão para ser usado como um “conversor de nível de tensão”.

Voltage level Converter.png

O esquema eléctrico abaixo, mostra com mais detalhes como se conectar o ESP8266.

ardufarmbot_complete_eletr_diagram

Se você quiser saber mais sobre o ESP8266, consulte meus posts anteriores aqui no Blog:

  1. O ESP8266 parte 1 – Serial WIFI Module
  2. O ESP8266 parte 2 – Web Server
  3. O ESP8266 parte 3 – Acionando LEDs remotamente

Note que estamos usando o ESP8266 conectado aos pinos 2 (Tx) e 3 (Rx) do Nano, utilizando-se da biblioteca “SoftSerial”. Se você quiser “livrar” os pinos digitais, poderá alternadamente usar os pinos 0 e 1 do Nano (Serial por HW). Apenas lembre-se que você deve desligá-los ao enviar o código para Nano.

NOTA: Se você deseja se conectar o “Buzzer”, você deve fazê-lo no pino D17 (o mesmo que o pino A3). É bom ter um alarme sonoro quando ocorra um erro de comunicação. Eu o usei durante a fase de teste, deixando de fora no HW do projecto final (mas o código está preparado para isso). Cabe a você decidir se o insta-la ou não.

O código abaixo pode ser usado para testar e / ou configurar o  ESP8266:

2.3: Conectando o  ESP8266  a internet

Uma vez que o módulo ESP8266 está instalado, o próximo passo é aplicar um “Reset” no pino CH-PD.

/***************************************************
* Reset funtion to accept communication
****************************************************/
void reset8266(void)
{
  pinMode(CH_PD, OUTPUT);
  digitalWrite(CH_PD, LOW);

  delay(300);
  digitalWrite(CH_PD, HIGH);
  Serial.print("8266 reset OK");
  lcd.clear();
  lcd.println("8266 reset OK       ");
}

Após o reset, vamos conectá-lo à rede local  (alterar o no código: username e password, por suas credenciais ) e iniciar o módulo como “Modo Station” (CWMODE = 1):

/***************************************************
* Connect WiFi
****************************************************/
void connectWiFi(void)
{
  sendData("AT+RST\r\n", 2000, DEBUG); // reset
  sendData("AT+CWJAP=\"USERNAME\",\"PASSWORD\"\r\n", 2000, DEBUG); //Connect network
  delay(3000);
  sendData("AT+CWMODE=1\r\n", 1000, DEBUG);
  sendData("AT+CIFSR\r\n", 1000, DEBUG); // Show IP Adress
  lcd.clear();
  lcd.print("8266 Connected");
  Serial.println("8266 Connected");
}

Para enviar dados ao ESP8266, utilizamos a função sendData():

/***************************************************
* Send AT commands to module
****************************************************/

String sendData(String command, const int timeout, boolean debug)
{
  String response = "";
  esp8266.print(command);
  long int time = millis();
  while ( (time + timeout) > millis())
  {
    while (esp8266.available())
    {
      // The esp has data so display its output to the serial window
      char c = esp8266.read(); // read the next character.
      response += c;
    }
  }
  if (debug)
  {
    Serial.print(response);
  }
  return response;
}

As funções acima serão chamadas durante a “fase de setup” de nosso Código. Se tudo foi feito corretamente, você deve ver pelo monitor serial, mensagens semelhantes como as de abaixo:

Picture of The ESP8266 connection

2.4: Data Storage Cloud: O ThinkSpeak.com

Todos os dados capturados pelo ArduFarmBot serão enviados para a nuvem, utilizando-se um serviço gratuito proporcionado pelo “ThinkSpeak.com“.

No “Loop ()”, depois de capturar os dados com readSensors (),  chamaremos uma função específica para carregar os dados capturados: updateDataThingSpeak ();

/***************************************************
* Transmit data to thingspeak.com
****************************************************/
void updateDataThingSpeak(void)
{
  startThingSpeakCmd ();
  
  cmd = msg ;
  cmd += "&field1=";     //field 1 for DHT temperature
  cmd += tempDHT;
  cmd += "&field2=";    //field 2 for DHT humidity
  cmd += humDHT;
  cmd += "&field3=";    //field 3 for LDR luminosity
  cmd += lumen;
  cmd += "&field4=";    //field 4 for Soil Moisture data 
  cmd += soilMoist;
  cmd += "&field5=";    //field 5 for PUMP Status
  cmd += pumpStatus;
  cmd += "&field6=";    //field 6 for LAMP Status
  cmd += lampStatus;
  cmd += "\r\n";

  sendThingSpeakCmd();
}

A fim de enviar esses dados, a primeira coisa a fazer é iniciar a comunicação com o ThingSpeak.com. Faremos isso, usando-se da função:startThingSpeakCmd ();

/***************************************************
* Start communication with ThingSpeak.com
****************************************************/
void startThingSpeakCmd(void)
{
  cmd = "AT+CIPSTART=\"TCP\",\"";
  cmd += IP;
  cmd += "\",80";
  esp8266.println(cmd);
  delay(2000);
  if(esp8266.find("Error"))
  {
    Serial.println("ESP8266 START ERROR");
    return;
  }
  Serial.println("Thinkspeak Comm Started");
  cmd ="";
}

Uma vez que o canal esteja aberto com o ThingSpeak e o string “cmd”  esteja montado com os dados, é hora de fazer o upload de tudo isso no canal correspondente do ThingSpeak usando-se da função:sendThingSpeakCmd();

/***************************************************    
* Update channel ThingSpeak.com
****************************************************/
String sendThingSpeakCmd(void)
{
  esp8266.print("AT+CIPSEND=");
  esp8266.println(cmd.length());
  if(esp8266.find(">")){
    esp8266.print(cmd);
    Serial.println("");
    Serial.println("");
    Serial.println(cmd);
    delay(500);
   
    String messageBody = "";
    while (esp8266.available()) 
    {
      String line = esp8266.readStringUntil('\n');
      if (line.length() == 1) 
      { //actual content starts after empty line (that has length 1)
        messageBody = esp8266.readStringUntil('\n');
        Serial.print("Message received: ");
        Serial.println(messageBody);
      }
    }
    return messageBody;
  }
  else{
    esp8266.println("AT+CIPCLOSE");
    Serial.println("ESP8266 CIPSEND ERROR: RESENDING"); //Resend...
    error=1;
    return "error";
  }
}

As funções acima foram baseadas em um tutorial muito bom desenvolvido por Michalis Vasilakis. Para mais detalhes, consulte:

Arduino IOT: Temperature and Humidity ( with ESP8266 WiFi).

A foto abaixo mostra o canal ArduFarmBot no site do ThingSpeak.com:

Picture of Cloud Storage Data: The ThinkSpeak.com

2.5: Comandando os atuadores a partir da web

Neste momento, estamos subindo (“Upload”) e armazenando todos os dados coletados na nuvem. Isto é muito útil para a monitoração remota, mas o que aconteceria se com base nesses dados gostaríamos de acionar a bomba ou a Lâmpada, independente do programa automático local? Para fazer isso, além do “Upload”, também faremos um “Download” de dados a partir da nuvem, informando ao controlador como agir basedo nesses dados (comandos).

Criemos para isso, campos específicos em nosso canal ThinkSpeak para comandar os atuadores:

  • Field 7:
    • Data = 1 ==> PUMP should be Turn ON
    • Data = 0 ==> PUMP should be Turn OFF
  • Field 8:
    • Data = 1 ==> LAMP should be Turn ON
    • Data = 0 ==> LAMP should be Turn OFF

OK, mas como configurar esses campos diretamente no ThingSpeak? Podemos fazê-lo, por exemplo, escrevendo um “plugin” diretamente para ThinksPeak, ou podemos usar um site externo para fazê-lo (esta será a nossa escolha). De qualquer forma, em ambos os casos, você deverá usar um comando como o de abaixo:

api.thingspeak.com/update?key=YOUR_WRITE_KEY&field7=1

Com o comando acima, por exemplo (e usando a sua chave de escrita de canal), você vai escrever “1” no Field 7, o que significa que a bomba deve ser ligada. Você pode facilmente testá-lo, escrevendo a linha de comando acima no seu navegador, o campo correspondente no seu canal será alterado. Como um retorno, o navegador irá mostrar uma página em branco com um único número no canto superior esquerdo, correspondente à entrada de dados sequencial no seu canal.

Até agora, 50% do trabalho está feito! Agora você deverá ler este “comando” (conteúdo  do campo), na estação local do ArduFarmBot .

O comando para fazer isso é mostrado abaixo. Ele vai obter o último dado que foi escrito no campo específico (que em nosso caso será um “comando”).

api.thingspeak.com/channels/CHANNEL_ID/fields/7/last

Da mesma forma como fizemos antes, você poderá testar a linha de comando, usando seu navegador. Neste caso, o navegador irá mostrar-lhe o dado armazenado esse campo específico. Veja abaixo:

Picture of Commanding the actuators from the web

Voltando à “terra”, escreveremos uma função que lerá este “último campo”:

/***************************************************
* Read data from field7 of thingspeak.com
****************************************************/
int readLastDataField7()
{
  startThingSpeakCmd ();

  // "GET /channels/CHANNEL_ID/fields/7/last";
  cmd = msgReadLastDataField7; 
  cmd += "\r\n";

  String messageDown = sendThingSpeakCmd();
  Serial.print("Command received: ");
  Serial.println(messageDown[7]);
  
  int command = messageDown[7]-48; 
  return command;
}

A função acima retornará o dado contido no Field 7 (“1” ou “0”). Uma função semelhante deve ser escrita para o Field 8.

Uma vez que já possuímos o conteúdo de ambos os campos, devemos utilizá-los em uma função que comandará os atuadores de maneira semelhante ao que fizemos com a “função de comando manual”:

/***************************************************
* Receive Commands from thingSpeak.com
****************************************************/
void receiveCommands()
{
  field7Data = readLastDataField7();
  if (field7Data == 1) 
  {
    digitalWrite(PUMP_PIN, HIGH);
    pumpStatus = 1;
    showDataLCD();
  }
  if (field7Data == 0) 
  {
    digitalWrite(PUMP_PIN, LOW);
    pumpStatus = 0;
    showDataLCD();
  }

  delay (500); 
  
  field8Data = readLastDataField8();
  if (field8Data == 1) 
  {
    digitalWrite(LAMP_PIN, HIGH);
    lampStatus = 1;
    showDataLCD();
  }
  if (field8Data == 0) 
  {
    digitalWrite(LAMP_PIN, LOW);
    lampStatus = 0;
    showDataLCD();
  }
  delay (500); 
}

Assim, a partir de agora você pode usar a linha de comando no seu navegador para ligar / desligar a bomba e a lâmpada remotamente. Abaixo, se pode ver como o comando recebido aparecerá no monitor serial:

Download command.png

Outra consideração importante é a “coordenação” entre o comando local e o remoto. Teremos de alterar a função readLocalCmd () para que também atualizemos os Fields7  e 8 do Thinkspeak respectivamente,  como o estado da bomba e da lâmpada:

field7Data = pumpStatus;

field8Data = lampStatus;

Agora “filed7Data” e “field8Data” estão em sincronia com os comandos da página web e também com as ações de comando locais quando você pressiona um botão. Então, vamos atualizar a função aplyCmd (), que é a responsável para ligar / desligar os atuadores:

/***************************************************
* Receive Commands and act on actuators
****************************************************/
void aplyCmd()
{
  if (field7Data == 1) digitalWrite(PUMP_PIN, HIGH);
  if (field7Data == 0) digitalWrite(PUMP_PIN, LOW);
  
  if (field8Data == 1) digitalWrite(LAMP_PIN, HIGH);
  if (field8Data == 0) digitalWrite(LAMP_PIN, LOW);
}

Quando você começar seus testes,  perceberá que qualquer comando executado manualmente no local ou via web, será superado pelas ações automáticas definidas pela função autoControlPlantation(). Neste ponto, você deve considerar quem será o “chefe” (ou patroa…), o qual terá a última palavra! Em nosso caso definiremos o seguinte:

  • Em cada ciclo de loop, que é quase “sempre”, verificamos se um botão local é pressionado
  • Aproximadamente a cada minuto, faremos um “pooling” no ThinkSpeak e verificamos se existe um nova ordem manual desde lá.
  • Aproximadamente  a cada 10 minutos, leremos os sensores, atualizando os dados no ThinkSpeak e mais importante,  executamos as medidas automáticas, que serão tomadas independente das que foram selecionados manualmente e será aquela que irá ser mantido.

Você pode alterar a lógica da maneira que melhor se adapte ao seu projeto. Essa é a coisa boa sobre o uso de um processador programável, como o Arduino para controlar coisas!

Assim, 2 temporizadores serão utilizados agora, um para agrupar os comandos remotos e outro para ler os sensores (o mesmo que foi utilizado anteriormente):

long sampleTimingSeconds = 75; // ==> ******** Define Sample time in seconds to read sensores *********
int reverseElapsedTimeSeconds = 0;
long startTiming = 0;
long elapsedTime = 0;
long poolingRemoteCmdSeconds = 20; // ==> ******** Define Pooling time in seconds for new ThingSpeak commands *********
long startRemoteCmdTiming = 0;  
long elapsedRemoteCmdTime = 0;

A função loop () deverá ser reescrita da seguinte forma:

void loop() 
{
  elapsedRemoteCmdTime = millis()-startRemoteCmdTiming;   // Start timer for pooling remote commands
  elapsedTime = millis()-startTiming;   // Start timer for measurements
  reverseElapsedTimeSeconds = round (sampleTimingSeconds - elapsedTime/1000);

  readLocalCmd(); //Read local button status
  showDataLCD();

  if (elapsedRemoteCmdTime > (poolingRemoteCmdSeconds*1000)) 
  {
    receiveCommands();
    updateDataThingSpeak();
    startRemoteCmdTiming = millis();
  }
  
  if (elapsedTime > (sampleTimingSeconds*1000)) 
  {
    readSensors();
    autoControlPlantation();
    updateDataThingSpeak();
    startTiming = millis();
  }
}

2.6: Implementação de uma página Web dedicada

Neste ponto o nosso ArduFarmBot está operacional e pode ser controlado a partir da web. Você pode monitorar os dados no site do Thinkspeak e também enviar comandos utilizando-se de um navegador, mas é claro que esta “solução web” não pode ser considerado “elegante”! A melhor maneira de implementar uma solução real para IoT, é desenvolver uma página web completa, a qual além de exibir todos os dados, também possuirá botões para ativação dos atuadores.

Para hospedar nossa página web, escolhí o Byethost, um site gratuito, muito fácil e simples para lidar com suas páginas. Também aproveitei a oportunidade de aplicar neste projecto, o que eu aprendi em uma fantástica especialização on-line no Coursera / Universidade de Michigan:Learn to Design and Create Websites (Construindo um portfólio web ágil e acessível usando HTML5, CSS3 e JavaScript ).

webpage

Não entrarei em detalhes como desenvolver esse tipo de página, uma vez que este não é o propósito central deste tutorial, mas incluirei aqui o HTML, CSS e códigos fonte do JavaScript que desenvolvi exclusivamente para minha página. Uma vez que alguém tenha interesse em como cheguei ao projeto final, podemos discuti-lo utilizando-se do Painel de Comentários no final do post.

É importante reforçar que essa página não trabalha diretamente com a Estação de Controle ArduFarmBot Local. O que ela está fazendo realmente é, interagir com o canal do ThinkSpeak  como descrito abaixo:

  1. Ler dados de sensores dos Fields 1, 2, 3, 4
  2. Ler estado do atuadores  (“Echo”) dos Fields  5 e 6
  3. Armazenar dados (comandos) nos Fields 7 e 8
  4. Ler dados meteorológicos locais (Yahoo)

O item 4 acima não é realmente crucial para o projeto, mas é importante ter dados adicionais disponíveis no caso de você querer tomar algumas ações remotas independente do que está acontecendo localmente com plantação do seu tomate. Outra consideração é que você pode, por exemplo, armazenar esses dados em outro canal ThingSpeak e transferir-los para o Arduino, mostrando dados meteorológicos no display LCD local por exemplo (eu desenvolvi isto em outro projeto que funcionou bem! Deixo aqui como uma sugestão para você).

2.7: A Matriz Sensor-Atuador

Picture of Return to the brain. A Sensor-Actuator Matrix approach

Na primeira parte deste projeto, definimos algumas considerações preliminares sobre como os atuadores devem agir em função da leitura dos sensores. Naquele caso, fizemos unicamente opções simples, mas o que vai acontecer se tivermos uma situação mais complexa? Várias condições diferentes? O que iremos desenvolver aqui é uma nova abordagem que chamaremos de “Matriz Sensor – Atuador”.

Em uma planilha foram definidas para cada sensor, as diferentes condições possíveis  e como deveria ser a respectiva saída dos atuadores. O resultado pode ser observado na planilha Excel abaixo.

Matrix.png

Na planilha Excel, existem duas Tabs. Uma com filtro como mostrado acima e outra que além da seleção, te permite obter o “codigo”binário que deverá ser carregado na varíavel da Matriz.

New Matrix Setup.png

Uma vez definida, a matriz deverá ser carregada em nosso código. Um array de 18 linhas e 10 colunas foi criado para este propósito:

//                       +---SOIL----+-LIGHT-+---TEMP---+---ACTUAT----+
 //                        SL  SM  SH  LL  LH  TL  TM  TH   Pump   Lamp
boolean SDf [18] [10] = {{  1,  0,  0,  0,  1,  0,  0,  1,    1,    0 }, 
                          { 1,  0,  0,  0,  1,  0,  1,  0,    1,    0 }, 
                          { 1,  0,  0,  0,  1,  1,  0,  0,    1,    1 }, 
                          { 1,  0,  0,  1,  0,  0,  0,  1,    1,    0 }, 
                          { 1,  0,  0,  1,  0,  0,  1,  0,    1,    0 }, 
                          { 1,  0,  0,  1,  0,  1,  0,  0,    0,    1 }, 
                          { 0,  1,  0,  0,  1,  0,  0,  1,    0,    0 }, 
                          { 0,  1,  0,  0,  1,  0,  1,  0,    0,    0 }, 
                          { 0,  1,  0,  0,  1,  1,  0,  0,    0,    1 }, 
                          { 0,  1,  0,  1,  0,  0,  0,  1,    0,    0 }, 
                          { 0,  1,  0,  1,  0,  0,  1,  0,    0,    1 }, 
                          { 0,  1,  0,  1,  0,  1,  0,  0,    0,    1 }, 
                          { 0,  0,  1,  0,  1,  0,  0,  1,    0,    0 }, 
                          { 0,  0,  1,  0,  1,  0,  1,  0,    0,    0 },
                          { 0,  0,  1,  0,  1,  1,  0,  0,    0,    1 },
                          { 0,  0,  1,  1,  0,  0,  0,  1,    0,    0 },
                          { 0,  0,  1,  1,  0,  0,  1,  0,    0,    1 },
                          { 0,  0,  1,  1,  0,  1,  0,  0,    0,    1 },
                         };

Para trabalhar com a Matrix, criou-se a função defSensorStatus (). Esta função testa para cada linha se a condição das 8 primeiras colunas são TRUE. Se sim, as condições definidas nas 2 últimas colunas são executadas.

por exemplo:

if (1 and 0 and 0 and 0 and 1 and 0 and 0 and 1) { pumpStatus = 1; lampStatus = 0}

else if (1 and 0 and 0 and 0 and 1 and 0 and 1 and 0) { pumpStatus = 1; lampStatus = 0}

e assim por diante …

Dentro da função acima outra array é criada com o estado de cada leitura do sensor:

boolean snsSts[8]={0, 0, 0, 0, 0, 0, 0, 0}; // SL, SM, SH, LL, LH, TL, TM, TH

Esta array variável será também utilizado para o registo do LOG.

Segue abaixo a planilha excel:

ARDUFARMBOT SENSOR ACTUATOR MATRIX NEW.xlsx ARDUFARMBOT SENSOR ACTUATOR MATRIX NEW.xlsx

2.8: Otimizando o código

Durante o processo de desenvolvimento do ArduFarmBot percebemos que algumas mudanças na especificação original deveria ser feita:

Display LCD:

O display LCD deve estar apagado por default e a qualquer momento que uma leitura de sensores é necessária, podemos acender-lo. Esta condição foi implementada no código e o botão de leitura de sensores deve ser utilizado no modo “toggle” para ligar / desligar o LCD a qualquer momento. Acender ou apagar o LCD irá automaticamente atualizar as leituras de sensores para a exibição, mas estas leituras não serão utilizadas pelo ArduFarmBot em suas funções regulares.

Configuração inicial:

Quando o ArduFarmBot é ligado (ou depois de um Reset), o LCD irá exibirá configuração  do controlador “Initial Set-up”. Para se iniciar a execução do programa, o botão “Sensores” deve ser pressionado novamante (o LCD se apagará). A informação inicial disponível na tela inicial do LCD será:

  • COLD Temperature (i.e. 12oC)
  • DRY Soil Humidity (i.e. 30%)
  • WET Soil Humidity (i.e. 60%)
  • DARK light (i.e. 40%)
  • P_ON Pump time be ON (i.e. 10s)
  • SCAN Time to read sensors (i.e. 600s)
  • SW_Vertion (i.e. 4.1)
img_0013
Registro do Log:

Para fins de auditoria, criamos um registro com as leituras e atuações do nosso Ardu FarmBot. Em cada ciclo de leitura, a função: storeDataLogEEPROM () é executada:

/***************************************************
* Storage of Log data at Arduino EEPROM
****************************************************/
void storeDataLogEEPROM(void)
{
  for (int i = 0; i<8; i++) 
  {
    logData = logData + (snsSts[i])<< 1;
  }
  EEPROM.write (memoAddr, logData);
  memoAddr++;
  logData = 0;
  logData = logData + pumpStatus;
  logData = logData << 1;
  logData = logData + lampStatus;
  EEPROM.write (memoAddr, logData);
  EEPROM.write (0, memoAddr+1);
  logData = 0; 
  if ((memoAddr+1) == 1023) memoAddr=1;
  else memoAddr++;
} 

Como comentado na última etapa, o que será armazenada na EEPROM do Arduino é o conteúdo, bit a bit do array snsSts[] adicionado do status da bomba e lâmpada. Você pode ver abaixo, o log no monitor serial:

serial-monitor-log

Como já visto na parte 1, para facilidade de entendimento e desenvolvimento, o código para o ArduFarmBot foi divididos em vários arquivos, criados por sua especialidade. Note que 2 novos arquivos foram adicionados nesta segunda parte:

  • communication.ino (ThingSpeak and ESP8266 specific funtions)
  • stationCredentials.h (ThinkSpeak Channel ID and specific Keys for writing on the channel)

Por último, uma vez que o código acabou ficando  com um tamanho razoável, decidi armazenar as constantes na memória flash (programa), em vez de SRAM. Para isso, usei a palavra-chave PROGMEM que é um modificador de variável. Por exemplo, em vez de utilizar:

#define DHTPIN 5, usaremos:

const PROGMEM byte DHTPIN = 5;

O PROGMEN informa ao compilador  para “colocar esta informação na memória flash”, em vez de em SRAM, onde iria normalmente. Você também deve incluir a biblioteca avr/pgmspace.h no arquivo principal do seu código.

Outro bom procedimento para reduzir o uso de SRAM é comentar (ou excluir) todas as linhas de Serial.print () que você usou para a depuração durante o desenvolvimento. Você perceberá que o código usado por exemplo para mostrar o log no monitor serial estará todo “comentado” no código final.

Abaixo você pode encontrará o código completo para o ArduFarmBot. Não se esqueça de alterar os dados no file credentials.h com seu Thinkspeak Channel Id e chave de escrita. Também no communication.ino, entre com seu nome de usuário e senha para conectar o ESP 8266 na Internet.

Abaixo testes do ArduFarmBot e instalação definitiva:fvc1gl0itchfzep-large

Preparando o reservatório de água:

reservatorio

Conectando a bomba dágua: bomba

Germinação (aproximadamente 45 dias):

germinacao 

Seleção melhores mudas e transplante :

transplante

 

2.9: Conclusão

Picture of Conclusion

Isso é tudo, pessoal! ……Por agora!!

Em breve publicaremos a terceira e última parte do nosso projeto que espero seja uma boa receita de pasta ao sugo, mas com molho de tomate orgânico. 😉 !

IMG_0014.JPG

A propósito, na foto abaixo vocês podem ver os primeiros suspiros de vida na plantação do Mauricio e seus tomates alguns meses depois

img_0515

Os arquivos e documentos podem ser encontrados aqui : ArduFarmBot GitHub

Como sempre, espero que este projeto ajude outras pessoas a encontrar seu caminho no apaixonante mundo da eletrônica, do IoT e dos robôs!

Não deixe de visitar e seguir minha página: MJRoBot.org no Facebookcapa-ardufarmbot

Este projeto também está disponível em formato Kindle:

Saludos desde el sur del mundo! 😉

Um abraço e até o próximo post!

Obrigado

Marcelo e Maurício

O ESP8266 parte 1 – Serial WIFI Module

Caminho das pedras para fazer o set-up e testar o modulo ESP8266 com um Arduino MEGA.

O ESP8266 é talvez o mais versátil modulo serial para se conectar “coisas” a internet, daí ele ser tão popular no mundo do IoT. Ele é um modulo completo, que inclui um microprocessador que pode ser programado diretamente via o IDE do Arduino (em C++), ou em outros ambientes para compilação (usualmente usando uma linguagem de alto nível própria, o “Lua”). Para se controlar “coisas”, não há necessidade de se ter o Arduino propriamente dito para a interface, pois o ESP8266 possui 2 GPIOs (dois “pinos” de entrada/saída).

Link para o Forum específico do ESP8266

Features:

  • 802.11 b/g/n
  • Wi-Fi Direct (P2P), soft-AP
  • Integrated TCP/IP protocol stack
  • Integrated TR switch, balun, LNA, power amplifier and matching network
  • Integrated PLLs, regulators, DCXO and power management units
  • +19.5dBm output power in 802.11b mode
  • Power down leakage current of <10uA
  • 1MB Flash Memory
  • Integrated low power 32-bit CPU could be used as application processor
  • SDIO 1.1 / 2.0, SPI, UART
  • STBC, 1×1 MIMO, 2×1 MIMO
  • A-MPDU & A-MSDU aggregation & 0.4ms guard interval
  • Wake up and transmit packets in < 2ms
  • Standby power consumption of < 1.0mW (DTIM3)

Meio cheio de palavrões acima, mas é bom ter a mão “just in case”.

Até hoje, eu somente estudei o ESP8266 junto com o Arduino, substituindo a necessidade de um relativamente caro shield para wiFi (Shield, são umas plaquinhas que se instalam ao Arduino para expandir suas capacidades).  Ainda não brinquei com a menina no modo “stand alone”, isso ficará para um post mais adiante. A propósito, o ESP8266 é realmente uma menina bonita e prendada, mas como todas elas, dão um trabalho ……… 😉

Testando o ESP8266 com comandos AT:

Bom, a primeira coisa que se tem que fazer é testar o módulo com comandos AT, que é o standard de comunicação. Em geral o modulo vem de fabrica falando em uma velocidade de 115.200 bauds. isso acaba complicando, pois no caso do Arduino UNO (vou usar só UNO daqui para frente), só a Serial por HW “0” , (pinos 0 e 1) consegue trabalhar nessa velocidade. O problema é que o Monitor serial do PC (vou também deixar PC como um termo genérico aqui, mas que meu Mac não me ouça…..), também usa esse mesmo port serial. A solução no caso do UNO é usar a biblioteca “SoftwareSerial” para designar outros 2 pinos genéricos (GPIOs) para serem usados como uma porta serial (por SW). Isso funciona OK desde que a velocidade de transmissão seja inferior a 19.200 bauds. Perfeito! Mas como fazer no caso do ESP8266 vir programado em uma velocidade maior? O jeito é reprogramar-lo, claro! BUT, nem todos os Firmwares que vem carregados no módulo aceitam reprogramação. Então, o negócio é atualizar o FW (Ufa!!!) . Em outro post eu vou explicar como. Aqui, para não esquentar a cabeça com esse negócio de velocidade, firmware, etc, vou sar o Arduino MEGA, que na falta de 1, tem 4 ports seriais por HW!!!!!!!! Viva a abundância! ops! Afinal sou brasileiro, né 😉

Os ports do MEGA:

  • TX0/RX0 ==> Pin 1,0 (mesmo que o UNO) ==> “Serial 0”
  • TX1/RX1 ==> Pin 18,19 ==> “Serial1”
  • TX2/RX2 ==> Pin 16,17 ==> “Serial2”
  • TX3/RX3 ==> Pin 14,15 ==> “Serial3”

Para meus testes, vou usar a Serial 2 (pinos 16 e 17)

Mega TxRx

Bueno, chegou a hora de olhar a menina mais de pertinho …

  • ALIMENTAÇAO: 3.3V. Isto é muito importante, pois o módulo não funciona com 5V e pode queimar se voce teimar (rimou!). Os pinos de entrada também não suportam 5V e ao receber um sinal do Arduino, é importante usar um “conversor de nível de tensão” (nome bonito para o bom e velho divisor de tensão por resistores). Outro ponto importante, é bom ter uma fonte de 3.3V independente. Nem sempre o Arduino consegue suprir a corrente necessária para a operação do módulo.

O módulo tem 6 pinos:

esp8266-pinout-800x379

  • TX: que vai ser conectado ao RX2 do MEGA (pode ser conectado direto, pois o MEGA não tem problema em entender 3.3V como HIGH).
  • RX: conectado ao TX2 do MEGA via um conversor de nível
  •  VCC: 3.3V
  • GND: Ground. Nunca é demais lembrar que é necessário conectar o GND do ESP8266 ao GND do MEGA.
  • CH_PD (*): conectado ao pin 4 do MEGA para reset de SW para iniciar comunicação
  • RST: RESET em geral, conecta em VCC
  • GPIO0: aberto
  • GPIO2: aberto

(*) Em vários sites na internet, esse pino é conectado direto a VCC. No meu caso, sem o “reset” por SW (coloca o pino momentaneamente em LOW), o ESP8266 não funcionou.

Existem no mercado adaptadores para inserir o modulo no protoboard, pois a distancia fisica entre os pinos do ESP8266 não são compatíveis). Eu usei um cabinho com fios “Macho/Fêmea” tipo FTDI (veja abaixo) para a conexão. As cores mostradas são compatíveis com o diagrama de conexão.

esp8266 cable color

 

 

 

 

O circuito então fica:

esp8266 test

Nada de especial no diagrama de HW. A plaquinha vermelha é uma fonte independente de 3.3V que se acopla ao protoboard. veja que o fio amarelo TX2 no arduino, passa pelo divisor de tensão (resistores de 1K e de 2.2K), para que quando o TX2 esteja em HIGH (5V), o ESP8266 receba aprox. 3.3V (HIGH para ele).

O Software:

A idéia dessa sketch é executar testes no module, fazendo cm que se possa entrar com comandos AT via o monitor serial e ver a resposta:

Na parte inicial de comentários, estão os comandos mais básicos. Ao carregar o programa, vai aparecer um monte de lixo, depois o nome no modulo e por fim a palavra “ready”. nesse momento se pode enviar os comandos AT.

Comece pelo AT simples, o modulo deve retornar OK, teste outros comandos e por aí vai.

Em seguida a sketch, há uma figura com o que aparece no Monitor serial, para diversos comandos.

/****************************************************************
* ESP8266
* Arduino Mega Using Serial2
* AT commands examples for test:
* AT =====> ESP8266 returns OK
* AT+RST =====> ESP8266 restart and returns OK
* AT+GMR =====> ESP8266 returns AT Version; SDK version; id; OK
* AT+CWMODE? => ESP8266 returns mode type
* AT+CWLAP ===> ESP8266 returs close access points
* AT+CIFSR ===> ESP8266 returs designided IP
* AT+CIPMUX=1 ==>Set ESP8266 for multoples conections 
* AT+CIOBAUD=9600 ==>Change Baudrate ==> ESP8266 returs OK
* AT+CIPSERVER=1,80 ==> set modo SERVER port: 4040
* AT+CWMODE=3 ==> Conect ESP8266 ascombined mode (Access Point (2) and Server (1))
* AT+CWSAP="Acc_Point_name","password",wifi_Channel,cript# ==> ej. AT+CWSAP="ESP_8266_AP,"1234",3,0
* AT+CWJAP="SSID","password" ==> Connect to WiFi network
* AT+CWJAP="ROVAI TIMECAP","mjr747@1"
*
* Marcelo Jose Rovai 18Jan16
******************************************************************/
#define esp8266 Serial2
#define CH_PD 4 
#define speed8266 9600 // This is the speed that worked with my ESP8266
void setup() 
{
 esp8266.begin (speed8266); 
 Serial.begin(9600);
 reset8266(); // Pin CH_PD need a reset before start communication
}
void loop() 
{
 while(esp8266.available())
 {
 Serial.write(esp8266.read());
 }
 while(Serial.available())
 {
 esp8266.write(Serial.read());
 }
}
/*************************************************/
// Reset funtion to accept communication
void reset8266 ()
{
 pinMode(CH_PD, OUTPUT);
 digitalWrite(CH_PD, LOW);
 delay(300);
 digitalWrite(CH_PD, HIGH);
}

O Monitor Serial:

Serial Monitor test

Deixo abaixo um link com meu Dropbox, onde estão os documentos referente aos testes: sketch do Arduino, o Fritzing e dois documentos em PDF bem legais. Um com a lista completa de comandos e outro com um guia para fazer o set-up do módulo em varias configurações (web server, Access point, etc.). Já antecipo que a única maneira de aprender é colocar a mão na massa e ver o que acontece. Faça as ligações, entre com o programa e mande bala!!!!!

Link para a documentação do ESP8266

Conclusão

Bom, é isso aí.É isso aí. Nos próximos posts mostrarei como configurar o ESP8266 como um servidor web. Agora é por a mão na massa e boa sorte!

Como sempre, espero que este projeto ajude outras pessoas a encontrar seu caminho no apaixonante mundo da eletrônica e do IoT!

Não deixe de visitar e seguir minha página: MJRoBot.org no Facebook

“Saludos desde el sur del mundo!” 😉

Um abraço e até o próximo post!

Obrigado

Marcelo