OLED Resource Issue?

Hello,

Full code at the bottom of the post, tried using Nano, Uno & Mega 2560.

Quick summary if you don't want to read the whole post,

I think I'm running out of resources is are the Adafruit_GFX.h & Adafruit_SSD1306.h libraries used to drive OLED displays know to be resources hungry and if so is there a way to reduce the resource requirement?

I'm creating a car display (RPM, boost, change lights, etc) that will also control a water-methanol injection system. I'm using 2 displays 0.91 inch 128 x 65 OLED with the Adafruit_GFX.h & Adafruit_SSD1306.h libraries to display the information.

Point to note for testing I'm using a potentiometer to generate the RPM and speed for the production device I'll be using the CANBUS. The IAT & Boost are not on the CANBUS (it's a 2002 Audi TT) so a separate IAT Boost sensor is used for these readings.

I'm having issues with it not working correctly when using all the required elements together, using the elements individually works fine.

I think I know what the issues is but would like someone to confirm my thinking.

Firstly when using the OLED screens and the CANBUS (mcp_can.h & SPI.h libraries) I was getting erratic results, I was able to resolve this by putting an interval timer on the display update (1/3 second).

To cut down on the wiring I've moved from LED's with a shift register for the change lights to a strip of WS2812B LED's (FastLED.h library), now using the WS2812B I'm experiencing the following,

  • The LED's on the WS2812B strip are not lighting up smoothly (when commenting out the OLED coding the lights light up very smoothly)
  • There is a glitch in the bottom right of display (OLED) 2.

I was able to get rid of the screen glitch by going from Uno to Mega but the jumpy light running is still there. At the moment I'm still using the the potentiometer for the RPM & Speed, but I suspect when I change to the CANBUS the problems will get bigger, I'm also still using the 1/3 second display update timer.

I think I'm running out of resources can someone tell me if I should be able to use the following libraries all at the same time,

OLED x 2 displays
Adafruit_GFX.h & Adafruit_SSD1306.h

CANBUS
mcp_can.h & SPI.h

WS2812B
FastLED.h

If I should be able to run all these libraries all at the same time can someone give me some pointers in rationalising my code to enable the code to run smoothly.

At the moment the only way I can think of to get the is working is to move the OLED screen control to a separate Arduino and using a serial connection from the Arduino that gathers & processes the data to deliver the the required display metrics.

Any advice most appreciated

Thanks

PS
Don't be to hard on my coding it's a hobby not my profession.


//OLED
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display1(OLED_RESET);
Adafruit_SSD1306 display2(OLED_RESET);

char message[] = "297M LstWyPt, 345M StPt, rec#89";
char printBuffer[128];
int x, minX;

//Display update inetrval
const unsigned long eventInterval = 333;
unsigned long previousTimeDisplay = 0;


// Boost Pressure and IAT
// int offset = 125; // low pressure calibration
// int span = 895; // high pressure calibration
int offset = 111; // low pressure calibration
int span = 912; // high pressure calibration
float Boost_pressure_Pa;
float Boost_pressure_kPa;
float Boost_pressure_PSI;
int boost_pressure_pin = A3;
int Max_PSI = 0;

int IAT_voltage = 0;
float IAT_Vin = 4.6; // 4.6 volts - USB powered
float IAT_Vout = 0;
float R1 = 2000; // Temperature resistor value
float IAT_buffer = 0;
float logR2;
float R2;
float IAT;
int IAT_pin = A1;
float IAT_C = 0;
float Max_IAT = 0;

// float A = 1.297373711e-03, B = 2.587931666e-04, C = 1.639343214e-07;  // Steinhart-Hart and Hart Coefficients Max
// float A = 1.306496435e-03, B = 2.580557547e-04, C = 1.752303942e-07;  // Steinhart-Hart and Hart Coefficients Nominal
float A = 1.316012871e-03, B = 2.572431200e-04, C = 1.877359037e-07;  // Steinhart-Hart and Hart Coefficients Min

#include <FastLED.h>
#define NUM_LEDS 20
#define DATA_PIN 2 //How boring and obvious!
#define COLOR_ORDER GRB //Green (G), Red (R), Blue (B)
#define CHIPSET WS2812B
#define BRIGHTNESS 25
#define VOLTS 5
#define MAX_AMPS 500 //value in milliamps
#define LED_COLOR CRGB::DarkOrchid
//ENOUGH NONSENSE!

CRGB leds[NUM_LEDS];


float Voltage = 1.00;

//RPM
int RPM = 1;
int Max_RPM = 0;
int RPM_NUM_LEDS = 0;

////Change lights
//int numLEDSLit = 1;
//int latchPin = 11;      // (11) ST_CP [RCK] on 74HC595
//int clockPin = 9;      // (9) SH_CP [SCK] on 74HC595
//int dataPin = 12;     // (12) DS [S1] on 74HC595
//int leds = 0;

//Speed
int Speed = 0;
int Max_Speed = 0;

//W-M
int Max_WM = 0;
int WM_value_percent = 1;
int WM_pin = 6;
int WM_value_T;
int WM_value_P;
int WM_value;
//int WM_Level_pin = A2;
int WM_Level = 101;

//History
int HistoryValue = 0;
int Max_Counter = 1;
int Max_Scroll = 4;
int Max_Reset = 7;



void setup() {
  Serial.begin(115200);
  display1.begin(SSD1306_SWITCHCAPVCC, 0x3D);
  display1.setTextSize(2);
  display1.setTextColor(WHITE);
  display1.setTextWrap(false);
  x = display1.width();
  minX = -12 * strlen(message);  // 12 = 6 pixels/character * text size 2
  display2.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display2.setTextSize(2);
  display2.setTextColor(WHITE);
  display2.setTextWrap(false);
  x = display2.width();
  minX = -12 * strlen(message);  // 12 = 6 pixels/character * text size 2
  pinMode(WM_pin, OUTPUT);

  //  pinMode(latchPin, OUTPUT);
  //  pinMode(dataPin, OUTPUT);
  //  pinMode(clockPin, OUTPUT);

  pinMode(Max_Reset, INPUT_PULLUP);
  pinMode(Max_Scroll, INPUT_PULLUP);

  FastLED.addLeds<CHIPSET, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  FastLED.setMaxPowerInVoltsAndMilliamps(VOLTS, MAX_AMPS);
  FastLED.setBrightness(BRIGHTNESS);
  FastLED.clear();
  FastLED.show();
}

void drawProgressbar(int x, int y, int width, int height, int progress)
{

  progress = progress > 100 ? 100 : progress;
  progress = progress < 0 ? 0 : progress;

  float bar = ((float)(width - 1) / 100) * progress;

  display2.drawRect(x, y, width, height, WHITE);
  display2.fillRect(x + 2, y + 2, bar , height - 4, WHITE);

  //     if( progress <50){
  //    display2.setCursor(64,0);
  //    display2.setTextSize(1);
  //    display2.setTextColor(WHITE);
  //    display2.print(RPM);
  //    display2.print("RPM");
  //     }
  // else{
  //      display2.setCursor(64,0);
  //     display2.setTextColor(BLACK, WHITE); // 'inverted' text
  //
  //     display2.print(RPM);
  //     display2.print("RPM");
  // }

  // Scroll in various directions, pausing in-between:
  //  display1.startscrollright(0x00, 0x0F);
  //  delay(2000);
  //  display1.stopscroll();
  //  delay(1000);
  //  display1.startscrollleft(0x00, 0x0F);
  //  delay(10500);
  //  display.stopscroll();
  //  delay(1000);
  //  display.startscrolldiagright(0x00, 0x07);
  //  delay(2000);
  //  display.startscrolldiagleft(0x00, 0x07);
  //  delay(2000);
  //  display.stopscroll();
  //  delay(1000);


  //     int RPM_NUM_LEDS = RPM / 365;
  //  // 3) Light up the LEDs
  //  // Only LEDs are switched on which correspond to the area left of the slide knob
  //  for (int i = 0; i < RPM_NUM_LEDS; ++i) {
  //    leds[i] = CRGB(0,255 - 4*i,4*i);
  //  }
  //  // LEDs are switched off which correspond to the area right of the slide knob
  //  for (int i = RPM_NUM_LEDS; i < NUM_LEDS; ++i) {
  //    leds[i] = CRGB::Black;
  //  }
  //
  //  FastLED.show();
  // Shift lights not sure how it works
  //  int numLEDSLit = RPM / 937;  //1023 / 9 / 2
  //  if (numLEDSLit >= 6) numLEDSLit = 8;
  //  if (numLEDSLit < 1) numLEDSLit = 1;
  //  leds = 0;   // no LEDs lit to start
  //  for (int i = 0; i < numLEDSLit; i++)
  //  {
  //    leds = leds + (1 << i);  // sets the i'th bit
  //  }
  //  updateShiftRegister();
  //Serial.println(Max_Counter);
  //Serial.println(MaxIAT);
  //Serial.println(IAT_C);
}
//void updateShiftRegister()
//{
//   digitalWrite(latchPin, LOW);
//   shiftOut(dataPin, clockPin, MSBFIRST, leds);
//   digitalWrite(latchPin, HIGH);
//}


void loop() {


  if (digitalRead(Max_Scroll) == LOW) {
    delay (150);

    if (digitalRead(Max_Scroll) == LOW) {
      Max_Counter = Max_Counter + 1;
    }
  }

  if (Max_Counter > 5) Max_Counter = 1;

  if (digitalRead(Max_Reset) == LOW)
  {
    Max_Speed = 0;
    Max_RPM = 0;
    Max_IAT = 0;
    Max_WM = 0;
    Max_PSI = 0;
  }
  // WM level code
  //  int WM_Level = analogRead(WM_Level_pin); // get adc value
  //
  //  if (((HistoryValue >= WM_Level) && ((HistoryValue - WM_Level) > 10)) || ((HistoryValue < WM_Level) && ((WM_Level - HistoryValue) > 10)))
  //  {
  //    //sprintf(printBuffer, "ADC%d level is %d\n", WM_Level_pin, WM_Level);
  //    //Serial.print(printBuffer);
  //    HistoryValue = WM_Level;
  //  }

  int sensorValue = analogRead(A0);
  Voltage = map(sensorValue, 0, 1023, 0, 500);

  // Boost Pressure
  Serial.println("  ");
  Boost_pressure_Pa = map(analogRead(boost_pressure_pin), offset, span, 500, 4000);
  Boost_pressure_kPa = Boost_pressure_Pa / 10, 1;
  Serial.print("Pressure: ");
  Serial.print(Boost_pressure_kPa);
  Serial.println(" kPa");

  Serial.println("  ");
  if (Boost_pressure_kPa < 20) Boost_pressure_kPa = 20;
  Boost_pressure_PSI = Boost_pressure_kPa * 0.145038;
  Boost_pressure_PSI = Boost_pressure_PSI - 14;
  if (Boost_pressure_PSI < 1) Boost_pressure_PSI = 0;
  if (Boost_pressure_PSI > Max_PSI) Max_PSI = Boost_pressure_PSI;

  // RPM
  Voltage = Voltage / 100;
  RPM = map(sensorValue, 0, 1023, 0, 7500);
  if (RPM > Max_RPM) Max_RPM = RPM;

  // Speed
  Speed = map(sensorValue, 0, 1023, 0, 150);
  if (Speed > Max_Speed) Max_Speed = Speed;


  //WM_Controller
  if (WM_value_percent > Max_WM) Max_WM = WM_value_percent;

  //IAT

  IAT_voltage = analogRead(IAT_pin);
  if (IAT_voltage) {
    IAT_buffer = IAT_voltage * IAT_Vin;
    IAT_Vout = (IAT_buffer) / 1024.0;
    IAT_buffer = (IAT_Vin / IAT_Vout) - 1;
    R2 = R1 / IAT_buffer;
    Serial.print("IAT_Vout: ");
    Serial.println(IAT_Vout);
    Serial.print("IAT_Vin: ");
    Serial.println(IAT_Vin);
    Serial.print("R2: ");
    Serial.println(R2);
  }

  logR2 = log(R2);
  IAT = (1.0 / (A + B * logR2 + C * logR2 * logR2 * logR2)); // Steinhart and Hart Equation. T  = 1 / {A + B[ln(R)] + C[ln(R)]^3}
  IAT_C =  IAT - 273.15;

  //  Serial.print("IAT = ");
  //  Serial.print(IAT_C);
  //  Serial.print(" C ");
  //  Serial.println("  ");


  // need to edit for sensor pressure
  if (IAT_C >= 27) {
    WM_value_T = map (IAT_C, 27, 40, 0, 255);
    WM_value_P = map(Boost_pressure_PSI, 8, 25, 0, 255);
    if (WM_value_T >= WM_value_P) WM_value = WM_value_T;
    if (WM_value_P >= WM_value_T) WM_value = WM_value_P;
    if (WM_value <= 0) WM_value = 0;
    WM_value_percent = WM_value / 2.5;
    if (Boost_pressure_PSI >= 31) WM_value_percent = 100;
    if (WM_value_percent >= 100) WM_value_percent = 100;
    WM_value = WM_value_percent * 2.55;
    analogWrite(WM_pin, WM_value);
  }
  else
  {
    WM_value_P = map(Boost_pressure_PSI, 8, 25, 0, 255);
    WM_value_T = map (IAT_C, 28, 40, 0, 255);
    if (WM_value_P >= WM_value_T) WM_value = WM_value_P;
    if (WM_value_T >= WM_value_P) WM_value = WM_value_T;
    if (WM_value <= 0) WM_value = 0;
    WM_value_percent = WM_value / 2.5;
    if (Boost_pressure_PSI >= 25) WM_value_percent = 100;
    if (WM_value_percent >= 100) WM_value_percent = 100;
    WM_value = WM_value_percent * 2.55;
    analogWrite(WM_pin, WM_value);
  }
  //  unsigned long currentTimeDisplay = millis();
  //  if (currentTimeDisplay - previousTimeDisplay >= eventInterval) {
  display1.clearDisplay();
  display1.setTextSize(1); // Draw 2X-scale text
  display1.setTextColor(SSD1306_WHITE);
  display1.setCursor(0, 0);
  // sensor voltage code
  //display1.println(F("SV"));
  display1.println(F("IAT"));
  display1.setCursor(28, 0);
  // sensor voltage code
  //display1.println(Voltage);
  display1.println(IAT_C);

  display1.setCursor(75, 0);
  display1.print(F("PSI"));
  display1.setCursor(99, 0);
  display1.println(Boost_pressure_PSI);
  display1.setCursor(112, 0);
  display1.setTextSize(3); // Draw 2X-scale text
  display1.setTextColor(SSD1306_WHITE);
  // WM level low code
  //  if (WM_Level <= 460) {
  //    display1.setTextSize(2); // Draw 2X-scale text
  //    display1.setCursor(0, 17);
  //    display1.println(F("W-M"));
  //    display1.setTextSize(3); // Draw 2X-scale text
  //    display1.setCursor(41, 10);
  //    display1.println(F("EMPTY"));
  //  }
  //  else {
  //    display1.setTextSize(2); // Draw 2X-scale text
  //    display1.setCursor(0, 17);
  //    //display1.print(F("PSI"));
  //    display1.println(F("W-M"));
  //    display1.setTextSize(3); // Draw 2X-scale text
  //    display1.setCursor(50, 10);
  //    //display1.println(Boost_pressure_PSI);
  //    display1.println(WM_value_percent);
  //    display1.setCursor(113, 10);
  //    display1.println(F("%"));
  //  }
  display1.setTextSize(2); // Draw 2X-scale text
  display1.setCursor(0, 17);
  //display1.print(F("PSI"));
  display1.println(F("W-M"));
  display1.setTextSize(3); // Draw 2X-scale text
  display1.setCursor(50, 10);
  //display1.println(Boost_pressure_PSI);
  display1.println(WM_value_percent);
  display1.setCursor(113, 10);
  display1.println(F("%"));

  display2.clearDisplay();
  // Here as it reads 0 when with the rest of the max readings??
  if (IAT_C > Max_IAT) Max_IAT = IAT_C;

  if (Max_Counter == 1) {
    display2.clearDisplay();
    display2.setTextSize(3); // Draw 2X-scale text
    display2.setTextColor(SSD1306_WHITE);
    display2.setCursor(50, 11);
    display2.println(Max_Speed);
    display2.setTextSize(1); // Draw 2X-scale text
    display2.setCursor(15, 12);
    display2.println(F("MAX"));
    display2.setCursor(15, 25);
    display2.println(F("MPH"));
  }
  if  (Max_Counter == 2) {
    display2.clearDisplay();
    display2.setTextSize(3); // Draw 2X-scale text
    display2.setTextColor(SSD1306_WHITE);
    display2.setCursor(50, 11);
    display2.println(Max_RPM);
    display2.setTextSize(1); // Draw 2X-scale text
    display2.setCursor(15, 12);
    display2.println(F("MAX"));
    display2.setCursor(15, 25);
    display2.println(F("RPM"));
  }
  if (Max_Counter == 3) {
    display2.clearDisplay();
    display2.setTextSize(3); // Draw 2X-scale text
    display2.setTextColor(SSD1306_WHITE);
    display2.setCursor(40, 11);
    display2.println(Max_IAT);
    display2.setTextSize(1); // Draw 2X-scale text
    display2.setCursor(15, 12);
    display2.println(F("MAX"));
    display2.setCursor(15, 25);
    display2.println(F("IAT"));
  }
  if (Max_Counter == 4) {
    display2.clearDisplay();
    display2.setTextSize(3); // Draw 2X-scale text
    display2.setTextColor(SSD1306_WHITE);
    display2.setCursor(50, 11);
    display2.println(Max_PSI);
    display2.setTextSize(1); // Draw 2X-scale text
    display2.setCursor(15, 12);
    display2.println(F("MAX"));
    display2.setCursor(15, 25);
    display2.println(F("PSI"));
  }
  if (Max_Counter == 5) {
    display2.clearDisplay();
    display2.setTextSize(3); // Draw 2X-scale text
    display2.setTextColor(SSD1306_WHITE);
    display2.setCursor(50, 11);
    display2.println(Max_WM);
    display2.setTextSize(1); // Draw 2X-scale text
    display2.setCursor(15, 12);
    display2.println(F("MAX"));
    display2.setCursor(15, 25);
    display2.println(F("W-M"));
  }


  if (Max_Counter == 1) {
    drawProgressbar(0, 0, 108, 10, Speed / 1.5  );
    display2.setCursor(110, 2);
    display2.setTextSize(1);
    display2.setTextColor(WHITE);
    display2.print("MPH");
  }
  if (Max_Counter == 2) {
    drawProgressbar(0, 0, 108, 10, RPM / 75  );
    display2.setCursor(110, 2);
    display2.setTextSize(1);
    display2.setTextColor(WHITE);
    display2.print("RPM");
  }
  if (Max_Counter == 3) {
    drawProgressbar(0, 0, 108, 10, IAT_C / 0.5  );
    display2.setCursor(110, 2);
    display2.setTextSize(1);
    display2.setTextColor(WHITE);
    display2.print("IAT");
  }
  if (Max_Counter == 4) {
    drawProgressbar(0, 0, 108, 10, Boost_pressure_PSI / 0.32  );
    display2.setCursor(110, 2);
    display2.setTextSize(1);
    display2.setTextColor(WHITE);
    display2.print("PSI");
  }
  if (Max_Counter == 5) {
    drawProgressbar(0, 0, 108, 10, WM_value_percent);
    display2.setCursor(110, 2);
    display2.setTextSize(1);
    display2.setTextColor(WHITE);
    display2.print("W-M");
  }


  display2.display();      // Show initial text
  display1.display();      // Show initial text
  //delay(100);




  //      previousTimeDisplay = currentTimeDisplay;
  //  }
  int RPM_NUM_LEDS = RPM / 365;
  // 3) Light up the LEDs
  // Only LEDs are switched on which correspond to the area left of the slide knob
  for (int i = 0; i < RPM_NUM_LEDS; ++i) {
    leds[i] = CRGB(0, 255 - 4 * i, 4 * i);
  }
  // LEDs are switched off which correspond to the area right of the slide knob
  for (int i = RPM_NUM_LEDS; i < NUM_LEDS; ++i) {
    leds[i] = CRGB::Black;
  }

  FastLED.show();
}

:laughing:

From my test compile:

"C:\\Users\\burne\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-size" -A "C:\\Users\\burne\\AppData\\Local\\Temp\\arduino_build_610717/sketch_sep11a.ino.elf"
Sketch uses 25346 bytes (9%) of program storage space. Maximum is 253952 bytes.
Global variables use 861 bytes (10%) of dynamic memory, leaving 7331 bytes for local variables. Maximum is 8192 bytes.

Appears you have ample resources: both SRAM and flash.

Another resource not often talked about is CPU cycles... you are running your Mega at 16 million operations per second.

What you are witnessing is bandwidth starvation; akin to (attempting) increasing the engine RPM and not providing an increase in fuel.

There are obvious opportunities for rewriting, but what I think you need to do is profile your library calls: that is set a unsigned long variable to micro() before a Oled section or fastled section of code and then subtract at the section end ... print to serial console.

Profile your code, section by section, the goal is to understand the time that your library calls take. The fix is a more efficient library, less library function use of slow functions, or a faster clocked uC.

Ray

Added: Mega2560 code for Rotax engine monitor.
The loop() section takes 700mS @ 16MHz


#include <HardwareSerial.h>         // System library
#include <AXE133Y.h>                // System library

// Note: Arduino IDE automatically performs a Forward Declaration for functions listed before setup()
#include "./AnalogAverage.h"        // Matrix summations
#include "./BATTERY.h"              // Voltage and Current
#include "./EGT.h"                  // Exhaust Gas temps left and right
#include "./ENGINE.h"               // Coolent temp, Front cyl temp, Rear cyl temp, oil temp, oil pressure
#include "./FUEL.h"                 // Fuel tank level

// Type Variable Declarations for the main sketch tab
int   errLED      =  2;             // Error LED for blinking OLED
int   OLED_Tx     =  3;             // Serial out for OLED_1 (Upper display)
int   OLED_Tx2    =  5;             // Serial out for OLED_2 (Lower display)
float temp        =  0.00;
float vLow, vHigh ;                 // High & Low (non-inclusive values) for nominal operation. Values outside this will return an error==true
int   err_count   = 0;

// Below commented code is in AnalogAverage.h tab, shown here to complete global variable view
// The 2-dimensional array is used to create a rolling average across the previous 5 (Average_Depth) readings
// C++ will automatically initialize this array to zero by default
// int AnalogAverageMatrix [9][Average_Depth];  // 9 is based on A0, A1, A2, A3, A4, A10, A12, A13, A15


// Instantiate the OLED display objects
AXE133Y oLED1 = AXE133Y(OLED_Tx);
AXE133Y oLED2 = AXE133Y(OLED_Tx2);

// Arduino-specific configuration code initialization section
void setup() {
  // analogReference(EXTERNAL) ;    // A precision 5.00 Volt source OR other precision source
  analogReference(DEFAULT) ;        // This is the Vcc +5-ish USB power rail. Leave the ARef pin open (not connected!)
  pinMode(errLED, OUTPUT);          // for error LED
  digitalWrite(errLED, HIGH);       // Turn error LED off (LED resistor goes to +5, so active LOW)

  Serial.begin(9600);               // Hardware serial port to PC terminal via USB (echo/diagnostic)
  Serial.println() ;

  // set-up the two OLED screens: #1 has no legends, #2 has V/A legend
  oLED1.clearScreen();
  oLED1.splash("Coming online...");
  oLED1.clearScreen(); oLED2.clearScreen();
  delay(100);                 
  oLED2.cursorPosition(1, 1); oLED2.print("Volts    Amps");
}


void loop() {
  err_count = 0;                    // clear global error (buzzer, warning light, etc.)
  digitalWrite(errLED, HIGH);       // turn off LED

  /* NOTE: passing 0 and 0 will DISABLE the compare logic in function, no error will occur based on ranges. */
  /* VALUES: https://www.experimentalaircraft.info/homebuilt-aircraft/rotax-aircraft-engines-3.php */
  vLow = 00.0; vHigh = 00.0;  if (oDISP1_1_0(vLow, vHigh)) ++err_count;         /* A13 Gasoline fuel remaining */

  vLow = 00.0; vHigh = 00.0;  if (oDISP1_1_4(vLow, vHigh)) ++err_count;         /* A1  Oil temperature */

  vLow = 00.0; vHigh = 00.0;  if (oDISP1_1_8(vLow, vHigh)) ++err_count;         /* A3  CylHead Front */

  vLow = 00.0; vHigh = 00.0;  if (oDISP1_1_12(vLow, vHigh)) ++err_count;        /*     Exhaust Gas left */

  /* Though not displayed, we can send it over the serial port                       A0 Water temperature */
  Serial.print("\"H2O_Tmp\":");    Serial.print(EngineCoolantTemp());  Serial.print (",");

  vLow = 02.0; vHigh = 05.0;  if (oDISP1_2_0(vLow, vHigh)) ++err_count;         /* A15 Gasoline fuel pressure */

  vLow = 00.0; vHigh = 00.0;  if (oDISP1_2_4(vLow, vHigh)) ++err_count;         /* A2  Engine Oil Pressure */

  vLow = 00.0; vHigh = 00.0;  if (oDISP1_2_8(vLow, vHigh)) ++err_count;         /* A4  CylHead Rear temperature */

  vLow = 00.0; vHigh = 00.0;  if (oDISP1_2_12(vLow, vHigh)) ++err_count;        /*     Exhaust Gas right */

  vLow = 00.0; vHigh = 00.0;  if (oDISP2_2_1(vLow, vHigh)) ++err_count;         /* A12 Battery voltage measured */

  vLow = 00.0; vHigh = 00.0;  if (oDISP2_2_10(vLow, vHigh)) ++err_count;        /* A10 Amps measured */

  if (err_count > 0) {
    digitalWrite(errLED, LOW);
    delay(5);                                        /* REMEMBER: delay values STOP the loop and reading updates */
  }
}

Glitch in the corner of the OLED is often an indication that something is overwriting the end of the display buffer. Possibly writing outside the bounds of an array or the LED buffer, looks like you should not be having any problems with the amount of ram.

Thanks both for your replies.

david_2018

That reminded me, I have seen something about the display buffer and the glitch somewhere before. Can't remember where though.

mrburnette

I did some testing this morning,

  • Implemented intervals for the display code, LED code and the rest of the loop (3 intervals in total).
  • Tried various timing intervals for all 3.
  • After a while it become apparent the only interval that actually made the LEDs run smooth was the display interval (adjusting the other intervals didn't make any difference until the interval was so long it was slowing the execution of the code which just made the LED's jumpy any way).

Using a display interval of 2500 millis the LEDs ran OK with the occasional jump, but obviously this interval is far to long to update the display. The best compromise I was able to achieve was 750 millis, which is not really an acceptable display update time. Previously while using the Shift register for the LEDs with the CANBUS rather than the potentiometer I settled on 333 millis as an acceptable display update time.

Even if I go with 750 millis display update time I think I'm going to run into the same problem when I change the potentiometer for the CANBUS.

What I have noticed is that if I comment out either of the displays it all runs OK with a display interval of 333 millis, it appears that driving 2 displays is causing the issue rather than the libraries or code per say. From my testing display 2 seems to be the biggest culprit.

Any further ideas on how to resolve this welcome.

Just for some further reference here is a Youtube of the setup with the shift register rather than the WS2812B.

Thanks again.

Done some more research.

Found out that the SSD1306.h library uses a 1024 byte buffer for a single 128x64 display (explains Nano & Uno having issues but doesn't really explain the Mega having issues??).

http://www.technoblogy.com/show?23OS

Looks like I have 3 options to resolve the issue,

1, Use the U8g2 library which can be coded to use no Buffer or only a small amount of RAM
( setup_tutorial · olikraus/u8g2 Wiki · GitHub - GitHub - olikraus/U8g2_Arduino: U8glib V2 library for Arduino ).
2, Use a separate Arduino to drive the displays (lets see how I get on with the U8g2 library).
3, Don't use a library to code the displays, not really an option see the coding required in the link,
(Dual-ssd1306-OLED/DUAL_1306_I2C_OLED_wEEpromFonts.ino at main · EKMallon/Dual-ssd1306-OLED · GitHub )

Update if someone has the same issue,

Used the the U8g2 library with no buffer, its a bit tricky as it only updates the pixels that are specified to be updated. IE If your displayed variable goes from 99 to 100 once it goes back to 99 you are still left with the last 0, so you have to incorporate an if statement that over writes the last 0 if your variable is under 100. Also the available fonts are a bit limited and there is no way to display graphics apart from the icons in the font options.

All things considered using a separate Nano to drive the 2 x 128x65 OLED screens might not be a bad idea also.

Why not unconditionally clear the area where you will be printing the value ? Much easier to program than using conditional programming

If you just clear the area required you still need to set the condition as to when to clear it and If you clear the whole screen (which was my first solution) you end up with a flashing screen.

PS
Migrated the code from Mega to Uno and it's way to big the font libraries really fill up the flash, going to see if I can rationalise it enough to get on to a Uno.

Why ?

Clear it unconditionally before you print any value.

Put that code in a function that takes the coordinates to print at and the value to be printed and it is just as easy as calling the normal function to print the value

One way to handle that is to save the old value of the variable, then when you want to erase it set the text color to the background color and re-display the old value. Usually faster than drawing a box over the text area.

The u8g2 font files can be rebuilt to include only the specific characters you need, considerably reducing the size. The u8g2 GitHub page has everything needed to do that, although it takes a bit of research to find examples of how to accomplish it.

Have not had an opportunity to try your code, the hard drive died on the laptop I was using to test code and have not taken the time to get it set up again.

That would be pretty much the same as clearing the whole screen but you would only have the area in question flickering every 1/3 second instead of the whole screen all the time.

What I'm doing is just printing a space after the 2 digit number.

I think I'm going down a bit of a rabbit hole with this, I've cut down the fonts so I'm just using a single font library and up scaling which is not ideal aesthetically but it's OK. I can probably get it all to fit on a Uno\Nano, but it will always be tittering on the edge especially when I add the CANBUS code. Also by trimming the libraries down to the minimum it will make any future updates problematic. Although it would be nice to have it all fit on a single processor, it looks like I might be heading towards separating out the screen control to a dedicated processor.
I'll see how I get on today with the size of the flash and make a decision from there.

Not if you only print if the value has changed, which is the sensible thing to do

Full new code at the bottom.

Confused, you still need to have some sort of condition indicating the value has changed, it's RPM & Speed that have the issue so the values will change constantly.

Good news on the compilation of the code, after a bit of jiggling with the display section and a change of approach of where & what to display on each screen I got it all in with the CANBUS using 70% :slight_smile:

Sketch uses 22604 bytes (70%) of program storage space. Maximum is 32256 bytes.
Global variables use 1033 bytes (50%) of dynamic memory, leaving 1015 bytes for local variables. Maximum is 2048 bytes.

Few of quick question's,

  • Is it possible to reduce the code for these 2 sections?
    1 u8x82.drawString(1, 0, "PSI");
    u8x82.draw2x2String(0, 3, String(Boost_pressure_PSI).c_str());

    2 u8x82.drawString(1, 0, "W-M");
    u8x82.drawString(12, 5, "%");
    if (WM_value_percent < 100) u8x82.draw2x2String(8, 3, " ");
    u8x82.draw2x2String(0, 3, String(WM_value_percent).c_str());

Lastly I want to set the LEDs as a range rather than a line for each LED, I thought it would be something like this,

leds[1, 10] = CRGB(0, 255, 0);

But this doesn't work any ideas?

//CanBus
#include <mcp_can.h>
#include <SPI.h>

long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
bool init_state = true;

#define CAN0_INT 9                              // Set INT to pin 9
MCP_CAN CAN0(10);                               // Set CS to pin 10

//OLED
#include <Arduino.h>
#include <U8x8lib.h>
#define OLED_RESET 4
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
//
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x81(/* reset=*/ U8X8_PIN_NONE);
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x82(/* reset=*/ U8X8_PIN_NONE);

//OLED_Display_update_inetrval
const unsigned long DisplayInterval = 333;
unsigned long previousTimeDisplay = 0;

// Boost_Pressure_and_IAT
// int offset = 125; // low pressure calibration
// int span = 895; // high pressure calibration
int offset = 111; // low pressure calibration
int span = 912; // high pressure calibration
int Boost_pressure_Pa;
int Boost_pressure_kPa;
int Boost_pressure_PSI;
int boost_pressure_pin = A3;
int Max_PSI = 0;

int IAT_voltage = 0;
float IAT_Vin = 4.6; // 4.6 volts - USB powered
float IAT_Vout = 0;
float R1 = 2000; // Temperature resistor value
float IAT_buffer = 0;
float logR2;
float R2;
float IAT;
int IAT_pin = A1;
int IAT_C = 0;
int Max_IAT = 0;

// float A = 1.297373711e-03, B = 2.587931666e-04, C = 1.639343214e-07;  // Steinhart-Hart and Hart Coefficients Max
// float A = 1.306496435e-03, B = 2.580557547e-04, C = 1.752303942e-07;  // Steinhart-Hart and Hart Coefficients Nominal
float A = 1.316012871e-03, B = 2.572431200e-04, C = 1.877359037e-07;  // Steinhart-Hart and Hart Coefficients Min

//LEDs_Change_lights
#include <FastLED.h>
#define NUM_LEDS 20
#define DATA_PIN 2 //How boring and obvious!
#define COLOR_ORDER GRB //Green (G), Red (R), Blue (B)
#define CHIPSET WS2812B
#define BRIGHTNESS 25
#define VOLTS 5
CRGB leds[NUM_LEDS];

//Voltage
float Voltage = 1.00;

//RPM
int RPM = 1;
int Max_RPM = 0;
//int ARPM = 0;
//int BRPM = 0;
int RPM_NUM_LEDS = 0;

//Speed
int Speed = 0;
int Max_Speed = 0;

//W-M
int Max_WM = 0;
int WM_value_percent = 0;
int WM_pin = 6;
int WM_value_T;
int WM_value_P;
int WM_value;
//int WM_Level_pin = A2;
int WM_Level = 101;

//History
int HistoryValue = 0;
int Display1_Counter = 1;
int Display2_Counter = 1;
int Display1_Scroll = 4;
int Display2_Scroll = 5;
int Max_Reset = 7;



void setup() {
  Serial.begin(115200);

  //OLED
  u8x81.setI2CAddress(0x78);
  u8x81.begin();
  u8x81.setPowerSave(0);
  u8x81.clear();
  u8x82.setI2CAddress(0x7A);
  u8x82.begin();
  u8x82.setPowerSave(0);
  u8x82.clear();

  //LEDs_Change_lights
  FastLED.addLeds<CHIPSET, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);
  FastLED.clear();
  FastLED.show();

  //Water_Meth
  pinMode(WM_pin, OUTPUT);

  //Rest_&_Scroll_History
  pinMode(Max_Reset, INPUT_PULLUP);
  pinMode(Display1_Scroll, INPUT_PULLUP);
  pinMode(Display2_Scroll, INPUT_PULLUP);

  //CANBUS
  // Initialize MCP2515 running at 8MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if (CAN0.begin(MCP_STDEXT, CAN_500KBPS, MCP_8MHZ) == CAN_OK) {
    Serial.println("MCP2515 Initialized Successfully!");
  }
  else {
    Serial.println("Error Initializing MCP2515...");
  }

  pinMode(9, INPUT);                            // Setting pin 9 for /INT input

  CAN0.init_Mask(0, 0, 0x07FF0000);              // Init first mask (Std CAN. No masking applied)
  CAN0.init_Filt(0, 0, 0x02800000);              // Init first filter...
  CAN0.init_Filt(1, 0, 0x02800000);              // Init second filter...

  CAN0.init_Mask(1, 0, 0x07FF0000);              // Init second mask (Std CAN. No masking applied)
  CAN0.init_Filt(2, 0, 0x02880000);              // Init third filter...
  CAN0.init_Filt(3, 0, 0x02880000);              // Init fourth filter...
  CAN0.init_Filt(4, 0, 0x02880000);              // Init fifth filter...
  CAN0.init_Filt(5, 0, 0x02880000);              // Init sixth filter...

  CAN0.setMode(MCP_NORMAL);                     // Set operation mode to normal so the MCP2515 sends acks to received data.
}

