Z-Uno "running slow" when OLED in use

Discussion about Z-Uno product. Visit http://z-uno.z-wave.me for more details.
Post Reply
andycee
Posts: 2
Joined: 15 Jul 2019 00:21

Z-Uno "running slow" when OLED in use

Post by andycee » 02 Oct 2019 00:41

I have a large project performing several tasks.

Hooked up is an ADA938 OLED display running over I2C as per this example
https://z-uno.z-wave.me/examples/bmp180-oled/

I have edited the address in ZUNO_OLED_I2C.cpp to 0x3D as per this post
https://forum.z-wave.me/viewtopic.php?f ... 23f#p72024

My project works, the display works but its clearly grinding somewhere. Board green LED flashes visibly slower than usual. Code runs for a few hours then Z-Uno hangs. I display a time from start (actually a daily timer) on the OLED, read straight from millis(), and it runs a LOT slower than real time. 10 seconds of time displayed on the OLED takes approx. 16 seconds real world.

I stripped back my code to isolate the cause, and its clearly the OLED part. This simple example is whats left, and makes the board "run slow".

Would really appreciate some advice.

Code: Select all

#include "ZUNO_OLED_I2C.h"
OLED oled;

// Pin definitions
#define PIN_OLEDClk 9
#define PIN_OLEDData 10
#define PIN_OLEDReset 11

#define PIN_LED_SOLENOID 13

unsigned long LastBaseUpdateMS = 0;
unsigned long LastDailyUpdateMS = 0;
float WaterTemp = 21.1;
int WaterLevelPct = 50;
float WaterLevelL = 500;
#define WaterLowLevelOn 200
#define WaterLowLevelOff 250
float DailyWaterInRain = 0;
float DailyWaterInFresh = 0;
float DailyWaterOut = 0;
float Meter1TOTAL = 0;
float Meter2TOTAL = 0;

void setup() {
  LastDailyUpdateMS = millis();
  
  pinMode(PIN_LED_SOLENOID, OUTPUT);
  
  // Initialise display
  pinMode(PIN_OLEDReset, OUTPUT);
  digitalWrite(PIN_OLEDReset, HIGH);
  delay(1);
  digitalWrite(PIN_OLEDReset, LOW);
  delay(10);
  digitalWrite(PIN_OLEDReset, HIGH);
  oled.begin();
  oled.clrscr();
}

void loop() {
  LastBaseUpdateMS = millis();
  
  // Calc daily timer
  unsigned long ElapsedMS = millis() - LastDailyUpdateMS;
  int ElapsedHours = ElapsedMS / 3600000;
  int ElapsedMins = (ElapsedMS % 3600000) / 60000;
  int ElapsedSecs = ((ElapsedMS % 3600000) % 60000) / 1000;
  oled.gotoXY(0, 0);
  if (ElapsedHours < 10) {oled.print("0");}
  oled.print(ElapsedHours);
  oled.print(":");
  if (ElapsedMins < 10) {oled.print("0");}
  oled.print(ElapsedMins);
  oled.print(":");
  if (ElapsedSecs < 10) {oled.print("0");}
  oled.print(ElapsedSecs);
  oled.print(" (");
  oled.print(WaterTemp, 1);
  oled.println("C)  ");
  oled.gotoXY(0, 1);
  oled.print("Water:");
  oled.print(WaterLevelL, 1);
  oled.print("L (");
  oled.print(WaterLevelPct);
  oled.println("%)    ");
  oled.gotoXY(0, 2);
  oled.print("Fill On/Off=");
  oled.print(int(WaterLowLevelOn));
  oled.print("/");
  oled.print(int(WaterLowLevelOff));
  oled.println("L");

  oled.gotoXY(0, 3);
  oled.print("Daily OUT=");
  oled.print(DailyWaterOut);
  oled.println("L");
  oled.gotoXY(0, 4);
  oled.print("Daily INfresh=");
  oled.print(DailyWaterInFresh);
  oled.println("L");
  oled.gotoXY(0, 5);
  oled.print("Daily INrain=");
  oled.print(DailyWaterInRain);
  oled.println("L");
  oled.gotoXY(0, 6);
  oled.print("M1-OUT=");
  oled.print(Meter1TOTAL);
  oled.println("L");
  oled.gotoXY(0, 7);
  oled.print("M2-INfresh=");
  oled.print(Meter2TOTAL);
  oled.println("L");

  while(millis() < LastBaseUpdateMS + 1000)
  {
    //  Wait!
  }

}

andycee
Posts: 2
Joined: 15 Jul 2019 00:21

Re: Z-Uno "running slow" when OLED in use

Post by andycee » 12 Oct 2019 23:32

Well since nobody seems to have a clue about this fundamental timing problem with the Z-Uno and OLEDs, which is provided as a "working" example...

This thread sounded like a lead, but changing all my OLED writes as INTs instead of floats made no difference.
https://forum.z-wave.me/viewtopic.php?t=25514&start=10

Further testing shows the slowness and stability is directly proportional to the amount of data being written to the OLED. In my sketch I'm updating all 7 lines of text (titles and data) every cycle, which is not neccesary.

As a workaround, I've changed to only updating each line when the value has changed from the previous cycle. As I'm still using floats I also need to check if the actual display reading (which is trimmed to a varying number of decimal points) has changed. I don't want to trigger an update if the actual display text has not changed, but the underlying float value has.

Code: Select all

...
if (CompareDispData(DailyWaterInFresh, DailyWaterInFreshPV, 10) == false)
  {
    DailyWaterInFreshPV = DailyWaterInFresh;
    oled.gotoXY(0, 4);
    oled.print("Daily INfresh=");
    oled.print(DailyWaterInFreshPV, 1);
    oled.println("L");
  }

  if (CompareDispData(DailyWaterInRain, DailyWaterInRainPV, 10) == false)
  {
    DailyWaterInRainPV = DailyWaterInRain;
    oled.gotoXY(0, 5);
    oled.print("Daily INrain=");
    oled.print(DailyWaterInRainPV, 1);
    oled.println("L");
  }
  
  ...
  
// Compare two floats to x decimal places to decide if we update OLED
// mul = 10 : 1 dec place
// mul = 100 : 2 dec place
// ...
bool CompareDispData(float v1, float v2, int mul)
{
  bool res;
  res = (int(v1 * mul) == int(v2 * mul));
  return res;
}
  

Post Reply