Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

IoT Made Easy w / UNO, ESP-01, ThingSpeak e MIT App Inventor

Componentes e suprimentos

Arduino UNO
× 1
Espressif ESP8266 ESP-01
× 1
Sensor de temperatura DHT22
× 1
DS18B20 Sensor de temperatura digital de 1 fio para uso no solo
× 1
LDR - Resistor dependente de luz
× 1
Módulo de relé de 2 canais DC 5V
× 1

Aplicativos e serviços online

Arduino IDE
API ThingSpeak
MIT App Inventor

Sobre este projeto


Nosso objetivo será basicamente coletar informações de uma unidade local e enviá-las para a internet. Um usuário em qualquer lugar do planeta olhando para essas informações tomará decisões enviando comandos remotos para os atuadores, que também estarão nesta unidade local. Qualquer sensor ou atuador pode ser usado.

A grande maioria do meu trabalho na arena IoT estava usando NodeMCU e, mais recentemente, o ESP32. Mas acho importante não esquecer meus primeiros passos, alguns anos atrás, quando comecei a aprender IoT usando um Arduino UNO e o velho e bom ESP8266-01.

Então, decido aqui voltar àquela época (com um pouco mais de experiência agora) e explorar novamente esses ótimos aparelhos, conectando-os à nuvem, usando o serviço web ThingSpeak.com. Também exploraremos para controlar as coisas remotamente, usando um App Android desenvolvido usando o MIT AppInventor.

O "Centro de nosso projeto IoT" será o ThingSpeak.com. A unidade local (UNO / ESP-01) irá capturar dados de sensores e status do atuador, enviar para a Internet, "escrevendo" em um ThingSpeak.com específico Canal de status . A unidade local também receberá dados da Internet, "lendo-os" de Canais de atuador ThingSpeak específicos .

Um aplicativo Android também estará lendo esses dados do Canal de status ThingSpeak.com e exibi-los para o usuário. Da mesma forma, o usuário, com base nessa informação de status, pode enviar comandos para atuadores, escrevendo -los nos canais do atuador ThingSpeak (consulte o diagrama de blocos acima para entender melhor o fluxo de dados).

Então, o que vamos fazer? O diagrama de blocos mostrado na próxima etapa nos dará uma visão geral do projeto final:





Etapa 1:Introdução


Usando sensores comuns, nosso projeto irá capturar diversos dados, enviando-os para a nuvem, onde todos poderão ver pela internet. Para trabalhar esses dados, usaremos o serviço fornecido por ThingSpeak.com, uma plataforma IoT aberta que nos permitirá coletar, analisar e agir sobre esses dados.

Os dados a serem coletados por sensores vai ser:
  • Temperatura do ar e umidade relativa
  • Temperatura e umidade do solo
  • Luminosidade

O projeto terá 2 atuadores :
  • Bomba elétrica
  • Lâmpada elétrica

O estado desses atuadores ("ON / OFF"), também deve ser enviado para a nuvem.

Então, a ideia será capturar esses dados dos sensores, por exemplo, uma plantação e mandar para a nuvem. Com base nesses dados, um usuário deve tomar a decisão com base nessas declarações:
  • LIGUE a bomba se a umidade do solo for muito baixa
  • LIGUE a lâmpada se a temperatura do solo estiver muito baixa

Para comandar remotamente nossos atuadores, usaremos um aplicativo Android.





Etapa 2:BoM - Lista de materiais


