NRF24 Arduino – Raspberry Pi – Arduino

Hola a tod@s, en esta entrada os voy a enseñar como mandar a la Raspberry Pi, un dato desde un Arduino. Y a su vez, esta va enviar el dato recibido a otro Arduino. Este post tiene como objeto llevar variables de temperatura y humedad con la idea de automatizar un sistema de riego. Como comente en la anterior entrada, los datos que vamos a leer en el Arduino (a una hora determinada del día) van a ser los de un sensor de humedad del suelo.

Material necesario:

Emisor (Arduino 1)

Lo primero que vamos a hacer es tomar una muestra de 10 valores de humedad a una hora determinada del día y hacer la media. Para ello necesitamos usar el RTC y el sensor de humedad, de los cuales ya hemos realizado una entrada. Después, la humedad media que nos de, se la enviaremos mediante el NRF24L01 a la Raspberry Pi.

Montaje

Montaje emisor

 

Código

//EMISOR

#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"

#include <Wire.h> //llamado de libreria
#include "RTClib.h" //llamado de libreria DS1307

RTC_DS1307 RTC;

int humedad_inicial=0;
int humedad_total;
int humedad;
int i;
int led=2;
int humedad_porciento;
 
RF24 radio(9,10);     // Pines del NRF24L01

byte pipes[][6] = {"1Node","2Node"};


void setup() {
  Serial.begin(57600);
  pinMode(led, OUTPUT);
  Wire.begin();  //Inicia el puerto I2C
  RTC.begin();   //Inicia la comunicación con el RTC

  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");  
    RTC.adjust(DateTime(__DATE__, __TIME__));
   }
  
  // Ajuste y configuración rf
  radio.begin();                          // Comienza la radio
  radio.setAutoAck(1);                    // Ensure autoACK is enabled
  radio.setRetries(15,15);                // Max delay between retries & number of retries
  radio.openWritingPipe(pipes[0]);
  radio.openReadingPipe(1,pipes[1]);
  
  radio.startListening();                 // Empieza a escuchar
}


void loop(void){

  DateTime now = RTC.now();
  
  Serial.print(now.day(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.year(), DEC);
  Serial.print(' ');
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println();

  delay(1000);
  
 
 /* Dejamos de escuchar en la radio para poder emitir.
  * Leemos el valor de millis (o el parametro que queramos enviar)   
  * y lo enviamos para despues testear si la emision ha sido o no correcta   
  */
  radio.stopListening();               // Paramos la escucha para poder hablar
    
  unsigned long humedad_porciento;
  humedad_inicial=analogRead(0);

  if (now.hour()==16 & now.minute()==52 & now.second()==40){
            
    for(i=0; i<10; i++){         //hacemos las 10 medidas de humedad
      Serial.print("Humedad: ");
      Serial.println(humedad_inicial);
      humedad_total=humedad_total+humedad_inicial;
    }
   
    humedad=humedad_total/i;         //realizamos la media de las 10 medidas
    Serial.print("Humedad media: ");
    Serial.println(humedad);

    humedad_porciento = map(humedad, 0, 1023, 100, 0);
     Serial.print("Valor humedad:");  
     Serial.print(humedad_porciento); 
     Serial.println("%");
     
    Serial.print("Enviando ... ");// Take the time, and send it.  This will block until complete
    bool ok = radio.write( &humedad_porciento, sizeof(unsigned long));
    
    if (ok)
      Serial.println("OK ...");

    else
      Serial.println("Error");
        
    radio.startListening();   // Volvemos a la escucha

 /*Esperamos la confirmacion de que han recibido 
  *el mensaje en el destino, durante 200 ms.
  * Al salir comprobamos si se acabó el tiempo, 
  * o hemos recibido un mensaje
  */
    unsigned long started_waiting_at = millis();            // Set up a timeout period, get the current microseconds
    bool timeout = false;                                   // Set up a variable to indicate if a response was received or not


    while ( ! radio.available() && ! timeout){             //esperamos 200seg                
      if (millis() - started_waiting_at > 200 ){       
          timeout = true;
          break;
      }      
    }

  /*Si ha disparado el timeout imprimimos un mensaje de error
  * En caso contrario procesamos el mensaje recibido
  */
     
    if ( timeout ){                // Describe the results
      Serial.println("Error, no ha habido respuesta a tiempo.");
      digitalWrite(led, HIGH);    // turn the LED off by making the voltage HIGH
       // Try again 1s later
    delay(1000);
    return ;
    }
    
    else{       //leemos el mensaje recibido
      digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
      unsigned long envio;       // Grab the response, compare, and send to debugging spew
      radio.read( &envio, sizeof(unsigned long) );

      Serial.print("Humedad: ");
      Serial.println(envio); 
    }
    
    humedad_total=0;
    // Try again 1s later
    delay(925);
   }   
}

Receptor-Emisor (Raspberry Pi)

En esta parte la Raspberry Pi va a recibir la humedad del Arduino 1, va a gestionar esta humedad y va a enviarle al Arduino 2 un número que indique si hay que regar o no.
Os preguntaréis por qué no enviamos los datos directamente entre Arduinos, verdad?.  Pues el motivo es que queremos  que lo gestione la Raspberry Pi, para almacenar estos datos en una base de datos y mostrarlos en un servidor web (esto lo veremos en otra entrada más adelante).

Para poner a punto la Raspberry Pi hay que seguir los pasos de la anterior entrada.

Montaje

monatje Raspberry Pi con NRF24L01

 

Código

#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <RF24/RF24.h>

//#include <my_global.h>
#include <mysql.h>

char riego[64]="";
char riego1[]="NO REGAR";
char riego2[]="PARTE 1 (TIEMPO CORTO) Y NO REGAR PARTE 2 Y 3";
char riego3[]="PARTE 1, 2 Y 3 (TIEMPO CORTO)";
char riego4[]="PARTE 1 (TIEMPO LARGO) Y PARTE 2 Y 3 (TIEMPO CORTO)";
char riego5[]="PARTE 1, 2 Y 3 (TIEMPO LARGO)";


using namespace std;
//
// Hardware configuration
//



// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 8Mhz
RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ);


