OLED not wroking for me



  • I am trying to get an 128x32 OLED (I2C) working with MySensors 2.2.0

    When i include the lib (regardless if i'm trying the Adafruit lib, U8g2lib or the shorted lib from https://forum.mysensors.org/topic/2360/temperature-humidity-node-with-oled-display/5) my sensor is not working anymore. I dont need to use the lib, including is enough.

    I'm using an NRF24L01+ with an Arduino Nano and here are my includes

    #define MY_DEBUG       //Comment out in production mode
    #define MY_RADIO_NRF24 //use the NRF24L01+ module
    #include <MySensors.h>
    #include <Arduino.h>      //need to be included, cause the file is moved to a .cpp file
    #include <MotionSensor.h> //MotionSensorLib
    //Include and Set Up BatteryMeter Library
    #include <BatteryMeter.h>
    #define USE_OLED
    #ifdef USE_OLED
    // includes for OLED 128x32 and 128x64 support
    #include <SSD1306_text.h>
    //SSD1306_text oled;
    
    #endif
    
    void setup(){
    ...
    }
    

  • Mod

    @kai-bepperling could you clarify what you mean by "my sensor is not working"? Do you get a compilation error? Or strange readings? Something else?



  • Ah damn it. I was sure i posted the Log...

    At the beginning everything initializes fine like:

    16 MCO:BGN:INIT NODE,CP=RNNNA---,VER=2.2.0
    25 TSM:INIT
    26 TSF:WUR:MS=0
    33 TSM:INIT:TSP OK
    35 TSF:SID:OK,ID=4
    37 TSM:FPAR
    73 TSF:MSG:SEND,4-4-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK:
    637 TSF:MSG:READ,0-0-4,s=255,c=3,t=8,pt=1,l=1,sg=0:0
    643 TSF:MSG:FPAR OK,ID=0,D=1
    985 TSF:MSG:READ,3-3-4,s=255,c=3,t=8,pt=1,l=1,sg=0:1
    2080 TSM:FPAR:OK
    2081 TSM:ID
    2082 TSM:ID:OK
    2084 TSM:UPL
    2087 TSF:MSG:SEND,4-4-0-0,s=255,c=3,t=24,pt=1,l=1,sg=0,ft=0,st=OK:1
    2098 TSF:MSG:READ,0-0-4,s=255,c=3,t=25,pt=1,l=1,sg=0:1
    2102 TSF:MSG:PONG RECV,HP=1
    2105 TSM:UPL:OK
    2106 TSM:READY:ID=4,PAR=0,DIS=1
    2111 TSF:MSG:SEND,4-4-0-0,s=255,c=3,t=15,pt=6,l=2,sg=0,ft=0,st=OK:0100
    2118 TSF:MSG:READ,0-0-4,s=255,c=3,t=15,pt=6,l=2,sg=0:0100
    2127 TSF:MSG:SEND,4-4-0-0,s=255,c=0,t=17,pt=0,l=5,sg=0,ft=0,st=OK:2.2.0
    2136 TSF:MSG:SEND,4-4-0-0,s=255,c=3,t=6,pt=1,l=1,sg=0,ft=0,st=OK:0
    2147 TSF:MSG:READ,0-0-4,s=255,c=3,t=6,pt=0,l=1,sg=0:M
    2154 TSF:MSG:SEND,4-4-0-0,s=255,c=3,t=11,pt=0,l=5,sg=0,ft=0,st=OK:RooDe
    2162 TSF:MSG:SEND,4-4-0-0,s=255,c=3,t=12,pt=0,l=6,sg=0,ft=0,st=OK:0.9.3b
    2170 TSF:MSG:SEND,4-4-0-0,s=0,c=0,t=3,pt=0,l=0,sg=0,ft=0,st=OK:
    2179 TSF:MSG:SEND,4-4-0-0,s=1,c=0,t=36,pt=0,l=0,sg=0,ft=0,st=OK:
    2186 TSF:MSG:SEND,4-4-0-0,s=3,c=0,t=36,pt=0,l=0,sg=0,ft=0,st=OK:
    2192 MCO:REG:REQ
    2195 TSF:MSG:SEND,4-4-0-0,s=255,c=3,t=26,pt=1,l=1,sg=0,ft=0,st=OK:2
    2202 TSF:MSG:READ,0-0-4,s=255,c=3,t=27,pt=1,l=1,sg=0:1
    2206 MCO:PIM:NODE REG=1
    2209 MCO:BGN:STP
    

    Then i calibrate my IR Sensors (Analog pins 7 and 😎 which fails because:

    1
    1
    2
    11
    11
    15
    15
    43
    47
    48
    56
    72
    79
    95
    111
    125
    New threshold is: 19327
    

    i am just calculating an average... After that the sensor does not detect movement through both sensors which results in not sending anything or i just getting a TNR.

    When reading values like IRR:770
    IRC:376
    wihtout the included library the sensor will send a new state. This is a very strange behavior.


  • Mod

    @kai-bepperling how much ram is available? (This is showsn at end of compilation if you press ctrl+r)
    Would you mind posting your entire sketch?



  • I'm using PlatformIO but i think this is what you asked for:

    Program:   15728 bytes (48.0% Full)
    (.text + .data + .bootloader)
    
    Data:        854 bytes (41.7% Full)
    (.data + .bss + .noinit)
    

    roode.cpp

    /*  Room Presence Detection - Microcontroller projects@H-BRS WS16/17
                          Kai Bepperling
    
    */
    // MySensorStuff
    #define MY_DEBUG       //Comment out in production mode
    #define MY_RADIO_NRF24 //use the NRF24L01+ module
    #include <MySensors.h>
    #include <Arduino.h>      //need to be included, cause the file is moved to a .cpp file
    #include <MotionSensor.h> //MotionSensorLib
    //Include and Set Up BatteryMeter Library
    #include <BatteryMeter.h>
    /*
      Version numbers
      Please update frequently
    */
    #define ROODE_VERSION "0.9.3b"
    // #define MYSENSORS_VERSION "2.2.0"
    
    /*Feature selection
      * USE_OLED for OLED 128x32 support
      * USE_BATTERY when powering the controller with an Lithium battery
      * CALIBRATION for calibrating the IR Sensors on startup
    */
    // #define USE_OLED
    // #define USE_BATTERY
    #define CALIBRATION //enables calibration of the irsensors and motion sensor initializing
    
    // battery setup
    #ifdef USE_BATTERY
    BatteryMeter battery(3);                            //BatteryMeter instance
    #define CHILD_ID_BATTERY 2                          //MySensors Battery child ID
    #define BATTERY_FULL 4.2                            // a 18650 lithium ion battery usually give 4.2V when full
    #define BATTERY_ZERO 3.5                            // 2.4V limit for 328p at 16MHz. 1.9V, limit for nrf24l01 without
    MyMessage voltage_msg(CHILD_ID_BATTERY, V_VOLTAGE); //MySensors battery voltage message instance
    #endif
    
    /* MySensors Message types and default settings */
    unsigned long SLEEP_TIME = 0; //sleep forever
    #define CHILD_ID_R 0
    #define CHILD_ID_PC 1
    #define CHILD_ID_THR 3
    MyMessage msg(CHILD_ID_R, V_STATUS);    //room on/off child
    MyMessage pcMsg(CHILD_ID_PC, V_TEXT);   //people counter child
    MyMessage thrMsg(CHILD_ID_THR, V_TEXT); //Threshold child
    
    /* Motion Sensor setup*/
    #define DIGITAL_INPUT_SENSOR 2 // motion sensor digital pin (2 or 3 because just those pins are interrupt pins)
    MotionSensor motion(DIGITAL_INPUT_SENSOR);
    // int pirState = LOW; // we start, assuming no motion detected
    // int val = 0;        // variable for reading the pin status
    // int MotionInit = 2; // set init time in seconds. Should be set to 60s in production mode!
    
    /* IR Sensor setup*/
    #define ANALOG_IR_SENSORR 0 //IR Room Analog Pin
    #define ANALOG_IR_SENSORC 2 //IR Corridor Analog Pin
    #define IR_D_R 7            //IR Sensor Digital Pin for Room - EN Pin
    #define IR_D_C 8            //IR Sensor Digital Pin for Corridor - EN Pin
    #define LTIME 10000         // loop time (should not be lower than 8 seconds)
    #define MTIME 800           // measuring/person
    #define CALIBRATION_VAL 500 //read 500 values (250 from each sensor)
    //#define IR_BOOT 30 // Not needed for the new sensors caused by the enable pin
    
    /* OLED setup 
      For now only the OLED 128x32 monochrom displays are supported without modification
    */
    #ifdef USE_OLED
    // includes for OLED 128x32 and 128x64 support
    #include <SSD1306_text.h>
    SSD1306_text oled;
    
    #endif
    
    // some needed var declarations
    int irrVal = 0;      //analog value store for the room sensor
    int ircVal = 0;      //analog value store for the corridor sensor
    int threshold = 160; //if CALIBRATION is not defined, this threshold is used (okay for a 80cm doorway using reflection foil)
    int inout = -1;      //if inout== 0 -> out; if inout == 1 --> in; THIS STATE WILL BE SENT!
    int peopleCount = 0; //default state: nobody is inside the room
    
    // function prototypes
    // int checkMotion();
    void irSensor();
    int calibration();
    void send();
    
    void setup()
    {
      #ifdef USE_OLED
      // display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
      // display.display();
      oled.init();
      oled.clear();
      // oled.setTextSize(2);
      // oled.setCursor(0, 0);
      // oled.println("### Roode ###");
      // oled.setCursor(0,15);
      // oled.print("RooDe: ");
      // oled.print(ROODE_VERSION);
      // oled.println("MySensors: 2.2.0");
      #endif
    
      Serial.println("##### RooDe Presence Detection System #####");
    
      //Corridor Sensor Enable PIN
      pinMode(IR_D_C, OUTPUT);
    
      //Room Sensor Voltage Enable PIN
      pinMode(IR_D_R, OUTPUT);
    
      //Motion Sensor
      pinMode(DIGITAL_INPUT_SENSOR, INPUT); // declare motionsensor as input
    
    #ifdef CALIBRATION
      // Serial.println("#### initialize the motion sensor ####");
      //Sensor intialisation
      // for (int i = 0; i < MotionInit; i++) {
      //   wait(1000);
      // }
      motion.Setup(10);
      // Serial.println("#### motion sensor initialized ####");
    
      Serial.println("#### calibrate the ir sensors ####");
      threshold = calibration();
      Serial.print("New threshold is: ");
      Serial.println(threshold);
      send(thrMsg.set(threshold));
      Serial.println("#### calibration done ####");
    #endif
    
      Serial.println("#### Setting the PresenceCounter and Status to OUT (0) ####");
      send(msg.set(0));   //Setting presence status to 0
      send(pcMsg.set(0)); //Setting the people counter to 0
    }
    
    void presentation()
    {
      sendSketchInfo("RooDe", ROODE_VERSION);
      present(CHILD_ID_R, S_BINARY);
      present(CHILD_ID_PC, S_INFO);
    #ifdef USE_BATTERY
      present(CHILD_ID_BATTERY, S_CUSTOM);
    #endif
      present(CHILD_ID_THR, S_INFO);
    }
    
    void loop()
    {
    
      // Sleep until interrupt comes in on motion sensor. Send never an update
    
      if (motion.checkMotion() == LOW)
      {
        irSensor();
        digitalWrite(IR_D_R, LOW);
        wait(1);
        digitalWrite(IR_D_C, LOW);
        sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), RISING, SLEEP_TIME);
        irSensor();
        while (motion.checkMotion() != LOW)
        {
          irSensor();
        }
      }
    }
    
    // int checkMotion() {
    //   //Motion Sensor
    //   val = digitalRead(DIGITAL_INPUT_SENSOR);  // read input value
    //   if (val == HIGH) {            // check if the input is HIGH
    //
    //     if (pirState == LOW) {      // check if the pir status is LOW
    // #ifdef MY_DEBUG
    //       Serial.println("Motion detected");
    // #endif
    //       pirState = HIGH;          // set pir status to HIGH
    //     }
    //   } else {
    //     if (pirState == HIGH) {     //check if the pir status is HIGH
    // #ifdef MY_DEBUG
    //       Serial.println("No Motion");
    // #endif
    //       pirState = LOW;           // set the pir status to LOW
    //     }
    //   }
    //   return pirState;
    // }
    
    void irSensor()
    {
      int starttime = millis();
      int endtime = starttime;
    
      while ((endtime - starttime) <= LTIME) // do this loop for up to 5000mS
      {
        // turn both sensors on
        digitalWrite(IR_D_R, HIGH);
        wait(1);
        digitalWrite(IR_D_C, HIGH);
        wait(5);
        inout = -1;
    
        irrVal = analogRead(ANALOG_IR_SENSORR);
        wait(10);
        ircVal = analogRead(ANALOG_IR_SENSORC);
    
    #ifdef MY_DEBUG
        Serial.print("IRR:");
        Serial.println(irrVal);
        Serial.print("IRC:");
        Serial.println(ircVal);
    #endif
        if (irrVal > threshold && ircVal < threshold && inout != 1)
        {
          int startR = millis();
          int endR = startR;
          while ((endR - startR) <= MTIME)
          {
            irrVal = analogRead(ANALOG_IR_SENSORR);
            wait(10);
            ircVal = analogRead(ANALOG_IR_SENSORC);
            if (ircVal > threshold && irrVal > threshold)
            {
    #ifdef MY_DEBUG
              Serial.print("In Loop IRR: ");
              Serial.println(irrVal);
              Serial.print("In Loop IRC: ");
              Serial.println(ircVal);
              Serial.print("Delay Time: ");
              Serial.println(MTIME - (endR - startR));
    #endif
              while (irrVal > threshold || ircVal > threshold)
              {
                irrVal = analogRead(ANALOG_IR_SENSORR);
                wait(10);
                ircVal = analogRead(ANALOG_IR_SENSORC);
                if (ircVal > threshold && irrVal < threshold)
                {
                  // turn both sensors off
                  digitalWrite(IR_D_R, LOW);
                  wait(1);
                  digitalWrite(IR_D_C, LOW);
                  inout = 0;
                  send();
                  break;
                }
                wait(11);
              }
    
              if (inout == 0)
              {
                wait(150);
                ircVal = 0;
                endR = millis();
                starttime = millis();
                endtime = starttime;
                break;
              }
            }
            else
            {
              wait(1);
              endR = millis();
            }
          }
        }
        else
        {
          endtime = millis();
        }
    
        if (ircVal > threshold && irrVal < threshold && inout != 0)
        {
          int startC = millis();
          int endC = startC;
          while ((endC - startC) <= MTIME)
          {
            ircVal = analogRead(ANALOG_IR_SENSORC);
            wait(10);
            irrVal = analogRead(ANALOG_IR_SENSORR);
            if (irrVal > threshold && ircVal > threshold)
            {
    #ifdef MY_DEBUG
              Serial.print("In Loop IRC: ");
              Serial.println(ircVal);
              Serial.print("In Loop IRR: ");
              Serial.println(irrVal);
              Serial.print("Delay Time: ");
              Serial.println(MTIME - (endC - startC));
    #endif
              while (irrVal > threshold || ircVal > threshold)
              {
                irrVal = analogRead(ANALOG_IR_SENSORR);
                wait(10);
                ircVal = analogRead(ANALOG_IR_SENSORC);
                if (irrVal > threshold && ircVal < threshold)
                {
                  // turn both sensors off
                  digitalWrite(IR_D_R, LOW);
                  wait(1);
                  digitalWrite(IR_D_C, LOW);
                  inout = 1;
                  send();
                  break;
                }
                wait(11);
              }
    
              if (inout == 1)
              {
                wait(150);
                irrVal = 0;
                endC = millis();
                starttime = millis();
                endtime = starttime;
                break;
              }
            }
            else
            {
              wait(11);
              endC = millis();
            }
          }
        }
        else
        {
          endtime = millis();
        }
        wait(11);
      }
    }
    
    void send()
    {
      if (inout == 1)
      {
        peopleCount++;
        send(msg.set(inout));
        wait(30);
        send(pcMsg.set(peopleCount));
      }
      else if (inout == 0)
      {
        if (peopleCount > 0)
        {
          peopleCount--;
        }
        if (peopleCount == 0)
        {
          send(msg.set(inout));
        }
        wait(30);
        send(pcMsg.set(peopleCount));
      }
    
    #ifdef USE_BATTERY
      float voltage = battery.checkBatteryLevel();
      send(voltage_msg.set(voltage, 3)); // redVcc returns millivolts. Set wants volts and how many decimals (3 in our case)
      sendBatteryLevel(round((voltage - BATTERY_ZERO) * 100.0 / (BATTERY_FULL - BATTERY_ZERO)));
    #endif
    }
    
    int calibration()
    {
    
      digitalWrite(IR_D_C, HIGH);
      digitalWrite(IR_D_R, HIGH);
      delay(100);
      int distances[CALIBRATION_VAL];
      int max = 0;
      for (int m = 0; m < CALIBRATION_VAL; m = m + 2)
      {
        delay(8);
        irrVal = analogRead(ANALOG_IR_SENSORR);
        delay(8);
        ircVal = analogRead(ANALOG_IR_SENSORC);
    
        //calculate the max without jumps for the room sensor
        if ((irrVal >= max && (irrVal - max) < 30) || irrVal - max == irrVal)
        {
          Serial.println(irrVal);
          max = irrVal;
          distances[m] = irrVal;
        }
        else
        {
          distances[m] = 0;
        }
    
        //calculate the max without jumps for the corridor sensor
        if (((ircVal >= max) && ((ircVal - max) < 30)) || ((ircVal - max) == ircVal))
        {
          Serial.println(ircVal);
          max = ircVal;
          distances[m + 1] = ircVal;
        }
        else
        {
          distances[m + 1] = 0;
        }
      }
    
      // shutdown both sensors
      digitalWrite(IR_D_C, LOW);
      digitalWrite(IR_D_R, LOW);
      max = 0;
      //calculate the absolute max value to determine the new threshold
      for (int i = 0; i < CALIBRATION_VAL; i++)
      {
        if (distances[i] >= max)
        {
          max = distances[i];
        }
      }
      return max + 30; //add 30 to be super safe
    }
    
    /*
      - Not sure if this function ever will be used... But good idea to have this as backup
      - Tests will be show more about RAM problems
    */
    int freeRam()
    {
      extern int __heap_start, *__brkval;
      int v;
      return (int)&v - (__brkval == 0 ? (int)&__heap_start : (int)__brkval);
    }
    
    

  • Mod

    @kai-bepperling I am not familiar with platformio, but it looks like ram should be fine.
    EDIT: you're allocating an array that is 1kB in size (500 integers). That brings the memory usage pretty close to maximum.

    One thing that seems strange to me is "overriding" send, and calling send from within send. To me, that should lead to endless recursion but you're not using send during calibration so I don't know what could be wrong.



  • If send had the same signature as the mysensors send it will be endless but it dont. Maybe i should rename my own send function.
    Should i clear the array by hand after the calibration? I thought this is not needed..

    Edit: thanks for the hint with the array. If i init the array with 250 ints the display is working for now.

    What is the best way to "clear/remove" an array?


  • Mod

    @kai-bepperling thanks for clarifying on the send function.

    From what I can see, you don't need the array at all. Just check if the new value is larger than the max value directly.



  • Nothing more to say. Sometimes it can be that simple 😅


 

308
Online

8.0k
Users

8.8k
Topics

94.3k
Posts