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:
- Dos Arduinos
- Raspberry Pi
- Sensor de humedad del suelo
- RTC
- NRF24L01
- Jumpers
[amazon_textlink asin=’B00MPB1X5S|B00MPB1X5S|B01FLRVBTA|B06XGVMF99|B06XJN417D|B01ICU18XC’ text=» template=’PCGuille’ store=’eelektronic06-21|eelektronic03-21|eelektronic0c-21|eelektronic00-21|eelektroni076-21|electroni0d54-20′ marketplace=’ES|DE|UK|IT|FR|US’ link_id=’9e5e7eba-ee95-11e7-8b15-bdd1f4bcbb5d’]
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
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
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
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.
Soy un pensionista que mata el tiempo con la Elektrónica y con Arduino
Desearía vuestra información de Electrónica
Muy bien Trancos. Entonces en tu lista de subscriptor te añadiremos a la categoría de Electrónica/Arduino.
Saludos