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