Alguns dos componentes mais importantes listados aqui, possuem um link e um preço indicativo em USD associados. Esses links são apenas para informação.
  • Arduino UNO (microcontrolador) - $ 10,00
  • ESP8266-01 (Módulo de comunicação) - $ 3,50
  • DHT22 (sensor de umidade relativa e ar) - $ 9,00
  • DS18B20 (sensor de temperatura digital de 1 fio para uso no solo) - US $ 6,00
  • YL-69 + LM393 (sensor de umidade do solo) - $ 2,00
  • LDR (Sensor de luminosidade) - $ 0,20
  • 2 x LEDs (vermelho e verde)
  • Módulo de relé de 1 x 2 canais DC 5V com gatilho de baixo nível de optoacoplador - $ 7,00
  • Bomba 5 V DC - $ 3,00
  • Lâmpada 220V
  • 2 x 330 ohm resistor (para ser usado com LEDs)
  • 2 x resistor de 10K ohm (para ser usado com DHT22 e LDR)
  • 1 resistor de 4 k7 ohm (para ser usado com DS18B20
  • Protoboard
  • Jumpers
  • Alimentação externa 5 V DC para relés





Etapa 3:o hardware


Vamos montar o Projeto HW. O ideal é instalar e testar nosso projeto por partes. A título de sugestão, podemos seguir os passos:
  • Instale e teste localmente todos os sensores
  • Instale e configure o ESP-01 (BareMinimum)
  • Altere a instalação do ESP-01 para sua configuração final e teste-a
  • Configurar o canal de status ThingsPeak
  • Instale o código ThingsPeak em seu Arduino e verifique o status dos sensores na nuvem
  • Desenvolva a primeira versão do aplicativo Android para exibir status e mensagens
  • Instale atuadores (LEDs e relés)
  • Configurar canais de atuadores ThingSpeak
  • Instale e teste o código Arduino com atuadores
  • Desenvolva a versão final do aplicativo Android





Etapa 4:conectando sensores


Devemos ter algumas bibliotecas instaladas em nosso IDE para ler os sensores corretamente. Verifique se você tem todas as bibliotecas instaladas. Sua configuração inicial deve ser:
  // DS18B20 # include  #include  #define ONE_WIRE_BUS 5 // DS18B20 no pino D5 OneWire oneWire (ONE_WIRE_BUS); DallasTemperature DS18B20 (&oneWire); int soloTemp =0; // DHT # include "DHT.h" #include  int pinoDHT =11; int tipoDHT =DHT22; DHT dht (pinoDHT, tipoDHT); int airTemp =0; int airHum =0; // LDR (Light) #define ldrPIN 1int light =0; // Umidade do solo # define soloHumPIN 0int soloHum =0;  

Em Setup e loop, vamos escrever:
  void setup () {Serial.begin (9600); DS18B20.begin (); dht.begin ();} void loop () {readSensors (); displaySensors (); atraso (10000);}  

E por último, vamos escrever duas funções específicas, uma para ler nossos sensores e outra para exibir seus valores no Monitor Serial:
  / ********* Valor dos sensores de leitura ************* / void readSensors (void) {airTemp =dht.readTemperature (); airHum =dht.readHumidity (); DS18B20.requestTemperatures (); soloTemp =DS18B20.getTempCByIndex (0); // O sensor 0 irá capturar a temperatura do solo em Celcius soloHum =map (analogRead (soloHumPIN), 1023, 0, 0, 100); luz =mapa (analogRead (ldrPIN), 1023, 0, 0, 100); // LDRDark:0 ==> luz 100%} / ********* Valor dos sensores de exibição ************* / void displaySensors (void) {Serial.print (" airTemp (oC):"); Serial.println (airTemp); Serial.print ("airHum (%):"); Serial.println (airHum); Serial.print ("soloTemp (oC):"); Serial.println (soloTemp); Serial.print ("soloHum (%):"); Serial.println (soloHum); Serial.print ("luz (%):"); Serial.println (claro); Serial.println ("");}  

A imagem do Serial Monitor abaixo nos mostra os valores do sensor.

O código pode ser baixado do meu GITHUB:Sens ors_Test.ino





Etapa 5:configuração inicial do ESP8266-01


O ESP-01 será utilizado como Serial Bridge, o que significa que iremos programá-lo utilizando "comandos AT". A primeira coisa é ter certeza de que o ESP-01 está na velocidade de comunicação da taxa de transmissão correta. Em nosso caso, 9.600 bauds. Normalmente, o ESP-01 vem programado de fábrica com 115.200 bauds e devemos alterá-lo para 9.600 bauds.

Primeiro, você deve conectar o ESP-01 conforme mostrado acima.

Em seguida, conecte o Arduino ao seu computador, abra o IDE e carregue o exemplo que está em Arquivo> Exemplos> 01.Basics> BareMinimum. Este é um código vazio, para garantir que não haverá conflito de comunicação entre o Arduino e o ESP.

Transferimos esse código para o Arduino antes de conectá-lo ao ESP-01S para garantir que o Arduino não use comunicação serial (TX e RX). Isso é importante para que o ESP possa se comunicar adequadamente.

Abra seu IDE Serial Monitor e mude a velocidade para 115.200 baud Comece enviando um comando "AT" em seu IDE Serial Monitor. O ESP-01 deve retornar "OK"

A seguir, vamos mudar a velocidade. Para isso, você pode usar o comando:
  AT + CIOBAUD =9600  

Note que o ESP-01 pode retornar à programação de fábrica (não sei se isso é devido à versão FW). Pelo menos no meu caso, tive que usar um comando diferente para alterar o BaudRate definitivamente:
  AT + UART_DEF =, , , ,   

Por exemplo:9600 baud / 8 bits de dados / 1 bits de parada e nenhum controle de paridade e fluxo:
  AT + UART_DEF =9600,8,1,0,0  

Na caixa de seleção na parte inferior do Monitor serial, altere a velocidade para "9600 baud". Teste a comunicação:na parte superior da janela, digite AT e veja a resposta OK. Agora você deve configurar o módulo em Modo Estação para atuar como Cliente da sua rede Wi-Fi. Use o comando:
  AT + CWMODE =1  

Agora devemos conectar o módulo à sua rede wi-fi.

Para fazer isso, use os comandos abaixo, substituindo "network_name" pelo nome da sua rede Wi-Fi e "network_name" pela sua senha. Mantenha as aspas.
  AT + CWJAP ="network_name", "network_name"  

Se você vir a resposta abaixo, sua conexão foi estabelecida corretamente:
  WIFI CONECTADO WIFI GOT IP  

Para encontrar o IP, execute o comando:
  AT + CIFSR  

E anote o endereço IP que aparecerá no seu Monitor Serial. Você pode precisar no futuro.





Etapa 6:Testar o ESP-01


Assim que tivermos o ESP-01 configurado, devemos instalá-lo em seu circuito final. Para isso devemos TROCAR a fiação feita antes e conectar o ESP-01 ao nosso UNO conforme abaixo:
  • ESP-01 RX (amarelo) para UNO pino D7
  • ESP-01 TX (laranja) para UNO pino D6
  • ESP-01 Ch-Pd (marrom) para Vcc (3,3V)
  • ESP-01 Reset (azul) para UNO pino D8
  • ESP-01 Vcc (vermelho) para 3,3 V
  • ESP-01 Gnd (preto) para UNO GND

Vamos fazer um teste simples para verificar se nosso ESP-01 foi corrigido instalado e testado. Insira o código abaixo:
  #include  SoftwareSerial esp8266 (6,7); // Rx ==> Pino 6; TX ==> Pin7 #define speed8266 9600 void setup () {esp8266.begin (speed8266); Serial.begin (velocidade 8266); Serial.println ("Teste de configuração do ESP8266 - use comandos AT");} void loop () {while (esp8266.available ()) {Serial.write (esp8266.read ()); } while (Serial.available ()) {esp8266.write (Serial.read ()); }}  

Agora, experimente alguns comandos AT e veja o resultado em seu monitor serial:
  * AT =====> ESP8266 retorna OK * AT + RST =====> ESP8266 reinicia e retorna OK * AT + GMR =====> ESP8266 retorna AT Version; Versão do SDK; identificação; OK * AT + CWMODE? => ESP8266 retorna o tipo de modo * AT + CWLAP ===> ESP8266 retorna pontos de acesso próximos * AT + CIFSR ===> ESP8266 retorna IP designado  

O código pode ser baixado do meu GITHUB:ESP_AT_Config.ino

Se você deseja se conectar à rede WiFi toda vez que ocorre uma reinicialização (ou seu Arduino é desligado / ligado) e inserindo suas credenciais, adicione uma chamada ao connectWiFi () função no final da função setup ():
  setup () {... connectWiFi (); }  

O connectWiFi () função deve estar no final do seu código principal .ino:
  void connectWiFi (void) {sendData ("AT + RST \ r \ n", 2000, 0); // redefine sendData ("AT + CWJAP =\" SEU NOME DE USUÁRIO \ ", \" SUA SENHA \ "\ r \ n", 2000, 0); // Atraso de conexão da rede (3000); sendData ("AT + CWMODE =1 \ r \ n", 1000, 0); sendData ("AT + CIFSR \ r \ n", 1000, 0); // Mostrar endereço IP Serial.println ("8266 Conectado");}  

Observe que a função acima chama outro sendData (data) função, que também deve estar localizada em seu código:
  String sendData (comando String, tempo limite const int, depuração booleana) {String response =""; EspSerial.print (comando); tempo interno longo =milis (); while ((time + timeout)> millis ()) {while (EspSerial.available ()) {// O esp possui dados para exibir sua saída na janela serial char c =EspSerial.read (); // leia o próximo caractere. resposta + =c; }} se (depurar) {Serial.print (resposta); } resposta de retorno;}  





Etapa 7:conectando sensores e ESP-01


Assim que tivermos todos os sensores instalados e testados e também nosso ESP-01 funcionando corretamente, vamos ver todos juntos e preparados para enviar dados para a internet.





Etapa 8:The ThingSpeak


Uma das partes mais importantes do nosso projeto é o ThingSpeak, uma plataforma IoT aberta que nos permitirá coletar, analisar e agir sobre os dados coletados. Se ainda não o fez, acesse o ThingSpeak, inscreva-se e crie sua conta.

Em seguida, crie um novo canal onde teremos nossos 2 atuadores, 5 sensores e um status de campo sobressalente:
  • Campo 1:Atuador 1
  • Campo 2:Atuador 2
  • Campo 3:Temperatura do ar em oC
  • Arquivado 4:Umidade Relativa do Ar em%
  • Campo 5:Temperatura do solo em oC
  • Campo 6:Umidade do solo em%
  • Campo 7:Luminosidade em%
  • Campo 8:Sobressalente

O campo 8 será deixado como reserva para ser usado para expansão futura ou para fins de depuração. Por exemplo, vou usá-lo como um "contador" para cada erro de comunicação que acontece durante o handshake do Arduino / ESP-01 com ThingSpeak.com.

Depois de criar o seu canal (neste caso será o nosso Canal de Status), será importante anotar suas chaves, conforme mostrado abaixo.





Etapa 9:Envio de status para a nuvem


Neste ponto, temos nosso Cloud Service disponível e nossos sensores capturando dados localmente. Vamos pegar esses valores e enviá-los para ThingSpeak.com. Vamos ESCREVER no canal ThingSpeak e para isso, precisaremos enviar uma string GET. Faremos em 3 partes:

Enviaremos um "cmd inicial":
  AT + CIPSTART ="TCP", "184.106.153.149", 80  

Seguindo o "comprimento" do comando:
  AT + CIPSEND =116  

E a própria string GET, que vai escrever nos campos apropriados do Canal de Status:
  GET / update? api_key =YOUR_WRITE_KEY_HERE &field1 =pump &fieldlamp =0 &field3 =airTemp &field4 =airHum &field5 =soloTemp &field6 =soloHum &field7 =light &field8 =sobressalente 

O código abaixo fará o trabalho por nós e o PrintScreen acima mostra o resultado no Monitor Serial:
  // String Thingspeak statusChWriteKey ="6SRPQQKIE6AJVQE6"; // ID do canal de status:385184 # include  SoftwareSerial EspSerial (6, 7); // Rx, Tx # define HARDWARE_RESET 8 // DS18B20 # include  #include  #define ONE_WIRE_BUS 5 // DS18B20 no pino D5 OneWire oneWire (ONE_WIRE_BUS); DallasTemperature DS18B20 (&oneWempire); =0; // DHT # inclui "DHT.h" #include  int pinoDHT =11; int tipoDHT =DHT22; DHT dht (pinoDHT, tipoDHT); int airTemp =0; int airHum =0; // LDR (Light) #define ldrPIN 1int light =0; // Umidade do solo # define soloHumPIN 0int soloHum =0; // Variáveis ​​a serem usadas com timerslong writeTimingSeconds =17; // ==> Definir o tempo de amostra em segundos para enviar datalong startWriteTiming =0; long elapsedWriteTime =0; // Variáveis ​​a serem usadas com Actuatorsboolean pump =0; lâmpada booleana =0; sobressalente interno =0; erro booleano; configuração vazia () {Serial.begin (9600); pinMode (HARDWARE_RESET, OUTPUT); digitalWrite (HARDWARE_RESET, HIGH); DS18B20.begin (); dht.begin (); EspSerial.begin (9600); // Comunicacao com Modulo WiFi EspHardwareReset (); // Reinicia do Modulo WiFi startWriteTiming =millis (); // iniciando o "relógio do programa"} void loop () {start:// label error =0; elapsedWriteTime =millis () - startWriteTiming; if (elapsedWriteTime> (writeTimingSeconds * 1000)) {readSensors (); writeThingSpeak (); startWriteTiming =millis (); } if (erro ==1) // Reenviar se a transmissão não for concluída {Serial.println ("<<<>>>"); atraso (2000); goto start; // vá para o rótulo "start"}} / ********* Valor dos sensores de leitura ************* / void readSensors (void) {airTemp =dht.readTemperature (); airHum =dht.readHumidity (); DS18B20.requestTemperatures (); soloTemp =DS18B20.getTempCByIndex (0); // O sensor 0 irá capturar a temperatura do solo em Celsius light =map (analogRead (ldrPIN), 1023, 0, 0, 100); // LDRDark:0 ==> luz 100% soloHum =map (analogRead (soloHumPIN), 1023, 0, 0, 100); } / ********* Conexao com TCP com Thingspeak ******* / void writeThingSpeak (void) {startThingSpeakCmd (); // preparação da string GET String getStr ="GET / update? api_key ="; getStr + =statusChWriteKey; getStr + ="&field1 ="; getStr + =String (bomba); getStr + ="&field2 ="; getStr + =String (lâmpada); getStr + ="&field3 ="; getStr + =String (airTemp); getStr + ="&field4 ="; getStr + =String (airHum); getStr + ="&field5 ="; getStr + =String (soloTemp); getStr + ="&field6 ="; getStr + =String (soloHum); getStr + ="&field7 ="; getStr + =String (claro); getStr + ="&field8 ="; getStr + =String (sobressalente); getStr + ="\ r \ n \ r \ n"; sendThingSpeakGetCmd (getStr); } / ********* Redefinir ESP ************* / void EspHardwareReset (void) {Serial.println ("Reseting ......."); digitalWrite (HARDWARE_RESET, LOW); atraso (500); digitalWrite (HARDWARE_RESET, HIGH); delay (8000); // Tempo necessário para começar a ler Serial.println ("RESET"); } / ********* Iniciar a comunicação com ThingSpeak ************* / void startThingSpeakCmd (void) {EspSerial.flush (); // o limpa buffer antes de começar a gravar String cmd ="AT + CIPSTART =\" TCP \ ", \" "; cmd + =" 184.106.153.149 "; // Endereco IP de api.thingspeak.com cmd + =" \ ", 80"; EspSerial.println (cmd); Serial.print ("enviado ==> cmd inicial:"); Serial.println (cmd); if (EspSerial.find ("Erro")) {Serial.println ("Erro AT + CIPSTART"); Retorna; }} / ********* enviar um GET cmd para ThingSpeak ************* / String sendThingSpeakGetCmd (String getStr) {String cmd ="AT + CIPSEND ="; cmd + =String (getStr.length ()); EspSerial.println (cmd); Serial.print ("enviado ==> comprimento cmd:"); Serial.println (cmd); if (EspSerial.find ((char *) ">")) {EspSerial.print (getStr); Serial.print ("enviado ==> getStr:"); Serial.println (getStr); delay (500); // tempo para processar o GET, sem este atraso apresenta ocupado no próximo comando String messageBody =""; while (EspSerial.available ()) {String line =EspSerial.readStringUntil ('\ n'); if (line.length () ==1) {// o conteúdo real começa depois da linha vazia (com comprimento 1) messageBody =EspSerial.readStringUntil ('\ n'); }} Serial.print ("MessageBody recebido:"); Serial.println (messageBody); return messageBody; } else {EspSerial.println ("AT + CIPCLOSE"); // alerta o usuário Serial.println ("ESP8266 CIPSEND ERROR:RESENDING"); // Reenviar ... sobressalente =sobressalente + 1; erro =1; retornar "erro"; }}  

O código pode ser baixado do meu GITHUB:SendingStatusTS_EXT.ino





Etapa 10:a primeira parte do aplicativo Android - monitoramento de status


Vamos criar nossa 1ª parte do aplicativo Android.

Primeiro, projetamos a interface do usuário. A tela de impressão acima mostra os principais elementos visíveis e não visíveis. Depois disso, devemos projetar os blocos (os números abaixo são correspondentes às figuras acima):

A cada 2 segundos (definido por Clock1), chamaremos um procedimento denominado:"readArduino".
  • O retorno desse procedimento será o valor de cada uma das variáveis ​​de Status que deverão ser exibidas na tela.
  • Observe que "converteremos" os valores "0" e "1" do status dos atuadores para "DESLIGADO" e "LIGADO" para melhor compreensão.
  • Esses valores ("Status") serão exibidos nas "etiquetas" correspondentes
  • As variáveis ​​de status devem ser declaradas como globais.
  • O procedimento "readArduino" irá, de fato, ler o Canal de status no ThingSpeak. Portanto, devemos definir a URL a ser enviada ao Thingspeak. Para isso, 3 variáveis ​​globais devem ser declaradas e unidas para criar a URL a ser enviada ao TS. Um GET deve ser enviado ao componente da Web chamado "ArduFarmBotStatusCh"
  • O texto obtido no comando anterior chegará no formato JSon. Este texto deve ser processado tendo cada campo a ser lido e armazenado na variável global correspondente.
  • The last thing to be done is call the "Alarm" procedure, that will analyze the status of two soil sensors. If the temperature is too low (in our case 10oC), a message must be displayed. Same for humidity, if it is lower than 60%. Note that we have defined another timer (Clock2), programmed to be fired each 1 second. This is only to "toggle" the color of message text (from white to red). This will make the message "blink".

The last photo above shows the final App working.

The App code can be downloaded from my GITHUB:ArduFarmBot_Status_App_EXT.aia





Step 11:Installing Actuators (LEDs and Relays)


Let's complete our HW.

For that, we must install our Actuators. As you remember, we will remotely receive commands to Turn ON and OFF a Pump and a Lamp. The Arduino output will activate a Relay (and a LED) to get those actions.

We will use a Relay module that has an Optocoupler Low-Level Trigger. Also, we will supply 5V to it through a separate pin, so we don't have to provide the required current on the input pin. The module does that for us.

The above figure shows how the actuators must be connected. Note that the Realy GND is NOT CONNECTED to Arduino GND. This will help not to introduce noise when the relay works.

For simplicity, I took out from the diagram, the sensors. But you can add the actuators circuitry to your project w/o taking out the sensors that you have already installed and tested.





Step 12:Configuring the ThingSpeak Actuators Channels


The same way that we did for the Status, we will create 2 new channels one for each actuator. From each one of them, take note of Channel ID, Read and Write keys. We will write only on Field 1 of each one of those channels. So, in my case for example:

Channel ID 375598 ==> LED Red (Pump)
  • Field1 =0 ==> Pump OFF
  • Field1 =1 ==> Pump ON

Channel ID 375599 ==> LED Green (Lamp)
  • Field1 =0 ==> Lamp OFF
  • Field1 =1 ==> Lamp ON





Step 13:Installing and Testing Arduino Code with Actuators


When we sent data to the web, what we did was to WRITE on a ThingSpeak channel (Channel status) to "transmit" (upload) data. Now we should READ from a ThingSpeak channel (Actuator Channel) to "receive" (download) data.

We will READ from a ThingSpeak channel and for that, we will need to send a GET string. We will do in 3 parts:

We will send a "Start cmd":
AT+CIPSTART="TCP","184.106.153.149",80 

Following the "length" of the command:
AT+CIPSEND=36 

And the GET string itself, that will read from field 1 on each one of the Actuator Channel:
GET /channels/375598/fields/1/last 

We will be reading from ThingSpeak channels on intervals of 10 seconds. After we send the GET command above, that is calling for the "LAST VALUE STORED ON FIELD 1 we will receive an answer from ThingSpeak that should be "1" or "0" on a specific position of the answer. If anything different from that arrived, we must ignore it.

The main difference between this part of the code and the previous one (to Send Status data), is the function:
readThingSpeak(String channelID) 

The below code will do the work for us and the above PrintScreen shows the result on Serial Monitor:
// Thingspeak String canalID1 ="375598"; //Actuator1String canalID2 ="375599"; //Actuator2#include SoftwareSerial EspSerial(6, 7); // Rx, Tx#define HARDWARE_RESET 8// Variables to be used with timerslong readTimingSeconds =10; // ==> Define Sample time in seconds to receive datalong startReadTiming =0;long elapsedReadTime =0;//Relays#define ACTUATOR1 10 // RED LED ==> Pump#define ACTUATOR2 12 // GREEN LED ==> Lampboolean pump =0; boolean lamp =0; int spare =0;boolean error;void setup(){ Serial.begin(9600); pinMode(ACTUATOR1,OUTPUT); pinMode(ACTUATOR2,OUTPUT); pinMode(HARDWARE_RESET,OUTPUT); digitalWrite(ACTUATOR1, HIGH); //o módulo relé é ativo em LOW digitalWrite(ACTUATOR2, HIGH); //o módulo relé é ativo em LOW digitalWrite(HARDWARE_RESET, HIGH); EspSerial.begin(9600); // Comunicacao com Modulo WiFi EspHardwareReset(); //Reset do Modulo WiFi startReadTiming =millis(); // starting the "program clock"}void loop(){ start://label error=0; elapsedReadTime =millis()-startReadTiming; if (elapsedReadTime> (readTimingSeconds*1000)) { int command =readThingSpeak(canalID1); if (command !=9) pump =command; delay (5000); command =readThingSpeak(canalID2); if (command !=9) lamp =command; takeActions(); startReadTiming =millis(); } if (error==1) //Resend if transmission is not completed { Serial.println(" <<<>>>"); delay (2000); goto start; //go to label "start" }}/********* Take actions based on ThingSpeak Commands *************/void takeActions(void){ Serial.print("Pump:"); Serial.println(pump); Serial.print("Lamp:"); Serial.println(lamp); if (pump ==1) digitalWrite(ACTUATOR1, LOW); else digitalWrite(ACTUATOR1, HIGH); if (lamp ==1) digitalWrite(ACTUATOR2, LOW); else digitalWrite(ACTUATOR2, HIGH);}/********* Read Actuators command from ThingSpeak *************/int readThingSpeak(String channelID){ startThingSpeakCmd(); int command; // preparacao da string GET String getStr ="GET /channels/"; getStr +=channelID; getStr +="/fields/1/last"; getStr +="\r\n"; String messageDown =sendThingSpeakGetCmd(getStr); if (messageDown[5] ==49) { command =messageDown[7]-48; Serial.print("Command received:"); Serial.println(command); } else command =9; return command;}/********* Reset ESP *************/void EspHardwareReset(void){ Serial.println("Reseting......."); digitalWrite(HARDWARE_RESET, LOW); atraso (500); digitalWrite(HARDWARE_RESET, HIGH); delay(8000);//Tempo necessário para começar a ler Serial.println("RESET"); }/********* Start communication with ThingSpeak*************/void startThingSpeakCmd(void){ EspSerial.flush();//limpa o buffer antes de começar a gravar String cmd ="AT+CIPSTART=\"TCP\",\""; cmd +="184.106.153.149"; // Endereco IP de api.thingspeak.com cmd +="\",80"; EspSerial.println(cmd); Serial.print("enviado ==> Start cmd:"); Serial.println(cmd); if(EspSerial.find("Error")) { Serial.println("AT+CIPSTART error"); Retorna; }}/********* send a GET cmd to ThingSpeak *************/String sendThingSpeakGetCmd(String getStr){ String cmd ="AT+CIPSEND="; cmd +=String(getStr.length()); EspSerial.println(cmd); Serial.print("enviado ==> lenght cmd:"); Serial.println(cmd); if(EspSerial.find((char *)">")) { EspSerial.print(getStr); Serial.print("enviado ==> getStr:"); Serial.println(getStr); delay(500);//tempo para processar o GET, sem este delay apresenta busy no próximo comando String messageBody =""; while (EspSerial.available()) { String line =EspSerial.readStringUntil('\n'); if (line.length() ==1) { //actual content starts after empty line (that has length 1) messageBody =EspSerial.readStringUntil('\n'); } } Serial.print("MessageBody received:"); Serial.println(messageBody); return messageBody; } else { EspSerial.println("AT+CIPCLOSE"); // alert user Serial.println("ESP8266 CIPSEND ERROR:RESENDING"); //Resend... spare =spare + 1; error=1; return "error"; }}  

The code can be downloaded from my GITHUB:ReadingCommandTS_EXT.ino





Step 14:Sending Commands to Actuators


At this point, we have the actuators channels configured on ThingSpeak and changing the value of Field 1 on each channel, we must see the actuators changing accordingly. On our final project we will do this task, using the Android App, but for testing proposes we can also do it using a normal browser. Vamos fazer isso.

The commands are:

Turn ON Pump (RED LED):
https://api.thingspeak.com/update?api_key=ACT1_WRITE_KEY&field1=1 

Turn OFF Pump (RED LED):
https://api.thingspeak.com/update?api_key=ACT1_WRITE_KEY&field1=0 

Turn ON Lamp (GREEN LED):
https://api.thingspeak.com/update?api_key=ACT2_WRITE_KEY&field1=1 

Turn OFF Lamp (GREEN LED):
https://api.thingspeak.com/update?api_key=ACT2_WRITE_KEY&field1=0 

Above you can see a print screen of a command to TurnOn the Pump sent from a browser and how it will appear at Serial Monitor. Obviously, the LED Red and relay will be also be turned on.





Step 15:Completing the Android APP


Let's complete the APP. Previously we have developed a simple App that gets the status from ThingSpeak (READ from Staus Channel). Now we must WRITE on Actuator channels, so those commands could be read by Arduino and act on Pump and Lamp accordingly.

For a user to pass the commands to the App, we will use "buttons". A pair of buttons (ON and OFF) for each one of the Actuators.

When a button is pressed, the color of its text changes.
  • If ON ==> Blue
  • if OFF ==> Red

Above you can see the set of blocks for each one of the pairs of buttons.

Test the App, sending commands to turn ON and OFF the actuators. Check on Serial Monitor, the messages exchanged between ESP-01 and ThingSpeak.

The complete App code can be downloaded from my GITHUB:ArduFarmBot_V1_EXT.aia





Step 16:Putting All Together


Perfeito! At this point, you have a full Android APP, a complete HW but you still do not have a code that will continuously read and write on ThingSpeak. Let's combine all that we have developed previously.

On the final code, you will find additional portions to verify for example if the ESP-01 is not freezing. We will do it, sending an AT command to it before any read or write. As we saw at the very beginning of this tutorial, sending an AT command should return from ESP-01 an OK. If this does not happen, we will proceed with an HW reset, commanded by SW (as we do once during setup phase).

The complete code for our project can be downloaded from my GITHUB:ArduFarmBot_Light_EXT.ino





Step 17:Conclusion


There is a lot to be explored in IoT arena with those great little devices, the Arduino Uno, and the ESP8266-01. We will return soon with new tutorials! Keep following MJRoBot tutorials!

As always, I hope this project can help others find their way in the exciting world of electronics, robotics, and IoT!

Please visit my GitHub for updated files:ArduFarmBot_Light

Para mais projetos, visite meu blog:MJRoBot.org

Saludos do sul do mundo!

Vejo vocês no meu próximo tutorial!

Obrigada,

Marcelo

Código

  • Snippet de código # 1
  • Snippet de código # 2
  • Snippet de código # 3
  • Code snippet #11
  • Code snippet #12
  • Code snippet #16
  • Code snippet #20
Snippet de código # 1 Texto simples
// DS18B20#include #include #define ONE_WIRE_BUS 5 // DS18B20 on pin D5 OneWire oneWire(ONE_WIRE_BUS);DallasTemperature DS18B20(&oneWire);int soilTemp =0;//DHT#include "DHT.h"#include int pinoDHT =11;int tipoDHT =DHT22;DHT dht(pinoDHT, tipoDHT); int airTemp =0;int airHum =0;// LDR (Light)#define ldrPIN 1int light =0;// Soil humidity#define soilHumPIN 0int soilHum =0;
Snippet de código # 2 Texto simples
void setup(){ Serial.begin(9600); DS18B20.begin(); dht.begin();}void loop(){ readSensors(); displaySensors(); delay (10000);}
Snippet de código # 3 Texto simples
/********* Read Sensors value *************/void readSensors(void){ airTemp =dht.readTemperature(); airHum =dht.readHumidity(); DS18B20.requestTemperatures(); soilTemp =DS18B20.getTempCByIndex(0); // Sensor 0 will capture Soil Temp in Celcius soilHum =map(analogRead(soilHumPIN), 1023, 0, 0, 100); light =map(analogRead(ldrPIN), 1023, 0, 0, 100); //LDRDark:0 ==> light 100% }/********* Display Sensors value *************/void displaySensors(void){ Serial.print ("airTemp (oC):"); Serial.println (airTemp); Serial.print ("airHum (%):"); Serial.println (airHum); Serial.print ("soilTemp (oC):"); Serial.println (soilTemp); Serial.print ("soilHum (%):"); Serial.println (soilHum); Serial.print ("light (%):"); Serial.println (light); Serial.println ("");}
Code snippet #11Plain text
#include  SoftwareSerial esp8266(6,7); //Rx ==> Pin 6; TX ==> Pin7 #define speed8266 9600 void setup() { esp8266.begin (speed8266); Serial.begin(speed8266); Serial.println("ESP8266 Setup test - use AT coomands");}void loop() { while(esp8266.available()) { Serial.write(esp8266.read()); } while(Serial.available()) { esp8266.write(Serial.read()); }} 
Code snippet #12Plain text
* 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
Code snippet #16Plain text
// Thingspeak String statusChWriteKey ="6SRPQQKIE6AJVQE6"; // Status Channel id:385184#include SoftwareSerial EspSerial(6, 7); // Rx, Tx#define HARDWARE_RESET 8// DS18B20#include #include #define ONE_WIRE_BUS 5 // DS18B20 on pin D5 OneWire oneWire(ONE_WIRE_BUS);DallasTemperature DS18B20(&oneWire);int soilTemp =0;//DHT#include "DHT.h"#include int pinoDHT =11;int tipoDHT =DHT22;DHT dht(pinoDHT, tipoDHT); int airTemp =0;int airHum =0;// LDR (Light)#define ldrPIN 1int light =0;// Soil humidity#define soilHumPIN 0int soilHum =0;// Variables to be used with timerslong writeTimingSeconds =17; // ==> Define Sample time in seconds to send datalong startWriteTiming =0;long elapsedWriteTime =0;// Variables to be used with Actuatorsboolean pump =0; boolean lamp =0; int spare =0;boolean error;void setup(){ Serial.begin(9600); pinMode(HARDWARE_RESET,OUTPUT); digitalWrite(HARDWARE_RESET, HIGH); DS18B20.begin(); dht.begin (); EspSerial.begin(9600); // Comunicacao com Modulo WiFi EspHardwareReset(); //Reset do Modulo WiFi startWriteTiming =millis(); // starting the "program clock"}void loop(){ start://label error=0; elapsedWriteTime =millis()-startWriteTiming; if (elapsedWriteTime> (writeTimingSeconds*1000)) { readSensors(); writeThingSpeak(); startWriteTiming =millis(); } if (error==1) //Resend if transmission is not completed { Serial.println(" <<<>>>"); delay (2000); goto start; //go to label "start" }}/********* Read Sensors value *************/void readSensors(void){ airTemp =dht.readTemperature(); airHum =dht.readHumidity(); DS18B20.requestTemperatures(); soilTemp =DS18B20.getTempCByIndex(0); // Sensor 0 will capture Soil Temp in Celcius light =map(analogRead(ldrPIN), 1023, 0, 0, 100); //LDRDark:0 ==> light 100% soilHum =map(analogRead(soilHumPIN), 1023, 0, 0, 100); }/********* Conexao com TCP com Thingspeak *******/void writeThingSpeak(void){ startThingSpeakCmd(); // preparacao da string GET String getStr ="GET /update?api_key="; getStr +=statusChWriteKey; getStr +="&field1="; getStr +=String(pump); getStr +="&field2="; getStr +=String(lamp); getStr +="&field3="; getStr +=String(airTemp); getStr +="&field4="; getStr +=String(airHum); getStr +="&field5="; getStr +=String(soilTemp); getStr +="&field6="; getStr +=String(soilHum); getStr +="&field7="; getStr +=String(light); getStr +="&field8="; getStr +=String(spare); getStr +="\r\n\r\n"; sendThingSpeakGetCmd(getStr); }/********* Reset ESP *************/void EspHardwareReset(void){ Serial.println("Reseting......."); digitalWrite(HARDWARE_RESET, LOW); atraso (500); digitalWrite(HARDWARE_RESET, HIGH); delay(8000);//Tempo necessário para começar a ler Serial.println("RESET"); }/********* Start communication with ThingSpeak*************/void startThingSpeakCmd(void){ EspSerial.flush();//limpa o buffer antes de começar a gravar String cmd ="AT+CIPSTART=\"TCP\",\""; cmd +="184.106.153.149"; // Endereco IP de api.thingspeak.com cmd +="\",80"; EspSerial.println(cmd); Serial.print("enviado ==> Start cmd:"); Serial.println(cmd); if(EspSerial.find("Error")) { Serial.println("AT+CIPSTART error"); Retorna; }}/********* send a GET cmd to ThingSpeak *************/String sendThingSpeakGetCmd(String getStr){ String cmd ="AT+CIPSEND="; cmd +=String(getStr.length()); EspSerial.println(cmd); Serial.print("enviado ==> lenght cmd:"); Serial.println(cmd); if(EspSerial.find((char *)">")) { EspSerial.print(getStr); Serial.print("enviado ==> getStr:"); Serial.println(getStr); delay(500);//tempo para processar o GET, sem este delay apresenta busy no próximo comando String messageBody =""; while (EspSerial.available()) { String line =EspSerial.readStringUntil('\n'); if (line.length() ==1) { //actual content starts after empty line (that has length 1) messageBody =EspSerial.readStringUntil('\n'); } } Serial.print("MessageBody received:"); Serial.println(messageBody); return messageBody; } else { EspSerial.println("AT+CIPCLOSE"); // alert user Serial.println("ESP8266 CIPSEND ERROR:RESENDING"); //Resend... spare =spare + 1; error=1; return "error"; }} 
Code snippet #20Plain text
// Thingspeak String canalID1 ="375598"; //Actuator1String canalID2 ="375599"; //Actuator2#include SoftwareSerial EspSerial(6, 7); // Rx, Tx#define HARDWARE_RESET 8// Variables to be used with timerslong readTimingSeconds =10; // ==> Define Sample time in seconds to receive datalong startReadTiming =0;long elapsedReadTime =0;//Relays#define ACTUATOR1 10 // RED LED ==> Pump#define ACTUATOR2 12 // GREEN LED ==> Lampboolean pump =0; boolean lamp =0; int spare =0;boolean error;void setup(){ Serial.begin(9600); pinMode(ACTUATOR1,OUTPUT); pinMode(ACTUATOR2,OUTPUT); pinMode(HARDWARE_RESET,OUTPUT); digitalWrite(ACTUATOR1, HIGH); //o módulo relé é ativo em LOW digitalWrite(ACTUATOR2, HIGH); //o módulo relé é ativo em LOW digitalWrite(HARDWARE_RESET, HIGH); EspSerial.begin(9600); // Comunicacao com Modulo WiFi EspHardwareReset(); //Reset do Modulo WiFi startReadTiming =millis(); // starting the "program clock"}void loop(){ start://label error=0; elapsedReadTime =millis()-startReadTiming; if (elapsedReadTime> (readTimingSeconds*1000)) { int command =readThingSpeak(canalID1); if (command !=9) pump =command; delay (5000); command =readThingSpeak(canalID2); if (command !=9) lamp =command; takeActions(); startReadTiming =millis(); } if (error==1) //Resend if transmission is not completed { Serial.println(" <<<>>>"); delay (2000); goto start; //go to label "start" }}/********* Take actions based on ThingSpeak Commands *************/void takeActions(void){ Serial.print("Pump:"); Serial.println(pump); Serial.print("Lamp:"); Serial.println(lamp); if (pump ==1) digitalWrite(ACTUATOR1, LOW); else digitalWrite(ACTUATOR1, HIGH); if (lamp ==1) digitalWrite(ACTUATOR2, LOW); else digitalWrite(ACTUATOR2, HIGH);}/********* Read Actuators command from ThingSpeak *************/int readThingSpeak(String channelID){ startThingSpeakCmd(); int command; // preparacao da string GET String getStr ="GET /channels/"; getStr +=channelID; getStr +="/fields/1/last"; getStr +="\r\n"; String messageDown =sendThingSpeakGetCmd(getStr); if (messageDown[5] ==49) { command =messageDown[7]-48; Serial.print("Command received:"); Serial.println(command); } else command =9; return command;}/********* Reset ESP *************/void EspHardwareReset(void){ Serial.println("Reseting......."); digitalWrite(HARDWARE_RESET, LOW); atraso (500); digitalWrite(HARDWARE_RESET, HIGH); delay(8000);//Tempo necessário para começar a ler Serial.println("RESET"); }/********* Start communication with ThingSpeak*************/void startThingSpeakCmd(void){ EspSerial.flush();//limpa o buffer antes de começar a gravar String cmd ="AT+CIPSTART=\"TCP\",\""; cmd +="184.106.153.149"; // Endereco IP de api.thingspeak.com cmd +="\",80"; EspSerial.println(cmd); Serial.print("enviado ==> Start cmd:"); Serial.println(cmd); if(EspSerial.find("Error")) { Serial.println("AT+CIPSTART error"); Retorna; }}/********* send a GET cmd to ThingSpeak *************/String sendThingSpeakGetCmd(String getStr){ String cmd ="AT+CIPSEND="; cmd +=String(getStr.length()); EspSerial.println(cmd); Serial.print("enviado ==> lenght cmd:"); Serial.println(cmd); if(EspSerial.find((char *)">")) { EspSerial.print(getStr); Serial.print("enviado ==> getStr:"); Serial.println(getStr); delay(500);//tempo para processar o GET, sem este delay apresenta busy no próximo comando String messageBody =""; while (EspSerial.available()) { String line =EspSerial.readStringUntil('\n'); if (line.length() ==1) { //actual content starts after empty line (that has length 1) messageBody =EspSerial.readStringUntil('\n'); } } Serial.print("MessageBody received:"); Serial.println(messageBody); return messageBody; } else { EspSerial.println("AT+CIPCLOSE"); // alert user Serial.println("ESP8266 CIPSEND ERROR:RESENDING"); //Resend... spare =spare + 1; error=1; return "error"; }} 
Github
https://github.com/Mjrovai/ArduFarmBot_Light

Esquemas

Electrical diagram
https://github.com/Mjrovai/ArduFarmBot_Light/blob/master/ArduFarmBot_Light/ArduFarmBot%20Light.fzz

Processo de manufatura

  1. Computação paralela em placas Raspberry Pi 4B + IoT simplificadas
  2. Monitor de freqüência cardíaca usando IoT
  3. WebServerBlink usando Arduino Uno WiFi
  4. Calculadora UNO simples
  5. Persistência da visão
  6. Porta de monitoramento de temperatura sem contato
  7. Arduino - Enviar temperatura para a Web via serial
  8. Estação meteorológica ThingSpeak Arduino
  9. Quão fácil é usar um termistor ?!
  10. Piscina Azure IoT