// Radio pipe addresses for the 2 nodes to communicate.
const uint8_t pipes[][6] = {"1Node","2Node"};
const uint8_t pipes_receptor[][6] = {"3Node","4Node"};

int test (unsigned long msg);


int finish_with_error(MYSQL *con)
{
  fprintf(stderr, "%s\n", mysql_error(con));
  mysql_close(con);
  return 1;        
}


int main(int argc, char** argv){      //inicio main

  // Setup and configure rf radio
  radio.begin();

  // optionally, increase the delay between retries & # of retries
  radio.setRetries(15,15);
  // Dump the configuration of the rf unit for debugging
  //radio.printDetails();

  radio.openWritingPipe(pipes[1]);
  radio.openReadingPipe(1,pipes[0]);
  radio.startListening();

  // forever loop
  while (1){      //inicio while

    if ( radio.available()){      //inicio if
      // Dump the payloads until we've gotten everything
				
      unsigned long humedad;
	
      // Fetch the payload, and see if this was the last one.
      while(radio.available()){
         radio.read( &humedad, sizeof(unsigned long) );
      }
	
      radio.stopListening();
      radio.write( &humedad, sizeof(unsigned long) );

      // Now, resume listening so we catch the next packets.
      radio.startListening();

      // Spew it
      printf("Humedad: %lu\n",humedad);			
      delay(925); 

      unsigned long msg_code;

      if (humedad<250){                //muy humedo
         printf("Humedad < 250\n");
         strcpy(riego,riego1);
         printf("%s\n", riego);
         msg_code = 1;
         //test(msg_code);
      }

      else if (humedad<400){                //humedo
         printf("Humedad entre 250 y 450\n");
         strcpy(riego,riego2);
         printf("%s\n", riego);
         msg_code = 2;
         //test(msg_code);
      }
	
      else{                                 //seco
         printf("Humedad > 450\n");
         strcpy(riego,riego3);
         printf("%s\n", riego);
         msg_code = 3;
         //test(msg_code);
      }


      printf("Humedad subida a la base de datos\n");
      //return 0;

      test(msg_code);
      return 0;
	
    } //fin if

  } // fin while

return 0;
} //fin main



