Go Down

Topic: Opinions on intercepting 433MHz from Oregon Scientific WMR200 Weather Station (Read 43930 times) previous topic - next topic

disco_very

Hi Rob!


First thank you so much for your prompt response, it's very kind of you taking the time to review my issue!

I have been following your advice, I were able to get to points 4 and 5; it also calls the add() function. But the only values I get are:
Code: [Select]
One second ...0,0,0.0,0.0,0.00,0.00,2.34,nan,0,0,0

I've been digging deeper: as mentioned, it enters to the add() function, it also enters to the else block here:
Code: [Select]
void add(byte bitData) {

Serial.println("POINT>> 10 Enters add()");
 if (discNos > 0) {
   discNos--;//discard bits before real data

Serial.println("POINT>> 11 - add() -  if (discNos > 0) {");    
 }
 else {   <<<<<<<<<<<ENTERS HERE

 
And sometimes here:

Code: [Select]
Serial.println("POINT>> 12 - add() -  else {");
   //the incoming bitstream has bytes placed in reversed nibble order on the fly, then the CS is done.
   if (bitData) {
     //if it is a '1' OR it in, others leave at a '0'
     manchester[nosBytes] |= oregon[nosBits];//places the reversed low nibble, with hi nibble, on the fly!!!
Serial.println("POINT>> 13 - add() - if (bitData) { ");
    
   }


but it never enters to any of these:

Code: [Select]
if (manchester[0] == 0xA2) {
     maxBytes = 11; //rain
     csIndex = 19;
   }
   if (manchester[0] == 0xA1) {
     maxBytes = 10; //wind
     csIndex = 18;
     Serial.println("Wind S detected");
   }
   if (manchester[0] == 0xAF) {
     maxBytes = 9; //temp
     csIndex = 16;
     Serial.println("Temp S detected");
   }
  if (manchester[0] == 0xAD) {
     maxBytes = 8; //UV Light Detector
     csIndex = 14; //CS byte begins at 14 nibble
   }
   if (manchester[0] == 0xA3) {
     maxBytes = 10; //experimental, Solar,Strikes,UV
     csIndex = 18; //CS byte begins at 18 nibble
   }



Hence I'm wondering if maybe the issue is that my sensor may have a different Hex code... Where do those codes come from?

Checking one of your sources (http://wmrx00.sourceforge.net/Arduino/OregonScientific-RF-Protocols.pdf) I found in page 10 all known Sensor ID Codes; my device is the WTGR800 and while is not specifically in the list, there is a WGR800 that includes a temperature/RH sensor; hex code = 1994 but the format seems to be different from the two digits hex codes from this block of code... So how shall I format it?

Also is there a way to find the right values for the
Code: [Select]
maxBytes
and
Code: [Select]
csIndex
of my sensor, or just trial and error?

It never gets to this code:
Code: [Select]
if (nosBytes == maxBytes) {
Serial.println("POINT>> 14 - add() -   if (nosBytes == maxBytes) {");

      hexBinDump();
      digitalWrite(ledPin, 1);
      Serial.println("WCheck SUM");
      //Check Checksum first
      if (ValidCS(csIndex)) {
        //Process the byte array into Human readable numbers
        analyseData();
      }
      noErrors = false; //make it begin again from the start



I really hope to get my sensor up and running, I'm looking forward to start extending my station with more of the OS great devices...

I will get a new Rx like the one you recommend ASAP, for now I have my sensor close to the RX.


Once again thank you for your help!
Javier



robwlakes

Hi Javier,

Glad to help. Corona Virus is making me feel very useless at the moment so this is a welcome distraction.

That reference I put in my GIT-Hub posting (OregonScientific-RF-Protocols.pdf) with some reluctance as the manner in which he talks about Manchester logic is some of the most convoluted way of thinking. Manchester encoding is very simple if the language around it is kept simple and he confabulates most of it.  How he got anything to work amazes me.  However it is worth a read, just to reassure ourselves it can be done.

First let's just revise some OS packet basics:

1. First we have a stream of 1's, these cannot be sure to be 1's until the first 0 turns up.

2. OS packets use the first synchronising zero bit as part of the first byte, it is counted into the data bytes.

3. Therefore the raw first byte (Station Identifying Byte) will always begin with a zero.
    (some protocols discard this 0). Set HexBinDump() to help debugging.

4. Using the Wind detector WGR800 as an example the bit stream appears as follows
   a. A string of 1's makes the header (stabilizes the AGC and level detector)
   b. First zero arrives, start packing this and all following bits into bytes ie add(byte bitData)
   c. The raw bit pattern that the Rx sees (including the first zero) is 01011000 for the first byte
   d. OS protocol reverses the order of bits in every 4 bit nibble throughout the whole packet.
   e. So the Rx sees raw ABCDEFGH bits, and then OS uses them as DCBAHGFE.
   f.  My program applies this to all the bytes in the packet, otherwise the actual wind speeds and directions are "hidden" and very hard to recognise.
   g. To simplify my program I apply this nibble reversal to the Station ID as well.
   h. So the station ID byte is received raw order 0101 1000, but I store it as 1010 0001 or hex A1
   i.  So all subsequent station checks are against the reversed Nibble order rather than the raw order received.
   j.  This means all station IDs are in reverse Nibble order and will have the XXX0XXXX make up, as that 0 is the necessary and included synchronising bit.
   k. When you have the packet in reversed nibble order you will be able to read the weather data inside the  packet so much easier and determine what is what.
 
5. The reverse Nibble arrangement is achieved by using a simple lookup array to add the bit into the right position in the right order. oregon[] is an indexed array.
         a. So the 8 byte masks are in this order 0001 0000, 0010 0000, 01000 0000, 1000 0000, 0000 0001, 0000 0010, 0000 0100, 0000 1000 or 16, 32, 64, 128, 1, 2, 4, 8
         b. So every byte received has this transformation applied, even the Station ID. To me this is the true station ID, not whatever is in that PDF.

6. When the station ID is detected it means the length of the packet can be associated with it and how many bytes (and therefore nibbles) can be expected. The required number of bytes means any thing shorter or longer is received, it is an error and gets dumped. You will need to find the number of bytes though first by trial and error first, then you can check it when you are ready. As long as you know what the station ID is don't worry what anybody else calls it.

7. The byte after the Station ID is usually a random (rolling 8 bit) number assigned when the power is applied to a sensor. I generally don't check this as usually most people just want to run one version of a sensor and they are the only people doing in the neighbourhood. However if you wanted to receive multiple sensors of the one type this would be important. Don't use it though if you don't have to, as that will mean you don't have to reset your receive program every time you change batteries!

8. The Protocol 3.0 has a simple checksum based on adding the nibbles into a number and storing it as  the last byte in the packet. This may or may not be an even number of nibbles, so when you get an idea of where the actual weather data is in the packet, what is left over is probably the check sum. You will need to turn off this checksum checking to begin with until you are ready. CSindex is set to a  known value once each Sensor ID is established. ie it is how many nibbles (not bytes, it may be an odd number) are included in the checksum.

9. You will also have to experiment with how many bytes are in the checks as well to see if you have  collected all the data. If you are using the BinHexDump() routine you will get an idea from the steady data early in the packet.  Be careful though if you make the number of bytes expected in the packet too long you will stop receiving the packet, and receive noise as malformed Manchester bit patterns. This will cause the program to exit and not allow you to process the data at all. So increase the number of bytes slowly and see what happens. This is what maxbytes refers to.

10 When you can receive a stable packet, and push it into HexBinCode() you will be nearly there.

11. I found the nibble formats for the Temp, Humidity, Wind Speed and direction followed fairly closely what other people had found in other OS sensors, so have a close look at how my calculations are derived. You should have the console to check your suspicions against to see if you have interpreted right. eg which byte changes when you move the direction vane and what does it say on the console?

12. Use HexBinDump() as you progress. It takes time to the do the dump (use Baud 115200, or as high as possible), so use it sparingly and move it further along the processing chain as you make headway.

I hope this helps and gets you further along the discovery trail.

RobW

 PS I presume you have the check turned off that it will not do anything until 3 sensors have been found? Line 641?
Learning Flute and C++, heading for a meltdown.

disco_very

Hey Rob,


Wow, thank you! I've read carefully all your explanations and I'm trying to understand the logic. I have to admit it's not easy for me...

Yes, check sum is disabled, as well as the "if ((scan&7)==7)" condition.

Findings:

While in the add() function, I never reach to meet if (nosBytes == maxBytes); so what I did was forcing executing hexBinDump() at the end of the function.

I'm not sure if this is any useful; I get mostly 0s, but for the first byte I'm sometimes getting a value, some of these values repeat, being 40 the most common, sometimes I get 00 or random values, which I think it's OK, my biggest concern is about the rest of the bytes being always 0.

Another exception is the last byte, that seems to be following a sequence, 0, 1, 2, 3 back to 0, some times up to 7, but most of the time follows the sequence (or repeat 01)

I attached a serial monitor capture, just in case you can have a look to it.

Do you think is there any reason to be a hardware issue?


Big, big thank you Rob, this project means a lot for me!
Greetings from Spain!
Javier

robwlakes

Hi Javier,

Glad to hear you are hanging in there and not giving up....

This bit of code below is the start of the add() routine. It is supplied with a bit stream where it packs bits into the bytes in the byte array manchester[]. It also checks the first byte in the manchester[] array for a station ID. I have included as an example the rainfall one with an ID of hex A2. The program cannot determine what the Station ID is until the whole byte is received, once it has done that though, the program can establish the number of bytes for that particular sensor and the number of nibbles used in the Checksum (these have been found out by trial and error previously, not calculated from the station ID).

void add(byte bitData) {
  if (discNos > 0) {
    discNos--;//discard bits before real data, we don't discard the first zero, we include it
  }
  else {
    //the incoming bitstream has bytes placed in reversed nibble order on the fly, then the CS is done.
    if (bitData) {
      //if it is a '1' OR it in, others leave at a '0'
      manchester[nosBytes] |= oregon[nosBits];//places the reversed low nibble, with hi nibble, on the fly!!!
    }
    //Oregon Scientific sensors have specific packet lengths
    //Maximum bytes for each sensor must set once the sensor has been detected.
    if (manchester[0] == 0xA2) {
      maxBytes = 11; //rain
      csIndex = 19;
    }


This stream of bits then packed in with this a bit further down

    nosBits++;
    //Pack the bits into 8bit bytes
    if (nosBits == 8 ) {
      nosBits = 0;
      nosBytes++;
      manchester[nosBytes] = 0; //next byte to 0 to accumulate data
    }

The maxBytes variable is initialised with a starting value of 9, this is long enough to ensure the reading starts, but as soon as the Station ID is recognised the appropriate maxBytes is assigned a proper value. We are chasing an unknown maxBytes and csIndex.

So before the checksum routine listed below add these lines...........

if (nosBytes == 5){
   //checkout the raw manchester array with no processing
   hexBinDump(); //see how we are going at this point
   eraseManchester(); //this array must always be zeroes at the start of a new run
   noErrors = false; //make it begin again from the start
}


You may have to make "5" as low as 2 to begin with.

This will dump out the progress of the incoming data, but only when at least 5 bytes has been received (ie not when every bit is added, that is too disruptive). If you can get a stable pattern after tuning things up then you could increase the number upwards from 5. Because nosBytes now never reaches maxBytes ie 9 then it won't try to do a checksum check either. (NB You may have to change that maxBytes=9 later if you need a bigger packet, but by then you will be defining it in this loop anyway).


    //Check the bytes for a valid packet once maxBytes received
    if (nosBytes == maxBytes) {
      //hexBinDump();
      digitalWrite(ledPin, 1);
      //Check Checksum first
      if (ValidCS(csIndex)) {
        //Process the byte array into Human readable numbers
        analyseData();
      }
      noErrors = false; //make it begin again from the start
    }
  }
}


I am worried that the assumption that the sensor uses V3.0 protocol. Have you found that referred to on the box or the instructions for your sensor? I have bought a combined temperature and humidity sensor only to slowly discover the protocol was different. The data rate was half the speed and the logic of the protocol was inverted compared to the V3.0 protocol. Took a long time to discover that. I had assumed it must be V3.0.

If you are getting the add(0 routine you must be at least getting a header, and finding the synchronising zero, what we need now is steady data in that manchester[] array, just looking at the first few bytes will help zoom in on the next part to focus on.

Keep up the good and keep our minds sharp. I feel like I am playing chess with a blindfold 8) at the moment, but we will get there.

RobW

Learning Flute and C++, heading for a meltdown.

disco_very

Thanks Rob!!!


I just read it and I'm going to test now, just wanted to confirm that this device uses protocol v3.0 as you can see in the attached picture.


Looking forward to make progress!!
Javier

disco_very

Hi again Rob!


I've been experimenting as you suggested but I've never been able to met the condition of the suggested block
Code: [Select]
if (nosBytes == 9) (I tried values from 2 to 9) so I kept digging and added this at the end of the add() function:

Code: [Select]
Serial.print("> My nosBits = ");
Serial.println(nosBits);

Serial.print(">> My nosBytes = ");
Serial.println(nosBytes);


To see how nosBits where (generally) increasing OK from 0 to 7, but nosBytes just went form 0 to 1 (and sometimes 2) hence it would be never able to meet the condition.

I found out that most of the time this condition is meet:

Code: [Select]
if (digitalRead(RxPin) != tempBit) {
     noErrors = false;
   }


I believe this could be OK as we are waiting for the transition to happen?


And sometimes this one is also triggered:

Code: [Select]
if (headerHits < headerBits) {
         noErrors = false;
       }



So noErrors = false and then nosBytes goes back to 0 at the beginning of loop()

Do you have any clue of what could be the reasons for this to happen?

Once again, thank you!!
Javier


disco_very

Hey Rob, one more thing, I'm following your advice on the Rx model and I found the model you mentioned although I'm confused about the "learning button function" is that something we can just ignore and use it as regular Rx?

I also found this other model that "it looks" similar to the one you have in GitHub:


Although it is not the the exact same based on how it looks. I'm not experienced on 433MHz Rx, they look all the same, is there any specific model I should look for?


Thanks!!!
Javier

zoomx

RXB6 is a good receiver, my boards work also without antenna.

disco_very


Go Up