<

Exibir mensagens

Esta seção lhe permite ver todas as mensagens deste membro. Note que você só pode ver as mensagens das áreas às quais você tem acesso.


Tópicos - Ivanov

Páginas: [1] 2 3 4
1
Projetos / Como ligar um LDR ao Arduino? [Video]
« Online: Dezembro 08, 2017, 09:27:35 am »
Como ligar um LDR ao Arduino? [Video]



Hoje vamos dar inicio à nossa secção de vídeos que preparamos para ajudar os nossos visitantes a se iniciarem no mundo do Arduino. Vamos começar por demonstrar como controlar a iluminação através do sensor de luz, o LDR. Após verem o video poderão realizar passo-a-passo o mesmo projeto em vossa casa. Abaixo poderão encontrar a lista de materiais utilizados, esquema de montagem e o código para o Arduino.



 


# Esquema de montagem:



# Código Utilizado:


int led = 2;
int LDR = A2;
int luminusidade;

void setup(){
pinMode(led, OUTPUT);
pinMode(LDR, INPUT);
}

void loop(){
luminusidade=analogRead(LDR);
if(luminusidade < 400){
digitalWrite(led, HIGH);
}
else{
digitalWrite(led, LOW);
}
delay(100);
}

 


# Lista de Material:



  • Arduino Nano

  • Led

  • Breadboard

  • Resistências

  • LDR (Sensor de luminosidade)

  • Kit Arduino Iniciação (opcional)


2
Projetos / Projetos do INETE com Arduino
« Online: Dezembro 08, 2017, 09:27:28 am »
Projetos do INETE com Arduino



Como podemos ver já existem várias escolas a adoptar o Arduino como ferramenta base para a construção de diversos projetos em conjunto com os seus alunos. Sendo uma ferramenta bastante dinâmica, o Arduino permite desenvolver soluções para resolver vários problemas que muitos de nós enfrenta no dia-a-dia.


De seguida podemos ver alguns projetos interessantes criados pelos alunos do INETE:



 





3
Projetos / Qual a diferença entre Buzzer Ativo vs Buzzer Passivo
« Online: Dezembro 08, 2017, 09:27:17 am »
Qual a diferença entre Buzzer Ativo vs Buzzer Passivo



O Buzzer Ativo e Buzzer Passivo visualmente eles podem ser idênticos, mas o funcionamento é muito diferente. O buzzer ativo é um produto mais complexo, de uso mais simples. Tem incorporado o circuito oscilador que produz o som e só requer energizar. O buzzer passivo é apenas um transdutor. Como um “alto falante” em miniatura.


Buzzer ativo




  • Mais fácil de testar e usar: ao energizar já apita continuamente.

  • Não é o mais apropriado para criar melodias. É mais apropriado para alarmes/avisos/sinalização.

  • Por norma a traseira do buzzer é lacrada com um pino maior (VCC) e outro menor (GND).


 


Buzzer passivo




  • Difícil de testar e usar: ao energizar só ouve um débil estalo. Parece um buzzer ativo com defeito.

  • É o mais apropriado para fazer melodias, porque tem o controlo sobre os tons gerados.

  • Por norma a traseira tem o PCB à mostra com os pinos do mesmo tamanho.


4
Projetos / Robot controlado por voz via WiFi
« Online: Dezembro 08, 2017, 09:27:10 am »
Robot controlado por voz via WiFi



O diagrama de blocos abaixo nos dá uma geral sobre o projeto que desenvolveremos aqui:


WiFi_Robot_Block_Diagram


e o filme mostra-nos como ficará o projeto:


Por favor, considere que um de meus motores estava com muito pouco torque. Apesar de o resultado parecer estranho, o projeto funciona a contento. Assim que mudar o motor, atualizarei o vídeo. Obrigado.




1: Lista de materiais (BoM)



 



  1. NodeMCU ESP8266-12E

  2. 400-point Experiment Breadboard Breadboard

  3. H-Bridge L293D

  4. Motor Robot Car Chassis Kit

  5. Male-Female Dupont Cables

  6. Portable Charger 5VDC 3000mAh Power Bank

  7. Bateria 9V DC


….. e qualquer telefone ou tablet Android!






2: A Ponte-H L293D


L293D





Para “drivar” os motores usaremos o L293D.





De acordo com seu Datasheet, o L293D é um controlador do tipo half-H quádruplo de alta corrente. O L293D foi projetado para fornecer correntes bidirecionais de até 600 mA em tensões variando de 4,5 V a 36 V.


Usaremos o CI L293D diretamente com o NodeMCU, em vez de um Shield, como se vê mais comumente em projetos no mercado.


Pois bem, nosso robot terá duas rodas, acionadas por 2 motores DC:



  • Motor esquerdo (LEFT)

  • Motor direito (RIGHT)NodeMCU_L293D_Block_Diagram

  • Ligaremos os motores ao L293D e este ao NodeMCU, como mostra o diagrama em blocos anterior, onde 6 de seus GPIOs comandarão esses motores.





 
int rightMotor2 = 13;   // D7 - right Motor -
int rightMotor1 = 15;   // D8 - right Motor +
int leftMotor2 = 0;     // D3 - left Motor -
int leftMotor1 = 2;     // D4 - left Motor +
int eneLeftMotor = 12;  // D6 - enable Motor Left
int eneRightMotor = 14; // D5 - enable Motor Right
 

Por exemplo, para mover o robô para a frente,  girando o motor esquerdo (LEFT) no sentido apropriado, você deve colocar:



  • HIGH no pino D4 (motor esquerdo +) e

  • LOW no pino D3 (motor esquerdo -)


Para o motor direito (RIGHT) você deve fazer o oposto:



  • HIGH no pino D8 (motor direito +) e

  • LOW no pino D7 (motor esquerdo -)

  • The H-Bridge L293D

  • Devido à maneira como meus motores são montados, a combinação acima irá girar ambos motores no mesmo sentido, “empurrando” o robot para a frente.

  • Robot direction.jpg


  • O diagrama acima define (ou melhor, convenciona) como o robot deverá se mover. Isso é importante para a definição adequada de suas variáveis.


    Para controlar a H-Bridge corretamente, você também deverá trabalhar com os pinos de habilitação (“enable”). No exemplo anterior onde o robô se move para a frente, além dos 4 GPIOs discutidos, o robot só funcionaia se os pinos de habilitação (eneLeftMotor e eneRightMotor) estiverem ambos em HIGH. Poderá conectar esses pinos do L293D (1 e 9) diretamente a + VCC e esquecê-los. Eu não gosto disso, porque se necessitar por exemplo, parar rapidamente seu robot, esses pinos deveriam estar em necessariamente em LOW. Além disso, associar os pinos de habilitação a saídas PWM do NodeMCU, permitirá também controlar a velocidade do motor. Em nosso exemplo, usaremos estes pinos apenas com valores digitais tais como HIGH e LOW, o que ajustará a velocidade para MAX e ZERO, respectivamente.


    Asim, para se criar uma função que conduza nosso robot para a frente, devemos escrever um código como este:



 
void forwardMotor(void)  
{
  digitalWrite(eneLeftMotor,HIGH);
  digitalWrite(eneRightMotor,HIGH);
   
  digitalWrite(leftMotor1,HIGH);
  digitalWrite(leftMotor2,LOW);
  digitalWrite(rightMotor1,HIGH);
  digitalWrite(rightMotor2,LOW);
}
 

3: Movendo o robot noutras direções





Na etapa anterior, aprendemos como podemos mover o robot para a frente, pensemos agora como movê-lo em outras direções.


Definamos 5 possíveis comandos:


  1. STOP: Pare

  2. LEFT: Vire à esquerda

  3. RIGHT: Vire à direita

  4. REVERSE: Dê marcha à ré

  5. FORWARD: Vá para a frente


O primeiro comando “STOP” é simples de realizar. Todas as entradas da H-Bridge devem estar em LOW, desta forma os motores não se moverão:





 
void stopMotor(void)  
{
  digitalWrite(eneLeftMotor,LOW);
  digitalWrite(eneRightMotor,LOW);

  digitalWrite(leftMotor1,LOW);
  digitalWrite(leftMotor2,LOW);
  digitalWrite(rightMotor1,LOW);
  digitalWrite(rightMotor2,LOW);
}
 

Da mesma forma pensemos em fazer o robot tomar outra direção, digamos que “virar à ESQUERDA”. Considere que o robot está indo para a frente, se queremos virar à esquerda podemos pensar em duas situações:



  1. Parar o motor ESQUERDO, mantendo o motor DIREITO no sentido a frente (Forward): o robot executará uma trajetória de arco para a esquerda

  2. Inverter o sentido do motor ESQUERDO, mantendo o motor DIREITO no sentido a frente (Forward): o robot irá girar sobre seu eixo para a esquerda.


Implementemos o caso 2 acima:


 
void leftMotor(void)  
{
  digitalWrite(eneLeftMotor,HIGH);
  digitalWrite(eneRightMotor,HIGH);
 
  digitalWrite(leftMotor1,LOW);
  digitalWrite(leftMotor2,HIGH);
  digitalWrite(rightMotor1,HIGH);
  digitalWrite(rightMotor2,LOW);
}
 

Os demais comandos seguirão a mesma lógica, como ilustra a tabela abiaxo:


Moving the Robot Around


4: Completando o HW


Completing the HW


Siga o diagrama acima e complete o HW de seu Robot.


Você poderá executar alguns testes simples para verificar que seu código está OK.  Para isto, introduziremos um “botão” para iniciar o seu robot. Vamos instalá-lo na porta D0 do NodeMCU como mostrado no diagrama elétrico anterior.


Você poderá utilizar o programa abaixo para testar os movimentos do seu robot:


 
// Set Motor Control Pins
int rightMotor2 = 13;    // D7 - right Motor -
int rightMotor1 = 15;    // D8 - right Motor +
int leftMotor2 = 0;    // D3 - left Motor -
int leftMotor1 = 2;    // D4 - left Motor +
int eneLeftMotor = 12;  // D6 - enable Mortor Left
int eneRightMotor = 14; // D5 - enable Mortor Right

int buttonPin = 16; // D0

void setup()
{
  Serial.begin(115200);

  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(eneLeftMotor, OUTPUT);
  pinMode(eneRightMotor, OUTPUT);
  pinMode(leftMotor1, OUTPUT);
  pinMode(leftMotor2, OUTPUT);  
  pinMode(rightMotor1, OUTPUT);  
  pinMode(rightMotor2, OUTPUT);  

  digitalWrite(eneLeftMotor,LOW);
  digitalWrite(eneRightMotor,LOW);
  digitalWrite(leftMotor1,LOW);
  digitalWrite(leftMotor2,LOW);
  digitalWrite(rightMotor1,LOW);
  digitalWrite(rightMotor2,LOW);
     
  while (digitalRead(buttonPin))  // Wait for button to be pressed to move on
  {  
  }
}

void loop()
{
  forwardMotor();
  delay (5000);
  stopMotor();
  delay (200);
  leftMotor();
  delay (3000);
  stopMotor();
  delay (200);
  forwardMotor();
  delay (5000);
  stopMotor();
  delay (200);
  rightMotor();
  delay (3000);
  stopMotor();
  delay (200);
  reverseMotor();
  delay (5000);
  stopMotor();
  delay (200);
}

/* command motor forward */
void forwardMotor(void)  
{
  digitalWrite(eneLeftMotor,HIGH);
  digitalWrite(eneRightMotor,HIGH);
   
  digitalWrite(leftMotor1,HIGH);
  digitalWrite(leftMotor2,LOW);
  digitalWrite(rightMotor1,HIGH);
  digitalWrite(rightMotor2,LOW);
}

/* command motor backward */
void reverseMotor(void)  
{
  digitalWrite(eneLeftMotor,HIGH);
  digitalWrite(eneRightMotor,HIGH);
 
  digitalWrite(leftMotor1,LOW);
  digitalWrite(leftMotor2,HIGH);
  digitalWrite(rightMotor1,LOW);
  digitalWrite(rightMotor2,HIGH);
}

/* command motor turn left */
void leftMotor(void)  
{
  digitalWrite(eneLeftMotor,HIGH);
  digitalWrite(eneRightMotor,HIGH);
 
  digitalWrite(leftMotor1,LOW);
  digitalWrite(leftMotor2,HIGH);
  digitalWrite(rightMotor1,HIGH);
  digitalWrite(rightMotor2,LOW);
}

/* command motor turn right */
void rightMotor(void)  
{
  digitalWrite(eneLeftMotor,HIGH);
  digitalWrite(eneRightMotor,HIGH);
 
  digitalWrite(leftMotor1,HIGH);
  digitalWrite(leftMotor2,LOW);
  digitalWrite(rightMotor1,LOW);
  digitalWrite(rightMotor2,HIGH);
}

/* command motor stop */
void stopMotor(void)  
{
  digitalWrite(eneLeftMotor,LOW);
  digitalWrite(eneRightMotor,LOW);

  digitalWrite(leftMotor1,LOW);
  digitalWrite(leftMotor2,LOW);
  digitalWrite(rightMotor1,LOW);
  digitalWrite(rightMotor2,LOW);
}
 



Quando você pressionar o botão, o robot começará a fazer os movimentos definidos no loop (). Os movimentos continuarão até que você pressione “Reset” no NodeMCU. Pressionando o botão “verde” novamente, o ciclo se repetirá.


O código acima poderá ser baixado deste GitHub:


WiFi_Robot_NodeMCU_Android_Voice_Motor_tests






5: Montando o corpo do robot


body Assembly



  1. Use o Kit: Chassis, 2 Rodas, 2 Motores DC, 1 roda solta (coaster)

  2. Solde 2 fios de 10 cm (Vermelho e Preto) em cada polo do motor

  3. Fixe os motores ao chassi como mostrado na foto acima

  4. Monte o coaster

  5. Conecte os fios do motor à eletrônica (L293D)

  6. Fixe a bateria de 9V ao chassi

  7. Fixe a bateria de 5V sob o chassi


O robot deverá ficar com essa cara:


Body Final


6: Conectando o NodeMCU ao seu WiFi local



Conectemos o NodeMCU ao WiFi local, verificando seu endereço IP. Para isso, podemos utilizar o programa abaixo:




 
#include
WiFiClient client;
WiFiServer server(80);
const char* ssid = "YOUR SSID";
const char* password = "YOUR PASSWORD";

void setup()
{
  Serial.begin(115200);
  connectWiFi();
  server.begin();
}

void loop()
{
}

