SoftwareSerial and SH1106 and SSD1306 compatibility

I have written a sketch for controlling an electric power assisted steering system.
Initially I used a 16 x 2 LCD to display status. I have tried to upgrade to an OLED display but there appears to be problems/conflict with SH1106 library and softwareSerial which causes the larger 1.3 OLED to lock, the smaller 0.9OLED and LCD work fine.
THe problem exists with all SoftwareSerial alternatives I have tried.
Any Ideas?

You could use a different Arduino that has more hardware serial ports, so that you don't need to use SoftwareSerial.

You haven't told us which Arduino you are currently using.

The Mega 2560 has four serial ports.
Arduino Uno R4, and some other models have two serial ports.

1 Like

The libraries for SH1106 and SSD1306 are not that different. I can't think of any reason why one would work with software serial and the other would not.

That said, you have given almost no detail for us to help you figure out what the problem is. You should post working and non-working code, schematics and links to the displays and other important components. It's all there to read in the forum guide.

And I agree with @JohnLincoln if you have a hardware port available, you should not be using software serial.

Thanks for your prompt replys. Just adding the softwarSerial library to a SH1106 sketch locks the 1.3 OLED screen and if you power off and back on again the screen is blank. This is not the case with LCD and 0.9 OlED.
Try one of the examples.

We can't help you without more information, sorry.

Good luck.

May be this has nothing to do with SoftwareSerial and you have a memory (ram) issue if the sketch does not work with the 1.3" OLED and does work with 0.9" (assuming more pixels on the larger display == more demand on the RAM).

Some details that might be useful for us to help you

  1. Which board are you using?
  2. Post your sketch; please do not forget to use code tags as described in https://forum.arduino.cc/t/how-to-get-the-best-out-of-this-forum/679966#posting-code-and-common-code-problems.

Try a SPI or I2C based display.

Thanks for all your responses.

Background
The Sketch I have developed run on a Nano and simulates the signals a vauxhall ECU sends to an electric power assisted steering unit. Information sent includes road speed, engine speed, assistance required, battery voltage as well as activation and configuration data. It also allows automatic overide to provide max assistance when the handbrake is applied for handbrake turns etc. The sketch is universal as it has to be configured for different cars.

The below includes a lot of in information that is in the final sketch and is not used in the this test sketch which is me just trying a few screen layouts when I change from the 16 x 2 LCD to an OLED. The display only used for setting up and can be removed once configured.

Using an OLED would allow me to display addition information just engine temperature, low oil pressure etc

The sketch below with the appropriate deletions marked in “large bold text”

The sketch compiles and uploads in all configurations but locks the 1.3 OLED display if SoftwareSerial is included.

THATS THE PROBLEM!

Sorry its a bit untidy but its work in progress

/*********

Setup code for OLED 1.3 and 0.9 OLED's to be included at start of sketch

*********/

//=============================================================================

// Universal Power Assistance Control code

// DO NOT CHANGE ANY VARIABLES OUTSIDE THIS SECTION

//Calibration corrects the speedometer increase if slow decrease if high default is 100

//LowMPH is speed at which assist switches from high to medium assistance default is 18

//MedMPH is speed at which assist switches from medium to low assitance default is 45

//Set values below or leave at defaults:

int Calibration = 100;

int LowMPH = 18;

int MedMPH = 45;

//=========================================================================================

// DO NOT CHANGE ANY OF THE VALUES BELOW!

//Setting up user defined variables

int LowHZ; //Hertz for transition from maximum to medium assistance default 40

int MedHZ; //Hertz for transition from Medium to minimum assistance default 100

float SpeedoHZ; //number of speed sensor pulses per second per 1 mph default 2.222'

float Ratio = 2.22222222222;

char duty[] = "D050"; //sets duty cycle of PWM

char low[] = "F062"; //sets frequency for high assistance

char med[] = "F222"; //sets frequency for medium assistance

char high[] = "F510"; //sets frequency for low assistance

char zero[] = "F001";

long int frq; //cycle count from frequency counter in gatetime

int hz; //frequency measure by frequency counter

int mph; //corrected MPH

int val; //value of handbrake trigger

String A= " mph ";

String B= "Speed ";

float Volts = 13.5; //charge voltage setting

char medi[] = "Medium";

//=========================================================================================================

//Download following libraries if not available

#include <SPI.h>

#include <Wire.h>

#include <Adafruit_GFX.h>

//#include <Adafruit_SH110X.h> //1.3OLED

