Programmet är långt ifrån färdigt, nuvarande version använder jag för att ta reda på dels vilka pulslängder som sensorerna faktiskt använder (eller mottagaren känner av) och för att försöka få stabila avläsningar. Jag får ibland signaler som har korrekt format men inte hör till mina sensorer, jag gissar att det är någon av grannarnas sensorer (minst 100 m bort) som inte använder riktigt samma format som de sensorer jag har. Programmet kör jag för ögonblicket på en Arduino Mega, med den syntax som dessa kort har. Jag har ändrat de pulslängder programmet skall acceptera utan att ändra kommentarerna i början, utveckling pågår som sagt.
Kod: Markera allt
/*
Receiver for temperature probes for wireless thermometers "TFA" brand
Long high signal measured as 1385 to 1445 µs stands for logic 0
Short high signal measured as 595 to 635 µs stands for logic 1
Signal train preceded by about 32 ms low (radio silence)
Between high signals the low part is measured as 970 to 1050 µs
See also http://thomaspfeifer.net/funk_temperatur_sensor_protokoll.htm for some details on the protocol
*/
#include "string.h"
//#define sigShort 615
//#define sigShortTolerance 150
//#define sigShortLow (sigShort - sigShortTolerance)
//#define sigShortHigh (sigShort + sigShortTolerance)
#define sigShortLow 350
#define sigShortHigh 850
//#define sigLong 1415
//#define sigLongTolerance 150
//#define sigLongLow (sigLong - sigLongTolerance)
//#define sigLongHigh (sigLong + sigLongTolerance)
#define sigLongLow 1150
#define sigLongHigh 1800
#define output Serial
#define rxPin 8
struct structTempSens { // Struct with information regarding each sensor
uint16_t id; // Unit ID (random at each reset/battery change of sensor unit)
uint8_t tA, tB, tC; // Transmitted temperature values, temperature = (A-5)*10 + B + C/10
char tempStr[6]; // Temperature as ASCII string
char name[16]; // Human comprehensible name
unsigned long values; // Received packages from this sensor
} tempSens[8];
uint8_t numberSensors = 0; // Number of sensors detected
uint8_t lastUnit;
byte data[44]; // Raw data from sensor via radio
unsigned long now;
uint16_t min0, max0, min1, max1;
unsigned long avg0, avg1;
uint8_t sensorNumber(uint16_t unitId) { // Find position in array of struct of this unitId, or create new
uint8_t i = 0, thisUnit;
while(i < numberSensors) {
if(tempSens[i].id == unitId) return(i); // Found a matching unit ID, return its number in the array
else i++;
}
thisUnit = numberSensors;
numberSensors++;
tempSens[thisUnit].id = unitId; // Store ID
switch (unitId) { // Store human comprehensible name, if available
case 0x0a06:
strcpy(tempSens[thisUnit].name, "inomhus");
break;
case 0x0a01:
strcpy(tempSens[thisUnit].name, "husvagg");
break;
case 0x0a08:
strcpy(tempSens[thisUnit].name, "garaget");
break;
default:
strcpy(tempSens[thisUnit].name, "unknown");
break;
}
tempSens[thisUnit].values = 0;
return(thisUnit); // Return the new number given to this unit ID
}
void process(void) {
uint16_t unitId = 0;
uint8_t unitA = 0, unitB = 0, unitC = 0;
uint8_t currentSensor;
uint8_t i;
for(uint8_t i=0; i<16; i++) {
unitId += data[i] << (15 - i);
}
for(uint8_t i=0; i<4; i++) {
unitA += data[i + 20] << (3 - i);
unitB += data[i + 24] << (3 - i);
unitC += data[i + 28] << (3 - i);
}
currentSensor = sensorNumber(unitId);
tempSens[currentSensor].tA = unitA;
tempSens[currentSensor].tB = unitB;
tempSens[currentSensor].tC = unitC;
i = 0;
if(unitA < 5) {
tempSens[currentSensor].tempStr[i++] = '-';
tempSens[currentSensor].tempStr[i++] = '0' + 5 - unitA;
} else if (unitA > 5) {
tempSens[currentSensor].tempStr[i++] = '0' + unitA - 5;
}
tempSens[currentSensor].tempStr[i++] = '0' + (unitB % 10);
tempSens[currentSensor].tempStr[i++] = '.';
tempSens[currentSensor].tempStr[i++] = '0' + unitC;
tempSens[currentSensor].tempStr[i++] = 0;
tempSens[currentSensor].values++;
lastUnit = currentSensor;
}
void reportBinData(void) {
for(uint8_t i=0; i<44; i++) {
output.print(data[i], DEC);
if((i >= 15) && (i+1) % 4 == 0) output.print(" ");
}
}
void reportTime(unsigned long now) {
char nowH, nowM, nowS;
now /= 1000UL;
nowS = now % 60UL;
now /= 60UL;
nowM = now % 60UL;
nowH = now / 60UL;
if(nowH < 10) output.print("0");
output.print(nowH, DEC);
output.print(":");
if(nowM < 10) output.print("0");
output.print(nowM, DEC);
output.print(":");
if(nowS < 10) output.print("0");
output.print(nowS, DEC);
}
void reportUnitId(uint16_t unitId) {
output.print("\"");
if(unitId < 0x1000) output.print("0");
if(unitId < 0x100) output.print("0");
if(unitId < 0x10) output.print("0");
output.print(unitId, HEX);
output.print("\"");
}
void reportUnit(uint8_t unitNumber) {
output.print("\"");
output.print(tempSens[unitNumber].name);
output.print("\";");
output.print(tempSens[unitNumber].tempStr);
output.print(";");
output.print(tempSens[unitNumber].values, DEC);
}
void report() {
reportTime(now);
output.print(";");
output.print(min0);
output.print(";");
output.print(avg0);
output.print(";");
output.print(max0);
output.print(";");
output.print(min1);
output.print(";");
output.print(avg1);
output.print(";");
output.print(max1);
for(uint8_t i=0; i<numberSensors; i++) {
output.print(";");
reportUnit(i);
}
output.println();
if(strcmp(tempSens[lastUnit].name, "unknown") == 0) {
reportBinData();
output.println();
output.print(tempSens[lastUnit].tA, DEC);
output.print(";");
output.print(tempSens[lastUnit].tB, DEC);
output.print(";");
output.print(tempSens[lastUnit].tC, DEC);
output.println();
}
}
void setup() {
pinMode(rxPin, INPUT);
output.begin(57600);
}
void loop() {
uint8_t i = 0, count0 = 0, count1 = 0, j;
uint16_t sample0[44], sample1[44];
unsigned long t;
boolean sigCheck = true;
while (i < 44) {
t = pulseIn(rxPin, HIGH, sigLongHigh);
if (sigShortLow < t && t < sigShortHigh) {
data[i++] = 1;
sample1[count1++] = int(t);
} else if(sigLongLow < t && t < sigLongHigh) {
data[i++] = 0;
sample0[count0++] = int(t);
} else {
i = 0;
count0 = 0;
count1 = 0;
continue;
}
}
j = 0;
while(sigCheck && j<4) {
sigCheck = sigCheck && (data[j+20] == data[j+32]);
sigCheck = sigCheck && (data[j+24] == data[j+36]);
j++;
}
if(sigCheck) {
avg0 = 0;
min0 = max0 = sample0[0];
for(j=0; j<count0; j++) {
avg0 += sample0[j];
min0 = min(min0, sample0[j]);
max0 = max(max0, sample0[j]);
}
avg0 /= count0;
avg1 = 0;
min1 = max1 = sample1[0];
for(j=0; j<count1; j++) {
avg1 += sample1[j];
min1 = min(min1, sample1[j]);
max1 = max(max1, sample1[j]);
}
avg1 /= count1;
now = millis();
process();
report();
}
}