1

I'm building a scale which reads a value (from a load cell) and outputs it on a LED screen.

There is a function for the scale, read which will read the value from the scale. However this is not instantaneous - it uses the yield function to wait until the scale is ready.

The LED screen has a function, display which will display an integer on the screen with no delay. However, this lasts barely a fraction of a second, so it must be repeatedly called.

These functions as is are called one after another inside loop(), but it causes only a quick flash of the LED screen followed by a half second of reading.

How would I allow the LED screen to keep displaying a value while the scale reads? I know there's BlinkWithoutDelay - but I'm not using specific times. There is no instance of the function delay anywhere in the program. I also am not going to edit the library which reads the load cell.

4 Answers4

1

There is similar questions answered a day ago - Multithreading with Arduino. What your are asking is multitasking or multithreading. Tasks have own loop and task scheduler stops and switches tasks periodically so they appear as if running simultaneously. Task scheduler in turn is usually driver by timer ISR, for AVR a 50-100Hz scheduler timer tick frequency is reasonable.

If there are 2 tasks with same priority (given task scheduler supports priority), they will spare MCU time ~ 50% / 50%. So if timer is 100Hz, each task runs 5ms and interrupted.

Surely task scheduler have overhead, but for small frequency it is negligible, less than 1%. There is no need to modify existing code/library, time sharing is organized transparently.

There are rules to follow when doing multitasking: for example when the scale related function is writing measured value of double type into some variable, this task might be interrupted (by scheduler) during the writing (when only half of the values is written) - and another task will see an incorrect value. The easiest way would be disabling the interrupts during such shared variable update. Google for "race condition", atomic operation, synchronization.

Flanker
  • 529
  • 2
  • 8
0

There is only one execution unit in this MCU so you can not truly run multiple tasks concurrently.

However, you can achieve the appearance of concurrency by running a higher priority task through an interrupt. For example, you cannot afford to have flickering disspplay. So set up a timer that invokees the display routine periodically. If you set the timer interrupt sufficiently small (over 25hz for example), the display will not flicker.

Your other routines can be run in other isr or in the main loop so they are interrupted by the display routine periodically. In a way that's fully transparent to you.

dannyf
  • 2,813
  • 11
  • 13
0

Here is sketch in pseudo-code that can keep your display going and still make frequent weight measurements, without having to do any multi-threading or similar. The value of 'if a measurement is ready' (below) may come from a status bit in the scale, or simply a time difference using the millis() function; I don't know the specifics of your hardware. I showed weight being an integer. Again, you may need to adapt this to your own hardware. But it is an uncomplicated process for displaying frequently to maintain the display, and reading whenever data is available so the display updates as you get new data, no concurrency required.

void setup()
{
   // initialize everything;
   // start the first measurement;
}

void loop()
{
   static int16_t weight = 0;

   // if a measurement is ready,
      // read the value and store it in 'weight;'
      // start a new measurement
   // endif

   // display 'weight' on the LCD;
}
JRobert
  • 15,407
  • 3
  • 24
  • 51
-1

Put the value variable outside the loop (as a global variable).

Then, call the display function BEFORE the read function.


This is not the best, but if should work fine.

Dat Ha
  • 2,943
  • 6
  • 24
  • 46