temp sensor over 433Mhz
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.
Diff: OregonBit.cpp
- Revision:
- 0:13cb9cc98bca
- Child:
- 1:706c7b028278
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OregonBit.cpp Tue Jul 26 10:19:11 2016 +0000 @@ -0,0 +1,360 @@ +/* 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, ¤tTime); + 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); +}