Skip to content

ROCK SBC Simple Status Monitor

Introduction

Adding a status monitor to any Rock SBC project can be very useful to give at a glance real-time status of how the CPU is performing in terms of usage, temperature, and RAM use as well as vital connectivity information. If overclocking is your thing, then this can prove extremely valuable to see what impact your settings have on the Rock SBC and adjust accordingly.

The TIMI-130 display, together with the Pi Adapter, is a perfect choice for this project due to its ease of use and simplicity in code needed to get this up and running.

TIMI-130

A Python library is provided to makes the coding experience effortless.

Requirements

To proceed with the project, the following are required.

Hardware

  • ROCK 4C+
  • TIMI-130
  • Pi Adaptor
  • Mates Programmer
  • One of the Storage media below:
    • microSD card, for any ROCK SBC model, larger than 8GB
    • eMMC Module, for removable eMMC ROCK SBC model only.

Software

Graphics Design

When you start Mates Studio, you will be prompted to select your product.

Step 1: Click on TIMI-130, and a graphical representation of the TIMI-130 will appear on the right-hand panel.

Select Product TIMI-130

Step 2: Click twice on the image of the TIMI-130 to rotate the display by 180 degrees.

Select Product TIMI-130 Rotation

Step 3: Click on CONFIRM and then select the Commander Environment.

Select Commander Environment

Step 4: The Commander environment will now open.

Commander Environment

Step 5: Click on the '+' to browse the page library.

Then select Status and Resource Monitor from the Notifications tab, and click on CONFIRM.

Select Status Monitor

Step 6: Change the Baud rate from 9600 to 115200 by clicking on the Tools and Configuration button and selecting 115200.

Baud Rate

Step 7: Next, select the com port for the Mates Programmer by clicking in the COM panel and selecting the correct port from the drop-down menu.

Select COM Port

Step 8: Finally, click on the Upload button to upload the Status Monitor to the TIMI-30.

Upload Status Monitor

The Status Monitor will now display on the TIMI-130.

Status Monitor on TIMI-130

The USB lead and Mates Programmer can now be removed from the Pi Adapter. The Pi Adapter switch can now be set to HOST, ready to receive commands from the Rock Pi.

Setting up the ROCK SBC

ROCK 4 SBC Setup

Set up the ROCK 4 SBC by following their getting started instructions for installing the OS.

When the OS has been transferred to the uSD card or eMMC, remove it from the PC and insert into the storage media into the socket on the board and then power it up. Rock SBC’s can consume quite a lot of current which may exceed the available current from a PC USB port so it may be necessary to use the official ROCK SBC power supply.

The ROCK 4 OS will need to be configured to connect to the internet, SSH, and also to enable the Serial port (UART) that we will use to talk to the TIMI-130. There is plenty of information about this online.

Enabling UART

Before we can use the serial port to control the display. We need to enable the overlays for the UART. To do this type the command below on the terminal.

sudo rsetup

It will open the rsetup configuration. Use arrow keys to go to Overlays and click enter.

rsetup

A warning message will show up. Click Yes to continue.

resetup-warning

Select Manage overlays from the option.

manage-overlays

Select Enable UART2 from the list of overlays and use space bar to enable. Select OK to save the configuration.

uart

It will ask you to reboot the system to enable the selected overlays. Exit the rsetup configuration tool. Then reboot the system.

reboot

Installing Git and GCC

Connect to Rock Pi using SSH connection to install Git and GCC.

To be able to clone the repositories that we need on this project you need to install Git

sudo apt install git

To be able to use the python libraries that we need in this project, we need to intall GCC and Python.

sudo apt install gcc python3-dev

Installing the Python Libraries

All the recent Debian OS are pre-loaded with Python 3 so we can simply install the required Python libraries using 'pip'.

Install python mates library that will be use to control the TIMI-130.

pip install mates-controller

Installing psutil for retrieving information on running processes and system utilization.

pip install psutil

