PretoWatch (Part 3)

Last time, in Part 2, we discussed some aspects of the hardware design of PretoWatch. In this blog post, we will explore more about the software side of the project.

As of writing this blog, PretoWatch is still under development. If you have any feedback, please feel free to leave a comment.

I’ve decided to use an RTOS (Real-Time Operating System) for this project because it allows better management of resources and makes it easier to set up a software architecture that provides a more real-time response to the user. By splitting the code into tasks, the system can schedule them to run one after another efficiently. In this blog, I’ll focus on the rationale behind the tasks I believe are necessary for this project.

Since the watch uses an E-ink screen, it’s important to note a distinctive characteristic of E-ink screens: they usually take quite a while to fully update their content. From the demo code of Waveshare E-ink screens (which is the one I’m using in this project), a full update takes a few seconds. Here is a short video showing how long it takes:

I realized that constantly performing full updates is not a good choice for updating content on PretoWatch. So, here comes partial update:

You may ask, what is the difference?

A partial update changes only a portion of the screen. For example, on the watch, only the area displaying the time frequently changes. With a partial update, only the time is updated, leaving the rest of the screen untouched. However, partial updates can cause a problem known as ‘ghosting’ on E-ink screens. This means that remnants from the previous screen can be left behind, making the display unclear to the user.

The edge of the circle is not sharp when it moves due to ghosting.

One way to solve ghosting is to perform a full update periodically, ensuring the entire screen is refreshed. To address both slow responsiveness and ghosting, I’ve decided to use a hybrid approach.

This approach highlights the advantages of using an RTOS in this project. With an RTOS, tasks can be scheduled effectively. For example, a partial update task can run every second, and a full update task can run every 15 minutes.

I have prior experience with FreeRTOS from my previous work, and I found that STM32CUBEIDE also supports it via CMSIS-RTOS, which only needed to be activated.

What other tasks do we need? In PretoWatch, we have a side switch and a vibration motor. We also need a task to control button presses and another task to activate the vibrations.

Tasks can have different priorities, indicating their importance to the system. This allows more important tasks to run when multiple tasks are waiting to be executed.

For tasks that interact with user input and provide haptic feedback, I’ve set their priority to osPriorityHigh. The Full Update Task, which runs once every 15 minutes and is less critical, is set to osPriorityLow. The Partial Update Task is set to osPriorityNormal.

In summary, we have four tasks:

Full Update TaskosPriorityLowEvery 15 Minutes
Partial Update TaskosPriorityNormalAll the time
Control TaskosPriorityHighAll the time
Notification TaskosPriorityHighAll the time

Here is a more detailed diagram illustrating how the RTOS scheduler interacts with different tasks and other system callback functions.

To demonstrate this more clearly, I’ve used a chart from the FreeRTOS book (FreeRTOS.org), which provided me with a solid understanding of its capabilities.

In FreeRTOS, you can use either a preemptive RTOS scheduler or a cooperative RTOS scheduler:

FeaturePreemptive RTOSCooperative RTOS
Task SwitchingScheduler can interrupt tasksTasks must yield voluntarily
ControlRTOS controls task switchingTasks control when to yield
LatencyLower for high-priority tasksHigher for high-priority tasks
OverheadHigher due to frequent switchesLower due to fewer switches
ComplexityMore complexSimpler
Use CaseReal-time systemsSimple embedded systems

For this project, I’ve chosen the preemptive RTOS, as I want the system to be as responsive as possible (also to compensate for using a slow update display).

I hope this blog provides some insights into my design choices. There are numerous tutorials and documents about RTOS, so I did not elaborate too much here. Instead, I wanted to highlight the key considerations behind the project.

Next time, I’ll be writing about state machines and button handling in PretoWatch. Stay tuned!

Leave a Reply

Your email address will not be published. Required fields are marked *