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

ArduFarmBot - Parte 2:Estação Remota e Implementação IoT

Componentes e suprimentos

Arduino Nano R3
× 1
Espressif ESP8266 ESP-01
× 1
Sensor de temperatura DHT22
× 1
ky18
× 1
hidrômetro
× 1
Relé (genérico)
× 2
lcd 4X20
× 1
SparkFun Botão de pressão 12 mm
× 3
LED (genérico)
× 3

Aplicativos e serviços online

API ThingSpeak

Sobre este projeto




Este tutorial é uma continuação do ArduFarmBot:Controlando uma fazenda doméstica do tomate usando Arduino e IoT

Na primeira parte criamos uma estação de controle local, captando informações de uma plantação de tomate, como temperatura, umidade relativa do ar, luminosidade e umidade do solo. Com base nesses dados, o ArduFarmBot decidiu automaticamente a quantidade certa (e quando) a plantação deveria receber calor e água. A estação local desenvolvida na Parte 1, também permitiu a intervenção manual de um operador para controlar a bomba d'água e a lâmpada elétrica. Nesta Parte 2, implementaremos uma abordagem de IoT onde essa "intervenção manual" também será possível remotamente via Internet. O diagrama de blocos mostra como faremos isso.

Observe que os dados capturados serão enviados para um "serviço Cloud Storage" (no nosso caso Thinkspeak.com). Também um site dedicado, a "Página de Controle Remoto" monitorará e exibirá esses dados quase em tempo real. Esta página da Web também permitirá a ativação remota da bomba e da lâmpada.





Etapa 1:lista de materiais

  • Arduino Nano - ($ 7,50)
  • Sensor de temperatura e umidade DHT22 ou DHT11 - ($ 3,66)
  • Sensor de luminosidade - Módulo de foto resistor AD-018. ou qualquer equivalente - ($ 0,71)
  • 2X sensor de umidade do solo - ($ 1,99) (opcional, pode ser DIY)
  • LCD I2C 20X4 ($ 13,99)
  • LEDs (1X) ($ 0,20)
  • Módulo transceptor sem fio Wifi Serial Esp8266 Esp-01 - ($ 5,96)
  • Campainha ativa - Ky-12 ou equivalente ($ 0,60)
  • Módulo de retransmissão 2 X 5v (US $ 11,60)
  • fios de ligação (S1.00)
  • resistor de 10KOhms - ($ 0,03)
  • Resistor de 2,2K Ohms - ($ 0,03)
  • resistor de 1,0K Ohms - ($ 0,03)
  • resistor de 220 Ohms - ($ 0,03)
  • Arduino Nano Shield ("Funduino") - ($ 7,28)
  • Teclado de membrana (4 teclas) - ($ 6,65)
  • Caixa de plástico





Etapa 2:Completando o Hardware


Começando com a estação local desenvolvida na Parte 1, o único HW adicional necessário é o ESP8266. O diagrama de blocos acima mostra todas as conexões de PIN do Arduino e dos componentes principais. O único cuidado que você deve ter está relacionado ao nível de tensão. O ESP8266 trabalha com 3,3V, portanto, o Rx Pin que não deve ser conectado diretamente ao Nano Tx Pin (D3). Um nível de tensão deve ser usado. Em nosso caso, construiremos um divisor de tensão para ser usado como conversor de nível de tensão. Os diagramas acima mostram com mais detalhes como conectar o ESP8266. Se você quiser saber mais sobre o ESP8266, consulte meus tutoriais:
  • O ESP8266 Parte 3 - Acionando LEDs do Arduino remotamente
  • O ESP8266 Parte 1 - Módulo WIFI serial para Arduino
  • O ESP8266 Parte 2 - Arduino Web Server

Observe que estamos usando o ESP8266 conectado ao Nano Pino 2 (Tx) e Pino 3 (Rx), usando a biblioteca SoftSerial. Se quiser "liberar" esses pinos digitais, você pode usar alternadamente os pinos 0 e 1 do Nano Serial. Lembre-se apenas de que você deve desconectá-los ao enviar o código para o Nano.