#include <Adafruit_SSD1306.h> //0.9OLED

#include <FreqCounter.h> //Created by Martin Nawrath, KHM Lab3, Dec. 2008

//pin D5 is input frequency

#include <SoftwareSerial.h>

SoftwareSerial SoftSerial(3, A0); // RX | TX pins. Can be reassigned if needed

const long BAUDRATE = 9600; // Baud rate of the XY-LPWM module#include SoftwareSerial.h> //created by Ardunio

//add additional libraries required above

//Screen setup for both 0.9 and 1.3 OLED's

#define i2c_Address 0x3c //initialize with the I2C addr 0x3C Typically eBay OLED's

// e.g. the one with GM12864-77 written on it

//#define i2c_Address 0x3d //initialize with the I2C addr 0x3D Typically Adafruit OLED's

#define SCREEN_WIDTH 128 // OLED display width, in pixels

#define SCREEN_HEIGHT 64 // OLED display height, in pixels

#define OLED_RESET -1 // QT-PY / XIAO

//Declaration for display delete as necessary 1306 for 0.9OLED or 1106G for 1.3OLED

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); //0.9OLED

//Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); //1.3OLED

// add below string, integer etc declarations common to both 0.9 and 1.3 OLED's

String X= "12345";

String Y= "678";

int testA = 27/9;

// Start of code

void setup() {

Serial.begin(9600); // Optional: for debugging via serial

//add this part specific to 0.9 OLED's

if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64

***Serial.println(F("SSD1306 allocation failed"));***

***for(;;);***

//add this part specific to 1.3 OLED's

//if (!display.begin(0x3C, 0x78)) { // Adjust I2C address if needed

//Serial.println(F("SH110X not found"));

//for (;;); // Don't proceed, loop forever

//display.setTextColor(SH110X_WHITE);

//display.setTextSize(2);

}

//Following is common to both 0.9 and 1.3 OLED's

//delay(1000);

}

void loop() {

//display.setTextColor(SH110X_WHITE,SH110X_BLACK);

display.setTextColor(WHITE,BLACK); // sets colour SH110X_WHITE for 1.3 OLED just WHITE for 0.9 OLED

display.clearDisplay();

display.setTextSize(2);

//display.setTextColor(SH110X_WHITE);

display.setCursor(17, 0);

display.setTextSize(1);

//display.setTextColor(SH110X_WHITE);

display.print("SPEED");

display.setCursor(51, 0);

// Display static text

display.setTextSize(2);

display.print("120");

display.setTextSize(1);

//display.setTextColor(SH110X_WHITE);

display.print(" MPH");

display.setTextSize(2);

display.setCursor(12, 16);

display.print(testA);

display.print(medi);

display.print("66");

display.setTextSize(2);

//display.setTextColor(SH110X_WHITE);

display.setCursor(0, 33);

display.println("Assistance");

display.setTextSize(1);

display.setCursor(0, 57);

display.print("BATTERY");

display.setTextSize(2);

display.setCursor(45, 50);

display.print("12.5");

display.setTextSize(1);

display.setCursor(95, 57);

display.print("Volts");

display.display();

delay(3000);

display.setCursor(0, 33);

display.setTextSize(2);

//display.print(" ");

//display.display();

//display.setCursor(0, 33);

display.print("ASSISTANCE");

display.display();

delay(3000);

}

You forgot to wrap the code in code tags.

Do you have different resolutions ?

Yes the code is much the same for both just look for parts in bold and italics and delete as appropriate or put // infront of parts not required.

//#include <Adafruit_SH110X.h> //1.3OLED

#include <Adafruit_SSD1306.h> //0.9OLED

see above where SSD1306.h is used for 0.9OLED to change configuration to 1.3OLED just change to:

#include <Adafruit_SH110X.h> //1.3OLED

//#include <Adafruit_SSD1306.h> //0.9OLED

go through all the bold italic section and change accordingly.

Hey Presto

I don’t read code that is not in code tags. Too boring.

I explained the problem in my first post the inclusion of softwareSerial and SH1106 causes a conflict which freezes the display on the 1.3OLED display it is that simple. Take an example from the libraries and try it.

The respondants to my post asked for code I did not offer it initially as I thought I would get an experts opinion or confirmation that the problem exists and may be a library that did work.

I did see a post about 2 years ago highlighting the same problem but this was closed without resolution, I thought may be things had moved on.

Without the code we would not have known that you're using the Adafruit library. Not sure which one causes the problem as I'm not behind a PC.

