http://csb.idilks.com/2014/03/megastat-second-gen-smart-thermostat-3.html
MegaStat – Second Gen Smart Thermostat – 3. 433Mhz Receiver
433 Mhz Communication with Spark Core
We have successful communication from the PIC temperature monitors to the Spark Core using the Linx 433 Mhz module. The first step is to solder the Linx module to some wires since this module is a 16-SMD package and will be hard to bread board. With some solder wizardry I managed to get all the wires on the module and attach an antenna.
On the transmitter modules (OOK Modulated) you will notice that in the code I have inverted the output going from the UART to the transmitter. This is done because the normal marking state of a UART is logic 1 or high. This marking state causes constant transmission. This would not be good when we are trying to have many monitoring modules transmitting to the thermostat. Therefore on the receiving end I also have to invert the output from the receiver going to the spark core. This can be achieved with a transistor or there are some chips you can buy to do the inverting.
License is located here.
byte RxMsg[11]; // Message from the sensors
byte RxIdx = 0; // Index in message buffer
void setup() {
Serial.begin(9600);
Serial1.begin(1200); // Init UART at 1200 baud
}
void loop() {
// Loop while bytes are available
while (Serial1.available()) {
RxMsg[RxIdx] = Serial1.read(); // Read in first byte
if (RxMsg[0] == 33) { // All messages start with "!"
if ((RxIdx == 1 && RxMsg[1] != 222) || (RxIdx == 2 && RxMsg[2] != 84) || (RxIdx == 3 && RxMsg[3] != 171)) { // Verify First Part of Message is correct
RxIdx = 0; // Message invalid start over
} else if (RxIdx == 11) {
bool goodMsg = true; // Made it this far, optimistic outcome
RxIdx = 0; // Start message index over for next temp broadcast
for (byte i=4; i <= 10 && goodMsg; i+=2) { // Validate the remaining bytes in the message
if ((RxMsg[i] ^ 255) != RxMsg[(i + 1)]) {
goodMsg = false;
break;
}
}
if (goodMsg) {
// Create MonitorTmp, DeviceId, Sign, DegreesF, DecimalF
//MonitorTemp Msg = MonitorTemp(RxMsg[4], RxMsg[6], RxMsg[8], RxMsg[10]);
Serial.println("Code here to set processing temp");
}
} else {
RxIdx++;
}
}
}
}
License is located here.
'**************************************************************** '* Name : Monitor.pbp * '* Author : Brian Dilks * '* Date : 10/11/2008 * '* Version : 1.0 * '* Notes : PIC12F683 * '* : * '**************************************************************** '_FCMEN_ON EQU H'3FFF' Fail Safe Clock Monitor '_FCMEN_OFF EQU H'37FF' '_IESO_ON EQU H'3FFF' Internal External Switchover bit '_IESO_OFF EQU H'3BFF' '_BOD_ON EQU H'3FFF' Brown Out '_BOD_NSLEEP EQU H'3EFF' Brown Out on, but not in sleep '_BOD_SBODEN EQU H'3DFF' Brown Out controlled by register '_BOD_OFF EQU H'3CFF' Brown Out off '_CPD_ON EQU H'3F7F' Data Code Protection '_CPD_OFF EQU H'3FFF' '_CP_ON EQU H'3FBF' Program Code Protection '_CP_OFF EQU H'3FFF' '_MCLRE_ON EQU H'3FFF' Reset Pin On '_MCLRE_OFF EQU H'3FDF' Reset Pin Off, Digital Input '_PWRTE_OFF EQU H'3FFF' '_PWRTE_ON EQU H'3FEF' Power Up Timer Enabled '_WDT_ON EQU H'3FFF' Watchdog Timer Enabled '_WDT_OFF EQU H'3FF7' '_LP_OSC EQU H'3FF8' '_XT_OSC EQU H'3FF9' XT OSC, OSC1 & OSC2 pins used '_HS_OSC EQU H'3FFA' '_EC_OSC EQU H'3FFB' '_INTRC_OSC_NOCLKOUT EQU H'3FFC' '_INTOSCIO EQU H'3FFC' '_INTRC_OSC_CLKOUT EQU H'3FFD' '_INTOSC EQU H'3FFD' '_EXTRC_OSC_NOCLKOUT EQU H'3FFE' '_EXTRCIO EQU H'3FFE' '_EXTRC_OSC_CLKOUT EQU H'3FFF' '_EXTRC EQU H'3FFF' @ __CONFIG _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_ON & _XT_OSC DEFINE OSC 4 DEFINE CHAR_PACING 1000 ' WPU Disabled, Interrupt on rising edege, Internal Instruction Cycle Clock, inc low to high T0CK1, Prescaler on TMR0 ' TMR0 1:4, WDT 1:2 OPTION_REG = %11000001 INTCON = 0 ' All interrupts off ADCON0 = 0 ' A/D Converter disabled ANSEL = 0 WPU = 0' Weak pull ups disabled ' 76543210 CMCON0 = 000111 ' All digital i/o GPIO = 000000 TRISIO = 111100 ' MCLR pin - input, GPIO2 Input, <5:4> 1 for OSC1 & 2, GPIO<1:0> Output T1CON.0 = %0 ' Timer1 Off T2CON.2 = %0 ' Timer2 Off DeviceID CON 1 'OSC1 VAR GPIO.5 'OSC2 VAR GPIO.4 'MCLR VAR GPIO.3 pTempSensorIO VAR GPIO.2 pTxData VAR GPIO.1 pTxSTBY VAR GPIO.0 RandomVal VAR WORD ' Random value to drift some transmitters don't broadcast on top of each other. LastRandomVal VAR WORD ' Last value SleepSec VAR BYTE ' Amount of time to sleep TxMsg VAR BYTE[11] '-------------- Temp Sensor Variables ------------- Busy VAR BIT ' Busy Status-Bit LocalTempRaw VAR WORD ' RAW Temperature readings LocalTemp VAR WORD ' Temp in deg F LocalTempSign VAR LocalTempRaw.Bit11' Sign-Bit for +/- Temp. 1 = Below 0 deg C LocalTempCalc VAR BYTE ' Dummy for Div32 LocalTempDeg VAR BYTE ' Degrees LocalTempDec1 VAR BYTE ' Tenths of temp LocalFullTemp VAR WORD ' Final Temperature in full, tenths is ones position IsNegC VAR BIT ' Raw reading was negative '-------------- End Temp Sensor Variables ------------- '-------------- Pre-Loop Code --------------- LocalFullTemp = 0 RandomVal = 0 LastRandomVal = 0 TxMsg[0] = "!" TxMsg[1] = (TxMsg[0] ^ 255) TxMsg[2] = "T" TxMsg[3] = (TxMsg[2] ^ 255) TxMsg[4] = DeviceID TxMsg[5] = (TxMsg[4] ^ 255) SLEEP 10 MainLoop: OWOUT pTempSensorIO, 1, [$CC, $44]' Skip ROM search & do temp conversion Nag: OWIN pTempSensorIO, 4, [Busy] ' Read busy bit IF Busy = 0 THEN Nag ' busy keep looping OWOUT pTempSensorIO, 1, [$CC, $BE]' Skip ROM search & read scratchpad memory OWIN pTempSensorIO, 2, [LocalTempRaw.Lowbyte, LocalTempRaw.Highbyte]' Read two bytes IsNegC = LocalTempSign IF IsNegC = 1 THEN LocalTempRaw = (LocalTempRaw ^ 65535) + 1 LocalTempCalc = LocalTempRaw * 1125 LocalTemp = DIV32 100 TxMsg[6] = "+" IF IsNegC = 1 THEN IF LocalTemp > 3200 THEN TxMsg[6] = "-" LocalTemp = 3200 - LocalTemp ELSE LocalTemp = LocalTemp + 3200 ENDIF ' encode next char based off of last one TxMsg[7] = (TxMsg[6] ^ 255) LocalTempDeg = LocalTemp / 100 ' whole degrees LocalTempDec1 = LocalTemp DIG 1 ' Tenths IF LocalTemp DIG 0 >= 5 THEN ' Hundreths, round it LocalTempDec1 = LocalTempDec1 + 1 if LocalTempDec1 > 9 THEN ' Rounded up a degree LocalTempDeg = LocalTempDeg + 1 LocalTempDec1 = 0 ENDIF ENDIF TxMsg[8] = LocaltempDeg TxMsg[9] = (TxMsg[8] ^ 255) TxMsg[10] = LocalTempDec1 TxMsg[11] = (TxMsg[10] ^ 255) pTxSTBY = 1 'Tx Not in standby SLEEP 1 ' Give 1 second to wait for temp sensor and transmitter to settle SEROUT pTxData, 5, [$55, $55, $55, $55, $55, TxMsg[0], TxMsg[1], TxMsg[2], TxMsg[3], TxMsg[4], TxMsg[5], TxMsg[6], TxMsg[7], TxMsg[8], TxMsg[9], TxMsg[10], TxMsg[11]] pTxSTBY = 0 'Tx in standby WHILE ABS (RandomVal - LastRandomVal) < 546 RANDOM RandomVal ' Get a random value 1 - 65535 WEND LastRandomVal = RandomVal SleepSec = 30 + (RandomVal / 546) ' Add to the 30 seconds a random amount of seconds up to 90 SLEEP SleepSec ' Preform sleep GOTO MainLoop END