...
Transmitter Code
Code Block | ||
---|---|---|
| ||
const int TX_PIN = 4; // ESP8266 pin D2
typedef struct {
boolean power;
int duration; // micro seconds
} signal;
const signal SHORT_ON { true, 500 };
const signal SHORT_OFF { false, 2000 };
const signal LONG_ON { true, 850 }; // not used
const signal LONG_OFF { false, 4000 };
const signal STOP_OFF { false, 500 };
const int REST = 9000; // 9 ms gap
// Here's a temperature of 24.5 forever...
//
signal sig_1 [] {
SHORT_ON, // start bit
SHORT_OFF, SHORT_ON, // a zero (0) bit
LONG_OFF, SHORT_ON, // a one (1) bit
LONG_OFF, SHORT_ON, // a one (1) bit
LONG_OFF, SHORT_ON, // a one (1) bit
LONG_OFF, SHORT_ON, // a one (1) bit
SHORT_OFF, SHORT_ON, // a zero (0) bit
SHORT_OFF, SHORT_ON, // a zero (0) bit
SHORT_OFF, SHORT_ON, // a zero (0) bit
LONG_OFF, SHORT_ON, // a one (1) bit
SHORT_OFF, SHORT_ON, // a zero (0) bit
SHORT_OFF, SHORT_ON, // a zero (0) bit
SHORT_OFF, SHORT_ON, // a zero (0) bit
SHORT_OFF, SHORT_ON, // a zero (0) bit
SHORT_OFF, SHORT_ON, // a zero (0) bit
SHORT_OFF, SHORT_ON, // a zero (0) bit
SHORT_OFF, SHORT_ON, // a zero (0) bit
// LONG_OFF, SHORT_ON, // a one (1) bit
LONG_OFF, SHORT_ON, // a one (1) bit
LONG_OFF, SHORT_ON, // a one (1) bit
LONG_OFF, SHORT_ON, // a one (1) bit
LONG_OFF, SHORT_ON, // a one (1) bit
SHORT_OFF, SHORT_ON, // a zero (0) bit
LONG_OFF, SHORT_ON, // a one (1) bit
SHORT_OFF, SHORT_ON, // a zero (0) bit
LONG_OFF, SHORT_ON, // a one (1) bit
SHORT_OFF, SHORT_ON, // a zero (0) bit
SHORT_OFF, SHORT_ON, // a zero (0) bit
SHORT_OFF, SHORT_ON, // a zero (0) bit
SHORT_OFF, SHORT_ON, // a zero (0) bit
LONG_OFF, SHORT_ON, // a one (1) bit
LONG_OFF, SHORT_ON, // a one (1) bit
LONG_OFF, SHORT_ON, // a one (1) bit
SHORT_OFF, SHORT_ON, // a zero (0) bit
STOP_OFF, SHORT_ON // stop bit
};
void doTransmission(signal array[67]) {
Serial.println("Doing transmission...");
for (int burst = 1; burst <= 7; burst++) {
for (int idx = 0; idx < 66; ++idx ) { // payload
digitalWrite(TX_PIN, array[idx].power);
delayMicroseconds( array[idx].duration );
}
delayMicroseconds(REST); // rest between bursts
}
}
void setup ( void ) {
pinMode(TX_PIN, OUTPUT);
Serial.begin ( 115200 );
}
void loop ( void ) {
Serial.println("Sending...");
doTransmission(sig_1);
delay(10000);
} |
Reading the values from the Transmitter
// ---------------------------------------------------------------------------------------
// Acurite 00606TX Transmitter
// ---------------------------------------------------------------------------------------
#define SYNC_LENGTH 9000
#define SEP_LENGTH 500
#define BIT1_LENGTH 4000
#define BIT0_LENGTH 2000
#define MESSAGE_SIZE 32
#define LSFR_OFFSET 4
uint8_t LSFR_sequence[MESSAGE_SIZE] = {0};
const int TX_PIN = D2;
byte payload[4];
// ---------------------------------------------------------------------------------------
// setup
// ---------------------------------------------------------------------------------------
void setup ( void ) {
pinMode(TX_PIN, OUTPUT);
Serial.begin ( 115200 );
Serial.println("Sending...");
generatePayload();
doTransmission();
}
// ---------------------------------------------------------------------------------------
// loop
// ---------------------------------------------------------------------------------------
void loop ( void ) {
delay(20000);
}
// ---------------------------------------------------------------------------------------
// generatePayload
// ---------------------------------------------------------------------------------------
void generatePayload(){
//define rolling code
byte rollingCode = 0xAA;
//generate random temperature
int temperature = (int)random(-400,400);
Serial.printf("Temp: %.1f\n",temperature/10.0);
unsigned int hightByteTemp = temperature >> 8;
unsigned int lowByteTemp = temperature & 0xff;
//add battery OK flag to
hightByteTemp = 0x80 + (hightByteTemp & 0x0F);
payload[0] = rollingCode;
payload[1] = hightByteTemp;
payload[2] = lowByteTemp;
payload[3] = computeChecksum(3,payload);
Serial.print("Payload: ");
for(int i=0;i<4;i++){
Serial.printf("%02x ",payload[i]);
}
Serial.println("");
}
// ---------------------------------------------------------------------------------------
// toggleLED
// ---------------------------------------------------------------------------------------
void toggleLED(){
//flash led
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
}
// ---------------------------------------------------------------------------------------
// doTransmission
// ---------------------------------------------------------------------------------------
void doTransmission() {
Serial.println("Doing transmission...");
toggleLED();
for (int burst = 1; burst <= 7; burst++) {
Serial.print("Sending: ");
sendPayload();
sendSync();
Serial.println("");
}
}
// ---------------------------------------------------------------------------------------
// sendPayload
// ---------------------------------------------------------------------------------------
void sendPayload(){
for(int i=0;i<4;i++){
sendByte(payload[i]);
}
}
// ---------------------------------------------------------------------------------------
// sendByte
// ---------------------------------------------------------------------------------------
void sendByte(byte b){
for(int i=7;i>=0;i--){
int bitValue = readBit(b,i);
sendBit(bitValue);
if(i%4==0){
Serial.print(" ");
}
}
}
// ---------------------------------------------------------------------------------------
// readBit
// ---------------------------------------------------------------------------------------
int readBit(byte b, int bitPos){
int x = b & (1 << bitPos);
return x == 0 ? 0 : 1;
}
// ---------------------------------------------------------------------------------------
// sendBit
// ---------------------------------------------------------------------------------------
void sendBit(int val){
digitalWrite(TX_PIN, HIGH );
delayMicroseconds(SEP_LENGTH );
digitalWrite(TX_PIN, LOW );
if(val==0){
delayMicroseconds(BIT0_LENGTH );
Serial.print("0");
}else{
delayMicroseconds(BIT1_LENGTH );
Serial.print("1");
}
}
// ---------------------------------------------------------------------------------------
// sendSync
// ---------------------------------------------------------------------------------------
void sendSync(){
digitalWrite(TX_PIN, HIGH );
delayMicroseconds(SEP_LENGTH);
digitalWrite(TX_PIN, LOW );
delayMicroseconds(SYNC_LENGTH );
Serial.print(" -");
}
// ---------------------------------------------------------------------------------------
// calculateLSFR
// ---------------------------------------------------------------------------------------
void calculateLSFR() {
int i;
uint8_t reg = 0x7C;
uint8_t temp_reg = 0;
for (i = 0; i < MESSAGE_SIZE; i++) {
temp_reg = reg & 0x01;
reg >>= 1;
reg |= (temp_reg << 7);
if (temp_reg) {
reg ^= 0x18;
}
LSFR_sequence[i] = reg;
//printf("%02x\n", LSFR_sequence[i]);
}
}
// ---------------------------------------------------------------------------------------
// combineLSFR
// ---------------------------------------------------------------------------------------
uint8_t combineLSFR(uint8_t len, uint8_t *data) {
uint8_t hash_reg = 0; // not 0x64
int byte_idx, bit_idx;
uint8_t byte, bit;
//printf("***COMBINE\n");
for (byte_idx = 0; byte_idx < len; byte_idx++) {
for (bit_idx = 7; bit_idx >= 0; bit_idx--) {
bit = (data[byte_idx] & (1 << bit_idx)) >> bit_idx;
if (bit) {
hash_reg ^= LSFR_sequence[byte_idx * 8 + (7 - bit_idx) + LSFR_OFFSET];
//printf("[%d]: %02x\n", byte_idx * 8 + (7 - bit_idx), hash_reg);
}
bit = 0;
}
}
return hash_reg;
}
// ---------------------------------------------------------------------------------------
// computeChecksum
// ---------------------------------------------------------------------------------------
uint8_t computeChecksum(int length, uint8_t *buff) {
calculateLSFR();
return combineLSFR(length, buff);
} |
Reading the values from the Transmitter
Receiver Code
Code Block | ||
---|---|---|
| ||
// --------------------------------------------------------------------------------------- // Acurite 00606TX Reader // Adapted from code by Ray Wang (Rayshobby LLC) // --------------------------------------------------------------------------------------- #define DATAPIN D2 // ring buffer size has to be large enough to fit // data between two successive sync signals #define RING_BUFFER_SIZE 256 #define SYNC_LENGTH 9000 #define SEP_LENGTH 500 #define BIT1_LENGTH 4000 #define BIT0_LENGTH 2000 #define MESSAGE_SIZE 32 #define LSFR_OFFSET 4 uint8_t LSFR_sequence[MESSAGE_SIZE] = {0}; //ringbuffer contains the time since the last signal was off. unsigned long timings[RING_BUFFER_SIZE]; unsigned int syncIndex1 = 0; // index of the first sync signal unsigned int syncIndex2 = 0; // index of the second sync signal bool received = false; //protypes void ICACHE_RAM_ATTR handler(); // --------------------------------------------------------------------------------------- // setup // --------------------------------------------------------------------------------------- void setup() { Serial.begin(115200); pinMode(DATAPIN, INPUT); attachInterrupt(digitalPinToInterrupt(DATAPIN), handler, CHANGE); Serial.println("\n\nStarted"); } // --------------------------------------------------------------------------------------- // loop // --------------------------------------------------------------------------------------- void loop() { //Did we get a message? if (received == true) { Serial.println("\nReceived..."); // disable interrupt to avoid new data corrupting the buffer detachInterrupt(digitalPinToInterrupt(DATAPIN)); //processSignal unsigned int bits[34]; bool error = processSignal(bits); if(error==false){ //convert our bits to byte array byte data[4]; bool success = bitsToByteArray(bits,32,data,4); if(success){ byte rollingCode = data[0]; Serial.printf("Rolling Code: 0x%02x\n",rollingCode); byte batteryStatus = (data[1] & 0xf0) >> 4; Serial.printf("Battery Status: 0x%02x\n",batteryStatus); float temperature = computeTemperature(data[1],data[2]); Serial.printf("Temp: %0.1f C\n",temperature); byte checksum = data[3]; Serial.printf("checksum: 0x%02x\n",checksum); //uint8_t computeChecksum(int length, uint8_t *buff) { byte computedChecksum = computeChecksum(3,data); if(checksum==computedChecksum){ Serial.printf("Checksum Verified!\n"); }else{ Serial.printf("Checksum Invalid!\n"); } }else{ Serial.printf("Failed to convert bits to bytes array\n"); } }//if(error==false){ // delay for 1 second to avoid repetitions delay(1000); received = false; syncIndex1 = 0; syncIndex2 = 0; // re-enable interrupt attachInterrupt(digitalPinToInterrupt(DATAPIN), handler, CHANGE); }//if (received == true) { } // --------------------------------------------------------------------------------------- // computeTemperature // --------------------------------------------------------------------------------------- // Temperature is a signed 12-bit value with resolution of 0.1C. For example, // 25.6C is encoded as the value 256 (0x100 hexadecimal). A value of -0.1C is // encoded as -1 (0xFFF hexadecimal). // --------------------------------------------------------------------------------------- float computeTemperature(byte highbyte, byte lowbyte){ bool negative=false; Serial.printf("highbyte : 0x%02x \n",highbyte); if((highbyte & 0x08) == 0x08){ negative=true; Serial.println("Negative"); } int rawTemperature = ((highbyte & 0x0f) << 8) + lowbyte; Serial.printf("rawTemperature: %d\n",rawTemperature); if(negative){ rawTemperature = rawTemperature - 4096; //limit to -40C like the acurite receiver if(rawTemperature < -400){ rawTemperature = -400; } } float temperature = rawTemperature / 10.0; return temperature; } // --------------------------------------------------------------------------------------- // processSignal // --------------------------------------------------------------------------------------- // Message is composed of: // - Rolling Code(2 nibbles - 8 bits), // - Status(1 nibble - 4 bits), // - Temperature (signed binary - 3 nibbles - 12 bits ), // - Hash Code (2 nibles - 8 bits) // // Each bit is composed of two signals - a seperator signal followed by a short/long // --------------------------------------------------------------------------------------- bool processSignal(unsigned int *bits){ bool error = false; int totalSignalsInMessage = 32 *2; int count =0; for(unsigned int i=syncIndex1; i!=(syncIndex1+totalSignalsInMessage)%RING_BUFFER_SIZE; i=(i+2)%RING_BUFFER_SIZE) { unsigned long t0 = timings[i]; unsigned long t1 = timings[(i+1)%RING_BUFFER_SIZE]; if (t0>(SEP_LENGTH-150) && t0<(SEP_LENGTH+150)){ if (t1>(BIT1_LENGTH-1000) && t1<(BIT1_LENGTH+1000)) { bits[count]=1; } else if (t1>(BIT0_LENGTH-1000) && t1<(BIT0_LENGTH+1000)) { bits[count]=0; } else { bits[count]=-1; } }else { // Serial.printf("** t0: %d, t1: %d\n",t0,t1); // Serial.printf("Read Error\n"); error=true; break; } count++; }//for if(error==false){ //print bits received Serial.print("bits: "); for(int i=0;i<32;i++){ if(bits[i]>=0){ Serial.print(bits[i]); }else{ Serial.print("X"); } if((i+1)%4==0){ Serial.printf(" "); } } Serial.println(""); } return error; } // --------------------------------------------------------------------------------------- // isSync // --------------------------------------------------------------------------------------- // Detect if a sync signal is present. A sync signal is composed of a seperator signal // (short off 0.5ms) followed by a sync signal (9ms off). // --------------------------------------------------------------------------------------- bool isSync(unsigned int idx) { //get the last two indexes from the ring buffer int t0Index = (idx+RING_BUFFER_SIZE-1) % RING_BUFFER_SIZE; unsigned long t0 = timings[t0Index]; unsigned long t1 = timings[idx]; //check that t0 is a seperator signal, should be around 0.5ms if (t0>(SEP_LENGTH-100) && t0<(SEP_LENGTH+100) ){ //check that t1 is a sync signal, allow for anything between 8-10ms if (t1>(SYNC_LENGTH-1000) && t1<(SYNC_LENGTH+1000)){ if (digitalRead(DATAPIN) == HIGH) { // Serial.printf("toIndex=%d, idx=%d, RING_BUFFER_SIZE=%d \n",t0Index, idx, RING_BUFFER_SIZE); // Serial.printf("t0=%d, t1=%d\n",t0,t1); //found return true; } } } return false; } // --------------------------------------------------------------------------------------- // handler // --------------------------------------------------------------------------------------- // Interrupt handler - reads incoming signal changes from receiver // --------------------------------------------------------------------------------------- void ICACHE_RAM_ATTR handler() { static unsigned long duration = 0; static unsigned long lastTime = 0; static unsigned int ringIndex = 0; static unsigned int syncCount = 0; // exit out if we are in processing a signal. if (received == true) { // Serial.println("received==true"); return; } // calculating timing since last change long time = micros(); duration = time - lastTime; lastTime = time; // store data in ring buffer ringIndex = (ringIndex + 1) % RING_BUFFER_SIZE; timings[ringIndex] = duration; // detect sync signal if (isSync(ringIndex)) { syncCount ++; if (syncCount == 1) { // first time sync is seen, record buffer index syncIndex1 = (ringIndex+1) % RING_BUFFER_SIZE; }else if (syncCount == 2) { syncCount = 0; // second time sync is seen, start bit conversion syncIndex2 = (ringIndex+1) % RING_BUFFER_SIZE; //check how many signals we have received between syncs unsigned int changeCount = 0; if(syncIndex2 < syncIndex1){ changeCount = syncIndex2+RING_BUFFER_SIZE - syncIndex1; }else{ changeCount = syncIndex2 - syncIndex1; } if (changeCount < 66 || changeCount > 68) { //too many signals, disregard received = false; syncIndex1 = 0; syncIndex2 = 0; } else { //we found our signal received = true; } } } } // --------------------------------------------------------------------------------------- // calculateLSFR // --------------------------------------------------------------------------------------- void calculateLSFR() { int i; uint8_t reg = 0x7C; uint8_t temp_reg = 0; for (i = 0; i < MESSAGE_SIZE; i++) { temp_reg = reg & 0x01; reg >>= 1; reg |= (temp_reg << 7); if (temp_reg) { reg ^= 0x18; } LSFR_sequence[i] = reg; //printf("%02x\n", LSFR_sequence[i]); } } // --------------------------------------------------------------------------------------- // combineLSFR // --------------------------------------------------------------------------------------- uint8_t combineLSFR(uint8_t len, uint8_t *data) { uint8_t hash_reg = 0; // not 0x64 int byte_idx, bit_idx; uint8_t byte, bit; //printf("***COMBINE\n"); for (byte_idx = 0; byte_idx < len; byte_idx++) { for (bit_idx = 7; bit_idx >= 0; bit_idx--) { bit = (data[byte_idx] & (1 << bit_idx)) >> bit_idx; if (bit) { hash_reg ^= LSFR_sequence[byte_idx * 8 + (7 - bit_idx) + LSFR_OFFSET]; //printf("[%d]: %02x\n", byte_idx * 8 + (7 - bit_idx), hash_reg); } bit = 0; } } return hash_reg; } // --------------------------------------------------------------------------------------- // computeChecksum // --------------------------------------------------------------------------------------- uint8_t computeChecksum(int length, uint8_t *buff) { calculateLSFR(); return combineLSFR(length, buff); } // --------------------------------------------------------------------------------------- // bitsToByteArray // --------------------------------------------------------------------------------------- // Convert array of integers containing the bits received into byte array // --------------------------------------------------------------------------------------- bool bitsToByteArray(unsigned int *bits, int len, byte* buffer, int bufferLen){ int bidx=0; unsigned int sum = 0; for(int i=0;i<len;i++){ //break out if we have filled up the buffer if(bidx >= bufferLen){ return false; } sum += bits[i]; //new byte? if((i+1)%8==0){ //save to buffer, reset sum and increment bidx buffer[bidx]=sum; sum=0; bidx++; }else{ sum<<=1; } } return true; } |
...