adds the correct driver, as the IL driver wasn't cut out for the job

This commit is contained in:
Robert Schauklies 2025-10-11 22:40:39 +02:00
parent 5ed20aef7f
commit 59daa25a91
2 changed files with 1253 additions and 68 deletions

View file

@ -1,76 +1,305 @@
# test of printing multiple fonts to the ILI9341 on an M5Stack using H/W SP
# MIT License; Copyright (c) 2017 Jeffrey N. Magee
from ili934xnew import ILI9341, color565
from machine import Pin, SPI,Timer
from ST7735 import TFT
import m5stack
import tt14
import glcdfont
import tt14
import tt24
import tt32
import uasyncio
from rotary_irq_esp import RotaryIRQ
fonts = [glcdfont,tt14,tt24,tt32]
from sysfont import sysfont
def splash():
# display.fill(0)
# display.fill_rect(0, 0, 32, 32, 1)
# display.fill_rect(2, 2, 28, 28, 0)
# display.vline(9, 8, 22, 1)
# display.vline(16, 2, 22, 1)
# display.vline(23, 8, 22, 1)
# display.fill_rect(26, 24, 2, 4, 1)
# display.text("MicroPython", 40, 0, 1)
# display.text("SSD1306", 40, 12, 1)
# display.text("OLED 128x64", 40, 24, 1)
#display.fill(0)
# display.text("SPIN", 34, 4, 1)
# display.text("COATER", 50, 14, 1)
# display.print("Spinner")
# display.print("COATER")
# tft.text((0,y),"Spin Coater",TFT.RED,sysfont,1,nowrap=True)
display.print("Spincoater",size=1,nowrap=True)
display.print("Spincoater",size=3,nowrap=True)
# #display.show()
# def tftprinttest():
# tft.fill(TFT.BLACK);
# v = 30
# tft.text((0, v), "Hello World!", TFT.RED, sysfont, 1, nowrap=True)
# v += sysfont["Height"]
# tft.text((0, v), "Hello World!", TFT.YELLOW, sysfont, 2, nowrap=True)
# v += sysfont["Height"] * 2
# tft.text((0, v), "Hello World!", TFT.GREEN, sysfont, 3, nowrap=True)
# v += sysfont["Height"] * 3
# tft.text((0, v), str(1234.567), TFT.BLUE, sysfont, 4, nowrap=True)
# time.sleep_ms(1500)
# tft.fill(TFT.BLACK);
# v = 0
# tft.text((0, v), "Hello World!", TFT.RED, sysfont)
# v += sysfont["Height"]
# tft.text((0, v), str(math.pi), TFT.GREEN, sysfont)
# v += sysfont["Height"]
# tft.text((0, v), " Want pi?", TFT.GREEN, sysfont)
# v += sysfont["Height"] * 2
# tft.text((0, v), hex(8675309), TFT.GREEN, sysfont)
# v += sysfont["Height"]
# tft.text((0, v), " Print HEX!", TFT.GREEN, sysfont)
# v += sysfont["Height"] * 2
# tft.text((0, v), "Sketch has been", TFT.WHITE, sysfont)
# v += sysfont["Height"]
# tft.text((0, v), "running for: ", TFT.WHITE, sysfont)
# v += sysfont["Height"]
# tft.text((0, v), str(time.ticks_ms() / 1000), TFT.PURPLE, sysfont)
# v += sysfont["Height"]
# tft.text((0, v), " seconds.", TFT.WHITE, sysfont)
def start_view(state, rotary):
display.set_pos(0,0)
text="Spin Coater\n"
#display.set_font(tt14)
text += "> " if rotary.value() == 0 else " "
text+="Edit\n"
text+= "> " if rotary.value() == 1 else " "
text+= "Start\n"
display.print(text)
#print(rotary.value())
def draw_edit_menu(state, rotary):
display.text("Deposit speed:", 0, 0, 1)
display.text("{: >{w}} RPM".format(config["deposit_rpm"], w=5), 56, 10, 1)
display.text("Coating speed:", 0, 21, 1)
display.text("{: >{w}} RPM".format(config["coating_rpm"], w=5), 56, 31, 1)
display.text("Coating time:", 0, 42, 1)
display.text("{: >{w}} sec".format(config["coating_time"], w=5), 56, 52, 1)
def edit_deposit_view(state, rotary):
config["deposit_rpm"] = rotary.value() * 100
draw_edit_menu(state, rotary)
display.text(">", 40, 10, 1)
def edit_coating_rpm_view(state, rotary):
config["coating_rpm"] = rotary.value() * 100
draw_edit_menu(state, rotary)
display.text(">", 40, 32, 1)
def edit_coating_time_view(state, rotary):
config["coating_time"] = rotary.value()
draw_edit_menu(state, rotary)
display.text(">", 40, 54, 1)
def draw_rpm(rpm):
display.text("RPM:{: >{w}.0f}".format(rpm, w=5), 30, 27, 1)
def deposit_view(state, rotary):
display.fill_rect(0, 0, 127, 14, 1)
display.text("Deposit", 36, 3, 0)
draw_rpm(state["rpm"])
display.text("Press to", 32, 42, 1)
display.text("continue", 32, 52, 1)
def coating_view(state, rotary):
display.fill_rect(0, 0, 127, 14, 1)
display.text("Coating", 36, 3, 0)
draw_rpm(state["rpm"])
display.text("{: >{w}} sec".format(state["timer"], w=4), 30, 48, 1)
def decode_ESC_telemetry(data, motor_poles=14):
if len(data) > 10:
# use latest telemetry
data = data[-10:]
temperature = int(data[0]) # degrees Celsius
voltage = int((data[1] << 8) | data[2]) * 0.01 # Volt
current = (
int((data[3] << 8) | data[4]) * 0.01
) # Amps, only available if the ESC has a current meter
consumption = int(
(data[5] << 8) | data[6]
) # mAh, only available if the ESC has a current meter
erpm = int((data[7] << 8) | data[8]) * 100
rpm = erpm / (motor_poles / 2)
crc = data[9]
print(" Temp (C):", temperature)
print(" Voltage (V):", voltage)
print(" Current (A):", current)
print("Consumption (mAh):", consumption)
print(" Erpm:", erpm)
print(" RPM:", rpm)
print(" CRC:", crc)
print()
return temperature, voltage, current, consumption, erpm, rpm
async def update_display():
global state
global rotary
while True:
display.fill(color565(0,0,0))
state["view"](state, rotary)
display.show()
await uasyncio.sleep_ms(33)
async def update_motor():
global state
#we want to use 18 for the SPI-Bus!
#https://docs.micropython.org/en/latest/esp32/quickref.html#hardware-spi-bus
dshot = Dshot(pin=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,
)
while True:
rpm_pid.setpoint = state["target_rpm"]
# read ESC telemetry
if uart.any() >= 10:
telemetry = decode_ESC_telemetry(uart.read())
if telemetry is not None:
state["rpm"] = telemetry[5]
throttle = rpm_pid(state["rpm"])
# print(
# "Throttle:",
# throttle,
# "pid components:",
# rpm_pid.components,
# "RPM:",
# state["rpm"],
# )
if state["target_rpm"] == 0 and state["rpm"] < 1000:
throttle = 0
rpm_pid.reset()
dshot.set_throttle(throttle)
await uasyncio.sleep_ms(1)
def debounce_button(p):
p.irq(trigger=Pin.IRQ_FALLING, handler=None) # remove irq
timer0 = Timer(0)
print("Button debounced!")
timer0.init(period=20, mode=Timer.ONE_SHOT, callback=lambda t: on_button_press(p))
def on_button_press(p):
p.irq(trigger=Pin.IRQ_FALLING, handler=debounce_button) # restore irq
print("Button pressed")
if p.value() == 1: # debounce
return
# return
# global state
# global config
# global rotary
# if state["view"] == start_view:
# if rotary.value() == 0:
# state["view"] = edit_deposit_view
# rotary.set(
# min_val=0,
# max_val=1000,
# range_mode=RotaryIRQ.RANGE_BOUNDED,
# value=int(0.01 * config["deposit_rpm"]),
# )
# return
# if rotary.value() == 1:
# state["view"] = deposit_view
# state["target_rpm"] = config["deposit_rpm"]
# return
# if state["view"] == edit_deposit_view:
# state["view"] = edit_coating_rpm_view
# rotary.set(
# min_val=0,
# max_val=1000,
# range_mode=RotaryIRQ.RANGE_BOUNDED,
# value=int(0.01 * config["coating_rpm"]),
# )
# return
# if state["view"] == edit_coating_rpm_view:
# state["view"] = edit_coating_time_view
# rotary.set(
# min_val=0,
# max_val=9999,
# range_mode=RotaryIRQ.RANGE_BOUNDED,
# value=config["coating_time"],
# )
# return
# if state["view"] == edit_coating_time_view:
# save_config()
# rotary.set(min_val=0, max_val=1, range_mode=RotaryIRQ.RANGE_BOUNDED, value=0)
# state["view"] = start_view
# return
# if state["view"] == deposit_view:
# state["view"] = coating_view
# start_coating(state)
# return
# if state["view"] == coating_view:
# stop_coating()
# return
global state
global config
global rotary
if state["view"] == start_view:
if rotary.value() == 0:
state["view"] = edit_deposit_view
rotary.set(
min_val=0,
max_val=1000,
range_mode=RotaryIRQ.RANGE_BOUNDED,
value=int(0.01 * config["deposit_rpm"]),
)
return
if rotary.value() == 1:
state["view"] = deposit_view
state["target_rpm"] = config["deposit_rpm"]
return
if state["view"] == edit_deposit_view:
state["view"] = edit_coating_rpm_view
rotary.set(
min_val=0,
max_val=1000,
range_mode=RotaryIRQ.RANGE_BOUNDED,
value=int(0.01 * config["coating_rpm"]),
)
return
if state["view"] == edit_coating_rpm_view:
state["view"] = edit_coating_time_view
rotary.set(
min_val=0,
max_val=9999,
range_mode=RotaryIRQ.RANGE_BOUNDED,
value=config["coating_time"],
)
return
if state["view"] == edit_coating_time_view:
save_config()
rotary.set(min_val=0, max_val=1, range_mode=RotaryIRQ.RANGE_BOUNDED, value=0)
state["view"] = start_view
return
if state["view"] == deposit_view:
state["view"] = coating_view
start_coating(state)
return
if state["view"] == coating_view:
stop_coating()
return
def start_coating(state):
global timer1
global timer2
state["timer"] = config["coating_time"]
timer1.init(
period=config["coating_time"] * 1000,
mode=Timer.ONE_SHOT,
callback=lambda t: stop_coating(),
)
def decrement_timer(t):
state["timer"] -= 1
timer2.init(period=1000, mode=Timer.PERIODIC, callback=decrement_timer)
# state["throttle"] = 0.10
state["target_rpm"] = config["coating_rpm"]
def stop_coating():
global state
global rotary
global timer1
global timer2
timer1.deinit()
timer2.deinit()
state["target_rpm"] = 0
rotary.set(min_val=0, max_val=1, range_mode=RotaryIRQ.RANGE_BOUNDED, value=0)
state["view"] = start_view
def save_config():
global config
with open("config.json", "w") as f:
json.dump(config, f)
@ -79,7 +308,6 @@ 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.value(1)
# No need to change the software. It's just a matter of different names.. Use this translation:
# SDO(MISO) <not used>
@ -91,7 +319,7 @@ power.value(1)
# CS CS
# GND GND
# VCC VCC
print("BOOOOOOTTTT")
print("BOOOOOOTTT2T")
spi = SPI(
2,
baudrate=40000000,
@ -99,14 +327,19 @@ spi = SPI(
mosi=Pin(m5stack.TFT_MOSI_PIN),
sck=Pin(m5stack.TFT_CLK_PIN))
display = ILI9341(
spi,
cs=Pin(m5stack.TFT_CS_PIN),
dc=Pin(m5stack.TFT_DC_PIN),
rst=Pin(m5stack.TFT_RST_PIN),
w=128,
h=160,
r=3)
# display = ILI9341(
# spi,
# cs=Pin(m5stack.TFT_CS_PIN),
# dc=Pin(m5stack.TFT_DC_PIN),
# rst=Pin(m5stack.TFT_RST_PIN),
# w=160,
# h=128,
# r=5)
tft = TFT(spi,m5stack.TFT_DC_PIN,m5stack.TFT_RST_PIN,m5stack.TFT_CS_PIN)
tft.initr()
tft.rgb(True)
#tftprinttest()
rotary = RotaryIRQ(
pin_num_clk=25,
pin_num_dt=13,
@ -117,12 +350,25 @@ rotary = RotaryIRQ(
)
button = Pin(15, Pin.IN, Pin.PULL_UP)
button.irq(trigger=Pin.IRQ_FALLING, handler=on_button_press)
state = {
"view": start_view,
"rpm": 0,
"target_rpm": 0,
"timer": 0,
"rotary_val":-1
}
#display.erase()
#display.set_pos(0,0)
#display.set_font(tt32)
tft.fill(TFT.BLACK)
display.erase()
display.set_pos(0,0)
for ff in fonts:
display.set_font(ff)
display.print(text)
splash()
# for ff in fonts:
# display.set_font(ff)
# display.print(text)
event_loop = uasyncio.get_event_loop()
event_loop.create_task(update_display())
#event_loop.create_task(update_motor())
event_loop.run_forever()