temp sensor over 433Mhz

Dependencies:   FastIO

BBC MicroBit with RF 433Mhz receiver reading Oregon-Scientific wireless temperature sensor. Originally written for the Raspberry Pi but easily converted for the little microbit.

OregonBit.cpp

Committer:
daw9000
Date:
2016-07-26
Revision:
1:706c7b028278
Parent:
0:13cb9cc98bca
Child:
2:7455dae4e624

File content as of revision 1:706c7b028278:

/* Program Oregon Written by David Wright, Jan 2015. */
/* thanks and plagarised from various internet sources on oregon sensors. Paul(DISK91.com), ALTelectronics for their document on      */
/* Oregon Scientific RF protocol v1.0, kevinmehall on github for rtldr-433m-sensor, Alexander Yerezeyev and more ....                 */
/* */
/* This Program reads a 433Mhz transmission from an Oregon version 1 Protocol Temperature Sensor */
/* */
/* Programming uses the logic of first detecting the preamble portion of transmission by counting the number of short 1 pulses         */
/* Next the progam monitors the 3 sync pulses and translates the last sync pulse to determine the first data message bit either 1 or 0 */
/* From knowing the first message data bit the program determines the next 31 message data bits using the logic as follows:-           */
/*   Two SHORT pulses means that the message data bit is the same as the previous message data bit (we know first so can do this)      */
/*   One LONG pulse means that the message data bit is opposite (inverse) of the previous message data bit.                            */
/* */
/* The resulting 32 bit message is reversed to form 8 nibbles(4 bit). These nibbles are decoded to produce the data values.            */
/* */
/* This program is quite basic and simplistic in that there is no error checking and only really gets temperature, channel and low bat */
/* I wrote this program to learn C programming from being a visual basic and java programmer and as an aid to learning to code         */
/* hardware interfaces on my Raspberry Pi B+. I found plenty of code for various Oregon sensors but none I could easily understand     */
/* from the C or Python code. Hence this program does nothing clever using bitwise or memory facilities or uses no rising clock edges  */
/* , falling clock edges, clock ticks etc. Just simple time measurement and ONs and OFFs. Also I dont do any hex conversions.          */
/* There are no hex conversions because for channel, temperature and low battery all the hex and decimal values are the same i.e.      */
/* only numbers 0 to 9 are used for each part of the message. The temp minus sign and low battery are determined from the raw binary   */
/* in nibble 2 (third nibble as it starts nibble zero).                                                                                */
/* */
/* If you wish this program can be improved on by adding error checking by using the checksum (hex conversion needed) and/or           */
/* by storing values and checking against the second transmission of the same message (all messages sent twice, I sleep through the    */
/* second transmission Zzzzz).                                                                                                         */
 
 
#include "MicroBit.h"
#include "FastIO.h"
 
