Skip to content

Instantly share code, notes, and snippets.

@Oneiroi
Last active August 21, 2025 08:52
Show Gist options
  • Select an option

  • Save Oneiroi/edf4e301a3fe8971d69c5b39228b170b to your computer and use it in GitHub Desktop.

Select an option

Save Oneiroi/edf4e301a3fe8971d69c5b39228b170b to your computer and use it in GitHub Desktop.
FIXED 20250820 old.py - Yahboom Jetson Nano Case Compatible with Jetson Orin Nano SUPER Orin NX SUPER Protective Case Xaver NX TX2-NX with RGB Fan, Antennas, OLED Display
#!/usr/bin/env python3
# coding=utf-8
import time
import os
import sys
import subprocess
from luma.core.interface.serial import i2c
from luma.oled.device import ssd1306
from PIL import Image, ImageDraw, ImageFont
# Jetson-compatible OLED class for SSD1306 128x32 display
class OLED:
def __init__(self, i2c_bus=7, i2c_address=0x3C, clear=False, debug=False):
self.__debug = debug
self.__i2c_bus = i2c_bus # Use bus 7 for Jetson
self.__i2c_address = i2c_address # OLED at 0x3C
self.__clear = clear
self.__top = -2
self.__x = 0
self.__total_last = 0
self.__idle_last = 0
self.__str_CPU = "CPU:0%"
self.__WIDTH = 128
self.__HEIGHT = 32
self.__image = Image.new('1', (self.__WIDTH, self.__HEIGHT))
self.__draw = ImageDraw.Draw(self.__image)
self.__font = ImageFont.load_default()
self.__device = None
def __del__(self):
self.clear(True)
if self.__debug:
print("---OLED-DEL---")
# Initialize OLED using luma.oled for Jetson compatibility
def begin(self):
try:
# Create I2C interface for Jetson
serial = i2c(port=self.__i2c_bus, address=self.__i2c_address)
self.__device = ssd1306(serial, width=128, height=32)
# Clear display
self.__device.clear()
if self.__debug:
print("---OLED begin ok!---")
return True
except Exception as e:
if self.__debug:
print(f"---OLED initialization failed: {e}---")
return False
# Clear the display
def clear(self, refresh=False):
self.__draw.rectangle(
(0, 0, self.__WIDTH, self.__HEIGHT), outline=0, fill=0)
if refresh and self.__device:
try:
self.refresh()
return True
except:
return False
# Add text to display buffer
def add_text(self, start_x, start_y, text, refresh=False):
if start_x > self.__WIDTH or start_x < 0 or start_y < 0 or start_y > self.__HEIGHT:
if self.__debug:
print("oled text: x, y input error!")
return
x = int(start_x + self.__x)
y = int(start_y + self.__top)
self.__draw.text((x, y), str(text), font=self.__font, fill=255)
if refresh:
self.refresh()
# Add line of text (4 lines max for 32px height)
def add_line(self, text, line=1, refresh=False):
if line < 1 or line > 4:
if self.__debug:
print("oled line input error!")
return
y = int(8 * (line - 1))
self.add_text(0, y, text, refresh)
# Display the image buffer on OLED
def refresh(self):
if self.__device:
self.__device.display(self.__image)
# Read CPU usage (same as original)
def getCPULoadRate(self, index):
count = 10
if index == 0:
f1 = os.popen("cat /proc/stat", 'r')
stat1 = f1.readline()
data_1 = []
for i in range(count):
data_1.append(int(stat1.split(' ')[i+2]))
self.__total_last = data_1[0]+data_1[1]+data_1[2]+data_1[3] + \
data_1[4]+data_1[5]+data_1[6]+data_1[7]+data_1[8]+data_1[9]
self.__idle_last = data_1[3]
elif index == 4:
f2 = os.popen("cat /proc/stat", 'r')
stat2 = f2.readline()
data_2 = []
for i in range(count):
data_2.append(int(stat2.split(' ')[i+2]))
total_now = data_2[0]+data_2[1]+data_2[2]+data_2[3] + \
data_2[4]+data_2[5]+data_2[6]+data_2[7]+data_2[8]+data_2[9]
idle_now = data_2[3]
total = int(total_now - self.__total_last)
idle = int(idle_now - self.__idle_last)
usage = int(total - idle)
usageRate = int(float(usage / total) * 100)
self.__str_CPU = "CPU:" + str(usageRate) + "%"
self.__total_last = 0
self.__idle_last = 0
return self.__str_CPU
# Get system time
def getSystemTime(self):
cmd = "date +%H:%M:%S"
date_time = subprocess.check_output(cmd, shell=True)
str_Time = str(date_time).lstrip('b\'')
str_Time = str_Time.rstrip('\\n\'')
return str_Time
# Get RAM usage
def getUsagedRAM(self):
cmd = "free | awk 'NR==2{printf \"RAM:%2d%% -> %.1fGB \", 100*($2-$7)/$2, ($2/1048576.0)}'"
FreeRam = subprocess.check_output(cmd, shell=True)
str_FreeRam = str(FreeRam).lstrip('b\'')
str_FreeRam = str_FreeRam.rstrip('\'')
return str_FreeRam
# Get disk usage
def getUsagedDisk(self):
cmd = "df -h | awk '$NF==\"/\"{printf \"SD: %s -> %.1fGB\", $5, $2}'"
Disk = subprocess.check_output(cmd, shell=True)
str_Disk = str(Disk).lstrip('b\'')
str_Disk = str_Disk.rstrip('\'')
return str_Disk
# Get local IP - Auto-detect interface for Jetson
def getLocalIP(self):
try:
# Use ip command to find active interface with IP
cmd = "ip route get 8.8.8.8 | grep -oP 'src \\K\\S+'"
ip = os.popen(cmd).read().strip()
if ip and len(ip) <= 15:
return ip
except:
pass
# Fallback: check common Jetson interface names
interfaces = ['enp*', 'eth*', 'wlp*', 'wlan*']
for iface_pattern in interfaces:
try:
cmd = f"ip addr show | grep -A2 '{iface_pattern[:-1]}' | grep 'inet ' | head -1 | awk '{{print $2}}' | cut -d'/' -f1"
ip = os.popen(cmd).read().strip()
if ip and len(ip) <= 15 and not ip.startswith('127.'):
return ip
except:
continue
return '<UNKNOWN>' # Your known IP as fallback
# Main display loop
def main_program(self):
try:
cpu_index = 0
state = self.begin()
while state:
self.clear()
if self.__clear:
self.refresh()
return True
str_CPU = self.getCPULoadRate(cpu_index)
str_Time = self.getSystemTime()
if cpu_index == 0:
str_FreeRAM = self.getUsagedRAM()
str_Disk = self.getUsagedDisk()
str_IP = "IP:" + self.getLocalIP()
self.add_text(0, 0, str_CPU)
self.add_text(50, 0, str_Time)
self.add_line(str_FreeRAM, 2)
self.add_line(str_Disk, 3)
self.add_line(str_IP, 4)
self.refresh()
cpu_index = cpu_index + 1
if cpu_index >= 5:
cpu_index = 0
time.sleep(.1)
return False
except Exception as e:
if self.__debug:
print(f"!!!---OLED refresh error: {e}---!!!")
return False
# Fan/RGB shutdown removed - thermal management should be independent
# def close_rgb_fan():
# try:
# import smbus
# bus = smbus.SMBus(7)
# bus.write_byte_data(0x0E, 0x08, 0) # Turn off fan
# time.sleep(.01)
# bus.write_byte_data(0x0E, 0x04, 0) # Turn off RGB
# except:
# pass
if __name__ == "__main__":
try:
oled_clear = False
oled_debug = False
state = False
if len(sys.argv) > 1:
if str(sys.argv[1]) == "clear":
oled_clear = True
elif str(sys.argv[1]) == "debug":
oled_debug = True
# Use I2C bus 7 for Jetson
oled = OLED(i2c_bus=7, clear=oled_clear, debug=oled_debug)
try:
import smbus
bus = smbus.SMBus(7) # Use bus 7 for Jetson
if not oled_clear:
start = 1 # Turn on fan
bus.write_byte_data(0x0E, 0x08, start)
time.sleep(.05)
effect = 3 # RGB effect 1-5
bus.write_byte_data(0x0E, 0x04, effect)
time.sleep(.05)
except:
pass
while True:
state = oled.main_program()
oled.clear(True)
if state:
del oled
print("---OLED CLEARED!---")
break
time.sleep(1)
except KeyboardInterrupt:
del oled
print("---Program closed!---")
@Oneiroi
Copy link
Author

Oneiroi commented Aug 20, 2025

sudo usermod  -a -G i2c $USER
#You will need to logon and back in before the next steps
pip install luma.core
python3 jetson_oled.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment