Displaying on an Oled screen values of 2 (or more) Oregon sensors

Hello,

I am new in Arduino programming. I am mixing different codes to display on a Oled screen the values of 2 Oregon Scientific sensors.

I’d like to display on the first line the value of the channel 1 sensor and on a second line the values of the channel 2 sensor. It works but alternatively ; the first values are correctly displayed but once the second sensor values are displayed on the second line the first line disappears.

My guess is I should not use an If control but I don’t want to use instead of it.

This is my code (not perfect)

// 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 $

#include <U8glib.h>
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_DEV_0);  // I2C / TWI

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;
    }
};

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;

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 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 reportSerial (const char* s, class DecodeOOK& decoder)
{
  byte pos;
  const byte* data = decoder.getData(pos);
  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.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();

  u8g.firstPage();
  do {
    u8g.setFont(u8g_font_helvR10);
    if (channel(data) == 1) {
    u8g.setPrintPos(0, 20);
    }
    else {
    u8g.setPrintPos(0, 40);
    }
    u8g.print(String(channel(data)) + String(temperature(data)) + String(humidity(data)));
    } while ( u8g.nextPage() );

  decoder.resetDecoder();
}

void setup ()
{
  Serial.begin(115200);
  Serial.println("\n[ookDecoder]");
  attachInterrupt(1, 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 (orscV2.nextPulse(p))
      reportSerial("OSV2", orscV2);

  }
}

At a quick glance, it appears that your code only writes one of the two values that you mention to the display. That won't help us understand the problem.

Can you please post code that actually matches the description of the problem?

Hello,

this is the only code I use.

The OregonDecoderV2 read and decode the Oregon sensor's then serial print the values.
this is an example of returned values in the serial monitor

OSV2 1A2D103D120810153370[THGR228N,...] Id:3D ,Channel:1 ,temp:8.10 ,hum:51 ,bat:90
OSV2 1A2D2061612030552FF6[THGR228N,...] Id:61 ,Channel:2 ,temp:20.60 ,hum:53 ,bat:90
OSV2 1A2D103D120810153370[THGR228N,...] Id:3D ,Channel:1 ,temp:8.10 ,hum:51 ,bat:90
OSV2 1A2D2061612020552EE3[THGR228N,...] Id:61 ,Channel:2 ,temp:20.60 ,hum:52 ,bat:90
OSV2 1A2D103D120810153370[THGR228N,...] Id:3D ,Channel:1 ,temp:8.10 ,hum:51 ,bat:90
OSV2 1A2D2061612020552EE3[THGR228N,...] Id:61 ,Channel:2 ,temp:20.60 ,hum:52 ,bat:90
OSV2 1A2D103D020820153359[THGR228N,...] Id:3D ,Channel:1 ,temp:8.00 ,hum:52 ,bat:90
OSV2 1A2D2061512020552DD9[THGR228N,...] Id:61 ,Channel:2 ,temp:20.50 ,hum:52 ,bat:90
OSV2 1A2D103D020820153359[THGR228N,...] Id:3D ,Channel:1 ,temp:8.00 ,hum:52 ,bat:90
OSV2 1A2D2061512020552DD9[THGR228N,...] Id:61 ,Channel:2 ,temp:20.50 ,hum:52 ,bat:90

If you have no display code, how do explain this statement?

It works but alternatively ; the first values are correctly displayed but once the second sensor values are displayed on the second line the first line disappears.

I guess the problem resides here.
I should not use "if" but I do not know how to do it.

 u8g.firstPage();
  do {
    u8g.setFont(u8g_font_helvR10);
    if (channel(data) == 1) {
    u8g.setPrintPos(0, 20);
    }
    else {
    u8g.setPrintPos(0, 40);
    }
    u8g.print(String(channel(data)) + String(temperature(data)) + String(humidity(data)));
    } while ( u8g.nextPage() );

Put your if() in loop and dump to
Value1
Value2

Then change your display to show those at the same display write.

The separate display writes is causing your grief.

On a cell phone so I can't type it out for you.

Thanks
Could you please give me an example of how to dump ?

for your oled

u8g.firstPage();
do {
u8g.setPrintPos(0, 20);
u8g.print(chOne);
u8g.print(chOneTempData);
u8g.print(chOneRHData);
u8g.setPrintPos(0, 40);
u8g.print(chTwo);
u8g.print(chTwoTempData);
u8g.print(chTwoRHData);
}
} while ( u8g.nextPage() );

but, you need to store the data into your global variables in loop()

I did not try to use just string, I used print and drawStr for data and text and printed my lines for data after writing the boxes and text.
I used 4 lines and put boxes around each line. used a heading on the screen to show what sensor I am using.

like you, I found that the oled library performs a clear screen when called so it wipes the old data in the event you tried to overlay data.

