fivdi/lcd

Random characters after using LCD during a while

georges6410 opened this issue · 14 comments

Hello,

I've tried using your library, and it works kinda well, but after using it a few minutes, the screen prints random characters.
Here I have :
http://image.noelshack.com/fichiers/2016/10/1457905151-img-20160313-223745.jpg

If I remove the wires to cut off the power, and replug it after : still the characters on the picture.

After a few tests, the characters can be removed, but I can't identify the actions to perform to achieve this.

Could you help ?

Thanks

fivdi commented

Whenever I saw this issue in the past it was related to timing. The lcd code should have waited for the LCD to complete an operation but it wasn't waiting long enough.

To help determine whether this could be a timing issue, please replace lcd.js from your installation with the modified version of lcd.js from this gist. Perhaps the modified version which quadruples the delays will improve things.

If it still doesn't work, please post the code that is causing the error.

fivdi commented

@georges6410 did the modified version of lcd.js with quadrupled delays resolve the issue?

It seems that the modified version doesn't resolve the issue.

I'll post here tonight the complete code, but I do this :

lcdScreen.clear(function() {
lcdScreen.print(theMessage);
});

Edit : it seems to be working finally. Don't know why the other day it wasn't working, but for now it works great.

So, I guess we can say it's closed and solved.

fivdi commented

If the following code is executed twice in quick succession there may be issues. The clear and print methods are both asynchronous. If the second call to clear occurs before the first call to print has completed the behavior is undefined.

lcdScreen.clear(function() {
  lcdScreen.print(theMessage);
});
fivdi commented

@georges6410 I'd like to try and reproduce the issue. Can you tell me which platform (Pi, BeagleBone, ...), operating system, and version of Node.js is being used?

fivdi commented

It's possible to reproduce the issue with the following code on a Raspberry Pi 1 Model B with Node.js v5.5 in less than a minute:

'use strict';

var Lcd = require('../lcd'),
  lcd = new Lcd({rs: 23, e: 24, data: [17, 18, 22, 27], cols: 20, rows: 4});

lcd.on('ready', function () {
  setInterval(function () {
    lcd.clear(function () {
      lcd.print(new Array(8).join('0123456789'));
    });
  }, 80);
});

Because both clear and print are asynchronous and because the program doesn't wait for print to complete execution before calling clear again everything can get very messed up. The lcd package doesn't have any internal mechanisms for preventing this from occurring.

I had the exact same problem, and it seems that this gist solved it. I created a fork to integrate it and to be able to use it as a dependency with npm.
@fivdi: don't you consider using it on master as the main code? It would help with reliability and using the library with proper npm versions.
Thanks

PS: The library is great btw 👍

fivdi commented

@roland-vachter I think the gist is more of a workaround or hack than a solution. It may work in some scenarios but not in others. I think the real problems is that asynchronous operations that are run "concurrently" are interfering with each other. Do you have code that can be used to reproduce the problem?

fivdi commented

Putting the asynchronous operations in a queue and running them sequentially rather than allowing them to run in parallel would be better.

The problem on my side appeared after running the code for a longer time, updating the display each minute. It was a simple clear -> setCursor to first line -> print -> setCursor to second line -> print.

let printLcd = (data) => {
    lcd.clear(() => {
        lcd.home(() => {
            lcd.setCursor(0, 0);
            setTimeout(() => {
                lcd.print('I: '+
                    ("     " + data.inside.temperature.toFixed(1)).slice(-5) + 'C  ' +
                    ("   " + data.inside.humidity).slice(-3) + '%',
                    () => {
                        lcd.setCursor(0, 1);
                        setTimeout(() => {
                            lcd.print('O: '+
                            ("     " + data.outside.temperature.toFixed(1)).slice(-5) + 'C  ' +
                            ("   " + data.outside.humidity).slice(-3) + '%');
                        }, 50);
                    }
                );
            }, 50);
        });
    });
};

I have the raspberry PI 2.

Now with this gist it runs for almost a day without issue.
There are libraries which access the GPIO in another way than onoff does, synchronously (https://www.npmjs.com/package/rpio), this might be a good solution avoiding conflicting async operations.

fivdi commented

@roland-vachter The above code will function correctly if printLcd is really only called once per minute. However, if printLcd called twice in quick succession it is highly likely that there will be issues. The clear, home, and print methods are asynchronous. It's therefore possible to call printLcd for a second time before a previous call to printLcd has completed. This is very likely to happen with heating-control-rpi. printLcd is called here when ambientalConditions change. The ambientalConditions can change when the outsideConditions or insideContitions change. The outsideConditions are updated every 60 seconds and the insideConditions are updated every 60 seconds. It's highly likely that the outsideConditions and the insideConditions will be updated at more or less the same time an that printLcd is called for a second time before the first call has completed.

Now with this gist it runs for almost a day without issue.

This may be the case but it's not a good solution.

There are libraries which access the GPIO in another way than onoff does, synchronously (https://www.npmjs.com/package/rpio), this might be a good solution avoiding conflicting async operations.

Internally the lcd package only uses synchronous onoff methods. The clear and home methods are asynchronous because it's essential to wait 1.52 milliseconds for a HD44780 LCD module to clear the display or move the cursor to the home position before asking the display to do anything else. The print method is asynchronous because it was designed that way. As far as I remember, it takes approximately 30 milliseconds to write 80 characters to an LCD display synchronously with onoff on a raspberry Pi 1 Model B. Blocking the CPU for 30 milliseconds is a long time, so the print method is asynchronous. It write the characters to the LCD one by one and returns to the Node.js event loop after writing each character.

fivdi commented

@georges6410 @roland-vachter lcd v1.1.3 has just been published on npm. lcd now queues asynchronous operations and executes them sequentially. It should resolve the issues that you were seeing.

That's a really good news! Thank you, I will give it a try once I get home.

fivdi commented

As mentioned above the lcd package now queues asynchronous operations and executes them sequentially. This prevents the asynchronous operations from stepping on each other and messing things up. Note that the print, clear, and home operations are still asynchronous.

Thanks for reporting this issue.