/* connecting WiFi */
void connectWiFi()
{
  Serial.println("Connecting to WIFI");
  WiFi.begin(ssid, password);
  while ((!(WiFi.status() == WL_CONNECTED)))
  {
    delay(300);
    Serial.print("..");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("NodeMCU Local IP is : ");
  Serial.print((WiFi.localIP()));
}
 

No monitor serial voce poderá observar o endereço IP dinâmico designado pelo Modem ao seu NodeMCU.


Connecting the NodeMCU to Local WiFi




Tome nota deste endereço de IP. Precisaremos dele para conectar o App Android.


O código acima poderá ser baixado deste GitHub:


NodeMCU_Connection_Test_EXT






7: Completando o código fonte para o NodeMCU



Para que nosso robô se mova, o NodeMCU deverá receber comandos provenientes do dispositivo Android. Para tal, definamos uma variável para receber estes comandos:


String  command ="";






Por exemplo, se a aplicação Android enviar como um comando: “forward” (a frente), o robot deverá avançar, invocando-se a função forwardMotor(). Veja abaixo:


 
if (command == "forward")
{
  forwardMotor();
}
 

O mesmo conceito deverá ser aplicado a todo os demais comandos e funções associadas tal como vimos no item 4:



  1. STOP: Pare

  2. LEFT: Vire à esquerda

  3. RIGHT: Vire à direita

  4. REVERSE: Dê marcha à ré

  5. FORWARD: Vá para a frente


Descarregue o código completo: WiFi_Robot_NodeMCU_Android_Voice_EXT deste GitHub.


Entre com as credenciais de sua rede local:


 


const char* ssid = "YOUR SSID";
const char* password = "YOUR PASSWORD";




Carregue o código em seu NodeMCU e pronto! Você poderá verificar no Monitor Serial se o programa está em execução. Deixe o programa em execução para podermos testar o o aplicativo a ser desenvolvido na próxima etapa.





8: A App Android : “Designer Tab”


The Android App:


Usaremos o MIT App Inventor para o desenvolvimento de nossa App Android.


Principais componentes da Screen 1 (veja a foto anterior):



  • User Interface:

    • Input of IP Address

      • TextBox named “IP_Address”



    • 5 Command Buttons:

      • forward

      • reverse

      • right

      • left

      • stop



    • Voice Input Button

      • Voice_Input





  • Non Visible Components:

    • Web1

    • SpeachRecognizer1

    • TextToSpeach1



  • Other:

    • Text Box:

      • Speach_To_Text



    • Label:

      • Comm_Status

      • Screenshot_2017-04-02-14-36-34


      • 9: A App Android: Botões


        The Android App: Buttons





      • Na Tab “Blocks”, deveremos criar 5 Botões, um para cada comando. Todos eles seguirão a estrutura dos blocos acima.


        Estes blocos serão chamados quando o botão “forward” (“botão com a seta para cima”) é pressionado.


        Quando você clicar no botão, 3 ações serão executadas:



        1. Um comando será enviado no formato: http: / ip_address * / forward

        2. Um “eco” no mesmo formato é esperado

        3. Uma “mensagem” audível será executada pela App: no caso: “forward”


        * O IP_Address será a que você digitar no seu App. Por exemplo, se o IP address é 10.1.0.3, a mensagem completa seria: http: /10.0.1.3/forward


        Poderá utilizar qualquer mensagem, ou até mesmo deixar a mensagem vazia.






        10: A App Android: Reconhecimento de voz


        The Android App: Voice Recognition


         




      • Os blocos acima mostram o código de reconhecimento de voz para o nosso aplicativo.Note que, para qualquer comando de voz inserido, o resultado será um comando em letras minúsculas. Isso facilitará a descodificação do comando pelo NodeMCU.Por exemplo, se você deseja mover o robô para a frente, uma palavra ou sentença deverá ser enviada para ser interpretada pelo NodeMCU. No exemplo abaixo, o código reconheceria qualquer uma das palavras: “forward”, “frente” ou “a frente “.







 
if (command == "forward" || command == "frente" || command == "a frente")  
{
  forwardMotor();
}
 



Assim, por exemplo quando digo “frente”, a App enviará : http: / 10.0.1.10/frente e o NodeMCU tomará o que é recebido após o “/”,  a palavra “frente” que será interpretada como um comando do tipo “forward”. Com este comando, a função forwardMotor () será invocada.





11: A App Android: Manipulação de erros


The Android App: Error Manipulation


Se ocorrer um erro, por exemplo, quando você diz um comando de voz não reconhecido pelo NodeMCU, o bloco acima irá gravar os detalhes do erro na última linha (Comm_Status) do App, conforme mostrado abaixo:


Screenshot_2017-04-02-14-36-50


12: Teste final


Final Test


Você poderá criar seu aplicativo passo a passo, como mostrado nas etapas anteriores ou fazer o upload do meu projeto completo (.aia) no MIT App Inventor, modificando-o de acordo a suas necessidades. Além disso, caso não tenha experiência no desenvolvimento de aplicativos para Android, poderá executar o arquivo .apk diretamente em seu dispositivo Android.


Ambos, os arquivos .aia e .apk podem ser baixados de meu GitHub:


WiFi_Voice_Robot_Ctrl_V2.aia


WiFi_Voice_Robot_Ctrl_V2.apk


O video abaixo mostra alguns testes de motores utilizando-se do App:





5
O IoT feito simples: Monitorizando a temperatura a partir de qualquer lugar



É incrível como hoje em dia podemos montar rapidamente um projeto de IoT utilizando-se apenas de um “chip” de uns poucos euros e um aplicativo carregado em seu smartphone.


Neste tutorial também aprenderemos sobre um sensor digital de temperatura confiável e muito fácil de usar, o DS18B20.



Como mostrado no diagrama de bloco acima, os dados recolhidos pelo sensor serão enviados à Internet com a ajuda de um NodeMCU ESP8266-E e monitorizados num telemóvel ou tablet utilizando-se o aplicativo Blynk.


1: Lista de Material



  • NodeMCU ESP 12-E



  • DS18B20 Temperature Sensor



  • Resistor 4.7K Ohms



2: DS18B20 Sensor Digital de Temperatura









Usaremos neste tutorial, uma versão à prova de agua do sensor DS18B20. Esta configuração é  muito útil para se medir temperaturas de maneira remota em condições de humidade, por exemplo em recolha de dados de solo. O sensor é isolado e pode ser usado em até 125oC (Adafrut não recomenda usá-lo acima dos 100oC devido a a capa de PVC  utilizada em seu cabo).


O DS18B20 é um sensor do tipo digital, o que o torna util para uso mesmo em longas distâncias! Estes sensores digitais de temperatura  “1-Wire” são bastante precisos (± 0,5 ° C em grande parte da faixa) e podem fornecer até 12 bits de precisão a partir do conversor digital-analógico integrado. Eles funcionam muito bem com micro-controladores como o NodeMCU ou Arduino, utilizando-se de apenas um único pino digital. Você poderá até mesmo conectar-lo a vários outros sensores no mesmo pino, pois cada um dos sensores possui um único ID de 64 bits gravado de fábrica para diferenciá-los.


O sensor funciona de 3.0 a 5.0V, o que significa que ele pode ser alimentado diretamente a partir de um dos pinos de 3.3V do NodeMCU.


O Sensor possui 3 fios:



  • Preto: GND



  • Vermelho: VCC



  • Amarelo: 1-Wire Data


No link ao lado, voce encontrará a especificação completa: DS18B20 Datasheet



3: Conectando o sensor ao NodeMCU


Conecte os 3 fios do sensor NodeMCU como mostrado no diagrama abaixo:




  • Vermelho ==> 3.3V



  • Preto ==> GND



  • Amarelo ==> D4


Insira o NodeMCU, de forma que seus pinos correspondam ao diagrama elétrico acima. Observe que o chip pressionará o cabo do sensor, ajudando a manter os contatos do sensor no lugar.



introduza uma resistência de 4.7K ohms entre VCC (3.3V) e Data (D4)



4: Instalando as bibliotecas apropriadas


Para o uso apropriado e de maneira simplificada do DS18B20, será necessária a instalação de 2 novas bibliotecas:




Instale ambas bibliotecas em seu diretório de Libraries do IDE


Observe que a biblioteca OneWire DEVE ser a versão modificada para ser usada com o ESP8266, caso contrário receberá um erro durante a compilação. Você encontrará a última versão no link acima ou fazendo o download do arquivo zip abaixo:




5: Testando o sensor









 
/**************************************************************
 * IoT Temperature Monitor with Blynk
 * Blynk library is licensed under MIT license
 * This example code is in public domain.
 *
 * Developed by Marcelo Rovai - 05 January 2017
 **************************************************************/

/* ESP & Blynk */
#include
#include
#define BLYNK_PRINT Serial // Comment this out to disable prints and save space
char auth[] = "YOUR AUTH CODE HERE";

/* WiFi credentials */
char ssid[] = "YOUR SSID";
char pass[] = "YOUR PASSWORD";

/* TIMER */
#include
SimpleTimer timer;

/* DS18B20 Temperature Sensor */
#include
#include
#define ONE_WIRE_BUS 2 // DS18B20 on arduino pin2 corresponds to D4 on physical board
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);
float temp;

void setup()
{
 Serial.begin(115200);
 Blynk.begin(auth, ssid, pass);
 DS18B20.begin();
 timer.setInterval(1000L, getSendData);
}

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

/***************************************************
 * Send Sensor data to Blynk
 **************************************************/
void getSendData()
{
 DS18B20.requestTemperatures();
 temp = DS18B20.getTempCByIndex(0);
 Serial.println(temp);
 Blynk.virtualWrite(10, temp); //virtual pin V10
}

 

Assim que o código for carregado e estiver em execução, verifique a aplicação BLYNK. Esta deverá também estar em execução.


Abaixo do código completo do Arduino para o seu projeto:


F05G780IXKPYLO4.ino



6
Projetos / IoT: Sensor de movimento com o NodeMCU e BLYNK
« Online: Dezembro 08, 2017, 09:25:35 am »
IoT: Sensor de movimento com o NodeMCU e BLYNK



Simples tutorial para demonstrar a facilidade de implementação de um projeto do tipo “Internet das Coisas” (IoT) com o NodeMCU e o Blynk.Toda vez que um movimento é detectado pelo sensor, uma mensagem fornecida pelo aplicativo Blynk é enviada para um smartphone.



Step 1: Principais componentes



  • NodeMCU ESP12-E



  • Motion Sensor HC-SR501



  • Resistor (1K, 2.2K and 330ohm)



  • LED



  • Breadboard



  • Cables



Step 2: O HC-SR501 “Passive Infrared (PIR) Motion Sensor”



Este módulo de sensor de movimento utiliza-se do sensor passivo de sinal infravermelho  LHI778 e o do circuito integrado BISS0001 para controlar como o “movimento deve ser detectado”.



O módulo possui sensibilidade ajustável que permite uma faixa de detecção de movimento de 3 a 7 metros.



O módulo também inclui ajustes de atraso de tempo e seleção de gatilho que permitem ajustes finos dentro de sua aplicação.


fkscpzbivo85exc-large


f19wasdivo85ey1-large


O link abaixo nos fornece mais detalhes do funcionamanto do sensor:


Arduino HC-SR501 Motion Sensor Tutorial



Step 3: O HW



O HW é muito simples. O sensor tem 3 pinos (+Power, GND e Saída).


É importante lembrar que a saída do HC-SR501 gera um sinal lógico de + 3.3V (ALTO) ou 0V (LOW), o qual É COMPATÍVEL com os níveis de entrada do NodeMCU, que também funciona com o nível 3.3V. Eu mantive a circuito com um conversor de nível para garantir caso seja utilizado algum outro sensor  com saída 5V.


Assim, você precisará de um divisor de tensão para converter os níveis de sinal (veja o diagrama elétrico acima).



  • Saída do HC-SR501 ==> para a entrada do divisor de tensão

  • NodeMCU Pin D1 (GPIO 5) ==> para o ponto médio do Divisor de Tensão


Também incluíremos um LED no pino D7 (GPIO13), para uma visualização local.



Step 4: Testando o sensor


Primeiramente faremos um programinha simples para testar e calibrar o sensor.


Carregue o código abaixo no Arduino IDE:


 
/* HC-SR501 Motion Detector */
#define ledPin D7 // Red LED
#define pirPin D1 // Input for HC-SR501

int pirValue; // variable to store read PIR Value

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(pirPin, INPUT);
  digitalWrite(ledPin, LOW);
}

void loop()
{
  pirValue = digitalRead(pirPin);
  digitalWrite(ledPin, pirValue);
}
 

Ao fazer um movimento na frente do sensor, você verá o LED vermelho acender. Você poderá usar o código acima para ajustes no sensor, se necessário.


Se você não sabe como preparar o IDE do arduino para trabalhar com o NodeMCU, por favor de uma olhadinha em meu tutorial:


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



Step 5: Incluindo o BLYNK



Siga os Passos abaixo::



  • Crie um  New Project.



  • Defina um nome para o projeto (em meu caso: “Motion Detector“)




    • Selecione NodeMCU como HW Model



    • Copie o  AUTH TOKEN para ser adicionado ao seu código do IDE (o melhor é enviar-lo para seu email).



    • Inclua o “Widget”:  Push Notification.


    • Pressione “Play” (o triangulo no canto superior direito)

    • fyieb1nivo85k5p-large

    • Naturalmente o aplicativo Blynk nesse ponto irá informar que o NodeMCU está off-line. antes de rodar o aplicativo Blynk, o código deve ser carregado e iniciado no módulo NodeMCU. Abaixo o código a ser ingressado no Arduino IDE:




 
/**************************************************************
 * IoT Motion Detector with Blynk
 * Blynk library is licensed under MIT license
 * This example code is in public domain.
 *
 * Developed by Marcelo Rovai - 30 November 2016
 **************************************************************/
#include

#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space
#include
char auth[] = "YOUR AUTH CODE HERE";

/* WiFi credentials */
char ssid[] = "YOUR SSID";
char pass[] = "YOUR PASSWORD";

/* HC-SR501 Motion Detector */
#define ledPin D7
#define pirPin D1 // Input for HC-S501
int pirValue; // Place to store read PIR Value

void setup()
{
  Serial.begin(115200);
  delay(10);
  Blynk.begin(auth, ssid, pass);
  pinMode(ledPin, OUTPUT);
  pinMode(pirPin, INPUT);
  digitalWrite(ledPin, LOW);
}

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

/***************************************************
 * Get PIR data
 **************************************************/
void getPirValue(void)
{
  pirValue = digitalRead(pirPin);
  if (pirValue)
  {
    Serial.println("==> Motion detected");
    Blynk.notify("T==> Motion detected");  
  }
  digitalWrite(ledPin, pirValue);
}
 

Assim que o código é carregado e executado, verifique a aplicação BLYNK, a qual também deverá estar funcionando.


Faça um movimento na frente do sensor, você deverá receber uma mensagem em seu celular como a mostrada abaixo:



Abaixo o código completo para ser executado no Arduino IDE (não se esqueça de entrar com seus dados):





Observação sobre o código:


Vale a pena comentar que os testes para este projeto foram executados somente em laboratório. Para projetos envolvendo sistemas caseiros de alarmes o código funcionaria sem problemas, mas se o sensor perceber muitas variações de movimento ao mesmo tempo, poderíamos chegar a ter problemas. Neste caso, uma solução envolvendo “SimpleTimer” seria o aconselhável.


O ideal quando se desenvolve projetos com o Blink é manter-se na função void loop() somente a função Blynk.run(), movendo-se a getPirValue() para dentro de uma função de timer, por exemplo: timer.setInterval(1000L, getPirValue);



7
Projetos / ArduFarmBot: Part 2 – “Estação Remota” – IoT
« Online: Dezembro 08, 2017, 09:25:24 am »
ArduFarmBot: Part 2 – “Estação Remota” – IoT




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


Na primeira parte do projeto, criamos uma estação local de controle e captura de informações, tais como temperatura, humidade relativa do ar, luminosidade e humidade 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, vamos implementar uma abordagem “IoT” onde a”intervenção manual” também poderá ser feita remotamente via Internet. O diagrama de blocos mostra como faremos isso:



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


Lista de materiais


Arduino Nano

Temperature and Humidity Sensor DHT22 ou DHT11

Luminosity Sensor – AD-018 Photo resistor module. ou equivalente

2X Soil Moisture Sensor –  (Opcional, pode ser do tipo “caseiro -DIY”)

LCD I2C 20X4

LEDs (1X)

Esp8266 Serial Wifi Wireless Transceiver Module Esp-01

Active Buzzer – Ky-12 ou equivalente

2 X 5v Relay Module

Jump wires

Resistor 10KOhms

Resistor 2.2K Ohms

Resistor 1.0K Ohms

Resistor 220 Ohms

Arduino Nano Shield (“Funduino”)

Membrane keyboard (4 Keys)

Caixa Plástica


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.



O único cuidado que 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 nivelador 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”.




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



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


NOTA: Se deseja se conectar o “Buzzer”, devera fazê-lo no pino D17 (o mesmo que o pino A3). É bom ter um alarme sonoro quando ocorra um erro de comunicação. Eu usei-o 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:


