Go Down

Topic: [solved]Sending sensor readings using RadioHead (Read 2161 times) previous topic - next topic

simpa

Oct 25, 2015, 05:25 pm Last Edit: Oct 26, 2015, 11:05 am by simpa
Hi, I'm trying to make 2 Arduinos communicate over RF 434MHz using the RadioHead library. One of the Arduinos will take some sensor readings, right now it's only temperature and soil moisture content but I plan to add more sensors later. The temperature reading is stored as a float and the soil moisture as an int. What I want to do is pass this variables to the send-function and transmit them both at the same time. So I want all the readings to be sent in the same transmission and I will then have to split them up on the receiving side.

My sketch now looks like this (far from being finished but I want to solve this problem first):

Code: [Select]
#include <RHDatagram.h>
#include <RH_ASK.h>
#include <SPI.h>
#include <OneWire.h>
#include <DallasTemperature.h>

//RH communication
#define CLIENT_ADDRESS 2
#define SERVER_ADDRESS 1
// Singleton instance of the radio driver
RH_ASK driver;
// Class to manage message delivery and receipt, using the driver declared above
RHDatagram manager(driver, CLIENT_ADDRESS);

//OneWire sensors
// Data wire is plugged into port 16 on the Arduino
#define ONE_WIRE_BUS 10
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

void setup()
{
  Serial.begin(9600);
  
  //RF communication
  if (!manager.init())
    Serial.println("init failed");

  // OneWire sensors
  sensors.begin();

}

  // RH communication, Dont put this on the stack:
  uint8_t buf[RH_ASK_MAX_MESSAGE_LEN];

void loop()
{
  float tempValue;
  int soilValue;
  tempValue = temperature();
  delay(1000);
  soilValue = soil();
  delay(1000);
  SendValues();
  Serial.println ("");
   delay(2000);
}

//RH communication
void SendValues()
{

  uint8_t data[] = "Hello World";
  
  Serial.println("Sending to ask_datagram_server");
  int i = 0;
  int repeat = 5; //Times to repeat same message
    
  // Send a message to manager_server
  while (i<repeat)
  {
    if (manager.sendto(data, sizeof(data), SERVER_ADDRESS))
    {
      Serial.println("Message sent");  
    }
    else
    {
      Serial.println("sendto failed");
    }
    
    delay(100);
    i = i+1;
  }
}

//Get temperatures from Dallas sensor
float temperature()
{
  float temp;
  // issue a global temperature request to all devices on the bus
  Serial.print("Requesting temperatures from all...");
  sensors.requestTemperatures(); // Send the command to get temperatures
  Serial.println("DONE");
  // Print temperatures
  Serial.print("Temperature for the device 1 (index 0) is: ");
  Serial.println(sensors.getTempCByIndex(0));  
  temp = sensors.getTempCByIndex(0);
  return temp;
}

//Soil hygrometer
int soil()
{
 int humidity = 0;

 // read soil moisture from sensor
 int sensorValue = analogRead(A1);
 int sensorValueCons = sensorValue;
 
 sensorValueCons = constrain (sensorValue, 300,1023);
 //Sensor value 300 equals 100% humidity and sensor value 1023 equals 0% humidity

 humidity = map (sensorValueCons, 300, 1023, 100, 0);
 Serial.print ("Soil hygrometer: ");
 Serial.print (humidity);
 Serial.println ("%");
 //Print sensor value
 Serial.println ("Soil hygrometer sensor value: ");
 Serial.println (sensorValue);
 return humidity;
}


As you can see right now the send-function only sends "Hello world!" and the function does not accept any variables to be passed on to it. The values I want to send are stored in soilValue and tempValue present in the main loop. I assume I will need to convert the variable type and then combine them in some way, then pass it on to the send-function. I'm however not sure how to do this and could use some help here ;) Perhaps I got it completely wrong and there is a much smarter way to do all of this :P

Johnny010


Make a "packet" array for ints:

Code: [Select]
char int_packet[3]; //2 for int bytes and one for end of string thingy '/0'.

Convert the int in to 2 bytes:

Code: [Select]


int_packet[0]= the_int_to_be_sent;
int_packet[1]= the_int_to_be_sent >> 8; //Shift 8 bits along and store the least sig. 8 in a char.
int_packet[2]= '/0';


Then just send the contents of "int_packet".

The RX code then takes each byte at a time:
Reverse the bit shifting process to make the original int:

Code: [Select]
byte lowbyte=recieved_byte[0];
byte highbyte=recieved_byte[1];

int recieved_int=lowbyte+(highbyte << 8);

jremington

#2
Oct 25, 2015, 09:48 pm Last Edit: Oct 25, 2015, 09:50 pm by jremington
Reply #1 in this post shows you how to send and receive a few sensor readings with RadioHead.

simpa

The method described in that post worked perfect. Very nice method to send the whole data structure, made everything so much easier. Thank you.

I did some modification to get it to work with RHDatagram as manager. Will also use it with RHReliableDatagram later.

Posting my code again if someone else is looking for a solution like this.

Transmitter
Code: [Select]
#include <RHDatagram.h>
#include <RH_ASK.h>
#include <SPI.h>
#include <OneWire.h>
#include <DallasTemperature.h>

