Different RF packages determined by different bits

Hi…

Im trying to change a code to receive data packages from a RF station, it has two modules:
-rain (only sends rain data)
-wind (sends 1 message with wind average; 1 message with temp and humi; 1 message with wind gust and wind direction)

this code is working ok with the rain module

#define nobits 36
#define initialstring "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
#define   syncmin   7500
#define   syncmax   9900
#define   separatormin 250
#define   separatormax   750
#define   lowmin   1700
#define   lowmax   2300
#define   highmin   3700
#define   highmax   4300
#define baudspeed 9600
#define receiverpin 2
#define ledpin 13
#define rflisteninterval 50
float rain = 0;
unsigned long lastReadMills = 0;
String lastReceivedCode = "";


void setup() {
pinMode(ledpin, OUTPUT);
pinMode(receiverpin, INPUT);
digitalWrite(receiverpin, HIGH);
Serial.begin(baudspeed);
}

void loop()
{
if(RFListened())
{
   //other processing
}
}
boolean RFListened()
{
if(((millis()-lastReadMills)/1000>rflisteninterval)||(millis()<lastReadMills))
{
   GetWeatherData();
   if((millis()==lastReadMills)&&(lastReadMills!=0))
   
            
         {
         Serial.println("Rain Data");
         Serial.print(rain); 
         Serial.print("mm; ");
         Serial.print(lastReadMills/1000);
         Serial.println("s; ");
         Serial.println(" ");
         return true;
       }
 
   return false;
}

else
{
   return true;
}

}
void GetWeatherData()
{
String receivedCode = ReceiveCode();
if (receivedCode!="")

  
  {
     rain = (receivedCode.charAt(31)=='1'?1:0)*32768 +
         (receivedCode.charAt(30)=='1'?1:0)*16384 +
         (receivedCode.charAt(29)=='1'?1:0)*8192 +
         (receivedCode.charAt(28)=='1'?1:0)*4096 +
         (receivedCode.charAt(27)=='1'?1:0)*2048 +
         (receivedCode.charAt(26)=='1'?1:0)*1024 +
         (receivedCode.charAt(25)=='1'?1:0)*512 +
         (receivedCode.charAt(24)=='1'?1:0)*256 +
         (receivedCode.charAt(23)=='1'?1:0)*128 +
         (receivedCode.charAt(22)=='1'?1:0)*64 +
         (receivedCode.charAt(21)=='1'?1:0)*32 +
         (receivedCode.charAt(20)=='1'?1:0)*16 +
         (receivedCode.charAt(19)=='1'?1:0)*8 +
         (receivedCode.charAt(18)=='1'?1:0)*4 +
         (receivedCode.charAt(17)=='1'?1:0)*2 +
         (receivedCode.charAt(16)=='1'?1:0);
        rain = rain/5;  
        lastReadMills = millis();
     
     }
 


}
String ReceiveCode()
{
String receivedCode = initialstring;
long startMicros = micros(), endMicros;
if (digitalRead(receiverpin)) return "";
while(!digitalRead(receiverpin))
{
   if ((micros()-startMicros)>syncmax)
     return "";
}
if ((micros()-startMicros)<syncmin)
   return "";
startMicros = micros();
while(digitalRead(receiverpin))
{
   if ((micros()-startMicros)>separatormax)
     return "";
}
if ((micros()-startMicros)<separatormin)
   return "";
for(int i = 0; i < nobits; i++)
{
   startMicros = micros();
   while(!digitalRead(receiverpin))
   {
     if ((micros()-startMicros)>highmax)
       return receivedCode;
   }
   endMicros = micros();
   if(((endMicros-startMicros)>lowmin)&&((endMicros-startMicros)<lowmax))
     receivedCode.setCharAt(i,'0');
   else
     if(((endMicros-startMicros)>highmin)&&((endMicros-startMicros)<highmax))
       receivedCode.setCharAt(i,'1');
     else
       return "";
   startMicros = micros();
   while(digitalRead(receiverpin))
   {
     if ((micros()-startMicros)>separatormax)
       return "";
   }
   if ((micros()-startMicros)<separatormin)
     return "";
}
//Serial.println(receivedCode);
if (receivedCode.charAt(4)=='0')
   return receivedCode;
else
   return "";
}

Now i want to add the wind module, but i need to define if the received message is rain or wind or temp/humidity and serial.print according to the message received. A sequence of bits is what determine which data contain the package, example: 11101 rain

i thought something like this:

boolean RFListened()
if receivedCode.substring(5,9)==11101 //(wind average)
serial.print (windaverage)
else if receivedCode.substring(5,9)==00100 //(rain)

  • serial.print (rain)*

(…)