ESP8266_test_Set_up.ino


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
", 2000, DEBUG); // reset
  sendData("AT+CWJAP="USERNAME","PASSWORD"
", 2000, DEBUG); //Connect network
  delay(3000);
  sendData("AT+CWMODE=1
", 1000, DEBUG);
  sendData("AT+CIFSR
", 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, deve ver pelo monitor serial, mensagens semelhantes como as de abaixo:



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 += "
";

  sendThingSpeakCmd();
}

A fim de enviar esses dados, a primeira coisa a fazer é iniciar a comunicação com o ThingSpeak.com. Faremos isso, usando a 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("
");
      if (line.length() == 1)
      { //actual content starts after empty line (that has length 1)
        messageBody = esp8266.readStringUntil("
");
        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 num tutorial muito bom desenvolvido por Michalis Vasilakis.

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


Comandando os atuadores a partir da web

Neste momento, estamos a descarregar (“Upload”) e a armazenar todos os dados recolhidos 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 baseado 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


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, 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:



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 += "
";

  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 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:


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 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 começar os 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, 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 a partir de lá.

  • Aproximadamente  a cada 10 minutos, vamos ler 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.


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();
  }
}

Implementação de uma página Web dedicada


Neste ponto o nosso ArduFarmBot está operacional e pode ser controlado a partir da web. Pode monitorizar 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 considerada “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, escolhi o Byethost, um site gratuito, muito fácil e simples para lidar com as suas páginas.


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 querer tomar algumas ações remotas independente do que está acontecendo localmente com plantação do seu tomate. Outra consideração é que 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 noutro projeto que funcionou bem! Deixo aqui como uma sugestão).


FQOK9ENIT653YX5


A Matriz Sensor-Atuador



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”.


Numa tabela 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 tabela Excel abaixo.


Na tabela Excel, existem duas Tabs. Uma com filtro como mostrado acima e outra que além da seleção, te permite obter o “código”binário que deverá ser carregado na variável da Matriz.



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.


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 acendê-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á:


/***************************************************
* 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:


Como já visto na parte 1, para facilidade de entendimento e desenvolvimento, o código para o ArduFarmBot foi dividido 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 por ficar 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. 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 usou para a depuração durante o desenvolvimento. Perceberá que o código usado por exemplo para mostrar o log no monitor serial estará todo “comentado” no código final.


Abaixo 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:



 


Preparando o reservatório de água:



Conectando a bomba da água:



Germinação (aproximadamente 45 dias):



Seleção melhores mudas e transplante :




8
Projetos / LaserCat – IoT com NodeMCU e Blynk
« Online: Dezembro 08, 2017, 09:24:51 am »
LaserCat – IoT com NodeMCU e Blynk



Este é um projeto muito simples, onde a ideia principal é explorar como controlar servos via internet. Para isso, usaremos uma grande dupla de componentes, o NodeMCU ESP12-E e um aplicativo Blynk.


O projeto foi baseado em um grande tutorial: Smartphone Controlled Cat Laser, desenvolvido usando-se um Arduino Uno conectado a um PC via Serial. Aqui porém, usaremos o NodeMCU, em um formato mais “portátil” utilizando-se WiFi e bateria.



IMPORTANTE: O apontador laser pode ser perigoso se apontado diretamente para os olhos. Proteja os seus olhos, o de animais e outras pessoas. Use com cuidado.


Abaixo, você poderá ver minha gatinha Cleo brincando com o laser:



Step 1: Os componentes principais:






Step 2: O mecanismo “Pan/Tilt” de posicionamento



Vamos construir um mecanismo de “Pan / Tilt” muito simples, montando os servos “um em cima do outro” como mostrado nas fotos abaixo:



  • O “Pan” Servo  é usado “como base”. Mantenha-o na vertical.



    • Fixe o “Tilt” Servo sobre a parte de movimento do “Pan” Servo  (na posição horizontal)



    • Fixe o ponteiro laser na parte movel do “Tilt” Servo como mostrado.


    • Note que usei algumas peças metálicas, aproveitadas de um brinquedo desmontado, como estrutura de base para o mecanismo “Pan / Tilt”. Você poderá utilizar outros tipos de estrutura, O importante é manter os movimentos horizontal e vertical.


      Step 3: O HW




    • O circuito elétrico é bem simples:


    • Antes de iniciar as conexões, leve em consideração que apesar do nodeMCU ser alimentado com 5V, ele funciona internamente com 3.3V (assim como seus pinos de I/O). Assim, os Servos não poderão ser alimentados a partir de uma das 3 saídas de 3.3V do NodeMCU. A exceção é o pino “Vin”, que pode tanto fornecer 5V para o breadboard “+ VCC rail”quanto alimentar o NodeMCU quando uma fonte externa é utilizada (como mostrado no diagrama elétrico abaixo).


    • O módulo laser deve ser alimentado com 5V, porém ele também funciona com 3.3V o  que faz com que a potência do laser seja menor e consequentemente, seu uso mais seguro.

      IMPORTANTE: O apontador laser pode ser perigoso se apontado diretamente para os olhos. Proteja os seus olhos, o de animais e outras pessoas. Use com cuidado.


      Observando atentamente o diagrama elétrico acima, execute as seguintes ligações:



      • Ligue o cabo de dados do servo Pan (eixo X) ao NodeMCU Pin D1 (note que todos os pinos digitais do NodeMCU são PWM)

      • Ligue os dados do servo Tilt (eixo “Y”) ao NodeMCU Pin D2

      • Ligue o pino “S” do ponteiro laser ao NodeMCU Pin D3

      • Ligue o pino “Vin” de NodeMCU ao “+ 5V Rail” do Breadboard

      • Conecte os pinos GND (comum ou terra) do NodeMCU, Servos e Ponteiro Laser ao “GND Rail” do Breadboard

      • Conecte os cabos de alimentação dos Servos ao  “+ 5V Rail” do Breadboard


       


      Step 4: O codigo


      Para o controle dos servos, usaremos a biblioteca do IDE: Servo.h, a qual gerará sinais PWM posicionando-os facilmente com entradas angulares.


      Uma vez que a base do projeto é usar o aplicativo BLYNK, o código torna-se muito simples. Devemos definir 4 variáveis virtuais:


      V0: “X position”


      V1: “Y position”


      V2: “Random or manual” operation


      V3: Laser ON/OFF command






 
BLYNK_WRITE(V0)
{
  xPotReading = param.asInt();
}
BLYNK_WRITE(V1)
{
  yPotReading = param.asInt();
}
BLYNK_WRITE(V2)
{
  randState = param.asInt();
}
BLYNK_WRITE(V4)
{
  laserState = param.asInt();
}
 

Se você não sabe como preparar o IDE do Arduino para trabalhar com o NodeMCU, por favor de uma olhadinha em meu tutorial:


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


Abaixo, o código completo. de uma passada de olhos nele. É muito fácil de entender.




Step 5: O “Blynk”




9
ArduFarmBot: Controlar um tomateiro com a ajuda de um Arduino e Internet das coisas (IoT)



O objectivo deste projecto criado a 4 mãos, é o de se conseguir uma plantação de tomates totalmente automatizada, onde também se pode monitorar pela internet informações tais como temperatura, humidade do solo, luminosidade, etc.


(A versão em inglês desse post pode ser encontrada aqui em meu blog: ArduFamBot ou em sua versão original no site do Instructables.com)


img_0508Neste tutorial desenvolveremos um controlador eletrônico (o “ArduFarmBot”) que a partir da captura de dados provenientes de uma plantação de tomates (vulgo tomateiro), tais como temperatura, umidade relativa do ar, luminosidade e umidade do solo, decidirá autonomamente a quantidade certa (e quando) o plantio deve receber calor e irrigação (água + nutrientes). Além disso, o ArduFarmBot permitirá a intervenção manual de um operador (tanto de forma local quanto remotamente via Internet), a fim de controlar o acionamento de uma bomba de água e de uma lâmpada elétrica (esta última para ser usada na geração de calor para as plantas).


Em suma, o ArduFarmBot receberá como entrada:



  • Sensores (dados analógicos):

    • Temperatura

    • Umidade do ar

    • Luminosidade

    • Umidade do solo




E fornecerá como saídas:



  • Atuadores:

    • Relé para controle de bomba

    • Relé para controlo da lâmpada



  • Sinalização (dados digitais):

    • Visual e sonoro para indicação de status / erro

    • Visual de Estado da bomba

    • Visual para o estado da lâmpada



  • Display dos dados

    • Todos os dados analógicos e digitais devem estar disponíveis para avaliação instantânea



  • Armazenamento de dados

    • Dados históricos deve ser de armazenamento remotamente na internet e opcionalmente também localmente (via cartão de memória).




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


NewBlockDiagram


O vídeo abaixo descreve os principais elementos utilizados no primeiro protótipo de laboratório usado para testes:


Neste segundo vídeo, mostramos como os comandos funcionarão em modo local e remotamente via Web page:



PARTE 1 – ESTAÇÃO LOCAL


O projeto será dividido em 3 partes:



  1. Estação local

  2. Estação Remota ( ESP8266, Thingspeak, criação da página web em HTML/CSS/JS, etc)

  3. Uso e Acompanhamento do ArduFarmBot em uma plantação real. 


Aqui nesta primeira parte, vamos explorar a estação local, desenvolvendo o HW e o SW para trabalhar com os sensores, atuadores, aprendendo como exibir dados, etc.


Abaixo o diagrama em blocos simplificado da versão 1 da estação local:


LocalStationBlockDiagram


1.1: Lista de Materiais


fullComponents


1.2: Instalação, programação e teste dos sensores


IMG_4702



SENSOR DE TEMPERATURA E HUMIDADE: DHT 22 (OR DHT11)



O primeiro sensor a ser testado e instalado é o DHT 22, um sensor digital de humidade relativa do ar e temperatura. Ele usa internamente um sensor capacitivo de humidade e um termistor para medir o ar circundante, gerando um sinal digital em sua saída de dados. 


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


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


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



  1. VCC (3 a 5V)

  2. saída de dados

  3. Não conectado

  4. GND (Terra)


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


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


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


 
 
/****************************************************************
 * DHT Sensor - Setup and Test
 * Based on the original code written by ladyada, public domain
 * MJRoBot 21Aug16
 ****************************************************************/
// Include DHT Library
#include

// Sensor defiitions
#define DHTPIN 5        // DHT data pin connected to Arduino pin 5
#define DHTTYPE DHT22   // DHT 22 (if your sensor is the DHT 11, only change this line by: #define DHTTYPE DHT11)

// Variables to be used by Sensor
float tempDHT; // on the final program we will use int insteady of float. No need for high precision measurements
float humDHT;
float hic; // only used here for testing purposes

// Initialize the DHT sensor
DHT dht(DHTPIN, DHTTYPE);

void setup()
{
  Serial.begin(9600);
  Serial.println("DHT 22 Setup & Test");
  dht.begin();
}

void loop()
{
  // Wait a few seconds between measurements.
  delay(2000);
 
  //Read temperature and humidity values from DHT sensor:
  tempDHT = dht.readTemperature();  
  humDHT = dht.readHumidity();

  // Check if any reads failed and exit early (to try again).
  if (isnan(humDHT) || isnan(tempDHT))
  {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(tempDHT, humDHT, false);
 
  // Show measurements at Serial monitor:
  Serial.print("   Temp DHT ==> ");
  Serial.print(tempDHT);
  Serial.print("oC  Hum DHT ==> ");
  Serial.print(humDHT);
  Serial.print("%  Heat index: ");
  Serial.print(hic);
  Serial.println(" oC ");
}
 

Sensor de Luminosidade (LDR)


Com o DHT funcionando, é hora de  instalar e testar o sensor de luminosidade. Para isso, podemos usar um simples LDR (Resistor variável com luz). Basicamente, o que se deve fazer é criar um divisor de tensão, onde um dos resistores é o LDR e o outro um fixo, sendo o “ponto médio do divisor” conectado a uma entrada analógica do Arduino. Desta forma, variando-se a luz, a resistência LDR variará proporcionalmente e por conseguinte , a tensão no ponto do meio do divisor também vai variar.


Em nosso projeto, por facilidade de instalação, usaremos um módulo LDR barato (KY18) o qual já possui o divisor de tensão integrado. O módulo tem 3 pinos ( “S” para dados; “+” para VCC e “-” para GND). O pino “S” será ligado ao pino analógico Ao do Arduino.  O “+” e “-” pinos devem ser ligadas, respectivamente, a 5 V e GND. Se o consumo de energia é uma preocupação, o “+” pode ser conectado a uma das saídas digitais do Arduino,  que deverá  ser colocada em “HIGH” alguns milésimos de segundo antes de se ler a tensão no pino A0, retornando para “LOW” depois disso.


A função getLumen (LDR_PIN) lerá algumas vezes a saída do sensor (poderia ser de 3, 10 ou mais, você decide o que é melhor para o seu caso) calculando a média dessas leituras (isso para diminuir o risco que uma uma única leitura seja na verdade um ruído). Além disso, uma vez que a saída do conversor analógico digital (ADC) interno do Arduino será um número de 0 a 1023, deveremos “mapear” esses valores, a fim de obter os seguintes resultados como porcentagens:



  • “Dark Full” ==> saída ADC: 1023 ==> 0%

  • “Full Light” ==>  saída ADC: 0 ==> 100%


Abaixo a função em C++:


 
int getLumen(int anaPin)
{
  int anaValue = 0;
  for(int i = 0; i < 10; i++) // read sensor 10X ang get the average { anaValue += analogRead(anaPin); delay(50); } anaValue = anaValue/10; //Light under 300; Dark over 800 anaValue = map(anaValue, 1023, 0, 0, 100); //LDRDark:0 ==> light 100%

  return anaValue;  
}
 

Sensor de Humidade de solo (Higrômetro)


Um sensor para testar a umidade do solo (ou higrômetro) é muito simples. Ele possui o mesmo princípio de funcionamento que o sensor de luminosidade. Um divisor de tensão será usado como ponto de entrada de uma das portas analógicas do Arduino, mas em vez de um resistor que varie com luz, usaremos um que varie com a humidade do solo. O circuito básico é muito simples e pode ser visto abaixo.


Picture of Installing, programing and testing the sensors


Infelizmente, a realidade é um pouco mais complexa do que isso (mas não muito). Um simples sensor como o descrito funcionaría bem, mas não por muito tempo. O problema é que ter uma corrente constante fluindo através dos eletrodos em uma única direção gerará corrosão sobre eles, devido ao efeito de eletrólise. Uma maneira de resolver isso é conectar-se os eletrodos não diretamente ao VCC e terra, mas à portas digitais do Arduino (por exemplo VCC a D7 e GND a D6 como mostrado acima). Ao fazer isso, em primeiro lugar o sensor seria “energizado” apenas quando a leitura realmente ocorresse e a direção da corrente sobre as sondas poderia ser alternada, eliminando o efeito da eletrólise.


Abaixo um código de teste simples.


 
/****************************************************
Soil Moisture Sensor Test
****************************************************/
#define SOIL_MOIST_PIN 1 // used for Soil Moisture Sensor Input
#define SMS_VCC 7
#define SMS_GND 6

int soilMoist; // analogical value obtained from sensor

void setup ()
{
  Serial.begin(9600);
  pinMode(SMS_VCC,OUTPUT);
  pinMode(SMS_GND,OUTPUT);

}

void loop (void)
{
  soilMoist = getSoilMoisture();
  Serial.print("Soil Moisture: ")
  Serial.print(soilMoist)
  Serial.println(" %")
}

/***************************************************
* Capture soil Moisture data
****************************************************/
int getSoilMoisture()
{
  int anaValue;
 
  digitalWrite(SMS_VCC,LOW);   // drive a current through the divider in one direction
  digitalWrite(SMS_GND,HIGH);
  delay(1000);   // wait a moment for capacitance effects to settle
  anaValue=analogRead(SOIL_MOIST_PIN);
 
  digitalWrite(SMS_VCC,HIGH);   // reverse the current
  digitalWrite(SMS_GND,LOW);
  delay(1000);   // give as much time in "reverse" as in "forward"
  digitalWrite(SMS_VCC,LOW);   // stop the current
 
  anaValue = map(anaValue, 1023, 0, 0, 100);
  return anaValue;
}
 

Nos testes preliminares para o desenvolvimento do SW, usaremos um  potenciômetro de 10K ohms entre + 5V e GND, simulando a saída analógica do sensor de umidade. Por agora isso será suficiente, uma vez que iremos discutir este sensor mais profundamente no capítulo 1.5.


Agora que todas as rotinas para os sensores estão prontas e testadas individualmente, criaremos uma função específica onde todos os sensores serão lidos ao mesmo tempo:


 
void readSensors(void)
{
  tempDHT = dht.readTemperature();   //Read temperature and humidity values from DHT sensor:
  humDHT = dht.readHumidity();
  lumen = getLumen(LDR_PIN);
  soilMoist = getSoilMoist();
}
 

Procure fazer alguns testes com os sensores, como cobrir o LDR com um pano ou a mão, colocar o dedo diretamente no DHT, etc. , e veja o  range de variação dos dados  Use o Serial Monitor como saída para leitura dos dados.


Sensors Output Serial



Abaixo o código completo:





  • Sensors_Setup_and_Test.inoSensors_Setup_and_Test.ino


  • 1.3: Adicionando um Display LCD para monitoramento local



  • IMG_4705ardufarmbot_sensors_lcd_eletr_diagram


  • É claro que nem sempre será possível usar o monitor serial para analisar a leitura de nossos sensores. Assim, para monitorização local, será adicionado um LCD ao projecto. A escolha ficou com um módulo LCD de 4 linhas de 20 caracteres cada, que permite configuração de contraste através de um potenciômetro instalado em sua parte traseira e comunicação I2C.


    fzxwqolirxthf88-smallPara comunicação serial do tipo I2C com o Arduino, o LCD possui 4 pinos:



    • GND

    • VCC

    • SDA

    • SCL


    O pino SDA será ligado em nosso caso a entrada A4 do Arduino e o pino SCL ao  A5, como mostrado no diagrama acima.


    Uma vez que os 4 fios são conectados, a próxima coisa a fazer é baixar e instalar a biblioteca I2C para o seu display LCD, a qual pode ser usada tanto  para um display do tipo 20 x 4 quanto para o  16 x 2 (2 linhas de 16 caracteres):


    https://github.com/fdebrabander/Arduino-LiquidCrys…


    Execute em seu Arduino o programa exemplo “Hello World” que vem incluído com a biblioteca, mudando o  set-up padrão (16 × 2) para o nosso 20 x 4. O  endereço default “0x27” funcionou bem em meu caso:




 
#include  
#include

// Set the LCD address to 0x27 for a 20 chars and 4 line display
LiquidCrystal_I2C lcd(0x27, 20, 4);

void setup()
{
    // initialize the LCD
    lcd.begin();

    // Turn on the blacklight and print a message.
    lcd.backlight();
    lcd.print("Hello, world!");
}

void loop()
{
    // Do nothing here...
}
 

Nota: Se você não tem certeza sobre o seu endereço I2C de seu LCD, uma simples varredura em seu HW irá mostrar se existem dispositivos I2C conectados, se estão funcionando corretamente e em qual seu endereço. O código para fazer o scanner pode ser encontrado aqui: http://playground.arduino.cc/Main/I2cScanner


57ba02f2deafa4839d00151e.jpeg



Como exemplo, em meu caso ao executar o programa obtive no Monitor Serial :


   Scanning..


   I2C device found at address 0x27 !


  done


Vamos incorporar as funções, definições específicas, etc. referentes ao display em nosso último código, para que possamos assim ver as leituras de sensores em LCD:





  • Sensors_Setup_and_Test_LCD.inoSensors_Setup_and_Test_LCD.ino


  • 1.4: Atuadores e botões para controle local


    Atuadores


    Até agora, pudemos obter os dados gerados pelos sensores e exibi-los no monitor serial e no LCD. É hora de fazer alguma coisa com esses dados. Vamos pensar sobre os atuadores!


    Como discutido na introdução, nosso objetivo final aqui é cuidar de uma plantação de tomate. Com os dados fornecidos por sensores, saberemos a temperatura e umidade do ar, a luminosidade e o mais importante quão “seco” se encontra o solo onde está a plantação. Com esses dados em mãos, o nosso programa deverá decidir se seria necessário irrigar a plantação, ligando uma bomba elétrica para bombear água  ou  uma lâmpada elétrica para fornecer o calor necessário para a cultura. Para isso, usaremos pequenos Módulos de %V para relés para a ativação da bomba e lâmpada. O diagrama do Módulo de Relé pode ser visto abaixo.



  • Picture of Actuators and buttons for local control


  • Módulos de relés podem apresentar várias nomenclaturas para seus pinos de entrada, tais como: “G”, “V”, “S” ou “S”, “-“, “+” ou “In”, “Vcc”, ” GND “, etc.


    Olhando para o diagrama, dependendo do seu módulo de relé, é necessário conectar:



    • Arduino 5V ==> “V” ou “+” ou “Vcc”

    • Arduino GND ==> “G” ou “-” ou “GND”

    • Arduino OUT ==> “S” ou “In” (em nosso caso o “Arduino OUT” deve ser D10 para Bomba e D8 para Lamp)


    Normalmente você vai encontrará como saída, 3 pinos: “NA” (ou NO), “Ref”, e “NF ” (ou NC), que são:” Normal Open ou Aberto”, Referência e” Normal Closed ou Fechado “. Nós usaremos o par: NA e Ref (centro). No diagrama acima, “NA” é o terminal para conectar-se ao positivo da fonte de alimentação (12 ou 9VDC para Bomba e 127 ou 220VAC para a lâmpada, conforme seu caso). O “Ref” será conectado à bomba ou da lâmpada, como mostrado na figura acima. Para saber mais sobre relés, visite: “ Controlling Power with Arduino “.


    Juntamente com os relés, opcionalmente 2 LEDs podem ser utilizados para mostrar se os relés estão ligados ou desligados:



    • LED vermelho: Bomba

    • LED verde: Lâmpada


    Para o teste é ótimo se ter os LEDs instalados em seu BreadBord, mas para o projeto final você pode eliminar-los, reduzindo a carga na saída do pino do Arduino (mesmo porque os módulos de relés em geral possuem um pequeno LED vermelho incorporado). Trabalhando juntos, eles “puxarão” uma quantidade razoável de corrente do Arduino (você poderá perceber uma redução no brilho no LCD). Outra alternativa é utilizar saídas digitais diferentes para os LEDs e relés, o que claro reduz a disponibilidade de pinos para outros usos. 



  • 57bb216d4936d4e847000021.jpeg


  • Botões


    Com base nas leituras dos sensores, um operador poderia decidir controlar manualmente a bomba e / ou lâmpada. Para isso, dois botões do tipo “push-button” serão incorporados ao projeto. Eles vão trabalhar em um modo de “alternância” (“Toggle”): Se um atuador está “ON”, pressionando-se o botão, ele passa a “OFF” e vice-versa. A lógica do botão será “normalmente fechada”, o que significa que a entrada do Arduino estará constantemente em “HIGH” (será usado um resistor de pull-up interno do Arduino). Pressionando-se o botão, uma estado “LOW” será aplicada ao pino do Arduino.


    Da mesma maneira que fizemos com os sensores, a toda vez que executemos o loop () , uma função readLocalCmd () será executada. Esta função lerá o estado dos botões, atualizando o status de variáveis correspondentes aos atuadores (pumpSatus e lampStatus). Note que a função debounce(pin) é chamado ao invés de um digitalRead (PIN). Isso é para evitar falsas leituras do botão. Se você quiser saber mais sobre debouncing, consulte:  Debouncing Tutorial.




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

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

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


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

~




Considerações sobre o “Timming” do programa


Quando pensamos sobre as tarefas a serem executadas, podemos agrupar-las em: 



  1. Ler sensores

  2. ler botões (comando local)

  3. Atuar sobre Bomba / Lâmpada

  4. Exibir todos os dados


Percebemos que o “timming” de quando deveríamos realizar tais tarefas não são necessariamente os mesmos. Por exemplo, para ler os dados de temperatura e de umidade do DHT 22, temos de esperar pelo menos 2 segundos entre medidas, mas diferenças em minutos não farão grandes diferenças. Para o sensor de umidade do solo, quanto menos medições fizermos, melhor (evita corrosão das pontas de prova devido a electrolise) e por último mas não menos importante, a luz do dia não vai variar instantaneamente. Mas quando pensamos sobre os atuadores, logo que se pressione um botão, gostaríamos (e possivelmente precisaríamos) de uma reacção rápida.


Assim, a última instrução antes do final do setup () será a inicialização de um temporizador principal usando a função” millis () ” em vez de espalhar um monte de delays()’s pelo código:


startTiming = millis ();  // Iniciar o “relógio do programa”


Durante o loop(), a primeira instrução será a de incrementar a variável startTiming com uma temporização real.


elapsedTime = millis () – startTiming ;


Depois disso, leremos o estado dos botões usando a função readLocalCmd ( ). Esta leitura irá acontecer toda a vez que o programa execute o loop ().


readLocalCmd (); // Ler estado dos botões locais


Em relação aos sensores, fazemos a leitura a cada 5 segundos, por exemplo, e não em cada loop:


IF (ELAPSEDTIME > (5000))



{


   readSensors();


   printData();


   startTiming = millis();


}


Abaixo o código completo para testar a nossa “Estação local”:





  • local_Station.inolocal_Station.ino


  • 1.5: Aprofundando com o sensor de humidade do solo


    Você poderá pular esta etapa se quiser, mas acho que seria interessante aprofundar-nos um pouco mais no estudo deste simples, mas crítico componente para o projeto. Como brevemente explicado anteriormente, o “Soil Moisture Sensor”, ou higrômetro, é um simples “divisor de tensão resistivo”.


    Sabendo disso, podemos construir um sensor muito simples usando duas sondas metálicas como pregos galvanizados, pinos ou parafusos. Abaixo você poderá ver o que criei utilizando-se de materiais simples: dois parafusos ligados a dois fios (preto / vermelho). Depois em um segundo sensor, foram adicionados um terceiro fio e um resistor.



  • Picture of Playing with a real Soil Moisture Sensor


  • Conforme descrito no item 1.2, “R1” é a “resistência do solo” (não é o melhor termo científico, mas está OK). Utilizando-se de 3 amostras de solo em diferentes estados de umidade, podemos medir o valor esse valor R1 utilisando-se de um multímetro comum e corrente, como mostrado na foto abaixo:




    • Seco:         R1 =    >20 Kohm (aprox)

    • Húmido:  R1 =    4K para 6Kohm (aprox.) 

    • Molhado: R1 =    >1kohm (aprox)

      R2 é a resistência física usada para completar o Divisor de Tensão (Vamos começar com um potenciômetro 10K para set-up). Calculando o Vin na porta A1 do Arduino , proporcionalmente à VCC, chegaríamos a equação:


      Vin = R2 / (R1 + R2) * VCC ou Vin / VCC = 10K / (R1 + 10K) * 100 [%]


      Usando os valores reais medidos com o multímetro, podemos antecipar que os resultados devem ser:






    • Seco:         10K / 30K *100 ==>   <30%



    • Húmido:  10K / 15K * 100 ==>  ~ 67%

    • Molhado: 10K / 11K * 100 ==>  > 90%


    • Fazendo as conexões com o Arduino e executando o código desenvolvido até agora, teremos como resultado:



      • Seco:       13%

      • Húmido: 62%

      • Molhado: 85%


      Obviamente devido a que mudei a posição dos sensores na terra R1 mudará um pouco, além de que o VCC também não é exatamente 5V, os valores práticos são um pouco diversos do teórico. Mas como o que realmente importa é o intervalo de variação e não o valor absoluto, o resultado foi muito satisfatório.


      O sensor será utilizado em 3 estados distintos:



      • Molhado (Wet): Mais de 60% (não ligaremos a bomba de maneira nenhuma)

      • Húmido: Entre 40 e 60% (Onde queremos trabalhar)  e

      • Seco: Abaixo de 30% (precisaremos ligar a bomba para aumentar a umidade)


      Como você pode observar, utilizando-se R2 como 10K ohm funcionou bem, o que nos leva a substituir o potenciômetro por um resistor fixo em nosso “Soil Moisture Sensor”.


      Outra coisa que se percebe quando testamos os sensores, é que ao fazer as medições vai se acumulando um pequeno erro nas leituras. Isto porque o sensor também se comportará como um “capacitor”.  Ao se “energizar” o sensor para uma única captura de dados  precisamos esperar um tempo razoável, mesmo depois de cortar o fornecimento de energia para que o mesmo possa se “descarregar “. Revertendo a corrente ajudará, mas não é suficiente.



    • SoilMoisture Sensor Readings Comp


    • Os gráficos acima mostram 2 conjuntos de medições:



      1. Linha azul : Um ciclo de 10 medições a cada 1 segundo entre amostras e com 1 minuto entre os ciclos

      2. Linha Laranja : Um ciclo de 10 medições a cada 1 segundo entre amostras e com 5 minutos entre ciclos


      Com intervalos de 1 segundo, cada nova amostra será aumentado significativamente. Esperar 1 minuto após desligar a energia irá diminuir o “efeito de tensão de armazenamento”, mas não vai eliminá-la por completo sendo que um valor residual será adicionado à próxima medição. O aumento do intervalo de ciclos para 5 minutos, por exemplo, praticamente eliminará o erro.


      Com base nos resultados acima, o código final não deve tomar amostras com uma frequência de menos do que 10 min.


      O vídeo abaixo, mostra os testes efetuados com o sensor:




    • 1.6: Compatibilizando as operações automática e manual 



    • ardufarmbot_local_station_eletr_diagramComo pudemos ver na última etapa, precisaremos esperar tempos maiores entre as medições do sensor de umidade, por exemplo: 10minutos. Isto  está Ok para as nossas necessidades automáticas, mas para a operação manual não vamos querer “esperar” dezenas de minutos olhando para o ArduFarmBot para saber se um valor medido pelo sensor mudou. Para solucionar o problema, introduziremos um terceiro botão de controle em nosso projeto, o qual será usado para exibir os dados reais e instantâneos dos sensores a qualquer momento, independente das programações de leituras automáticas.

    • Picture of Changing the code to accommodate real measurements and final HWPara o Push-Button, usaremos o pino digital D17  (o mesmo que está compartilhado com a entrada analógica A3). Introduziremos também um “LED de aviso” (o amarelo na foto) conectada ao pino 13. Este LED acenderá toda a vez em que os sensores estão sendo atualizados. Abaixo a nova função readLocalCmd() :




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

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

  digiValue = debounce(SENSORS_READ);
  if (!digiValue)
  {
    digitalWrite(YELLOW_LED, HIGH);
    lcd.setCursor (0,0);
    lcd.print("< Updating Sensors >");
    readSensors();
    digitalWrite(YELLOW_LED, LOW);
  }
}
 

Outro ponto a considerar, é a introdução de um segundo “Soil Moisture Sensor” (higrômetro). Em nosso projeto final utilizaremos 2 sensores em pontos diferentes da plantação.  Nós usaremos a média das leitura para decidir quando se deve ligar a bomba, por exemplo.


O “VCC e GND” dos sensores serão o mesmo (D7 e D6 respectivamente) e usaremos a entrada A2 do Arduino para o segundo sensor. Se a area da plantação é pequena não justificando 2 sensores, somente o valor lido em A1 será considerado pelo SW. (Isto deve ser informado na variável correspondente na area de set-up do SW). 


// to be used by SM Sensor

int soilMoist;

int soilMoistAlert = 0;

int DRY_SOIL = 30;

int WET_SOIL = 60;

int numSM = 1; // “numSM” defines number of moisture sensors that are connected

int numSamplesSMS = 1; // “numSamplesSMS” defines number of samples of each reading cycle


O número de amostras de cada ciclo também será definido por uma variável específica: “numSamplesSMS”. Em princípio apenas uma leitura é suficiente, levando-se em consideração que as leituras que fazemos em um curto espaço de tempo introduzirão erros devido ao efeito de capacitância. Se você começar a ver erros na leitura, talvez sejam necessárias tomar amostras extras.


Abaixo a nova função para o  “Soil Moisture Sensor”:


 
/***************************************************
* Capture soil Moisture data
****************************************************/
int getSoilMoist()
{
  int i = 0;
  int anaValue1 = 0;
  int anaValue2 = 0;
  for(i = 0; i < numSamplesSMS; i++) // "numSamplesSMS" defines number of samples of each reading cycle
  {
    digitalWrite(SMS_VCC,LOW);   // drive a current through the divider in one direction
    digitalWrite(SMS_GND,HIGH);
    delay(500);   // wait a moment for capacitance effects to settle
    anaValue1 += analogRead(SOIL_MOIST_1_PIN);
    delay(500);   // wait a moment for ADC settle-up
    anaValue2 += analogRead(SOIL_MOIST_2_PIN);
   
    digitalWrite(SMS_VCC,HIGH);   // reverse the current
    digitalWrite(SMS_GND,LOW);
    delay(1000);   // give as much time in "reverse" as in "forward"
    digitalWrite(SMS_VCC,LOW);   // stop the current
  }
 

O diagrama abaixo mostra as conexões completas para a estação local de controle


ardufarmbot_local_pin_diagram




1.7: It’s show time!






Picture of It


Neste ponto, já temos todo o HW no lugar e quase todos os elementos de SW desenvolvidos. O que falta agora é a “inteligência”,  que permitirá ao nosso sistema realmente executar a tarefa de irrigar a plantação automaticamente! Para isto, precisaremos adicionar alguns “neurônios” ao nosso cérebro!


Como discutido anteriormente, definiremos o intervalo inicial onde os sensores irão trabalhar. Esses valores deverão ser alterados mais tarde a partir de resultados de testes reias na plantação:


Umidade do solo:



  • Molhado (Wet): Mais de 60% (não ligaremos a bomba de maneira nenhuma)

  • Húmido: Entre 40 e 60% (Onde queremos trabalhar)  e

  • Seco: Abaixo de 30% (precisaremos ligar a bomba para aumentar a umidade)


Temperatura:



  • Frio: Abaixo de 15oC (Ligar Luz / Calor *)

  • Confortável: entre 20 oC e 25 oC

  • Calor: Mais que 25 ° C (não vire-a luz / calor)


Leve:



  • Escuro (noite): Abaixo de 40% (não ligar bomba)

  • Luz (dia): Mais de 40%


(*) Você poderá opcionalmente testar aqui as novas luzes LED para vegetais hidropônicos . Estas lâmpadas de LED podem ser utilizadas tanto para ajudar o crescimento mais rápido devido a  luzes de frequências especiais como também para fornecer calor em caso de baixa temperatura.


Você deverá ter em mente que cada tipo de semente possui uma faixa ideal de temperatura na qual ela crescerá mais rápidamente. Por exemplo, para os Tomates o tempo mínimo para as sementes germinarem será de 6 dias em temperaturas entre 20 e 25 oC, aumentando para temperaturas superiores ou inferiores a esta faixa:



  • Temperatura: graus (oC):             10    15   20  25  30  35

  • Tempo para germinação (dias):  43   14    8     6    6   9


Você pode verificar mais informações sobre esta relação (temp / dias de germinação) aqui: O efeito da temperatura do solo na germinação de sementes


Tendo em mãos estas 4 leitura (temperatura, umidade, Soil Moisture and luz), podemos criar uma matriz que definirá como queremos que os nossos tomates crescem:


Então, tomemos nossas variáveis e definamos algumas novas valores:


Para ser utilizado pelo sensor DHT:



  • int tempDHT;

  • int HOT_TEMP = 25;

  • int COLD_TEMP = 15;


Para ser usado por sensor LDR:



  • lumen int;

  • int DARK_LIGHT = 40;


Para ser usado pelo higrômetro:



  • int soilMoist;

  • int DRY_SOIL = 40;

  • int WET_SOIL = 60;


Com base nas definições acima, pensemos sobre algumas premissas-chave:



  1. Se é durante o dia (lumen  > DARK_LIGHT) e o solo está SECO (soilMoist < DRY_SOIL) ==>  BOMBA = ON 

  2. Se é durante a noite (lumen < DARK_LIGHT) e o solo está SECO (soilMoist < DRY_SOIL) ==>  BOMBA = OFF  (Tomates não gostam de receber água durante a noite)

  3. Se estiver frio (tempDHT <COLD_TEMP)  ==> LAMPADA = ON

  4. Se estiver frio (tempDHT <COLD_TEMP) e solo muito húmido (soilMoist > WET_SOIL) ==> LAMP = OFF (para proteger a raiz)


Nesta primeira parte do projeto, vamos mantê-lo simples e não exploraremos todas as combinações possíveis e o papel da humidade do ar na equação. Explorar uma combinação mais complexa de sensores na 3º parte deste projeto, quando aplicaremos o ArduFarmBot em uma plantação real.


O Código :


Criaremos uma nova função, que baseado na leitura dos sensores, lidará automaticamente com os atuadores (ligar / desligar a bomba e lâmpada): AutoControlPlantation (). Esta função mostrada abaixo, será chamada em cada ciclo de leituras dos sensores:




 
void loop()
{
  // Start timer for measurements
  elapsedTime = millis()-startTiming;

  readLocalCmd(); //Read local button status
  showDataLCD();
 
  if (elapsedTime > (sampleTimingSeconds*1000))
  {
    readSensors();
    autoControlPlantation();
    startTiming = millis();
  }
}
 

A função terá 2 tarefas principais:



  • Controle de bomba

  • Controle da lâmpada


O segmento de controle da bomba utilizará uma nova variável: ” soilMoistAlert “.


 
//--------------------------------- PUMP ------//
  if (soilMoist < DRY_SOIL && lumen > DARK_LIGHT)
  {
    if (soilMoistAlert == HIGH)
    {
      soilMoistAlert = LOW;
      turnPumpOn();
    }
    else soilMoistAlert = HIGH;
  }
  else soilMoistAlert = LOW;
 

Esta variável será utilizada para evitar um “falso verdadeiro”. Então por exemplo, se tivermos um verdadeiro no resultado do teste: soilMoist <DRY_SOIL e que não seja durante a noite (lumen> DARK_LIGHT), não ligaremos imediatamente na bomba, mas ao invés disso, esperaremos o próximo ciclo verificando se o ” solo está muito seco “. Se o resultado for um “sim” (obtendo um “verdadeiro” como resposta duas vezes), somente aí a função turnPumpOn() será chamada:


 
/***************************************************
* TurnPumOn
****************************************************/
void turnPumpOn()
{
  digitalWrite(PUMP_PIN, HIGH);
  pumpStatus = 1;
  showDataLCD();
  delay (timePumpOn*1000);
  digitalWrite(PUMP_PIN, LOW);
  pumpStatus = 0;
  showDataLCD();
}
 

A bomba deverá permanecer ligada por um determinado período de tempo, definido pela variável: ” timePumpOn” em segundos.


Note que também mudaremos a função que exibe dados no LCD criando um 3o. estado:



  • “0”: Bomba OFF (pumpStatus = 0; e soilMoistAlert = 0;)

  • “X”: Bomba em alerta (pumpStatus = 0; e soilMoistAlert = 1;)

  • “1”: Bomba ON (pumpStatus = 1; e soilMoistAlert = 0;)


 
  lcd.print("Pump: ");
  if (soilMoistAlert  == 1) lcd.print ("X");
  else lcd.print(pumpStatus);
 

O mesmo princípio será aplicado ao controle da lâmpada, onde uma “baixa temperatura” será o “trigger” para acionar a lâmpada desde que o solo não esteja muito molhado”. Abaixo a função completa: autoControlPlantation ():


 
/***************************************************
* Automatically Control the Plantation based on sensors reading
****************************************************/
void autoControlPlantation()
{
//--------------------------------- PUMP ------//
  if (soilMoist < DRY_SOIL && lumen > DARK_LIGHT)
  {
    if (soilMoistAlert == HIGH)
    {
      soilMoistAlert = LOW;
      turnPumpOn();
    }
    else soilMoistAlert = HIGH;
  }
  else soilMoistAlert = LOW;

//--------------------------------- HEAT ------//
  if (tempDHT < COLD_TEMP && soilMoist < WET_SOIL)
  {
    if (tempLowAlert == HIGH)
    {
      tempLowAlert = LOW;
      digitalWrite(LAMP_PIN, HIGH);
      lampStatus = 1;
    }
    else tempLowAlert = HIGH;
  }
  else
  {
    tempLowAlert = LOW;
    digitalWrite(LAMP_PIN, LOW);
    lampStatus = 0;
  }
}
 



Neste ponto, o ArduFarmBot esta totalmente funcional em termos de HW e SW e já poderia ser instalado em uma plantação para testes. O código completo pode ser encontrado abaixo:








1.8: Small Form Factor (colocando tudo na “caixinha”)


FullSizeRender 20.jpg




Uma vez que possuímos nosso protótipo funcional, vamos montar-lo de uma forma melhor, usando-se um “Shield” para o Arduino Nano (no caso, um fabricado pela  “Funduino”) e uma caixa plástica, o que ajudará nos testes externos. A grande vantagem de se usar um shield para o Nano,  é que cada componente fica melhor montado reduzindo os maus contatos e ruídos, além da facilidade de se ter todos os componentes principais reunidos em uma pequena caixa de plástico.


IMG_4781.JPG


Se você estiver usando o DHT isolado (sem ser em um módulo), você adicione um resistor de 10K entre VCC e Signal. Se você estiver usando um módulo sensor, a resistência já se encontra incluído. Para este novo teste usarei o módulo DHT11 que tenho disponível. O resultado para o nosso propósito é o mesmo (apenas não se esqueça de alterar a linha no código para definir o sensor apropriado que você irá usar: #define DHTTYPE DHT11).




57c1b7c767400c7912000c37.jpeg


Faça 4 furos na caixa de plástico para a instalação do LCD (eu o deixei dentro da caixa).




Faça 57c1b7a045bcebf5270006ab.jpegfuros laterais na caixa para que que você possa acessar os sensores, ter acesso ao Nano (seja para a fonte de alimentação externa ou atualizações de SW) e ligar os atuadores (Bomba / Lampada) nas saídas de relés


Picture of Changing to a Small Form Factor


Note que para os botões de controle, usei aqui um teclado do tipo membrana de 4 teclas “1 × 4 Key Matrix Membrane Switch”. 


IMG_4788.JPG


Você pode decidir a melhor maneira de fixar os componentes na caixa. Eu pessoalmente, gosto desse fixador removível da 3M para facilitar a instalação (veja as foto).





1.9: Testes funcionais em laboratório


Uma vez que tudo está fixada em seu devido lugar e o SW carregado, vamos fazer alguns testes funcionais que simulem diferentes condições de sensores, a fim de se verificar que tudo esteja bem ligado:


Com luz  e temperatura normais, introduzir o higrômetro em um copo com amostra de solo húmido. Observe a foto 1 (Temp é 22oC;. Soil Hum é de 85% e luz é de 80%). Nada deve acontecer. Pump e Lamp devem ser OFF ( “0”).



Picture of Funcional tests


Mantendo-se a mesma luz e temperatura, passemos a sonda para o copo com amostra de solo seco. Na foto 2, você pode observar que a bomba foi ligada (Primeiro aparecerá o “X” e depois o “1” durante algum tempo, tal como definido no programa).


57c1e6574fbadef414000d35.jpeg


Agora, como mostrado na foto 3, o LDR foi coberto com um pano preto e a luminosidade decresceu para 19%. Neste caso, apesar do fato de que o solo esteja seco, a bomba não ligará, porque o ArduFarmBot entenderá que é à noite.




57c1e71ddeafa41a5b0007af.jpeg


Na foto 4, colocaremos gelo no fundo da nossa caixa, junto ao sensor DHT. A temperatura desceu a 12oC e a lâmpada foi ligada.


57c1e801deafa41a5b0007b5.jpeg




E por último, na foto 5 manteremos o gelo, mas mudaremos a sonda novamente para a amostra de solo húmido. Neste caso apesar do fato de estar frio, de acordo com a matriz, a lâmpada permanece desligada.


57c1e8f84fbadef21e00044f.jpeg





1.10: “Test Drive”: Regando um tomateiro com o ArduFarmBot





Picture of





Para os primeiros testes reias, liguei uma bomba elétrica que tinha disponível (no projeto final a bomba será uma pequena bomba DC de 9V). Este primeiro teste é só para ver como o projeto vai funcionar, então não se preocupam com as gotas que você vai ver no vídeo ao lado).






1.11: O ArduFarmBot em acção


Com base em tudo o que nós aprendemos aqui, o passo agora será colocar o ArduFarmBot para controlar sua plantação verdadeira de tomate. Com base nesta experiência real, calibraremos e definiremos melhor os sensores e parâmetros do projeto. As fotos aqui dão uma idéia da sequência da preparação da terra e a introdução das sementes. Essa parte do projeto está a cargo de nosso “Chef” Maurício! Todos os detalhes dos testes reais serão explorados em na 3a. e última parte do projeto.


MauFarmColagem


O filme abaixo mostra o ArduFarmBot em ação:



1.12: Parte 1 Conclusão


MJRoBot and ArduFarmBot


 


capa-ardufarmbot


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



10
Projetos / O ESP8266 parte 3 – Acionar LEDs de forma remota
« Online: Dezembro 08, 2017, 09:23:47 am »
O ESP8266 parte 3 – Acionar LEDs de forma remota



LED Ctrl


O Circuito:

O circuito é muito simples. As conexões do ESP8266 com o UNO são as mesmas dos posts anteriores, apenas acrescentamos os 3 LEDs a 3 GPIOs do UNO:


GPIO 11: LED azul

GPIO 12: LED vermelho

GPIO 11: LED verde


ES8266_Arduino_UNO_GPIO_Control


O código HTML:

A Página deve ser gerada em HTML em um editor qualquer e salva no desktop.


HTML Buttons


A parte principal do codigo HTML abaixo, é a geração dos “botões”, no caso “ON” e “OFF”. Observe que para cada botão (são 6 no total, 2 para cada GPIO), é gerado um “id” específico. Por exemplo, se o botão “ON” para o GPIO 11 for pressionado, o id será “111”, ou seja os dois primeiros dígitos para a identificação do GPIO (no caso “11”) e o 3o. dígito para o estado, no caso “1” ou “ON”. Se fosse “OFF”, o Id sería 110. No caso, na saída digital do pino 11, está o LED azul.


Uma vez gerado o “id” uma função na página se encarrega de enviar-la para para o IP address do ESP8266. Observe que o endereço que aparece no set-up do ESP 8266 tem que ser incluído na linha ==> $.get(“http://10.0.1.14:80/&#8221;, {pin:p});


HTML Button click


No monitor serial se pode observar o valor do pin que é gerado pela página.


Serial monitor ongoing


As primeiras vezes que testei o programa, tive vários problemas e o mais importante foi que observei que só era possível enviar 5 comandos aos LEDs. Isso porque  a cada envío de informação o ESP8255 considerava uma conexão aberta (CONNECT 0, 1, 2, 3, 4) e o limite é 5.


Observei também que quando fazia um “refresh” na página, o connect, voltava a zero. A solução foi incluir um novo codigo HTML, que forçava o refresh automático da página (código tipo “META”). No caso optei por fazer um refresh a cada 15s para não ficar muito ruim para o usuário. Funcionou sem problemas:


<META HTTP-EQUIV=”refresh” CONTENT=”15″>


O código do Arduino:

O código é muito parecido com o código anterior:


Inicializa, faz o setup das portas, “reseta” e inicializa o ESP8266, etc., usando as mesmas funções definidas no post anterior.


A diferença básica está na porção em verde do código contido  no “Loop”:


 
void loop()
{
  if(esp8266.available())
  {
    if(esp8266.find("+IPD,"))
    {
      delay(1000);
     
      int connectionId = esp8266.read()-48;
      esp8266.find("pin=");
      int pinNumber = (esp8266.read()-48)*10;
      pinNumber += (esp8266.read()-48);
      int statusLed =(esp8266.read()-48);
      digitalWrite(pinNumber, statusLed)
     
      String closeCommand = "AT+CIPCLOSE=";
      closeCommand+=connectionId;
      closeCommand+="
";
      sendData(closeCommand,1000,DEBUG);
    }
  }
}
 

Ao ler o “id”, por exemplo “111”, o código separa os primeiros dois dígitos e constrói a variável “pinNumber”. Com o 3o. dígito, se obtém o “statusLed”. A função digitalWrite enviará o status do LED, no caso do exemplo “1” para o GPIO correspondente (ou “pinNumber”), no exemplo 11.


No vídeo abaixo, pode-se ver um exemplo do acionamento remoto dos LEDs:


Link para o vídeo do acionamento remoto de GPIOs via ESP8266


Para finalizar, no link abaixo deixo o codigo completo para o Arduino e para a pagina em codigo HTML.


Link para os codigos fonte


 



11
Projetos / O ESP8266 parte 2 – Web Server
« Online: Dezembro 08, 2017, 09:23:35 am »
O ESP8266 parte 2 – Web Server



Neste tutorial vamos ver o que se deve fazer com o ESP para interagir com os GPIOs do Arduino remotamente via web .


Alguém disse uma vez “If you can blink a LED you can do anything”. Quando você faz com que um LED acenda a partir de um sinal gerado em uma das portas do Arduino, ou que ele possa ler o status de uma chave ou sensor, o que está realmente acontecendo é a interação do mundo da eletrônica com o mundo físico! Conseguir essa interação via uma página da internet é de fato toda a essência do IoT.


image


A primeira configuracão que testarei, será o ES8266 funcionando como um servidor web local, conectado a um Arduino MEGA. Vamos instalar botões em dois GPIOs digitais do Arduino (Pinos 8 e 9) simulando o estado de algum sensor e um potenciômetro na porta analógica A0, simulando os dados fornecidos por um sensor analógico, como por exemplo temperatura (os “inputs” do diagram acima). A função do ESP8266 será ler esses sinais, gerar uma página HTML  simples, publicando os resultados em tempo real na web! Cool!!!!!!!!


 


O circuito:

Webserver circuit


Observe que  o circuito é basicamente o mesmo que o do post anterior, apenas adicionei dois botões (normalmente abertos) conectados entre as entradas do Arduino  e o VCC (via um resistor de 10K para não gerar um curto-circuito, claro). Ao pressionar o botão, o que estamos fazendo é colocar um sinal HIGH na entrada digital do Arduino. O potenciômetro (também de 10K) será montado entre VCC (5V) e Terra, com seu pino central conectado a entrada analógica A0 do MEGA. O pot controlará o nível de tensão na entrada analógica A0,  a qual variará de “0V a 5V”. O MEGA lerá a tensão no pino AO e seu ADC interno (Analogic Digital Converter), convertendo a mesma para um valor que variará respectivamente de “0 a 1023”.


O Código:

O que farei aqui, será ressaltar as principais diferenças da sketch anterior ( O ESP8266 Serial Wifi Module), mas não se preocupem que no final, deixo o link para o código completo:



  • Antes de mais nada, depois das definições e set up geral como já foi visto anteiormente, é importante iniciar o ESP como um servidor. Para isso, a função InitWifiModule()


 
void InitWifiModule()
{
  sendData("AT+RST
", 2000, DEBUG); // reset
  sendData("AT+CWJAP="Your network ID","password"
", 2000, DEBUG);
  delay(3000);
  sendData("AT+CWMODE=1
", 1000, DEBUG);
  sendData("AT+CIFSR
", 1000, DEBUG); // Show IP Adress
  sendData("AT+CIPMUX=1
", 1000, DEBUG); // Multiple conexions
  sendData("AT+CIPSERVER=1,80
", 1000, DEBUG); // start comm port 80
}
 


  • No loop principal, se espera para ver se o ESP está enviando algo e se o string  “+IPD” é encontrado significa que a pagina foi identificada (veja a cópia do monitor serial mais abaixo).

  • Esperamos 300 milisegundos para garantir que o buffer serial tenha lido todos os dados.

  • Como a função read() retorna ASCII, é importante que ao se carregar o connection ID, seja subtraído o valor “48” do dado lido. 48 é o código do primeiro caracter decimal “0”. Assim se o dado 49 (codigo ASCII para  “1”) é recebido, ao subtrair 48, o resultado será um digito puro (“1”).

  • Em verde, está o código HTML que será enviada ao Browser para a construção da página (Note que mesmo que você não seja familiar com a linguagem HTML, em vermelho está o que aparecerá escrito na página, fique livre para customizer-la a seu gosto).

  • Em azul, as informações são enviadas (Comando CPISEND) e em laranja se fecha a conexão (comando CPICLOSE).


 
void loop()
{
   if (esp8266.available()) // check if 8266 is sending data
   {
      if (esp8266.find("+IPD,"))
      {
         delay(300);
         int connectionId = esp8266.read() - 48;
 
         String webpage = "

MJRoBot WebServer ESP8266


Ardin: “; webpage += “D8 status ==> “; int a = digitalRead(8); webpage += a; webpage += “


Arduino Pin: D9 status ==> “; int b = digitalRead(9); webpage += b; webpage += “


Arduino Pin: A0 data ===> “; int c = analogRead(0); webpage += c; webpage += “


“; String cipSend = “AT+CIPSEND=”; cipSend += connectionId; cipSend += “,”; cipSend += webpage.length(); cipSend += “
”; sendData(cipSend, 1000, DEBUG); sendData(webpage, 1000, DEBUG); String closeCommand = “AT+CIPCLOSE=”; closeCommand += connectionId; // append connection id closeCommand += “
”; sendData(closeCommand, 3000, DEBUG); } } }



  • A função “sendData()” enviará os comandos AT para o ESP

  • Quando o esp8266.available é TRUE, significa que existem dados disponíveis , portanto a resposta “c” é montada


 
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())
            {
              char c = esp8266.read(); // read the next character.
              response += c;
            }
      }
      if (debug)
        {
          Serial.print(response);
        }
      return response;
}
 


  • Durante a conexão o monitor serial apresenta os dados abaixo:

  • Muito importante é o segundo IP address que aparece no monitor: 10.0.1.2Serial - Conxion

  • Ao entrar com o IP acima, em um browser, o ESP montará a pagina HTML que foi programada e começará a enviar as informações capturadas nas entradas do MEGA:Webserver page

  • No monitor Serial, se observará os dados que são continuamente atualizados:Serial Ongoing comm

  • No vídeo abaixo poderá observar o WebServer a funcionar:


  • Link para a sketch do Arduino MEGA e do diagrama eletrônico


    Tudo o que foi visto aqui para o Arduino MEGA poderia ser executado com um Arduino UNO, ou qualquer outro da família.


    A diferença básica será a utilização de outros GPIOs como port serial. Como o UNO só tem 1 port, usaremos a biblioteca softwareSerial () para definir os pinos 2 e 3 como RX e TX respectivamente (note que isso só funciona para velocidades mais baixas que 19.600bauds)


    As definições iniciais no código devem ser alteradas para:


    #include <SoftwareSerial.h>

    SoftwareSerial esp8266(2,3);  //Rx ==> Pin 2; TX ==> Pin3


    #define speed8266 9600


    O restante do código para o UNO funcionará da mesma maneira que para o MEGA.


    O novo circuito:


    ESP8266_WebServer_UNO


    O vídeo abaixa, mostra o UNO como um WebServer executando o mesmo código anterior:


    Link para o vídeo do WebServer funcionando com o UNO




 



12
Projetos / Deteção de cores com o Arduino
« Online: Dezembro 08, 2017, 09:22:41 am »
Deteção de cores com o Arduino



Neste tutorial, exploraremos como ler cores usando um Arduino e sensores como o TCS 3200. A ideia será detectar a cor de um objeto, exibindo-a em um LCD. Este tutorial é a primeira parte de um projeto maior, um braço robótico que decide que operação executar a partir da cor de uma peça.


O diagrama de blocos abaixo mostra os principais componentes:


Color Detector Block Diagram


O vídeo abaixo mostra como ficará o projeto final:




1: Lista de materiais (BoM)



 



  1. Arduino Nano

  2. TCS3200 Color Sensor Module

  3. IIC/I2C/TWI 1602 Serial Blue Backlight LCD Module

  4. Breadboard

  5. Cables






2: O sensor TSC 3200


The TSC 3200 Color Sensor



Como descrito en seu Datasheet, O TCS3200 é um conversor programável de luz (cor) em frequência que combina fotodiodos de silício configuráveis e um conversor de corrente em frequência, tudo encapsulado em um único circuito integrado do tipo CMOS.


A saída é um sinal do tipo “onda quadrada” (ciclo de trabalho de 50%) cuja freqüência é diretamente proporcional à intensidade da luz (irradiance). A frequência de saída pode ser escalonada por um dos três valores predefinidos através de dois pinos de entrada de controle (S0 e S1).




Entradas e saída digitais permitem interface direta com um microcontrolador ou outros circuitos lógicos.

TSC3200 Diagram


Output enable (OE) coloca a saída no estado de alta impedância para a partilha de múltiplas unidades de uma linha de entrada do microcontrolador. No TCS3200, o conversor de luz em frequência lê uma matriz 8 x 8 de fotodíodos. O OE (Enable) deve ser conectado a GND (LOW).


  • 16 fotodiodos têm filtros azuis,

  • 16 fotodiodos têm filtros verdes,

  • 16 fotodiodos têm filtros vermelhos e

  • 16 fotodiodos são claros sem filtros.


Os pinos S2 e S3 são usados para selecionar qual grupo de fotodíodos (vermelho, verde, azul ou claro) está ativo. Os fotodiodos têm um tamanho de 110 μm x 110 μm e estão em centros de 134 μm.


O Sensor deve ser alimentado entre 2.7 e 5.5VDC. Usaremos a saída 5V do Arduino para alimentar o sensor.


Para usar corretamente o sensor, vamos instalar um pequeno anel de borracha para isolar o sensor da luz lateral. Eu usei cola quente para corrigi-lo.


Sensor with ring


3: Conectando o HW


Connecting the HW





  1. Instale o Arduino Nano no BreadBoard

  2. Conecte a saída de 5V e GND do Nano 5Va ambos Power Rails do BreadBoard

  3. Conecte o sensor TSC3200 como descrito abaixo:

    • S0     ==> Nano pin D4

    • S1     ==> Nano pin D5

    • S2     ==> Nano pin D6

    • S3     ==> Nano pin D7

    • OUT ==> Nano Pin D8

    • EN    ==> GND

    • VCC  ==> +5V

    • GND ==> GND



  4. Conecte o I2C LCD 2/16 Serial Display como abaixo:

    • SDA ==> Nano Pin A4

    • SCL ==> Nano Pin A5








4: O código do Arduino





The Arduino Code





A primeira coisa a definir é a escala de freqüência a ser utilizada, tal como definida na tabela mostrada acima. Os pinos S0 e S1 são usados para isso. A escala da freqüência de saída é útil para otimizar as leituras de sensores para vários contadores de freqüência ou microcontroladores. Definiremos S0 e S1 em HIGH (100%), funcionou bem com meu Nano. Já observei em alguns projectos com o UNO, a frequência escalonada em 20%. Teste para ver o melhor em seu caso.






 
  digitalWrite(s0,HIGH);
  digitalWrite(s1,HIGH);
 

A próxima coisa a fazer é selecionar a cor a ser lida pelo fotodíodo (vermelho, verde ou azul), usamos os pinos de controle S2 e S3 para isso. Como os fotodiodos são conectados em paralelo, o ajuste de S2 e S3 como LOW ou HIGH em combinações diferentes, permite que você selecione diferentes fotodiodos, como mostrado na tabela acima e definidos no código abaixo:


 
void readRGB()
{
  red = 0;
  grn = 0;
  blu = 0;
  int n = 10;
  for (int i = 0; i < n; ++i)
  {
    //read red component
    digitalWrite(s2, LOW);
    digitalWrite(s3, LOW);
    red = red + pulseIn(outPin, LOW);
 
    //read green component
    digitalWrite(s2, HIGH);
    digitalWrite(s3, HIGH);
    grn = grn + pulseIn(outPin, LOW);
 
    //let"s read blue component
    digitalWrite(s2, LOW);
    digitalWrite(s3, HIGH);
    blu = blu + pulseIn(outPin, LOW);
  }
  red = red/n;
  grn = grn/n;
  blu = blu/n;
}
 

Observe que no código acima, leremos algumas vezes cada um dos componentes RGB, tomando uma média, para que com isso possamos reduzir o erro se algumas leituras forem ruins.


Uma vez de posse dos 3 componentes (RGB), deveremos definir a qual cor equivale. A maneira de fazê-lo é “calibrando-se” previamente o projeto. Você pode usar tanto papel quanto objetos com cores conhecidas e assim ler os 3 componentes gerados por este objeto.


Você pode começar com o meu set-up, mudando os parâmetros para o seu nível de luz:


 
void getColor()
{
 readRGB();
      if (red > 8 && red < 18 && grn > 9 && grn < 19 && blu > 8 && blu < 16) color = "WHITE"; else if (red > 80 && red < 125 && grn > 90 && grn < 125 && blu > 80 && blu < 125) color = "BLACK"; else if (red > 12 && red < 30 && grn > 40 && grn < 70 && blu > 33 && blu < 70) color = "RED"; else if (red > 50 && red < 95 && grn > 35 && grn < 70 && blu > 45 && blu < 85) color = "GREEN"; else if (red > 10 && red < 20 && grn > 10 && grn < 25 && blu > 20 && blu < 38) color = "YELLOW"; else if (red > 65 && red < 125 && grn > 65 && grn < 115 && blu > 32 && blu < 65) color = "BLUE";
 else color = "NO_COLOR";
}
 

Como você pode ver acima tenho predefinido 6 cores: Branco, Preto, Vermelho, Verde, Amarelo e Azul.


À medida que a luz ambiente diminui, os parâmetros tendem a aumentar de valor.


Dentro do loop (), definimos que as leituras são mostradas no LCD a cada 1 segundo.


O código completo pode ser encontrado neste GitHub:


https://github.com/Mjrovai/Color-Detector


 


5: Conclusão






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






13
Projetos / Controlar o robot aspirador “Roomba” com Arduino e Android
« Online: Dezembro 08, 2017, 09:22:30 am »
Controlar o robot aspirador “Roomba” com Arduino e Android



O Create 2 é uma plataforma robusta e relativamente barata para o desenvolvimento de projetos na área da robótica. O Create2 é na verdade um Robô Aspirador de pó “Roomba” da série 660 restaurado que permite uma variedade de métodos de programação.


Para começar, usei um Arduino e um aplicativo Android para poder mover o robot por aí. Neste tutorial, explorarei como conectar o Arduino com o Roomba via porta serial e como comandar seus motores, LEDs e som.



PASSO 1: LISTA DE MATERIAIS

BoM



  • iRobot “Roomba”Create2

  • Arduino UNO

  • módulo Bluetooth HC-06

  • Botão (“Push0Button”)

  • Protobard e cabos de conecção.


 


PASSO 2: O ROOMBA CREATE2


O Roomba é um robô do tipo diferencial, com 2 rodas e um “caster”


Roomba Wheels


 


 


Sua velocidade vai até 500 mm/s e pode ser comandado para ir tanto para a frente como para trás.


 


Para sinalização, podemos contar com 4 displays de sete segmentos e 5 LEDs:Create-Sensors-LEDS



  • Limpar (Clean)

  • Local (Spot)

  • Doca (Dock)

  • Aviso (Warning)

  • Sugeira (Dirt / Debris)


Como sensores internos, temos entre outros:



  • Detector de degrau (Cliff) (4 à frente)

  • Detectores de colisão (2 na frente)

  • Codificadores de giro das rodas


 


Para a programação, deve ser usado o documento de referencia: iRobot® Create® 2 Open Interface (OI) .


O Roomba  possui 3 modos de programação:



  • Modo de segurança (Safe):

    Libera o controle total do Roomba, com a excepção das seguintes condições de segurança:



    • Carregador de batería conectado e ligado.

    • A detecção de uma queda de roda (ocorre quando se “levanta o Roomba do chão”).

    • A detecção de um degrau de escada por exemplo, enquanto se move para a frente (ou movendo-se para trás com um raio de giro pequeno).




Se uma das condições de segurança acima ocorrem enquanto o Roomba está em modo de segurança, Roomba para todos os motores e reverte para o modo passivo.



  • Modo passivo (Passive):

    Ao enviar o comando Iniciar (“Start”) ou qualquer um dos comandos do modo de limpeza (por exemplo, “Spot”, “Clean”, “Seek Dock”), o Roomba entra em modo passivo. Quando o Roomba está em modo passivo, você pode solicitar e receber dados utilizando qualquer um dos comandos de sensores, mas você não pode mudar os parâmetros de comando dos atuadores (motores, som, luzes, saídas digitais, etc.) .



  • Modo completo (Full):

    Libera o controle completo do Roomba, a  todos os seus atuadores e a todas as condições de segurança que são restritos quando o robô está em modo de segurança descritas no modo Safe.


PASSO 3: A LIGAÇÃO EM SÉRIE


Para a comunicação entre o Roomba e o Arduino, será utilizada a porta serial de ambos. Por padrão, o Roomba se comunica a 115.200 bauds, mas para uma melhor comunicação com o Arduino, vamos modificar-lo para 19.200 bauds.


Existem 2 maneiras de se definir a taxa de transmissão do Roomba :



  • Durante o  desligamento do Roomba, continue a manter pressionado o botão central POWER/CLEAN, mesmo após a luz se apagar. Após cerca de 10 segundos, o Roomba tocará uma música com tons descendentes. A partir daí, o Roomba irá comunicar-se a 19.200 bauds até que o processador perda a energia da bateria ou a taxa de transmissão seja explicitamente alterada através de programação.

  • Usar o pino 5 no conector Mini-DIN (Baud Rate Change pin) para alterar a taxa de transmissão do Roomba. Depois de ligar o Roomba, espere 2 segundos; em seguida, aplique um pulso de nivel baixo no pin5 três vezes. Cada pulso deve durar entre 50 e 500 milissegundos. O Roomba irá comunicar-se a 19200 bauds até que o processador perca a energia da bateria ou a taxa de transmissão seja explicitamente alterada por SW.


O diagrama abaixo mostra como o Arduino deve ser conectado ao conector Mini-DIN do Roomba:


Serial_Conn


Para se ter acesso ao Mini-DIN se deve remover a parte superior do Create 2 (capa verde), ou simplesmente fazer um furo na mesma.


IMG_4317IMG_4306


PASSO 4: INICIALIZANDO O ROOMBA


O primeiro passo a ser feito na programação de um Roomba é:



  • “Acordar” o robô

  • Iniciar e definir o modo de operação (Safe ou Full)


Para acordar o Roomba, devemos enviar um pulso baixo para o pino 5 do Mini-DIN (detectar dispositivo de entrada), como mostrado na função abaixo (ddPin é o pin 5 do Arduino conectado ao pin% do Roomba):


 
void wakeUp (void)
{
  digitalWrite(ddPin, HIGH);
  delay(100);
  digitalWrite(ddPin, LOW);
  delay(500);
  digitalWrite(ddPin, HIGH);
  delay(2000);
}
 

Para iniciar o Roomba, sempre devem ser enviados 2 códigos : “START” [128] e o modo, no nosso caso “modo de segurança” [131]. Se você quizer o “modo completo”, deve enviar o código [132].


 
void startSafe()
{
  Roomba.write(128); //Start
  Roomba.write(131); //Safe mode
  delay(1000);
}
 

PASSO 5: LIGAR OS LEDS E VISOR


Ligando os LEDs

Conforme descrito na introdução, o Roomba possui 5 LEDs:



  • POWER/CLEAN (bicolor vermelho / verde e intensidade controlada)

  • SPOT (Verde, intensidade fixa)

  • DOVK (verde, a intensidade fixa)

  • WARNING / Check (Laranja, intensidade fixa)

  • DIRT (azul, intensidade fixa)


Todos os LEDs podem ser comandados usando o código [139]


Para controlar o LED POWER/CLEAN, você deve enviar dois bytes de dados para o Roomba: “cor” e “intensidade”.



  • Cor:

    • Verde = 0

    • Laranja = 128

    • vermelho = 255



  • Intensidade:

    • Min = 0

    • Max = 255




A função setPowerLED (byte setColor, byte setIntensity) faz isso automaticamente:


 
void setPowerLED(byte setColor, byte setIntensity)
{
    color = setColor;
    intensity = setIntensity;
    Roomba.write(139);
    Roomba.write((byte)0x00);
    Roomba.write((byte)color);
    Roomba.write((byte)intensity);
}
 

Por exemplo, para acender o LED POWER com cor de laranja e na metade de sua intensidade maxima, você pode chamar a função como abaixo:


 
setPowerLED (128, 128);
 

Para acender os restantes 4 LEDs, devem ser utilizadas as funções:


 
   setDebrisLED (ON);

   setDockLED (ON);

   setSpotLED (ON);

   setWarningLED (ON);
 

Todas as funções acima tem um código semelhante a este:


 
void setDebrisLED(bool enable)
{
  debrisLED = enable;
  Roomba.write(139);
  Roomba.write((debrisLED ? 1 : 0) + (spotLED ? 2 : 0) + (dockLED ? 4 : 0) + (warningLED ? 8 : 0));
  Roomba.write((byte)color);
  Roomba.write((byte)intensity);
}
 

Basicamente, a diferença estará na linha:


 
debrisLED = enable;
 

IMG_4305


 


 


a qual deverá ser alterada permitindo (“enabling”) que cada um dos outros LEDs (spotLED, dockLED, warningLED) acenda.





Envio de mensagens a serem mostradas

O Roomba possui quatro Displays de 7 Segmentos que você podem ser usados para enviar mensagens de duas maneiras diferentes:



  • Código [163]: LEDs com dígitos numéricos (“Raw”)

  • Código [164]: LEDs com dígitos ASCII (aproximação de letras e códigos especiais)


Para exibir números é muito facil. Você apenas deve enviar o código [163], seguido dos 4 dígitos a serem  exibidos. A função:


setDigitLEDs (digit1 byte, digit2 byte, digit3 byte, byte digit4)


faz isso para si:


 
void setDigitLEDs(byte digit1, byte digit2, byte digit3, byte digit4)
{
    Roomba.write(163);
    Roomba.write(digit1);
    Roomba.write(digit2);
    Roomba.write(digit3);
    Roomba.write(digit4);
}
 

Por exemplo, para exibir “1, 2, 3, 4”, basta chamar a função:


 
setDigitLEDs(1, 2, 3, 4);
 

Com o código [164], é possível aproximação de envio de ASCII.


A função: setDigitLEDFromASCII(byte digit, char letter) faz isso para nós:


 
void setDigitLEDFromASCII(byte digit, char letter)
{
  switch (digit){
  case 1:
    digit1 = letter;
    break;
  case 2:
    digit2 = letter;
    break;
  case 3:
    digit3 = letter;
    break;
  case 4:
    digit4 = letter;
    break;
  }
  Roomba.write(164);
  Roomba.write(digit1);
  Roomba.write(digit2);
  Roomba.write(digit3);
  Roomba.write(digit4);
}
 

Para simplificar, criei uma nova função que pode ser utilizada para enviar os 4 dígitos ao mesmo tempo:


 
void writeLEDs (char a, char b, char c, char d)
{
  setDigitLEDFromASCII(1, a);
  setDigitLEDFromASCII(2, b);
  setDigitLEDFromASCII(3, c);
  setDigitLEDFromASCII(4, d);
}
 

Por exemplo, para exibir “STOP”, você deve chamar a função:


 
writeLEDs ( "s", "t", "o", "p");
 

IMG_4304


PASSO 6: PILOTANDO O ROOMBA PELA CASA


Para sua mobilidade, o Roomba possui 2 motores DC independentes que podem ser programados para rodar a uma velocidade de até 500 mm/s. Existem vários comandos que podem ser usados para dirigir o robô. Os principais são:



  1. Código [137]: Drive ==> devem ser enviados: +/- velocidade em mm/s e +/- Radius em mm

  2. Código [145]: Direct Drive ==> deve ser enviado velocidade à Esquerda/Direita em mm/s (+ para a frente e – para trás)

  3. Código [146]: Drive PWM ==> devem ser enviados +/- dados PWM individualmente para as rodas esquerda e direita.


Abaixo o código para essas 3 opções descritas anteriormente:


 
void drive(int velocity, int radius)
{
  clamp(velocity, -500, 500); //def max and min velocity in mm/s
  clamp(radius, -2000, 2000); //def max and min radius in mm
 
  Roomba.write(137);
  Roomba.write(velocity >> 8);
  Roomba.write(velocity);
  Roomba.write(radius >> 8);
  Roomba.write(radius);
}

//---------------------------------------------------------------

void driveWheels(int right, int left)
{
  clamp(right, -500, 500);
  clamp(left, -500, 500);
 
  Roomba.write(145);
  Roomba.write(right >> 8);
  Roomba.write(right);
  Roomba.write(left >> 8);
  Roomba.write(left);
  }

//---------------------------------------------------------------
void driveWheelsPWM(int rightPWM, int leftPWM)
{
  clamp(rightPWM, -255, 255);
  clamp(leftPWM, -255, 255);
 
  Roomba.write(146);
  Roomba.write(rightPWM >> 8);
  Roomba.write(rightPWM);
  Roomba.write(leftPWM >> 8);
  Roomba.write(leftPWM);
}
 

Note que a função “clamp” define os valores máximos e mínimos que são permitidos para como entrada. Essa função é definida no arquivo rombaDefines.h :


 
  #define clamp(value, min, max) (value < min ? min : value > max ? max : value)
 

Usando os códigos descritos acima, funções mais simples podem ser criadas para mover o Roomba:


 
void turnCW(unsigned short velocity, unsigned short degrees)
{
   drive(velocity, -1);
   clamp(velocity, 0, 500);
   delay(6600);
   drive(0,0);
}

//---------------------------------------------------------------
void turnCCW(unsigned short velocity, unsigned short degrees)
{
   drive(velocity, 1);
   clamp(velocity, 0, 500);
   delay(6600);
   drive(0,0);
}

//---------------------------------------------------------------
void driveStop(void)
{
 drive(0,0);
}

//---------------------------------------------------------------
void driveLeft(int left)
{
 driveWheels(left, 0);
}

//---------------------------------------------------------------
void driveRight(int right)
{
 driveWheels(0, right);
}
 

Note-se que para se obter um valor de ângulo correto, o argumento da função “delay” deve ser calculada especificamente para uma dada velocidade (o método de tentativa e erro é a melhor opção aqui).


Abaixo alguns exemplos que podem ser utilizados para testar os motores:


 
  turnCW (40, 180); // girar no sentido horário em 180 graus e parar

  driveWheels (20, -20); // girar sobre seu eixo ("spin") a uma velocidade de 20mm/s

  driveLeft (20); // Virar à esquerda a uma velocidade de 20mm/s
 

IMG_4307


 


Para testar os motores, é bom adicionar um botão externo (no meu caso ligado ao Arduino pino 12), de modo a que você possa baixar o código para o Arduino, iniciando o Roomba, mas parando a execução até que o botão seja é pressionado.


 


Abaixo, simples exemplo de um código de testes para os motores utilizando-se Arduino (observe que para o codigo ser executado, funções e definições discutidas nos steps anteriores deverão ser utilizadas):


 
#include "roombaDefines.h"
#include

// Roomba Create2 connection
int rxPin=10;
int txPin=11;
SoftwareSerial Roomba(rxPin,txPin);

//---------------------------------------------
void setup()
{
   Roomba.begin(19200);
 
   pinMode(ddPin, OUTPUT);
   pinMode(buttonPin, INPUT_PULLUP); // connected to Arduino pin 12 and used for "starting"

   delay(2000);
 
   wakeUp (); // Wake-up Roomba
   startSafe(); // Start Roomba in Safe Mode

   while (digitalRead(buttonPin)) { } // wait button to be pressed to continous run code
 
   turnCW (40, 180); //test Roomba spin clock-wise 180 degrees and stop
}

//---------------------------------------------
void loop()
{
}
 

PASSO 7: CONTROLANDO ROOMBA VIA BLUETOOTH


Para completar a nossa primeira parte do projeto, vamos instalar um módulo Bluetooth (HC-06) para a nosso Arduino. O diagrama abaixo mostra como fazê-lo.


Serial_BT_Conn


Normalmente, o HC-06 é fornecido de fábrica com uma taxa de transmissão de 9600 bauds. É importante que você o altere para 19.200, de maneira a ser compatível com a velocidade de comunicação utilizada pelo Arduino-Roomba. Você pode fazer isso enviando um comando AT para o módulo (AT + BAUD5 onde “5” é o código para 19.200).


Se você tem alguma dúvida sobre como o HC-06 trabalha, por favor dê uma olhada no meu tutorial: Conectando “coisas” através do Bluetooth


Para guiar o Roomba, vamos utilizar um aplicativo genérico para controle de robôs móveis que desenvolvi a partir do MIT AppInventor 2: “MJRoBot BT Remote Control”. O aplicativo pode ser baixado gratuitamente a partir da loja Google.



O aplicativo tem uma interface simples, o que lhe permite enviar comandos para o módulo de BT em ambos, modo texto ou directamente através de botões pré-programados (cada vez que um botão é pressionado, um caracter é enviado):



  • w: Foreward

  • s: Backward

  • d: Right

  • a: Left

  • f: Stop

  • p: ON / OFF (não utilizado nesta primeira parte)

  • m: manual / automatic (utilizado para reiniciar o Roomba caso ele esteje em modo de segurança e encontre um obstáculo como um degrau por exemplo)

  • +: Velocidade Up

  • -: Speed -Down


Você também pode enviar outros comandos como texto, se necessário. Há também uma janela de texto para exibição de mensagens recebidas a partir do módulo de BT. Esta característica é muito importante durante a fase de testes, pode ser usada da mesma forma que o “Serial Monitor” do PC.


A função loop () do código será a responsável pela “escuta” do dispositivo bluetooth e dependendo do comando recebido, tomar uma ação:


 
void loop()
{
   checkBTcmd(); // verify if a comand is received from BT remote control
   manualCmd ();
}
 

A função checkBTcmd () é mostrada abaixo:


 
void checkBTcmd() // verify if a command is received from BT remote control
{
  if (BT1.available())
  {
    command = BT1.read();
    BT1.flush();
   }
}
 

Uma vez que um comando é recebido, a função manualCmd () irá tomar as medidas apropriadas:


 
void manualCmd()
{
  switch (command)
  {
     case "m":
        startSafe();
        BT1.print("Roomba BT Ctrl OK - Safe mode");
        BT1.println("
");
        command = "f";
        playSound (3);
        break;
 
     case "f":
        driveStop(); //turn off both motors
        writeLEDs ("s", "t", "o", "p");
        state = command;
        break;

     case "w":
        drive (motorSpeed, 0);
        writeLEDs (" ", "g", "o", " ");
        state = command;
        break;

     case "d":
        driveRight(motorSpeed);
        writeLEDs ("r", "i", "g", "h");
        break;

     case "a":
        driveLeft(motorSpeed);
        writeLEDs ("l", "e", "f", "t");
        break;
 
     case "s":
        drive (-motorSpeed, 0);
        writeLEDs ("b", "a", "c", "k");
        state = command;
        break;

     case "+":
        if (state == "w")
        {
          motorSpeed = motorSpeed + 10;
          if (motorSpeed > MAX_SPEED)
          {
             motorSpeed = MAX_SPEED;
           }
           command = "w";
         } else {command = state;}
         break;

     case "-":
 
        if (state == "w")
        {
          motorSpeed = motorSpeed - 10;
        }
        if (motorSpeed < MIN_SPEED )
        {    
          motorSpeed = MIN_SPEED;
         }
         command = state;
         break;
     }
}
 

PASSO 8: CONCLUSÃO


O código Arduino completo e  documentos relacionados podem ser encontrados neste depositário do GitHub: Roomba_BT_Ctrl.


Observe que nem todos os atuadores e sensores do Roomba foram discutidos neste tutorial. Existem outros motores utilizados especificamente para a limpeza, LEDs utilizados para a programação, botões, sensores, etc.


Várias das funções que criei em meu programa foram baseados na biblioteca Create 2 desenvolvida por Dom Amato. Você pode descarregar a biblioteca completa através do link: https://github.com/brinnLabs/Create2


 



14
Projetos / Estação meteorológica doméstica com NodeMCU e OLED
« Online: Dezembro 08, 2017, 09:21:56 am »
Estação meteorológica doméstica com NodeMCU e OLED




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



 


Lista de materiais:



  • Placa NodeMcu Lua Wifi ESP8266 ESP-12F

  • 0.96″ I2C IIC SPI Serial 128X64 White OLED LCD LED Display Module

  • Sensor de humidade e temperatura DHT 22 AM2302

  • Mini Breadboard

  • Cabos Jumper Macho-Macho

  • Fonte externa de 5V ou bateria


 


Instalando o OLED no NodeMCU



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


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



  • Tamanho da tela: 0.96 “

  • Comunicação Serial I2C IIC SPI

  • 128X64

  • Display de caracteres na cor branca


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



  • SDA ==> D1 (5)

  • SCL * ==> D2 (4) * Também poderá encontrar “SDC” ao invés de SCL

  • VCC ==> 3.3V ou 5V

    GND ==> GND


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


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


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


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


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


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


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

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


A-Controle de exibição do display:


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


B-Desenho gráfico


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


C-Operações com texto:


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

// Available default fonts: ArialMT_Plain_10, ArialMT_Plain_16, ArialMT_Plain_24

D. Frames (“Ui Library”)


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


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

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



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

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


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


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


Obtendo os dados internos (“Indoor”)



 


Neste momento, nosso NodeMCU já pode se comunicar com o mundo pelo display! Instalemos agora o sensor de humidade e temperatura DHT 22 AM2302, nosso bom e velho DHTxx (DHT11 ou DHT22). Abaixo tem algumas informações que de devemos saber sobre este sensor:


Visão geral


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


DHT11 vs DHT22


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


DHT11



  • Bom para leituras de 20-80% de humidade com 5% de precisão

  • Bom para leituras de temperatura de 0-50 ° C ± 2 ° C de precisão

  • Não mais de 1 Hz taxa de amostragem (uma vez por segundo)

  • Ultra baixo custo

  • Alimentação: 3 a 5V

  • Consumo: 2.5mA max (durante a conversão de dados)

  • Tamanho do corpo 15.5mm x 12mm x 5.5mm

  • 4 pinos com espaçamento de 0,1 “


DHT22



  • Bom para leituras de 0-100% de humidade com precisão de 2 a 5%

  • Bom para leituras de temperatura de -40 a 125 ° C Precisão de ± 0,5 ° C

  • Não mais de 0,5 Hz taxa de amostragem (uma vez a cada 2 segundos)

  • Baixo custo

  • Alimentação: 3 a 5V

  • Consumo: 2.5mA max (durante a conversão de dados)

  • Tamanho do corpo 15.1mm x 25mm x 7.7mm

  • 4 pinos com espaçamento de 0,1 “


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


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



  • VCC (conectado a 5V externo ou a 3.3V de NodeMCU)

  • Dados

  • Não conectado

  • Terra.



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


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


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


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


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

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


<pre class=”brush:cpp c”>


/***************************************************

* Get indoor Temp/Hum data

****************************************************/

void getDHT()

{

float tempIni = localTemp;

float humIni = localHum;

localTemp = dht.readTemperature();

localHum = dht.readHumidity();

if (isnan(localHum) || isnan(localTemp)) // Check if any reads failed and exit early (to try again).

{

Serial.println(“Failed to read from DHT sensor!”);

localTemp = tempIni;

localHum = humIni;

return;

}

}


</pre>


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


<pre class=”brush:cpp c”>


/***************************************************

* Draw Indoor Page

****************************************************/

void drawDHT()

{

int x=0;

int y=0;

display.setFont(ArialMT_Plain_10);

display.setTextAlignment(TEXT_ALIGN_LEFT);

display.drawString(0 + x, 5 + y, “Hum”);


display.setFont(ArialMT_Plain_10);

display.setTextAlignment(TEXT_ALIGN_LEFT);

display.drawString(43 + x, y, “INDOOR”);


display.setFont(ArialMT_Plain_24);

String hum = String(localHum) + “%”;

display.drawString(0 + x, 15 + y, hum);

int humWidth = display.getStringWidth(hum);


display.setFont(ArialMT_Plain_10);

display.setTextAlignment(TEXT_ALIGN_LEFT);

display.drawString(95 + x, 5 + y, “Temp”);


display.setFont(ArialMT_Plain_24);

String temp = String(localTemp) + “°C”;

display.drawString(70 + x, 15 + y, temp);

int tempWidth = display.getStringWidth(temp);

}


</pre>


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



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


Home Weather Station Indoor code


Obtendo os dados externos (“Outdoor”):



Nossos dados meteorológicos serão fornecidos por um serviço gratuito, o “Weather Underground“. Você precisará criar uma conta em seu site e obter uma chave para poder se utilizar da API. Faça-o, seguindo as instruções no link abaixo:


https://www.wunderground.com/weather/api


Nossa estação meteorológica doméstica é baseada no extraordinário trabalho desenvolvido por Daniel Eichhorn (@ squix78). Siga as instruções constantes de seu GitHub para obter as bibliotecas apropriadas. Você precisará ao menos, instalar as bibliotecas abaixo:



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


MJRoBot Home Weather Station code


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


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

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

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



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


A última etapa é montar nossa estação numa caixa. Fiz duas montagens diferentes em caixas plásticas.


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


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




15
Projetos / O braço robótico: Desenvolvimento do Projeto
« Online: Dezembro 08, 2017, 09:21:16 am »
O braço robótico: Desenvolvimento do Projeto



 


O circuito como comentado no meu post anterior:


O braço robótico – Introdução


Será baseado no Arduino MEGA, alguns potenciômetros, botões e LEDS para o “painel de controle local”.



Um modulo HC-06  vai ligar o braço, via rede Bluetooth, com um telemóvel Android (controle em modo remoto).


BRAÇOS ROBÓTICOS:


Os braços robóticos podem ser classificados segundo o número de “juntas”, ou “graus de liberdade” (DOF – Degree of Freedom) que possuem. Por exemplo:



  • 4dof-robotBase giratória (de 360 ou 180 graus). A base é conhecida como “Waist” ou simplesmente “Base”.

  • O ombro ou “Shoulder” é o responsável por levantar ou abaixar o braço na vertical

  • O cotovelo ou”Elbow”, fará o braço ir para a frente ou para trás.

  • A garra ou “Gripper” (em alguns casos “Claw”), funciona abrindo ou fechando para “agarrar coisas”.



Observe que nesse diagrama só o braço propriamente dito já possui 3 DOF. A garra que no caso do meArm (4DOF) adiciona o quarto elemento. Nesse projeto ficaremos por aqui (até 4 DOF), mas é obvio que poderíamos ter mais “juntas no corpo”  e principalmente a garra poderia ser mais sofisticada com 2 ou 3 DOF (rotação e elevação).


easyarmdf


O braço ao lado por exemplo, possui 5DOF e foi desenvolvido pela EASYDS, que possui uma linha completa de Kits Robóticos Educacionais em MDF. Vale a pena dar uma olhada no site.


O CIRCUITO:


Para o acionamento das juntas serão utilizados servo motores conectados diretamente ao Arduino, mas poderiam também ser utilizados “Stepper Motors” para maior torque e precisão.


A escolha adequada dos servos é muito importante (existem servos baratos chineses que são muito mal construídos como por exemplo o MG995, que infelizmente são os que vieram com meu SanSmart 3DOF aArm) .


A alimentação dos servos deve ser separada do Arduino e demais componentes. Uma fonte externa de 5 a 6V deve funcionar sem problemas (verifique o datasheet de seus servos para verificar a faixa de voltagem apropriada). Uma prática comum também é a utilização de capacitores de 470uF entre VCC e GND para minimizar os ruídos gerados pelos motores internos dos servos.  Não se esqueça de conectar todos os terras (fonte externa com  o Arduino).


Caso os servos tenham problemas e vibrem muito, faça ajustes nos delays de seu codigo. É importante que os servos tenham tempo para chegar a um determinado ponto antes de receber um novo comando. Também vale a pena verificar se os servos são digitais ou analógicos, pois apesar de serem parecidos mecanicamente, os digitais trabalham em uma frequência de 300Hz enquanto que os analógicos com 50Hz. A biblioteca standard do Arduino  foi desenvolvida para servos analógicos e podem ser modificadas caso necessário, para para um melhor funcionamento com servos digitais.


Abaixo o diagrama completo:


O CÓDIGO:


O projeto não é complicado, mas possui muitas variáveis. O mais prudente foi definir-las claramente e deixar suas declarações en um arquivo exclusivo:


ArmDefine.h

No arquivo também foram definidos os valores mínimo, máximo e iniciais para os servos. No codigo incluído nesse tutorial, existem dois conjuntos de parâmetros referentes aos braços robóticos que testei em meu projeto (claro que somente um grupo de constantes deverá ser utilizado):



  1. MeArm 4-DOF


    • #define minGrip 15 
      #define minBase 0
      #define minShou 60
      #define minElbw 60



    • #define maxGrip 45 
      #define maxBase 170
      #define maxShou 180
      #define maxElbw 150

      #define midGrip 30
      #define midBase 87
      #define midShou 138
      #define midElbw 100




  2. SS 3-DOF


    • #define minGrip 75 
      #define minBase 5
      #define minShou 5
      #define minElbw 0

      #define maxGrip 125 
      #define maxBase 150
      #define maxShou 155
      #define maxElbw 0

      #define midGrip 100
      #define midBase 90
      #define midShou 90
      #define midElbw 0





Para cada tipo de braço vão existir parâmetros distintos e é importante que você encontre os correctos para o seu. O que sugiro é que inicialmente os potenciômetros fiquem em seu ponto médio e que o Mapping das saídas PWM sejam definidas com os valores standard: Max = 255, Min = 0 e Mid = 126 (“#defines” acima). Ao se ir variando os potenciômetros (um a um), deve-se observar no Monitor Serial (ou LCD) quais deverão ser os valores mínimos e máximos em que o braço trabalhará corretamente. Estes serão os valores finais a serem utilizados para as definições.


Para a “gravação” dos conjuntos de coordenadas (ou steps) que o robot deverá reproduzir, utilizarei arrays de dados:


 
int gripPosition[100];
int basePosition[100];
int shouPosition[100];
int elbwPosition[100];
 

 
int positionIndex = 0;
 

Observe que não estou guardando as posições “gravadas” e ao finalizar -se o “programa do robot”, o índice voltará a zero e o robot esperará pela gravação de uma nova sequência. Se poderia guardar esses arrays de dados na EEPROM do Arduino, por exemplo. Isso faria com que o programa pudesse ser executado infinitas vezes, ou até mesmo possuir mais de um programa armazenado. Fica aqui a dica para o desenvolvimento de um projeto mais sofisticado.


A lógica do programa:

O bloco principal (“Loop”) é na verdade bem simples:



  1. Verifica se há mensagens no buffer serial, provenientes do Android

  2. Se há mensagens, verifica se o controle deverá ser Local ou Remoto ( o default é Local).

  3. Verifica se existe um comando para executar o “programa” (sequencia de passos). Se existe, o executa. Do contrário, entende que o “programa” não está completo e ainda se devem gravar novos passos.

  4. Se há uma nova posição é definida, adiciona a mesma ao programa

  5. Volta ao início e executa o passo 1 novamente.


 
void loop()
{
  checkBTcmd();
  defineLocalRemote();
 
  execTaskCmd = digitalRead (execTaskPin);
  if(execTaskCmd == HIGH || command == "runon")
  {
    runProgram();
  }
  else recArmPosition();
  command = "";
}
 

A função checkBTcmd() monta uma string a partir dos caracteres que chegam do modulo BT. Essa string é passada a variável “command”.


A função defineLocalRemote() analisará  a variável “command” verificando se um comando para mudar a função de local a remoto ou vice e versa é recebida. O comando de Alarm também é analisado aqui. Pela lógica do programa, se “Alarm” for acionado no no Android,significará que o braço deverá  passar obrigatoriamente ao modo Remoto.


A função runProgram () executará as preparações, como acender/apagar os LEDS correspondentes, etc. e principalmente invocará a função: executeTask(). Essa última, é a função que contem a lógica de execução da sequencia de steps. A função incrementa o “positionIndex” enviando ao braço uma a uma,  as coordenadas para seu posicionamento usando a função: armPosition(grip, base, shoulder, elbow).


Por último, a função que realmente comandará os servos e gravará os “steps” é a recArmPosition(). Dependendo do comando recebido do Android, esta função deverá definir se o posicionamento dos servos será comandado através dos potenciômetros, ou através dos “sliders” do Android. A cada mudança de posição, esta função enviará as coordenadas aos servos via a função armPosition(grip, base, shoulder, elbow). A leitura da posição dos potenciômetros ou dos sliders e o correspondente acionamento dos servos ocorrerá até o momento em que o comando de “Gravar” ou “PROGRAM” seja acionado. Nesse momento o índice de posição dos Arrays será incrementado e as coordenadas guardadas.


Para simplificação de entendimento, todo o codigo foi baseado em funções específicas. O bloco de Setup, Loop e as funções descritas anteriormente estão praticamente todas no file:


 
MJRoBot_Arm_Robot_Task_Prgm.ino
 

As funções mais gerais como leituras de comandos BT: void checkBTcmd(); gerador de som: void beep(int pin, int freq, long ms)  e debouncing : boolean debounce(int pin); estão no file:


 
General_Functions.ino
 

Um dado importante. Como o Arduino executará instruções baseadas em um clock de 16Mhz, é de se esperar que os botões de comando sejam lidos centenas ou até milhares de vezes por segundo, daí ser importantíssimo fazer um “debouncing” do botão que define a gravação do step.


O quarto e último file que compõe o código é:


 
Arm_Ctrl_and_Display.ino
 

Nesse file estão principalmente as funções de leitura de potenciômetros: bool readPotenciometers(); leitura dos sliders do Android: bool readSliders(); posicionamento dos servos: void armPosition(int gripp, int basee, int shoulder, int elbow). As demais funções do file são auxiliares para display de dados no LCD, Serial Monitor, alarmes, etc.


O código completo para o projeto pode ser baixado aqui:


Link para o código do Arduino


Abaixo um vídeo do braço robótico 4DOF “meArm”:



No vídeo o braço está sendo programado remotamente através da nova versão da app Android


androidapp


A app pode ser descarregada gratuitamente aqui:


MJRoBot Arduino Arm Robot Ctrl.


Toda a documentação para o projeto pode ser descarregada a partir deste GitHub


Agora é só colocar a mão na massa, quer dizer no Arduino e começar a trabalhar!



Páginas: [1] 2 3 4