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:
0:13cb9cc98bca
Child:
1:706c7b028278

File content as of revision 0:13cb9cc98bca:

/* 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"

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
MicroBit uBit;


long getTime(long returnUsecs)
{
	returnUsecs = uBit.systemTime();
/*	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; */
        returnUsecs = returnUsecs * 100; // microsecs
	return(returnUsecs); 
}
int getPinValue(int returnPinValue)
{
       // returnPinValue = digitalRead(myPin);
        returnPinValue = uBit.io.pin[myPin].getDigitalValue(); 
	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);
		}
		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(" degC.");
			uBit.display.scroll(nibbleValues[x]);
		}
		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;
		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);
}