make faster looptime with LCD display

Hello.

I have a question about using classic LCD display (LiquidCrystal.h)

I use arduino with MSGEQ7 and LED strip to make "color music".
I have also the LCD keypad Shield, where I can see actual spectrum, values send to LED, looptime and filter value.
Problem is, that the LCD adds around 15ms to the loop time, which is pretty high in music.

Is there any way to display the value but have also still fast loop?
I was thinking about using timer interrupt to read and send values to LEDs, but it's a lot of code (there is also circular buffer with averaging) so the interrupt would be probably too short.

Or is there any faster display?
What I looked on OLED, it's very similar, maybe even worse (up to 30ms).

Here I post a peace of code, where I display the values.

Thank you :slight_smile:

for (i = 0; i < 7; i++)
  {
    tempValue = avgSpectrum[i] * 2;
    lcd.setCursor(i, 1);
    if (tempValue <= 64)  lcd.write(byte(1));
    else if (tempValue <= 128) lcd.write(byte(2));
    else if (tempValue <= 192) lcd.write(byte(3));
    else if (tempValue <= 256) lcd.write(byte(4));
    else if (tempValue <= 320) lcd.write(byte(5));
    else if (tempValue <= 384) lcd.write(byte(6));
    else if (tempValue <= 448) lcd.write(byte(7));
    else lcd.write(byte(8));
    lcd.setCursor(i, 0);
    if (tempValue <= 512) lcd.print(" ");
    else if (tempValue <= 576) lcd.write(byte(1));
    else if (tempValue <= 640) lcd.write(byte(2));
    else if (tempValue <= 704) lcd.write(byte(3));
    else if (tempValue <= 768) lcd.write(byte(4));
    else if (tempValue <= 832) lcd.write(byte(5));
    else if (tempValue <= 896) lcd.write(byte(6));
    else if (tempValue <= 960) lcd.write(byte(7));
    else lcd.write(byte(8));
  }
  for (i = 0; i < 3; i++)
  {
    if (i == 0)tempValue = LEDbass;
    if (i == 1)tempValue = LEDmid;
    if (i == 2) tempValue = LEDhigh;
    lcd.setCursor(i + 8, 1);
    if (tempValue <= 16) lcd.write(byte(1));
    else if (tempValue <= 32) lcd.write(byte(2));
    else if (tempValue <= 48) lcd.write(byte(3));
    else if (tempValue <= 64) lcd.write(byte(4));
    else if (tempValue <= 80) lcd.write(byte(5));
    else if (tempValue <= 96) lcd.write(byte(6));
    else if (tempValue <= 112) lcd.write(byte(7));
    else lcd.write(byte(8));
    lcd.setCursor(i + 8, 0);
    if (tempValue <= 128) lcd.print(" ");
    else if (tempValue <= 144) lcd.write(byte(1));
    else if (tempValue <= 160) lcd.write(byte(2));
    else if (tempValue <= 176) lcd.write(byte(3));
    else if (tempValue <= 192) lcd.write(byte(4));
    else if (tempValue <= 208) lcd.write(byte(5));
    else if (tempValue <= 224) lcd.write(byte(6));
    else if (tempValue <= 240) lcd.write(byte(7));
    else lcd.write(byte(8));
  }
  lcd.setCursor(14, 0);
  lcd.print("  ");
  lcd.setCursor(14, 0);
  lcd.print(smooth);
  lcd.setCursor(13, 1);
  lcd.print("   ");
  lcd.setCursor(13, 1);
  lcd.print(loopTime);

Benik3:
Is there any way to display the value but have also still fast loop?

Yes. Do the LCD updates in a smarter way so you write to the display less often.
For example, one simple thing would be to track the last spectrum values and if it is the same, then there is no need to update the display.
Same is true for other values/things being displayed.
The less you update the display the faster your loop will be.
And keep in mind that clear() and home() are quite slow and should be avoided if possible.
For example, in many cases it can be faster to write spaces to the entire display than to call clear().
But the best thing for speed & efficiency is to never clear the display but merely update the needed portions of the display.

Another technique is to limit how often you update the display. Often it is not necessary to update the display more than a few times per second so you can check in your loop to see if it has been X number of milliseconds before updating the display to limit the display to no more than say 3-4 times per second.
Many of the low cost hd44780 displays have very slow liquid inside them that takes quite a bit of time to rotate. Many in the 50ms range and some are really slow in the 200ms range.
Updating the display more times per second than the display is capable of displaying is wasting time since the display cannot modify the pixels as fast as they are being changed.

