adds first PoC wise PiD controller, which should probably hold the RPM

This commit is contained in:
Robert Schauklies 2025-11-22 01:06:58 +01:00
parent 38ea428824
commit e87293a6e2
3 changed files with 352 additions and 79 deletions

BIN
src/fafo_green.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -2,6 +2,7 @@
# MIT License; Copyright (c) 2017 Jeffrey N. Magee # MIT License; Copyright (c) 2017 Jeffrey N. Magee
from ili934xnew import ILI9341, color565 from ili934xnew import ILI9341, color565
from machine import Pin, SPI,Timer, UART,PWM from machine import Pin, SPI,Timer, UART,PWM
from machine import Counter
from ST7735 import TFT,TFTColor from ST7735 import TFT,TFTColor
import m5stack import m5stack
import tt14 import tt14
@ -16,6 +17,9 @@ from rotary_irq_esp import RotaryIRQ
fonts = [glcdfont,tt14,tt24,tt32] fonts = [glcdfont,tt14,tt24,tt32]
from sysfont import sysfont from sysfont import sysfont
import json import json
from pid import PID
COILS = 14
# from enum import Enum # from enum import Enum
# class EditMenu(Enum): # class EditMenu(Enum):
@ -210,41 +214,56 @@ async def update_motor():
global state global state
#we want to use 18 for the SPI-Bus! #we want to use 18 for the SPI-Bus!
#https://docs.micropython.org/en/latest/esp32/quickref.html#hardware-spi-bus #https://docs.micropython.org/en/latest/esp32/quickref.html#hardware-spi-bus
dshot = Dshot(pin=Pin(25)) # dshot = Dshot(pin=Pin(25))
rpm_pid = PID( # rpm_pid = PID(
Kp=config["PID"]["Kp"], # Kp=config["PID"]["Kp"],
Ki=config["PID"]["Ki"], # Ki=config["PID"]["Ki"],
Kd=config["PID"]["Kd"], # Kd=config["PID"]["Kd"],
setpoint=0, # setpoint=0,
sample_time=None, # sample_time=None,
output_limits=(0.0, 1.0), # output_limits=(0.0, 1.0),
# proportional_on_measurement=True, # # proportional_on_measurement=True,
) # )
while True: # while True:
rpm_pid.setpoint = state["target_rpm"] # rpm_pid.setpoint = state["target_rpm"]
# read ESC telemetry # # read ESC telemetry
if uart.any() >= 10: # if uart.any() >= 10:
telemetry = decode_ESC_telemetry(uart.read()) # telemetry = decode_ESC_telemetry(uart.read())
if telemetry is not None: # if telemetry is not None:
state["rpm"] = telemetry[5] # state["rpm"] = telemetry[5]
throttle = rpm_pid(state["rpm"]) # throttle = rpm_pid(state["rpm"])
print( # print(
"Throttle:", # "Throttle:",
throttle, # throttle,
"pid components:", # "pid components:",
rpm_pid.components, # rpm_pid.components,
"RPM:", # "RPM:",
state["rpm"], # state["rpm"],
) # )
if state["target_rpm"] == 0 and state["rpm"] < 1000: # if state["target_rpm"] == 0 and state["rpm"] < 1000:
throttle = 0 # throttle = 0
rpm_pid.reset() # rpm_pid.reset()
dshot.set_throttle(throttle) # dshot.set_throttle(throttle)
# await uasyncio.sleep_ms(1)
old_value=0
current_rpm=0
def timer_callback(f):
global old_value
global current_rpm
val = counter.value()
current_rpm = val-old_value
old_value = val
# print(current_rpm)
def kill_me(f):
state["target_rpm"] = 0
await uasyncio.sleep_ms(1)
def update_motor_pwm(): def update_motor_pwm():
global timer3
global current_rpm
pwm = PWM(Pin(26)) pwm = PWM(Pin(26))
rpm_pid = PID( rpm_pid = PID(
Kp=config["PID"]["Kp"], Kp=config["PID"]["Kp"],
@ -256,24 +275,19 @@ def update_motor_pwm():
# proportional_on_measurement=True, # proportional_on_measurement=True,
) )
pwm.freq(50) pwm.freq(50)
# pwm.duty_u16(1638)
# pwm.duty_u16(8192) timer3.init(mode=Timer.PERIODIC, period=100, callback=timer_callback)
# set_throttle(pwm,1055)
pwm.duty_ns(1055*10**3) pwm.duty_ns(1055*10**3)
time.sleep(1) time.sleep(1)
pwm.duty_ns(1070*10**3)
time.sleep(10) print((current_rpm*60)/COILS)
global rpm_counter
rpm_counter= 0
pwm.duty_ns(1200*10**3)
time.sleep(10)
global rpm_counter
rpm_counter= 0
pwm.duty_ns(1400*10**3)
time.sleep(60)
pwm.duty_ns(1055*10**3) pwm.duty_ns(1055*10**3)
#pwm.duty_ns(1200*10**3)
#global rpm_counter
#rpm_counter= 0
#time.sleep(10)
# time.sleep(10) # keep low signal to arm # time.sleep(10) # keep low signal to arm
# # for i in range(1060,1800): # # for i in range(1060,1800):
# # pwm.duty_u16(i*3) # # pwm.duty_u16(i*3)
@ -281,14 +295,19 @@ def update_motor_pwm():
# pwm.duty_ns(1070*10**3) # pwm.duty_ns(1070*10**3)
# pwm.duty_u16(1700) # pwm.duty_u16(1700)
# time.sleep(200) # time.sleep(200)
while True: pwm.duty_ns(1060*10**3)
state["target_rpm"] = 5000
timer2.init(mode=Timer.PERIODIC, period=30000, callback=kill_me)
while(True):
print(f'target RPM:{state["target_rpm"]}')
rpm_pid.setpoint = state["target_rpm"] rpm_pid.setpoint = state["target_rpm"]
# read ESC telemetry # read ESC telemetry
if uart.any() >= 10: telemetry = (current_rpm*600)/COILS
telemetry = decode_ESC_telemetry(uart.read())
if telemetry is not None: if telemetry is not None:
state["rpm"] = telemetry[5] state["rpm"] = telemetry
throttle = rpm_pid(state["rpm"]) throttle = rpm_pid(state["rpm"])
print( print(
"Throttle:", "Throttle:",
@ -299,9 +318,21 @@ def update_motor_pwm():
state["rpm"], state["rpm"],
) )
if state["target_rpm"] == 0 and state["rpm"] < 1000: if state["target_rpm"] == 0:
print("Killing Coater!")
throttle = 0 throttle = 0
rpm_pid.reset() rpm_pid.reset()
pwm.duty_ns(1055*10**3)
return
print(throttle)
new_duty = 1060+(int(660*throttle))
print(new_duty)
pwm.duty_ns(new_duty*10**3)
pwm.duty_ns(1050*10**3)
pwm.duty_ns(1055*10**3)
def set_throttle(pwm,us): def set_throttle(pwm,us):
hertz = 50 hertz = 50
#we now have to calculate the duty_cycle! #we now have to calculate the duty_cycle!
@ -320,10 +351,7 @@ def debounce_button(p):
timer0 = Timer(0) timer0 = Timer(0)
timer0.init(period=20, mode=Timer.ONE_SHOT, callback=lambda t: on_button_press(p)) timer0.init(period=20, mode=Timer.ONE_SHOT, callback=lambda t: on_button_press(p))
rpm_counter = 0
def rpm_count(p):
global rpm_counter
rpm_counter+=1
def on_button_press(p): def on_button_press(p):
@ -419,12 +447,14 @@ def save_config():
text = 'Now is the time for all good men to come to the aid of the party.'
power = Pin(m5stack.TFT_LED_PIN, Pin.OUT) power = Pin(m5stack.TFT_LED_PIN, Pin.OUT)
power.value(1) power.value(1)
timer1 = Timer(1) timer1 = Timer(1)
timer2 = Timer(2) timer2 = Timer(2)
counter = Counter(0,Pin(19,Pin.IN))
timer3 = Timer(3)
# No need to change the software. It's just a matter of different names.. Use this translation: # No need to change the software. It's just a matter of different names.. Use this translation:
@ -457,7 +487,6 @@ display = tft
tft.initr() tft.initr()
tft.rgb(True) tft.rgb(True)
#tftprinttest() #tftprinttest()
uart = UART(1, baudrate=115200, rx=5) # to receive ESC telemetry
rotary = RotaryIRQ( rotary = RotaryIRQ(
pin_num_clk=25, pin_num_clk=25,
pin_num_dt=13, pin_num_dt=13,
@ -469,8 +498,6 @@ rotary = RotaryIRQ(
button = Pin(15, Pin.IN, Pin.PULL_UP) button = Pin(15, Pin.IN, Pin.PULL_UP)
button.irq(trigger=Pin.IRQ_FALLING, handler=on_button_press) button.irq(trigger=Pin.IRQ_FALLING, handler=on_button_press)
#interrupt for rpm sensor! #interrupt for rpm sensor!
rpm_pin = Pin(19, Pin.IN, Pin.PULL_UP)
rpm_pin.irq(trigger=Pin.IRQ_FALLING, handler=rpm_count)
state = { state = {
"view": start_view, "view": start_view,
@ -492,27 +519,10 @@ tft.fill(TFT.BLACK)
# display.set_font(ff) # display.set_font(ff)
# display.print(text) # display.print(text)
update_motor_pwm() update_motor_pwm()
print(rpm_counter)
# event_loop = uasyncio.get_event_loop() # event_loop = uasyncio.get_event_loop()
# event_loop.create_task(update_display()) # event_loop.create_task(update_display())
# event_loop.create_task(update_motor_pwm()) # #event_loop.create_task(update_motor_pwm())
# event_loop.run_forever() # event_loop.run_forever()
# pwm = PWM(Pin(26))
# rpm_pid = PID(
# Kp=config["PID"]["Kp"],
# Ki=config["PID"]["Ki"],
# Kd=config["PID"]["Kd"],
# setpoint=0,
# sample_time=None,
# output_limits=(0.0, 1.0),
# # proportional_on_measurement=True,
# )
# pwm.freq(50)
# # pwm.duty_u16(1638)
# # pwm.duty_u16(8192)
# # set_throttle(pwm,1055)
# pwm.duty_ns(1055*10**3)
# time.sleep(3)
# pwm.duty_ns(1070*10**3)

263
src/sysfont.py Normal file
View file

@ -0,0 +1,263 @@
#Font used for ST7735 display.
#Each character uses 5 bytes.
#index using ASCII value * 5.
#Each byte contains a column of pixels.
#The character may be 8 pixels high and 5 wide.
sysfont = {"Width": 5, "Height": 8, "Start": 0, "End": 254, "Data": bytearray([
0x00, 0x00, 0x00, 0x00, 0x00,
0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
0x18, 0x3C, 0x7E, 0x3C, 0x18,
0x1C, 0x57, 0x7D, 0x57, 0x1C,
0x1C, 0x5E, 0x7F, 0x5E, 0x1C,
0x00, 0x18, 0x3C, 0x18, 0x00,
0xFF, 0xE7, 0xC3, 0xE7, 0xFF,
0x00, 0x18, 0x24, 0x18, 0x00,
0xFF, 0xE7, 0xDB, 0xE7, 0xFF,
0x30, 0x48, 0x3A, 0x06, 0x0E,
0x26, 0x29, 0x79, 0x29, 0x26,
0x40, 0x7F, 0x05, 0x05, 0x07,
0x40, 0x7F, 0x05, 0x25, 0x3F,
0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
0x7F, 0x3E, 0x1C, 0x1C, 0x08,
0x08, 0x1C, 0x1C, 0x3E, 0x7F,
0x14, 0x22, 0x7F, 0x22, 0x14,
0x5F, 0x5F, 0x00, 0x5F, 0x5F,
0x06, 0x09, 0x7F, 0x01, 0x7F,
0x00, 0x66, 0x89, 0x95, 0x6A,
0x60, 0x60, 0x60, 0x60, 0x60,
0x94, 0xA2, 0xFF, 0xA2, 0x94,
0x08, 0x04, 0x7E, 0x04, 0x08,
0x10, 0x20, 0x7E, 0x20, 0x10,
0x08, 0x08, 0x2A, 0x1C, 0x08,
0x08, 0x1C, 0x2A, 0x08, 0x08,
0x1E, 0x10, 0x10, 0x10, 0x10,
0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
0x30, 0x38, 0x3E, 0x38, 0x30,
0x06, 0x0E, 0x3E, 0x0E, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x5F, 0x00, 0x00,
0x00, 0x07, 0x00, 0x07, 0x00,
0x14, 0x7F, 0x14, 0x7F, 0x14,
0x24, 0x2A, 0x7F, 0x2A, 0x12,
0x23, 0x13, 0x08, 0x64, 0x62,
0x36, 0x49, 0x56, 0x20, 0x50,
0x00, 0x08, 0x07, 0x03, 0x00,
0x00, 0x1C, 0x22, 0x41, 0x00,
0x00, 0x41, 0x22, 0x1C, 0x00,
0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
0x08, 0x08, 0x3E, 0x08, 0x08,
0x00, 0x80, 0x70, 0x30, 0x00,
0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x60, 0x60, 0x00,
0x20, 0x10, 0x08, 0x04, 0x02,
0x3E, 0x51, 0x49, 0x45, 0x3E,
0x00, 0x42, 0x7F, 0x40, 0x00,
0x72, 0x49, 0x49, 0x49, 0x46,
0x21, 0x41, 0x49, 0x4D, 0x33,
0x18, 0x14, 0x12, 0x7F, 0x10,
0x27, 0x45, 0x45, 0x45, 0x39,
0x3C, 0x4A, 0x49, 0x49, 0x31,
0x41, 0x21, 0x11, 0x09, 0x07,
0x36, 0x49, 0x49, 0x49, 0x36,
0x46, 0x49, 0x49, 0x29, 0x1E,
0x00, 0x00, 0x14, 0x00, 0x00,
0x00, 0x40, 0x34, 0x00, 0x00,
0x00, 0x08, 0x14, 0x22, 0x41,
0x14, 0x14, 0x14, 0x14, 0x14,
0x00, 0x41, 0x22, 0x14, 0x08,
0x02, 0x01, 0x59, 0x09, 0x06,
0x3E, 0x41, 0x5D, 0x59, 0x4E,
0x7C, 0x12, 0x11, 0x12, 0x7C,
0x7F, 0x49, 0x49, 0x49, 0x36,
0x3E, 0x41, 0x41, 0x41, 0x22,
0x7F, 0x41, 0x41, 0x41, 0x3E,
0x7F, 0x49, 0x49, 0x49, 0x41,
0x7F, 0x09, 0x09, 0x09, 0x01,
0x3E, 0x41, 0x41, 0x51, 0x73,
0x7F, 0x08, 0x08, 0x08, 0x7F,
0x00, 0x41, 0x7F, 0x41, 0x00,
0x20, 0x40, 0x41, 0x3F, 0x01,
0x7F, 0x08, 0x14, 0x22, 0x41,
0x7F, 0x40, 0x40, 0x40, 0x40,
0x7F, 0x02, 0x1C, 0x02, 0x7F,
0x7F, 0x04, 0x08, 0x10, 0x7F,
0x3E, 0x41, 0x41, 0x41, 0x3E,
0x7F, 0x09, 0x09, 0x09, 0x06,
0x3E, 0x41, 0x51, 0x21, 0x5E,
0x7F, 0x09, 0x19, 0x29, 0x46,
0x26, 0x49, 0x49, 0x49, 0x32,
0x03, 0x01, 0x7F, 0x01, 0x03,
0x3F, 0x40, 0x40, 0x40, 0x3F,
0x1F, 0x20, 0x40, 0x20, 0x1F,
0x3F, 0x40, 0x38, 0x40, 0x3F,
0x63, 0x14, 0x08, 0x14, 0x63,
0x03, 0x04, 0x78, 0x04, 0x03,
0x61, 0x59, 0x49, 0x4D, 0x43,
0x00, 0x7F, 0x41, 0x41, 0x41,
0x02, 0x04, 0x08, 0x10, 0x20,
0x00, 0x41, 0x41, 0x41, 0x7F,
0x04, 0x02, 0x01, 0x02, 0x04,
0x40, 0x40, 0x40, 0x40, 0x40,
0x00, 0x03, 0x07, 0x08, 0x00,
0x20, 0x54, 0x54, 0x78, 0x40,
0x7F, 0x28, 0x44, 0x44, 0x38,
0x38, 0x44, 0x44, 0x44, 0x28,
0x38, 0x44, 0x44, 0x28, 0x7F,
0x38, 0x54, 0x54, 0x54, 0x18,
0x00, 0x08, 0x7E, 0x09, 0x02,
0x18, 0xA4, 0xA4, 0x9C, 0x78,
0x7F, 0x08, 0x04, 0x04, 0x78,
0x00, 0x44, 0x7D, 0x40, 0x00,
0x20, 0x40, 0x40, 0x3D, 0x00,
0x7F, 0x10, 0x28, 0x44, 0x00,
0x00, 0x41, 0x7F, 0x40, 0x00,
0x7C, 0x04, 0x78, 0x04, 0x78,
0x7C, 0x08, 0x04, 0x04, 0x78,
0x38, 0x44, 0x44, 0x44, 0x38,
0xFC, 0x18, 0x24, 0x24, 0x18,
0x18, 0x24, 0x24, 0x18, 0xFC,
0x7C, 0x08, 0x04, 0x04, 0x08,
0x48, 0x54, 0x54, 0x54, 0x24,
0x04, 0x04, 0x3F, 0x44, 0x24,
0x3C, 0x40, 0x40, 0x20, 0x7C,
0x1C, 0x20, 0x40, 0x20, 0x1C,
0x3C, 0x40, 0x30, 0x40, 0x3C,
0x44, 0x28, 0x10, 0x28, 0x44,
0x4C, 0x90, 0x90, 0x90, 0x7C,
0x44, 0x64, 0x54, 0x4C, 0x44,
0x00, 0x08, 0x36, 0x41, 0x00,
0x00, 0x00, 0x77, 0x00, 0x00,
0x00, 0x41, 0x36, 0x08, 0x00,
0x02, 0x01, 0x02, 0x04, 0x02,
0x3C, 0x26, 0x23, 0x26, 0x3C,
0x1E, 0xA1, 0xA1, 0x61, 0x12,
0x3A, 0x40, 0x40, 0x20, 0x7A,
0x38, 0x54, 0x54, 0x55, 0x59,
0x21, 0x55, 0x55, 0x79, 0x41,
0x21, 0x54, 0x54, 0x78, 0x41,
0x21, 0x55, 0x54, 0x78, 0x40,
0x20, 0x54, 0x55, 0x79, 0x40,
0x0C, 0x1E, 0x52, 0x72, 0x12,
0x39, 0x55, 0x55, 0x55, 0x59,
0x39, 0x54, 0x54, 0x54, 0x59,
0x39, 0x55, 0x54, 0x54, 0x58,
0x00, 0x00, 0x45, 0x7C, 0x41,
0x00, 0x02, 0x45, 0x7D, 0x42,
0x00, 0x01, 0x45, 0x7C, 0x40,
0xF0, 0x29, 0x24, 0x29, 0xF0,
0xF0, 0x28, 0x25, 0x28, 0xF0,
0x7C, 0x54, 0x55, 0x45, 0x00,
0x20, 0x54, 0x54, 0x7C, 0x54,
0x7C, 0x0A, 0x09, 0x7F, 0x49,
0x32, 0x49, 0x49, 0x49, 0x32,
0x32, 0x48, 0x48, 0x48, 0x32,
0x32, 0x4A, 0x48, 0x48, 0x30,
0x3A, 0x41, 0x41, 0x21, 0x7A,
0x3A, 0x42, 0x40, 0x20, 0x78,
0x00, 0x9D, 0xA0, 0xA0, 0x7D,
0x39, 0x44, 0x44, 0x44, 0x39,
0x3D, 0x40, 0x40, 0x40, 0x3D,
0x3C, 0x24, 0xFF, 0x24, 0x24,
0x48, 0x7E, 0x49, 0x43, 0x66,
0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
0xFF, 0x09, 0x29, 0xF6, 0x20,
0xC0, 0x88, 0x7E, 0x09, 0x03,
0x20, 0x54, 0x54, 0x79, 0x41,
0x00, 0x00, 0x44, 0x7D, 0x41,
0x30, 0x48, 0x48, 0x4A, 0x32,
0x38, 0x40, 0x40, 0x22, 0x7A,
0x00, 0x7A, 0x0A, 0x0A, 0x72,
0x7D, 0x0D, 0x19, 0x31, 0x7D,
0x26, 0x29, 0x29, 0x2F, 0x28,
0x26, 0x29, 0x29, 0x29, 0x26,
0x30, 0x48, 0x4D, 0x40, 0x20,
0x38, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x38,
0x2F, 0x10, 0xC8, 0xAC, 0xBA,
0x2F, 0x10, 0x28, 0x34, 0xFA,
0x00, 0x00, 0x7B, 0x00, 0x00,
0x08, 0x14, 0x2A, 0x14, 0x22,
0x22, 0x14, 0x2A, 0x14, 0x08,
0xAA, 0x00, 0x55, 0x00, 0xAA,
0xAA, 0x55, 0xAA, 0x55, 0xAA,
0x00, 0x00, 0x00, 0xFF, 0x00,
0x10, 0x10, 0x10, 0xFF, 0x00,
0x14, 0x14, 0x14, 0xFF, 0x00,
0x10, 0x10, 0xFF, 0x00, 0xFF,
0x10, 0x10, 0xF0, 0x10, 0xF0,
0x14, 0x14, 0x14, 0xFC, 0x00,
0x14, 0x14, 0xF7, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0xFF,
0x14, 0x14, 0xF4, 0x04, 0xFC,
0x14, 0x14, 0x17, 0x10, 0x1F,
0x10, 0x10, 0x1F, 0x10, 0x1F,
0x14, 0x14, 0x14, 0x1F, 0x00,
0x10, 0x10, 0x10, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x1F, 0x10,
0x10, 0x10, 0x10, 0x1F, 0x10,
0x10, 0x10, 0x10, 0xF0, 0x10,
0x00, 0x00, 0x00, 0xFF, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0xFF, 0x10,
0x00, 0x00, 0x00, 0xFF, 0x14,
0x00, 0x00, 0xFF, 0x00, 0xFF,
0x00, 0x00, 0x1F, 0x10, 0x17,
0x00, 0x00, 0xFC, 0x04, 0xF4,
0x14, 0x14, 0x17, 0x10, 0x17,
0x14, 0x14, 0xF4, 0x04, 0xF4,
0x00, 0x00, 0xFF, 0x00, 0xF7,
0x14, 0x14, 0x14, 0x14, 0x14,
0x14, 0x14, 0xF7, 0x00, 0xF7,
0x14, 0x14, 0x14, 0x17, 0x14,
0x10, 0x10, 0x1F, 0x10, 0x1F,
0x14, 0x14, 0x14, 0xF4, 0x14,
0x10, 0x10, 0xF0, 0x10, 0xF0,
0x00, 0x00, 0x1F, 0x10, 0x1F,
0x00, 0x00, 0x00, 0x1F, 0x14,
0x00, 0x00, 0x00, 0xFC, 0x14,
0x00, 0x00, 0xF0, 0x10, 0xF0,
0x10, 0x10, 0xFF, 0x10, 0xFF,
0x14, 0x14, 0x14, 0xFF, 0x14,
0x10, 0x10, 0x10, 0x1F, 0x00,
0x00, 0x00, 0x00, 0xF0, 0x10,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
0x38, 0x44, 0x44, 0x38, 0x44,
0x7C, 0x2A, 0x2A, 0x3E, 0x14,
0x7E, 0x02, 0x02, 0x06, 0x06,
0x02, 0x7E, 0x02, 0x7E, 0x02,
0x63, 0x55, 0x49, 0x41, 0x63,
0x38, 0x44, 0x44, 0x3C, 0x04,
0x40, 0x7E, 0x20, 0x1E, 0x20,
0x06, 0x02, 0x7E, 0x02, 0x02,
0x99, 0xA5, 0xE7, 0xA5, 0x99,
0x1C, 0x2A, 0x49, 0x2A, 0x1C,
0x4C, 0x72, 0x01, 0x72, 0x4C,
0x30, 0x4A, 0x4D, 0x4D, 0x30,
0x30, 0x48, 0x78, 0x48, 0x30,
0xBC, 0x62, 0x5A, 0x46, 0x3D,
0x3E, 0x49, 0x49, 0x49, 0x00,
0x7E, 0x01, 0x01, 0x01, 0x7E,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x44, 0x44, 0x5F, 0x44, 0x44,
0x40, 0x51, 0x4A, 0x44, 0x40,
0x40, 0x44, 0x4A, 0x51, 0x40,
0x00, 0x00, 0xFF, 0x01, 0x03,
0xE0, 0x80, 0xFF, 0x00, 0x00,
0x08, 0x08, 0x6B, 0x6B, 0x08,
0x36, 0x12, 0x36, 0x24, 0x36,
0x06, 0x0F, 0x09, 0x0F, 0x06,
0x00, 0x00, 0x18, 0x18, 0x00,
0x00, 0x00, 0x10, 0x10, 0x00,
0x30, 0x40, 0xFF, 0x01, 0x01,
0x00, 0x1F, 0x01, 0x01, 0x1E,
0x00, 0x19, 0x1D, 0x17, 0x12,
0x00, 0x3C, 0x3C, 0x3C, 0x3C
])}