But one of the libraries that you use uses dynamic memory allocation and that chews away memory; I think it's the SSD1306 and SH1106. For the SSD1306 that would be 1 kByte, don't know for thw SH1106.

So if the memory reports e.g. 750 bytes used you need to add that 1 kByte and you're skating on thine ice when it comes to dynamic memory usage.

Please add code tags to your code posted on the forum (as requested) so the code is easier to read and (maybe more important) essier to copy.

The posted code uses 760 bytes of ram, the display will add 1024 bytes, leaving only 264 bytes for the stack, local variables, heap, etc.

You can save a bit of ram by using the F() macro for the display print statements.

Avoid the use of String, that can use a considerable amount of ram. Your code declares a few String variables, but never uses any of them, if you were to use those the memory usage would increase.f

Note that Software serial allocates two buffers, each 64 bytes in size, and makes heavy use of interrupts, which may interfere with the FreqCounter library.

Thanks for you reply

The information at the top of the sketch is used in the final LCD sketch, I just left it there.

When I write the final OLED sketch I will not be using strings they were just used in the LCD version as it was easier to display status information on the 16 x 2 character LCD screen.

I did read that SSD 1306 and SH1106 manage memory differently, I seem to recall SH1106 buffers a whole screen before sending it to the display.

As far as number of pixels both 1.3 and 0.9 LED’s are the same although on some 1.3OLED’s you can get an extra 3 or 4 additional pixels on the width.

SoftwareSerial is only used to change the frequency of the PWM output which adjusts the servo assistance. This is infrequent in practice.

FreqCounter has worked fine, perhaps because the frequencies I am measuring are low (less than 200HZ)

without seeing a code I can just suggest to check how the two different variants are initialized in the code.
SSD1306 starts this way:

oled.begin(SSD1306_SWITCHCAPVCC, I2Cadd); // for SSD1306 only

SH1106G starts like this:

oled.begin(I2Cadd);

maybe you forgot to correct this on switching Oled-types

Thanks to all those who responded to my post including bored J-M-L.

In reality there are only 4 solutions to my issue.

  1. a coding issue
  2. coding changes to Adafruit SH110X to eleviate the conflict
  3. An alternative to SoftwareSerial
  4. An alternative to Adafruit SH110X

“1” I dismissed as just including SoftwareSerial to working sketches for the 0.9 and 1.3 OLED’s caused the 1.3OLED to freeze but not the 0.9OLED.

“2” was above my pay grade hence my post to the experts.

“3” I explored extensively but was unable to find a solution“4” I have found a solution in <U8x8lib.h> library. A copy of the sketch is included. This has the advantage it can be used with both OLED without change and there is no conflict with SoftwareSerial. There is slight noise problem on some 0.9 OLEDs on the left hand side in the unused pixels.

I expect you are all award that all these OLEDs are actually 132 pixels wide and the 4 “spare pixels” are treated differently in the OLED firmware. Most 0.9 OLEDs have two spare pixels either side of the display so postion 0 is actually the third pixel while the 0.9OLEDS have two spare pixels each side of the display, postion 0 being the second pixel.

Please accept apologies for using tabs could not work out how to use them

`

/*

Test with 1.3 and 0.9 OLED's using <U8x8lib.h> library

*/

#include <SoftwareSerial.h>

#include <FreqCounter.h>

#include <Arduino.h>

#include <U8x8lib.h>

#ifdef U8X8_HAVE_HW_SPI

#include <SPI.h>

#endif

//U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);

//U8X8_SSD1306_128X64_ALT0_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);

U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);

void setup(void)

{

u8x8.begin();

u8x8.setPowerSave(0);

}

void loop(void)

{

u8x8.clearDisplay();

u8x8.setFont(u8x8_font_px437wyse700a_2x2_r);

u8x8.setInverseFont(0);

u8x8.drawString(0,6,"Hello""!");

u8x8.setInverseFont(1);

u8x8.setFont(u8x8_font_chroma48medium8_r);

u8x8.drawString(0,0,"012345678901234");

u8x8.setInverseFont(0);

u8x8.setFont(u8x8_font_7x14_1x2_r);

u8x8.drawString(0,2,"012345678901234");

u8x8.drawString(4,4,"EUREKA!");

delay(2000);

u8x8.drawString(4,4," ");

u8x8.setFont(u8x8_font_chroma48medium8_r);

u8x8.drawString(0,0,"XXXXX");

delay(2000);

u8x8.clearDisplay();

}

`

still very bored as you did not use code tags...