Binary data coercion

I have been wracking my brain for a week on this.

Using the SIMPLEdht library I can get a 40-bit binary data string, and I want to transmit this raw data using 433MHz transmitter.

Using RadioHead, I can send a fixed length character string. The problem is that the string length changes as we go from double figure to single figure to negative single figure to negative double figure temperatures, So I guessed it would be more practical to transmit the raw data and do any number crunching on the receiver side. To date, I have been padding out the transmission string to a longer string with spaces and removing them at the receiver. It works but I am looking for a simpler and more elegant method.

static char *msg = str_out.c_str();
  
  rf_driver.send((uint8_t *)msg, strlen(msg));

The way I understand the above code, is that each string character, that has been saved at specific memory location, is converted to set of 8 bit unsigned integers with a length of "strlen".

As I mentioned above, I already have 40 bits, i.e. five 8-bit bytes.

Could anyone enlighten me on how to prepare this data string for transmission, without coercing the binary to integers to text string, only to convert back for transmission?

Post your full code. Where did str_out come from?

Using RadioHead, I can send a fixed length character string.

You are using the library to send variable length strings.

Could anyone enlighten me on how to prepare this data string[\quote] Without seeing how you got the string? No.

It doesn't look you need to anything to the data string. When you send data, the number of bytes sent is part of the received data, so you can convert the array of chars back to a string.

There is no excuse for using Strings.

If we can assume that the message is a signed integer, we can send and receive the high and low bytes of the integer, without conversion to strings etc.

byte h = (myInt>>8) & 0xff;
rf_driver.send(h); // not familiar with the library
byte l = myInt & 0xff;
rf_driver.send(l);

On the receiving side, you read the received bytes into an array, for simplicity, of 2 bytes.

int myInt = buff[1] | (buff[0]<<8);

Sorry if I was too vague!

  1. str_out is an arbitrary string with a fixed length. Irrelevant to what I wish to achieve. Just an example of from the original demo sketch with the library description.

  2. rf_driver is the RH_ASK object, send is the method with parameters (data, length)

Unfortunately, I cannot find what the "data" type is, I assume it must be binary, all the manual says is stated above!

00010001 00110110 10000000 11010100 11001010 is a typical binary string from the DHT module

The first two bytes are humidity, the second two bytes are the temperature and the last byte is a checksum.

gfvalvo: Post your full code.

Now here is the code.

//433MHz Transmitter Module
//Wiring Left to Right
//Data(to pin D12), 5V, GND.

// RadoiHead Amplitude Shift Keying Library
#include <RH_ASK.h>
// SPI Library
#include <SPI.h>

// Create Amplitude Shift Keying Object
RH_ASK rf_driver;

//DHT22
//Wiring Left to Right
// for DHT22,
//      VCC: 5V or 3V
//      DATA: 2
//      Not Used
//      GND: GND

#include <SimpleDHT.h>
#include <string.h>

int pinDHT22 = 7;
SimpleDHT22 dht22(pinDHT22);

void setup() {
  Serial.begin(9600);
  
  // Turn built-in LED off
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  
  //Initialise ASK Object
  rf_driver.init();  
}

void loop() {
  delay(5000);
 
  float temperature = 0;
  float humidity = 0;
  byte myData[40] = {0};
  int err = SimpleDHTErrSuccess;
  if ((err = dht22.read2(&temperature, &humidity, myData)) != SimpleDHTErrSuccess) {
    Serial.println();
    Serial.println("Data Error                              ");
    Serial.println();
    return;
  } else {
    rf_driver.send(myData, 5);
    rf_driver.waitPacketSent();
          
      }
}

Unfortunately, I cannot find what the "data" type is, I assume it must be binary, all the manual says is stated above!

You need to carefully study the library code, available here.

The data type is indeed binary, but the code is quite convoluted and the documentation atrocious.

I would pick another library.

Here’s what I would do:

//433MHz Transmitter Module
//Wiring Left to Right
//Data(to pin D12), 5V, GND.

// RadoiHead Amplitude Shift Keying Library
#include <RH_ASK.h>
// SPI Library
#include <SPI.h>

// Create Amplitude Shift Keying Object
RH_ASK rf_driver;