void loop() {

  //Rest_&_Scroll_History
  // Display1
  if (digitalRead(Display1_Scroll) == LOW) {
    delay (100);

    if (digitalRead(Display1_Scroll) == LOW) {
      u8x81.clear();
      Display1_Counter = Display1_Counter + 1;
    }
  }
  if (Display1_Counter > 10) Display1_Counter = 1;

  // Display2
  if (digitalRead(Display2_Scroll) == LOW) {
    delay (100);

    if (digitalRead(Display2_Scroll) == LOW) {
      u8x82.clear();
      Display2_Counter = Display2_Counter + 1;
    }
  }

  if (Display2_Counter > 10) Display2_Counter = 1;

  // MAX_Reset
  if (digitalRead(Max_Reset) == LOW)
  {
    u8x81.clear();
    u8x82.clear();
    Max_Speed = 0;
    Max_RPM = 0;
    Max_IAT = 0;
    Max_WM = 0;
    Max_PSI = 0;
  }

  //CANBUS
  if (!digitalRead(9))                   // If pin 9 is low, read receive buffer
  {
    //            Serial.println("before readMsgBuf");
    CAN0.readMsgBuf(&rxId, &len, rxBuf); // Read data: len = data length, buf = data byte(s)

    //    Serial.print("ID: ");
    //    Serial.print(rxId, HEX);
    //    Serial.print(" Data: ");
    //    for (int i = 0; i < len; i++)        // Print each byte of the data
    //
    //    {
    //      if (rxBuf[i] < 0x10)               // If data byte is less than 0x10, add a leading zero
    //      {
    //        Serial.print("0");
    //      }
    //      Serial.print(rxBuf[i], HEX);
    //      Serial.print(" ");
    //    }
    //    Serial.println();


    if (rxId == 0x280) {

      //          throttle = rxBuf[5] * 0.4;
      //          Serial.print("Throttle (%): ");
      //          Serial.print(throttle, HEX);
      //          Serial.print("   ");
      //          Serial.println(throttle, DEC);
      //          if (throttle > throttlemax) throttlemax = throttle;
      //          Serial.print("Throttlemax: ");
      //          Serial.println(throttlemax, DEC);
      //
      //
      //          load = rxBuf[1] * 0.39;
      //          Serial.print("Engine Load (%): ");
      //          Serial.print(load, HEX);
      //          Serial.print("   ");
      //          Serial.println(load, DEC);
      //          if (load > loadmax) loadmax = load;
      //          Serial.print("loadmax: ");
      //          Serial.println(loadmax, DEC);

      RPM = ((rxBuf[3] * 256) + rxBuf[2]) * 0.25;
      //      ARPM = rxBuf[3] * 256;
      //      BRPM = ARPM + rxBuf[2];
      //      RPM = BRPM * 0.25;

    }

    if (rxId == 0x288) {

      Speed = (rxBuf[3] * 0.759);
      Serial.print("vehicle Speed (MPH): ");
      Serial.print(Speed);
      Serial.print("   ");
      Serial.println(Speed, DEC);
//      if (Speed > Max_Speed) Max_Speed = Speed;
      //          Serial.print("Max_Speed: ");
      //          Serial.println(Max_Speed, DEC);
    }
  }

  // WM level code
  //  int WM_Level = analogRead(WM_Level_pin); // get adc value
  //
  //  if (((HistoryValue >= WM_Level) && ((HistoryValue - WM_Level) > 10)) || ((HistoryValue < WM_Level) && ((WM_Level - HistoryValue) > 10)))
  //  {
  //    //sprintf(printBuffer, "ADC%d level is %d\n", WM_Level_pin, WM_Level);
  //    //Serial.print(printBuffer);
  //    HistoryValue = WM_Level;
  //  }

  // Boost Pressure
  Boost_pressure_Pa = map(analogRead(boost_pressure_pin), offset, span, 500, 4000);
  Boost_pressure_kPa = Boost_pressure_Pa / 10, 1;
  if (Boost_pressure_kPa < 20) Boost_pressure_kPa = 20;
  Boost_pressure_PSI = Boost_pressure_kPa * 0.145038;
  Boost_pressure_PSI = Boost_pressure_PSI - 14;
  if (Boost_pressure_PSI < 1) Boost_pressure_PSI = 0;
  if (Boost_pressure_PSI > Max_PSI) Max_PSI = Boost_pressure_PSI;

  // Potentiometer_in_lieu_of_CANBUS
  //  int sensorValue = analogRead(A0);

  // RPM
  //  RPM = map(sensorValue, 0, 1023, 100, 7500);
  if (RPM > Max_RPM) Max_RPM = RPM;

  // Speed
  //  Speed = map(sensorValue, 0, 1023, 0, 155);
  if (Speed > Max_Speed) Max_Speed = Speed;

  //WM_Controller
  if (WM_value_percent > Max_WM) Max_WM = WM_value_percent;

  //IAT
  IAT_voltage = analogRead(IAT_pin);
  if (IAT_voltage) {
    IAT_buffer = IAT_voltage * IAT_Vin;
    IAT_Vout = (IAT_buffer) / 1024.0;
    IAT_buffer = (IAT_Vin / IAT_Vout) - 1;
    R2 = R1 / IAT_buffer;
  }

  logR2 = log(R2);
  IAT = (1.0 / (A + B * logR2 + C * logR2 * logR2 * logR2)); // Steinhart and Hart Equation. T  = 1 / {A + B[ln(R)] + C[ln(R)]^3}
  IAT_C =  IAT - 273.15;

  // Edit_for_WM_delivery
  if (IAT_C >= 27) {
    WM_value_T = map (IAT_C, 27, 40, 0, 255);
    WM_value_P = map(Boost_pressure_PSI, 8, 25, 0, 255);
    if (WM_value_T >= WM_value_P) WM_value = WM_value_T;
    if (WM_value_P >= WM_value_T) WM_value = WM_value_P;
    if (WM_value <= 0) WM_value = 0;
    WM_value_percent = WM_value / 2.5;
    if (Boost_pressure_PSI >= 31) WM_value_percent = 100;
    if (WM_value_percent >= 100) WM_value_percent = 100;
    WM_value = WM_value_percent * 2.55;
    analogWrite(WM_pin, WM_value);
  }
  else
  {
    WM_value_P = map(Boost_pressure_PSI, 8, 25, 0, 255);
    WM_value_T = map (IAT_C, 28, 40, 0, 255);
    if (WM_value_P >= WM_value_T) WM_value = WM_value_P;
    if (WM_value_T >= WM_value_P) WM_value = WM_value_T;
    if (WM_value <= 0) WM_value = 0;
    WM_value_percent = WM_value / 2.5;
    if (Boost_pressure_PSI >= 25) WM_value_percent = 100;
    if (WM_value_percent >= 100) WM_value_percent = 100;
    WM_value = WM_value_percent * 2.55;
    analogWrite(WM_pin, WM_value);
  }
  //    // Here as it reads 0 when with the rest of the max readings??
  if (IAT_C > Max_IAT) Max_IAT = IAT_C;

  //OLED
  unsigned long currentTimeDisplay = millis();
  if (currentTimeDisplay - previousTimeDisplay >= DisplayInterval) {

    //Dispslay1
    u8x81.setFont(u8x8_font_px437wyse700b_2x2_r);

    if (Display1_Counter == 1) {
      u8x81.drawString(1, 0, "W-M");
      u8x81.drawString(12, 5, "%");
      if (WM_value_percent < 100) u8x81.draw2x2String(8, 3, " ");
      u8x81.draw2x2String(0, 3, String(WM_value_percent).c_str());

    }
    if (Display1_Counter == 2) {
      u8x81.drawString(1, 0, "PSI");
      u8x81.draw2x2String(0, 3, String(Boost_pressure_PSI).c_str());

    }
    if (Display1_Counter == 3) {
      u8x81.drawString(1, 0, "IAT");
      u8x81.drawString(9, 5, "C");
      u8x81.draw2x2String(0, 3, String(IAT_C).c_str());

    }
    if (Display1_Counter == 4) {
      u8x81.drawString(1, 0, "MPH");
      if (Speed < 100) u8x81.draw2x2String(8, 3, " ");
      u8x81.draw2x2String(0, 3, String(Speed).c_str());

    }
    if (Display1_Counter == 5) {
      u8x81.drawString(1, 0, "RPM");
      if (RPM < 1000) u8x81.draw2x2String(12, 3, " ");
      u8x81.draw2x2String(0, 3, String(RPM).c_str());
    }

    if (Display1_Counter == 6) {
      u8x81.drawString(1, 0, "MAX W-M");
      u8x81.drawString(12, 5, "%");
      u8x81.draw2x2String(0, 3, String(Max_WM).c_str());

    }

    if (Display1_Counter == 7) {
      u8x81.drawString(1, 0, "MAX PSI");
      u8x81.draw2x2String(0, 3, String(Max_PSI).c_str());

    }

    if (Display1_Counter == 8) {
      u8x81.drawString(1, 0, "MAX IAT");
      u8x81.drawString(9, 5, "C");
      u8x81.draw2x2String(0, 3, String(Max_IAT).c_str());

    }

    if (Display1_Counter == 9) {
      u8x81.drawString(1, 0, "MAX MPH");
      u8x81.draw2x2String(1, 3, String(Max_Speed).c_str());

    }

    if (Display1_Counter == 10) {
      u8x81.drawString(1, 0, "MAX RPM");
      u8x81.draw2x2String(0, 3, String(Max_RPM).c_str());
    }

    //Display_2

    u8x82.setFont(u8x8_font_px437wyse700b_2x2_r);

    if (Display1_Counter == 1) {
      u8x82.drawString(1, 0, "W-M");
      u8x82.drawString(12, 5, "%");
      if (WM_value_percent < 100) u8x82.draw2x2String(8, 3, " ");
      u8x82.draw2x2String(0, 3, String(WM_value_percent).c_str());

    }
    if (Display1_Counter == 2) {
      u8x82.drawString(1, 0, "PSI");
      u8x82.draw2x2String(0, 3, String(Boost_pressure_PSI).c_str());

    }
    if (Display1_Counter == 3) {
      u8x82.drawString(1, 0, "IAT");
      u8x82.drawString(9, 5, "C");
      u8x82.draw2x2String(0, 3, String(IAT_C).c_str());

    }
    if (Display1_Counter == 4) {
      u8x82.drawString(1, 0, "MPH");
      if (Speed < 100) u8x82.draw2x2String(8, 3, " ");
      u8x82.draw2x2String(0, 3, String(Speed).c_str());

    }
    if (Display1_Counter == 5) {
      u8x82.drawString(1, 0, "RPM");
      if (RPM < 1000) u8x82.draw2x2String(12, 3, " ");
      u8x82.draw2x2String(0, 3, String(RPM).c_str());
    }

    if (Display1_Counter == 6) {
      u8x82.drawString(1, 0, "MAX W-M");
      u8x82.drawString(12, 5, "%");
      u8x82.draw2x2String(0, 3, String(Max_WM).c_str());

    }

    if (Display1_Counter == 7) {
      u8x82.drawString(1, 0, "MAX PSI");
      u8x82.draw2x2String(0, 3, String(Max_PSI).c_str());

    }

    if (Display1_Counter == 8) {
      u8x82.drawString(1, 0, "MAX IAT");
      u8x82.drawString(9, 5, "C");
      u8x82.draw2x2String(0, 3, String(Max_IAT).c_str());

    }

    if (Display1_Counter == 9) {
      u8x82.drawString(1, 0, "MAX MPH");
      u8x82.draw2x2String(1, 3, String(Max_Speed).c_str());

    }

    if (Display1_Counter == 10) {
      u8x82.drawString(1, 0, "MAX RPM");
      u8x82.draw2x2String(0, 3, String(Max_RPM).c_str());
    }

    previousTimeDisplay = currentTimeDisplay;
  }

  // WM level low code
  //  if (WM_Level <= 460) {
  //    Display1_Counter = 0;
  //    Display2_Counter = 0;
  //    u8x81.drawString(1, 0, "W-M");
  //    u8x82.drawString(1, 0, "W-M");
  //    u8x81.draw2x2String(0, 3, "LOW ");
  //    u8x82.draw2x2String(0, 3, "LOW ");
  //    u8x81.draw2x2String(0, 3, "    ");
  //    u8x82.draw2x2String(0, 3, "    ");
  //  }


  int RPM_NUM_LEDS = RPM / 365;
  if (RPM_NUM_LEDS >= 16) RPM_NUM_LEDS = 20;
  // Light up the LEDs
  // Only LEDs are switched on which correspond to the area left slide
  //  for (int i = 0; i < RPM_NUM_LEDS; ++i) {
  //
  //    leds[i] = CRGB(0, 255 - 4 * i, 4 * i);
  //  }
  //    leds[1] = CRGB(0,255,0);
  //    leds[2] = CRGB(15,242,0);
  //    leds[3] = CRGB(31,216,0);
  //    leds[4] = CRGB(47,203,0);
  //    leds[5] = CRGB(63,190,0);
  //    leds[6] = CRGB(79,177,0);
  //    leds[7] = CRGB(95,164,0);
  //    leds[8] = CRGB(111,151,0);
  //    leds[9] = CRGB(127,138,0);
  //    leds[10] = CRGB(143,125,0);
  //    leds[11] = CRGB(159,112,0);
  //    leds[12] = CRGB(175,99,0);
  //    leds[13] = CRGB(191,86,0);
  //    leds[14] = CRGB(207,73,0);
  //    leds[15] = CRGB(223,60,0);
  //    leds[16] = CRGB(239,47,0);
  //
  //    leds[17] = CRGB(255,0,0);
  //    leds[18] = CRGB(255,0,0);
  //    leds[19] = CRGB(255,0,0);
  //    leds[20] = CRGB(255,0,0);

  leds[0] = CRGB(0, 255, 0);
  leds[1] = CRGB(0, 255, 0);
  leds[2] = CRGB(0, 255, 0);
  leds[3] = CRGB(0, 255, 0);
  leds[4] = CRGB(0, 255, 0);
  leds[5] = CRGB(0, 255, 0);
  leds[6] = CRGB(0, 255, 0);
  leds[7] = CRGB(0, 255, 0);
  leds[8] = CRGB(0, 255, 0);
  leds[9] = CRGB(0, 255, 0);
  leds[10] = CRGB(0, 255, 0);
  leds[11] = CRGB(0, 255, 0);
  leds[12] = CRGB(255, 50, 0);
  leds[13] = CRGB(255, 50, 0);
  leds[14] = CRGB(255, 50, 0);
  leds[15] = CRGB(255, 50, 0);

  leds[16] = CRGB(255, 0, 0);
  leds[17] = CRGB(255, 0, 0);
  leds[18] = CRGB(255, 0, 0);
  leds[19] = CRGB(255, 0, 0);

  // LEDs are switched off which correspond to the area right side
  for (int i = RPM_NUM_LEDS; i < NUM_LEDS; ++i) {

    leds[i] = CRGB::Black;
  }

  FastLED.show();
}

Thanks

When you say that the values will change constantly, the rate at which they will change is nothing compared to the rate at which the loop() function will repeat

Written properly the loop() function will run many thousands of time per second and you certainly don't want to update the display that frequently, even if you could

There are at least 2 approaches to avoid this. One would be to update the display at a fixed rate that you decide, whether or not the value has changed.

The second is to compare the value of RPM with its previous value and to print it only if it has changed

The obvious way to do this is to use a for loop to set the value for each LED before the show() function is called. FastLED also allows the use of zones of the full LED strip which I believe allow you to operate on all of the LEDs in a zone with a single command although I have never tried the functionality

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.