int thisPin;
int lastPin;
int preambleON;
int onShortLo;
int onShortHi;
int offShortLo;
int offShortHi;
int onLongLo;
int onLongHi;
int offLongLo;
int offLongHi;
int syncEnd0Lo;
int syncEnd0Hi;
long timeDiff;
long startedAt;
long endedAt;
int preambleFound;
int dataBits[32];
//int myPin = 1; // MicroBit P1
MicroBitPin P1(MICROBIT_ID_IO_P1, MICROBIT_PIN_P1, PIN_CAPABILITY_ALL);
MicroBit uBit;
FastInOut<MICROBIT_PIN_P1> (myPin);
Timer xTime; 
long getTime(long returnUsecs)
{
    returnUsecs = xTime.read_us();
/*  struct timespec currentTime;
        long microSecs;
        long  secs;
    clock_gettime(CLOCK_MONOTONIC, &currentTime);
        microSecs = currentTime.tv_nsec  * 0.001;
        secs = currentTime.tv_sec;
        returnUsecs = microSecs +  secs * 1000; */
         
    return(returnUsecs); 
}
int getPinValue(int returnPinValue)
{
       // returnPinValue = digitalRead(myPin);
        returnPinValue = myPin.read(); 
    return(returnPinValue);
}
int detectPreamble(int returnDetected)
{
 
    thisPin = getPinValue(thisPin);
    if (!(thisPin == lastPin))
    {
        endedAt = getTime(endedAt); // set timer end for last pin
        timeDiff = endedAt - startedAt; // reset time
        if (lastPin == 1)
        {
            if ((timeDiff >= onShortLo) && (timeDiff <= onShortHi)) // error of margin on pulse length
            {
                preambleON++; // looking for 12 short ON pulses.
            }
            else // not preamble
            {
                preambleON = 0;
            }
        }
        else // check is this preamble, lastPin off
        {
 
 
            if (preambleON < 11) // last preamble is special as next low not short(thisPin)
            {
                if ((timeDiff > offShortLo) && (timeDiff < offShortHi)) // off ok
                {
                }
                else // not preamble
                {
                    preambleON = 0;
                }
 
            }
        }
 
    startedAt = endedAt; //  set timer start for this pin
    lastPin = thisPin;
    }
    if (preambleON == 12) 
    {
        returnDetected = 1;
    }
    else
    {
        returnDetected = 0;
    }
    return(returnDetected);
}
int getSync()
{
        // sync is long OFF, long ON, long OFF
 
        int sCount;
    sCount =  1;
        thisPin = getPinValue(thisPin);
        lastPin = thisPin; //looking for state changes
        while (sCount < 3) // 3 sync pulses
        {
           if (!(thisPin == lastPin))
           {
                sCount ++;
        if (sCount == 3)
        {
                    startedAt = getTime(startedAt); // time this pulse to get first bit value
        }
                lastPin = thisPin;
          }
           thisPin = getPinValue(thisPin); // poll the pin state
        }
        while ((thisPin == lastPin))
        {
             thisPin = getPinValue(thisPin);
        }
        endedAt = getTime(endedAt);
    timeDiff = endedAt - startedAt;
    startedAt = endedAt; // start timer for next bit. 
    if (timeDiff > syncEnd0Lo && timeDiff < syncEnd0Hi)
    {
        dataBits[0] = 0;
    }
    else
    {
        dataBits[0] = 1;
    }
        return;
}
 
int getData()
{
// get next 31 data bits, we determined bit 0 in SYNC
int i;
int l;
int s;
        i = 1; //first bit[0] was derived in Sync
    s = 0; // short pulse 
    l = 0; // long pulse
 
        while (i < 32)
        {
           if (!(thisPin == lastPin)) // lastPin and thisPin are from getSync.
           {
                endedAt = getTime(endedAt); //  timer started in getSync
                timeDiff = endedAt - startedAt;
        startedAt = endedAt; // next starts at this end
            if (lastPin == 0) //lastPin was OFF
            {
                if ((timeDiff > offShortLo) && (timeDiff < offShortHi))
                    { // short off detected
                        s++;
                        l=0;
                    }
                    if ((timeDiff > offLongLo) && (timeDiff < offLongHi))
                    { // long off detected
                        l++;
                        s=0;
                    }
            }
            else // lastPin was ON
            {
                    if ((timeDiff > onShortLo) && (timeDiff < onShortHi)) // half-time
                    { // short on detetcted
                        s++;
                        l=0;
                    }
                    if ((timeDiff > onLongLo) && (timeDiff < onLongHi)) // full-time
                    { // long on detected
                        l++;
                        s=0;
                    }
            }
            if (s == 2)
            { // 2 short pulses this bit equals previous bit (we know 1st bit from sync)
                    dataBits[i] = dataBits[(i-1)];
                    i++;
                    s=0;
                    l=0;
            }
            if (l == 1)
            { // 1 long pulse this bit is inverse of previous bit (we know 1st bit from sync)
                    if (dataBits[(i-1)] == 0)
                    {
                       dataBits[i] = 1;
                    }
                    else
                    {
                       dataBits[i] = 0;
                    }
                    l=0;
                    s=0;
                    i++;
            }
            // update  last pin to this pin value
                lastPin = thisPin;
           }
           thisPin = getPinValue(thisPin); // get pin value 
        }
    return;
}
 
