chipKIT® Development Platform

Inspired by Arduino™

Serial vs Parallel LCD display for speed and efficency

Created Mon, 27 Feb 2012 22:06:02 +0000 by IGGYWOOWOO


IGGYWOOWOO

Mon, 27 Feb 2012 22:06:02 +0000

I am in the process of adding fuel injection to my 1983 Craftsman riding mower as a first time Arduino project. I am currently using an Arduino Uno R3, but I just discovered the chipKIT UNO32 and purchased one of those as well. I have the lawnmower running, but I run into problems when the RPMs get over 2500. I am running a 4x20 Scott Edwards serial LCD @ 9600 baud to display things like RPM, TPS%, and inject pulse width. The display is being updated every 500 milliseconds. I put 4 magnets on my daughter's top and spun it hard to simulate the flywheel spinning. I noticed that there was a delay in the injector clicking every time the LCD updated. I also know that parallel data should be faster too.

Would it benefit me to switch to a parallel display for speed? I am also considering throwing my UNO32 in instead of my UNO R3 to speed things up as well.

Your thoughts on this would be appreciated,

Brandon


Ryan K

Thu, 01 Mar 2012 23:03:30 +0000

Hello Brandon,

Hmm, well a 2 Hz refresh rate is pretty slow. But as to what you are saying you are saying that you refresh every time the injector clicks and then you refresh the display and that there is a noticeable lag from the refresh? I would recommend using the chipkit uno because of the faster instruction clock. I expect that you should see a speed increase from using the chipkit Uno.

You should be able to get a faster transmission rate with the parallel display (limited to whatever the hold time of the device is) but it doesn't seem like it should be necessary. With 9600 baud and 8 bits per character(not sure if this is correct for your device I'm just assuming) and 80 characters per display that will put you at around ~67 ms. If you want it to go faster than that you'll need to get a serial LCD that allows a faster baud or a parallel LCD.

Best Regards, Ryan K


JamesDH

Sat, 07 Jul 2012 18:45:41 +0000

Hi Iggy,

As an Electronic Tech and also a BMW tech for 13 years may I suggest that you take a trick out of the early BMW Motronic bag of tricks. On the 6 cylinder engines they would fire the injectors in banks of 3, ie 2 drivers, each firing 3 injectors. I noticed that above about 3000 RPM's they would revert to firing the injectors every 4th revolution instead of every 2nd revolution. Of course the dwell (time the injector is energized) had to be increased to supply enough fuel but they were able to keep up with engine RPM back in the days of slow processors and even slower injectors. Just an idea.

James


majenko

Tue, 10 Jul 2012 09:20:39 +0000

I make it 83.3333ms per full frame of 80 characters.

9600 baud, at 10 symbols per character (8 bit, 1 start, 1 stop), is 960 cps. 80 chars at 960cps = 12 frames per second. 1/12fps = 0.083333333...

12 frames per second is 720 frames per minute. When triggering 4 times per revolution, at 2880rpm the time between each triggering becomes lower than the time it takes to display a frame.

Of course, this is all complete hogwash if you're not displaying the full 80 characters every time, and there will be other overheads I have not taken into account, but you can see how the time taken to display a frame can impact the triggering of the injectors.

What you can do:

  1. Yes, a parallel LCD will give you a shorter display update time.

  2. Slow down the display update. Why update the whole display every time? Why not just one character at a time? Display a character, trigger the injector, display the next character, trigger the injector, etc. Of course, if the RPM is lower than a certain threshold you will want to display more characters at a time, otherwise you will get a display that refreshes incredibly slowly at low RPMs and even stops updating when the engine isn't rotating.

  3. Use interrupts. By using interrupts you can have one task running periodically, either using a timer, or an external signal, whilst doing other things. You could either have the display on an interrupt so it updates every 500ms regardless of what else is happening, or (and this is better) have the injector sensing/control on an interrupt, so that triggers on the flywheel position sensor to activate the injector triggering code. That way the injectors will trigger at the right time regardless of what else (within reason) you are doing.