//DHT22
//Wiring Left to Right
// for DHT22,
//      VCC: 5V or 3V
//      DATA: 2
//      Not Used
//      GND: GND

#include <SimpleDHT.h>

struct TempHumidData {
  float temperature;
  float humidity;
};

int pinDHT22 = 7;
SimpleDHT22 dht22(pinDHT22);

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

  // Turn built-in LED off
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);

  //Initialise ASK Object
  rf_driver.init();
}

void loop() {
  TempHumidData sensorData;
  float temperature;
  float humidity;
  uint8_t err;

  delay(5000);
  err = SimpleDHTErrSuccess;
  if ((err = dht22.read2(&temperature, &humidity, nullptr)) != SimpleDHTErrSuccess) {
    Serial.println();
    Serial.println("Data Error                              ");
    Serial.println();
  } else {
    sensorData.temperature = temperature;
    sensorData.humidity = humidity;
    rf_driver.send((uint8_t *)(&sensorData), sizeof(sensorData));
    rf_driver.waitPacketSent();
  }
}

Or, even more compactly:

//433MHz Transmitter Module
//Wiring Left to Right
//Data(to pin D12), 5V, GND.

// RadoiHead Amplitude Shift Keying Library
#include <RH_ASK.h>
// SPI Library
#include <SPI.h>

// Create Amplitude Shift Keying Object
RH_ASK rf_driver;

//DHT22
//Wiring Left to Right
// for DHT22,
//      VCC: 5V or 3V
//      DATA: 2
//      Not Used
//      GND: GND

#include <SimpleDHT.h>

struct TempHumidData {
  float temperature;
  float humidity;
};

int pinDHT22 = 7;
SimpleDHT22 dht22(pinDHT22);

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

  // Turn built-in LED off
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);

  //Initialise ASK Object
  rf_driver.init();
}

void loop() {
  TempHumidData sensorData;
  uint8_t err;

  delay(5000);
  err = SimpleDHTErrSuccess;
  if ((err = dht22.read2(&sensorData.temperature, &sensorData.humidity, nullptr)) != SimpleDHTErrSuccess) {
    Serial.println();
    Serial.println("Data Error                              ");
    Serial.println();
  } else {
    rf_driver.send((uint8_t *)(&sensorData), sizeof(sensorData));
    rf_driver.waitPacketSent();
  }
}

I don’t have the SimpleDHT library, so I can’t compile error-free. But, this code is close.

jremington

Unfortunately, the link you suggested is dead. Would have loved to take a peek at the documentation.

And thanks for all the contributions!

IMHO, RadioHead’s documentation (in doxygen) is pretty good, certainly better than most Arduino libraries. Start here.

Check out the list of classes and examples. You might want to try the RHReliableDatagram class as it handles much of the grunt work as well as providing for message acknowledgments and automatic retries. The examples are commented and easy to follow.

The RH documentation is very good. Thanks!

Here is a naive question....

I come from the Javascript, Python, PHP world, and I am new at C.

Does code indentation act the same as curly braces in C?

Code indention is generally for aesthetics and readability. Curly braces are part of the language and actually affect how the code compiles and runs.

The SIMPLEdht library is storing one bit per byte in your data array.

else {
    rf_driver.send(myData, 5);
    rf_driver.waitPacketSent();
          
      }

You are sending the first five bytes, which contain the first five bits of the data. You probably want to consolidate first.

  else
  {
    byte dataByte = 0;
    byte byteCounter = 0;
    byte bitCounter = 0;
    for (byte i = 0; i< 40; i++)
    {
      dataByte <<= 1;
      dataByte |= myData[i];
      bitCounter++;
      if (bitCounter == 8)  // We have filled a byte
      {
        myData[byteCounter++] = dataByte;  // Save it in the buffer
        dataByte = 0;
        bitCounter = 0;
      }
    }
    rf_driver.send(myData, 5);
    rf_driver.waitPacketSent();
  }

johnwasser

Thanks, that worked. Now I am going to learn how these bitwise operations work.

Unfortunately, the link you suggested is dead.

Sorry, SimpleDHT library is here. The "documentation" is limited to the few comments in the code, which are pretty much useless.

If you insist on using this poor example of a library, I would go with the approach outlined in reply #8.

In other words, just get the temperature and humidity and do what you like with them.