diff --git a/README.md b/README.md index f8fdc53..a8976b6 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,11 @@ Для работы ПО на компьютере необходимо установить `python3`, создать `venv` и установить все библиотеки, что описаны в `common/requirements.txt`. Далее просто запустить `common/main.py`. Интерфейс там интуитивно понятный. +Для имитации PWM и бенчмаркинга используется второй микроконтроллер - RP2040. На нем запускается программа `common/rp2040-pwm-generator.py`. +Для проверки работоспособности выставляется эталонная частота и эталонная длительность импульса. +Для проверки максимальной скорости работы устанавливается максимально возможная частота PWM и длительность импульса. + +# Benchmarking + +... результаты ... + diff --git a/common/rp2040-pwm-generator.py b/common/rp2040-pwm-generator.py new file mode 100644 index 0000000..8316dfd --- /dev/null +++ b/common/rp2040-pwm-generator.py @@ -0,0 +1,106 @@ +# Программа PWM-генератора с кнопкой. +# Запускать строго на отладочной плате RP2040 и Micropython! + +# Использование: если синий светодиод горит, значит PWM работает, в противном случае PWM отключен. +# Включать/отключать PWM можно нажатием кнопки USR на плате с микроконтроллером. + +import machine +from machine import Pin +import time +from time import ticks_ms + +PWM_PIN = 23 # пин PWM +PWM_FREQ = 100 # частота PWM +PWM_DUTY_US = 100000 # длительность каждого импульса в микросекундах + + +class Button(object): + rest_state = False + # pin = None + # pin_number = 0 + RELEASED = 'released' + PRESSED = 'pressed' + DEBOUNCE_TIME = 50 + + def __init__(self, pin, rest_state = False, callback = None, internal_pullup = False, internal_pulldown = False, debounce_time = None): + self.pin_number = pin + self.rest_state = rest_state + self.previous_state = rest_state + self.current_state = rest_state + self.previous_debounced_state = rest_state + self.current_debounced_state = rest_state + self.last_check_tick = ticks_ms() + self.debounce_time = debounce_time or Button.DEBOUNCE_TIME + if internal_pulldown: + self.internal_pull = Pin.PULL_DOWN + self.rest_state = False + elif internal_pullup: + self.internal_pull = Pin.PULL_UP + self.rest_state = True + else: + self.internal_pull = None + self.pin = Pin(pin, mode = Pin.IN, pull = self.internal_pull) + self.callback = callback + self.active = False + + def debounce(self): + ms_now = ticks_ms() + self.current_state = self.pin.value() + state_changed = self.current_state != self.previous_state + if state_changed: + self.last_check_tick = ms_now + state_stable = (ms_now - self.last_check_tick) > self.debounce_time + if state_stable and not state_changed: + self.last_check_tick = ms_now + self.current_debounced_state = self.current_state + self.previous_state = self.current_state + + def check_debounce_state(self): + if self.current_debounced_state != self.previous_debounced_state: + if self.current_debounced_state != self.rest_state: + self.active = True + if self.callback != None: + self.callback(self.pin_number, Button.PRESSED) + else: + self.active = False + if self.callback != None: + self.callback(self.pin_number, Button.RELEASED) + self.previous_debounced_state = self.current_debounced_state + + def update(self): + self.debounce() + self.check_debounce_state() + + +onboard_led = Pin(25, mode=Pin.OUT, value=0) +pwm_enabled = False +pwm = machine.PWM(Pin(PWM_PIN), freq=PWM_FREQ) + + +def pwm_button_callback(pin, state): + global onboard_led, pwm_enabled, pwm + if state == Button.PRESSED: + pwm_enabled = not pwm_enabled + if pwm_enabled: + pwm.duty_ns(PWM_DUTY_US) + print("PWM active!") + onboard_led.value(1) + else: + pwm.duty_u16(0) + print("PWM stoped!") + onboard_led.value(0) + + +def main(): + #lcd = SoftwareLcd() + bu = Button(pin=24, internal_pullup=True, callback=pwm_button_callback) + while True: + bu.update() + #onboard_led.value(onboard_led.value() ^ 1) + #lcd.send_data(0x40) + time.sleep_ms(1) + + +if __name__ == '__main__': + main() +