-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using libpifacecad sometimes corrupts LCD display #1
Comments
My first thoughts were that this could be a timing issue. However I managed to get up to 400+ runs without any screen corruption. Perhaps you have less tolerant hardware? Have you tried increasing the delays in |
Increasing DELAY_SETTLE_NS does seem to fix the problem. Multiplying your value by 10 was not enough, but after multiplying by 100, I could no longer get the screen to corrupt. |
Does it impact the speed of your program, greatly? I want to change I'm going to leave the header file as is for now but leave this issue open to see if any more people have similar issues within the week. |
I have the same issue here furthermore I experience display brightness flickering during write access. This is Independent from the power supply. Tested with 2A5V as well as 1A5V, behaviour seems a bit unstable when accessing the CAD Modul using libpifacecad code. By the way example Code for the button read using an event driven mechanism in c++ would be nice. Some further insight would be nice |
@xpeace Does increasing the settle delay not fix your issue? What about the Python modules? Can you upload an video of the problem to YouTube or something? This is difficult to test since libpifacecad works on all of our boards. Event driven mechanisms will require using epoll to monitor events on GPIO pin 25 which is where the interrupt pin is connected to. I'm completely snowed under with work at the moment so I can't implement this myself (at the moment) but it should be possible to do with a bit of reading. |
Things that seem to have increased stability (I can't reproduce it any more):
|
Looks like a race condition, I had two threads trying to access the unit, resulting in a messed up display, currently its working again, also reset to default 40µs timing delay, OS: Raspbian Wheezy |
I am having exactly the same issue. I am getting corrupt text on the lcd after a seemingly random amount of time. |
I was likewise seeing corruption that would scroll from right to left after a seemingly random amount of time (though always within 30s of running my app). I have since reset the OC setting with raspi-config and it is now stable. My sequence of calls was: open, blink off, cursor off and once per second in a loop: clear, write (6-8 chars), set cursor, write (6-8 chars), and either backlight on or off. ANYTIME I tried to set position to the first row (0) with my system overclocked the entire display would instantly go blank. If I just let the text lay out or used a newline in the first write to move the second write to the second line without setting position the display would work for quite some time before garbage characters would scroll in from the right and move one position every loop. In all cases the backlight control still worked as expected based off of calculated values that I was supposed to be displaying. |
And right as I posted, the screen went all wonky. As soon as I get my pi shutdown and get code copied over I'll post a pastebin of my app source. Edit: linky: http://pastebin.com/9MLt26TP |
I referenced this issue on the pifacecad python page. Looking over the code pastebin, the problem is exactly the same as I had. This problem now seems clear at a high level to me. When there are 2 concurrent lcd writes (with no barrier between the instructions), the display will become garbled. In the code sample above, when the loop is executing quickly, 2 writes can happen at the same time. The reason can be that fscanf and fopen will soon be read quickly from a page cache. I first noted this when I was updating the display every second. The solution for my app was make all writes to the display from one method. I added a lock to that method so that only one write can occur at a time (in C, you can likely use a posix semaphore). The garbled text issue then subsided. However, I also wonder why the piface should have garbled text in the first place when concurrent writes are performed. Can that be better handled at a lower level? |
In the above loop, I now wonder if the compiler is optimizing the instructions so that the sleep call is not executed as often. Curious to see the assembly :) |
@tompreston - no, my pi is not overclocked. @sshivaji - i am not doing concurrent writes. my application is single threaded and i write to the screen once a second from a single subroutine. i am not using python, so we can rule that out being at fault. |
All other implementations on the web of the hd44780 I`ve seen use an additional LCDBusy check before writing, not just rely on timings. Maybe this would contribute to overclocking stability issues as well. |
@dch26 python or not, the issue is the same. Can you confirm via assembly or the low level trace that it indeed happens once a second, the compiler could be optimizing away your code. Try putting a lock on every write and a small sleep to ensure that nothing else is happening during a write and see if that solves your problem. @xpeace reading and writing at the same time could be the problem as well. I will test for that. If the hd44780 uses an LCD busy check, there is definitely an issue at the driver level. |
For what it's worth I had this issue with python as well. Ended up writing a class than would enqueue writes and issue them serially. Sent from my mobile device. All spelling errors are it's fault.
|
@xpeace Briefly read over the writing to the LCD implementation for both the C and the python versions of pifacecad. A sleep is used instead of checking for the busy bit. The reference guide for hd44780 suggests that the busy bit (bit number 7) can/should be checked before performing a write. Did you attempt a patch already? Changing the sleep to a busy bit check and wait for ack will probably solve the issue at a lower level. @tompreston I probably want to patch this soon. Would you agree that this is the right approach? |
Checking for the busy bit looks like the correct approach. Are you able to patch it since I have a few other projects to handle? I can squeeze it in sometime this week, if you can't. |
Scratch that, I've patched it. Can someone test the version in the |
Thanks for the quick patch! I personally can't extensively test the C version. I can do that on the python version (pifacecad tree) after applying your logic changes, and will report if it works. |
I'll be able to test the patch in 2 days. Will keep in touch. |
In function
reverted to previous version ... works "normal" |
@xpeace I'm no longer calling |
I dont`t know what happened I got inconsistent code, before. I am getting deadlocked in the busy loop frequently (if i reset cursor and write a second time to line 0). I disabled all threads - just plain serial calls- but I already get stuck during my app start (only serial calls here) pifacecad_lcd_cursor_off(); pifacecad_lcd_send_command // removed busybit wait -> App did not lockup any more but text has been completely messed up again, ... |
Branch dev_tp is working great for me so far; this is the longest it has remained stable. I'm going to leave it running overnight and will report back if there end up being any issues. Thanks for the fix! (I was really worried I might have to cross over to the python world to get some basic stuff set up right off the bat!) |
@xpeace Do you have an example program I can try running on my CAD that will break it? All my tests seem to work for me. |
The tp_dev branch is working quite well for me too. I tried http://pastebin.com/9MLt26TP with master and every second run or so lead to a garbled display. 20+ runs under tp_dev were not able to garble the display! Will try to port this fix over to the python this week. More complex than it appears at first with the clock pulse, and register setting especially if you don't do embedded programming. |
It is really hard to manage different threads that write to the LCD, Clear the LCD and Polling the Button states every x milliseconds.at the same time, ... For thread access control I use one global mutex object ...
This seems to work nicely. By the way can I read access the Buttons while writing to the LCD ? I managed to get the PI completely locked up by calling the CAD functions, even no more remote access via ssh was possible (but I think this was before i was shure of having all Mutexes in place) For the latest branch - I needed to comment out one of the busy bit checks - then the busycode worked reliable for me as well.
setCursor to new line fails when I do not remove that check (will loop in busy check eternally) -> Also See the other Issue: 16 Digits and Linebreak with Pifacecad cmd program and tp_branch and I get stuck on busy loop at the newline (setcursor code) position (tho I thought internal memory size is valid for 40 chars per line, one could decrease the 80 bytes in the Header to 40 for testing , ...) Is it normal that the backlight does flicker when executing eg. an LCD clear command or closing the connection with backlight still on ? I`m not sure if this is a kind of feature or Network / Audio related, ... |
Multiplying settle_ns by 100 seem to make it relatively stable for me so far. My Configuration: latest debian wheezy for Pi, all updates, Pi Firmware 02.02.2014 without multiplying the settle_ns I still get corrupt ascii displayed |
i took the dev_tp code and compiled it. |
Sorry about the long delay! I've added support for interrupts and hopefully fixed the bug in |
I have just pulled dev_tp and tested it. The "while(is_busy()); // wait until not busy" works - no more corruptions with "showTimingError" with any delay setting between 0 us and 1520 us (see previous post today). Also "pifacecad_lcd_display_off();" works with 0 delay after "pifacecad_lcd_clear();" which never worked before. I measured the execution time of the new routine "is_busy()" with getimeofday(). This showed that "is_busy()" actually takes 860 us +- 30 us to execute. This slows down the transfer of data in "pifacecad_lcd_send_data()" significantly. The only instance where "while(is_busy());" looped twice was after the "pifacecad_lcd_clear()" command, which confirms that this command actually executes in somewhere between 1720 us and 2580 us, which is slightly more than I measured with "showTimingError" above. Because of the slow execution time of "is_busy()" i feel it would be better to patch "pifacecad_lcd_clear(): as follows
"pifacecad_lcd_home() could be patched the same way to satisfy the HITACHI spec for this command. All other commands only take 37 us according to the HITACHI spec, which is taken care of by the 40 us delay after every "pifacecad_lcd_send_byte()" call in pifacecad.c in the original and new implementation. Therefore no other busy waits are necessary. More tests will confirm whether this is safe. |
I have now managed to create a "gist" https://gist.github.com/JohnWulff/29f216a7d79d09807712 containing the two files mentioned in the previous 2 posts. showTimingError.c is the 2nd file in the gist (although I entered it first) It shows consistent corruptions if called with delays between 100 and 750 us when linked with the master branch of libpifacecad. When linked with the dev_tp branch of libpifacecad it shows no corruptions. The 1st file in the gist is pifacecad_dev_tp_measure_busy.c, which is a patched version of src/pifacecad.c and should replace that file temporarily to build libpifacecad.a. When exercised with showTimingError linked with this version of libpifacecad.a (and -lm the math library) it shows execution times of is_busy() and how many times it repeats in the while loop (which it does only after libpiface_lcd_clear() calls like so: texts[5] "texts[5]"; clear + 0 ns # 0x01 is the 'Clear display command' This also shows that there is a 870 us busy wait after every character transferred to the display, which should be avoided. |
I managed to run your tests last week and I can confirm that the problem exists as you describe. Unfortunately, with constant deadlines and being between houses at the moment I just don't have the time to spare to patch in the fix (which also has to be included into the LCDproc patch) and get in touch with SparkFun about the error in the datasheet. Since the delay's are constant, I think you're right in suggesting that we can just program them in rather than waiting for the busy line. I'd be more than happy to merge a pull-request into my dev branch, if you/anyone feels like making the changes yourself. If not, the changes will have to wait until I get a spare moment. I've not forgotten about this, I just can't prioritise it at the moment! |
pull-request from https://github.com/JohnWulff/libpifacecad/ to implement the above suggestions add 2.6 ms delay to piface_lcd_clear() and piface_lcd_home()
change SEQOP_ON to SEQOP_OFF in piface_open_noinit() These values set bit 5 of the IOCON register in the MCP23S17 I/O Expander. Setting this bit to 0 (SEQOP_ON) enables address pointer increments in the MCP23S17. I do not think this is ever used (especially with BANK_OFF). Every command to the MCP23S17 sets a new address. The auto-incrementing of text byte transfers in the HD44780U is handled somewhere else. |
I wrote the following for the "man page" of my application program iCpiFace, which handles direct input/output for the "immediate C" system from up to 8 PiFace/PiFaceCAD units connected to a Raspberry Pi either plugged in directly or via one or more PiRacks. This helped me to clarify the action of the software on the many different components, which have to be considered. TECHNICAL BACKGROUND
For the PiFaceCad there are two additional paths from the Raspberry Pi to consider:
|
I've merged your pull request. This bug should now be closed! Thank you John and everyone else for all your input. |
I am working a program that makes use of libpifacecad to manipulate my PiFace CAD. I am using the library's pifacecad_open, pifacecad_lcd_backlight_on, pifacecad_lcd_clear, piface_lcd_write, and piface_lcd_close functions. Rather often, the display of the PiFace CAD shows a corrupt string of characters.
I wrote a simple test program containing:
int main(void)
{
pifacecad_open();
pifacecad_lcd_backlight_on();
pifacecad_lcd_clear();
pifacecad_lcd_write("Hello, World!");
pifacecad_close();
}
I have found that even this program corrupts the screen, although much more rarely than my larger program. For example, once I saw a corrupt screen after the 43rd run. Other times, I see the corrupt screen every 20 or so runs. I run these tests with the following, where a.out is the program above:
c=0; while true; do ./a.out; c=$((c + 1)); echo $c; read; done
The text was updated successfully, but these errors were encountered: