Close

20x4 displays tested, nested app folders and HW/SW plans

A project log for pyLCI - Linux Control Interface

Makes Raspberry Pi accessible, portable and easily configurable.

aryaArya 04/07/2016 at 20:440 Comments

Starting another work session now. Ain't got much time, about 6-7 hours, and I don't feel all that energetic, but I hope I stil accomplish things today.

One more usage for my system. I wrote a simple script using curl to login to my university wireless network, and it only took me 2 minutes to hook it to pyLCI. It could be better written in Python, with HTML parsing and all that, but it's still very good. Actually, sounds like one more small universal utility to be made =) I guess there could be use for a "Ping/DNS check application"

So, I received a 20x4 HD44780 display and adjusted the config.json "output"."kwargs" to say "rows":4 and "cols":20. And guess what? It worked right away, with both Menu and Printer UI elements!

I have to say though, I might need to optimise HD44780 library to avoid re-drawing the screen each time I scroll down in a menu - it's very noticeable on a 20x4. The library certainly needs to store the output data somewhere and do char-to-char comparisons. Overall, there's still a healthy chunk of things to optimise in hd44780.py, and, thankfully, it can be done without breaking the interface.

I also need to add output.type=["char"] definition in all current display objects. Forward compatibility, you know =) There's also a necessity to automatically turn off the backlight after the screen hasn't been updated for a while. Just one more simple thread and one flag to be added and it'll mostly sleep all the time, hardly impacting performance at all but heavily impacting power usage. Oh, I'd also probably need to check whether sending a noDisplay command impacts power consumption. I run things from batteries, after all.

Main menu system needs improvement. It's not nested, there's yet no way to categorize elements and it already makes hell of a clutter. I'm talking about re-making the main menu alike to menus like this:

|Main menu
|-System apps
|--System info app
|--Shutdown&reboot app
|-Media apps
|--MOCP control app
|--Volume control app
|-Electronics
|--I2C toolkit app
|--EEPROM read/write app
|-Networking apps
|--Bluetooth app
|--Wireless app
|--Network interface app

I'd be damned if those folders weren't infinitely nestable and would require a configuration file, and I've figured it out - it could easily use __init__.py in a clever way. I could even specify how to order apps in a menu using same __init__.py! It's a problem right now because, well, they are ordered chaotically. When you think about it, any order of applications other than "user-preferred" is to be perceived as chaotic.


That's the first thing to start with. Other priorities:

First of all, I've got an unfinished "System info" application, I worked on it yesterday. It's already shipped with pyLCI and can show you uptime, loadavg and memory stats both for x86 and ARM Linux systems. It can detect if it's run on RPi too - I plan to make some custom menu entries concerning Raspberry Pi-exclusive features =)

Second thing is eliminating and debugging all kinds of LCD redraw problems. When the display is re-drawn too often, it might start showing garbage, either recovering in a couple more refreshes or never recovering. AFAIK it might miss/misdetect a nibble once in a while and fuck the "byte-by-4-bits" part up completely, it might be a race condition between threads... There's plenty of things to test.

I also found a 24x2 display at home. Surprisingly though, it doesn't work with pyLCI. It doesn't even show anything, it's just stuck at "first line filled with white blocks" part when I init it, even when launching a driver directly. That's quite a problem, this display is cool - especially given it's a piece of hardware excellent for testing for some well-hidden bugs. I'll try to wire it to a different I2C expander now, as a start to my tinkering sesson. If it won't work, I'll put it away for a while until I can research it further.

So, I'll start working. First, the display...


Nah. It shows a couple of blocks, but that, maybe the pinout is not right? Or, maybe the RS line is inverted. I have this feeling because, well, it shows 3 zeros and it gets sent 0000;0011 three times during the init sequence - but as a command. Seriously, look at it once again!

...Nah. Didn't do shit. I guess I need to make a "display testing stand" for displays like this one, which would use 8-bit and 4-bit modes, try to read busy flags and so on. Maybe it'd be possible to swap data lines, use different headers and header pinouts, negative voltages for backlight... Wonder if it'd pay off.
Hmm, zeros... Maybe it cannot into 4-bit? But still, fail. Moving on...

Fail. I'm getting distracted by the display, it still feels like a challenge =D

Screw this display...

...Okay. I went as far as to have detection of arbitrarily nested subdirs and modules in them, except for subdirs nested in the module dirs - it doesn't make sense to use them. See, every subdir of "./apps" represents a Menu object, and, as a subdir can contain both other subdirs and module dirs, its contents are either calls to Menu objects created by subdirs or application callbacks. I yet have no idea how to make it so that it's logical and expandable. Maybe return something like contents of os.walk? Sounds good, and, hey, Python devs didn't have this function with such weird output just for fun, there's definitely something to learn from it.

Aaaand... Done. Made it "walk". Now just let me test it with subdirs...

('./apps/ee_apps/ee_apps', [], ['i2ctools'])
('./apps/ee_apps', ['ee_apps'], ['i2ctools'])
('./apps/media_apps', [], ['mocp', 'volume'])
('./apps/system_apps', [], ['system', 'shutdown'])
('./apps/network_apps', [], ['network', 'wpa_cli'])
('./apps', ['ee_apps', 'media_apps', 'system_apps', 'network_apps'], ['test', 'skeleton'])

Yep, it behaves like os.walk, only that I omit anything that's not a module or a subdir. Now, let's see if my intuition is right about telling me that behaving like os.walk is the best solution...

Also, I have success making apps to load with this technique =) Creating menus is a problem, though. I need to think it through better...

And done. Behaving like os.walk was *the* best way, indeed. I needed to iterate over app_walk output once, then over all the detected subdirs to build a tree of them and them over all the apps to link them to correct subdirs. That's overhead of looping through things 3 times, yeah, but I think it can be avoided if necessary - and it happens only once, at system launch, and hasn't slowed down things any significantly. Single-app mode is working - moreover, it's working with paths, and shell autocomplete! And, yeah, arbitrarily nested folders, of course.

Only thing left before merging this in the main branch is documenting all of the added stuff, making sure nothing's overlooked and generally making this exception-less.

I have an idea for adding hardware. I could just add support for many GPIO-based LCD&button shields, as well as some I2C-based, test the code (adding mockups with I2C) and release it as "supported&untested", then talk through the issues with all the people that have those shields and decide to use them. GPIO is, well, easy to map for different things, so as long as I have one tested GPIO setup, I basically have them all supported - but unless I list GPIO-based shields as "supported", nobody's gonna think about it. Also, I got an MCP23017 coming my way - in case of modules using that, which is plenty of them, I can easily make a breadboard circuit and it'll be no different from the hardware. Then, I can just wait until I have more hardware =) I have 3 different Pis sporting my interface right now, and it's very good so far, but obviously not enough for the "hardware support" page.


PiFaceCAD module needs a rewrite. It's got its own library with its own quirks, and it's one more thing to think about - which ain't so great considering it's, once again, just an MCP23017 on a shield, nothing special. The library will need to be scanned for workarounds for problems discovered by whoever made the library, though, I won't discard such a source of knowledge =) As for now, though, it's not a priority as long as it works correctly.

With that in mind, I'll take a short break for the weekend. As soon as I finish my "system info" app and document all the changes I've made =) I hope it won't be another build log that's stretched over two or three days, like this one - not that it's a bad thing, I just don't have that much time.

Discussions