int processData()
{
int x = 0;
int y = 0;
int z=  0;
int nStart;
int nFinish;
int nibbleValue;
int nibbleValues[8];
int temp;
int nib;
int nibble[4];
int lowBat=0;
 
    for (x=0;x<8;x++)
    {
        for (y=0;y<4;y++){nibble[y]=0;} //initialise
        nStart=(31-((x*4)+3)); // array index for nibble start
        nFinish=nStart+4;
        y = 3; // nibble index
        // Reverse the bits in message data (dataBits) to create 8 nibbles of 4 bits.
        for (z=nStart;z<nFinish;z++) // read 4 bits 
        {
            if (y >= 0)
            {
                nibble[y]=dataBits[z];//reverse bits, y starts at 3 back to 0
                y--;
            }
        }
        nibbleValue=0;
        nib=8;
        temp=0;
        for (z=0;z<4;z++) // convert this nibble to decimal from binary
        {
            temp=nibbleValue;
            nibbleValue=(nib * nibble[z]) + temp;
            temp=nib;
            if (temp > 1) nib = (temp / 2);
 
        }
        nibbleValues[x] = nibbleValue; // store nibble decimal values
    }
 
    // Print out the converted decimal nibble values
    for (x=0;x<8;x++)
    {
        if (x==6) //channel number conversion
        {
             temp=99;
             if (nibbleValues[x]==0) temp=1;
             if (nibbleValues[x]==4) temp=2;
             if (nibbleValues[x]==8) temp=3;
       //      printf(" Channel     : %d\n",temp);
             uBit.display.scroll("Channel:");
             uBit.display.scroll(temp);
        }
        if (x==2)
        {
            // printf(" Temperature:");
            uBit.display.scroll("Temp :");
            if ((nibbleValues[x]==10) || (nibbleValues[x]==2)) uBit.display.scroll("-"); // printf("-"); // 8 = low bat, 2=minus, 10=minus+low bat
            if ((nibbleValues[x]==8) || (nibbleValues[x]==10)) lowBat=1; else lowBat=0;
 
        }
        if ((x==3) || (x==4)) uBit.display.scroll(nibbleValues[x]);// printf("%d",nibbleValues[x]);
        if (x==5)
        {
            // printf(".");
            // printf("%d degC.\n",nibbleValues[x]);
            uBit.display.scroll(".");
            uBit.display.scroll(nibbleValues[x]);
            uBit.display.scroll("degC");
            
        }
        if (lowBat==1) uBit.display.scroll("Low Battery"); // printf("Low Battery. \n");
    }
    return;
}
int main()
{
int p;
uBit.init();
//  on short 1720, on long 3180, off short 1219, off long 2680
// sync 1 off 4200, sync 2 on 5700, sync 3 off 5200 (sync 3 off long 6680)
        onShortLo = 1500;
        onShortHi = 2400;
        offShortLo = 970;
        offShortHi = 1950;
        onLongLo = 2980;
        onLongHi = 3880;
        offLongLo = 1950;
        offLongHi = 2900;
      //  syncBeginLo = 4000;
      //  syncBeginHi = 4400;
      //  syncLo = 5500;
      //  syncHi = 5900;
      //  syncEnd1Lo = 5000;
      //  syncEnd1Hi = 5400;
        syncEnd0Lo = 6480;
        syncEnd0Hi = 6880;
//        wiringPiSetup();
//        pinMode(myPin, INPUT);
          uBit.io.pin[myPin].setDigitalValue(0); 
    preambleFound = 0;
    preambleON = 0;
    // printf("Waiting for transmission (approx. every 30s).\n");
    // printf("Press Ctrl-C to exit.\n");
    uBit.display.scroll("Waiting...");
    while (1)
    { // loop forever or ctrl-c
 
        thisPin = getPinValue(thisPin);
        lastPin = thisPin;
        xTime.start();
        endedAt = getTime(endedAt); // set initial timer end
        startedAt = endedAt;
 
        while (preambleFound == 0) // constantly monitor for preamble
        {
            preambleFound = detectPreamble(preambleFound);
        }
        if (preambleFound == 1)
        {
                    getSync();
                    getData();
            processData();
            preambleFound = 0;
            preambleON = 0;
            uBit.sleep(10); // avoid second xmission of same data
        }
    }
    exit(0);
}