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

21 21UTC setembro 21UTC 2016 — 4 Comentários

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

Anúncios

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

  1. 

    Marcelo, projeto muito bem documentado e detalhado! A edição de imagens é muito bem feita.
    Qual programa tem usado ? Gostei demais. Abração. Gustavo Murta

    Curtir

Trackbacks e Pingbacks:

  1. “ArduFarmBot 2” – Sistema automático para irrigação e calor, agora com o NodeMCU e Blynk – MJRoBot.org - fevereiro 21, 2017

    […] 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, […]

    Curtir

  2. ArduFarmBot: Controlando um tomateiro com a ajuda de um Arduino e Internet das coisas (IoT) – MJRoBot.org - janeiro 30, 2017

    […] você gostou do projeto, não deixe de ver a segunda parte de nosso projeto: ArduFarmBot: Part 2 – “Estação Remota” – IoT, que mostrará a conexão com a internet e sua aplicação na plantação de […]

    Curtir

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s