Installing uptime to provide system uptime and boot time.

pip install uptime

Clone the code from the github by running the following command.

git clone https://github.com/BreadBoardMates/ROCK-TIMI-130-Status-Monitor.git

The Python Code

#!/usr/bin/python

import time
import sys
import psutil
import socket
import fcntl
import struct
import uptime

from mates.controller import MatesController
from mates.constants import *

# When using the GPIO, ROCK SBC requires 'sudo'
def initResetPin(pin, mode: str):
    with open("/sys/class/gpio/export", "w") as f:
        f.write(str(pin))
    with open("/sys/class/gpio/gpio" + str(pin) + "/direction", "w") as m:
        m.write(str(mode))

# When using the GPIO, ROCK SBC requires 'sudo'
def setPin(pin, value):
    with open("/sys/class/gpio/gpio" + str(pin) + "/value", "w") as f:
        f.write(str(value))


# When resetting the module, ROCK SBC requires 'sudo'
def resetModule():
    initResetPin(75, "out")
    time.sleep(0.01)
    setPin(75, 0)
    time.sleep(0.01)
    setPin(75, 1)
    time.sleep(0.01)


def up():
    t = uptime.uptime()
    days = 0
    hours = 0
    min = 0
    out = ""

    while t > 86400:
        t -= 86400
        days += 1

    while t > 3600:
        t -= 3600
        hours += 1

    while t > 60:
        t -= 60
        min += 1

    out += str(days) + "d"
    out += str(hours) + "h"
    out += str(min) + "m"

    return out


def getTemp(sensor: str, multiplier: int = 1):
    temp = psutil.sensors_temperatures()[sensor][0]
    return round(temp.current * multiplier)

def get_interface_ipaddress(network):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        return socket.inet_ntoa(
            fcntl.ioctl(
                s.fileno(), 0x8915, struct.pack("256s", network[:15].encode("utf-8"))
            )[20:24]
        )
    except OSError:
        return "0.0.0.0"

if __name__ == "__main__":

    # When resetting the module, ROCK SBC requires 'sudo'
    # mates = MatesController('/dev/ttyS2', resetFunction=resetModule)
    mates = MatesController("/dev/ttyS2")
    mates.begin(115200)

    lastCpuUse = 0
    lastCpuTempG = 0
    lastCpuTempL = 0
    lastGpuTemp = 0
    lastRamUse = 0
    lastWIPaddr = 0
    lastEIPaddr = 0
    IPinterval = 0

    gtime = up()
    cpu_use = round(psutil.cpu_percent())               # CPU usage
    cpu_tempG = getTemp("cpu_thermal")                  # CPU temperature for gauge value
    cpu_tempL = getTemp("cpu_thermal", 10)              # CPU temperature for leddigits
    ram_use = round(psutil.virtual_memory().percent)    # RAM usage

    mates.updateTextArea(5, gtime, True)

    while True:

        cpu_tempG = getTemp("cpu_thermal")
        cpu_tempL = getTemp("cpu_thermal", 10)
        cpu_use = round(psutil.cpu_percent())
        ram_use = round(psutil.virtual_memory().percent)

        if cpu_use < lastCpuUse:
            lastCpuUse = lastCpuUse - (1 + (lastCpuUse - cpu_use > 9))
        if cpu_use > lastCpuUse:
            lastCpuUse = lastCpuUse + 1 + (cpu_use - lastCpuUse > 9)
        if cpu_tempL < lastCpuTempL:
            lastCpuTempL = lastCpuTempL - 1
        if cpu_tempL > lastCpuTempL:
            if (cpu_tempL - lastCpuTempL) > 10:
                lastCpuTempL = lastCpuTempL + 10
            else:
                lastCpuTempL = lastCpuTempL + 1

        if cpu_tempG < lastCpuTempG:
            lastCpuTempG = lastCpuTempG - (1 + (lastCpuTempG - cpu_tempG > 9))
        if cpu_tempG > lastCpuTempG:
            lastCpuTempG = lastCpuTempG + 1 + (cpu_tempG - lastCpuTempG > 9)
        if ram_use < lastRamUse:
            lastRamUse = lastRamUse - (1 + (lastRamUse - ram_use) > 9)
        if ram_use > lastRamUse:
            lastRamUse = lastRamUse + 1 + (ram_use - lastRamUse > 9)

        # CPU Temperature
        if cpu_tempG != lastCpuTempG:
            mates.setWidgetValueByIndex(
                MatesWidget.MATES_MEDIA_GAUGE_B, 0, lastCpuTempG
            )
        if cpu_tempL != lastCpuTempL:
            mates.setLedDigitsShortValue(0, lastCpuTempL)

        # Percentage of used CPU
        if cpu_use != lastCpuUse:
            mates.setWidgetValueByIndex(MatesWidget.MATES_MEDIA_GAUGE_B, 1, lastCpuUse)
            mates.setLedDigitsShortValue(1, lastCpuUse)

        # Percentage of used RAM
        if ram_use != lastRamUse:
            mates.setWidgetValueByIndex(MatesWidget.MATES_MEDIA_GAUGE_B, 2, lastRamUse)
            mates.setLedDigitsShortValue(2, lastRamUse)

        if IPinterval > 20:
            tempIPaddr = get_interface_ipaddress("eth0")
            if tempIPaddr != lastEIPaddr:
                mates.updateTextArea(1, tempIPaddr, True)
                lastEIPaddr = tempIPaddr

            tempIPaddr = get_interface_ipaddress("wlan0")
            if tempIPaddr != lastWIPaddr:
                mates.updateTextArea(3, tempIPaddr, True)
                lastWIPaddr = tempIPaddr

            IPinterval = 0

        IPinterval = IPinterval + 1
        time.sleep(0.060)

        tempTime = up()
        if tempTime != gtime:
            mates.updateTextArea(5, tempTime, True)
            gtime = tempTime
        time.sleep(0.04)

The python script below will create a Mates Controller instance and start the serial(UART) communication at 115200 baud.

# When resetting the module, ROCK SBC requires 'sudo'
# mates = MatesController('/dev/ttyS2', resetFunction=resetModule)
mates = MatesController("/dev/ttyS2")
mates.begin(115200)

You can reset the display during Serial UART setup, however this requires root privileges.

A set of variables are then created which will be set after each time the various states are updated. This enables the main loop to compare the status that has just read with its last state and then update the corresponding widget only if it has changed in value.

lastCpuUse = 0
lastCpuTempG = 0
lastCpuTempL = 0
lastGpuTemp = 0
lastRamUse = 0
lastWIPaddr = 0
lastEIPaddr = 0
IPinterval = 0

The project starts by updating the display with initial values

gtime = up()
cpu_use = round(psutil.cpu_percent())               # CPU usage
cpu_tempG = getTemp("cpu_thermal")                  # CPU temperature for gauge value
cpu_tempL = getTemp("cpu_thermal", 10)              # CPU temperature for leddigits
ram_use = round(psutil.virtual_memory().percent)    # RAM usage

mates.updateTextArea(5, gtime, True)

Every iteration of the loop will update the widgets on the display using the following simple commands.

cpu_tempG = getTemp("cpu_thermal")
cpu_tempL = getTemp("cpu_thermal", 10)
cpu_use = round(psutil.cpu_percent())
ram_use = round(psutil.virtual_memory().percent)

if cpu_use < lastCpuUse:
    lastCpuUse = lastCpuUse - (1 + (lastCpuUse - cpu_use > 9))
if cpu_use > lastCpuUse:
    lastCpuUse = lastCpuUse + 1 + (cpu_use - lastCpuUse > 9)
if cpu_tempL < lastCpuTempL:
    lastCpuTempL = lastCpuTempL - 1
