Project status.
It works.
Feb 2010,
This page follow on from work I did last year, see - driving a ((Nokia colour LCD in SAM7 FORTH)).
I won't be repeating the general overview I wrote there so take a look at it first.
Overview.
This project is a kind of graphical controller which can display sensor information obtained via a TWI network and control devices via the same TWI.
It is a homebrew "shield" for an Atmel AVR mega328 based arduino pro.
The nokia style LCD is a nice cheap colour display but has a few things that make it a pain to use in DIY projects.
One of those things is the connector.
That #$%^% connector.
The PCB connector is 0.5mm pitch and almost impossible to solder wires to.
The SF part is http://www.sparkfun.com/commerce/product_info.php?products_id=570
One very important thing to note is that the numbering on the LCD is reversed to that commonly used in tutorials etc.
I've almost certainly killed one display because I assumed they were the same. If your LED supply pins aren't the at the corner furthest from the centre of the display - check again.
Attempt one.
I did manage to solder wire wrap wire to the pins after a lot of trouble. I tinned the connector and wire then sweated it together. It is difficult to get enough heat into the join with a dry iron and having solder on the iron will most like cause a solder bridge. I've since obtained finer solder wire and solder paste - this could help a lot. I also haven't been too impressed by fine tipped soldering tips - the heat doesn't seem to get to the point.
Anyway I got the wires on but the heat didn't do the plastic housing much good and the connector pins came loose.
Attempt two.
Much the same result.
Attempt three.
I took single strands of wire from multi stranded wire and soldered them across two pins at a time then cut out the unwanted wire with a stanley knife. I then slipped insulation stripped from wire warp wire over the wires.
I also covered it with nail polish to secure the wires more.
This connector seemed to work but didn't stand up to having the LCD swapped as I needed to do for this early prototyping.
Attempt four.
Instead of using the pads on the breakout to solder the connector to I used the tracks.
The tracks were cut with a dremel and the solder mask sanded off with fine sandpaper then tinned with ordinary solder.
I soldered the socket in place with solder paste and reflowed it using a hot air gun on the underside. I had a lot of trouble and could have done a better job with rosin core. I'm fairly new to solder paste as I usually use ordinary solder and rework flux for my SM work.
The socket does work but isn't %100 reliable. I'm inclined the think the problem is with the contacts and not the soldering. It works well enough to do my software but still needs improvement.
Circuit.
Note that this PCB is untested.
This is my first board in Eagle. I'm a long term user of protel/altium but want to use something free or open for my personal work.
The PCB is a shield for an arduino pro and is mainly just the LCD and a SF trackball module. Note that these two devices use most of the mega's i/o pin. This could be a problem for some applications but I don't need any extra i/o apart from TWI. I've kept the serial lines uncommitted and there are still a couple of other uncommitted i/o pins.
With almost all of the i/o pins used for the display and trackball there is little advantage in keeping the auduino pro pinout. There is enough room to put the mega328 on the same PCB as the LCD and get rid of one PCB and all those connectors and pins.
On the other hand others may want to use it on a USB-arduino and use the FTDI/USb/serial interface.
Eagle files are here.
ARD-LCD-TB-1.2.zip
You can also order this PCB here http://batchpcb.com/index.php/Products/28792
Note this is the batchPCB price - I don't make a cent.
LED back light.
The LCD back light consist of two white LEDs in series. It is fairly common to use a voltage booster to boost the 3 or 5 volts supply to 7 volts or so to drive the LEDS. In my case regulating 12V down to 5V and boosting would be silly. Boosting then limiting with resistors as some people do is even sillier. I use a LM317 adjustable regulator in a current regulation mode to put 40mA or so through the LEDs.
If voltage boost was required I'd be inclined to use an i/o pin to pulse a MOSFET to drive a inductive booster. I see no need for a closed loop switching voltage regulator. I'd definitely fuse it though because jamming the switch on would make smoke somewhere.
A software driven booster has the advantage of few parts and having software control over brightness.
Level shifting.
My AVR is 5 volt. I choose to make my system 5V to get the extra clock speed. The module is part of a network which uses a 5V TWI bus.
On a 3V3 system interfacing is trivial.
I've read the displays are not 5 volt tolerant. There are variants of the display so who knows if they are all the same in that regard. I've chosen to use a simple voltage divider to reduce my 5 volts logic signals to around 3V3.
So far this is working but at higher bits rates this may not be good enough. My dividers have a resistance of around 1 Kohm.
If you have a good stiff 3.3 volt supply powering the LCD you may be able to get away with just having current limiting resistors. The input pin's protection diodes *should* clamp the voltage to a safe level.
In my case the supply voltage could be pulled too high through the diodes. This would happen when the LCD is in a low power mode and the supply is unloaded.
Controller - what controller?
One of the big negatives of these displays is they come with more than one type of controller. The two main types are Philips and Epson (or clones?). The Philips usually have brown connectors an Epson have green.
The some commands for the two types are different - particularly the initialisation commands. Different versions of controllers also have variations. Code I found online needed modified for both types of controller.
For example James Lynch's code needed to be modified to work of my Philips type display. I've had a similar issue with Epson controllers.
The Philips controllers allow the controller ID to be read out but I've been unable to do so - presumably the serial out pin hasn't been connected on the displays I have.
Coding.
With two main types of controller and variants of each type writting code for these displays is a pain. Not only do the data formats change but also the contrast setting need to be adjusted for individual displays.
When I wrote my FORTH code last year for the epson based LCD I had to figure out what the new formats were because it was different to the published data.
The same thing happen now with the Philips based LCD. The code written by James Lynch did not work properly.
I trust his code did work on the display he had but the new version is different.
I had to change some of the initialisation code and the data format for 12 bit per pixel mode now needs four bits of padding. You now have to send 16 bits per pixel. This make the code easier but makes the display update even slower.
Unless you have a need for a lot of cheap displays you really should consider a more expensive display with a more stable controller.
It should be possible to write a single code base which can either be conditionally compiled for the various controllers or code which can select different controller at runtime.
For my AVR based projects the controller type and other parameters such as contrast could be stored in EEPROM.
To make life even more difficult many examples on the web need particular compilers. My code is for winAVR GCC.
The main changes that I needed to make were to rewrite the I/O port code. Another trap is GCC moves constants to RAM unless told otherwise. Before I worked that out character generators cause the cause my program to crash.
We also lack a standard for defining the constants used by the controllers (ie commands) - I've added to this by remaining all the commands that are used by both types so the they are unique.
We had identical names for constant which have different values for the different controllers - this is asking for trouble.
Everybody seems to generate the serial signals differently. Being a non-standard 9 bit format the AVR hardware can't generate it properly. Some bit bang the lines using assembler, James bitbangs the first bit then uses the SPI hardware. I currently bitbang in "C" but may change that later.
The SPI sends two types of data. It sends commands and it sends parameters (AKA data). Some programmer have seperate "senddata" "sendcommand" function while others use a single "send" function and pass a mode to it.
There is no right or wrong way to do this stuff - there is no clear winner at this point.
The old controllers used 12bits/pixel in the 12bit/pixel mode - the new ones seem to use 16.
For the old ones it made sense to process two bits at the time and send 3 bytes - so you will find some convoluted code for doing this. The new way is simpler but need more serial bandwidth.
I made a few little tweaks. Most lines I draw are horizontal or vertical so I treat these as special cases. For any line of more than a few pixels it is faster to draw them as a narrow filled rectangle.
Unfilled rectangles are drawn as four lines so the rectangle code is now recursive. If it is asked to draw an unfilled box in calls itself four times will the parameters to draw four one pixel wide filled boxes which make up the box outline.
The code will be available for people's amusement but the longer I wait to post it the more complete it will be. If you need a copy sooner let me know.
March 13,
Hackaday just published a digital picture frame project (link below) using the same display (looks like the Philips type). They mention the 2 pixel 3 byte format is still possible.
Personally I've been thinking the opposite - buy a cheap photo-frame and hack it for the display.
March 22,
The menu code I'm working on has it's own page - micro menu.
March 25,
Spark fun have released a colour shield for the arduino. It has no trackball, a few switches and uses a voltage booster.
April 2,
Over time I will be making major changes to the high level function names.
Looking ahead I want code calling these functions to be reusable for other devices.
For example the function name LCDSetRect() makes sense if LCD is all I will ever do.
On the other hand when I want to change to use OLED or some other display type I won't be able to reuse the application code which uses the LCD module without either calling my OLED rectangle draw routine LCDSetRect() as well or changing all the calls to it to be OLEDSetRect() or whatever I want to call the new one.
It may be possible to use #define to create alias but I think makes sense to me to use more generic function names.
So for starters LCDSetRect() has been renamed to ScreentRect().
If all the higher functions like LCDSetLine(),LCDSetPixel() and LCDPutStr() are given generic names and have the same parameters - porting applications to different devices will be a lot easier.
I've also made the LCD,Trackball and Menu code more modular.
The same logic applies to the trackball functions which will become generic HIDxxxx name.
HID being human interface device.
This will make changing from trackball to some other similar input device simple as well.
This won't work for something radically different like a touchscreen.
LCD,OLED and other bitmap orientated displays should be fairly compatible.
Trackball, joystick and switches can easily be made the HID for my projects.
April 8'th.
PCBs arrived today and after a couple of minor mods I have one working.
Eagle files are now online - see "circuit" section above.
April 9'th.
I built a second one using an epson based LCD. The hardware worked without any problems.
I had the modify my code to work with the controller. My code can now be conditionally compiled for either epson or philips controller. The epson display seems to have a slightly better image.
The epson uses a 3 Bytes for 2 pixel format so it will be a little faster to update.
April 25'th.
It is time to move on. I did a bit more work on the GUI which I'll report on the micro menu page. In nut shell I can now flip thorough the (four) display pages with a sideways roll of the track ball and also put in into a "slide show" mode where they change automatically. I've also added some data-logging and log display code as seen in the photo above.
Conclusion.
I'm happy with the way the project turned out. This particular project is totally useless to almost everybody else but shows that a $15 display and a $5 micro can do useful work. With only 32K or flash and 2K of RAM - resources are limited. A modern PC might have one million times the RAM - not a totally fair comparison but you get the idea.
I did everything I wanted with 4K of flash to spare and almost half the RAM unused.
Using a trackball is fun but switches would work fine for a budget human interface.
I couldn't find a source for low cost micro-joysticks but they must be out there somewhere.
The olimex SAM7ex-256 boards has one. I've seen them on cameras and phones.
The mega328 only has 7 I/O lines spare after the display and trackball are connected. This is no problem for me but might be a bit light on for some control protects. The code could easily be ported to a large AVR.
I used the SPI pins for the SPI connection to the LCD. Seeing I'm not actually using the SPI controller it may be better to use different pins and keep the SPI available for other devices. Usually SPI devices also have a select pin so they should able to share the SPI pins with the LCD anyway.
The LCD code is totally written in C. I was planning to speed it up by adding SPI code written in assembler but it doesn't seem necessary.
I'd like to see my display code used for other projects, either mine or other peoples. I'm in no hurry to put the source online as it is still a work in progress.
The menu and trackball code will be available as CC or JPL, if you need it sooner ask.
Maybe someone would like to port it to the arduino IDE?
Links.
http://hackaday.com/2009/01/08/how-to-digital-picture-frame-100-diy/
SF colour shield http://www.sparkfun.com/commerce/product_info.php?products_id=9363