From 38ea42882463c8685b878cd5a3f58baf53d21075 Mon Sep 17 00:00:00 2001 From: Robert Schauklies Date: Sun, 2 Nov 2025 00:02:25 +0100 Subject: [PATCH] rpm sensor+pwm is working in a slightly cursed way --- src/main.py | 148 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 122 insertions(+), 26 deletions(-) diff --git a/src/main.py b/src/main.py index f70a30d..55e1ae7 100644 --- a/src/main.py +++ b/src/main.py @@ -1,7 +1,7 @@ # 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 machine import Pin, SPI,Timer, UART,PWM from ST7735 import TFT,TFTColor import m5stack import tt14 @@ -80,7 +80,7 @@ def fafo(): for col in range(w): bgr = f.read(3) tft._pushcolor(TFTColor(bgr[2],bgr[1],bgr[0])) - time.sleep(10) + time.sleep(5) def tftprinttest(): tft.fill(TFT.BLACK) v = 30 @@ -155,17 +155,17 @@ def draw_rpm(rpm): def deposit_view(state, rotary): # display.fill_rect(0, 0, 127, 14, 1) - display.text("Deposit") + display.print("Deposit") draw_rpm(state["rpm"]) - display.text("Press to") - display.text("continue") + display.print("Press to") + display.print("continue") def coating_view(state, rotary): # display.fill_rect() - display.text("Coating") + display.print("Coating") draw_rpm(state["rpm"]) - display.text("{: >{w}} sec".format(state["timer"], w=4)) + display.print("{: >{w}} sec".format(state["timer"], w=4)) def decode_ESC_telemetry(data, motor_poles=14): @@ -201,7 +201,7 @@ async def update_display(): global state global rotary while True: - display.fill(color565(0,0,0)) + display.print("LOLOLOL") state["view"](state, rotary) await uasyncio.sleep_ms(200) @@ -210,7 +210,7 @@ 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)) + dshot = Dshot(pin=Pin(25)) rpm_pid = PID( Kp=config["PID"]["Kp"], Ki=config["PID"]["Ki"], @@ -229,14 +229,14 @@ async def update_motor(): 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"], - # ) + print( + "Throttle:", + throttle, + "pid components:", + rpm_pid.components, + "RPM:", + state["rpm"], + ) if state["target_rpm"] == 0 and state["rpm"] < 1000: throttle = 0 @@ -244,13 +244,87 @@ async def update_motor(): dshot.set_throttle(throttle) await uasyncio.sleep_ms(1) +def update_motor_pwm(): + 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(1) + pwm.duty_ns(1070*10**3) + + time.sleep(10) + 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) + # time.sleep(10) # keep low signal to arm + # # for i in range(1060,1800): + # # pwm.duty_u16(i*3) + # # time.sleep(1) + # pwm.duty_ns(1070*10**3) + # pwm.duty_u16(1700) + # time.sleep(200) + 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() +def set_throttle(pwm,us): + hertz = 50 + #we now have to calculate the duty_cycle! + # Period defined as 1/Hertz, we need to multiply by 1_000_000 to calculate to microseconds + period = (1/hertz)*1000000 + # us = max(1060, min(1860, us)) + #our thing has to be one for x microseconds during the period! + duty_cycle_percentage = (us/period)*100 + + duty = int((duty_cycle_percentage/100))*65535 + print(duty) + pwm.duty_u16(duty) def debounce_button(p): p.irq(trigger=Pin.IRQ_FALLING, handler=None) # remove irq timer0 = Timer(0) 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): p.irq(trigger=Pin.IRQ_FALLING, handler=debounce_button) # restore irq @@ -264,7 +338,6 @@ def on_button_press(p): 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"]), ) @@ -285,6 +358,7 @@ def on_button_press(p): if state["view"] == edit_coating_rpm_view: state["view"] = edit_coating_time_view rotary.set( + max_val=1000, min_val=0, max_val=9999, range_mode=RotaryIRQ.RANGE_BOUNDED, @@ -295,8 +369,8 @@ def on_button_press(p): 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: + return state["view"] = coating_view start_coating(state) return @@ -363,7 +437,6 @@ timer2 = Timer(2) # CS CS # GND GND # VCC VCC -print("BOOOOOOTTT2T") spi = SPI( 2, baudrate=40000000, @@ -384,7 +457,7 @@ display = tft tft.initr() tft.rgb(True) #tftprinttest() - +uart = UART(1, baudrate=115200, rx=5) # to receive ESC telemetry rotary = RotaryIRQ( pin_num_clk=25, pin_num_dt=13, @@ -395,6 +468,10 @@ rotary = RotaryIRQ( ) button = Pin(15, Pin.IN, Pin.PULL_UP) button.irq(trigger=Pin.IRQ_FALLING, handler=on_button_press) +#interrupt for rpm sensor! +rpm_pin = Pin(19, Pin.IN, Pin.PULL_UP) +rpm_pin.irq(trigger=Pin.IRQ_FALLING, handler=rpm_count) + state = { "view": start_view, "rpm": 0, @@ -410,13 +487,32 @@ with open("config.json", "r") as f: tft.fill(TFT.BLACK) # splash() -fafo() +#fafo() # for ff in fonts: # display.set_font(ff) # display.print(text) -event_loop = uasyncio.get_event_loop() -event_loop.create_task(update_display()) +update_motor_pwm() +print(rpm_counter) +# event_loop = uasyncio.get_event_loop() +# event_loop.create_task(update_display()) -#event_loop.create_task(update_motor()) -event_loop.run_forever() +# event_loop.create_task(update_motor_pwm()) +# 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)