переделал код - не работает. Что не так?
- Войдите на сайт для отправки комментариев
Втр, 24/11/2015 - 00:25
Всем привет. В общем решил переписать код под себя: не использую bmp085, вре11 - все остальное есть. Код юрал здесь http://devicter.blogspot.co.il/2013/01/blog-post.html
Использую дисплей 16x2 не i2c. Код компилируется, но ничего не выводится. ( При нажатаии на кнопку - не мигает светодиод.
#include <LiquidCrystalRus.h>
#include <SoftwareSerial.h>
#include <Wire.h>
#include "RTClib.h"
#include <Bounce.h>
#include "DHT.h"
//#define DISABLE_DEBUG // если нужен вывод в Serial - закомментируйте эту строчку
#define LED 13 // LED на D13
#define BUTTON 3
Bounce bouncer = Bounce( BUTTON,5 );
#define DS1307_I2C_ADDRESS 0x68
LiquidCrystalRus lcd(4, 5, 10, 11, 12, 13);
char sTemp[16];
int LCD_LED = 8; //подсветка дисплея
static char wDay[7][4] =
{
"Sun","Mon","Tue","Wed","Thu","Fri","Sat"
};
static char wMonth[12][4] =
{
"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
};
// температура
float t[4];
// влажность
float h[4];
// батарейка
byte b[2];
// счетчик (используем для переключения "экранов")
byte cDisp = 0;
unsigned long dispNow = 0;
unsigned long ledNow = 0;
// параметры для формирования трендов
#define DELTA_TIME 900000 // 15 минут
#define DELTA_TEMP 0.1 // превышение этого значения будет означать изменение температуры
#define DELTA_HYM 1 // порог для влажности
#define DELTA_BAR 1
float PrevTemp[4];
float PrevHym[4];
unsigned long PrevMeasure[3];
char TrendTemp[4];
char TrendHym[4];
#define BMP085_ADDRESS 0x77 // I2C address of BMP085
const unsigned char OSS = 0; // Oversampling Setting
// Calibration values
int ac1;
int ac2;
int ac3;
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1;
int b2;
int mb;
int mc;
int md;
// b5 is calculated in bmp085GetTemperature(...), this variable is also used in bmp085GetPressure(...)
// so ...Temperature(...) must be called before ...Pressure(...).
long b5;
#define DHTPIN 4
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
// Oregon V2 decoder added - Dominique Pierre
// New code to decode OOK signals from weather sensors, etc.
// 2010-04-11 <jcw@equi4.com> http://opensource.org/licenses/mit-license.php
// $Id: ookDecoder.pde 5331 2010-04-17 10:45:17Z jcw $
class DecodeOOK {
protected:
byte total_bits, bits, flip, state, pos, data[25];
virtual char decode (word width) =0;
public:
enum {
UNKNOWN, T0, T1, T2, T3, OK, DONE };
DecodeOOK () {
resetDecoder();
}
bool nextPulse (word width) {
if (state != DONE)
switch (decode(width)) {
case -1:
resetDecoder();
break;
case 1:
done();
break;
}
return isDone();
}
bool isDone () const {
return state == DONE;
}
const byte* getData (byte& count) const {
count = pos;
return data;
}
void resetDecoder () {
total_bits = bits = pos = flip = 0;
state = UNKNOWN;
}
// add one bit to the packet data buffer
virtual void gotBit (char value) {
total_bits++;
byte *ptr = data + pos;
*ptr = (*ptr >> 1) | (value << 7);
if (++bits >= 8) {
bits = 0;
if (++pos >= sizeof data) {
resetDecoder();
return;
}
}
state = OK;
}
// store a bit using Manchester encoding
void manchester (char value) {
flip ^= value; // manchester code, long pulse flips the bit
gotBit(flip);
}
// move bits to the front so that all the bits are aligned to the end
void alignTail (byte max =0) {
// align bits
if (bits != 0) {
data[pos] >>= 8 - bits;
for (byte i = 0; i < pos; ++i)
data[i] = (data[i] >> bits) | (data[i+1] << (8 - bits));
bits = 0;
}
// optionally shift bytes down if there are too many of 'em
if (max > 0 && pos > max) {
byte n = pos - max;
pos = max;
for (byte i = 0; i < pos; ++i)
data[i] = data[i+n];
}
}
void reverseBits () {
for (byte i = 0; i < pos; ++i) {
byte b = data[i];
for (byte j = 0; j < 8; ++j) {
data[i] = (data[i] << 1) | (b & 1);
b >>= 1;
}
}
}
void reverseNibbles () {
for (byte i = 0; i < pos; ++i)
data[i] = (data[i] << 4) | (data[i] >> 4);
}
void done () {
while (bits)
gotBit(0); // padding
state = DONE;
}
};
// 433 MHz decoders
//===================================================================
class OregonDecoderV3 : public DecodeOOK {
public:
OregonDecoderV3() {}
// add one bit to the packet data buffer
virtual void gotBit (char value) {
data[pos] = (data[pos] >> 1) | (value ? 0x80 : 00);
total_bits++;
pos = total_bits >> 3;
if (pos >= sizeof data) {
//Serial.println("sizeof data");
resetDecoder();
return;
}
state = OK;
}
virtual char decode (word width) {
if (200 <= width && width < 1200) {
//Serial.println(width);
byte w = width >= 700;
switch (state) {
case UNKNOWN:
if (w == 0) {
// Long pulse
++flip;
} else if (32 <= flip) {
flip = 1;
manchester(1);
} else {
// Reset decoder
return -1;
}
break;
case OK:
if (w == 0) {
// Short pulse
state = T0;
} else {
// Long pulse
manchester(1);
}
break;
case T0:
if (w == 0) {
// Second short pulse
manchester(0);
} else {
// Reset decoder
return -1;
}
break;
}
} else {
// Trame intermédiaire 48bits ex: [OSV3 6281 3C 6801 70]
return (total_bits <104 && total_bits>=40 ) ? 1: -1;
}
return (total_bits == 104) ? 1: 0;
}
};
class OregonDecoderV2 : public DecodeOOK {
public:
OregonDecoderV2() {}
// add one bit to the packet data buffer
virtual void gotBit (char value) {
if(!(total_bits & 0x01))
{
data[pos] = (data[pos] >> 1) | (value ? 0x80 : 00);
}
total_bits++;
pos = total_bits >> 4;
if (pos >= sizeof data) {
Serial.println("sizeof data");
resetDecoder();
return;
}
state = OK;
}
virtual char decode (word width) {
if (200 <= width && width < 1200) {
//Serial.println(width);
byte w = width >= 700;
switch (state) {
case UNKNOWN:
if (w != 0) {
// Long pulse
++flip;
} else if (w == 0 && 24 <= flip) {
// Short pulse, start bit
flip = 0;
state = T0;
} else {
// Reset decoder
return -1;
}
break;
case OK:
if (w == 0) {
// Short pulse
state = T0;
} else {
// Long pulse
manchester(1);
}
break;
case T0:
if (w == 0) {
// Second short pulse
manchester(0);
} else {
// Reset decoder
return -1;
}
break;
}
} else if (width >= 2500 && pos >= 8) {
return 1;
} else {
return -1;
}
return 0;
}
};
//===================================================================
OregonDecoderV2 orscV2;
OregonDecoderV3 orscV3;
volatile word pulse;
void ext_int_1(void)
{
static word last;
// determine the pulse length in microseconds, for either polarity
pulse = micros() - last;
last += pulse;
}
void reportSerial (const char* s, class DecodeOOK& decoder) {
byte pos;
const byte* data = decoder.getData(pos);
#ifndef DISABLE_DEBUG
Serial.print(s);
Serial.print(' ');
for (byte i = 0; i < pos; ++i) {
Serial.print(data[i] >> 4, HEX);
Serial.print(data[i] & 0x0F, HEX);
}
Serial.println();
#endif
// Outside/Water Temp : THGN132N,...
if(data[0] == 0xEA && data[1] == 0x4C)
{
#ifndef DISABLE_DEBUG
Serial.print("[THGN132N,...] Id:");
Serial.print(data[3], HEX);
Serial.print(", Channel:");
Serial.print(channel(data));
Serial.print(", temp:");
Serial.print(temperature(data));
Serial.print(", hum:");
Serial.print(humidity(data));
Serial.print(", bat:");
Serial.print(battery(data));
Serial.println();
#endif
// используем только 2 датчика THGN132N на 1 и 2 канале
if (channel(data) > 0 && channel(data) < 4){
t[channel(data)-1]=temperature(data);
h[channel(data)-1]=humidity(data);
b[channel(data)-1]=battery(data);
// если время с прошлого измерения больше DELTA_TIME
if(millis()-PrevMeasure[channel(data)-1] > DELTA_TIME) {
// считаем тренд по двум значениям
TrendTemp[channel(data)-1] = getTrend(t[channel(data)-1], PrevTemp[channel(data)-1], DELTA_TEMP);
TrendHym[channel(data)-1] = getTrend(h[channel(data)-1], PrevHym[channel(data)-1], DELTA_HYM);
// запоминаем "предыдущее" значение
PrevTemp[channel(data)-1] = t[channel(data)-1];
PrevHym[channel(data)-1] = h[channel(data)-1];
// и записываем текущее время
PrevMeasure[channel(data)-1] = millis();
#ifndef DISABLE_DEBUG
Serial.print("TrendTemp[");
Serial.print(channel(data)-1, DEC);
Serial.print("]:");
Serial.print(TrendTemp[channel(data)-1], DEC);
Serial.print(", TrendHym[");
Serial.print(channel(data)-1, DEC);
Serial.print("]:");
Serial.print(TrendHym[channel(data)-1], DEC);
Serial.println();
#endif
}
}
}
decoder.resetDecoder();
}
//установка времени
void setDateDs1307(byte second, // 0-59
byte minute, // 0-59
byte hour, // 1-23
byte dayOfWeek, // 1-7
byte dayOfMonth, // 1-28/29/30/31
byte month, // 1-12
byte year) // 0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}
void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f);
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
void setup () {
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
Wire.begin();
second = 30;
minute = 00;
hour = 23;
dayOfWeek = 7;
dayOfMonth = 17;
month = 5;
year = 15;
// setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
#ifndef DISABLE_DEBUG
Serial.begin(9600);
Serial.println("\n[WeatherStation]");
#endif
lcd.begin(16, 2);
pinMode(2, INPUT); // D2 - RF-модуль
digitalWrite(2, 1); // включим подтягивающий резистор
pinMode(LED, OUTPUT); // LED
pinMode(BUTTON,INPUT);
Wire.begin();
dht.begin();
bmp085Calibration();
attachInterrupt(0, ext_int_1, CHANGE);
}
void loop () {
// char string[20];
noInterrupts();
word p = pulse;
pulse = 0;
interrupts();
if (p != 0) {
if (orscV2.nextPulse(p)){
reportSerial("OSV2", orscV2);
digitalWrite(LED, HIGH);
ledNow = millis()+200;
}
}
// Update the debouncer
bouncer.update ( );
// Get the update value
int value = bouncer.read();
if ((millis() >= dispNow) || ( value == HIGH)) {
//lcd.print(string);
getMeasure();
printValues();
dispNow=millis()+20000;
}
if (millis() >= ledNow) {
digitalWrite(LED, LOW);
}
}
float temperature(const byte* data)
{
int sign = (data[6]&0x8) ? -1 : 1;
float temp = ((data[5]&0xF0) >> 4)*10 + (data[5]&0xF) + (float)(((data[4]&0xF0) >> 4) / 10.0);
return sign * temp;
}
byte humidity(const byte* data)
{
return (data[7]&0xF) * 10 + ((data[6]&0xF0) >> 4);
}
// Ne retourne qu'un apercu de l'etat de la baterie : 10 = faible
byte battery(const byte* data)
{
return (data[4] & 0x4) ? 10 : 90;
}
byte channel(const byte* data)
{
byte channel;
switch (data[2])
{
case 0x10:
channel = 1;
break;
case 0x20:
channel = 2;
break;
case 0x40:
channel = 3;
break;
}
return channel;
}
void printValues(){
char buf[17];
char tbuf[6];
char pbuf[6];
char string[20];
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
switch (cDisp) {
case 0:
sprintf(buf, "Время: %02i:%02i:%02i ", hour, minute, dayOfWeek);
lcd.setCursor(0, 1);
lcd.print(buf);
sprintf(buf, " %2d %s %4d ", dayOfMonth, month, year);
lcd.setCursor(0, 1);
lcd.print(buf);
cDisp++;
break;
case 1:
dtostrf(t[3],5,1,tbuf);
sprintf(buf, "Inside: %s\xDF""C%c", tbuf, getTrendSign(TrendTemp[3]));
lcd.setCursor(0, 0);
lcd.print(buf);
dtostrf(h[2],5,1,tbuf);
dtostrf(h[3],3,0,pbuf);
sprintf(buf, "%s%%%c %smm%c", tbuf, getTrendSign(TrendHym[2]), pbuf, getTrendSign(TrendHym[3]));
lcd.setCursor(0, 1);
lcd.print(buf);
cDisp++;
break;
case 2:
for (int i=0; i<2; i++) {
dtostrf(t[i],5,1,tbuf);
dtostrf(h[i],3,0,pbuf);
sprintf(buf, "%s\xDF""C%c %s%%%c %c", tbuf, getTrendSign(TrendTemp[i]), pbuf, getTrendSign(TrendHym[i]), getBattSign(b[i]));
lcd.setCursor(0, i);
lcd.print(buf);
}
cDisp++;
break;
}
if (cDisp>2) cDisp=0;
}
// функция получения тренда
char getTrend(float val1, float val2, float delta) {
if (val1-val2>delta) {
return 1;
}
else if (val2-val1>delta) {
return -1;
}
else {
return 0;
}
}
// функция выбора символа для отображения тренда
char getTrendSign(char trend) {
switch (trend){
case -1:
return '_';
break;
case 1:
return '^';
break;
default:
return ' ';
break;
}
}
// функция выбора символа для отображения батареи
char getBattSign(byte batt) {
if (batt > 50){
return char(219);
}
return char(161);
}
// измерение
void getMeasure() {
// барометр
t[3] = bmp085GetTemperature(bmp085ReadUT());
h[3] = bmp085GetPressure(bmp085ReadUP());
h[3] = h[3]*0.0075006375541921;
//Serial.println(pressure*0.0075006375541921);
// DHT22
t[2] = dht.readTemperature();
h[2] = dht.readHumidity();
// тренды
if(millis()-PrevMeasure[3] > DELTA_TIME) {
// считаем тренд по двум значениям
TrendTemp[3] = getTrend(t[3], PrevTemp[3], DELTA_TEMP);
TrendHym[3] = getTrend(h[3], PrevHym[3], DELTA_BAR); // давление у нас тут
TrendTemp[2] = getTrend(t[2], PrevTemp[2], DELTA_TEMP);
TrendHym[2] = getTrend(h[2], PrevHym[2], DELTA_HYM); // а тут влажность, как и должно
// запоминаем "предыдущее" значение
PrevTemp[3] = t[3];
PrevHym[3] = h[3];
PrevTemp[2] = t[2];
PrevHym[2] = h[2];
// и записываем текущее время
PrevMeasure[3] = millis(); // поскольку у нас DHT22 и BMP085 опрашиваются одновременно - фиксируем время только одно
}
return;
}
void bmp085Calibration()
{
//Serial.println("test0");
ac1 = bmp085ReadInt(0xAA);
//Serial.println("test1");
ac2 = bmp085ReadInt(0xAC);
ac3 = bmp085ReadInt(0xAE);
ac4 = bmp085ReadInt(0xB0);
ac5 = bmp085ReadInt(0xB2);
ac6 = bmp085ReadInt(0xB4);
b1 = bmp085ReadInt(0xB6);
b2 = bmp085ReadInt(0xB8);
mb = bmp085ReadInt(0xBA);
mc = bmp085ReadInt(0xBC);
md = bmp085ReadInt(0xBE);
//Serial.println("test2");
}
// Calculate temperature in deg C
float bmp085GetTemperature(unsigned int ut){
long x1, x2;
x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
x2 = ((long)mc << 11)/(x1 + md);
b5 = x1 + x2;
float temp = ((b5 + 8)>>4);
temp = temp /10;
return temp;
}
// Calculate pressure given up
// calibration values must be known
// b5 is also required so bmp085GetTemperature(...) must be called first.
// Value returned will be pressure in units of Pa.
long bmp085GetPressure(unsigned long up){
long x1, x2, x3, b3, b6, pr;
unsigned long b4, b7;
b6 = b5 - 4000;
// Calculate B3
x1 = (b2 * (b6 * b6)>>12)>>11;
x2 = (ac2 * b6)>>11;
x3 = x1 + x2;
b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
// Calculate B4
x1 = (ac3 * b6)>>13;
x2 = (b1 * ((b6 * b6)>>12))>>16;
x3 = ((x1 + x2) + 2)>>2;
b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
b7 = ((unsigned long)(up - b3) * (50000>>OSS));
if (b7 < 0x80000000)
pr = (b7<<1)/b4;
else
pr = (b7/b4)<<1;
x1 = (pr>>8) * (pr>>8);
x1 = (x1 * 3038)>>16;
x2 = (-7357 * pr)>>16;
pr += (x1 + x2 + 3791)>>4;
long temp = pr;
return temp;
}
// Read 1 byte from the BMP085 at 'address'
char bmp085Read(unsigned char address)
{
unsigned char data;
Wire.beginTransmission(BMP085_ADDRESS);
Wire.write(address);
Wire.endTransmission();
Wire.requestFrom(BMP085_ADDRESS, 1);
while(!Wire.available())
;
return Wire.read();
}
// Read 2 bytes from the BMP085
// First byte will be from 'address'
// Second byte will be from 'address'+1
int bmp085ReadInt(unsigned char address)
{
unsigned char msb, lsb;
//Serial.println("test3");
Wire.beginTransmission(BMP085_ADDRESS);
Wire.write(address);
Wire.endTransmission();
//Serial.println("test4");
Wire.requestFrom(BMP085_ADDRESS, 2);
while(Wire.available()<2);
msb = Wire.read();
lsb = Wire.read();
//Serial.println("test5");
return (int) msb<<8 | lsb;
}
// Read the uncompensated temperature value
unsigned int bmp085ReadUT(){
unsigned int ut;
// Write 0x2E into Register 0xF4
// This requests a temperature reading
Wire.beginTransmission(BMP085_ADDRESS);
Wire.write(0xF4);
Wire.write(0x2E);
Wire.endTransmission();
// Wait at least 4.5ms
delay(5);
// Read two bytes from registers 0xF6 and 0xF7
ut = bmp085ReadInt(0xF6);
return ut;
}
// Read the uncompensated pressure value
unsigned long bmp085ReadUP(){
unsigned char msb, lsb, xlsb;
unsigned long up = 0;
// Write 0x34+(OSS<<6) into register 0xF4
// Request a pressure reading w/ oversampling setting
Wire.beginTransmission(BMP085_ADDRESS);
Wire.write(0xF4);
Wire.write(0x34 + (OSS<<6));
Wire.endTransmission();
// Wait for conversion, delay time dependent on OSS
delay(2 + (3<<OSS));
// Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
msb = bmp085Read(0xF6);
lsb = bmp085Read(0xF7);
xlsb = bmp085Read(0xF8);
up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);
return up;
}
void writeRegister(int deviceAddress, byte address, byte val) {
Wire.beginTransmission(deviceAddress); // start transmission to device
Wire.write(address); // send register address
Wire.write(val); // send value to write
Wire.endTransmission(); // end transmission
}
int readRegister(int deviceAddress, byte address){
int v;
Wire.beginTransmission(deviceAddress);
Wire.write(address); // register to read
Wire.endTransmission();
Wire.requestFrom(deviceAddress, 1); // read a byte
while(!Wire.available()) {
// waiting
}
v = Wire.read();
return v;
}
Данный код полностью работает для датчика DHN132... используется протокол V2
// New code to decode OOK signals from Energy OWL CMR180 sensor // Oregon V3 decoder added - Eric Vandecasteele (onlinux) // // Oregon V2 decoder modfied - Olivier Lebrun // Oregon V2 decoder added - Dominique Pierre // New code to decode OOK signals from weather sensors, etc. // 2010-04-11 <jcw@equi4.com> http://opensource.org/licenses/mit-license.php // $Id: ookDecoder.pde 5331 2010-04-17 10:45:17Z jcw $ //http://nm.omarov.net/ //http://cyber-place.ru/showthread.php?t=1169 //https://github.com/onlinux/OWL-CM180/blob/6d47a1003ffe4d00a5d72f01ffb3477ba8083a4e/arduino/oregon_owl.ino #include <LiquidCrystal.h> LiquidCrystal lcd(4, 5, 10, 11, 12, 13); //#define DISABLE_DEBUG // если нужен вывод в Serial - закомментируйте эту строчку class DecodeOOK { protected: byte total_bits, bits, flip, state, pos, data[31]; virtual char decode (word width) =0; public: enum { UNKNOWN, T0, T1, T2, T3, OK, DONE }; DecodeOOK () { resetDecoder(); } bool nextPulse (word width) { if (state != DONE) switch (decode(width)) { case -1: resetDecoder(); break; case 1: done(); break; } return isDone(); } bool isDone () const { return state == DONE; } const byte* getData (byte& count) const { count = pos; return data; } void resetDecoder () { total_bits = bits = pos = flip = 0; state = UNKNOWN; } // add one bit to the packet data buffer virtual void gotBit (char value) { total_bits++; byte *ptr = data + pos; *ptr = (*ptr >> 1) | (value << 7); if (++bits >= 8) { bits = 0; if (++pos >= sizeof data) { resetDecoder(); return; } } state = OK; } // store a bit using Manchester encoding_rx void manchester (char value) { flip ^= value; // manchester code, long pulse flips the bit gotBit(flip); } // move bits to the front so that all the bits are aligned to the end void alignTail (byte max =0) { // align bits if (bits != 0) { data[pos] >>= 8 - bits; for (byte i = 0; i < pos; ++i) data[i] = (data[i] >> bits) | (data[i+1] << (8 - bits)); bits = 0; } // optionally shift bytes down if there are too many of 'em if (max > 0 && pos > max) { byte n = pos - max; pos = max; for (byte i = 0; i < pos; ++i) data[i] = data[i+n]; } } void reverseBits () { for (byte i = 0; i < pos; ++i) { byte b = data[i]; for (byte j = 0; j < 8; ++j) { data[i] = (data[i] << 1) | (b & 1); b >>= 1; } } } void reverseNibbles () { for (byte i = 0; i < pos; ++i) data[i] = (data[i] << 4) | (data[i] >> 4); } void done () { while (bits) gotBit(0); // padding state = DONE; } }; class OregonDecoderV2 : public DecodeOOK { public: OregonDecoderV2() {} // add one bit to the packet data buffer virtual void gotBit (char value) { if(!(total_bits & 0x01)) { data[pos] = (data[pos] >> 1) | (value ? 0x80 : 00); } total_bits++; pos = total_bits >> 4; if (pos >= sizeof data) { Serial.println("sizeof data"); resetDecoder(); return; } state = OK; } virtual char decode (word width) { if (200 <= width && width < 1200) { //Serial.println(width); byte w = width >= 700; switch (state) { case UNKNOWN: if (w != 0) { // Long pulse ++flip; } else if (w == 0 && 24 <= flip) { // Short pulse, start bit flip = 0; state = T0; } else { // Reset decoder return -1; } break; case OK: if (w == 0) { // Short pulse state = T0; } else { // Long pulse manchester(1); } break; case T0: if (w == 0) { // Second short pulse manchester(0); } else { // Reset decoder return -1; } break; } } else if (width >= 2500 && pos >= 8) { return 1; } else { return -1; } return 0; } }; //=================================================================== class OregonDecoderV3 : public DecodeOOK { public: OregonDecoderV3() {} // add one bit to the packet data buffer virtual void gotBit (char value) { data[pos] = (data[pos] >> 1) | (value ? 0x80 : 00); total_bits++; pos = total_bits >> 3; if (pos >= sizeof data) { //Serial.println("sizeof data"); resetDecoder(); return; } state = OK; } virtual char decode (word width) { if (200 <= width && width < 1200) { //Serial.println(width); byte w = width >= 700; switch (state) { case UNKNOWN: if (w == 0) { // Long pulse ++flip; } else if (32 <= flip) { flip = 1; manchester(1); } else { // Reset decoder return -1; } break; case OK: if (w == 0) { // Short pulse state = T0; } else { // Long pulse manchester(1); } break; case T0: if (w == 0) { // Second short pulse manchester(0); } else { // Reset decoder return -1; } break; } } else { // Trame intermédiaire 48bits ex: [OSV3 6281 3C 6801 70] return (total_bits <104 && total_bits>=40 ) ? 1: -1; } return (total_bits == 104) ? 1: 0; } }; //=================================================================== OregonDecoderV2 orscV2; OregonDecoderV3 orscV3; volatile word pulse; void ext_int_1(void) { static word last; // determine the pulse length in microseconds, for either polarity pulse = micros() - last; last += pulse; } float temperature(const byte* data) { int sign = (data[6]&0x8) ? -1 : 1; float temp = ((data[5]&0xF0) >> 4)*10 + (data[5]&0xF) + (float)(((data[4]&0xF0) >> 4) / 10.0); return sign * temp; } byte humidity(const byte* data) { return (data[7]&0xF) * 10 + ((data[6]&0xF0) >> 4); } // Ne retourne qu'un apercu de l'etat de la batterie : 10 = faible byte battery(const byte* data) { return (data[4] & 0x4) ? 10 : 90; } byte channel(const byte* data) { byte channel; switch (data[2]) { case 0x10: channel = 1; break; case 0x20: channel = 2; break; case 0x40: channel = 3; break; } return channel; } unsigned int power(const byte* d){ unsigned int val = 0; val += d[4] << 8; val += d[3]; return val & 0xFFF0 ; } unsigned long total(const byte* d){ long val = 0; val = (unsigned long)d[8]<<24; // Serial.println(); // Serial.print(" val:"); Serial.print(val,HEX); Serial.print(" "); // Serial.println(d[8], HEX); val += (unsigned long)d[7] << 16; // Serial.print(" val:"); Serial.print(val,HEX); Serial.print(" "); // Serial.println(d[7], HEX); val += d[6] << 8; // Serial.print(" val:"); Serial.print(val,HEX); Serial.print(" "); // Serial.println(d[6], HEX); val += d[5]; // Serial.print(" val:"); Serial.print(val,HEX); Serial.print(" "); // Serial.println(d[5], HEX); return val ; } void reportSerial (const char* s, class DecodeOOK& decoder) { byte pos; const byte* data = decoder.getData(pos); #ifndef DISABLE_DEBUG Serial.print(s); Serial.print(' '); for (byte i = 0; i < pos; ++i) { Serial.print(data[i] >> 4, HEX); Serial.print(data[i] & 0x0F, HEX); } #endif // Energy OWL : CMR180 if(data[2] == 0x3C ) { #ifndef DISABLE_DEBUG Serial.print("[CMR180,...] Id:"); Serial.print(data[0], HEX);Serial.print(data[1], HEX); Serial.print(", size:"); Serial.print(pos); Serial.print(" ,Flags:"); Serial.print(data[3] & 0x0F, HEX); Serial.print(" ,power:"); Serial.print(power(data)); if (pos > 6) { // Display only for main frame // Secondary frame is only 6 Bytes long Serial.print(" ,total:"); Serial.print(total(data)); Serial.print(" ,total kWh:"); Serial.print(total(data)/3600/1000); } Serial.println(); #endif } // Outside/Water Temp : THN132N,... if (data[0] == 0xEA && data[1] == 0x4C) { #ifndef DISABLE_DEBUG Serial.print("[THN132N,...] Id:"); Serial.print(data[3], HEX); Serial.print(" ,Channel:"); Serial.print(channel(data)); Serial.print(" ,temp:"); Serial.print(temperature(data)); Serial.print(" ,bat:"); Serial.print(battery(data)); Serial.println(); #endif lcd.setCursor(0, 0); lcd.print("temp:"); lcd.setCursor(5, 0); lcd.print(temperature(data)); lcd.setCursor(10, 0); lcd.print("\x99"); } // Inside Temp-Hygro : THGR228N,... else if(data[0] == 0x1A && data[1] == 0x2D) { #ifndef DISABLE_DEBUG Serial.print("[THGR228N,...] Id:"); Serial.print(data[3], HEX); Serial.print(" ,Channel:"); Serial.print(channel(data)); Serial.print(" ,temp:"); Serial.print(temperature(data)); Serial.print(" ,hum:"); Serial.print(humidity(data)); Serial.print(" ,bat:"); Serial.print(battery(data)); Serial.println(); #endif } decoder.resetDecoder(); } void setup () { #ifndef DISABLE_DEBUG Serial.begin(115200); Serial.println("\n[ookDecoder]"); #endif lcd.begin(16, 2); attachInterrupt(0, ext_int_1, CHANGE); //DDRE &= ~_BV(PE5); //input with pull-up //PORTE &= ~_BV(PE5); } void loop () { static int i = 0; cli(); word p = pulse; pulse = 0; sei(); if (p != 0) { if (orscV3.nextPulse(p)) reportSerial("OSV3", orscV3); if (orscV2.nextPulse(p)) reportSerial("OSV2", orscV2); } }
Эх.... забыл спрятать под спойлер . Как можно отредактиовать тему?