переделал код - не работает. Что не так?

mkvmaks
Offline
Зарегистрирован: 07.07.2013

Всем привет. В общем решил переписать код под себя: не использую 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);   
    }
}

 

mkvmaks
Offline
Зарегистрирован: 07.07.2013

Эх.... забыл спрятать под спойлер . Как можно отредактиовать тему?