int test (unsigned long msg){

   printf("Numero a enviar: %lu \n", msg);

   radio.stopListening();
   radio.openWritingPipe(pipes_receptor[0]);
   radio.openReadingPipe(1,pipes_receptor[1]);
  
	
   // First, stop listening so we can talk.
   radio.stopListening();

   // Take the time, and send it.  This will block until complete

   //printf("Now sending...\n");
   unsigned long time = millis();

   bool ok = radio.write( &msg, sizeof(unsigned long) );

   if (!ok){
      printf("failed.\n");
   }

   // Now, continue listening
   radio.startListening();

   // Wait here until we get a response, or timeout (250ms)
   unsigned long started_waiting_at = millis();
   bool timeout = false;
   while ( ! radio.available() && ! timeout ) {
      if (millis() - started_waiting_at > 200 )
         timeout = true;
   }

   // Describe the results
   if ( timeout ){
      printf("Failed, response timed out.\n");
   }
   else{
      // Grab the response, compare, and send to debugging spew
      radio.read( &msg, sizeof(unsigned long) );

      // Spew it
      //printf("Numero enviado (respuesta) %lu\n",msg);
   }

   // Try again 1s later
   delay(1000);
   return 0;

}

 

Receptor (Arduino 2)

Este Arduino recibirá un número, el cuál es enviado mediante la Raspberry Pi. En este caso este número indica si hay que regar o no. Más adelante incluiremos una electroválvula para poder regar o no, pero eso no es importante ahora.

 

Montaje

Receptor NRF24L01

 

Código

#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"
#include <Wire.h>

#define RELAY_ON 0
#define RELAY_OFF 1

int electro1=7;
int electro2=6;

// Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 9 & 10 
RF24 radio(9,10);

byte addresses[][6] = {"3Node","4Node"};


void setup() {

  Serial.begin(57600);
  
  digitalWrite(electro1, RELAY_OFF);
  pinMode(electro1,OUTPUT);//Declara una vía de la válvula como salida
  digitalWrite(electro2, RELAY_OFF);
  pinMode(electro2,OUTPUT);//Declara una vía de la válvula como salida

  printf_begin();
  
  // Setup and configure rf radio
  radio.begin();                          // Start up the radio
  radio.setAutoAck(1);                    // Ensure autoACK is enabled
  radio.setRetries(15,15);                // Max delay between retries & number of retries
  radio.openWritingPipe(addresses[1]);
  radio.openReadingPipe(1,addresses[0]);
  
  radio.startListening();                 // Start listening
  radio.printDetails();                   // Dump the configuration of the rf unit for debugging
}

void loop(void){

  if( radio.available()){    
    unsigned long numero;                                       // Variable for the received timestamp
    while (radio.available()) { 
       // While there is data ready
       radio.read( &numero, sizeof(unsigned long) );             // Get the payload
    }    

    radio.stopListening();                                        // First, stop listening so we can talk   
    // delay(2000);
    radio.write( &numero, sizeof(unsigned long) );              // Send the final one back.      
    radio.startListening();                                       // Now, resume listening so we catch the next packets.     
 
    if (numero==1){
       Serial.println("NO REGAR");
       digitalWrite(electro1, RELAY_OFF);
       digitalWrite(electro2, RELAY_OFF); 
    }

    else if (numero==2){
       Serial.println("REGAR POCO TIEMPO (1 hora)");
       digitalWrite(electro1,RELAY_ON);
       delay(3600000);   //1h
       digitalWrite(electro1, RELAY_OFF);
    }
            
    else{
       Serial.println("REGAR MUCHO TIEMPO (2 horas)");
       digitalWrite(electro1,RELAY_ON);
       digitalWrite(electro2,RELAY_ON);
       delay(7200000);   //2h
       digitalWrite(electro1, RELAY_OFF);
       digitalWrite(electro2, RELAY_OFF);
    }
  }
 
}

 

Espero que no os hayais liado mucho con tanto paso de un lado a otro. En la próxima entrada os explicaré como subir los datos que envía el Arduino a la Raspberry Pi a un servido web.
Ya nos queda muy poco para terminar nuestro regadio automatizado mediante microcontroladores.

 

 

Guardar

Guardar

Guardar

Guardar

Guardar

3 comentarios en “NRF24 Arduino – Raspberry Pi – Arduino”

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *