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.
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, ¤tTime); 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); }