Question

I'm receiving a UART message containing an array of raw sensor data. I'm reading the message within the main loop of the program. There are 2 things I need the PIC to do with the different values. Display it on a LCD (somewhat time consuming) and, atleast for one of the values, change a LED-bar connected to PORTD accordingly to the value (rather simple).

In the main loop this is my current way of working:

  • Request sensor data from external device on UART
  • Receive bytes array from external device
  • Do calculation to convert raw sensor data to actual values/units
  • Display RPM value on LCD-bar using this code:

     if (RPM < 99)
     {
       PORTD = 0;
     }
    
     if (RPM > 100)
     {
       PORTD = 0x01;
     }
    
     if (RPM > 2400)
     {
       PORTD = 0x03;
     }
    
     if (RPM > 3700)
     {
       PORTD = 0x07;
     }
    
     if (RPM > 4900)
     {
       PORTD = 0x0F;
     }
    
     if (RPM > 6200)
     {
       PORTD = 0x1F;
     }
    
     if (RPM > 7400)
     {
       PORTD = 0x3F;
     }
    
     if (RPM > 8700)
     {
       PORTD = 0x7F;
     }
    
     if (RPM > 10000)
     {
       PORTD = 0xFF;
     }
    
  • Finally displaying multiple values on a LCD. Thus removing old value, drawing the label, set new value, again draw the label.

That last task slows the whole loop down, which is making the LED-bar function to 'laggy'. I got the suggestion to check if the value(s) have changed before redrawing the labels, to avoid unnecessary drawing. But all the values are rather rapid changing values like RPM and such.

Any suggestion would be welcome!!

Was it helpful?

Solution

Data going to an display does not need to change faster than the viewer can sense. If your changes are greater than a threshold (40 to 100 Hz), then only use the last change that occurred in the previous period.

int UpdateValue;
int UpdateNeeded = 0;

void TimerServiceRountine() { // called at N (60) Hz.
  if (UpdateNeeded) {
    UpdateNeeded = 0;
    UpdateLCD(UpdateValue);
  }
  // ...
}

// Call this with each RPM
void UpdateDisplay(int Value) {
  UpdateValue = Value;
  UpdateNeeded = 1;
}

Further refinement: Only call UpdateLCD(x) if x is different from before.

OTHER TIPS

Solution idea #1

My guess is that the slowness of the LCD part is due to that you need to wait for the LCD to process the commands sent to it (common with certain alphanumeric LCDs).

Your main loop otherwise could probably do several thousand cycles a second.

If this is the case, then you should implement a state machine for the LCD output in the main loop. This state machine would clock out the necessary commands to the LCD for updating the display, one by one, once in each run of the main loop, only if the LCD is ready to accept the new command.

This way your main loop can run free of waiting for the LCD, while the LCD also gets updated sufficiently fast (depending on whether the turnaround time of the main loop without the LCD task would be sufficiently low: optimally less than the typical "busy" time of the LCD).

Solution idea #2

This is more complicated and applies if the LCD process is rather calculation heavy for some reason (pixel by pixel work on a graphic LCD?).

Even this case a similar approach to Solution #1 may work well. If you can split up the LCD task to smaller chunks with roughly similar processing time requirements, you may speed up the main loop (by only processing one chunk of these at once).

If you rather would prefer a more accurate timing for the main task, then the main task needs to be put in an interrupt (Assuming that you request the data from your sensor, you need a timer IT to time these requests). The main loop then would only work with the LCD.

Common elements

In all cases you do more samplings while a single fragmented LCD display data construction processes. This needs some data management: You have to "sample" (mostly copy away, interrupts disabled in the case of the last solution) your data going onto the LCD before starting building the display.

All the solutions I presented are "ideal" in that sense they could "automatically" pull out the most (in the term of display update frequency) from your hardware using all cycles available. You only need to select the appropriate method for your situation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top