avenue33

Tue, 10 Jul 2012 13:06:23 +0000

Another option consists on smart LCD displays.

Those LCD displays are called smart because they embed their own MCU in charge of all the screen management, including even touch, SD card and sound.

I've been using the μLCD-32PT(SGC) 3.2” Serial LCD Display Module from 4D Systems. It requires a single standard serial port with speeds up to 115200bps with a chipKIT Uno32.

I've developed a suite of libraries which provides high level commands for:

  • Screen management with touch, SD card read and write, sound
  • GUI with label, button, dialog box, menu, slider
  • Graphics with gauges, histograms, ...
  • For 4D Systems μLCD, μLED and μVGA screens
  • and much more...

Learn more at my :arrow: website, with documentation, tutorial, examples, code and downloads.

The dedicated thread on this forum is :arrow: 4D Systems μLCD-μLED-μVGA Serial LCD Library.


bperrybap

Mon, 12 Nov 2012 06:12:37 +0000

The issue here is not really update rate or data transfer speed to the LCD since the actual needed refresh rate of the LCD is so slow. It is the combination of CPU overhead vs the tolerance of latency/overhead in servicing other things in the system based on the current s/w system design.

Just a guess, but it sounds like everything is being processed at foreground level in loop() That means that as any code is added overhead is inserted, everything slows down because of the added latency because in a simple foreground loop design there is no priority. Insert too much overhead somewhere and things break.

The HardwareSerial code currently does not Q any characters so that means that when sending more than the internal fifo can hold, the CPU is just spinning doing nothing waiting for the bits to be pushed out. Send 30 characters at 9600 baud and you just burned 30ms of time doing nothing useful.

Depending on the overall software design, this may or may not be an issue. If the time critical code was interrupt driven vs running in loop(), then the CPU could spin waiting on serial bits to empty and there would be no impact on the time critical code as it would interrupt the spinning serial code.

Also, if the serial code was interrupt driven then the output data would be Q'd and then immediately return to allow the processor to continue to do useful work while the characters were going out the serial port. Serial interrupts would come in to process the Q'd characters.

Lowering the CPU overhead to send serial characters will create breathing room for other foreground tasks. While moving to a faster interface like parallel will speed to transfer time to the LCD it may not reduce the overall CPU overhead much. That is because the LCD takes time to do things and the LCD libraries out there spin wait to give the LCD time to do the processing. Things like HOME and CLEAR are VERY slow. The LiquidCrystal library supplied with chipkit will spin for 2ms when these commands are issued. So even if all the other other overhead were ZERO, lcd.home() and lcd.clear() would use 2ms of CPU time!

To solve this what needs to be done is to look at things from an overall system point of view. There needs to be clear understanding of how often certain parts of the code need to run to be able to determine if that can be met with the given design and overhead involved with displaying the information.

There are some options:

  • switch to AVR and use Arduino IDE 1.x The AVR core code Q's characters for the serial port and so the CPU overhead for serial transmission will approach zero and not bog down the CPU. Ironically, depending on other factors, an AVR might actually outrun the pic32 for this s/w design.

  • switch to a lower overhead LCD interface and library. While this may not completely solve the problem it will buy some breathing room for the other foreground code.

-redesign the code to use interrupts for the time critical code This is really the only fool proof option. If you want it to be bullet proof, the high priority code needs to be guaranteed of running when it needs to run and the only way to do that is to use interrupts.

If you want to try a faster library that will reduce the CPU overhead here is a library that is MUCH faster than the LiquidCrystal library supplied with Arduino or chipkit. It supports parallel, shift register, and i2c interfaces. There was lots of optimization done for the timing and I have some tweaks for the pic32 built in as well. On a Uno32, byte transfer overheads were measured in the 50-60us time vs the 1ms you are seeing with the serial interface which is about 20 times less overhead. And that can be achieved in 4 bit mode or using only 2 wires and a shift register. Here is a link to the library: [url]https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home[/url]

--- bill