Alternatively, or in addition, you could switch to a better/faster LCD library.
The LiquidCrystal library is not very fast particularly the one in IDEs older than the the most recent couple of IDEs.
You could run my hd44780 library using the hd44780_pinIO class.
It is quite a bit faster than the LiquidCrystal library.
It is available in the IDE library manager.
You can read more about it here: GitHub - duinoWitchery/hd44780: Extensible hd44780 LCD library
It is optimized to allow the Arduino to run in parallel during many of the LCD commands.

Then there are these two libraries:
LiquidCrystalFast: LiquidCrystal Arduino Library, using small character LCD modules with Teensy

fm's new LiquidCrystal: https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home

--- bill

Thanks for quick reply!

Well I would like to refresh the display as fast, as possible. But it's true, that refresh it faster then 50 or 100ms is no sense.
Anyway also this will make lag in the loop.

I will check yours library for the LCD and also the others. Thanks so much! :slight_smile:

updating the display less often based on elapsed time will not make additional lag in the loop.
It will reduce it. The key point is that you cannot use delay().
Like I mentioned earlier you must check to see how many milliseconds have passed, and if the threshold has been reached, then the display is updated.

These are some of the things you can start to look at to reduce your loop latency

  • update the display less often based on how much time as passed since the last update
  • avoid using clear() & home()
  • only update when something changes - if the values have not changed there is no need to update the display
  • only update the portions of the display that have changed vs the entire display
  • use a faster library

--- bill

I tested the libs you mentioned.
Even without any other changes, I went from 20ms of loop time to 9ms with yours and with NewLiquidCrystal library (that's only around 5ms more then without display). That's great!

On the other hands, the Liquid crystal fast is even worse - I got around 25ms...

Now I will implement the update only if there is a change and reduce the numbers of the updates.

Thanks again :slight_smile:

Since you have an LCD keypad shield. If you haven't already, you may want to take a look at this thread:
(it is also a sticky)
http://forum.arduino.cc/index.php?topic=96747.0

If you are using my hd44780 library package, hd44780_pinIO will automatically detect the h/w issue and prevent any damage to the Arduino when doing backlight control, as long as you use the hd44780 library backlight API functions vs controlling the backlight control pin yourself.

--- bill

Yes, I'm using keyPad shiled and I know about this problem.
But I don't use brightness control over arduino :slight_smile:

BTW when are you talking about this, I have another problem with this LCD, which I didn't saw anywhere.
I made a thermometer with this display and the display will always start to lost contrast slowly. When I turn of the display and let it settle down, it goes again back to normal.
Did you ever noticed this? Maybe the display is just some bad peace...

Benik3:
Yes, I'm using keyPad shiled and I know about this problem.
But I don't use brightness control over arduino :slight_smile:

You still may want to run the keypad backlight test to see if your h/w has the issue.

BTW when are you talking about this, I have another problem with this LCD, which I didn't saw anywhere.
I made a thermometer with this display and the display will always start to lost contrast slowly. When I turn of the display and let it settle down, it goes again back to normal.
Did you ever noticed this? Maybe the display is just some bad peace...

Is the temperature changing?
The contrast will vary depending on the supply voltage and the temperature.
So when either of those changes, you may have to adjust the contrast potentiometer to compensate.

It happen also on power supply with constant voltage and in room temperature.
It will be probably problem of the display itself, because I have the same second LCD and that one works without problem...

So I want to make the writing only when value changes.
Does the reading from screen is also so slow as writing?
Because now I use one temp variable to write all the values on screen, otherwise I will have to make some array with 10 elements.

Thank you

Benik3:
So I want to make the writing only when value changes.
Does the reading from screen is also so slow as writing?

Reading from the LCD is quite rare.
In fact the only library that I've seen that supports this is my hd44780 library and one other.

Reads from the display are identical timing wise to writes.

It is not necessary to read from the display to tell if the display needs to be updated.
And in fact you really would not want to read from the display to see if it needs to be updated as that is still doing i/o operation to the display.
Which completely defeats the point.
i.e. if you read the display to see if the display is changed, you are actually going to do more i/o to the display than just re-writing.
This is because if the display didn't need updating, your reads are just as much overhead as re-writing it.
And if the display does need updating you doubled your i/o (first the read, then the write)

You must do the detection for updating the display in your code.
It can based on elapsed time or data values changing or a combination of both.

--- bill