NOTA:Se você deseja conectar o BUZZER, deve fazê-lo no pino D17 (igual ao pino A3). É bom ter um som quando houver um erro de comunicação. Usei durante a fase de teste, deixando de fora no projeto final (o hw, mas o código está preparado para isso). Depende de você ter ou não.

Você pode usar o código abaixo para testar e / ou configurar seu ESP8266:
FC9DBPKIT682FY7.ino





Etapa 3:a conexão ESP8266


Para conectar o ArduFarmBot à Internet, usaremos o ESP8266, um módulo simples, barato e fácil de programar para projetos de IoT. Assim que o módulo estiver instalado, a primeira coisa a fazer é aplicar um "Reset" em seu pino CH-PD.
  / ******************************************* ********* Redefinir função para aceitar comunicação ************************************ **************** / void reset8266 (void) {pinMode (CH_PD, OUTPUT); digitalWrite (CH_PD, LOW); atraso (300); digitalWrite (CH_PD, HIGH); Serial.print ("8266 reset OK"); lcd.clear (); lcd.println ("8266 reset OK");}  

Após a reinicialização, vamos conectá-lo à sua rede local usando suas credenciais (no código, altere:NOME DE USUÁRIO e SENHA) e iniciar o módulo como "STA:Modo Estação" (CWMODE =1):
  / ******************************************* ********* Conecte WiFi *************************************** ************* / void connectWiFi (void) {sendData ("AT + RST \ r \ n", 2000, DEBUG); // redefine sendData ("AT + CWJAP =\" NOME DE USUÁRIO \ ", \" SENHA \ "\ r \ n", 2000, DEBUG); // Atraso de conexão da rede (3000); sendData ("AT + CWMODE =1 \ r \ n", 1000, DEBUG); sendData ("AT + CIFSR \ r \ n", 1000, DEBUG); // Mostra o endereço IP lcd.clear (); lcd.print ("8266 Conectado"); Serial.println ("8266 Conectado");}  

Para enviar dados para ESP8266, a função sendData () foi usado:
  / ******************************************* ********* Enviar comandos AT para o módulo ************************************* **************** / String sendData (comando String, tempo limite const int, depuração booleana) {String response =""; esp8266.print (comando); tempo interno longo =milis (); while ((time + timeout)> millis ()) {while (esp8266.available ()) {// O esp possui dados, então exibe sua saída para a janela serial char c =esp8266.read (); // leia o próximo caractere. resposta + =c; }} se (depurar) {Serial.print (resposta); } resposta de retorno;}  

As funções acima serão chamadas durante a "Fase de Configuração" do nosso Código. Se tudo foi feito corretamente, você deverá ver no Serial Monitor mensagens semelhantes às acima.





Etapa 4:Dados de armazenamento em nuvem:ThinkSpeak.com


Todos os dados capturados pelo ArduFarmBot serão enviados para a nuvem, utilizando o serviço gratuito de "ThinkSpeak.com".

Na função "Loop ()" (depois de capturarmos os dados com readSensors () ), chamaremos uma função específica para fazer upload dos dados capturados: updateDataThingSpeak ();
  / ******************************************* ********* Transmitir dados para thingspeak.com *********************************** ***************** / void updateDataThingSpeak (void) {startThingSpeakCmd (); cmd =msg; cmd + ="&field1 ="; // campo 1 para temperatura DHT cmd + =tempDHT; cmd + ="&field2 ="; // campo 2 para umidade DHT cmd + =humDHT; cmd + ="&field3 ="; // campo 3 para luminosidade LDR cmd + =lumen; cmd + ="&field4 ="; // campo 4 para dados de umidade do solo cmd + =soloMoist; cmd + ="&field5 ="; // campo 5 para PUMP Status cmd + =pumpStatus; cmd + ="&field6 ="; // campo 6 para LAMP Status cmd + =lampStatus; cmd + ="\ r \ n"; sendThingSpeakCmd ();}  

Para enviar esses dados, a primeira coisa a fazer é iniciar a comunicação com o ThingSpeak. Faremos isso usando a função: startThingSpeakCmd ();
  / ******************************************* ********* Inicie a comunicação com ThingSpeak.com *********************************** ****************** / void startThingSpeakCmd (void) {cmd ="AT + CIPSTART =\" TCP \ ", \" "; cmd + =IP; cmd + =" \ ", 80"; esp8266.println (cmd); atraso (2000); if (esp8266.find ("Error")) {Serial.println ("ESP8266 START ERROR"); Retorna; } Serial.println ("Thinkspeak Comm Started"); cmd ="";}  

Uma vez que o canal é aberto com ThingSpeak e a string "cmd" é montada com os dados, é hora de enviar tudo para o canal correspondente em ThingSpeak usando a função: sendThingSpeakCmd ();
  / ******************************************* ******** * Atualizar canal 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); atraso (500); String messageBody =""; while (esp8266.available ()) {String line =esp8266.readStringUntil ('\ n'); if (line.length () ==1) {// o conteúdo real começa depois da linha vazia (que tem comprimento 1) messageBody =esp8266.readStringUntil ('\ n'); Serial.print ("Mensagem recebida:"); Serial.println (messageBody); }} return messageBody; } else {esp8266.println ("AT + CIPCLOSE"); Serial.println ("ESP8266 CIPSEND ERROR:RESENDING"); // Reenviar ... erro =1; retornar "erro"; }}  

As funções acima foram baseadas em um ótimo e detalhado tutorial desenvolvido por Michalis Vasilakis. Para obter mais detalhes, consulte seu tutorial:Arduino IOT:Temperatura e Umidade (com ESP8266 WiFi).

A foto mostra o canal ArduFarmBot em ThingSpeak.com.





Etapa 5:Comandar os atuadores da web


No momento, estamos enviando todos os dados coletados e armazenando-os na nuvem. Isso é muito bom e útil para um monitoramento remoto, mas o que acontece se com base nesses dados também quisermos ligar a bomba ou a lâmpada, independente do programa automático local? Para fazer isso, também precisaremos "baixar" os dados da nuvem e comandar o controlador para agir com base nesses comandos.

Criaremos campos específicos em nosso canal ThinkSpeak para comandar os atuadores:

Campo 7:
  • Data =1 ==> A BOMBA deve estar LIGADA
  • Dados =0 ==> BOMBA deve estar DESLIGADA

Campo 8:
  • Data =1 ==> LAMP deve estar LIGADO
  • Data =0 ==> LAMP deve estar DESLIGADO

OK, mas como configurar esses campos diretamente no ThingSpeak? Podemos fazer isso, por exemplo, escrevendo um "PlugIn" diretamente no ThinksPeak, ou podemos usar um site externo para fazer isso (a escolha será nossa). De qualquer forma, em ambos os casos você deve usar um comando como:
  api.thingspeak.com/update?key=YOUR_WRITE_KEY&field7=1  

Com o comando acima, por exemplo (e usando a chave Write do seu canal), você escreverá "1" no campo 7, o que significa que a BOMBA deve estar ligada. Você pode testá-lo facilmente, escrevendo a linha de comando acima em seu navegador, o campo correspondente em seu canal será alterado. Como retorno, o navegador mostrará uma página em branco com um único número no canto superior esquerdo, correspondendo à entrada de dados sequenciais em seu canal.

50% do trabalho está feito, agora você deve ler este "comando" (dados em campo), na estação local do ArduFarmBot.

O comando para fazer isso é mostrado abaixo. Irá obter os últimos dados que foram escritos no campo específico (que no nosso caso será um "comando".
  api.thingspeak.com/channels/CHANNEL_ID/fields/7/last  

Da mesma forma que fizemos antes, você pode testar a linha de comando, usando seu navegador da web. Nesse caso, o navegador mostrará os dados desse campo específico. Veja a foto acima.

Volte para "terra", vamos escrever uma função que irá ler este "último campo":
  / ******************************************* ********* Leia os dados do field7 de thingspeak.com ********************************* ******************* / int readLastDataField7 () {startThingSpeakCmd (); // "GET / channels / CHANNEL_ID / fields / 7 / last"; cmd =msgReadLastDataField7; cmd + ="\ r \ n"; String messageDown =sendThingSpeakCmd (); Serial.print ("Comando recebido:"); Serial.println (messageDown [7]); comando interno =mensagemDown [7] -48; comando de retorno;}  

A função acima retornará os dados do campo 7 ("1" ou "0"). Uma função semelhante deve ser escrita para o Campo 8.

Uma vez que tenhamos o conteúdo de ambos os campos, devemos usá-los em uma função que comandará os atuadores da mesma forma que fizemos com a "função de comando manual":
  / ******************************************* ********* Receber comandos de 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 (); } atraso (500); field8Data =readLastDataField8 (); if (field8Data ==1) {digitalWrite (LAMP_PIN, HIGH); lampStatus =1; showDataLCD (); } if (field8Data ==0) {digitalWrite (LAMP_PIN, LOW); lampStatus =0; showDataLCD (); } atraso (500); }  

Portanto, a partir de agora você pode usar a linha de comando em seu navegador para ligar / desligar a bomba e a lâmpada remotamente. A foto acima mostra como o comando recebido aparecerá no seu monitor serial.

Outra consideração importante é a "coordenação" entre o comando local e remoto. Devemos alterar a função readLocalCmd () para também atualizar o Thinkspeak Field 7 e 8 respectivamente com o status da bomba e da lâmpada (em sua "declaração IF" correspondente. Veja o código completo no final deste tutorial):
  field7Data =pumpStatus; field8Data =lampStatus;  

Agora, "filed7Data" e "field8Data" estão em sincronia com os comandos da página da web e também com as ações de comando locais quando você pressiona um botão. Então, vamos atualizar o aplyCmd () função, que é a responsável por ligar / desligar os atuadores:
  / ******************************************* ********* Receber comandos e agir sobre atuadores *********************************** ***************** / 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);}  

Ao iniciar seus testes você perceberá que qualquer comando que você fizer 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", tendo a última palavra! No nosso caso, definiremos o seguinte:
  • A cada ciclo de loop, que é quase "sempre", vamos olhar se um botão é pressionado
  • A cada minuto, devemos fazer um "pool" no ThingSpeak e ver se recebemos um pedido de lá.
  • A cada 10 minutos, leremos os sensores, atualizaremos os dados no ThingSpeak e, o que é mais importante, realizaremos as ações automáticas. Essas ações serão realizadas independentemente do que foi selecionado manualmente e será o que será mantido.

Você pode mudá-lo da maneira que quiser. Essa é a vantagem de usar um processador programável para controlar as coisas!

Portanto, 2 temporizadores serão usados ​​agora, um para agrupar os comandos remotos e outro para ler os sensores (o mesmo que usamos antes:
  long sampleTimingSeconds =75; // ==> ******** Definir tempo de amostra em segundos para leitura de sensores ********* int reverseElapsedTimeSeconds =0; long startTiming =0; long elapsedTime =0; long poolingRemoteCmdSeconds =20; // ==> ******** Definir o tempo de pooling em segundos para novos comandos ThingSpeak ********* long startRemoteCmdTiming =0; long elapsedRemoteCmdTime =0;  

Então, o loop () função agora deve ser reescrita como abaixo:
  void loop () {elapsedRemoteCmdTime =millis () - startRemoteCmdTiming; // Inicia o cronômetro para agrupar comandos remotos elapsedTime =millis () - startTiming; // Iniciar cronômetro para medições reverseElapsedTimeSeconds =round (sampleTimingSeconds - elapsedTime / 1000); readLocalCmd (); // Lê o status do botão local showDataLCD (); if (elapsedRemoteCmdTime> (poolingRemoteCmdSeconds * 1000)) {receiveCommands (); updateDataThingSpeak (); startRemoteCmdTiming =millis (); } if (elapsedTime> (sampleTimingSeconds * 1000)) {readSensors (); autoControlPlantation (); updateDataThingSpeak (); startTiming =millis (); }}  





Etapa 6:Implementação de uma página da web dedicada


Neste ponto, nosso ArduFarmBot está operacional e pode ser controlado pela web. Você pode monitorar os dados no site Thinkspeak e também enviar comandos usando um navegador, mas é claro que esta "solução web" não pode ser considerada uma "elegante"! A melhor forma de implementar uma solução IoT completa é desenvolver uma página web completa que mostre todos os dados, contando também com botões para ativar os atuadores.

Escolhi o Byethost, um webhost gratuito, muito fácil e simples de manusear suas páginas. Também aproveitei a oportunidade para me inscrever neste projeto, o que aprendi em uma fantástica especialização on-line no Coursera / University of Michigan:Aprenda a projetar e criar sites (construir um portfólio da Web responsivo e acessível usando HTML5, CSS3 e JavaScript )

Não entrarei em detalhes de como desenvolver tal página, uma vez que este não é o objetivo central deste tutorial, mas incluirei aqui os códigos-fonte HTML, CSS e JavaScript. E quando alguém tiver interesse em como obtive os resultados, podemos discutir isso à parte, usando o quadro de comentários no final do projeto.

É importante ressaltar que esta página não funciona diretamente com a Estação de Controle Local ArduFarmBot. O que ele realmente está fazendo é interagir com o canal ThinkSpeak conforme abaixo:
  • Leitura de dados do sensor nos campos 1, 2, 3, 4
  • Leitura do status do atuador nos campos 5 e 6
  • Gravação de dados nos campos 7 e 8
  • Leitura de dados meteorológicos locais de serviços do Yahoo

O item 4 acima não é realmente crucial para o projeto, mas sempre há dados adicionais disponíveis caso você queira realizar alguma ação remota independente do que está acontecendo localmente com seu plantio de tomate. Outra consideração é que você pode, por exemplo, armazenar esses dados em outro ThingSpeak Channel e baixá-los para o seu Arduino, mostrando os dados meteorológicos no display LCD local (eu desenvolvi isso em outro projeto legal que funcionou bem! Deixo aqui como uma sugestão para vocês).
FQOK9ENIT653YX5.zip





Etapa 7:Retorne ao cérebro. Uma abordagem de Matriz Sensor-Atuador:


Na primeira parte deste projeto, definimos algumas considerações preliminares sobre como os atuadores deveriam agir dependendo da leitura dos sensores. Fizemos apenas escolhas simples, mas o que acontecerá se tivermos uma situação mais complexa? Várias condições diferentes? O que iremos desenvolver é uma "abordagem de matriz Sensor - Atuador".

Em uma Matriz foram definidos para cada sensor, sua condição e como deveria ser a saída dos atuadores. O resultado pode ser visualizado na planilha Excel incluída a seguir. No arquivo Excel existem duas planilhas. A tabela com um filtro e uma versão onde você pode selecionar várias condições do sensor e ver como os atuadores irão funcionar devido a esta seleção.

Uma vez definida a Matriz, devemos traduzi-la para o nosso código. Uma matriz de 18 linhas e 10 colunas foi criada para "copiar" as condições da Matriz Sensor-Atuador:
  // + --- SOLO ---- + - LUZ - + --- TEMP --- + --- ATUAÇÃO ---- + // SL SM SH LL LH TL TM TH Bomba Lampboolean 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, criamos uma função defSensorStatus () . Esta função testa para cada linha se a condição das 8 primeiras colunas é TRUE. Se sim, a condição das 2 últimas colunas é executada.

Por exemplo:
  if (1 e 0 e 0 e 0 e 1 e 0 e 0 e 1) {pumpStatus =1; lampStatus =0} else if (1 e 0 e 0 e 0 e 1 e 0 e 1 e 0) {pumpStatus =1; lampStatus =0}  

e assim por diante.

Dentro da função acima, outro array é criado com o status de cada leitura do sensor:
  boolean snsSts [8] ={0, 0, 0, 0, 0, 0, 0, 0}; // SL, SM, SH, LL, LH, TL, TM, TH  

Este array de variáveis ​​também será usado para o registro LOG.
F2HWXBYITA8WIN1.xlsx





Etapa 8:Otimização de código


Durante o processo de desenvolvimento do ArduFarmBot, percebemos que algumas mudanças na especificação original devem ser feitas:

Exibir:

O display LCD deve estar DESLIGADO por padrão e sempre que uma leitura de sensores for necessária, podemos ativá-lo manualmente. Esta condição foi implementada no código e o botão "Sensors Read" deve ser usado como no modo "toggle" para LIGAR / DESLIGAR o LCD a qualquer momento. LIGAR ou DESLIGAR a tela irá atualizar as leituras dos sensores para exibição, mas não usadas pelo ArduFarmBot em suas funções regulares.

Configuração inicial:

Quando o ArduFarmBot é ligado (ou redefinido), o LCD exibirá a "Configuração inicial". Para iniciar a execução do programa, deve-se pressionar o botão "Sensores". As informações iniciais (veja a foto acima) mostradas são:
  • Temperatura FRIA (ou seja, 12oC)
  • Umidade do solo SECO (ou seja, 30%)
  • Umidade do solo úmido (ou seja, 60%)
  • luz ESCURA (ou seja, 40%)
  • P_ON Tempo de bomba LIGADO (ou seja, 10s)
  • Tempo de SCAN para ler sensores (ou seja, 600s)
  • SW_Vertion (ou seja, 4.1)

Registro de log:

Para fins de auditoria, criamos um LOG com as leituras e atuações de nosso ArduFarmBot. Em cada ciclo de leitura, a função: storeDataLogEEPROM () É executado.
  / ******************************************* ********* Armazenamento de dados de log no 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 ++;}  

Conforme comentado na última etapa, o que será armazenado no Arduino EEPROM é o conteúdo, um pouco do array snsSts [] além do status da bomba e da lâmpada. Acima você pode ver o LOG no Monitor Serial.

Todo o código do ArduFarmBot foi dividido em arquivos diferentes para ser mais fácil de entender. Observe que 2 novos arquivos foram adicionados nesta segunda parte:
  • comunicação.ino (Funções específicas do ThingSpeak e ESP8266)
  • stationCredentials.h (ID do canal ThingSpeak e teclas específicas para gravação no canal)

Por último, mas não menos importante, uma vez que o código terminou com um tamanho razoável, decidimos armazenar os dados constantes na memória flash (programa) em vez de SRAM. Para isso, utilizamos a palavra-chave PROGMEM que é um modificador de variável. Por exemplo, em vez de usar:
  #define DHTPIN 5  

Nós costumavamos:
  const PROGMEM byte DHTPIN =5;  

A palavra-chave PROGMEN diz ao compilador "coloque esta informação na memória flash", em vez de na SRAM, onde ela normalmente iria. 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 Serial.Print () usadas para depuração durante o desenvolvimento. Você perceberá que o código utilizado por exemplo para mostrar o LOG no Monitor Serial estará comentado nos arquivos abaixo.

Abaixo você pode encontrar o código ArduFarmBot Arduino completo. Não se esqueça de alterar os dados fictícios em credentials.h com seu ID de canal e chave de gravação. Também no communication.ino, use seu nome de usuário e senha reais para conectar o ESP 8266 na Internet.
FTUT5VIIT67U8ME.ino FWMIPSSIT67U8MG.ino FJPGZNKIT67U8MK.ino FQH3X9VIT67U8NA.ino F15MY4YIT67U8NB.ino FVU64X1IT67U8NC.h FZ057E3IT67U8P5.h





Etapa 9:a fazenda doméstica MJRovai


As fotos abaixo mostram fotos sequenciais de ArduFarmBot controlando minha primeira plantação de tomate.

A sequência de fotos abaixo, mostra a evolução do meu 2º plantio desde o plantio de sementes até o momento de selecionar as melhores plantas (cerca de 45 dias) e os transplantes das 6 melhores plantas.





Etapa 10:Conclusão


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

Como sempre, espero que este projeto possa ajudar outras pessoas a encontrar seu caminho no emocionante mundo da eletrônica, IoT e Robótica!

Em breve provavelmente publicaremos a terceira e última parte do nosso projeto que, espero, seja uma receita muito boa de macarrão com molho de tomate orgânico.

Aliás, na foto acima vocês podem ver os primeiros suspiros de vida na roça do Mauricio! And before you go, please give a look and the new ArduFarmBot, the book!, where I pack all project on a more friendly format:





ArduFarmBot, the Book!


"ArduFarmBot, the book" is also at Amazon.com! You can get it, by clicking hereThe book uses the electronic controller ArduFarmBot as a basis for teaching how to work in both HW and SW, with:
  • LCD and OLED type displays;
  • LEDs and buttons;
  • Activation of pumps and lamps via relays and
  • Sensors such as:DHT22 (temperature and relative air humidity), DS18B20 (soil temperature), YL69 (soil moisture) and LDR (luminosity).

All key stages of the project are documented in detail through explanatory texts, block diagrams, high-resolution color photos, electrical diagrams using Fritzing application, complete codes stored in GitHub and YouTube vídeos.

Two versions of the electronic controller ArduFarmBot are developed in detail in the book. From capture of data coming from a garden, such as air and soil temperature, relative humidity, soil moisture and luminosity, the ArduFarmBot helps to control when a crop should receive heat and water. Control will happen automatically, locally and remotely via internet. The book is divided into 3 parts. In the first part, the Arduino Nano is the starting point for development of a local version of ArduFarmBot , that can be controlled both, manually and automatically.

In the second part, the book dives into automation design, introducing remote operation through the creation of a webpage. The ESP8266-01 is used for Wi-Fi connection, sending data to an important web service in the field of IoT, the ThingSpeak.com .

In the third part, a second version of ArduFarmBot is developed, introducing the NodeMCU ESP8266-12E , a powerful and versatile IoT device, which replaces both the Arduino Nano and the ESP8266-01 , used in the earlier parts of the book.

In this last part of the book, a new service platform of the IoT universe, the Blynk , is also explored.

Download the book, give it a review and please use the message board here to give us any comment, suggestion or critic!

For more projects, please visit my blog:MJRoBot.org

Saludos from the south of the world!

See you at my next project!

Obrigada

Marcelo

Código

  • Code snippet #1
  • Snippet de código # 2
  • Code snippet #3
  • Code snippet #4
  • Snippet de código # 5
  • Code snippet #6
  • Code snippet #9
  • Code snippet #10
  • Code snippet #11
  • Code snippet #12
  • Code snippet #13
  • Code snippet #14
  • Code snippet #15
Code snippet #1Plain text
/**************************************************** Reset funtion to accept communication****************************************************/void reset8266(void){ pinMode(CH_PD, OUTPUT); digitalWrite(CH_PD, LOW); atraso (300); digitalWrite(CH_PD, HIGH); Serial.print("8266 reset OK"); lcd.clear (); lcd.println("8266 reset OK ");}
Snippet de código # 2 Texto simples
/**************************************************** 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");}
Code snippet #3Plain text
/**************************************************** 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;}
Code snippet #4Plain text
/**************************************************** 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();}
Snippet de código # 5 Texto simples
/**************************************************** Start communication with ThingSpeak.com****************************************************/void startThingSpeakCmd(void){ cmd ="AT+CIPSTART=\"TCP\",\""; cmd +=IP; cmd +="\",80"; esp8266.println(cmd); atraso (2000); if(esp8266.find("Error")) { Serial.println("ESP8266 START ERROR"); Retorna; } Serial.println("Thinkspeak Comm Started"); cmd ="";}
Code snippet #6Plain text
/*************************************************** * 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); atraso (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"; }} 
Code snippet #9Plain text
/**************************************************** 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;}
Code snippet #10Plain text
/**************************************************** 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); } 
Code snippet #11Plain text
/**************************************************** 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);}
Code snippet #12Plain text
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;
Code snippet #13Plain text
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(); }} 
Code snippet #14Plain text
 // +---SOIL----+-LIGHT-+---TEMP---+---ACTUAT----+ // SL SM SH LL LH TL TM TH Pump Lampboolean 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 }, };
Code snippet #15Plain text
/**************************************************** 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++;} 
ArduFarmBot GitHub
https://github.com/Mjrovai/ArduFarmBot

Esquemas

ardufarmbot_qpNcBDX6Jr.fzz

Processo de manufatura

  1. Tendências de implementação de IoT
  2. 6-Shooter:Estação de Mistura de Bebidas Arduino
  3. Sensor de temperatura múltipla
  4. MotionSense
  5. Impressora 3D Segurança contra incêndio
  6. IoT Gauge com Arduino, Yaler e IFTTT
  7. Levitação eletromagnética repulsiva Arduino
  8. Controle Remoto Gripper Bot
  9. Registrador de dados do balão meteorológico Arduino
  10. CoroFence - Detector Térmico🖖