by using loop() to fill the variables, then printing them when writing everything to the whole screen at one time, it solved my problem. since mine is for a garden, I really do not care if the data is a few seconds old.

since mine is so different than yours, and I am lazy, here is how I did it.

void drawOLEDBME1() {  //++++++++++++  DRAW +++++++++++++
  Serial.println(" BME one to OLED ");
    u8g2.firstPage();
    do {
      u8g2.drawRFrame(0,15,126,16,5);  // start x, start y , width, height, radius
      u8g2.drawRFrame(0,30,126,16,5);
      u8g2.drawRFrame(0,45,126,16,5);
      u8g2.setFont(u8g2_font_ncenB10_tr); //larger
      u8g2.drawStr(5, 13, " - - BME 1 - - ");   //first line line for heading
      u8g2.drawStr(5, 28, "TempF ");
      u8g2.drawStr(5, 43, "Humid ");
      u8g2.drawStr(5, 58, "Press ");


      u8g2.setCursor(72, 28);
      u8g2.print(BME1T);    //second line for data
      u8g2.setCursor(70, 43);
      u8g2.print(RH1);    // third line for data
      u8g2.setCursor(70, 58);
      u8g2.print(Pres1);    // fourth line for data
    } while ( u8g2.nextPage() );
    delay(2000);

redfirebrooks:
Thanks
Could you please give me an example of how to dump ?

'dump' is slang for posting the variables you stored elsewhere.
fill your global variables in loop
post them in your OLED screen

Thanks a lot, I will try this soon.

I tried different solutions to fill variables but I am still stuck.
The second problem is since I add something in the loop, the reportSerial stops working.

void loop () {

float CHAN = channel(data) ;
float temperature(const byte* data) ;
byte humidity(const byte* data) ;

  static int i = 0;
  cli();
  word p = pulse;

  pulse = 0;
  sei();

  if (p != 0)
  {
    if (orscV2.nextPulse(p))
      reportSerial("OSV2", orscV2);
   };

   u8g.firstPage();
  do {
    u8g.setFont(u8g_font_helvR10);
    u8g.setPrintPos(0, 20);
    u8g.print(String(channel(data)) + String(temperature(data)) + String(humidity(data)));
    } while ( u8g.nextPage() );

   
}

I did it :slight_smile:

Using the oregon.h library I managed to send to the oled display the values of my two oregon sensors

Many thanks dave-in-nj for your help.

// Enable debug prints
#define MY_DEBUG

#include <SPI.h>
#include <EEPROM.h>
#include <Oregon.h>
#include <U8glib.h>

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_DEV_0);  // I2C / TWI

//Define pin where is 433Mhz receiver (here, pin 2)
#define MHZ_RECEIVER_PIN 3
//Define maximum Oregon sensors (here, 3 differents sensors)
#define COUNT_OREGON_SENSORS 3

void setup ()
{

  Serial.begin(115200);
  Serial.println("Setup started");

  //Setup received data
  attachInterrupt(digitalPinToInterrupt(MHZ_RECEIVER_PIN), ext_int_1, CHANGE);

  Serial.println("Setup completed");
}


void loop () {

static int Chan1 ;
static int Chan2 ;
static float Temp1 ;
static float Temp2 ;
static int Hum1 ;
static int Hum2 ;
static int Batt1 ;
static int Batt2 ;
  
  //------------------------------------------
  //Start process new data from Oregon sensors
  //------------------------------------------
  cli();
  word p = pulse;
  pulse = 0;
  sei();
  if (p != 0)
  {
    if (orscV2.nextPulse(p))
    {
      //Decode Hex Data once
      const byte* DataDecoded = DataToDecoder(orscV2);
      //Find or save Oregon sensors's ID
      int SensorID = FindSensor(id(DataDecoded), COUNT_OREGON_SENSORS);

      // just for DEBUG
      OregonType(DataDecoded);
      channel(DataDecoded);
      temperature(DataDecoded);
      humidity(DataDecoded);
      battery(DataDecoded);

      switch (channel(DataDecoded)) {

      case 1:
      Chan1 = channel(DataDecoded);
      Temp1 = temperature(DataDecoded);
      Hum1 = humidity(DataDecoded);
      break;

      case 2:
      Chan2 = channel(DataDecoded);
      Temp2 = temperature(DataDecoded);
      Hum2 = humidity(DataDecoded);
       
      }

      u8g.firstPage();
      do {

        u8g.setFont(u8g_font_helvR10);
        // u8g.setPrintPos(0, 20);
        // u8g.print("Chan Temp Hum");
        u8g.setPrintPos(0, 20);
        u8g.print("Bed  " + String(Temp1,1) + "\xb0" + " " + String(Hum1) + "%");
        u8g.setPrintPos(0, 40);
        u8g.print("Bath " + String(Temp2,1) + "\xb0" + " " + String(Hum2) + "%");

      } while (u8g.nextPage() );

    }

  }

}