Search code examples
cmultitaskingpicuartmikroc

PIC 18F46K22, MikroC: 'Multitasking' simple and time consuming task


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!!


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.