Design pattern: refresh-based or event-based?

I think if several indicators move then the 10 hz updates could be noticable. Also if it's a touch screen then you want it to be more responsive than a 10 hz update could give you.

Reply to
Paul Rubin
Loading thread data ...

As I wrote in another post, one thing is the events triggered by the graphical toolikt (even emwin is event-based) and another is the events generated by the applications, for example from the lower level layer that manages the field bus (remote sensors/peripherals).

When the user touches a button, an event is raised automatically from emWin and a callback is automatically called. What to do is a work for the programmer that fills in the callback function.

Even in this scenario I can decide to update *values* on the display at a regular time base, for example every 100ms. A timer expiration event trigger a refresh function. Maybe the name of the function would be update() instead of refresh() that recalls the low-level mechanism of refreshing pixels.

Reply to
pozz

If this is a car application, the CANbus/CANopen controllers would be the most likely type. In 11 bit CAN there are up to 2048 identifier (source addresses) available to a whole system. A subset of these are assigned to each of the various controllers.

Typically, each controller broadcasts these messages (with 64 bit payload) each time it has something to say ("to whom it might concern") and each other controller, including the display control, listens for those CAN-IDs it is interested in. Since it knows (by system configuration) what controller and what data is sent in an specific message, it then can make decision what to do about it.

Typically, a controller sends out a message, when there is a significant event in the controller, such as change of state in a binary input or periodically. If only change of state, you need to get the initial state by explicitly reading each CAN-Id with the RTR bit set.

In CANopen, if the display controller is a CANopen master, it can periodically send the SYNC message, prompting each controller to immediately reply by the request sending the values of each message it poses. Again, the messages are identified by the CAN-IDs and thus can be decoded correctly.

With CANopen in the display controller sending SYNC messages, it would be natural to do a full refresh (at least if any message contents has changed) after a while after the SYNC message.

For a simpler CANbus system, especially if the controllers send messages only on change of state, you definitively need e.g. a RTR scan to get the initial states (and updated states periodically, if some messages are lost) so some more event based display system would be preferable.

You should think about the whole system, not just the display.

Reply to
upsidedown

Yes, it's just not clear to me why to do that.

Do you know the idea of Model-View-Controller (MVC)? It might be helpful here:

formatting link

Basically it means you have a data object (the model) tracking the state of the system. The "controller" reads stuff from the field bus and updates values in the model, and then the display (the view) shows the contents of the model.

It's generally reasonable for the controller posting updates to values in the model to also send events to the UI as the updates happen. In a simple system the model can be the state of the UI widgets. UI libraries will typically let you read from the widgets as well as write to them.

You do end up wanting to use some concurrency in these interfaces, but if you implement it with message passing and accept a bit of overhead from that, you're reasonably safe from the classic hazards of concurrent programming.

What hardware and OS are you using?

Reply to
Paul Rubin

You were referring to a high-resolution TFT display, so you'll probably have quite a lot of RAM (or are you building your screen like this computer: ? Then you're in deep trouble :-). Lots of RAM means a processor with quite a few bits and MHz, so redrawing a full screen of new values should be well possible. It's only a few bitblts and fills; people were doing full-screen 3-D with 66 MHz 486's 20 years ago.

Long story short: I would not optimize for minimum redraw, but for simplicity. Probably not redraw the whole wallpaper each time, but every gauge.

Stefan

Reply to
Stefan Reuther

For example in the nuvi package (the spectrometry app under DPS running on our products) each object (spectrum, setup window, oscilloscope display etc.) keeps track of when it was last modified (in system timebase ticks IIRC). That is when some object - say, an acquisition module - modifies the data object it is connected to it sets "last" moment of change (action being called, well, "setlast" :-) ). The displaying loop checks all of the objects ("getlast", I may move this to the more universal getxpar/setxpar, it predates these) some of them has been modified since its last refresh, it gets refreshed. One can set the refresh rate on a per "display" (i.e. window) basis, meaning once a refresh is done no other will be attempted for that period of time. Whoever missed the train - no matter by how little - will have to wait for the next one.

Dimiter

------------------------------------------------------ Dimiter Popoff, TGI

formatting link

------------------------------------------------------

formatting link

Reply to
Dimiter_Popoff

I would go for simplicity too, which means let the GUI toolkit or window system deal with the redrawing. I think the question is not about redrawing per se though, but about how to update the individual GUI widgets. And having written a bunch of such things, I've generally found it simplest to just update them asynchronously when external events are observed, rather than trying to synchronize all the updates. That's how gauges and indicators work in the analog world too. It's usually been straightforward to code this way with the toolkits I've used, though that's not a huge number.

Reply to
Paul Rubin

You still (generally) have interrupts though - they are simply buried in the system or library layers and you are presented with a simplified abstraction. It's also largely irrelevant for the task in hand since our input is from a random collection of sensors as opposed to more usual GUI user input. Either those are not going to fit into the GUI's input module or you are going to have to do your own preparatory work to make them fit, i.e. write the interrupt handlers that perform the appropriate callbacks.

--
Andrew Smallshaw 
andrews@sdf.lonestar.org
Reply to
Andrew Smallshaw

We don't know anything about the hardware or software setup of this system, or even whether it has been firmly selected yet. The CAN bus is well supported by many OS's to the point where the application sees just another network or serial-like interface. It can handle that with an event loop or with threads/coroutines, and communicate with the UI through events or messages. Anything having to do with interrupt handlers is long since taken care of by the OS, if a reasonable OS is in use. Why re-develop all that from scratch?

Reply to
Paul Rubin

For simplicity. The code is very simple, a single function to call regularly on a time basis that redraw every widget on UI.

Interesting.

As I wrote in my original post, the event-based, asyncronous design is more attractive and clean for me... but it has some pitfalls and additional complexities... so the original question: what is the better method?

I think the question is indipendent from the hw. Anyway I'm actually using a LPC1788 MCU without a really OS.

Reply to
pozz

It seems to me this is a variant of my "refresh-based" approach. When a new value is received, no message is asyncronously emitted (or event triggered). You only save the time when the last value arrived to the controller.

In the refresh function, you check the last update time only to understand if the value must be updated on the display too.

Reply to
pozz

No, it is the best of both worlds. You will always have some time between event and refresh no matter what; wanting it below a few mS is not practical simply because no human can see that. So with this approach you get the display refreshed within a certain time after an event - with DPS you can get that time down even into microseconds range were it needed - and you do not do any refresh when it is not needed, as it would be with your suggested "refresh-based" approach.

Basically it is a simple enough issue, does not take a lot to get to the optimum choice nor is there much to do to improve on it.

Dimiter

------------------------------------------------------ Dimiter Popoff, TGI

formatting link

------------------------------------------------------

formatting link

Reply to
Dimiter_Popoff

For a human eye, 10Hz or 5Hz is enough to feel the system responsive. That's

5 times (or 10 times) per second following rate of the actual events.

I would implement such a system this way:

5 or 10 times per second a global "refresh" routine. This will check the "old" values against new ones and make the required update only when a change is detected. Yes, you need memory for keeping the old values. This technique is more important when displaying on large tft displays, it will keep the updates flickering unnoticable.

At a lower level I would implement the "event" system. It would be triggered by the real events but all it has to do is to store the new values in memory. Being much more lightweight it may be triggered in any context, even interrupts.

Reply to
raimond.dragomir

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.