#include "SPI.h" #include "RFM.h" byte commandData[32]; byte commandDataPointer = 0; RFM rfm(11, 12, 13, 10); struct Frame { byte Header; byte ID; bool NewBatteryFlag; bool Bit12; float Temperature; bool WeakBatteryFlag; byte Humidity; byte CRC; bool IsValid; }; void setup() { Serial.begin(9600); rfm.Begin(true); rfm.InitializeLaCrosse(); rfm.SetFrequency(868300); rfm.SetDataRate(17241ul); rfm.EnableReceiver(true); } void loop() { rfm.Receive(); if (rfm.PayloadIsReady()) { rfm.EnableReceiver(false); byte payload[PAYLOADSIZE]; rfm.GetPayload(payload); String result; struct Frame frame; DecodeFrame(payload, &frame); byte filter[5]; filter[0] = 0; filter[1] = 0; filter[2] = 0; filter[3] = 0; filter[4] = 0; bool hideIt = false; for (int f = 0; f < 5; f++) { if (frame.ID == filter[f]) { hideIt = true; break; } } if (!hideIt) { // Check CRC if (frame.IsValid != false) { result += "{"; // Sensor ID result += "\"id\":\""; result += String(frame.ID, HEX); // New battery flag result += "\",\"newBatt\":"; result += String(frame.NewBatteryFlag, DEC); // Bit 12 result += ",\"bit12\":"; result += String(frame.Bit12, DEC); // Temperature result += ",\"temp\":"; result += frame.Temperature; // Humidity result += ",\"hum\":"; result += frame.Humidity; // Weak battery flag result += ",\"weakBatt\":"; result += String(frame.WeakBatteryFlag, DEC); // CRC result += ",\"crc\":"; result += String(frame.CRC, DEC); result += "}"; Serial.println(result); Serial.flush(); } } rfm.EnableReceiver(true); } } void DecodeFrame(byte *bytes, struct Frame *frame) { frame->IsValid = true; frame->CRC = bytes[4]; if (frame->CRC != CalculateCRC(bytes, 4)) { frame->IsValid = false; } // SSSS.DDDD DDN_.TTTT TTTT.TTTT WHHH.HHHH CCCC.CCCC frame->ID = 0; frame->ID |= (bytes[0] & 0xF) << 2; if (0) { // This is the way how the initial release calculated th ID // It's wrong because the two bits must be moved to the right frame->ID |= (bytes[1] & 0xC0); } else { // The new ID calculation. The order of the bits is respected frame->ID |= (bytes[1] & 0xC0) >> 6; } frame->Header = (bytes[0] & 0xF0) >> 4; if (frame->Header != 9) { frame->IsValid = false; } frame->NewBatteryFlag = (bytes[1] & 0x20) >> 5; frame->Bit12 = (bytes[1] & 0x10) >> 4; byte bcd[3]; bcd[0] = bytes[1] & 0xF; bcd[1] = (bytes[2] & 0xF0) >> 4; bcd[2] = (bytes[2] & 0xF); float t = 0; t += bcd[0] * 100.0; t += bcd[1] * 10.0; t += bcd[2] * 1.0; t = t / 10; t -= 40; frame->Temperature = t; frame->WeakBatteryFlag = (bytes[3] & 0x80) >> 7; frame->Humidity = bytes[3] & 0b01111111; } byte CalculateCRC(byte *data, byte len) { int i, j; byte res = 0; for (j = 0; j < len; j++) { uint8_t val = data[j]; for (i = 0; i < 8; i++) { uint8_t tmp = (uint8_t)((res ^ val) & 0x80); res <<= 1; if (0 != tmp) { res ^= 0x31; } val <<= 1; } } return res; }