I2C OLED causing program to freeze and slowdown when using Blynk.VirtualWrite

Hello all,

i’ve been searching all weekend and have struggled to find the cause (and solution) to a problem I am having converting my code for use with Blynk.

I am using an Arduino Uno and ESP12 module for the wifi connectivity to a local server, I am having no issues with the wifi connection itconnects every time.

Please see my code prior to alterations for Blynk usage

#include <LiquidCrystal_I2C.h>

const int xpin = A1;                  // x-axis of the accelerometer
const int ypin = A2;                  // y-axis
const int zpin = A3;                  // z-axis (only on 3-axis models)

int sampleDelay = 20;   //number of milliseconds between readings

LiquidCrystal_I2C lcd(0x27, 2, 1, 0 ,4 ,5 ,6 ,7 ,3, POSITIVE);  // Set the LCD I2C address;

void setup()
{
  lcd.begin(16,2);
  lcd.clear();
  lcd.setCursor(0, 0); // Sets the cursor to col 0 and row 0
  lcd.print("X:");
  lcd.setCursor(0, 1); // Sets the cursor to col 0 and row 1
  lcd.print("Y:");
  lcd.setCursor(8, 0); // Sets the cursor to col 8 and row 0
  lcd.print("Z:");
  
  analogReference(EXTERNAL);
  pinMode(xpin, INPUT);
  pinMode(ypin, INPUT);
  pinMode(zpin, INPUT);
  Serial.begin(9600);
}

void loop()
{
 Serial.print(analogRead(xpin));
 Serial.print(",");
 Serial.print(analogRead(ypin));
 Serial.print(","); 
 Serial.println(analogRead(zpin));

 lcd.setCursor(3, 0); // Sets the cursor to col 0 and row 0
 lcd.print(analogRead(xpin));
 lcd.setCursor(3, 1); // Sets the cursor to col 0 and row 1
 lcd.print(analogRead(ypin));
 lcd.setCursor(10, 0); // Sets the cursor to col 8 and row 0
 lcd.print(analogRead(zpin));
}

The purpose of the sketch is to read the feedback from a 3 Axis accelerometer and the value of each axis is subsequently printed to the serial monitor and a OLED display .

Here is my code reformatted for use with Blynk.

#include <LiquidCrystal_I2C.h>
#include <Wire.h> 
#include <ESP8266_Lib.h>
#define BLYNK_PRINT Serial
#include <BlynkSimpleShieldEsp8266.h>

char auth[] = "bleh";
char ssid[] = "bleh";
char pass[] = "bleh";

#include <SoftwareSerial.h>
SoftwareSerial EspSerial(8, 9); // RX, TX

#define ESP8266_BAUD 9600
ESP8266 wifi(&EspSerial);

const int xpin = A1;                  // x-axis of the accelerometer
const int ypin = A2;                  // y-axis
const int zpin = A3;                  // z-axis (only on 3-axis models)

//LiquidCrystal_I2C lcd(0x27, 2, 1, 0 ,4 ,5 ,6 ,7 ,3, POSITIVE);  // Set the LCD I2C address;

BlynkTimer timer;

void setup()
{
 
//  lcd.begin(16,2);
//  lcd.clear();
 // lcd.setCursor(0, 0); // Sets the cursor to col 0 and row 0
//  lcd.print("X:");
 // lcd.setCursor(0, 1); // Sets the cursor to col 0 and row 1
 // lcd.print("Y:");
//  lcd.setCursor(8, 0); // Sets the cursor to col 8 and row 0
 // lcd.print("Z:");
  
  analogReference(EXTERNAL);
  pinMode(xpin, INPUT);
  pinMode(ypin, INPUT);
  pinMode(zpin, INPUT);
  
  Serial.begin(9600);
  EspSerial.begin(ESP8266_BAUD);
  delay(10);
  
  Blynk.begin(auth, wifi, ssid, pass, "10.1.1.244", 8080);

  timer.setInterval(20L, serialmonitor);
  //timer.setInterval(450l, superchart);
}

void serialmonitor()
{  
  Serial.print(analogRead(xpin));
  Serial.print(",");
  Serial.print(analogRead(ypin));
  Serial.print(",");
  Serial.println(analogRead(zpin));

  //lcd.setCursor(3, 0); // Sets the cursor to col 0 and row 0
 // lcd.print(analogRead(xpin));
 // lcd.setCursor(3, 1); // Sets the cursor to col 0 and row 1
  //lcd.print(analogRead(ypin));
  //lcd.setCursor(10, 0); // Sets the cursor to col 8 and row 0
 // lcd.print(analogRead(zpin));
}

void superchart()
{
  Blynk.virtualWrite(V5, analogRead(xpin));
  Blynk.virtualWrite(V6, analogRead(ypin));
  Blynk.virtualWrite(V7, analogRead(zpin));
}

void loop()
{
 Blynk.run();
 timer.run();
}

I am now finding myself with two problems:

  1. Using the liquidcrystal_I2C library causes everything to freeze once I connect to the server, on the serial monitor I can see I connect, the ping is reported (Ready) but the serialmonitor code does not run and I am disconnected in the app. If I don’t use this library then as soon as I connect values are immediately printed to the serial monitor.

  2. As soon as I activate the ‘superchart’ timer to virtualwrite analogread values to virtual pins the program slows down to a crawl. The serial monitor slows down to printing approximately 1 or 2 times a second (according to timestamps).

Now I assume I am doing something incorrect here causing the problem but after lots of searching all weekend I can’t figure it out. I have tried assigning each virtualwrite to its own timer but that made no real difference apart from the fact I could see the serial monitor response getting slower each timer another virtualwrite was taking place.

Thanks in advance for any assistance and patience.

Why are you using an LCD library for an OLED display? What is the model of your display?

Hi Gunner it is a Winstar 16x2 OLED that is HD44780 pin ‘compatible’, both my LCD and OLED work it. I could probably try wiring up the screen directly and using the adafruit library instead as per here:
https://learn.sparkfun.com/tutorials/oled-display-hookup-guide/all
but I still don’t get why merely including that library effectively breaks my sketch.

Have you tested with a simpler sketch that only puts some data to the screen (uptime count or something) and see it that works fine?

Well as it stands with all the code for the LCD commented out (not sure what correct term is) and only the library included the blynk timers don’t run. As soon as I remove the library as well it all goes fine.

Later when i’m home i’ll try running blynk with just the OLED and blynk, i’ll also try running without the IC2 library and connect directly to the screen.

Any thoughts on the slowdown when using the blynk virtualwrite? is that a n arduino limitation in terms of speed or am I missing somethign else?

Exactly what LiquidCrystal I2C library are you using?? I have one running with Blynk and about a bazillion timers on my Mega and it works… at least last time I used it.

EDIT - Turns out I am using this library… https://github.com/marcoschwartz/LiquidCrystal_I2C

I did install the latest Arduino/Adafruit one, as you seem to be using (same library name, but slightly differing setup)… but unable to get anything usable on the display… just a flashing cursor.

I think this process is using-up all of your available processor time.
The serialmonitor function is taking a reading from 3 different GPIO pins, then printing the results to the serial monitor, along with some additional information.
According to this information:
https://www.microchip.com/forums/m/tm.aspx?m=405110&p=1
It takes just over 1 millisecond to write one character to the serial monitor at 9600 baud.
I have no idea how the UART FIFO buffer works on an Arduino, but it seems to me that you’re sending trying to send it data faster than it can push it out to the serial monitor. Add to that the time taken to do the digital reads and the whole thing can’t realistically complete in 20 milliseconds.

Asking the processor to service the Blynk library (which is processor hungry - not surprising considering all the magic it does) and service the Wi-Fi Comms, timer function SoftwareSerial library etc as well as pushing data to the LCD via the I2C bus then it’s not surprising that it spits it’s dummy and says ‘enough is enough already!’

Using an MCU with more horsepower and built-in Wi-Fi coms such as a NodeMCU may help, but I don’t really see why you need to be taking 50 samples per second from your accelerometer.

Also, the maximum granularity for SuperChart is one data point per minute. You can send data more frequently, but it will be averaged-out to give you the single data point per virtual pin.
That means that from a SuperChart point of view, you’re over-sampling by 3000 readings per minute.

Pete.

1 Like

I was using this one https://github.com/fmalpartida/New-LiquidCrystal with a more upto date library hosted here https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads/ .

I was getting mixed up earlier regarding the library. Including the library isn’t the problem it is when I define the I2C address and screen pinout (without running any other lcd related code) that blynk locks up. I didn’t get much of a chance today but tomorrow i’ll try a few different libraries, there is like half a dozen all including liquidcrystal I2C.

@PeteKnight thank you for that comprehensive and candid response. I guess i’m not truly appreciating how much work the arduino is doing, not like on my PC where I would just open task manager and think ohh cpu is at 100%, in fact if my arduino was running windows I would of probably forced a BSOD!

I’ve got a NodeMCU here with a ESP12E chip but that only has 1 analog pin and I require 3 to read the ADXL335 accelerometer, I see the newer NodeMCU-32S though has many more pins and they are very cheap so i’ll give that a go and see how I fare.

Good point about the over sampling, initially I was blasting readings out over serial so I could plot them in real time to measure vibration and produce a nice smooth response. I’m starting to realise now though that perhaps supercharts isn’t the best solution for this.

Ok so I tried several different ‘liquidcrystal’ libraries but this one actually seemed to be quite comprehensive

it seems the author had gone to some lengths trying to sort out all the problems with other conflicting libraries as mentioned in this thread (bperrybap)
https://forum.arduino.cc/index.php?topic=485166.0

anyway regardless of which library I tried I was still getting the lockup issue so I decided to switch from the softserial ESP wifi to local server connection via USB and the LCD screen and blynk worked!

I think it is as @PeteKnight alluded to I have been asking too much of the arduino. I’ve picked up a ESP32S so i’ll see how I fair with that. Thanks all for the information and prods in the right direction.

Why not use the <LiquidCrystal.h> which comes with the Arduino IDE’s? https://www.arduino.cc/en/Tutorial/HelloWorld

Also, your’re reading the analog pins 2 times, once per loop and the other within the 20ms. Store the reading in a variable and reuse it. At least, this way, the monitor print outs match with your blynk displays :wink:

That doesn’t cover I2C though? I’ve used like 4 different libraries with the same result everytime, once I declare the I2C address it locks if I am running ESP serial (for wifi) and the blynk process. Remove any 1 of those 3 and it works.

Good tip on the variable, I do have that in a sketch but I stripped it all out trying to dumb it down as much as I could to isolate the problem. Glad you mentioned it though as things like that i’m trying to learn as I go to improve program efficiency, just the wifi and blynk magic seems to be bringing the uno to it’s knees.

Do you really need the UNO? Maybe you can run the code entirely on the ESP unless, you need to use more pins. To redure the number of pins needed for the display, you may want to use I2C unless your display doesn’t allow it.

I was using the 3 analog pins on the uno for the accelerometer as the ESP12 only has 1 but since Pete’s post above I have purchased a ESP32 which has bulk pins and wifi built in so i’ll be giving that a go, oh and the display is already using I2C hence the problems in the first post!