but i cant write the receivedCode.substring in the section of the boolean RFListened()…only in the GetWeatherData() and String Received Code.

Or i can do this?

GetWeatherData()
if receivedCode.substring(5,9)==11101 //(wind average)
windaverage = (receivedCode.charAt(31)==‘1’?1:0)*32768 +
(receivedCode.charAt(30)==‘1’?1:0)*16384 +
(…)

else if receivedCode.substring(5,9)==00100 //(rain)
rain = (receivedCode.charAt(31)==‘1’?1:0)*32768 +
(receivedCode.charAt(30)==‘1’?1:0)*16384 +
(…)

but i dont know what to put in the boolean RFListened(), to serial.print the correct data or if i use only if or else if…any help i´ll appreciate :slight_smile:

So this RF station actually sends a stream of ASCII '1's and '0's does it?

There are a few issues with the code, anything with that many micros() and millis() can't be right I would think.

But let's go back to the beginning.

How do you know when a new block of data starts?

What is the exact format of this data?


Rob

The station sends 1 and 0 encoded with the length of bit. 1--> 4ms ; 0-->2ms; space between bits-->0.5ms, the micros is to check if the bit is 1,0 or separator

Each data package (rain, temp/humi, wind, etc) is different, but i´ll explain two, just to compare.

The complete protocol can be found here http://www.tfd.hu/tfdhu/files/wsprotocol/auriol_protocol_v20.pdf

The package contains 36bit
001000110110110000000000000000000000

00100011 -->sensor id (pluviometer)
0 ->1 battery low; 0 battery ok
1101100 ->package ID (in this case: rain)
0000000000000000 ->rain data, in this case is 0
0000 ->checksum

111000110110111000000000000000000000

11100011 -->sensor id (anemometer)
0 ->battery
110111 ->package id (scheduled transmission, in this case, wind direction and wind gust, )
000000000 -> wind direction data
00000000 -> wind gust data
0000 -> checksum

How do you know when a new block of data starts?
Supposedly there are some sync bits before a new block of data starts, but since the 5 bit in the sensor id is always 0 (for all types of sensor id), in the end of the code you can find:
if (receivedCode.charAt(4)=='0')
return receivedCode;

That code is displaying ok. Sometimes i get 0.00mm of rain, because the code isn't doing checksum (something to add later)

There is a lot to be done, but first i need to add the rest of data packages:
-Adding checksum
-Check for battery low
-If last package received is the same from the previous one, dont print

Temporary solution for determining what package received

if ((((((receivedCode.charAt(9)=='1')&&(receivedCode.charAt(10)=='1')&&(receivedCode.charAt(11)=='0')&&(receivedCode.charAt(12)=='1')&&(receivedCode.charAt(13)=='1')&&(receivedCode.charAt(14)=='0'))))))

Still a lot of work to be done in the code..

I can’t help much with the reception of the modulated data and I don’t do C++ much but all that playing with a String object is probably very inefficient.

I will assume that you can get the data into the array correctly.

Here’s an example of getting the sensor/package ID (or whatever it’s called). It assumes the 36 bits are stored in an array of chars where ‘1’ = 1 and ‘0’ = 0.

#define N_BITS 		36
#define PLUVIOMETER B00100011
#define ANEMOMETER 	B11100011

char receivedCode[N_BITS];
byte package_id;
byte sensor_id;
byte battery_state;
char *ptr;
byte csum;


void setup () {

}

void loop () {
}


void parseData () {
	ptr = receivedCode;  	// set a pointer to the start of the data array
							// this pointer is moved along the data during the course of this function

	/// get the sensor ID part (the first 8 bits)
	for (int i = 0; i < 8; i++, ptr++) {
	   sensor_id <<= 1;
	   sensor_id != *ptr - '0';
	}
Serial.println (sensor_id, BYTE);

#if 0  /// don't enable this until you get the ID part working

	battery_state = *ptr++ - '0';

	/// get the package ID part (the next 7 bits)

	for (int i = 0; i < 7; i++, ptr++) {
	   package_id <<= 1;
	   package_id != *ptr - '0';
	}

	// now you can do an easy switch on the ID


	switch (sensor_id) {
		case PLUVIOMETER:
				   // similar code to the above loop to get rain data
			break;
			
		case ANEMOMETER:
				   // similar code to the above loop to get wind direction and wind gust
			break;

	}

        // the above two cases must leave the pointer pointing to the CSUM
	for (int i = 0; i < 4; i++, ptr++) {
	   csum <<= 1;
	   csum != *ptr - '0';
	}
#endif
}

See if you can get something working from that then get back to us.

This can be cleaned up a lot yet, but let’s see if it works first.


Rob