//RH communication
#define CLIENT_ADDRESS 2
#define SERVER_ADDRESS 1
// Singleton instance of the radio driver
RH_ASK driver;
// Class to manage message delivery and receipt, using the driver declared above
RHDatagram manager(driver, CLIENT_ADDRESS);

//OneWire sensors
// Data wire is plugged into port 16 on the Arduino
#define ONE_WIRE_BUS 10
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

struct dataStruct{
  float tempValue;
  int soilValue;
  int soilRaw;
  unsigned long counter;
   
}SensorReadings;

 // RF communication, Dont put this on the stack:
  byte buf[sizeof(SensorReadings)] = {0};

void setup()
{
  Serial.begin(9600);
 
  //RF communication
  if (!manager.init())
    Serial.println("init failed");

  // OneWire sensors
  sensors.begin();

  SensorReadings.tempValue = 0;
  SensorReadings.soilValue = 0;
  SensorReadings.soilRaw = 0;
  SensorReadings.counter = 0;
}

void loop()
{
  Serial.println("------------------------------------");
  float tempValue;
  int soilValue;
 
  temperature(); //Read temp sensor
  delay(1000);
 
  soilValue = soil(); //Read hygrometer
  delay(1000);
 
  SendValues(); //Send sensor values
  delay(2000);
  Serial.println("------------------------------------");
}

//Get temperatures from Dallas sensor
void temperature()
{
  // issue a global temperature request to all devices on the bus
  Serial.print("Requesting temperatures from all...");
  sensors.requestTemperatures(); // Send the command to get temperatures
  Serial.println("DONE");
  // Print temperatures
  Serial.print("Temperature for the device 1 (index 0) is: ");
  Serial.println(sensors.getTempCByIndex(0));
  Serial.println(""); 
  SensorReadings.tempValue = sensors.getTempCByIndex(0);
}

//Soil hygrometer
int soil()
{
 // read soil moisture from sensor
 int sensorValue = analogRead(A1);
 int sensorValueCons = sensorValue;
 
 sensorValueCons = constrain (sensorValue, 300,1023);
 //Sensor value 300 equals 100% humidity and sensor value 1023 equals 0% humidity

 SensorReadings.soilValue = map (sensorValueCons, 300, 1023, 100, 0);
 Serial.print ("Soil hygrometer: ");
 Serial.print (SensorReadings.soilValue);
 Serial.println ("%");
 //Print sensor value
 Serial.print ("Soil hygrometer sensor value: ");
 Serial.println (sensorValue);
 Serial.println("");
 SensorReadings.soilRaw = sensorValue;
}

//RF communication
void SendValues()

  //Load message into data-array
  //byte data[sizeof(sensorValues)];

  byte zize=sizeof(SensorReadings);
  memcpy (buf, &SensorReadings, zize);

 
  Serial.println("Sending to ask_datagram_server");
  int i = 0;
  int repeat = 10; //Times to repeat same message
   
  // Send a message to manager_server
  while (i<repeat)
  {
    if (manager.sendto(buf, zize, SERVER_ADDRESS))
    {
      Serial.println("Message sent");   
    }
    else
    {
      Serial.println("sendto failed");
    }
    delay(100);
    i = i+1;
  }
  SensorReadings.counter = SensorReadings.counter + 1;
}


Reciever
Code: [Select]
#include <RHDatagram.h>
#include <RH_ASK.h>
#include <SPI.h>

//#define CLIENT_ADDRESS 1
#define SERVER_ADDRESS 1

// Singleton instance of the radio driver
RH_ASK driver;
// Class to manage message delivery and receipt, using the driver declared above
RHDatagram manager(driver, SERVER_ADDRESS);

struct dataStruct{
  float tempValue;  //Store temperature sensor value (degC)
  int soilValue;    //Store soil moisture level (%)
  int soilRaw;      //Store hygrometer sensor reading
  unsigned long counter;
   
}SensorReadings;

void setup()
{
  Serial.begin(9600);
  if (!manager.init())
    Serial.println("init failed");

  SensorReadings.tempValue = 0;
  SensorReadings.soilValue = 0;
  SensorReadings.soilRaw = 0;
  SensorReadings.counter = 0;
}

void loop()
{
ReciveFromSensors();
}

void ReciveFromSensors()
{
  // Dont put this on the stack:
  uint8_t buf[sizeof(SensorReadings)];
  uint8_t from;
  uint8_t len = sizeof(buf);
 
  if (manager.available())
  {   
    // Wait for a message addressed to us from the client
    if (manager.recvfrom(buf, &len, &from))
    {
      int i;
      memcpy(&SensorReadings, buf, sizeof(SensorReadings));
      Serial.println("--------------------------------------------");
      Serial.print("Got message from unit: ");
      Serial.println(from, DEC);
      Serial.print("Transmission number: ");
      Serial.println(SensorReadings.counter);
      Serial.println("");
       
      Serial.print("Temperature: ");
      Serial.println(SensorReadings.tempValue);
       
      Serial.print("Soil moisture content: ");
      Serial.println(SensorReadings.soilValue);
       
      Serial.print("Hygrometer sensor reading");
      Serial.println(SensorReadings.soilRaw);
      Serial.println("--------------------------------------------");
    }
  }
}

Go Up