if cpu_tempL > lastCpuTempL:
    if (cpu_tempL - lastCpuTempL) > 10:
        lastCpuTempL = lastCpuTempL + 10
    else:
        lastCpuTempL = lastCpuTempL + 1

if cpu_tempG < lastCpuTempG:
    lastCpuTempG = lastCpuTempG - (1 + (lastCpuTempG - cpu_tempG > 9))
if cpu_tempG > lastCpuTempG:
    lastCpuTempG = lastCpuTempG + 1 + (cpu_tempG - lastCpuTempG > 9)
if ram_use < lastRamUse:
    lastRamUse = lastRamUse - (1 + (lastRamUse - ram_use) > 9)
if ram_use > lastRamUse:
    lastRamUse = lastRamUse + 1 + (ram_use - lastRamUse > 9)

# CPU Temperature
if cpu_tempG != lastCpuTempG:
    mates.setWidgetValueByIndex(
        MatesWidget.MATES_MEDIA_GAUGE_B, 0, lastCpuTempG
    )
if cpu_tempL != lastCpuTempL:
    mates.setLedDigitsShortValue(0, lastCpuTempL)

# Percentage of used CPU
if cpu_use != lastCpuUse:
    mates.setWidgetValueByIndex(MatesWidget.MATES_MEDIA_GAUGE_B, 1, lastCpuUse)
    mates.setLedDigitsShortValue(1, lastCpuUse)

# Percentage of used RAM
if ram_use != lastRamUse:
    mates.setWidgetValueByIndex(MatesWidget.MATES_MEDIA_GAUGE_B, 2, lastRamUse)
    mates.setLedDigitsShortValue(2, lastRamUse)

if IPinterval > 20:
    tempIPaddr = get_interface_ipaddress("eth0")
    if tempIPaddr != lastEIPaddr:
        mates.updateTextArea(1, tempIPaddr, True)
        lastEIPaddr = tempIPaddr

    tempIPaddr = get_interface_ipaddress("wlan0")
    if tempIPaddr != lastWIPaddr:
        mates.updateTextArea(3, tempIPaddr, True)
        lastWIPaddr = tempIPaddr

    IPinterval = 0

IPinterval = IPinterval + 1
time.sleep(0.060)

tempTime = up()
if tempTime != gtime:
    mates.updateTextArea(5, tempTime, True)
    gtime = tempTime
time.sleep(0.04)

Running the Project

Step 1: Before running this project, serial port needs to be released from the console after boot.

The Serial port of the Rock Pi is used by the console so it needs to be released after boot. Please take note of the UART that we enable from the overlays earlier. This can be achieved by using these commands:

cd /etc/systemd/system
systemctl mask serial-getty@ttyS2.service
sync
sudo reboot

Step 2: Connect Pi Adaptor into the 40-pin GPIO header on ROCK 4C+. Then connect TIMI-130 to the adaptor as shown below.

rockpi-timi-130

Step 3: As the TIMI-130 needs to be configured for the Status Monitor, the switch on the Pi adapter needs to be set to PROG. Then attach the Mates Programmer as shown below.

rockpi-timi-130_prog

Step 4: Connect a USB cable to the Mates Programmer and to a PC USB port. The TIMI-130 is now ready for the Status Monitor project to be installed.

Mates Studio will be required to configure the TIMI-130, and you can download it from here:

Download Mates Studio

Go to Graphics Design section for uploading the status monitor project.

Step 5: Run the app by navigating to ROCK-TIMI-130-Status-Monitor folder:

cd ROCK-TIMI-130-Status-Monitor

Before running the application you need to change attributes from the folder /dev/ttyS2.

sudo chmod o=rw /dev/ttyS2

Run the application with the applicable command below.

python bbm-status-monitor.py
sudo python bbm-status-monitor.py

The TIMI-130 should first reset to an off-screen and then start showing the status of CPU use, CPU temp and RAM use along with connected IP address and uptime.

If you would like the Status Monitor to run as a background task, simply add '&' to the command.

python bbm-status-monitor.py &