From 2f54fce24a468fe7d15d13d1fa39130bc6b564b0 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Wed, 24 Jul 2024 14:10:43 +0200 Subject: [PATCH 01/46] mod: _touch_events naming updated to generic _events --- arduino_alvik/arduino_alvik.py | 51 ++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index fac115e..a2653fb 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -17,8 +17,8 @@ class ArduinoAlvik: _update_thread_running = False _update_thread_id = None - _touch_events_thread_running = False - _touch_events_thread_id = None + _events_thread_running = False + _events_thread_id = None def __new__(cls): if not hasattr(cls, '_instance'): @@ -181,9 +181,9 @@ def begin(self) -> int: self._idle(1000) self._begin_update_thread() sleep_ms(100) - if self._touch_events.has_callbacks(): - print('Starting touch events') - self._start_touch_events_thread() + if self._has_events_registered(): + print('Starting events thread') + self._start_events_thread() self._reset_hw() self._flush_uart() self._snake_robot(1000) @@ -194,6 +194,17 @@ def begin(self) -> int: self._set_color_reference() return 0 + def _has_events_registered(self) -> bool: + """ + Returns True if Alvik has some events registered + :return: + """ + + return any([ + self._touch_events.has_callbacks() + # more events check + ]) + def _wait_for_ack(self) -> None: """ Waits until receives 0x00 ack from robot @@ -313,7 +324,7 @@ def stop(self): self._stop_update_thread() # stop touch events thread - self._stop_touch_events_thread() + self._stop_events_thread() # delete _instance del self.__class__._instance @@ -1056,35 +1067,38 @@ def on_touch_right_pressed(self, callback: callable, args: tuple = ()) -> None: """ self._touch_events.register_callback('on_right_pressed', callback, args) - def _start_touch_events_thread(self) -> None: + def _start_events_thread(self) -> None: """ Starts the touch events thread :return: """ - if not self.__class__._touch_events_thread_running: - self.__class__._touch_events_thread_running = True - self.__class__._touch_events_thread_id = _thread.start_new_thread(self._update_touch_events, (50,)) + if not self.__class__._events_thread_running: + self.__class__._events_thread_running = True + self.__class__._events_thread_id = _thread.start_new_thread(self._update_events, (50,)) - def _update_touch_events(self, delay_: int = 100): + def _update_events(self, delay_: int = 100): """ Updates the touch state so that touch events can be generated :param delay_: :return: """ while True: - if self.is_on() and self._touch_byte is not None: - self._touch_events.update_touch_state(self._touch_byte) - if not ArduinoAlvik._touch_events_thread_running: + if not ArduinoAlvik._events_thread_running: break + + if self.is_on(): + self._touch_events.update_touch_state(self._touch_byte) + # MORE events update callbacks to be added + sleep_ms(delay_) @classmethod - def _stop_touch_events_thread(cls): + def _stop_events_thread(cls): """ Stops the touch events thread :return: """ - cls._touch_events_thread_running = False + cls._events_thread_running = False class _ArduinoAlvikWheel: @@ -1320,13 +1334,16 @@ def _is_right_pressed(current_state, new_state) -> bool: """ return not bool(current_state & 0b10000000) and bool(new_state & 0b10000000) - def update_touch_state(self, touch_state: int): + def update_touch_state(self, touch_state: int | None): """ Updates the internal touch state and executes any possible callback :param touch_state: :return: """ + if touch_state is None: + return + if self._is_ok_pressed(self._current_touch_state, touch_state): self.execute_callback('on_ok_pressed') From 1bee06f51487944f0aa17c24feb4b1634e49cf64 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Wed, 24 Jul 2024 16:59:03 +0200 Subject: [PATCH 02/46] feat: _move_events --- arduino_alvik/arduino_alvik.py | 261 +++++++++++++++++++++++++++++++-- examples/move_events.py | 57 +++++++ 2 files changed, 302 insertions(+), 16 deletions(-) create mode 100644 examples/move_events.py diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index a2653fb..814a9b7 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -36,6 +36,7 @@ def __init__(self): rgb_mask=[0b00100000, 0b01000000, 0b10000000]) self._battery_perc = None self._touch_byte = None + self._move_byte = None self._behaviour = None self._red = None self._green = None @@ -70,6 +71,7 @@ def __init__(self): self._waiting_ack = None self._version = [None, None, None] self._touch_events = _ArduinoAlvikTouchEvents() + self._move_events = _ArduinoAlvikMoveEvents() @staticmethod def is_on() -> bool: @@ -201,7 +203,8 @@ def _has_events_registered(self) -> bool: """ return any([ - self._touch_events.has_callbacks() + self._touch_events.has_callbacks(), + self._move_events.has_callbacks() # more events check ]) @@ -614,6 +617,9 @@ def _parse_message(self) -> int: elif code == ord('t'): # touch input _, self._touch_byte = self._packeter.unpacketC1B() + elif code == ord('d'): + # movement/shake input + _, self._move_byte = self._packeter.unpacketC1B() elif code == ord('b'): # behaviour _, self._behaviour = self._packeter.unpacketC1B() @@ -723,6 +729,42 @@ def get_touch_right(self) -> bool: """ return bool(self._touch_bits & 0b10000000) + @property + def _move_bits(self) -> int: + """ + Returns the shake/tilt state + :return: + """ + return (self._move_byte & 0xFF) if self._move_byte is not None else 0x00 + + def get_shake(self) -> bool: + """ + Returns true if Alvik is shaken + :return: + """ + return bool(self._move_bits & 0b00000001) + + def get_tilt(self) -> str: + """ + Returns the tilt string eg: "X", "-Z" etc + :return: + """ + + if bool(self._move_bits & 0b00000100): + return "X" + if bool(self._move_bits & 0b00001000): + return "-X" + if bool(self._move_bits & 0b00010000): + return "Y" + if bool(self._move_bits & 0b00100000): + return "-Y" + if bool(self._move_bits & 0b01000000): + return "Z" + if bool(self._move_bits & 0b10000000): + return "-Z" + + return "" + @staticmethod def _limit(value: float, lower: float, upper: float) -> float: """ @@ -1067,6 +1109,69 @@ def on_touch_right_pressed(self, callback: callable, args: tuple = ()) -> None: """ self._touch_events.register_callback('on_right_pressed', callback, args) + def on_shake(self, callback: callable, args: tuple = ()) -> None: + """ + Register callback when Alvik is shaken + :param callback: + :param args: + :return: + """ + self._move_events.register_callback('on_shake', callback, args) + + def on_x_tilt(self, callback: callable, args: tuple = ()) -> None: + """ + Register callback when Alvik is tilted on X-axis + :param callback: + :param args: + :return: + """ + self._move_events.register_callback('on_x_tilt', callback, args) + + def on_nx_tilt(self, callback: callable, args: tuple = ()) -> None: + """ + Register callback when Alvik is tilted on negative X-axis + :param callback: + :param args: + :return: + """ + self._move_events.register_callback('on_nx_tilt', callback, args) + + def on_y_tilt(self, callback: callable, args: tuple = ()) -> None: + """ + Register callback when Alvik is tilted on Y-axis + :param callback: + :param args: + :return: + """ + self._move_events.register_callback('on_y_tilt', callback, args) + + def on_ny_tilt(self, callback: callable, args: tuple = ()) -> None: + """ + Register callback when Alvik is tilted on negative Y-axis + :param callback: + :param args: + :return: + """ + self._move_events.register_callback('on_ny_tilt', callback, args) + + def on_z_tilt(self, callback: callable, args: tuple = ()) -> None: + """ + Register callback when Alvik is tilted on Z-axis + :param callback: + :param args: + :return: + """ + self._move_events.register_callback('on_z_tilt', callback, args) + + def on_nz_tilt(self, callback: callable, args: tuple = ()) -> None: + """ + Register callback when Alvik is tilted on negative Z-axis + :param callback: + :param args: + :return: + """ + self._move_events.register_callback('on_nz_tilt', callback, args) + def _start_events_thread(self) -> None: """ Starts the touch events thread @@ -1087,7 +1192,8 @@ def _update_events(self, delay_: int = 100): break if self.is_on(): - self._touch_events.update_touch_state(self._touch_byte) + self._touch_events.update_state(self._touch_byte) + self._move_events.update_state(self._move_byte) # MORE events update callbacks to be added sleep_ms(delay_) @@ -1219,6 +1325,8 @@ class _ArduinoAlvikEvents: This is a generic events class """ + available_events = [] + def __init__(self): self._callbacks = dict() @@ -1230,6 +1338,9 @@ def register_callback(self, event_name: str, callback: callable, args: tuple = N :param args: arguments tuple to pass to the callable. remember the comma! (value,) :return: """ + + if event_name not in self.__class__.available_events: + return self._callbacks[event_name] = (callback, args,) def has_callbacks(self) -> bool: @@ -1249,6 +1360,13 @@ def execute_callback(self, event_name: str): return self._callbacks[event_name][0](*self._callbacks[event_name][1]) + def update_state(self, state): + """ + Updates the internal state of the events handler + :return: + """ + pass + class _ArduinoAlvikTouchEvents(_ArduinoAlvikEvents): """ @@ -1334,43 +1452,154 @@ def _is_right_pressed(current_state, new_state) -> bool: """ return not bool(current_state & 0b10000000) and bool(new_state & 0b10000000) - def update_touch_state(self, touch_state: int | None): + def update_state(self, state: int | None): """ Updates the internal touch state and executes any possible callback - :param touch_state: + :param state: :return: """ - if touch_state is None: + if state is None: return - if self._is_ok_pressed(self._current_touch_state, touch_state): + if self._is_ok_pressed(self._current_touch_state, state): self.execute_callback('on_ok_pressed') - if self._is_cancel_pressed(self._current_touch_state, touch_state): + if self._is_cancel_pressed(self._current_touch_state, state): self.execute_callback('on_cancel_pressed') - if self._is_center_pressed(self._current_touch_state, touch_state): + if self._is_center_pressed(self._current_touch_state, state): self.execute_callback('on_center_pressed') - if self._is_up_pressed(self._current_touch_state, touch_state): + if self._is_up_pressed(self._current_touch_state, state): self.execute_callback('on_up_pressed') - if self._is_left_pressed(self._current_touch_state, touch_state): + if self._is_left_pressed(self._current_touch_state, state): self.execute_callback('on_left_pressed') - if self._is_down_pressed(self._current_touch_state, touch_state): + if self._is_down_pressed(self._current_touch_state, state): self.execute_callback('on_down_pressed') - if self._is_right_pressed(self._current_touch_state, touch_state): + if self._is_right_pressed(self._current_touch_state, state): self.execute_callback('on_right_pressed') - self._current_touch_state = touch_state + self._current_touch_state = state - def register_callback(self, event_name: str, callback: callable, args: tuple = None): - if event_name not in self.__class__.available_events: + +class _ArduinoAlvikMoveEvents(_ArduinoAlvikEvents): + """ + Event class to handle move events + """ + + available_events = ['on_shake', 'on_x_tilt', 'on_y_tilt', 'on_z_tilt', + 'on_nx_tilt', 'on_ny_tilt', 'on_nz_tilt'] + + def __init__(self): + self._current_state = 0 + super().__init__() + + @staticmethod + def _is_shaken(current_state, new_state) -> bool: + """ + True if Alvik was shaken + :param current_state: + :param new_state: + :return: + """ + return not bool(current_state & 0b00000001) and bool(new_state & 0b00000001) + + @staticmethod + def _is_x_tilted(current_state, new_state) -> bool: + """ + True if Alvik is tilted on X-axis + :param current_state: + :param new_state: + :return: + """ + return not bool(current_state & 0b00000100) and bool(new_state & 0b00000100) + + @staticmethod + def _is_neg_x_tilted(current_state, new_state) -> bool: + """ + True if Alvik is tilted on negative X-axis + :param current_state: + :param new_state: + :return: + """ + return not bool(current_state & 0b00001000) and bool(new_state & 0b00001000) + + @staticmethod + def _is_y_tilted(current_state, new_state) -> bool: + """ + True if Alvik is tilted on Y-axis + :param current_state: + :param new_state: + :return: + """ + return not bool(current_state & 0b00010000) and bool(new_state & 0b00010000) + + @staticmethod + def _is_neg_y_tilted(current_state, new_state) -> bool: + """ + True if Alvik is tilted on negative Y-axis + :param current_state: + :param new_state: + :return: + """ + return not bool(current_state & 0b00100000) and bool(new_state & 0b00100000) + + @staticmethod + def _is_z_tilted(current_state, new_state) -> bool: + """ + True if Alvik is tilted on Z-axis + :param current_state: + :param new_state: + :return: + """ + return not bool(current_state & 0b01000000) and bool(new_state & 0b01000000) + + @staticmethod + def _is_neg_z_tilted(current_state, new_state) -> bool: + """ + True if Alvik is tilted on negative Z-axis + :param current_state: + :param new_state: + :return: + """ + return not bool(current_state & 0b10000000) and bool(new_state & 0b10000000) + + def update_state(self, state: int | None): + """ + Updates the internal state and executes any possible callback + :param state: + :return: + """ + + if state is None: return - super().register_callback(event_name, callback, args) + + if self._is_shaken(self._current_state, state): + self.execute_callback('on_shake') + + if self._is_x_tilted(self._current_state, state): + self.execute_callback('on_x_tilted') + + if self._is_neg_x_tilted(self._current_state, state): + self.execute_callback('on_nx_tilted') + + if self._is_y_tilted(self._current_state, state): + self.execute_callback('on_y_tilted') + + if self._is_neg_y_tilted(self._current_state, state): + self.execute_callback('on_ny_tilted') + + if self._is_z_tilted(self._current_state, state): + self.execute_callback('on_z_tilted') + + if self._is_neg_z_tilted(self._current_state, state): + self.execute_callback('on_nz_tilted') + + self._current_state = state # UPDATE FIRMWARE METHOD # diff --git a/examples/move_events.py b/examples/move_events.py new file mode 100644 index 0000000..264de5c --- /dev/null +++ b/examples/move_events.py @@ -0,0 +1,57 @@ +from arduino_alvik import ArduinoAlvik +from time import sleep +import sys + +value = 0 + + +def toggle_left_led(custom_text: str = '') -> None: + global value + value = (value + 1) % 2 + alvik.left_led.set_color(value, 0, 0) + print(f"RED BLINKS! {custom_text}") + + +def simple_print(custom_text: str = '') -> None: + print(custom_text) + +alvik = ArduinoAlvik() +alvik.on_shake(toggle_left_led, ("ALVIK WAS SHAKEN... YOU MAKE ME SHIVER :)", )) +alvik.on_x_tilt(simple_print, ("TILTED ON X",)) +alvik.on_nx_tilt(simple_print, ("TILTED ON -X",)) +alvik.on_y_tilt(simple_print, ("TILTED ON Y",)) +alvik.on_ny_tilt(simple_print, ("TILTED ON -Y",)) +alvik.on_z_tilt(simple_print, ("TILTED ON Z",)) +alvik.on_nz_tilt(simple_print, ("TILTED ON -Z",)) + +alvik.begin() + +alvik.left_wheel.reset() +alvik.right_wheel.reset() + +while True: + try: + alvik.left_wheel.set_position(30) + sleep(2) + print(f'Left wheel degs: {alvik.left_wheel.get_position()}') + print(f'Right wheel degs: {alvik.right_wheel.get_position()}') + + alvik.right_wheel.set_position(10) + sleep(2) + print(f'Left wheel degs: {alvik.left_wheel.get_position()}') + print(f'Right wheel degs: {alvik.right_wheel.get_position()}') + + alvik.left_wheel.set_position(180) + sleep(2) + print(f'Left wheel degs: {alvik.left_wheel.get_position()}') + print(f'Right wheel degs: {alvik.right_wheel.get_position()}') + + alvik.right_wheel.set_position(270) + sleep(2) + print(f'Left wheel degs: {alvik.left_wheel.get_position()}') + print(f'Right wheel degs: {alvik.right_wheel.get_position()}') + + except KeyboardInterrupt as e: + print('over') + alvik.stop() + sys.exit() From 9546829032bd169d7a9a54b560fd172fc5ffcb7c Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Wed, 24 Jul 2024 17:03:45 +0200 Subject: [PATCH 03/46] mod: rem unused 'd' command code --- arduino_alvik/arduino_alvik.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index fac115e..53e6d6e 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -597,9 +597,6 @@ def _parse_message(self) -> int: elif code == ord('p'): # battery percentage _, self._battery_perc = self._packeter.unpacketC1F() - elif code == ord('d'): - # distance sensor - _, self._left_tof, self._center_tof, self._right_tof = self._packeter.unpacketC3I() elif code == ord('t'): # touch input _, self._touch_byte = self._packeter.unpacketC1B() From a711f594349a79f47ba20d29242c6e9d0fadefd1 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Wed, 24 Jul 2024 18:04:37 +0200 Subject: [PATCH 04/46] reverted previous commit --- arduino_alvik/arduino_alvik.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index 53e6d6e..fac115e 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -597,6 +597,9 @@ def _parse_message(self) -> int: elif code == ord('p'): # battery percentage _, self._battery_perc = self._packeter.unpacketC1F() + elif code == ord('d'): + # distance sensor + _, self._left_tof, self._center_tof, self._right_tof = self._packeter.unpacketC3I() elif code == ord('t'): # touch input _, self._touch_byte = self._packeter.unpacketC1B() From efed28ce2830be69d189562326493f28269846f9 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Wed, 24 Jul 2024 18:12:45 +0200 Subject: [PATCH 05/46] mod: move events command code from 'd' to 'm' examp: move_events.py without motors activation --- arduino_alvik/arduino_alvik.py | 2 +- examples/move_events.py | 25 ++----------------------- 2 files changed, 3 insertions(+), 24 deletions(-) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index 814a9b7..9e895ec 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -617,7 +617,7 @@ def _parse_message(self) -> int: elif code == ord('t'): # touch input _, self._touch_byte = self._packeter.unpacketC1B() - elif code == ord('d'): + elif code == ord('m'): # movement/shake input _, self._move_byte = self._packeter.unpacketC1B() elif code == ord('b'): diff --git a/examples/move_events.py b/examples/move_events.py index 264de5c..e3dfaaf 100644 --- a/examples/move_events.py +++ b/examples/move_events.py @@ -2,8 +2,6 @@ from time import sleep import sys -value = 0 - def toggle_left_led(custom_text: str = '') -> None: global value @@ -15,6 +13,7 @@ def toggle_left_led(custom_text: str = '') -> None: def simple_print(custom_text: str = '') -> None: print(custom_text) + alvik = ArduinoAlvik() alvik.on_shake(toggle_left_led, ("ALVIK WAS SHAKEN... YOU MAKE ME SHIVER :)", )) alvik.on_x_tilt(simple_print, ("TILTED ON X",)) @@ -26,30 +25,10 @@ def simple_print(custom_text: str = '') -> None: alvik.begin() -alvik.left_wheel.reset() -alvik.right_wheel.reset() - while True: try: - alvik.left_wheel.set_position(30) - sleep(2) - print(f'Left wheel degs: {alvik.left_wheel.get_position()}') - print(f'Right wheel degs: {alvik.right_wheel.get_position()}') - - alvik.right_wheel.set_position(10) - sleep(2) - print(f'Left wheel degs: {alvik.left_wheel.get_position()}') - print(f'Right wheel degs: {alvik.right_wheel.get_position()}') - - alvik.left_wheel.set_position(180) - sleep(2) - print(f'Left wheel degs: {alvik.left_wheel.get_position()}') - print(f'Right wheel degs: {alvik.right_wheel.get_position()}') - - alvik.right_wheel.set_position(270) + print(alvik.get_distance()) sleep(2) - print(f'Left wheel degs: {alvik.left_wheel.get_position()}') - print(f'Right wheel degs: {alvik.right_wheel.get_position()}') except KeyboardInterrupt as e: print('over') From 9308a4b5fda7368112a89e7436478dcba9ddeba3 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Fri, 26 Jul 2024 15:12:15 +0200 Subject: [PATCH 06/46] feat: timer events --- arduino_alvik/arduino_alvik.py | 78 ++++++++++++++++++++++++++++++- examples/timer_periodic_events.py | 48 +++++++++++++++++++ 2 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 examples/timer_periodic_events.py diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index 9e895ec..22e67cf 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -72,6 +72,7 @@ def __init__(self): self._version = [None, None, None] self._touch_events = _ArduinoAlvikTouchEvents() self._move_events = _ArduinoAlvikMoveEvents() + self._timer_events = _ArduinoAlvikTimerEvents(-1) @staticmethod def is_on() -> bool: @@ -204,7 +205,8 @@ def _has_events_registered(self) -> bool: return any([ self._touch_events.has_callbacks(), - self._move_events.has_callbacks() + self._move_events.has_callbacks(), + self._timer_events.has_callbacks() # more events check ]) @@ -618,7 +620,7 @@ def _parse_message(self) -> int: # touch input _, self._touch_byte = self._packeter.unpacketC1B() elif code == ord('m'): - # movement/shake input + # tilt/shake input _, self._move_byte = self._packeter.unpacketC1B() elif code == ord('b'): # behaviour @@ -1046,6 +1048,19 @@ def print_status(self): print(f'LINEAR VEL: {self._linear_velocity}') print(f'ANGULAR VEL: {self._angular_velocity}') + def timer(self, mode: str, period: int, callback: callable, args: tuple = ()) -> None: + """ + Register a timer callback + :param mode: _ArduinoAlvikTimerEvents.PERIODIC or .ONE_SHOT + :param period: period in milliseconds + :param callback: + :param args: + :return: + """ + + self._timer_events = _ArduinoAlvikTimerEvents(period) + self._timer_events.register_callback(mode, callback, *args) + def on_touch_ok_pressed(self, callback: callable, args: tuple = ()) -> None: """ Register callback when touch button OK is pressed @@ -1194,6 +1209,7 @@ def _update_events(self, delay_: int = 100): if self.is_on(): self._touch_events.update_state(self._touch_byte) self._move_events.update_state(self._move_byte) + self._timer_events.update_state(ticks_ms()) # MORE events update callbacks to be added sleep_ms(delay_) @@ -1368,6 +1384,64 @@ def update_state(self, state): pass +class _ArduinoAlvikTimerEvents(_ArduinoAlvikEvents): + """ + Event class to handle timer events + """ + + available_events = ['periodic', 'one_shot'] + PERIODIC = 'periodic' + ONE_SHOT = 'one_shot' + + def __init__(self, period: int): + """ + Timer initialization + :param period: Timer period in milliseconds + """ + self._last_trigger = ticks_ms() + self._period = period + self._triggered = False + super().__init__() + + def register_callback(self, event_name: str, callback: callable, args: tuple = None): + """ + Repeated calls to register_callback will overwrite the timer's behaviour. The Timer can be either PERIODIC + or ONE_SHOT + :param event_name: + :param callback: + :param args: + :return: + """ + self._callbacks = dict() + super().register_callback(event_name, callback, args) + + def _is_period_expired(self, now=ticks_ms()) -> bool: + """ + True if the timer period is expired + :return: + """ + + if ticks_diff(now, self._last_trigger) > self._period: + self._last_trigger = now + return True + + return False + + def update_state(self, state): + """ + Updates the internal state of the events handler and executes the related callback + :return: + """ + + if list(self._callbacks.keys()) == [self.PERIODIC]: + if self._is_period_expired(state): + self.execute_callback(self.PERIODIC) + elif list(self._callbacks.keys()) == [self.ONE_SHOT] and not self._triggered: + if self._is_period_expired(state): + self.execute_callback(self.ONE_SHOT) + self._triggered = True + + class _ArduinoAlvikTouchEvents(_ArduinoAlvikEvents): """ This is the event class to handle touch button events diff --git a/examples/timer_periodic_events.py b/examples/timer_periodic_events.py new file mode 100644 index 0000000..f026112 --- /dev/null +++ b/examples/timer_periodic_events.py @@ -0,0 +1,48 @@ +from arduino_alvik import ArduinoAlvik +from time import sleep +import sys + +value = 0 + + +def toggle_left_led(custom_text: str = '') -> None: + global value + value = (value + 1) % 2 + alvik.left_led.set_color(value, 0, 0) + print(f"RED BLINKS! {custom_text}") + + +alvik = ArduinoAlvik() +alvik.timer('periodic', 500, toggle_left_led, ("500 ms have passed...", )) + +alvik.begin() + +alvik.left_wheel.reset() +alvik.right_wheel.reset() + +while True: + try: + alvik.left_wheel.set_position(30) + sleep(2) + print(f'Left wheel degs: {alvik.left_wheel.get_position()}') + print(f'Right wheel degs: {alvik.right_wheel.get_position()}') + + alvik.right_wheel.set_position(10) + sleep(2) + print(f'Left wheel degs: {alvik.left_wheel.get_position()}') + print(f'Right wheel degs: {alvik.right_wheel.get_position()}') + + alvik.left_wheel.set_position(180) + sleep(2) + print(f'Left wheel degs: {alvik.left_wheel.get_position()}') + print(f'Right wheel degs: {alvik.right_wheel.get_position()}') + + alvik.right_wheel.set_position(270) + sleep(2) + print(f'Left wheel degs: {alvik.left_wheel.get_position()}') + print(f'Right wheel degs: {alvik.right_wheel.get_position()}') + + except KeyboardInterrupt as e: + print('over') + alvik.stop() + sys.exit() From d2bdc4ffd43341bcbbae0795219d2fce251fe8d5 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Fri, 26 Jul 2024 15:18:17 +0200 Subject: [PATCH 07/46] fix: tilt events not firing --- arduino_alvik/arduino_alvik.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index 22e67cf..e157d24 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -1656,22 +1656,22 @@ def update_state(self, state: int | None): self.execute_callback('on_shake') if self._is_x_tilted(self._current_state, state): - self.execute_callback('on_x_tilted') + self.execute_callback('on_x_tilt') if self._is_neg_x_tilted(self._current_state, state): - self.execute_callback('on_nx_tilted') + self.execute_callback('on_nx_tilt') if self._is_y_tilted(self._current_state, state): - self.execute_callback('on_y_tilted') + self.execute_callback('on_y_tilt') if self._is_neg_y_tilted(self._current_state, state): - self.execute_callback('on_ny_tilted') + self.execute_callback('on_ny_tilt') if self._is_z_tilted(self._current_state, state): - self.execute_callback('on_z_tilted') + self.execute_callback('on_z_tilt') if self._is_neg_z_tilted(self._current_state, state): - self.execute_callback('on_nz_tilted') + self.execute_callback('on_nz_tilt') self._current_state = state From fe8af5a47f3b364d3f161dafdfb08bcd2baea9fc Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Fri, 26 Jul 2024 15:24:44 +0200 Subject: [PATCH 08/46] fix: initial tilt to be set to -Z (arbitrary) --- arduino_alvik/arduino_alvik.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index e157d24..73227fc 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -737,7 +737,7 @@ def _move_bits(self) -> int: Returns the shake/tilt state :return: """ - return (self._move_byte & 0xFF) if self._move_byte is not None else 0x00 + return (self._move_byte & 0xFF) if self._move_byte is not None else 0x80 def get_shake(self) -> bool: """ From 2cff02311f9cad62a74994253942700570014951 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Fri, 26 Jul 2024 16:13:50 +0200 Subject: [PATCH 09/46] fix: timer callback registration wrong params --- arduino_alvik/arduino_alvik.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index 73227fc..55ae4dc 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -1059,7 +1059,7 @@ def timer(self, mode: str, period: int, callback: callable, args: tuple = ()) -> """ self._timer_events = _ArduinoAlvikTimerEvents(period) - self._timer_events.register_callback(mode, callback, *args) + self._timer_events.register_callback(mode, callback, args) def on_touch_ok_pressed(self, callback: callable, args: tuple = ()) -> None: """ From beba5578e9babf1678b1382cc91d39b2999b31bb Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Fri, 26 Jul 2024 16:19:46 +0200 Subject: [PATCH 10/46] ex: timer_one_shot_events.py --- examples/timer_one_shot_events.py | 48 +++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 examples/timer_one_shot_events.py diff --git a/examples/timer_one_shot_events.py b/examples/timer_one_shot_events.py new file mode 100644 index 0000000..98501b9 --- /dev/null +++ b/examples/timer_one_shot_events.py @@ -0,0 +1,48 @@ +from arduino_alvik import ArduinoAlvik +from time import sleep +import sys + +value = 0 + + +def toggle_left_led(custom_text: str = '') -> None: + global value + value = (value + 1) % 2 + alvik.left_led.set_color(value, 0, 0) + print(f"RED BLINKS! {custom_text}") + + +alvik = ArduinoAlvik() +alvik.timer('one_shot', 10000, toggle_left_led, ("10 seconds have passed... I won't do this again", )) + +alvik.begin() + +alvik.left_wheel.reset() +alvik.right_wheel.reset() + +while True: + try: + alvik.left_wheel.set_position(30) + sleep(2) + print(f'Left wheel degs: {alvik.left_wheel.get_position()}') + print(f'Right wheel degs: {alvik.right_wheel.get_position()}') + + alvik.right_wheel.set_position(10) + sleep(2) + print(f'Left wheel degs: {alvik.left_wheel.get_position()}') + print(f'Right wheel degs: {alvik.right_wheel.get_position()}') + + alvik.left_wheel.set_position(180) + sleep(2) + print(f'Left wheel degs: {alvik.left_wheel.get_position()}') + print(f'Right wheel degs: {alvik.right_wheel.get_position()}') + + alvik.right_wheel.set_position(270) + sleep(2) + print(f'Left wheel degs: {alvik.left_wheel.get_position()}') + print(f'Right wheel degs: {alvik.right_wheel.get_position()}') + + except KeyboardInterrupt as e: + print('over') + alvik.stop() + sys.exit() From 7cc26a537b9599f163c241f6d8ddd2de0e2e6fc3 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Mon, 29 Jul 2024 13:43:08 +0200 Subject: [PATCH 11/46] mod: timer events starting right after thread is started mod: move_events.py ren to movement_events.py --- arduino_alvik/arduino_alvik.py | 18 +++++++++++++++--- .../{move_events.py => movement_events.py} | 0 2 files changed, 15 insertions(+), 3 deletions(-) rename examples/{move_events.py => movement_events.py} (100%) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index 55ae4dc..e661ac5 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -183,10 +183,9 @@ def begin(self) -> int: sleep_ms(1000) self._idle(1000) self._begin_update_thread() + sleep_ms(100) - if self._has_events_registered(): - print('Starting events thread') - self._start_events_thread() + self._reset_hw() self._flush_uart() self._snake_robot(1000) @@ -195,6 +194,11 @@ def begin(self) -> int: self.set_illuminator(True) self.set_behaviour(1) self._set_color_reference() + + if self._has_events_registered(): + print('Starting events thread') + self._start_events_thread() + return 0 def _has_events_registered(self) -> bool: @@ -1194,6 +1198,7 @@ def _start_events_thread(self) -> None: """ if not self.__class__._events_thread_running: self.__class__._events_thread_running = True + self._timer_events.reset() self.__class__._events_thread_id = _thread.start_new_thread(self._update_events, (50,)) def _update_events(self, delay_: int = 100): @@ -1403,6 +1408,13 @@ def __init__(self, period: int): self._triggered = False super().__init__() + def reset(self): + """ + Resets the timer. Use just before starting the events thread + :return: + """ + self._last_trigger = ticks_ms() + def register_callback(self, event_name: str, callback: callable, args: tuple = None): """ Repeated calls to register_callback will overwrite the timer's behaviour. The Timer can be either PERIODIC diff --git a/examples/move_events.py b/examples/movement_events.py similarity index 100% rename from examples/move_events.py rename to examples/movement_events.py From 1cfe93d272c41b32dee4f7347a4f70c58de834e9 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Mon, 29 Jul 2024 14:40:12 +0200 Subject: [PATCH 12/46] fix: movement_events.py value is undefined --- examples/movement_events.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/movement_events.py b/examples/movement_events.py index e3dfaaf..49a7442 100644 --- a/examples/movement_events.py +++ b/examples/movement_events.py @@ -3,6 +3,9 @@ import sys +value = 0 + + def toggle_left_led(custom_text: str = '') -> None: global value value = (value + 1) % 2 From d8bbf66b7e11dcc0a541e021b69174923d6f5a2a Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Mon, 29 Jul 2024 16:03:04 +0200 Subject: [PATCH 13/46] fix: always detecting -Z tilt at the beginning of events --- arduino_alvik/arduino_alvik.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index e661ac5..da6adeb 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -1198,7 +1198,8 @@ def _start_events_thread(self) -> None: """ if not self.__class__._events_thread_running: self.__class__._events_thread_running = True - self._timer_events.reset() + self._timer_events.reset() # resets the timer before starting + self._move_events.reset(_ArduinoAlvikMoveEvents.NZ_TILT) # resets the orientation to -Z tilted self.__class__._events_thread_id = _thread.start_new_thread(self._update_events, (50,)) def _update_events(self, delay_: int = 100): @@ -1580,10 +1581,20 @@ class _ArduinoAlvikMoveEvents(_ArduinoAlvikEvents): available_events = ['on_shake', 'on_x_tilt', 'on_y_tilt', 'on_z_tilt', 'on_nx_tilt', 'on_ny_tilt', 'on_nz_tilt'] + NZ_TILT = 0x80 + def __init__(self): self._current_state = 0 super().__init__() + def reset(self, state: int = 0x00): + """ + Sets the initial state + :param state: + :return: + """ + self._current_state = state + @staticmethod def _is_shaken(current_state, new_state) -> bool: """ From 6d703a793e4e102219a0eb138f63261a6bce9b32 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Mon, 29 Jul 2024 16:47:10 +0200 Subject: [PATCH 14/46] mod: events examples depending on a 'state' use generators instead of globals --- examples/movement_events.py | 28 ++++++++++++++++++++-------- examples/timer_one_shot_events.py | 27 ++++++++++++++++++++------- examples/timer_periodic_events.py | 27 ++++++++++++++++++++------- examples/touch_events.py | 25 +++++++++++++++++++------ 4 files changed, 79 insertions(+), 28 deletions(-) diff --git a/examples/movement_events.py b/examples/movement_events.py index 49a7442..49c804a 100644 --- a/examples/movement_events.py +++ b/examples/movement_events.py @@ -3,13 +3,25 @@ import sys -value = 0 - - -def toggle_left_led(custom_text: str = '') -> None: - global value - value = (value + 1) % 2 - alvik.left_led.set_color(value, 0, 0) +def toggle_value(): + """ + This function yields a generator object that toggles values between 0 and 1. + :return: + """ + value = 0 + while True: + yield value % 2 + value += 1 + + +def toggle_left_led(custom_text: str, val) -> None: + """ + This function toggles the lef led in the red channel. It also writes some custom text. + :param custom_text: your custom text + :param val: a toggle signal generator + :return: + """ + alvik.left_led.set_color(next(val), 0, 0) print(f"RED BLINKS! {custom_text}") @@ -18,7 +30,7 @@ def simple_print(custom_text: str = '') -> None: alvik = ArduinoAlvik() -alvik.on_shake(toggle_left_led, ("ALVIK WAS SHAKEN... YOU MAKE ME SHIVER :)", )) +alvik.on_shake(toggle_left_led, ("ALVIK WAS SHAKEN... YOU MAKE ME SHIVER :)", toggle_value(), )) alvik.on_x_tilt(simple_print, ("TILTED ON X",)) alvik.on_nx_tilt(simple_print, ("TILTED ON -X",)) alvik.on_y_tilt(simple_print, ("TILTED ON Y",)) diff --git a/examples/timer_one_shot_events.py b/examples/timer_one_shot_events.py index 98501b9..f605946 100644 --- a/examples/timer_one_shot_events.py +++ b/examples/timer_one_shot_events.py @@ -2,18 +2,31 @@ from time import sleep import sys -value = 0 - -def toggle_left_led(custom_text: str = '') -> None: - global value - value = (value + 1) % 2 - alvik.left_led.set_color(value, 0, 0) +def toggle_value(): + """ + This function yields a generator object that toggles values between 0 and 1. + :return: + """ + value = 0 + while True: + yield value % 2 + value += 1 + + +def toggle_left_led(custom_text: str, val) -> None: + """ + This function toggles the lef led in the red channel. It also writes some custom text. + :param custom_text: your custom text + :param val: a toggle signal generator + :return: + """ + alvik.left_led.set_color(next(val), 0, 0) print(f"RED BLINKS! {custom_text}") alvik = ArduinoAlvik() -alvik.timer('one_shot', 10000, toggle_left_led, ("10 seconds have passed... I won't do this again", )) +alvik.timer('one_shot', 10000, toggle_left_led, ("10 seconds have passed... I won't do this again", toggle_value(), )) alvik.begin() diff --git a/examples/timer_periodic_events.py b/examples/timer_periodic_events.py index f026112..c1be256 100644 --- a/examples/timer_periodic_events.py +++ b/examples/timer_periodic_events.py @@ -2,18 +2,31 @@ from time import sleep import sys -value = 0 - -def toggle_left_led(custom_text: str = '') -> None: - global value - value = (value + 1) % 2 - alvik.left_led.set_color(value, 0, 0) +def toggle_value(): + """ + This function yields a generator object that toggles values between 0 and 1. + :return: + """ + value = 0 + while True: + yield value % 2 + value += 1 + + +def toggle_left_led(custom_text: str, val) -> None: + """ + This function toggles the lef led in the red channel. It also writes some custom text. + :param custom_text: your custom text + :param val: a toggle signal generator + :return: + """ + alvik.left_led.set_color(next(val), 0, 0) print(f"RED BLINKS! {custom_text}") alvik = ArduinoAlvik() -alvik.timer('periodic', 500, toggle_left_led, ("500 ms have passed...", )) +alvik.timer('periodic', 500, toggle_left_led, ("500 ms have passed...", toggle_value(), )) alvik.begin() diff --git a/examples/touch_events.py b/examples/touch_events.py index db2d64f..9ef35e3 100644 --- a/examples/touch_events.py +++ b/examples/touch_events.py @@ -2,13 +2,26 @@ from time import sleep import sys -value = 0 +def toggle_value(): + """ + This function yields a generator object that toggles values between 0 and 1. + :return: + """ + value = 0 + while True: + yield value % 2 + value += 1 -def toggle_left_led(custom_text: str = '') -> None: - global value - value = (value + 1) % 2 - alvik.left_led.set_color(value, 0, 0) + +def toggle_left_led(custom_text: str, val) -> None: + """ + This function toggles the lef led in the red channel. It also writes some custom text. + :param custom_text: your custom text + :param val: a toggle signal generator + :return: + """ + alvik.left_led.set_color(next(val), 0, 0) print(f"RED BLINKS! {custom_text}") @@ -16,7 +29,7 @@ def simple_print(custom_text: str = '') -> None: print(custom_text) alvik = ArduinoAlvik() -alvik.on_touch_ok_pressed(toggle_left_led, ("OK WAS PRESSED... THAT'S COOL", )) +alvik.on_touch_ok_pressed(toggle_left_led, ("OK WAS PRESSED... THAT'S COOL", toggle_value(), )) alvik.on_touch_center_pressed(simple_print, ("CENTER PRESSED",)) alvik.on_touch_cancel_pressed(simple_print, ("CANCEL PRESSED",)) alvik.on_touch_up_pressed(simple_print, ("UP PRESSED",)) From 6d0028deef10f32ed86f791857ef002835059979 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Tue, 30 Jul 2024 16:20:36 +0200 Subject: [PATCH 15/46] feat: alvik's timer events can be set and reset (restarted) --- arduino_alvik/arduino_alvik.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index da6adeb..64b932b 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -1409,12 +1409,28 @@ def __init__(self, period: int): self._triggered = False super().__init__() - def reset(self): + def set(self, start=ticks_ms(), period: int = None): """ - Resets the timer. Use just before starting the events thread + Sets the last trigger time + :param start: + :param period: :return: """ - self._last_trigger = ticks_ms() + self._last_trigger = start + if period is not None: + self._period = period + + def reset(self, start=ticks_ms(), period: int = None): + """ + Resets the timer. Use just before starting the events thread or if you want to restart the Timer + :param start: + :param period: + :return: + """ + self._last_trigger = start + if period is not None: + self._period = period + self._triggered = False def register_callback(self, event_name: str, callback: callable, args: tuple = None): """ From 3b8787556f2c1589a7f3ba7dcca712efa9c91ad2 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Tue, 30 Jul 2024 16:48:31 +0200 Subject: [PATCH 16/46] ex: read_orientation.py --- examples/read_orientation.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 examples/read_orientation.py diff --git a/examples/read_orientation.py b/examples/read_orientation.py new file mode 100644 index 0000000..23cf006 --- /dev/null +++ b/examples/read_orientation.py @@ -0,0 +1,16 @@ +from arduino_alvik import ArduinoAlvik +from time import sleep_ms +import sys + +alvik = ArduinoAlvik() +alvik.begin() + +while True: + try: + roll, pitch, yaw = alvik.get_orientation() + print(f'ROLL: {roll}, PITCH: {pitch}, YAW: {yaw}') + sleep_ms(50) + except KeyboardInterrupt as e: + print('over') + alvik.stop() + sys.exit() From dbec9de3afb99c5373612192927f84d0806b2d13 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Tue, 30 Jul 2024 19:01:39 +0200 Subject: [PATCH 17/46] feat: set single servo position --- arduino_alvik/arduino_alvik.py | 25 +++++++++++++++++++++++++ examples/set_servo.py | 22 ++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 examples/set_servo.py diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index 55ae4dc..8aaeee5 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -29,6 +29,9 @@ def __init__(self): self._packeter = ucPack(200) self.left_wheel = _ArduinoAlvikWheel(self._packeter, ord('L')) self.right_wheel = _ArduinoAlvikWheel(self._packeter, ord('R')) + self._servo_positions = list((None, None,)) + self.servo_A = _ArduinoAlvikServo(self._packeter, 'A', 0, self._servo_positions) + self.servo_B = _ArduinoAlvikServo(self._packeter, 'B', 1, self._servo_positions) self._led_state = list((None,)) self.left_led = self.DL1 = _ArduinoAlvikRgbLed(self._packeter, 'left', self._led_state, rgb_mask=[0b00000100, 0b00001000, 0b00010000]) @@ -195,6 +198,7 @@ def begin(self) -> int: self.set_illuminator(True) self.set_behaviour(1) self._set_color_reference() + self.set_servo_positions(0, 0) return 0 def _has_events_registered(self) -> bool: @@ -508,6 +512,8 @@ def set_servo_positions(self, a_position: int, b_position: int): :param b_position: position of B servomotor (0-180) :return: """ + self._servo_positions[0] = a_position + self._servo_positions[1] = b_position self._packeter.packetC2B(ord('S'), a_position & 0xFF, b_position & 0xFF) uart.write(self._packeter.msg[0:self._packeter.msg_size]) @@ -1223,6 +1229,25 @@ def _stop_events_thread(cls): cls._events_thread_running = False +class _ArduinoAlvikServo: + + def __init__(self, packeter: ucPack, label: str, servo_id: int, position: list[int | None]): + self._packeter = packeter + self._label = label + self._id = servo_id + self._position = position + + def set_position(self, position): + """ + Sets the position of the servo + :param position: + :return: + """ + self._position[self._id] = position + self._packeter.packetC2B(ord('S'), self._position[0] & 0xFF, self._position[1] & 0xFF) + uart.write(self._packeter.msg[0:self._packeter.msg_size]) + + class _ArduinoAlvikWheel: def __init__(self, packeter: ucPack, label: int, wheel_diameter_mm: float = WHEEL_DIAMETER_MM): diff --git a/examples/set_servo.py b/examples/set_servo.py new file mode 100644 index 0000000..b4e9084 --- /dev/null +++ b/examples/set_servo.py @@ -0,0 +1,22 @@ +from arduino_alvik import ArduinoAlvik +from time import sleep_ms +import sys + +alvik = ArduinoAlvik() +alvik.begin() + +i = 0 + +while True: + try: + + alvik.servo_A.set_position(i) + alvik.servo_B.set_position(i) + + i = (i + 1) % 180 + + sleep_ms(100) + except KeyboardInterrupt as e: + print('over') + alvik.stop() + sys.exit() From fba0e9fa07584851f287d68216a8ef49e938cc16 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Wed, 31 Jul 2024 12:30:59 +0200 Subject: [PATCH 18/46] feat: servo get_position methods --- arduino_alvik/arduino_alvik.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index 8aaeee5..d6b2ccd 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -517,6 +517,14 @@ def set_servo_positions(self, a_position: int, b_position: int): self._packeter.packetC2B(ord('S'), a_position & 0xFF, b_position & 0xFF) uart.write(self._packeter.msg[0:self._packeter.msg_size]) + def get_servo_positions(self) -> (int, int): + """ + Returns the current servomotor positions + :return: position of A/B servomotor (0-180) + """ + + return self._servo_positions[0], self._servo_positions[1] + def get_ack(self) -> str: """ Returns last acknowledgement @@ -1247,6 +1255,13 @@ def set_position(self, position): self._packeter.packetC2B(ord('S'), self._position[0] & 0xFF, self._position[1] & 0xFF) uart.write(self._packeter.msg[0:self._packeter.msg_size]) + def get_position(self) -> int: + """ + Returns the position of the servo + :return: + """ + return self._position[self._id] + class _ArduinoAlvikWheel: From 728cd685513fc7517418c873859818deecdc5e13 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Wed, 31 Jul 2024 17:22:32 +0200 Subject: [PATCH 19/46] feat: alvik timer stop/resume/get fix: wrong default start on set/reset --- arduino_alvik/arduino_alvik.py | 65 +++++++++++++++++++++++-------- examples/timer_one_shot_events.py | 16 ++++++-- examples/timer_periodic_events.py | 13 +++++-- 3 files changed, 72 insertions(+), 22 deletions(-) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index 64b932b..b4659bc 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -1052,7 +1052,7 @@ def print_status(self): print(f'LINEAR VEL: {self._linear_velocity}') print(f'ANGULAR VEL: {self._angular_velocity}') - def timer(self, mode: str, period: int, callback: callable, args: tuple = ()) -> None: + def set_timer(self, mode: str, period: int, callback: callable, args: tuple = ()) -> None: """ Register a timer callback :param mode: _ArduinoAlvikTimerEvents.PERIODIC or .ONE_SHOT @@ -1065,6 +1065,14 @@ def timer(self, mode: str, period: int, callback: callable, args: tuple = ()) -> self._timer_events = _ArduinoAlvikTimerEvents(period) self._timer_events.register_callback(mode, callback, args) + @property + def timer(self): + """ + Gives access to the timer object + :return: + """ + return self._timer_events + def on_touch_ok_pressed(self, callback: callable, args: tuple = ()) -> None: """ Register callback when touch button OK is pressed @@ -1407,31 +1415,54 @@ def __init__(self, period: int): self._last_trigger = ticks_ms() self._period = period self._triggered = False + self._stopped = False super().__init__() - def set(self, start=ticks_ms(), period: int = None): + def set(self, start=None, period: int = None): """ Sets the last trigger time :param start: :param period: :return: """ - self._last_trigger = start + self._last_trigger = start if start is not None else ticks_ms() if period is not None: self._period = period - def reset(self, start=ticks_ms(), period: int = None): + def reset(self, start=None, period: int = None): """ Resets the timer. Use just before starting the events thread or if you want to restart the Timer :param start: :param period: :return: """ - self._last_trigger = start + self._last_trigger = start if start is not None else ticks_ms() if period is not None: self._period = period self._triggered = False + def stop(self): + """ + Stops the timer + :return: + """ + + self._stopped = True + + def resume(self): + """ + Resumes the timer + :return: + """ + self._stopped = False + + def get(self) -> int: + """ + Returns the time passed since the last trigger in ms + :return: + """ + return ticks_diff(ticks_ms(), self._last_trigger) + def register_callback(self, event_name: str, callback: callable, args: tuple = None): """ Repeated calls to register_callback will overwrite the timer's behaviour. The Timer can be either PERIODIC @@ -1444,30 +1475,32 @@ def register_callback(self, event_name: str, callback: callable, args: tuple = N self._callbacks = dict() super().register_callback(event_name, callback, args) - def _is_period_expired(self, now=ticks_ms()) -> bool: + def _is_period_expired(self, now=None) -> bool: """ True if the timer period is expired :return: """ - if ticks_diff(now, self._last_trigger) > self._period: - self._last_trigger = now - return True + if now is None: + now = ticks_ms() + return ticks_diff(now, self._last_trigger) > self._period - return False - - def update_state(self, state): + def update_state(self, ticks): """ Updates the internal state of the events handler and executes the related callback :return: """ if list(self._callbacks.keys()) == [self.PERIODIC]: - if self._is_period_expired(state): - self.execute_callback(self.PERIODIC) + if self._is_period_expired(ticks): + self._last_trigger = ticks + if not self._stopped: + self.execute_callback(self.PERIODIC) elif list(self._callbacks.keys()) == [self.ONE_SHOT] and not self._triggered: - if self._is_period_expired(state): - self.execute_callback(self.ONE_SHOT) + if self._is_period_expired(ticks): + self._last_trigger = ticks + if not self._stopped: + self.execute_callback(self.ONE_SHOT) self._triggered = True diff --git a/examples/timer_one_shot_events.py b/examples/timer_one_shot_events.py index f605946..ddfecce 100644 --- a/examples/timer_one_shot_events.py +++ b/examples/timer_one_shot_events.py @@ -21,12 +21,13 @@ def toggle_left_led(custom_text: str, val) -> None: :param val: a toggle signal generator :return: """ - alvik.left_led.set_color(next(val), 0, 0) - print(f"RED BLINKS! {custom_text}") + led_val = next(val) + alvik.left_led.set_color(led_val, 0, 0) + print(f"RED {'ON' if led_val else 'OFF'}! {custom_text}") alvik = ArduinoAlvik() -alvik.timer('one_shot', 10000, toggle_left_led, ("10 seconds have passed... I won't do this again", toggle_value(), )) +alvik.set_timer('one_shot', 10000, toggle_left_led, ("10 seconds have passed... I won't do this again", toggle_value(), )) alvik.begin() @@ -55,6 +56,15 @@ def toggle_left_led(custom_text: str, val) -> None: print(f'Left wheel degs: {alvik.left_wheel.get_position()}') print(f'Right wheel degs: {alvik.right_wheel.get_position()}') + if alvik.timer._triggered: + alvik.timer.reset(period=1000) + alvik.timer.stop() + for _ in range(0, 10): + if _ == 2: + alvik.timer.resume() + print(f'TRIGGERED:{alvik.timer._triggered} STOPPED:{alvik.timer._stopped} TIME: {alvik.timer.get()}') + sleep(1) + except KeyboardInterrupt as e: print('over') alvik.stop() diff --git a/examples/timer_periodic_events.py b/examples/timer_periodic_events.py index c1be256..c3974ed 100644 --- a/examples/timer_periodic_events.py +++ b/examples/timer_periodic_events.py @@ -21,12 +21,13 @@ def toggle_left_led(custom_text: str, val) -> None: :param val: a toggle signal generator :return: """ - alvik.left_led.set_color(next(val), 0, 0) - print(f"RED BLINKS! {custom_text}") + led_val = next(val) + alvik.left_led.set_color(led_val, 0, 0) + print(f"RED {'ON' if led_val else 'OFF'}! {custom_text}") alvik = ArduinoAlvik() -alvik.timer('periodic', 500, toggle_left_led, ("500 ms have passed...", toggle_value(), )) +alvik.set_timer('periodic', 500, toggle_left_led, ("500 ms have passed...", toggle_value(), )) alvik.begin() @@ -55,6 +56,12 @@ def toggle_left_led(custom_text: str, val) -> None: print(f'Left wheel degs: {alvik.left_wheel.get_position()}') print(f'Right wheel degs: {alvik.right_wheel.get_position()}') + alvik.timer.reset(period=1000) + alvik.timer.stop() + for _ in range(0, 20): + print(f'.{alvik.timer._triggered}: {alvik.timer.get()}') + sleep(1) + except KeyboardInterrupt as e: print('over') alvik.stop() From 773c6ec36838d569f830e46b8c7d6739afc9eed6 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Thu, 1 Aug 2024 13:26:16 +0200 Subject: [PATCH 20/46] feat: is_triggered, is_stopped alvik.timer methods --- arduino_alvik/arduino_alvik.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index b4659bc..940f108 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -1418,6 +1418,20 @@ def __init__(self, period: int): self._stopped = False super().__init__() + def is_triggered(self): + """ + Returns the trigger state + :return: + """ + return self._triggered + + def is_stopped(self): + """ + Return True if timer is stopped + :return: + """ + return self._stopped + def set(self, start=None, period: int = None): """ Sets the last trigger time From a06727bc6db6450688428686ac6fb6674cb0ff34 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Thu, 1 Aug 2024 14:46:50 +0200 Subject: [PATCH 21/46] fix: timer examples still using protected attribs --- examples/timer_one_shot_events.py | 4 ++-- examples/timer_periodic_events.py | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/timer_one_shot_events.py b/examples/timer_one_shot_events.py index ddfecce..8ab8a99 100644 --- a/examples/timer_one_shot_events.py +++ b/examples/timer_one_shot_events.py @@ -56,13 +56,13 @@ def toggle_left_led(custom_text: str, val) -> None: print(f'Left wheel degs: {alvik.left_wheel.get_position()}') print(f'Right wheel degs: {alvik.right_wheel.get_position()}') - if alvik.timer._triggered: + if alvik.timer.is_triggered(): alvik.timer.reset(period=1000) alvik.timer.stop() for _ in range(0, 10): if _ == 2: alvik.timer.resume() - print(f'TRIGGERED:{alvik.timer._triggered} STOPPED:{alvik.timer._stopped} TIME: {alvik.timer.get()}') + print(f'TRIGGERED:{alvik.timer.is_triggered()} STOPPED:{alvik.timer.is_stopped()} TIME: {alvik.timer.get()}') sleep(1) except KeyboardInterrupt as e: diff --git a/examples/timer_periodic_events.py b/examples/timer_periodic_events.py index c3974ed..fd5aa28 100644 --- a/examples/timer_periodic_events.py +++ b/examples/timer_periodic_events.py @@ -59,7 +59,9 @@ def toggle_left_led(custom_text: str, val) -> None: alvik.timer.reset(period=1000) alvik.timer.stop() for _ in range(0, 20): - print(f'.{alvik.timer._triggered}: {alvik.timer.get()}') + if _ == 5: + alvik.timer.resume() + print(f'TRIGGERED:{alvik.timer.is_triggered()} STOPPED:{alvik.timer.is_stopped()} TIME: {alvik.timer.get()}') sleep(1) except KeyboardInterrupt as e: From dafb803b046a63330bac91b628aba905f4b4f41e Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Thu, 1 Aug 2024 14:52:39 +0200 Subject: [PATCH 22/46] ex: movement_events.py --- examples/movement_events.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/movement_events.py b/examples/movement_events.py index 49c804a..f7edf01 100644 --- a/examples/movement_events.py +++ b/examples/movement_events.py @@ -21,8 +21,9 @@ def toggle_left_led(custom_text: str, val) -> None: :param val: a toggle signal generator :return: """ - alvik.left_led.set_color(next(val), 0, 0) - print(f"RED BLINKS! {custom_text}") + led_val = next(val) + alvik.left_led.set_color(led_val, 0, 0) + print(f"RED {'ON' if led_val else 'OFF'}! {custom_text}") def simple_print(custom_text: str = '') -> None: From 5e0d2f6e6889880ad8400fed04b493b5bb0138de Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Wed, 7 Aug 2024 18:53:09 +0200 Subject: [PATCH 23/46] feat: i2c exposed. if Alvik off bms has priority --- arduino_alvik/arduino_alvik.py | 97 ++++++++++++++++++++++++----- arduino_alvik/pinout_definitions.py | 4 +- 2 files changed, 84 insertions(+), 17 deletions(-) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index b2bd83e..0f6b322 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -26,6 +26,7 @@ def __new__(cls): return cls._instance def __init__(self): + self.i2c = _ArduinoAlvikI2C(A4, A5) self._packeter = ucPack(200) self.left_wheel = _ArduinoAlvikWheel(self._packeter, ord('L')) self.right_wheel = _ArduinoAlvikWheel(self._packeter, ord('R')) @@ -100,36 +101,42 @@ def _progress_bar(percentage: float) -> None: word = marks_str + f" {percentage}% \t" sys.stdout.write(bytes((word.encode('utf-8')))) - def _idle(self, delay_=1, check_on_thread=False) -> None: + def _lenghty_op(self, iterations=10000000) -> int: + result = 0 + for i in range(1, iterations): + result += i * i + return result + + def _idle(self, delay_=1, check_on_thread=False, blocking=False) -> None: """ Alvik's idle mode behaviour :return: """ - NANO_CHK.value(1) - sleep_ms(500) + self.i2c._prio = True + + if blocking: + self._lenghty_op(50000) + else: + sleep_ms(500) led_val = 0 try: while not self.is_on(): if check_on_thread and not self.__class__._update_thread_running: break - _ESP32_SDA = Pin(A4, Pin.OUT) - _ESP32_SCL = Pin(A5, Pin.OUT) - _ESP32_SCL.value(1) - _ESP32_SDA.value(1) - sleep_ms(100) - _ESP32_SCL.value(0) - _ESP32_SDA.value(0) cmd = bytearray(1) cmd[0] = 0x06 - i2c = I2C(0, scl=ESP32_SCL, sda=ESP32_SDA) - i2c.writeto(0x36, cmd) - soc_raw = struct.unpack('h', i2c.readfrom(0x36, 2))[0] + self.i2c.writeto(0x36, cmd, start=True, priority=True) + + soc_raw = struct.unpack('h', self.i2c.readfrom(0x36, 2, priority=True))[0] soc_perc = soc_raw * 0.00390625 self._progress_bar(round(soc_perc)) - sleep_ms(delay_) + if blocking: + self._lenghty_op(10000) + else: + sleep_ms(delay_) if soc_perc > 97: LEDG.value(0) LEDR.value(1) @@ -137,6 +144,7 @@ def _idle(self, delay_=1, check_on_thread=False) -> None: LEDR.value(led_val) LEDG.value(1) led_val = (led_val + 1) % 2 + self.i2c._prio = False print("********** Alvik is on **********") except KeyboardInterrupt: self.stop() @@ -148,6 +156,7 @@ def _idle(self, delay_=1, check_on_thread=False) -> None: LEDR.value(1) LEDG.value(1) NANO_CHK.value(0) + self.i2c._prio = False @staticmethod def _snake_robot(duration: int = 1000): @@ -582,7 +591,7 @@ def _update(self, delay_=1): while True: if not self.is_on(): print("Alvik is off") - self._idle(1000, check_on_thread=True) + self._idle(1000, check_on_thread=True, blocking=True) self._reset_hw() self._flush_uart() sleep_ms(1000) @@ -1249,6 +1258,64 @@ def _stop_events_thread(cls): cls._events_thread_running = False +class _ArduinoAlvikI2C: + + def __init__(self, sda: int, scl: int): + """ + Alvik I2C wrapper + :param sda: + :param scl: + """ + self._lock = _thread.allocate_lock() + self._prio = False + self.sda = sda + self.scl = scl + + def _start(self): + """ + Bitbanging start condition + :return: + """ + _SDA = Pin(self.sda, Pin.OUT) + _SDA.value(1) + sleep_ms(100) + _SDA.value(0) + + def scan(self, start=False, priority=False): + """ + I2C scan method + :return: + """ + if not priority and self._prio: + return [] + with self._lock: + if start: + self._start() + i2c = I2C(0, scl=Pin(self.scl, Pin.OUT), sda=Pin(self.sda, Pin.OUT)) + out = i2c.scan() + return out + + def readfrom(self, addr, nbytes, stop=True, start=False, priority=False): + if not priority and self._prio: + return None + with self._lock: + if start: + self._start() + i2c = I2C(0, scl=Pin(self.scl, Pin.OUT), sda=Pin(self.sda, Pin.OUT)) + out = i2c.readfrom(addr, nbytes, stop) + return out + + def writeto(self, addr, buf, stop=True, start=False, priority=False): + if not priority and self._prio: + return None + with self._lock: + if start: + self._start() + i2c = I2C(0, scl=Pin(self.scl, Pin.OUT), sda=Pin(self.sda, Pin.OUT)) + out = i2c.writeto(addr, buf, stop) + return out + + class _ArduinoAlvikServo: def __init__(self, packeter: ucPack, label: str, servo_id: int, position: list[int | None]): diff --git a/arduino_alvik/pinout_definitions.py b/arduino_alvik/pinout_definitions.py index 06d24a3..8892a38 100644 --- a/arduino_alvik/pinout_definitions.py +++ b/arduino_alvik/pinout_definitions.py @@ -13,8 +13,8 @@ RESET_STM32 = Pin(D3, Pin.OUT) # nano D3 -> STM32 NRST NANO_CHK = Pin(D4, Pin.OUT) # nano D4 -> STM32 NANO_CHK CHECK_STM32 = Pin(A6, Pin.IN, Pin.PULL_DOWN) # nano A6/D23 -> STM32 ROBOT_CHK -ESP32_SDA = Pin(A4, Pin.OUT) # ESP32_SDA -ESP32_SCL = Pin(A5, Pin.OUT) # ESP32_SCL +# ESP32_SDA = Pin(A4, Pin.OUT) # ESP32_SDA +# ESP32_SCL = Pin(A5, Pin.OUT) # ESP32_SCL # LEDS LEDR = Pin(46, Pin.OUT) #RED ESP32 LEDR From 69b100c1464e19adcac2507e1e3b3421531f239e Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Thu, 8 Aug 2024 12:02:59 +0200 Subject: [PATCH 24/46] ex: i2c_scan.py --- examples/i2c_scan.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 examples/i2c_scan.py diff --git a/examples/i2c_scan.py b/examples/i2c_scan.py new file mode 100644 index 0000000..9f8388e --- /dev/null +++ b/examples/i2c_scan.py @@ -0,0 +1,20 @@ +from time import sleep_ms + +from arduino_alvik import ArduinoAlvik + +alvik = ArduinoAlvik() +alvik.begin() + +sleep_ms(1000) + +while True: + out = alvik.i2c.scan() + + if len(out) == 0: + print("\nNo device found on I2C") + else: + print("\nList of devices") + for o in out: + print(o) + print(alvik.get_distance()) + sleep_ms(100) \ No newline at end of file From b7232157ddee8a07630e653366cf0a8d5a44ef0a Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Thu, 8 Aug 2024 15:09:30 +0200 Subject: [PATCH 25/46] mod: alvik_i2c single_thread operation based on thread id ex: i2c_scan.py better output --- arduino_alvik/arduino_alvik.py | 60 +++++++++++++++++++++++++--------- examples/i2c_scan.py | 4 +-- 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index 0f6b322..f8325c5 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -113,7 +113,7 @@ def _idle(self, delay_=1, check_on_thread=False, blocking=False) -> None: :return: """ NANO_CHK.value(1) - self.i2c._prio = True + self.i2c.set_single_thread(True) if blocking: self._lenghty_op(50000) @@ -123,14 +123,15 @@ def _idle(self, delay_=1, check_on_thread=False, blocking=False) -> None: try: while not self.is_on(): + if check_on_thread and not self.__class__._update_thread_running: break cmd = bytearray(1) cmd[0] = 0x06 - self.i2c.writeto(0x36, cmd, start=True, priority=True) + self.i2c.writeto(0x36, cmd, start=True) - soc_raw = struct.unpack('h', self.i2c.readfrom(0x36, 2, priority=True))[0] + soc_raw = struct.unpack('h', self.i2c.readfrom(0x36, 2))[0] soc_perc = soc_raw * 0.00390625 self._progress_bar(round(soc_perc)) if blocking: @@ -144,19 +145,19 @@ def _idle(self, delay_=1, check_on_thread=False, blocking=False) -> None: LEDR.value(led_val) LEDG.value(1) led_val = (led_val + 1) % 2 - self.i2c._prio = False + self.i2c.set_single_thread(False) print("********** Alvik is on **********") except KeyboardInterrupt: self.stop() sys.exit() except Exception as e: pass - # print(f'Unable to read SOC: {e}') + print(f'Unable to read SOC: {e}') finally: LEDR.value(1) LEDG.value(1) NANO_CHK.value(0) - self.i2c._prio = False + self.i2c.set_single_thread(False) @staticmethod def _snake_robot(duration: int = 1000): @@ -193,7 +194,8 @@ def begin(self) -> int: if not self.is_on(): print("\n********** Please turn on your Arduino Alvik! **********\n") sleep_ms(1000) - self._idle(1000) + self.i2c.set_main_thread(_thread.get_ident()) + self._idle(1000, blocking=True) self._begin_update_thread() sleep_ms(100) @@ -588,6 +590,9 @@ def _update(self, delay_=1): :param delay_: while loop delay (ms) :return: """ + + self.i2c.set_main_thread(_thread.get_ident()) + while True: if not self.is_on(): print("Alvik is off") @@ -1260,6 +1265,8 @@ def _stop_events_thread(cls): class _ArduinoAlvikI2C: + _main_thread_id = None + def __init__(self, sda: int, scl: int): """ Alvik I2C wrapper @@ -1267,10 +1274,33 @@ def __init__(self, sda: int, scl: int): :param scl: """ self._lock = _thread.allocate_lock() - self._prio = False + + self._is_single_thread = False + self.sda = sda self.scl = scl + def set_main_thread(self, thread_id: int): + """ + Sets the main thread of control. It will be the only thread allowed if set_single_thread is True + """ + with self._lock: + print(f"Setting I2C main thread to: {thread_id}") + self.__class__._main_thread_id = thread_id + + def set_single_thread(self, value): + """ + Sets the single thread mode on/off. + In single mode only the main thread is allowed to access the bus + """ + self._is_single_thread = value + + def is_accessible(self): + """ + Returns True if bus is accessible by the current thread + """ + return not self._is_single_thread or _thread.get_ident() == self.__class__._main_thread_id + def _start(self): """ Bitbanging start condition @@ -1281,12 +1311,12 @@ def _start(self): sleep_ms(100) _SDA.value(0) - def scan(self, start=False, priority=False): + def scan(self, start=False): """ I2C scan method :return: """ - if not priority and self._prio: + if not self.is_accessible(): return [] with self._lock: if start: @@ -1295,9 +1325,9 @@ def scan(self, start=False, priority=False): out = i2c.scan() return out - def readfrom(self, addr, nbytes, stop=True, start=False, priority=False): - if not priority and self._prio: - return None + def readfrom(self, addr, nbytes, stop=True, start=False): + if not self.is_accessible(): + return bytes(nbytes) with self._lock: if start: self._start() @@ -1305,8 +1335,8 @@ def readfrom(self, addr, nbytes, stop=True, start=False, priority=False): out = i2c.readfrom(addr, nbytes, stop) return out - def writeto(self, addr, buf, stop=True, start=False, priority=False): - if not priority and self._prio: + def writeto(self, addr, buf, stop=True, start=False): + if not self.is_accessible(): return None with self._lock: if start: diff --git a/examples/i2c_scan.py b/examples/i2c_scan.py index 9f8388e..6996681 100644 --- a/examples/i2c_scan.py +++ b/examples/i2c_scan.py @@ -15,6 +15,6 @@ else: print("\nList of devices") for o in out: - print(o) - print(alvik.get_distance()) + print(hex(o)) + sleep_ms(100) \ No newline at end of file From 99657809955f0f1ac811f99de0d8e687eaf89e13 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Thu, 8 Aug 2024 15:20:47 +0200 Subject: [PATCH 26/46] mod: rem start parameter from alvikI2C methods --- arduino_alvik/arduino_alvik.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index f8325c5..81ac240 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -129,7 +129,9 @@ def _idle(self, delay_=1, check_on_thread=False, blocking=False) -> None: cmd = bytearray(1) cmd[0] = 0x06 - self.i2c.writeto(0x36, cmd, start=True) + + self.i2c._start() + self.i2c.writeto(0x36, cmd) soc_raw = struct.unpack('h', self.i2c.readfrom(0x36, 2))[0] soc_perc = soc_raw * 0.00390625 @@ -1285,7 +1287,6 @@ def set_main_thread(self, thread_id: int): Sets the main thread of control. It will be the only thread allowed if set_single_thread is True """ with self._lock: - print(f"Setting I2C main thread to: {thread_id}") self.__class__._main_thread_id = thread_id def set_single_thread(self, value): @@ -1311,7 +1312,7 @@ def _start(self): sleep_ms(100) _SDA.value(0) - def scan(self, start=False): + def scan(self): """ I2C scan method :return: @@ -1319,28 +1320,22 @@ def scan(self, start=False): if not self.is_accessible(): return [] with self._lock: - if start: - self._start() i2c = I2C(0, scl=Pin(self.scl, Pin.OUT), sda=Pin(self.sda, Pin.OUT)) out = i2c.scan() return out - def readfrom(self, addr, nbytes, stop=True, start=False): + def readfrom(self, addr, nbytes, stop=True): if not self.is_accessible(): return bytes(nbytes) with self._lock: - if start: - self._start() i2c = I2C(0, scl=Pin(self.scl, Pin.OUT), sda=Pin(self.sda, Pin.OUT)) out = i2c.readfrom(addr, nbytes, stop) return out - def writeto(self, addr, buf, stop=True, start=False): + def writeto(self, addr, buf, stop=True): if not self.is_accessible(): return None with self._lock: - if start: - self._start() i2c = I2C(0, scl=Pin(self.scl, Pin.OUT), sda=Pin(self.sda, Pin.OUT)) out = i2c.writeto(addr, buf, stop) return out From 17b171bfd238a0e9a1d929f97f96f66f49d48a84 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Thu, 8 Aug 2024 15:52:31 +0200 Subject: [PATCH 27/46] feat: all i2c methods implemented for AlvikI2C --- arduino_alvik/arduino_alvik.py | 119 +++++++++++++++++++++++++++++---- 1 file changed, 107 insertions(+), 12 deletions(-) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index 81ac240..7fa2468 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -130,7 +130,7 @@ def _idle(self, delay_=1, check_on_thread=False, blocking=False) -> None: cmd = bytearray(1) cmd[0] = 0x06 - self.i2c._start() + self.i2c.start() self.i2c.writeto(0x36, cmd) soc_raw = struct.unpack('h', self.i2c.readfrom(0x36, 2))[0] @@ -1302,7 +1302,7 @@ def is_accessible(self): """ return not self._is_single_thread or _thread.get_ident() == self.__class__._main_thread_id - def _start(self): + def start(self): """ Bitbanging start condition :return: @@ -1312,7 +1312,28 @@ def _start(self): sleep_ms(100) _SDA.value(0) - def scan(self): + def init(self, scl, sda, freq=400_000) -> None: + """ + init method just for call compatibility + """ + print("AlvikWarning:: init Unsupported. Alvik defines/initializes its own I2C bus") + + def deinit(self): + """ + deinit method just for call compatibility + """ + print("AlvikWarning:: deinit Unsupported. Alvik defines/initializes its own I2C bus") + + def stop(self): + """ Bitbanging stop condition (untested) + :return: + """ + _SDA = Pin(self.sda, Pin.OUT) + _SDA.value(0) + sleep_ms(100) + _SDA.value(1) + + def scan(self) -> list[int]: """ I2C scan method :return: @@ -1321,24 +1342,98 @@ def scan(self): return [] with self._lock: i2c = I2C(0, scl=Pin(self.scl, Pin.OUT), sda=Pin(self.sda, Pin.OUT)) - out = i2c.scan() - return out + return i2c.scan() - def readfrom(self, addr, nbytes, stop=True): + def readfrom(self, addr, nbytes, stop=True) -> bytes: + """ + Wrapping i2c readfrom + """ if not self.is_accessible(): return bytes(nbytes) with self._lock: i2c = I2C(0, scl=Pin(self.scl, Pin.OUT), sda=Pin(self.sda, Pin.OUT)) - out = i2c.readfrom(addr, nbytes, stop) - return out + return i2c.readfrom(addr, nbytes, stop) + + def writeto(self, addr, buf, stop=True) -> int: + """ + Wrapping i2c writeto + """ + if not self.is_accessible(): + return 0 + with self._lock: + i2c = I2C(0, scl=Pin(self.scl, Pin.OUT), sda=Pin(self.sda, Pin.OUT)) + return i2c.writeto(addr, buf, stop) - def writeto(self, addr, buf, stop=True): + def readinto(self, buf, nack=True) -> None: + """ + Wrapping i2c readinto + """ if not self.is_accessible(): - return None + return with self._lock: i2c = I2C(0, scl=Pin(self.scl, Pin.OUT), sda=Pin(self.sda, Pin.OUT)) - out = i2c.writeto(addr, buf, stop) - return out + return i2c.readinto(buf, nack) + + def write(self, buf) -> int: + """ + Wrapping i2c write + """ + if not self.is_accessible(): + return 0 + with self._lock: + i2c = I2C(0, scl=Pin(self.scl, Pin.OUT), sda=Pin(self.sda, Pin.OUT)) + return i2c.write(buf) + + def readfrom_into(self, addr, buf, stop=True) -> None: + """ + Wrapping i2c readfrom_into + """ + if not self.is_accessible(): + return + with self._lock: + i2c = I2C(0, scl=Pin(self.scl, Pin.OUT), sda=Pin(self.sda, Pin.OUT)) + return i2c.readfrom_into(addr, buf, stop) + + def writevto(self, addr, vector, stop=True) -> int: + """ + Wrapping i2c writevto + """ + if not self.is_accessible(): + return 0 + with self._lock: + i2c = I2C(0, scl=Pin(self.scl, Pin.OUT), sda=Pin(self.sda, Pin.OUT)) + return i2c.writevto(addr, vector, stop) + + def readfrom_mem(self, addr, memaddr, nbytes, addrsize=8) -> bytes: + """ + Wrapping i2c readfrom_mem + """ + if not self.is_accessible(): + return bytes(nbytes) + with self._lock: + i2c = I2C(0, scl=Pin(self.scl, Pin.OUT), sda=Pin(self.sda, Pin.OUT)) + return i2c.readfrom_mem(addr, memaddr, nbytes, addrsize=addrsize) + + def readfrom_mem_into(self, addr, memaddr, buf, addrsize=8) -> None: + """ + Wrapping i2c readfrom_mem_into + """ + if not self.is_accessible(): + return + with self._lock: + i2c = I2C(0, scl=Pin(self.scl, Pin.OUT), sda=Pin(self.sda, Pin.OUT)) + return i2c.readfrom_mem_into(addr, memaddr, buf, addrsize=addrsize) + + def writeto_mem(self, addr, memaddr, buf, addrsize=8) -> None: + """ + Wrapping i2c writeto_mem + """ + if not self.is_accessible(): + return + with self._lock: + i2c = I2C(0, scl=Pin(self.scl, Pin.OUT), sda=Pin(self.sda, Pin.OUT)) + return i2c.writeto_mem(addr, memaddr, buf, addrsize=addrsize) + class _ArduinoAlvikServo: From 9716c38e2334f36350b1db61f6602ea7c5d738ea Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Thu, 8 Aug 2024 16:13:19 +0200 Subject: [PATCH 28/46] impr: i2c example --- examples/i2c_scan.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/examples/i2c_scan.py b/examples/i2c_scan.py index 6996681..a246787 100644 --- a/examples/i2c_scan.py +++ b/examples/i2c_scan.py @@ -1,4 +1,5 @@ from time import sleep_ms +import sys from arduino_alvik import ArduinoAlvik @@ -8,13 +9,17 @@ sleep_ms(1000) while True: - out = alvik.i2c.scan() + try: + out = alvik.i2c.scan() - if len(out) == 0: - print("\nNo device found on I2C") - else: - print("\nList of devices") - for o in out: - print(hex(o)) + if len(out) == 0: + print("\nNo device found on I2C") + else: + print("\nList of devices") + for o in out: + print(hex(o)) - sleep_ms(100) \ No newline at end of file + sleep_ms(100) + except KeyboardInterrupt as e: + alvik.stop() + sys.exit() \ No newline at end of file From a966f0ac835232428e2e10592df37c0b2332e08d Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Thu, 8 Aug 2024 16:25:27 +0200 Subject: [PATCH 29/46] fix: blocking idle makes update thread unstoppable --- arduino_alvik/arduino_alvik.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index 7fa2468..ff5f1aa 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -148,7 +148,8 @@ def _idle(self, delay_=1, check_on_thread=False, blocking=False) -> None: LEDG.value(1) led_val = (led_val + 1) % 2 self.i2c.set_single_thread(False) - print("********** Alvik is on **********") + if self.is_on(): + print("********** Alvik is on **********") except KeyboardInterrupt: self.stop() sys.exit() @@ -197,7 +198,7 @@ def begin(self) -> int: print("\n********** Please turn on your Arduino Alvik! **********\n") sleep_ms(1000) self.i2c.set_main_thread(_thread.get_ident()) - self._idle(1000, blocking=True) + self._idle(1000) self._begin_update_thread() sleep_ms(100) @@ -598,7 +599,7 @@ def _update(self, delay_=1): while True: if not self.is_on(): print("Alvik is off") - self._idle(1000, check_on_thread=True, blocking=True) + self._idle(1000, check_on_thread=True) self._reset_hw() self._flush_uart() sleep_ms(1000) From 419246229404deeb247b607bc0d8363cf6c1ea31 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Mon, 12 Aug 2024 12:25:28 +0200 Subject: [PATCH 30/46] feat: alvik wheels set position acknowledgment --- arduino_alvik/arduino_alvik.py | 38 +++++++++++++++++++++++++--------- examples/pose_example.py | 11 ++++------ examples/wheels_position.py | 34 +++++++++++++++++++++++++++++- 3 files changed, 65 insertions(+), 18 deletions(-) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index b2bd83e..6f83fa4 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -27,8 +27,8 @@ def __new__(cls): def __init__(self): self._packeter = ucPack(200) - self.left_wheel = _ArduinoAlvikWheel(self._packeter, ord('L')) - self.right_wheel = _ArduinoAlvikWheel(self._packeter, ord('R')) + self.left_wheel = _ArduinoAlvikWheel(self._packeter, ord('L'), alvik=self) + self.right_wheel = _ArduinoAlvikWheel(self._packeter, ord('R'), alvik=self) self._servo_positions = list((None, None,)) self.servo_A = _ArduinoAlvikServo(self._packeter, 'A', 0, self._servo_positions) self.servo_B = _ArduinoAlvikServo(self._packeter, 'B', 1, self._servo_positions) @@ -380,17 +380,22 @@ def set_wheels_speed(self, left_speed: float, right_speed: float, unit: str = 'r self._packeter.packetC2F(ord('J'), left_speed, right_speed) uart.write(self._packeter.msg[0:self._packeter.msg_size]) - def set_wheels_position(self, left_angle: float, right_angle: float, unit: str = 'deg'): + def set_wheels_position(self, left_angle: float, right_angle: float, unit: str = 'deg', blocking: bool = True): """ Sets left/right motor angle :param left_angle: :param right_angle: :param unit: the speed unit of measurement (default: 'rpm') + :param blocking: :return: """ - self._packeter.packetC2F(ord('A'), convert_angle(left_angle, unit, 'deg'), - convert_angle(right_angle, unit, 'deg')) + left_angle = convert_angle(left_angle, unit, 'deg') + right_angle = convert_angle(right_angle, unit, 'deg') + self._packeter.packetC2F(ord('A'), left_angle, right_angle) uart.write(self._packeter.msg[0:self._packeter.msg_size]) + self._waiting_ack = ord('P') + if blocking: + self._wait_for_target(idle_time=(max(left_angle, right_angle) / MOTOR_CONTROL_DEG_S)) def get_wheels_position(self, unit: str = 'deg') -> (float | None, float | None): """ @@ -1277,12 +1282,14 @@ def get_position(self) -> int: class _ArduinoAlvikWheel: - def __init__(self, packeter: ucPack, label: int, wheel_diameter_mm: float = WHEEL_DIAMETER_MM): + def __init__(self, packeter: ucPack, label: int, wheel_diameter_mm: float = WHEEL_DIAMETER_MM, + alvik: ArduinoAlvik = None): self._packeter = packeter self._label = label self._wheel_diameter_mm = wheel_diameter_mm self._speed = None self._position = None + self._alvik = alvik def reset(self, initial_position: float = 0.0, unit: str = 'deg'): """ @@ -1350,16 +1357,27 @@ def get_position(self, unit: str = 'deg') -> float | None: """ return convert_angle(self._position, 'deg', unit) - def set_position(self, position: float, unit: str = 'deg'): + def set_position(self, position: float, unit: str = 'deg', blocking: bool = True): """ Sets left/right motor speed - :param position: the speed of the motor + :param position: the position of the motor :param unit: the unit of measurement + :param blocking: :return: """ - self._packeter.packetC2B1F(ord('W'), self._label & 0xFF, ord('P'), - convert_angle(position, unit, 'deg')) + position = convert_angle(position, unit, 'deg') + self._packeter.packetC2B1F(ord('W'), self._label & 0xFF, ord('P'), position) uart.write(self._packeter.msg[0:self._packeter.msg_size]) + self._alvik._waiting_ack = ord('P') + if blocking: + self._alvik._wait_for_target(idle_time=(position / MOTOR_CONTROL_DEG_S)) + + def is_target_reached(self): + """ + Checks if the target position is reached + :return: + """ + return self._alvik.is_target_reached() class _ArduinoAlvikRgbLed: diff --git a/examples/pose_example.py b/examples/pose_example.py index ab248e9..11b675a 100644 --- a/examples/pose_example.py +++ b/examples/pose_example.py @@ -32,40 +32,37 @@ print("___________NON-BLOCKING__________________") alvik.move(50.0, 'mm', blocking=False) - print("on target after move") while not alvik.is_target_reached(): alvik.left_led.set_color(1, 0, 0) sleep_ms(500) alvik.left_led.set_color(0, 0, 0) sleep_ms(500) + print("on target after move") alvik.rotate(45.0, 'deg', blocking=False) - print("on target after rotation") - while not alvik.is_target_reached(): alvik.left_led.set_color(1, 0, 0) sleep_ms(500) alvik.left_led.set_color(0, 0, 0) sleep_ms(500) + print("on target after rotation") alvik.move(100.0, 'mm', blocking=False) - print("on target after move") - while not alvik.is_target_reached(): alvik.left_led.set_color(1, 0, 0) sleep_ms(500) alvik.left_led.set_color(0, 0, 0) sleep_ms(500) + print("on target after move") alvik.rotate(-90.00, 'deg', blocking=False) - print("on target after rotation") - while not alvik.is_target_reached(): alvik.left_led.set_color(1, 0, 0) sleep_ms(500) alvik.left_led.set_color(0, 0, 0) sleep_ms(500) + print("on target after rotation") x, y, theta = alvik.get_pose() print(f'Current pose is x(cm)={x}, y(cm)={y}, theta(deg)={theta}') diff --git a/examples/wheels_position.py b/examples/wheels_position.py index b4220dd..47cd6c0 100644 --- a/examples/wheels_position.py +++ b/examples/wheels_position.py @@ -1,5 +1,5 @@ from arduino_alvik import ArduinoAlvik -from time import sleep +from time import sleep, sleep_ms import sys alvik = ArduinoAlvik() @@ -10,6 +10,12 @@ while True: try: + + alvik.set_wheels_position(45, 45) + sleep(2) + print(f'Left wheel degs: {alvik.left_wheel.get_position()}') + print(f'Right wheel degs: {alvik.right_wheel.get_position()}') + alvik.left_wheel.set_position(30) sleep(2) print(f'Left wheel degs: {alvik.left_wheel.get_position()}') @@ -30,6 +36,32 @@ print(f'Left wheel degs: {alvik.left_wheel.get_position()}') print(f'Right wheel degs: {alvik.right_wheel.get_position()}') + print("___________NON-BLOCKING__________________") + + alvik.set_wheels_position(90, 90, blocking=False) + while not alvik.is_target_reached(): + alvik.left_led.set_color(1, 0, 0) + sleep_ms(500) + alvik.left_led.set_color(0, 0, 0) + sleep_ms(500) + print(f'Wheels position reached: R{alvik.right_wheel.get_position()} L:{alvik.left_wheel.get_position()}') + + alvik.left_wheel.set_position(180) + while not alvik.left_wheel.is_target_reached(): + alvik.left_led.set_color(1, 0, 0) + sleep_ms(500) + alvik.left_led.set_color(0, 0, 0) + sleep_ms(500) + print(f'Left wheel position reached: {alvik.left_wheel.get_position()}') + + alvik.right_wheel.set_position(180) + while not alvik.right_wheel.is_target_reached(): + alvik.right_led.set_color(1, 0, 0) + sleep_ms(500) + alvik.right_led.set_color(0, 0, 0) + sleep_ms(500) + print(f'Left wheel position reached: {alvik.right_wheel.get_position()}') + except KeyboardInterrupt as e: print('over') alvik.stop() From 43ceb09675b058baca4de7bcfa1a2ed8acfb10ee Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Mon, 12 Aug 2024 12:42:26 +0200 Subject: [PATCH 31/46] fix: wheels_position.py --- examples/wheels_position.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/wheels_position.py b/examples/wheels_position.py index 47cd6c0..4f8a6a5 100644 --- a/examples/wheels_position.py +++ b/examples/wheels_position.py @@ -41,25 +41,25 @@ alvik.set_wheels_position(90, 90, blocking=False) while not alvik.is_target_reached(): alvik.left_led.set_color(1, 0, 0) - sleep_ms(500) + sleep_ms(200) alvik.left_led.set_color(0, 0, 0) - sleep_ms(500) - print(f'Wheels position reached: R{alvik.right_wheel.get_position()} L:{alvik.left_wheel.get_position()}') + sleep_ms(200) + print(f'Wheels position reached: R:{alvik.right_wheel.get_position()} L:{alvik.left_wheel.get_position()}') - alvik.left_wheel.set_position(180) + alvik.left_wheel.set_position(180, blocking=False) while not alvik.left_wheel.is_target_reached(): alvik.left_led.set_color(1, 0, 0) - sleep_ms(500) + sleep_ms(200) alvik.left_led.set_color(0, 0, 0) - sleep_ms(500) + sleep_ms(200) print(f'Left wheel position reached: {alvik.left_wheel.get_position()}') - alvik.right_wheel.set_position(180) + alvik.right_wheel.set_position(180, blocking=False) while not alvik.right_wheel.is_target_reached(): alvik.right_led.set_color(1, 0, 0) - sleep_ms(500) + sleep_ms(200) alvik.right_led.set_color(0, 0, 0) - sleep_ms(500) + sleep_ms(200) print(f'Left wheel position reached: {alvik.right_wheel.get_position()}') except KeyboardInterrupt as e: From 5b91e512431d9ab9333e79f7b7a723ad6811ee62 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Mon, 12 Aug 2024 12:54:42 +0200 Subject: [PATCH 32/46] ex: wheels_position.py --- examples/wheels_position.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/examples/wheels_position.py b/examples/wheels_position.py index 4f8a6a5..6f3a151 100644 --- a/examples/wheels_position.py +++ b/examples/wheels_position.py @@ -12,27 +12,22 @@ try: alvik.set_wheels_position(45, 45) - sleep(2) print(f'Left wheel degs: {alvik.left_wheel.get_position()}') print(f'Right wheel degs: {alvik.right_wheel.get_position()}') alvik.left_wheel.set_position(30) - sleep(2) print(f'Left wheel degs: {alvik.left_wheel.get_position()}') print(f'Right wheel degs: {alvik.right_wheel.get_position()}') alvik.right_wheel.set_position(10) - sleep(2) print(f'Left wheel degs: {alvik.left_wheel.get_position()}') print(f'Right wheel degs: {alvik.right_wheel.get_position()}') alvik.left_wheel.set_position(180) - sleep(2) print(f'Left wheel degs: {alvik.left_wheel.get_position()}') print(f'Right wheel degs: {alvik.right_wheel.get_position()}') alvik.right_wheel.set_position(270) - sleep(2) print(f'Left wheel degs: {alvik.left_wheel.get_position()}') print(f'Right wheel degs: {alvik.right_wheel.get_position()}') @@ -41,8 +36,10 @@ alvik.set_wheels_position(90, 90, blocking=False) while not alvik.is_target_reached(): alvik.left_led.set_color(1, 0, 0) + alvik.right_led.set_color(1, 0, 0) sleep_ms(200) alvik.left_led.set_color(0, 0, 0) + alvik.right_led.set_color(0, 0, 0) sleep_ms(200) print(f'Wheels position reached: R:{alvik.right_wheel.get_position()} L:{alvik.left_wheel.get_position()}') From dbe98abccf99555d023508e132adac2343e8e5f0 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Mon, 12 Aug 2024 15:48:55 +0200 Subject: [PATCH 33/46] fix: ALVIKDEV-95 battery readout must be stored in status when in idle mode --- arduino_alvik/arduino_alvik.py | 1 + 1 file changed, 1 insertion(+) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index ff5f1aa..c4b9486 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -135,6 +135,7 @@ def _idle(self, delay_=1, check_on_thread=False, blocking=False) -> None: soc_raw = struct.unpack('h', self.i2c.readfrom(0x36, 2))[0] soc_perc = soc_raw * 0.00390625 + self._battery_perc = soc_perc self._progress_bar(round(soc_perc)) if blocking: self._lenghty_op(10000) From 4379f3200bf0dc74d9f7fb5a27245418c040f65f Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Mon, 12 Aug 2024 16:27:37 +0200 Subject: [PATCH 34/46] ver: 1.0.2 ex: rearranged examples folder --- README.md | 2 +- arduino_alvik/__init__.py | 2 +- examples/{ => actuators}/leds_setting.py | 0 examples/{ => actuators}/move_wheels.py | 0 examples/{ => actuators}/pose_example.py | 0 examples/{ => actuators}/set_servo.py | 0 examples/{ => actuators}/wheels_position.py | 0 examples/{ => actuators}/wheels_speed.py | 0 examples/{ => communication}/i2c_scan.py | 0 examples/{ => demo}/demo.py | 0 examples/{ => demo}/hand_follower.py | 0 examples/{ => demo}/line_follower.py | 0 examples/{ => demo}/main.py | 0 examples/{ => demo}/touch_move.py | 0 examples/{movement_events.py => events/motion_events.py} | 0 examples/{ => events}/timer_one_shot_events.py | 0 examples/{ => events}/timer_periodic_events.py | 0 examples/{ => events}/touch_events.py | 0 examples/{ => sensors}/read_color_sensor.py | 0 examples/{ => sensors}/read_imu.py | 0 examples/{ => sensors}/read_orientation.py | 0 examples/{ => sensors}/read_tof.py | 0 examples/{ => sensors}/read_touch.py | 0 examples/{ => tests}/message_reader.py | 0 examples/{ => tests}/test_idle.py | 0 examples/{ => tests}/test_meas_units.py | 0 package.json | 2 +- 27 files changed, 3 insertions(+), 3 deletions(-) rename examples/{ => actuators}/leds_setting.py (100%) rename examples/{ => actuators}/move_wheels.py (100%) rename examples/{ => actuators}/pose_example.py (100%) rename examples/{ => actuators}/set_servo.py (100%) rename examples/{ => actuators}/wheels_position.py (100%) rename examples/{ => actuators}/wheels_speed.py (100%) rename examples/{ => communication}/i2c_scan.py (100%) rename examples/{ => demo}/demo.py (100%) rename examples/{ => demo}/hand_follower.py (100%) rename examples/{ => demo}/line_follower.py (100%) rename examples/{ => demo}/main.py (100%) rename examples/{ => demo}/touch_move.py (100%) rename examples/{movement_events.py => events/motion_events.py} (100%) rename examples/{ => events}/timer_one_shot_events.py (100%) rename examples/{ => events}/timer_periodic_events.py (100%) rename examples/{ => events}/touch_events.py (100%) rename examples/{ => sensors}/read_color_sensor.py (100%) rename examples/{ => sensors}/read_imu.py (100%) rename examples/{ => sensors}/read_orientation.py (100%) rename examples/{ => sensors}/read_tof.py (100%) rename examples/{ => sensors}/read_touch.py (100%) rename examples/{ => tests}/message_reader.py (100%) rename examples/{ => tests}/test_idle.py (100%) rename examples/{ => tests}/test_meas_units.py (100%) diff --git a/README.md b/README.md index 94ba587..55915a6 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ You can now use Arduino Lab for Micropython to run your examples remotely from t ## Default Demo -Use `mpremote` to copy following the files from the examples folder: +Use `mpremote` to copy following the files from the `examples\demo` folder: - `main.py`, this file allows you to automatically start the demo - `demo.py`, demo launcher - `touch_move.py`, programming the robot movements via touch buttons demo diff --git a/arduino_alvik/__init__.py b/arduino_alvik/__init__.py index f4c742a..8561554 100644 --- a/arduino_alvik/__init__.py +++ b/arduino_alvik/__init__.py @@ -4,7 +4,7 @@ __author__ = "Lucio Rossi , Giovanni Bruno " __license__ = "MPL 2.0" -__version__ = "1.0.1" +__version__ = "1.0.2" __maintainer__ = "Lucio Rossi , Giovanni Bruno " from .arduino_alvik import * diff --git a/examples/leds_setting.py b/examples/actuators/leds_setting.py similarity index 100% rename from examples/leds_setting.py rename to examples/actuators/leds_setting.py diff --git a/examples/move_wheels.py b/examples/actuators/move_wheels.py similarity index 100% rename from examples/move_wheels.py rename to examples/actuators/move_wheels.py diff --git a/examples/pose_example.py b/examples/actuators/pose_example.py similarity index 100% rename from examples/pose_example.py rename to examples/actuators/pose_example.py diff --git a/examples/set_servo.py b/examples/actuators/set_servo.py similarity index 100% rename from examples/set_servo.py rename to examples/actuators/set_servo.py diff --git a/examples/wheels_position.py b/examples/actuators/wheels_position.py similarity index 100% rename from examples/wheels_position.py rename to examples/actuators/wheels_position.py diff --git a/examples/wheels_speed.py b/examples/actuators/wheels_speed.py similarity index 100% rename from examples/wheels_speed.py rename to examples/actuators/wheels_speed.py diff --git a/examples/i2c_scan.py b/examples/communication/i2c_scan.py similarity index 100% rename from examples/i2c_scan.py rename to examples/communication/i2c_scan.py diff --git a/examples/demo.py b/examples/demo/demo.py similarity index 100% rename from examples/demo.py rename to examples/demo/demo.py diff --git a/examples/hand_follower.py b/examples/demo/hand_follower.py similarity index 100% rename from examples/hand_follower.py rename to examples/demo/hand_follower.py diff --git a/examples/line_follower.py b/examples/demo/line_follower.py similarity index 100% rename from examples/line_follower.py rename to examples/demo/line_follower.py diff --git a/examples/main.py b/examples/demo/main.py similarity index 100% rename from examples/main.py rename to examples/demo/main.py diff --git a/examples/touch_move.py b/examples/demo/touch_move.py similarity index 100% rename from examples/touch_move.py rename to examples/demo/touch_move.py diff --git a/examples/movement_events.py b/examples/events/motion_events.py similarity index 100% rename from examples/movement_events.py rename to examples/events/motion_events.py diff --git a/examples/timer_one_shot_events.py b/examples/events/timer_one_shot_events.py similarity index 100% rename from examples/timer_one_shot_events.py rename to examples/events/timer_one_shot_events.py diff --git a/examples/timer_periodic_events.py b/examples/events/timer_periodic_events.py similarity index 100% rename from examples/timer_periodic_events.py rename to examples/events/timer_periodic_events.py diff --git a/examples/touch_events.py b/examples/events/touch_events.py similarity index 100% rename from examples/touch_events.py rename to examples/events/touch_events.py diff --git a/examples/read_color_sensor.py b/examples/sensors/read_color_sensor.py similarity index 100% rename from examples/read_color_sensor.py rename to examples/sensors/read_color_sensor.py diff --git a/examples/read_imu.py b/examples/sensors/read_imu.py similarity index 100% rename from examples/read_imu.py rename to examples/sensors/read_imu.py diff --git a/examples/read_orientation.py b/examples/sensors/read_orientation.py similarity index 100% rename from examples/read_orientation.py rename to examples/sensors/read_orientation.py diff --git a/examples/read_tof.py b/examples/sensors/read_tof.py similarity index 100% rename from examples/read_tof.py rename to examples/sensors/read_tof.py diff --git a/examples/read_touch.py b/examples/sensors/read_touch.py similarity index 100% rename from examples/read_touch.py rename to examples/sensors/read_touch.py diff --git a/examples/message_reader.py b/examples/tests/message_reader.py similarity index 100% rename from examples/message_reader.py rename to examples/tests/message_reader.py diff --git a/examples/test_idle.py b/examples/tests/test_idle.py similarity index 100% rename from examples/test_idle.py rename to examples/tests/test_idle.py diff --git a/examples/test_meas_units.py b/examples/tests/test_meas_units.py similarity index 100% rename from examples/test_meas_units.py rename to examples/tests/test_meas_units.py diff --git a/package.json b/package.json index a1be8be..5cfb1ae 100644 --- a/package.json +++ b/package.json @@ -12,5 +12,5 @@ "deps": [ ["github:arduino/ucPack-mpy", "0.1.6"] ], - "version": "1.0.1" + "version": "1.0.2" } From 4ed7f46a41e34bd143964711e2d288001ba4ea0e Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Mon, 12 Aug 2024 16:39:04 +0200 Subject: [PATCH 35/46] ex: modulino.py --- examples/communication/modulino.py | 35 ++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 examples/communication/modulino.py diff --git a/examples/communication/modulino.py b/examples/communication/modulino.py new file mode 100644 index 0000000..bf1e8e2 --- /dev/null +++ b/examples/communication/modulino.py @@ -0,0 +1,35 @@ +from arduino_alvik import ArduinoAlvik +from time import sleep_ms +import sys +try: + from modulino import ModulinoPixels +except ImportError as e: + print("ImportError: ModulinoPixels not installed") + sys.exit(-1) + +alvik = ArduinoAlvik() +alvik.begin() + +pixels = ModulinoPixels(alvik.i2c) + +if not pixels.connected: + print("🤷 No pixel modulino found") + sys.exit(-2) + +while True: + try: + for i in range(0, 8): + pixels.clear_all() + pixels.set_rgb(i, 255, 0, 0, 100) + pixels.show() + sleep_ms(50) + + for i in range(7, -1, -1): + pixels.clear_all() + pixels.set_rgb(i, 255, 0, 0, 100) + pixels.show() + sleep_ms(50) + + except KeyboardInterrupt as e: + alvik.stop() + sys.exit() From d2f7d320232128b8ce381637965626b355a7f7d2 Mon Sep 17 00:00:00 2001 From: Giovanni Bruno Date: Wed, 21 Aug 2024 18:36:44 +0200 Subject: [PATCH 36/46] 1.0.3 - added check version --- arduino_alvik/__init__.py | 3 +- arduino_alvik/arduino_alvik.py | 66 +++++++++++++++++++++++++++++--- examples/tests/message_reader.py | 2 +- package.json | 2 +- 4 files changed, 65 insertions(+), 8 deletions(-) diff --git a/arduino_alvik/__init__.py b/arduino_alvik/__init__.py index 8561554..d3e412f 100644 --- a/arduino_alvik/__init__.py +++ b/arduino_alvik/__init__.py @@ -4,7 +4,8 @@ __author__ = "Lucio Rossi , Giovanni Bruno " __license__ = "MPL 2.0" -__version__ = "1.0.2" +__version__ = "1.0.3" __maintainer__ = "Lucio Rossi , Giovanni Bruno " +__required_firmware_version__ = "1.0.3" from .arduino_alvik import * diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index 3351fb5..03421eb 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -13,6 +13,9 @@ from .robot_definitions import * from .constants import * +from .__init__ import __version__ +from .__init__ import __required_firmware_version__ + class ArduinoAlvik: _update_thread_running = False @@ -73,7 +76,9 @@ def __init__(self): self._angular_velocity = None self._last_ack = None self._waiting_ack = None - self._version = [None, None, None] + self._version = list(map(int, __version__.split('.'))) + self._fw_version = [None, None, None] + self._required_fw_version = list(map(int, __required_firmware_version__.split('.'))) self._touch_events = _ArduinoAlvikTouchEvents() self._move_events = _ArduinoAlvikMoveEvents() self._timer_events = _ArduinoAlvikTimerEvents(-1) @@ -208,6 +213,9 @@ def begin(self) -> int: self._flush_uart() self._snake_robot(1000) self._wait_for_ack() + if not self._wait_for_fw_check(): + print('\n********** PLEASE UPDATE ALVIK FIRMWARE! Check documentation **********\n') + sys.exit(-2) self._snake_robot(2000) self.set_illuminator(True) self.set_behaviour(1) @@ -241,6 +249,18 @@ def _wait_for_ack(self) -> None: sleep_ms(20) self._waiting_ack = None + def _wait_for_fw_check(self) -> bool: + """ + Waits until receives version from robot, check required version and return true if everything is ok + :return: + """ + while self._fw_version == [None, None, None]: + sleep_ms(20) + if self.check_firmware_compatibility(): + return True + else: + return False + @staticmethod def _flush_uart(): """ @@ -689,7 +709,7 @@ def _parse_message(self) -> int: _, self._x, self._y, self._theta = self._packeter.unpacketC3F() elif code == 0x7E: # firmware version - _, *self._version = self._packeter.unpacketC3B() + _, *self._fw_version = self._packeter.unpacketC3B() else: return -1 @@ -1053,12 +1073,46 @@ def get_distance_bottom(self, unit: str = 'cm') -> float | None: """ return convert_distance(self._bottom_tof, 'mm', unit) - def get_version(self) -> str: + def get_version(self, version: str = 'fw') -> str: + """ + Returns the version of the Alvik firmware or micropython library + :param version: + :return: + """ + if version == 'fw' or version == 'FW' or version == 'firmware': + return self.get_fw_version() + elif version == 'lib' or version == 'LIB': + return self.get_lib_version() + else: + return f'{None, None, None}' + + def get_lib_version(self) -> str: """ - Returns the firmware version of the Alvik + Returns the micropython library version of the Alvik :return: """ return f'{self._version[0]}.{self._version[1]}.{self._version[2]}' + + def get_fw_version(self) -> str: + """ + Returns the firmware version of the Alvik Carrier + :return: + """ + return f'{self._fw_version[0]}.{self._fw_version[1]}.{self._fw_version[2]}' + + def get_required_fw_version(self) -> str: + """ + Returns the required firmware version of the Alvik Carrier for this micropython library + :return: + """ + return f'{self._required_fw_version[0]}.{self._required_fw_version[1]}.{self._required_fw_version[2]}' + + def check_firmware_compatibility(self) -> bool: + """ + Returns true if the library and the firmware are compatible + :return: + """ + return self._fw_version == self._required_fw_version def print_status(self): """ @@ -1066,7 +1120,9 @@ def print_status(self): :return: """ print('---ALVIK STATUS---') - print(f'VERSION: {self._version}') + print(f'LIBRARY VERSION: {self._version}') + print(f'REQUIRED FW VERSION: {self._required_fw_version}') + print(f'FIRMWARE VERSION: {self._fw_version}') print('---SENSORS---') print(f'TOF: T:{self._top_tof} B:{self._bottom_tof} L:{self._left_tof} CL:{self._center_left_tof}' + diff --git a/examples/tests/message_reader.py b/examples/tests/message_reader.py index e03707c..7ae24e1 100644 --- a/examples/tests/message_reader.py +++ b/examples/tests/message_reader.py @@ -9,7 +9,7 @@ while True: try: - print(f'VER: {alvik.get_version()}') + print(f'FW VER: {alvik.get_fw_version()}') print(f'LSP: {alvik.left_wheel.get_speed()}') print(f'RSP: {alvik.right_wheel.get_speed()}') print(f'LPOS: {alvik.left_wheel.get_position()}') diff --git a/package.json b/package.json index 5cfb1ae..df6d045 100644 --- a/package.json +++ b/package.json @@ -12,5 +12,5 @@ "deps": [ ["github:arduino/ucPack-mpy", "0.1.6"] ], - "version": "1.0.2" + "version": "1.0.3" } From 07ff960f26f514e3e5b787862738b231ca690974 Mon Sep 17 00:00:00 2001 From: Giovanni Bruno Date: Wed, 21 Aug 2024 18:43:47 +0200 Subject: [PATCH 37/46] test version --- examples/tests/test_version.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 examples/tests/test_version.py diff --git a/examples/tests/test_version.py b/examples/tests/test_version.py new file mode 100644 index 0000000..1682316 --- /dev/null +++ b/examples/tests/test_version.py @@ -0,0 +1,19 @@ +from arduino_alvik import ArduinoAlvik +from time import sleep_ms +import sys + +alvik = ArduinoAlvik() + +alvik.begin() + +while True: + try: + print(f'\nLIBRARY VERSION: {alvik.get_lib_version()}') + print(f'FIRMWARE VERSION: {alvik.get_fw_version()}') + print(f'REQUIRED FW VERSION: {alvik.get_required_fw_version()}') + print(f'FIRMWARE VERSION COMPATIBILITY CHECK: {alvik.check_firmware_compatibility()}\n') + sleep_ms(1000) + except KeyboardInterrupt as e: + print('over') + alvik.stop() + sys.exit() \ No newline at end of file From 60b1baace864a6a654bd5472600370af5418d349 Mon Sep 17 00:00:00 2001 From: Giovanni Bruno Date: Wed, 21 Aug 2024 19:01:27 +0200 Subject: [PATCH 38/46] added required version in message --- arduino_alvik/arduino_alvik.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index 03421eb..476e000 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -214,7 +214,7 @@ def begin(self) -> int: self._snake_robot(1000) self._wait_for_ack() if not self._wait_for_fw_check(): - print('\n********** PLEASE UPDATE ALVIK FIRMWARE! Check documentation **********\n') + print('\n********** PLEASE UPDATE ALVIK FIRMWARE (required: '+'.'.join(map(str,self._required_fw_version))+')! Check documentation **********\n') sys.exit(-2) self._snake_robot(2000) self.set_illuminator(True) From 48db6a3d26c798b4be06fa6e71de005901f716fc Mon Sep 17 00:00:00 2001 From: Giovanni Bruno Date: Thu, 29 Aug 2024 17:23:14 +0200 Subject: [PATCH 39/46] fixed flash_firmware.py --- examples/flash_firmware.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/flash_firmware.py b/examples/flash_firmware.py index e96a3cf..a3327da 100644 --- a/examples/flash_firmware.py +++ b/examples/flash_firmware.py @@ -1,5 +1,10 @@ # from machine import reset from arduino_alvik import update_firmware +# this is a patch to fix possible running threads on Alvik +from arduino_alvik import ArduinoAlvik +alvik = ArduinoAlvik() +alvik.stop() + update_firmware('./firmware.bin') -# reset() +# reset() \ No newline at end of file From 177c43620b08ee6f66fac4d11839564eebddbd88 Mon Sep 17 00:00:00 2001 From: Giovanni Bruno Date: Thu, 26 Sep 2024 10:33:05 +0200 Subject: [PATCH 40/46] 1.0.4 - default servo 90 --- arduino_alvik/__init__.py | 2 +- arduino_alvik/arduino_alvik.py | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arduino_alvik/__init__.py b/arduino_alvik/__init__.py index d3e412f..52e97bb 100644 --- a/arduino_alvik/__init__.py +++ b/arduino_alvik/__init__.py @@ -4,7 +4,7 @@ __author__ = "Lucio Rossi , Giovanni Bruno " __license__ = "MPL 2.0" -__version__ = "1.0.3" +__version__ = "1.0.4" __maintainer__ = "Lucio Rossi , Giovanni Bruno " __required_firmware_version__ = "1.0.3" diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index 476e000..039a41e 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -223,7 +223,7 @@ def begin(self) -> int: if self._has_events_registered(): print('Starting events thread') self._start_events_thread() - self.set_servo_positions(0, 0) + self.set_servo_positions(90, 90) return 0 def _has_events_registered(self) -> bool: diff --git a/package.json b/package.json index df6d045..3ac4da9 100644 --- a/package.json +++ b/package.json @@ -12,5 +12,5 @@ "deps": [ ["github:arduino/ucPack-mpy", "0.1.6"] ], - "version": "1.0.3" + "version": "1.0.4" } From b388b8100692698e938a18552d671bfba928ad50 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Wed, 9 Oct 2024 12:47:11 +0200 Subject: [PATCH 41/46] feat: alvik _battery_is_charging info --- arduino_alvik/arduino_alvik.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index 476e000..7b63d96 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -42,6 +42,7 @@ def __init__(self): self.right_led = self.DL2 = _ArduinoAlvikRgbLed(self._packeter, 'right', self._led_state, rgb_mask=[0b00100000, 0b01000000, 0b10000000]) self._battery_perc = None + self._battery_is_charging = None self._touch_byte = None self._move_byte = None self._behaviour = None @@ -92,10 +93,11 @@ def is_on() -> bool: return CHECK_STM32.value() == 1 @staticmethod - def _progress_bar(percentage: float) -> None: + def _print_battery_status(percentage: float, is_charging) -> None: """ - Prints a progressbar - :param percentage: + Pretty prints the battery status + :param percentage: SOC of the battery + :param is_charging: True if the battery is charging :return: """ sys.stdout.write(bytes('\r'.encode('utf-8'))) @@ -103,7 +105,8 @@ def _progress_bar(percentage: float) -> None: marks_str = ' \U0001F50B' else: marks_str = ' \U0001FAAB' - word = marks_str + f" {percentage}% \t" + charging_str = f' \U0001F50C' if is_charging else ' \U000026A0WARNING: battery is discharging!' + word = marks_str + f" {percentage}%" + charging_str + " \t" sys.stdout.write(bytes((word.encode('utf-8')))) def _lenghty_op(self, iterations=10000000) -> int: @@ -140,8 +143,9 @@ def _idle(self, delay_=1, check_on_thread=False, blocking=False) -> None: soc_raw = struct.unpack('h', self.i2c.readfrom(0x36, 2))[0] soc_perc = soc_raw * 0.00390625 - self._battery_perc = soc_perc - self._progress_bar(round(soc_perc)) + self._battery_is_charging = soc_perc > 0 + self._battery_perc = abs(soc_perc) + self._print_battery_status(round(soc_perc), self._battery_is_charging) if blocking: self._lenghty_op(10000) else: @@ -671,7 +675,9 @@ def _parse_message(self) -> int: _, self._ax, self._ay, self._az, self._gx, self._gy, self._gz = self._packeter.unpacketC6F() elif code == ord('p'): # battery percentage - _, self._battery_perc = self._packeter.unpacketC1F() + _, battery_perc = self._packeter.unpacketC1F() + self._battery_is_charging = battery_perc > 0 + self._battery_perc = abs(battery_perc) elif code == ord('d'): # distance sensor _, self._left_tof, self._center_tof, self._right_tof = self._packeter.unpacketC3I() From 7835a2a54332b576933dd4f930fcc2946a25db48 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Wed, 9 Oct 2024 14:48:05 +0200 Subject: [PATCH 42/46] mod: alvik.begin activates battery check behaviour --- arduino_alvik/arduino_alvik.py | 1 + 1 file changed, 1 insertion(+) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index 7b63d96..748231c 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -223,6 +223,7 @@ def begin(self) -> int: self._snake_robot(2000) self.set_illuminator(True) self.set_behaviour(1) + self.set_behaviour(2) self._set_color_reference() if self._has_events_registered(): print('Starting events thread') From 91f3bb461aa777658e8f061dc0125b9b74f1108c Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Wed, 9 Oct 2024 17:56:42 +0200 Subject: [PATCH 43/46] feat: alvik.is_battery_charging --- arduino_alvik/arduino_alvik.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index 748231c..0b89d64 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -733,6 +733,13 @@ def get_battery_charge(self) -> int | None: return 100 return round(self._battery_perc) + def is_battery_charging(self) -> bool: + """ + Returns True if the device battery is charging + :return: + """ + return self._battery_is_charging + @property def _touch_bits(self) -> int: """ From 5ba7b4043fce0447fc05c3d0a22d21365443e4a4 Mon Sep 17 00:00:00 2001 From: Giovanni Bruno Date: Thu, 10 Oct 2024 19:12:42 +0200 Subject: [PATCH 44/46] 1.0.5 - battery alert --- arduino_alvik/__init__.py | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arduino_alvik/__init__.py b/arduino_alvik/__init__.py index 52e97bb..a1b78be 100644 --- a/arduino_alvik/__init__.py +++ b/arduino_alvik/__init__.py @@ -4,8 +4,8 @@ __author__ = "Lucio Rossi , Giovanni Bruno " __license__ = "MPL 2.0" -__version__ = "1.0.4" +__version__ = "1.0.5" __maintainer__ = "Lucio Rossi , Giovanni Bruno " -__required_firmware_version__ = "1.0.3" +__required_firmware_version__ = "1.0.4" from .arduino_alvik import * diff --git a/package.json b/package.json index 3ac4da9..bfd3bb6 100644 --- a/package.json +++ b/package.json @@ -12,5 +12,5 @@ "deps": [ ["github:arduino/ucPack-mpy", "0.1.6"] ], - "version": "1.0.4" + "version": "1.0.5" } From bffa68124ef48bbd160379eb253047b6d29ddaef Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Tue, 15 Oct 2024 14:27:21 +0200 Subject: [PATCH 45/46] mod: set_behaviour(2) in _update method --- arduino_alvik/arduino_alvik.py | 1 + 1 file changed, 1 insertion(+) diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index 1a21ef5..d83305a 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -638,6 +638,7 @@ def _update(self, delay_=1): sleep_ms(2000) self.set_illuminator(True) self.set_behaviour(1) + self.set_behaviour(2) if not ArduinoAlvik._update_thread_running: break if self._read_message(): From 8a48f838d156c933bc8ddf0f69f3940c7591a283 Mon Sep 17 00:00:00 2001 From: Giovanni Bruno Date: Wed, 16 Oct 2024 16:38:36 +0200 Subject: [PATCH 46/46] 1.1.0 ready --- arduino_alvik/__init__.py | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arduino_alvik/__init__.py b/arduino_alvik/__init__.py index a1b78be..50fb7db 100644 --- a/arduino_alvik/__init__.py +++ b/arduino_alvik/__init__.py @@ -4,8 +4,8 @@ __author__ = "Lucio Rossi , Giovanni Bruno " __license__ = "MPL 2.0" -__version__ = "1.0.5" +__version__ = "1.1.0" __maintainer__ = "Lucio Rossi , Giovanni Bruno " -__required_firmware_version__ = "1.0.4" +__required_firmware_version__ = "1.1.0" from .arduino_alvik import * diff --git a/package.json b/package.json index bfd3bb6..8c829cb 100644 --- a/package.json +++ b/package.json @@ -12,5 +12,5 @@ "deps": [ ["github:arduino/ucPack-mpy", "0.1.6"] ], - "version": "1.0.5" + "version": "1.1.0" }