adds the correct driver, as the IL driver wasn't cut out for the job
This commit is contained in:
parent
5ed20aef7f
commit
bb33920af9
4 changed files with 1275 additions and 72 deletions
395
src/main.py
395
src/main.py
|
|
@ -1,76 +1,312 @@
|
|||
# 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
|
||||
import json
|
||||
from enum import Enum
|
||||
|
||||
class EditMenu(Enum):
|
||||
DEPOSIT = 1
|
||||
COATING = 2
|
||||
TIME = 3
|
||||
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"
|
||||
display.print(text,size=2)
|
||||
|
||||
#display.set_font(tt14)
|
||||
before = "> " if rotary.value() == 0 else " "
|
||||
display.print(before + "Edit")
|
||||
before = "> " if rotary.value() == 1 else " "
|
||||
display.print(before + "Start")
|
||||
#print(rotary.value())
|
||||
|
||||
def draw_edit_menu(state, rotary):
|
||||
display.print("Deposit speed:")
|
||||
display.print("{: >{w}} RPM".format(config["deposit_rpm"], w=5))
|
||||
display.print("Coating speed:")
|
||||
display.print("{: >{w}} RPM".format(config["coating_rpm"], w=5))
|
||||
display.print("Coating time:")
|
||||
display.print("{: >{w}} sec".format(config["coating_time"],w=2))
|
||||
display.reset_pos()
|
||||
|
||||
def edit_deposit_view(state, rotary):
|
||||
config["deposit_rpm"] = rotary.value() * 100
|
||||
draw_edit_menu(state, rotary)
|
||||
|
||||
|
||||
def edit_coating_rpm_view(state, rotary):
|
||||
config["coating_rpm"] = rotary.value() * 100
|
||||
|
||||
draw_edit_menu(state, rotary)
|
||||
|
||||
|
||||
def edit_coating_time_view(state, rotary):
|
||||
config["coating_time"] = rotary.value()
|
||||
draw_edit_menu(state, rotary)
|
||||
|
||||
|
||||
def draw_rpm(rpm):
|
||||
display.print("RPM:{: >{w}.0f}".format(rpm, w=5))
|
||||
|
||||
|
||||
def deposit_view(state, rotary):
|
||||
# display.fill_rect(0, 0, 127, 14, 1)
|
||||
display.text("Deposit")
|
||||
draw_rpm(state["rpm"])
|
||||
display.text("Press to")
|
||||
display.text("continue")
|
||||
|
||||
|
||||
def coating_view(state, rotary):
|
||||
# display.fill_rect()
|
||||
display.text("Coating")
|
||||
draw_rpm(state["rpm"])
|
||||
display.text("{: >{w}} sec".format(state["timer"], w=4))
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -78,8 +314,8 @@ 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)
|
||||
|
||||
|
||||
timer1 = Timer(1)
|
||||
timer2 = Timer(2)
|
||||
# No need to change the software. It's just a matter of different names.. Use this translation:
|
||||
|
||||
# SDO(MISO) <not used>
|
||||
|
|
@ -91,7 +327,7 @@ power.value(1)
|
|||
# CS CS
|
||||
# GND GND
|
||||
# VCC VCC
|
||||
print("BOOOOOOTTTT")
|
||||
print("BOOOOOOTTT2T")
|
||||
spi = SPI(
|
||||
2,
|
||||
baudrate=40000000,
|
||||
|
|
@ -99,14 +335,20 @@ 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)
|
||||
display = tft
|
||||
tft.initr()
|
||||
tft.rgb(True)
|
||||
#tftprinttest()
|
||||
|
||||
rotary = RotaryIRQ(
|
||||
pin_num_clk=25,
|
||||
pin_num_dt=13,
|
||||
|
|
@ -117,12 +359,27 @@ 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
|
||||
}
|
||||
with open("config.json", "r") as f:
|
||||
config = json.load(f)
|
||||
#display.erase()
|
||||
#display.set_pos(0,0)
|
||||
#display.set_font(tt32)
|
||||
tft.fill(TFT.BLACK)
|
||||
|
||||
splash()
|
||||
# for ff in fonts:
|
||||
# display.set_font(ff)
|
||||
# display.print(text)
|
||||
event_loop = uasyncio.get_event_loop()
|
||||
event_loop.create_task(update_display())
|
||||
|
||||
display.erase()
|
||||
display.set_pos(0,0)
|
||||
for ff in fonts:
|
||||
display.set_font(ff)
|
||||
display.print(text)
|
||||
|
||||
#event_loop.create_task(update_motor())
|
||||
event_loop.run_forever()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue