diff --git a/README.md b/README.md index 55915a6..0efb38f 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ Each color allows to run a different demo as following: To run a demo, press the `OK touch button`, after selecting the right demo color. -To run a different demo, turn the robot off and on again or reset the Arduino® Nano ESP32. +To run a different demo, press the `CANCEL touch button` and you will be redirected to the main menu. ### 1. Touch mode example (RED) This example starts with the red leds on. @@ -125,6 +125,7 @@ The leds will blink in red. To start the sequence, press the `OK touch button`. Pressing the `CANCEL touch button` at any time stops the robot and resets the sequence. +Pressing the `CANCEL touch button` two times during sequence programming you will be redirected to the main menu.
@@ -167,4 +168,4 @@ __WARNING: do not open bin files with Arduino Lab for Micropython 0.8.0 because ## Useful links - [Arduino_Alvik](https://github.com/arduino-libraries/Arduino_Alvik): Arduino library required to program Alvik - [Arduino_AlvikCarrier](https://github.com/arduino-libraries/Arduino_AlvikCarrier): Arduino library required to build the firmware -- [Arduino Alvik product page](https://store.arduino.cc/pages/alvik) \ No newline at end of file +- [Arduino Alvik product page](https://store.arduino.cc/pages/alvik) diff --git a/arduino_alvik/__init__.py b/arduino_alvik/__init__.py index 50fb7db..bb92f05 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.1.0" +__version__ = "1.1.4" __maintainer__ = "Lucio Rossi , Giovanni Bruno " -__required_firmware_version__ = "1.1.0" +__required_firmware_version__ = "1.1.1" from .arduino_alvik import * diff --git a/arduino_alvik/arduino_alvik.py b/arduino_alvik/arduino_alvik.py index d83305a..d1a5629 100644 --- a/arduino_alvik/arduino_alvik.py +++ b/arduino_alvik/arduino_alvik.py @@ -1,5 +1,3 @@ -import sys -import gc import struct from machine import I2C import _thread @@ -17,18 +15,79 @@ from .__init__ import __required_firmware_version__ +def writes_uart(method): + def wrapper(*args, **kwargs): + with ArduinoAlvik._write_lock: + return method(*args, **kwargs) + + return wrapper + + +def reads_uart(method): + def wrapper(*args, **kwargs): + with ArduinoAlvik._read_lock: + return method(*args, **kwargs) + + return wrapper + + +class _AlvikRLock: + def __init__(self): + """Alvik re-entrant Lock implementation""" + self._lock = _thread.allocate_lock() + self._owner = None + self._count = 0 + + def acquire(self): + tid = _thread.get_ident() + + if self._owner == tid: + self._count += 1 + return True + + self._lock.acquire() + self._owner = tid + self._count = 1 + return True + + def release(self): + tid = _thread.get_ident() + + if self._owner != tid: + raise RuntimeError("Cannot release an unowned lock") + + self._count -= 1 + if self._count == 0: + self._owner = None + self._lock.release() + + def locked(self): + return self._lock.locked() + + def __enter__(self): + self.acquire() + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.release() + + class ArduinoAlvik: _update_thread_running = False _update_thread_id = None _events_thread_running = False _events_thread_id = None + _write_lock = _AlvikRLock() + _read_lock = _AlvikRLock() + def __new__(cls): if not hasattr(cls, '_instance'): cls._instance = super(ArduinoAlvik, cls).__new__(cls) return cls._instance - def __init__(self): + def __init__(self, stack_size = THREAD_STACK_SIZE): + _thread.stack_size(stack_size) self.i2c = _ArduinoAlvikI2C(A4, A5) self._packeter = ucPack(200) self.left_wheel = _ArduinoAlvikWheel(self._packeter, ord('L'), alvik=self) @@ -84,6 +143,14 @@ def __init__(self): self._move_events = _ArduinoAlvikMoveEvents() self._timer_events = _ArduinoAlvikTimerEvents(-1) + def __del__(self): + """ + This method is a stub. __del__ is not implemented in MicroPython (https://docs.micropython.org/en/latest/genrst/core_language.html#special-method-del-not-implemented-for-user-defined-classes) + :return: + """ + ... + # self.__class__._instance = None + @staticmethod def is_on() -> bool: """ @@ -100,16 +167,20 @@ def _print_battery_status(percentage: float, is_charging) -> None: :param is_charging: True if the battery is charging :return: """ - sys.stdout.write(bytes('\r'.encode('utf-8'))) + print("\033[2K\033[1G", end='\r') if percentage > 97: marks_str = ' \U0001F50B' else: marks_str = ' \U0001FAAB' - 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')))) + if is_charging: + charging_str = ' \U0001F50C ' + else: + charging_str = ' \U000026A0 WARNING: battery is discharging!' + word = marks_str + f" {percentage}% {charging_str} \t" + print(word, end='') - def _lenghty_op(self, iterations=10000000) -> int: + @staticmethod + def _lengthy_op(self, iterations=10000000) -> int: result = 0 for i in range(1, iterations): result += i * i @@ -124,7 +195,7 @@ def _idle(self, delay_=1, check_on_thread=False, blocking=False) -> None: self.i2c.set_single_thread(True) if blocking: - self._lenghty_op(50000) + self._lengthy_op(50000) else: sleep_ms(500) led_val = 0 @@ -147,7 +218,7 @@ def _idle(self, delay_=1, check_on_thread=False, blocking=False) -> None: self._battery_perc = abs(soc_perc) self._print_battery_status(round(soc_perc), self._battery_is_charging) if blocking: - self._lenghty_op(10000) + self._lengthy_op(10000) else: sleep_ms(delay_) if soc_perc > 97: @@ -159,13 +230,16 @@ def _idle(self, delay_=1, check_on_thread=False, blocking=False) -> None: led_val = (led_val + 1) % 2 self.i2c.set_single_thread(False) if self.is_on(): - print("********** Alvik is on **********") - except KeyboardInterrupt: + print("\n********** Alvik is on **********") + except KeyboardInterrupt as e: self.stop() - sys.exit() + raise e + except OSError as e: + print(f'\nUnable to read SOC: {e}') + raise e except Exception as e: - pass - print(f'Unable to read SOC: {e}') + print(f'\nUnhandled exception: {e} {type(e)}') + raise e finally: LEDR.value(1) LEDG.value(1) @@ -187,18 +261,14 @@ def _snake_robot(duration: int = 1000): frame = '' for i in range(0, cycles): - sys.stdout.write(bytes('\r'.encode('utf-8'))) + print("\033[2K\033[1G", end='\r') pre = ' ' * i between = ' ' * (i % 2 + 1) post = ' ' * 5 frame = pre + snake + between + robot + post - sys.stdout.write(bytes(frame.encode('utf-8'))) + print(frame, end='') sleep_ms(200) - sys.stdout.write(bytes('\r'.encode('utf-8'))) - clear_frame = ' ' * len(frame) - sys.stdout.write(bytes(clear_frame.encode('utf-8'))) - def begin(self) -> int: """ Begins all Alvik operations @@ -218,15 +288,15 @@ 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 (required: '+'.'.join(map(str,self._required_fw_version))+')! Check documentation **********\n') - sys.exit(-2) + self.stop() + raise Exception('\n********** PLEASE UPDATE ALVIK FIRMWARE (required: '+'.'.join(map(str,self._required_fw_version))+')! Check documentation **********\n') 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') + print('\n********** Starting events thread **********\n') self._start_events_thread() self.set_servo_positions(90, 90) return 0 @@ -254,26 +324,32 @@ def _wait_for_ack(self) -> None: sleep_ms(20) self._waiting_ack = None - def _wait_for_fw_check(self) -> bool: + def _wait_for_fw_check(self, timeout=5) -> bool: """ Waits until receives version from robot, check required version and return true if everything is ok + :param timeout: wait for fw timeout in seconds :return: """ + start = ticks_ms() while self._fw_version == [None, None, None]: sleep_ms(20) + if ticks_diff(ticks_ms(), start) > timeout * 1000: + print("Could not get FW version") + return False + if self.check_firmware_compatibility(): return True else: return False @staticmethod + @reads_uart def _flush_uart(): """ Empties the UART buffer :return: """ - while uart.any(): - uart.read(1) + uart.read(uart.any()) def _begin_update_thread(self): """ @@ -302,6 +378,7 @@ def _wait_for_target(self, idle_time): # print(self._last_ack) sleep_ms(100) + @writes_uart def is_target_reached(self) -> bool: """ Returns True if robot has sent an M or R acknowledgment. @@ -319,6 +396,7 @@ def is_target_reached(self) -> bool: return True return False + @writes_uart def set_behaviour(self, behaviour: int): """ Sets the behaviour of Alvik @@ -328,6 +406,7 @@ def set_behaviour(self, behaviour: int): self._packeter.packetC1B(ord('B'), behaviour & 0xFF) uart.write(self._packeter.msg[0:self._packeter.msg_size]) + @writes_uart def rotate(self, angle: float, unit: str = 'deg', blocking: bool = True): """ Rotates the robot by given angle @@ -344,6 +423,7 @@ def rotate(self, angle: float, unit: str = 'deg', blocking: bool = True): if blocking: self._wait_for_target(idle_time=(angle / MOTOR_CONTROL_DEG_S)) + @writes_uart def move(self, distance: float, unit: str = 'cm', blocking: bool = True): """ Moves the robot by given distance @@ -377,10 +457,6 @@ def stop(self): # stop touch events thread self._stop_events_thread() - # delete _instance - del self.__class__._instance - gc.collect() - @staticmethod def _reset_hw(): """ @@ -401,6 +477,7 @@ def get_wheels_speed(self, unit: str = 'rpm') -> (float | None, float | None): """ return self.left_wheel.get_speed(unit), self.right_wheel.get_speed(unit) + @writes_uart def set_wheels_speed(self, left_speed: float, right_speed: float, unit: str = 'rpm'): """ Sets left/right motor speed @@ -420,12 +497,13 @@ 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]) + @writes_uart 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 unit: the speed unit of measurement (default: 'deg') :param blocking: :return: """ @@ -483,6 +561,7 @@ def get_line_sensors(self) -> (int | None, int | None, int | None): return self._left_line, self._center_line, self._right_line + @writes_uart def drive(self, linear_velocity: float, angular_velocity: float, linear_unit: str = 'cm/s', angular_unit: str = 'deg/s'): """ @@ -523,6 +602,7 @@ def get_drive_speed(self, linear_unit: str = 'cm/s', angular_unit: str = 'deg/s' return convert_speed(self._linear_velocity, 'mm/s', linear_unit), angular_velocity + @writes_uart def reset_pose(self, x: float, y: float, theta: float, distance_unit: str = 'cm', angle_unit: str = 'deg'): """ Resets the robot pose @@ -552,6 +632,7 @@ def get_pose(self, distance_unit: str = 'cm', angle_unit: str = 'deg') \ convert_distance(self._y, 'mm', distance_unit), convert_angle(self._theta, 'deg', angle_unit)) + @writes_uart def set_servo_positions(self, a_position: int, b_position: int): """ Sets A/B servomotor angle @@ -579,10 +660,16 @@ def get_ack(self) -> str: """ return self._last_ack - # def send_ack(self): - # self._packeter.packetC1B(ord('X'), ACK_) - # uart.write(self._packeter.msg[0:self._packeter.msg_size]) + @writes_uart + def send_ack(self, ack: str = 'K'): + """ + Sends an ack message on UART + :return: + """ + self._packeter.packetC1B(ord('X'), ord(ack)) + uart.write(self._packeter.msg[0:self._packeter.msg_size]) + @writes_uart def _set_leds(self, led_state: int): """ Sets the LEDs state @@ -641,21 +728,23 @@ def _update(self, delay_=1): self.set_behaviour(2) if not ArduinoAlvik._update_thread_running: break - if self._read_message(): - self._parse_message() + self._read_message() sleep_ms(delay_) - def _read_message(self) -> bool: + @reads_uart + def _read_message(self) -> None: """ Read a message from the uC :return: True if a message terminator was reached """ - while uart.any(): - b = uart.read(1)[0] - self._packeter.buffer.push(b) - if b == self._packeter.end_index and self._packeter.checkPayload(): - return True - return False + buf = bytearray(uart.any()) + uart.readinto(buf) + if len(buf): + uart.readinto(buf) + for b in buf: + self._packeter.buffer.push(b) + if b == self._packeter.end_index and self._packeter.checkPayload(): + self._parse_message() def _parse_message(self) -> int: """ @@ -820,6 +909,13 @@ def get_shake(self) -> bool: """ return bool(self._move_bits & 0b00000001) + def get_lifted(self) -> bool: + """ + Returns true if Alvik is lifted + :return: + """ + return bool(self._move_bits & 0b00000010) + def get_tilt(self) -> str: """ Returns the tilt string eg: "X", "-Z" etc @@ -1251,6 +1347,24 @@ def on_shake(self, callback: callable, args: tuple = ()) -> None: """ self._move_events.register_callback('on_shake', callback, args) + def on_lift(self, callback: callable, args: tuple = ()) -> None: + """ + Register callback when Alvik is lifted + :param callback: + :param args: + :return: + """ + self._move_events.register_callback('on_lift', callback, args) + + def on_drop(self, callback: callable, args: tuple = ()) -> None: + """ + Register callback when Alvik is dropped + :param callback: + :param args: + :return: + """ + self._move_events.register_callback('on_drop', callback, args) + def on_x_tilt(self, callback: callable, args: tuple = ()) -> None: """ Register callback when Alvik is tilted on X-axis @@ -1513,7 +1627,6 @@ def writeto_mem(self, addr, memaddr, buf, addrsize=8) -> None: return i2c.writeto_mem(addr, memaddr, buf, addrsize=addrsize) - class _ArduinoAlvikServo: def __init__(self, packeter: ucPack, label: str, servo_id: int, position: list[int | None]): @@ -1521,7 +1634,8 @@ def __init__(self, packeter: ucPack, label: str, servo_id: int, position: list[i self._label = label self._id = servo_id self._position = position - + + @writes_uart def set_position(self, position): """ Sets the position of the servo @@ -1550,7 +1664,8 @@ def __init__(self, packeter: ucPack, label: int, wheel_diameter_mm: float = WHEE self._speed = None self._position = None self._alvik = alvik - + + @writes_uart def reset(self, initial_position: float = 0.0, unit: str = 'deg'): """ Resets the wheel reference position @@ -1562,6 +1677,7 @@ def reset(self, initial_position: float = 0.0, unit: str = 'deg'): self._packeter.packetC2B1F(ord('W'), self._label & 0xFF, ord('Z'), initial_position) uart.write(self._packeter.msg[0:self._packeter.msg_size]) + @writes_uart def set_pid_gains(self, kp: float = MOTOR_KP_DEFAULT, ki: float = MOTOR_KI_DEFAULT, kd: float = MOTOR_KD_DEFAULT): """ Set PID gains for Alvik wheels @@ -1581,6 +1697,7 @@ def stop(self): """ self.set_speed(0) + @writes_uart def set_speed(self, velocity: float, unit: str = 'rpm'): """ Sets the motor speed @@ -1617,6 +1734,7 @@ def get_position(self, unit: str = 'deg') -> float | None: """ return convert_angle(self._position, 'deg', unit) + @writes_uart def set_position(self, position: float, unit: str = 'deg', blocking: bool = True): """ Sets left/right motor speed @@ -1647,6 +1765,7 @@ def __init__(self, packeter: ucPack, label: str, led_state: list[int | None], rg self._rgb_mask = rgb_mask self._led_state = led_state + @writes_uart def set_color(self, red: bool, green: bool, blue: bool): """ Sets the LED's r,g,b state @@ -1957,7 +2076,7 @@ class _ArduinoAlvikMoveEvents(_ArduinoAlvikEvents): Event class to handle move events """ - available_events = ['on_shake', 'on_x_tilt', 'on_y_tilt', 'on_z_tilt', + available_events = ['on_shake', 'on_lift', 'on_drop', 'on_x_tilt', 'on_y_tilt', 'on_z_tilt', 'on_nx_tilt', 'on_ny_tilt', 'on_nz_tilt'] NZ_TILT = 0x80 @@ -1984,6 +2103,26 @@ def _is_shaken(current_state, new_state) -> bool: """ return not bool(current_state & 0b00000001) and bool(new_state & 0b00000001) + @staticmethod + def _is_lifted(current_state, new_state) -> bool: + """ + True if Alvik was lifted + :param current_state: + :param new_state: + :return: + """ + return not bool(current_state & 0b00000010) and bool(new_state & 0b00000010) + + @staticmethod + def _is_dropped(current_state, new_state) -> bool: + """ + True if Alvik was dropped + :param current_state: + :param new_state: + :return: + """ + return bool(current_state & 0b00000010) and not bool(new_state & 0b00000010) + @staticmethod def _is_x_tilted(current_state, new_state) -> bool: """ @@ -2057,6 +2196,12 @@ def update_state(self, state: int | None): if self._is_shaken(self._current_state, state): self.execute_callback('on_shake') + if self._is_lifted(self._current_state, state): + self.execute_callback('on_lift') + + if self._is_dropped(self._current_state, state): + self.execute_callback('on_drop') + if self._is_x_tilted(self._current_state, state): self.execute_callback('on_x_tilt') @@ -2096,6 +2241,19 @@ def update_firmware(file_path: str): STM32_eraseMEM, STM32_writeMEM, ) + def flash_toggle(): + i = 0 + + while True: + if i == 0: + LEDR.value(1) + LEDG.value(0) + else: + LEDR.value(0) + LEDG.value(1) + i = (i + 1) % 2 + yield + if CHECK_STM32.value() is not 1: print("Turn on your Alvik to continue...") while CHECK_STM32.value() is not 1: @@ -2112,8 +2270,13 @@ def update_firmware(file_path: str): STM32_eraseMEM(0xFFFF) print("\nWRITING MEM") - STM32_writeMEM(file_path) + toggle = flash_toggle() + STM32_writeMEM(file_path, toggle) + print("\nDONE") print("\nLower Boot0 and reset STM32") + LEDR.value(1) + LEDG.value(1) + STM32_endCommunication() diff --git a/arduino_alvik/robot_definitions.py b/arduino_alvik/robot_definitions.py index 26a2e51..c0a0864 100644 --- a/arduino_alvik/robot_definitions.py +++ b/arduino_alvik/robot_definitions.py @@ -12,3 +12,6 @@ # Robot params ROBOT_MAX_DEG_S = 6*(2*MOTOR_MAX_RPM*WHEEL_DIAMETER_MM)/WHEEL_TRACK_MM + +# Thread stack size +THREAD_STACK_SIZE = 8*1024 diff --git a/arduino_alvik/stm32_flash.py b/arduino_alvik/stm32_flash.py index 89522c6..83b3ff2 100644 --- a/arduino_alvik/stm32_flash.py +++ b/arduino_alvik/stm32_flash.py @@ -1,5 +1,4 @@ import os -import sys from time import sleep_ms from machine import UART, Pin @@ -296,7 +295,7 @@ def STM32_readMEM(pages: int): _incrementAddress(readAddress) -def STM32_writeMEM(file_path: str): +def STM32_writeMEM(file_path: str, toggle: "Generator" = None): with open(file_path, 'rb') as f: print(f"Flashing {file_path}\n") @@ -322,10 +321,13 @@ def STM32_writeMEM(file_path: str): print(f"STM32 ERROR FLASHING PAGE: {writeAddress}") return - sys.stdout.write('\r') - sys.stdout.write(f"{int((i/file_pages)*100)}%") + percentage = int((i / file_pages) * 100) + print("\033[2K\033[1G", end='\r') + print(f"Flashing STM32: {percentage:>3}%", end='') i = i + 1 _incrementAddress(writeAddress) + if toggle is not None: + next(toggle) def _STM32_standardEraseMEM(pages: int, page_list: bytearray = None): diff --git a/examples/actuators/leds_setting.py b/examples/actuators/leds_setting.py index cceb6c4..3ea1020 100644 --- a/examples/actuators/leds_setting.py +++ b/examples/actuators/leds_setting.py @@ -1,6 +1,6 @@ from arduino_alvik import ArduinoAlvik from time import sleep_ms -import sys + alvik = ArduinoAlvik() alvik.begin() @@ -34,4 +34,4 @@ except KeyboardInterrupt as e: print('over') alvik.stop() - sys.exit() + break diff --git a/examples/actuators/move_wheels.py b/examples/actuators/move_wheels.py index d6f6e7e..94537a3 100644 --- a/examples/actuators/move_wheels.py +++ b/examples/actuators/move_wheels.py @@ -1,6 +1,6 @@ from arduino_alvik import ArduinoAlvik from time import sleep_ms -import sys + alvik = ArduinoAlvik() alvik.begin() @@ -33,4 +33,4 @@ except KeyboardInterrupt as e: print('over') alvik.stop() - sys.exit() + break diff --git a/examples/actuators/pose_example.py b/examples/actuators/pose_example.py index 11b675a..465a635 100644 --- a/examples/actuators/pose_example.py +++ b/examples/actuators/pose_example.py @@ -1,82 +1,80 @@ from arduino_alvik import ArduinoAlvik from time import sleep_ms -import sys + alvik = ArduinoAlvik() alvik.begin() -while True: - try: +try: + + alvik.move(100.0, 'mm') + print("on target after move") + + alvik.move(50.0, 'mm') + print("on target after move") + + alvik.rotate(90.0, 'deg') + print("on target after rotation") - alvik.move(100.0, 'mm') - print("on target after move") + alvik.rotate(-45.00, 'deg') + print("on target after rotation") - alvik.move(50.0, 'mm') - print("on target after move") + x, y, theta = alvik.get_pose() + print(f'Current pose is x(cm)={x}, y(cm)={y}, theta(deg)={theta}') - alvik.rotate(90.0, 'deg') - print("on target after rotation") + alvik.reset_pose(0, 0, 0) - alvik.rotate(-45.00, 'deg') - print("on target after rotation") + x, y, theta = alvik.get_pose() + print(f'Updated pose is x(cm)={x}, y(cm)={y}, theta(deg)={theta}') + sleep_ms(500) - x, y, theta = alvik.get_pose() - print(f'Current pose is x(cm)={x}, y(cm)={y}, theta(deg)={theta}') + print("___________NON-BLOCKING__________________") - alvik.reset_pose(0, 0, 0) + alvik.move(50.0, 'mm', blocking=False) - x, y, theta = alvik.get_pose() - print(f'Updated pose is x(cm)={x}, y(cm)={y}, theta(deg)={theta}') + 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) + 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") - print("___________NON-BLOCKING__________________") - - alvik.move(50.0, 'mm', 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("on target after move") - - alvik.rotate(45.0, 'deg', 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("on target after rotation") - - alvik.move(100.0, 'mm', 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("on target after move") - - alvik.rotate(-90.00, 'deg', 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("on target after rotation") - - x, y, theta = alvik.get_pose() - print(f'Current pose is x(cm)={x}, y(cm)={y}, theta(deg)={theta}') - - alvik.reset_pose(0, 0, 0) - - x, y, theta = alvik.get_pose() - print(f'Updated pose is x={x}, y={y}, theta(deg)={theta}') + alvik.move(100.0, 'mm', 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("on target after move") + + alvik.rotate(-90.00, 'deg', 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("on target after rotation") + + x, y, theta = alvik.get_pose() + print(f'Current pose is x(cm)={x}, y(cm)={y}, theta(deg)={theta}') + + alvik.reset_pose(0, 0, 0) + + x, y, theta = alvik.get_pose() + print(f'Updated pose is x={x}, y={y}, theta(deg)={theta}') + sleep_ms(500) - alvik.stop() - sys.exit() +except KeyboardInterrupt as e: + print('Test interrupted') - except KeyboardInterrupt as e: - print('over') - alvik.stop() - sys.exit() +finally: + alvik.stop() + print("END of pose example") \ No newline at end of file diff --git a/examples/actuators/set_servo.py b/examples/actuators/set_servo.py index b4e9084..48720c1 100644 --- a/examples/actuators/set_servo.py +++ b/examples/actuators/set_servo.py @@ -1,6 +1,6 @@ from arduino_alvik import ArduinoAlvik from time import sleep_ms -import sys + alvik = ArduinoAlvik() alvik.begin() @@ -19,4 +19,4 @@ except KeyboardInterrupt as e: print('over') alvik.stop() - sys.exit() + break diff --git a/examples/actuators/wheels_position.py b/examples/actuators/wheels_position.py index 6f3a151..fc521c6 100644 --- a/examples/actuators/wheels_position.py +++ b/examples/actuators/wheels_position.py @@ -1,6 +1,6 @@ from arduino_alvik import ArduinoAlvik from time import sleep, sleep_ms -import sys + alvik = ArduinoAlvik() alvik.begin() @@ -62,4 +62,4 @@ except KeyboardInterrupt as e: print('over') alvik.stop() - sys.exit() + break diff --git a/examples/actuators/wheels_speed.py b/examples/actuators/wheels_speed.py index 1919f27..3a54340 100644 --- a/examples/actuators/wheels_speed.py +++ b/examples/actuators/wheels_speed.py @@ -1,6 +1,6 @@ from arduino_alvik import ArduinoAlvik from time import sleep_ms -import sys + alvik = ArduinoAlvik() alvik.begin() @@ -21,4 +21,4 @@ except KeyboardInterrupt as e: print('over') alvik.stop() - sys.exit() + break diff --git a/examples/arduino-runtime/blink.py b/examples/arduino-runtime/blink.py new file mode 100644 index 0000000..920838f --- /dev/null +++ b/examples/arduino-runtime/blink.py @@ -0,0 +1,28 @@ +from time import sleep_ms + +from arduino import start +from arduino_alvik import ArduinoAlvik + + +alvik = ArduinoAlvik() + + +def setup(): + alvik.begin() + + +def loop(): + print('blinking LEDs') + alvik.left_led.set_color(0, 0, 1) + alvik.right_led.set_color(0, 0, 1) + sleep_ms(500) + alvik.left_led.set_color(1, 0, 0) + alvik.right_led.set_color(1, 0, 0) + sleep_ms(500) + + +def cleanup(): + alvik.stop() + + +start(setup=setup, loop=loop, cleanup=cleanup) diff --git a/examples/arduino-runtime/line_follower.py b/examples/arduino-runtime/line_follower.py new file mode 100644 index 0000000..cf6c861 --- /dev/null +++ b/examples/arduino-runtime/line_follower.py @@ -0,0 +1,64 @@ +from time import sleep_ms + +from arduino import start +from arduino_alvik import ArduinoAlvik + + +alvik = ArduinoAlvik() + + +def calculate_center(left: int, center: int, right: int): + centroid = 0 + sum_weight = left + center + right + sum_values = left + 2 * center + 3 * right + if sum_weight != 0: + centroid = sum_values / sum_weight + centroid = 2 - centroid + return centroid + + +def run_line_follower(alvik): + + kp = 50.0 + line_sensors = alvik.get_line_sensors() + print(f' {line_sensors}') + + error = calculate_center(*line_sensors) + control = error * kp + + if control > 0.2: + alvik.left_led.set_color(1, 0, 0) + alvik.right_led.set_color(0, 0, 0) + elif control < -0.2: + alvik.left_led.set_color(1, 0, 0) + alvik.right_led.set_color(0, 0, 0) + else: + alvik.left_led.set_color(0, 1, 0) + alvik.right_led.set_color(0, 1, 0) + + alvik.set_wheels_speed(30 - control, 30 + control) + sleep_ms(100) + + +def setup(): + alvik.begin() + alvik.left_led.set_color(0, 0, 1) + alvik.right_led.set_color(0, 0, 1) + + +def loop(): + while not alvik.get_touch_ok(): + alvik.left_led.set_color(0, 0, 1) + alvik.right_led.set_color(0, 0, 1) + alvik.brake() + sleep_ms(100) + + while not alvik.get_touch_cancel(): + run_line_follower(alvik) + + +def cleanup(): + alvik.stop() + + +start(setup=setup, loop=loop, cleanup=cleanup) diff --git a/examples/arduino-runtime/read_tof.py b/examples/arduino-runtime/read_tof.py new file mode 100644 index 0000000..63fb76d --- /dev/null +++ b/examples/arduino-runtime/read_tof.py @@ -0,0 +1,26 @@ +from time import sleep_ms + +from arduino import start +from arduino_alvik import ArduinoAlvik + + +alvik = ArduinoAlvik() + + +def setup(): + alvik.begin() + + +def loop(): + L, CL, C, CR, R = alvik.get_distance() + T = alvik.get_distance_top() + B = alvik.get_distance_bottom() + print(f'T: {T} | B: {B} | L: {L} | CL: {CL} | C: {C} | CR: {CR} | R: {R}') + sleep_ms(100) + + +def cleanup(): + alvik.stop() + + +start(setup=setup, loop=loop, cleanup=cleanup) diff --git a/examples/communication/i2c_scan.py b/examples/communication/i2c_scan.py index a246787..6f1ed45 100644 --- a/examples/communication/i2c_scan.py +++ b/examples/communication/i2c_scan.py @@ -1,5 +1,5 @@ from time import sleep_ms -import sys + from arduino_alvik import ArduinoAlvik @@ -22,4 +22,4 @@ sleep_ms(100) except KeyboardInterrupt as e: alvik.stop() - sys.exit() \ No newline at end of file + break \ No newline at end of file diff --git a/examples/communication/modulino.py b/examples/communication/modulino.py index bf1e8e2..e5950d7 100644 --- a/examples/communication/modulino.py +++ b/examples/communication/modulino.py @@ -1,11 +1,12 @@ 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) + print("\nImportError: ModulinoPixels not installed") + raise e alvik = ArduinoAlvik() alvik.begin() @@ -13,8 +14,7 @@ pixels = ModulinoPixels(alvik.i2c) if not pixels.connected: - print("🤷 No pixel modulino found") - sys.exit(-2) + raise Exception("🤷 No pixel modulino found") while True: try: @@ -32,4 +32,4 @@ except KeyboardInterrupt as e: alvik.stop() - sys.exit() + break diff --git a/examples/demo/demo.py b/examples/demo/demo.py index 931aa47..f1b283d 100644 --- a/examples/demo/demo.py +++ b/examples/demo/demo.py @@ -1,6 +1,10 @@ from arduino_alvik import ArduinoAlvik from time import sleep_ms -import sys + +from line_follower import run_line_follower +from touch_move import run_touch_move +from hand_follower import run_hand_follower + alvik = ArduinoAlvik() alvik.begin() @@ -27,12 +31,21 @@ def update_led_status(val): try: if alvik.get_touch_ok(): - if menu_status == 0: - import line_follower - elif menu_status == 1: - import hand_follower - elif menu_status == -1: - import touch_move + alvik.left_led.set_color(0, 0, 0) + alvik.right_led.set_color(0, 0, 0) + sleep_ms(500) + while not alvik.get_touch_cancel(): + if menu_status == 0: + run_line_follower(alvik) + elif menu_status == 1: + run_hand_follower(alvik) + elif menu_status == -1: + if run_touch_move(alvik) < 0: + break + alvik.left_led.set_color(0, 0, 0) + alvik.right_led.set_color(0, 0, 0) + sleep_ms(500) + alvik.brake() if alvik.get_touch_up() and menu_status < 1: menu_status += 1 @@ -50,4 +63,4 @@ def update_led_status(val): except KeyboardInterrupt as e: print('over') alvik.stop() - sys.exit() + break diff --git a/examples/demo/hand_follower.py b/examples/demo/hand_follower.py index fcdc41e..1b784b5 100644 --- a/examples/demo/hand_follower.py +++ b/examples/demo/hand_follower.py @@ -1,38 +1,43 @@ from arduino_alvik import ArduinoAlvik from time import sleep_ms -import sys -alvik = ArduinoAlvik() -alvik.begin() -reference = 10.0 +def run_hand_follower(alvik): + reference = 10.0 + alvik.left_led.set_color(0, 0, 0) + alvik.right_led.set_color(0, 0, 0) + L, CL, C, CR, R = alvik.get_distance() + print(f'C: {C}') + error = C - reference + alvik.set_wheels_speed(error * 10, error * 10) + sleep_ms(100) -alvik.left_led.set_color(0, 1, 0) -alvik.right_led.set_color(0, 1, 0) -while alvik.get_touch_ok(): - sleep_ms(50) +if __name__ == "__main__": -while not alvik.get_touch_ok(): - sleep_ms(50) + alvik = ArduinoAlvik() + alvik.begin() + + alvik.left_led.set_color(0, 1, 0) + alvik.right_led.set_color(0, 1, 0) + + while alvik.get_touch_ok(): + sleep_ms(50) + + while not alvik.get_touch_ok(): + sleep_ms(50) -try: while True: - while not alvik.get_touch_cancel(): - alvik.left_led.set_color(0, 0, 0) - alvik.right_led.set_color(0, 0, 0) - L, CL, C, CR, R = alvik.get_distance() - print(f'C: {C}') - error = C - reference - alvik.set_wheels_speed(error*10, error*10) - sleep_ms(100) - - while not alvik.get_touch_ok(): - alvik.left_led.set_color(0, 1, 0) - alvik.right_led.set_color(0, 1, 0) - alvik.brake() - sleep_ms(100) -except KeyboardInterrupt as e: - print('over') - alvik.stop() - sys.exit() + try: + while not alvik.get_touch_cancel(): + run_hand_follower(alvik) + + while not alvik.get_touch_ok(): + alvik.left_led.set_color(0, 1, 0) + alvik.right_led.set_color(0, 1, 0) + alvik.brake() + sleep_ms(100) + except KeyboardInterrupt as e: + print('over') + alvik.stop() + break diff --git a/examples/demo/line_follower.py b/examples/demo/line_follower.py index 041faf6..c61f3c4 100644 --- a/examples/demo/line_follower.py +++ b/examples/demo/line_follower.py @@ -1,6 +1,5 @@ from arduino_alvik import ArduinoAlvik from time import sleep_ms -import sys def calculate_center(left: int, center: int, right: int): @@ -13,52 +12,54 @@ def calculate_center(left: int, center: int, right: int): return centroid -alvik = ArduinoAlvik() -alvik.begin() +def run_line_follower(alvik): + kp = 50.0 + line_sensors = alvik.get_line_sensors() + print(f' {line_sensors}') -error = 0 -control = 0 -kp = 50.0 + error = calculate_center(*line_sensors) + control = error * kp -alvik.left_led.set_color(0, 0, 1) -alvik.right_led.set_color(0, 0, 1) + if control > 0.2: + alvik.left_led.set_color(1, 0, 0) + alvik.right_led.set_color(0, 0, 0) + elif control < -0.2: + alvik.left_led.set_color(1, 0, 0) + alvik.right_led.set_color(0, 0, 0) + else: + alvik.left_led.set_color(0, 1, 0) + alvik.right_led.set_color(0, 1, 0) -while alvik.get_touch_ok(): - sleep_ms(50) + alvik.set_wheels_speed(30 - control, 30 + control) + sleep_ms(100) -while not alvik.get_touch_ok(): - sleep_ms(50) -try: +if __name__ == "__main__": + + alvik = ArduinoAlvik() + alvik.begin() + + alvik.left_led.set_color(0, 0, 1) + alvik.right_led.set_color(0, 0, 1) + + while alvik.get_touch_ok(): + sleep_ms(50) + + while not alvik.get_touch_ok(): + sleep_ms(50) + while True: - while not alvik.get_touch_cancel(): - - line_sensors = alvik.get_line_sensors() - print(f' {line_sensors}') - - error = calculate_center(*line_sensors) - control = error * kp - - if control > 0.2: - alvik.left_led.set_color(1, 0, 0) - alvik.right_led.set_color(0, 0, 0) - elif control < -0.2: - alvik.left_led.set_color(1, 0, 0) - alvik.right_led.set_color(0, 0, 0) - else: - alvik.left_led.set_color(0, 1, 0) - alvik.right_led.set_color(0, 1, 0) - - alvik.set_wheels_speed(30 - control, 30 + control) - sleep_ms(100) - - while not alvik.get_touch_ok(): - alvik.left_led.set_color(0, 0, 1) - alvik.right_led.set_color(0, 0, 1) - alvik.brake() - sleep_ms(100) - -except KeyboardInterrupt as e: - print('over') - alvik.stop() - sys.exit() + try: + while not alvik.get_touch_cancel(): + run_line_follower(alvik) + + while not alvik.get_touch_ok(): + alvik.left_led.set_color(0, 0, 1) + alvik.right_led.set_color(0, 0, 1) + alvik.brake() + sleep_ms(100) + + except KeyboardInterrupt as e: + print('over') + alvik.stop() + break diff --git a/examples/demo/touch_move.py b/examples/demo/touch_move.py index b51e4ca..728cc03 100644 --- a/examples/demo/touch_move.py +++ b/examples/demo/touch_move.py @@ -1,17 +1,8 @@ from arduino_alvik import ArduinoAlvik from time import sleep_ms -import sys -alvik = ArduinoAlvik() -alvik.begin() -alvik.left_led.set_color(1, 0, 0) -alvik.right_led.set_color(1, 0, 0) - -movements = [] - - -def blink(): +def blink(alvik): alvik.left_led.set_color(1, 0, 1) alvik.right_led.set_color(1, 0, 1) sleep_ms(200) @@ -19,27 +10,25 @@ def blink(): alvik.right_led.set_color(1, 0, 0) -def add_movement(): - global movements - +def add_movement(alvik, movements): if alvik.get_touch_up(): movements.append('forward') - blink() + blink(alvik) while alvik.get_touch_up(): sleep_ms(100) if alvik.get_touch_down(): movements.append('backward') - blink() + blink(alvik) while alvik.get_touch_down(): sleep_ms(100) if alvik.get_touch_left(): movements.append('left') - blink() + blink(alvik) while alvik.get_touch_left(): sleep_ms(100) if alvik.get_touch_right(): movements.append('right') - blink() + blink(alvik) while alvik.get_touch_right(): sleep_ms(100) if alvik.get_touch_cancel(): @@ -53,7 +42,7 @@ def add_movement(): sleep_ms(100) -def run_movement(movement): +def run_movement(alvik, movement): if movement == 'forward': alvik.move(10, blocking=False) if movement == 'backward': @@ -70,33 +59,45 @@ def run_movement(movement): alvik.right_led.set_color(0, 0, 0) sleep_ms(100) -while alvik.get_touch_ok(): - sleep_ms(50) -while not (alvik.get_touch_ok() and len(movements) != 0): - add_movement() - sleep_ms(50) +def run_touch_move(alvik) -> int: + movements = [] + while not (alvik.get_touch_ok() and len(movements) != 0): + if alvik.get_touch_cancel(): + if len(movements) == 0: + return -1 + movements.clear() + blink(alvik) + alvik.left_led.set_color(1, 0, 0) + alvik.right_led.set_color(1, 0, 0) + alvik.brake() + add_movement(alvik, movements) + sleep_ms(100) -try: - while True: - alvik.left_led.set_color(0, 0, 0) - alvik.right_led.set_color(0, 0, 0) - for move in movements: - run_movement(move) - if alvik.get_touch_cancel(): - break + alvik.left_led.set_color(0, 0, 0) + alvik.right_led.set_color(0, 0, 0) + for move in movements: + run_movement(alvik, move) + if alvik.get_touch_cancel(): + movements.clear() + blink(alvik) + sleep_ms(100) + return 1 - movements = [] - while not (alvik.get_touch_ok() and len(movements) != 0): - alvik.left_led.set_color(1, 0, 0) - alvik.right_led.set_color(1, 0, 0) - alvik.brake() - add_movement() - sleep_ms(100) -except KeyboardInterrupt as e: - print('over') - alvik.stop() - sys.exit() +if __name__ == "__main__": + alvik = ArduinoAlvik() + alvik.begin() + + alvik.left_led.set_color(1, 0, 0) + alvik.right_led.set_color(1, 0, 0) + + while True: + try: + run_touch_move(alvik) + except KeyboardInterrupt as e: + print('over') + alvik.stop() + break diff --git a/examples/events/hot_wheels.py b/examples/events/hot_wheels.py new file mode 100644 index 0000000..7ce9894 --- /dev/null +++ b/examples/events/hot_wheels.py @@ -0,0 +1,44 @@ +from arduino_alvik import ArduinoAlvik +from time import sleep_ms + + +def stop_when_up(alvik): + print("lift") + alvik.set_wheels_speed(0, 0) + + +def run_when_down(alvik): + print("drop") + alvik.set_wheels_speed(20, 20) + + +alvik = ArduinoAlvik() +alvik.on_lift(stop_when_up, (alvik,)) +alvik.on_drop(run_when_down, (alvik,)) +alvik.begin() +color_val = 0 + + +def blinking_leds(val): + alvik.left_led.set_color(val & 0x01, val & 0x02, val & 0x04) + alvik.right_led.set_color(val & 0x02, val & 0x04, val & 0x01) + + +while not alvik.get_touch_ok(): + sleep_ms(100) + +alvik.set_wheels_speed(20, 20) + +while not alvik.get_touch_cancel(): + + try: + blinking_leds(color_val) + color_val = (color_val + 1) % 7 + sleep_ms(500) + + except KeyboardInterrupt as e: + print('over') + alvik.stop() + break + +alvik.stop() diff --git a/examples/events/motion_events.py b/examples/events/motion_events.py index f7edf01..f8ea953 100644 --- a/examples/events/motion_events.py +++ b/examples/events/motion_events.py @@ -1,6 +1,5 @@ from arduino_alvik import ArduinoAlvik from time import sleep -import sys def toggle_value(): @@ -32,6 +31,8 @@ def simple_print(custom_text: str = '') -> None: alvik = ArduinoAlvik() alvik.on_shake(toggle_left_led, ("ALVIK WAS SHAKEN... YOU MAKE ME SHIVER :)", toggle_value(), )) +alvik.on_lift(simple_print, ("ALVIK WAS LIFTED",)) +alvik.on_drop(simple_print, ("ALVIK WAS DROPPED",)) 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",)) @@ -49,4 +50,4 @@ def simple_print(custom_text: str = '') -> None: except KeyboardInterrupt as e: print('over') alvik.stop() - sys.exit() + break diff --git a/examples/events/timer_one_shot_events.py b/examples/events/timer_one_shot_events.py index 8ab8a99..487c4fb 100644 --- a/examples/events/timer_one_shot_events.py +++ b/examples/events/timer_one_shot_events.py @@ -1,17 +1,5 @@ from arduino_alvik import ArduinoAlvik from time import sleep -import sys - - -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: @@ -21,13 +9,12 @@ def toggle_left_led(custom_text: str, val) -> None: :param val: a toggle signal generator :return: """ - 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.left_led.set_color(val, 0, 0) + print(f"LEFT LED -> RED {'ON' if val else 'OFF'}! {custom_text}") alvik = ArduinoAlvik() -alvik.set_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", 1, )) alvik.begin() @@ -68,4 +55,4 @@ def toggle_left_led(custom_text: str, val) -> None: except KeyboardInterrupt as e: print('over') alvik.stop() - sys.exit() + break \ No newline at end of file diff --git a/examples/events/timer_periodic_events.py b/examples/events/timer_periodic_events.py index fd5aa28..d56e90c 100644 --- a/examples/events/timer_periodic_events.py +++ b/examples/events/timer_periodic_events.py @@ -1,6 +1,5 @@ from arduino_alvik import ArduinoAlvik from time import sleep -import sys def toggle_value(): @@ -67,4 +66,4 @@ def toggle_left_led(custom_text: str, val) -> None: except KeyboardInterrupt as e: print('over') alvik.stop() - sys.exit() + break diff --git a/examples/events/touch_events.py b/examples/events/touch_events.py index 9ef35e3..db0d6c1 100644 --- a/examples/events/touch_events.py +++ b/examples/events/touch_events.py @@ -1,6 +1,5 @@ from arduino_alvik import ArduinoAlvik from time import sleep -import sys def toggle_value(): @@ -67,4 +66,4 @@ def simple_print(custom_text: str = '') -> None: except KeyboardInterrupt as e: print('over') alvik.stop() - sys.exit() + break diff --git a/examples/flash_firmware.py b/examples/flash_firmware.py index a3327da..b98fba8 100644 --- a/examples/flash_firmware.py +++ b/examples/flash_firmware.py @@ -1,4 +1,18 @@ -# from machine import reset +import sys + + +def reload_modules(): + to_be_reloaded = [] + + for m in sys.modules: + to_be_reloaded.append(m) + del sys.modules[m] + + for m in to_be_reloaded: + exec(f'import {m}') + + +reload_modules() from arduino_alvik import update_firmware # this is a patch to fix possible running threads on Alvik @@ -6,5 +20,4 @@ alvik = ArduinoAlvik() alvik.stop() -update_firmware('./firmware.bin') -# reset() \ No newline at end of file +update_firmware('/firmware.bin') diff --git a/examples/reload_modules.py b/examples/reload_modules.py new file mode 100644 index 0000000..bd5108a --- /dev/null +++ b/examples/reload_modules.py @@ -0,0 +1,14 @@ +import sys + +def reload_modules(): + to_be_reloaded = [] + + for m in sys.modules: + to_be_reloaded.append(m) + del sys.modules[m] + + for m in to_be_reloaded: + exec(f'import {m}') + + +reload_modules() \ No newline at end of file diff --git a/examples/sensors/read_color_sensor.py b/examples/sensors/read_color_sensor.py index 462826c..0c92871 100644 --- a/examples/sensors/read_color_sensor.py +++ b/examples/sensors/read_color_sensor.py @@ -1,6 +1,6 @@ from arduino_alvik import ArduinoAlvik from time import sleep_ms -import sys + alvik = ArduinoAlvik() alvik.begin() @@ -15,4 +15,4 @@ except KeyboardInterrupt as e: print('over') alvik.stop() - sys.exit() + break diff --git a/examples/sensors/read_imu.py b/examples/sensors/read_imu.py index 3c6589b..7c0d984 100644 --- a/examples/sensors/read_imu.py +++ b/examples/sensors/read_imu.py @@ -1,6 +1,6 @@ from arduino_alvik import ArduinoAlvik from time import sleep_ms -import sys + alvik = ArduinoAlvik() alvik.begin() @@ -14,4 +14,4 @@ except KeyboardInterrupt as e: print('over') alvik.stop() - sys.exit() + break diff --git a/examples/sensors/read_orientation.py b/examples/sensors/read_orientation.py index 23cf006..33b0113 100644 --- a/examples/sensors/read_orientation.py +++ b/examples/sensors/read_orientation.py @@ -1,6 +1,6 @@ from arduino_alvik import ArduinoAlvik from time import sleep_ms -import sys + alvik = ArduinoAlvik() alvik.begin() @@ -13,4 +13,4 @@ except KeyboardInterrupt as e: print('over') alvik.stop() - sys.exit() + break diff --git a/examples/sensors/read_tof.py b/examples/sensors/read_tof.py index 990bf63..20d37f0 100644 --- a/examples/sensors/read_tof.py +++ b/examples/sensors/read_tof.py @@ -1,6 +1,6 @@ from arduino_alvik import ArduinoAlvik from time import sleep_ms -import sys + alvik = ArduinoAlvik() alvik.begin() @@ -15,4 +15,4 @@ except KeyboardInterrupt as e: print('over') alvik.stop() - sys.exit() + break diff --git a/examples/sensors/read_touch.py b/examples/sensors/read_touch.py index 21c5ebb..6a627df 100644 --- a/examples/sensors/read_touch.py +++ b/examples/sensors/read_touch.py @@ -1,6 +1,6 @@ from arduino_alvik import ArduinoAlvik from time import sleep_ms -import sys + alvik = ArduinoAlvik() alvik.begin() @@ -27,4 +27,4 @@ except KeyboardInterrupt as e: print('over') alvik.stop() - sys.exit() + break diff --git a/examples/tests/message_reader.py b/examples/tests/message_reader.py index 7ae24e1..d2eb283 100644 --- a/examples/tests/message_reader.py +++ b/examples/tests/message_reader.py @@ -1,6 +1,6 @@ from arduino_alvik import ArduinoAlvik from time import sleep_ms -import sys + alvik = ArduinoAlvik() alvik.begin() @@ -25,5 +25,5 @@ except KeyboardInterrupt as e: print('over') alvik.stop() - sys.exit() + break diff --git a/examples/tests/test_idle.py b/examples/tests/test_idle.py index f65625a..1c26a97 100644 --- a/examples/tests/test_idle.py +++ b/examples/tests/test_idle.py @@ -1,6 +1,6 @@ from arduino_alvik import ArduinoAlvik from time import sleep_ms -import sys + alvik = ArduinoAlvik() alvik.begin() @@ -19,5 +19,5 @@ except KeyboardInterrupt as e: print('over') alvik.stop() - sys.exit() + break diff --git a/examples/tests/test_meas_units.py b/examples/tests/test_meas_units.py index 468073d..3938a56 100644 --- a/examples/tests/test_meas_units.py +++ b/examples/tests/test_meas_units.py @@ -1,124 +1,122 @@ from arduino_alvik import ArduinoAlvik from time import sleep_ms -import sys + alvik = ArduinoAlvik() alvik.begin() -while True: - try: - - # -- LINEAR MOVEMENTS -- - - print("Move fw 0.05 m") - alvik.move(0.05, unit='m') - sleep_ms(2000) - - print("Move fw 10 cm") - alvik.move(5, unit='cm') - sleep_ms(2000) - - print("Move bw 100 mm") - alvik.move(-100, unit='mm') - sleep_ms(2000) - - print("Move fw 1 inch") - alvik.move(1, unit='in') - sleep_ms(2000) - - print(f"Current position: {alvik.get_pose()}") - alvik.reset_pose(0, 0, theta=3.1415, angle_unit='rad') - sleep_ms(2000) - - print(f"Current position: {alvik.get_pose()}") - - # -- WHEEL ROTATIONS -- - alvik.right_wheel.reset() - sleep_ms(2000) - curr_pos = alvik.right_wheel.get_position() - print(f'R wheel pos: {curr_pos}') - sleep_ms(2000) - - print("Rotate right wheel 25% fw") - alvik.right_wheel.set_position(25, unit='%') - sleep_ms(2000) - curr_pos = alvik.right_wheel.get_position() - print(f'R wheel pos: {curr_pos}') - - print("Rotate right wheel 90 deg bw") - alvik.right_wheel.set_position(-90, unit='deg') - sleep_ms(2000) - curr_pos = alvik.right_wheel.get_position() - print(f'R wheel pos: {curr_pos}') - - print("Rotate right wheel pi rad fw") - alvik.right_wheel.set_position(3.14, unit='rad') - sleep_ms(2000) - curr_pos = alvik.right_wheel.get_position() - print(f'R wheel pos: {curr_pos}') - - print("Rotate right wheel a quarter revolution bw") - alvik.right_wheel.set_position(-0.25, unit='rev') - sleep_ms(2000) - curr_pos = alvik.right_wheel.get_position() - print(f'R wheel pos: {curr_pos}') - - # -- WHEELS SPEED -- - print("Set speed 50% max_rpm (35.0 rpm)") - alvik.set_wheels_speed(50, 50, '%') - sleep_ms(1000) - print(f"Current speed is {alvik.get_wheels_speed()} rpm") - - print("Set speed 12 rpm (1 rev in 5 sec)") - alvik.set_wheels_speed(12, 12, 'rpm') - sleep_ms(1000) - print(f"Current speed is {alvik.get_wheels_speed()} rpm") - - print("Set speed -pi rad/s (1 back rev in 2 sec)") - alvik.set_wheels_speed(-3.1415, -3.1415, 'rad/s') - sleep_ms(1000) - print(f"Current speed is {alvik.get_wheels_speed()} rpm") - - print("Set speed 180 deg/s (1 back rev in 2 sec)") - alvik.set_wheels_speed(180, 180, 'deg/s') - sleep_ms(1000) - print(f"Current speed is {alvik.get_wheels_speed()} rpm") - - # -- DRIVE -- - print("Driving at 10 mm/s (expecting approx 5.6 rpm 64 deg/s)") - alvik.drive(10, 20, linear_unit='mm/s', angular_unit='%') - sleep_ms(2000) - print(f"Current speed is {alvik.get_drive_speed()} (mm/s, deg/s))") - - print("Driving at 10 mm/s (expecting approx 5.6 rpm)") - alvik.drive(10, 0, linear_unit='mm/s') - sleep_ms(2000) - print(f"Current speed is {alvik.get_wheels_speed()} rpm") - - print("Driving at 2 cm/s (expecting approx 11.2 rpm)") - alvik.drive(2, 0, linear_unit='cm/s') - sleep_ms(2000) - print(f"Current speed is {alvik.get_wheels_speed()} rpm") - - print("Driving at 1 in/s (expecting approx 14 rpm)") - alvik.drive(1, 0, linear_unit='in/s') - sleep_ms(2000) - print(f"Current speed is {alvik.get_wheels_speed()} rpm") - - print("Driving at 5 mm/s (expecting approx 5.6 rpm) pi/8 rad/s (22.5 deg/s)") - alvik.drive(5, 3.1415/8, linear_unit='mm/s', angular_unit='rad/s') - sleep_ms(2000) - print(f"Current speed is {alvik.get_drive_speed()} (mm/s) (rpm)") - - print("Driving at 5 mm/s (expecting approx 5.6 rpm) 1/8 rev/s (45 deg/s)") - alvik.drive(5, 1/8, linear_unit='mm/s', angular_unit='rev/s') - sleep_ms(2000) - print(f"Current speed is {alvik.get_drive_speed()} (mm/s) (rpm)") - - alvik.stop() - sys.exit() - - except KeyboardInterrupt as e: - print('over') - alvik.stop() - sys.exit() +try: + + # -- LINEAR MOVEMENTS -- + + print("Move fw 0.05 m") + alvik.move(0.05, unit='m') + sleep_ms(2000) + + print("Move fw 10 cm") + alvik.move(5, unit='cm') + sleep_ms(2000) + + print("Move bw 100 mm") + alvik.move(-100, unit='mm') + sleep_ms(2000) + + print("Move fw 1 inch") + alvik.move(1, unit='in') + sleep_ms(2000) + + print(f"Current position: {alvik.get_pose()}") + alvik.reset_pose(0, 0, theta=3.1415, angle_unit='rad') + sleep_ms(2000) + + print(f"Current position: {alvik.get_pose()}") + + # -- WHEEL ROTATIONS -- + alvik.right_wheel.reset() + sleep_ms(2000) + curr_pos = alvik.right_wheel.get_position() + print(f'R wheel pos: {curr_pos}') + sleep_ms(2000) + + print("Rotate right wheel 25% fw") + alvik.right_wheel.set_position(25, unit='%') + sleep_ms(2000) + curr_pos = alvik.right_wheel.get_position() + print(f'R wheel pos: {curr_pos}') + + print("Rotate right wheel 90 deg bw") + alvik.right_wheel.set_position(-90, unit='deg') + sleep_ms(2000) + curr_pos = alvik.right_wheel.get_position() + print(f'R wheel pos: {curr_pos}') + + print("Rotate right wheel pi rad fw") + alvik.right_wheel.set_position(3.14, unit='rad') + sleep_ms(2000) + curr_pos = alvik.right_wheel.get_position() + print(f'R wheel pos: {curr_pos}') + + print("Rotate right wheel a quarter revolution bw") + alvik.right_wheel.set_position(-0.25, unit='rev') + sleep_ms(2000) + curr_pos = alvik.right_wheel.get_position() + print(f'R wheel pos: {curr_pos}') + + # -- WHEELS SPEED -- + print("Set speed 50% max_rpm (35.0 rpm)") + alvik.set_wheels_speed(50, 50, '%') + sleep_ms(1000) + print(f"Current speed is {alvik.get_wheels_speed()} rpm") + + print("Set speed 12 rpm (1 rev in 5 sec)") + alvik.set_wheels_speed(12, 12, 'rpm') + sleep_ms(1000) + print(f"Current speed is {alvik.get_wheels_speed()} rpm") + + print("Set speed -pi rad/s (1 back rev in 2 sec)") + alvik.set_wheels_speed(-3.1415, -3.1415, 'rad/s') + sleep_ms(1000) + print(f"Current speed is {alvik.get_wheels_speed()} rpm") + + print("Set speed 180 deg/s (1 back rev in 2 sec)") + alvik.set_wheels_speed(180, 180, 'deg/s') + sleep_ms(1000) + print(f"Current speed is {alvik.get_wheels_speed()} rpm") + + # -- DRIVE -- + print("Driving at 10 mm/s (expecting approx 5.6 rpm 64 deg/s)") + alvik.drive(10, 20, linear_unit='mm/s', angular_unit='%') + sleep_ms(2000) + print(f"Current speed is {alvik.get_drive_speed()} (mm/s, deg/s))") + + print("Driving at 10 mm/s (expecting approx 5.6 rpm)") + alvik.drive(10, 0, linear_unit='mm/s') + sleep_ms(2000) + print(f"Current speed is {alvik.get_wheels_speed()} rpm") + + print("Driving at 2 cm/s (expecting approx 11.2 rpm)") + alvik.drive(2, 0, linear_unit='cm/s') + sleep_ms(2000) + print(f"Current speed is {alvik.get_wheels_speed()} rpm") + + print("Driving at 1 in/s (expecting approx 14 rpm)") + alvik.drive(1, 0, linear_unit='in/s') + sleep_ms(2000) + print(f"Current speed is {alvik.get_wheels_speed()} rpm") + + print("Driving at 5 mm/s (expecting approx 5.6 rpm) pi/8 rad/s (22.5 deg/s)") + alvik.drive(5, 3.1415/8, linear_unit='mm/s', angular_unit='rad/s') + sleep_ms(2000) + print(f"Current speed is {alvik.get_drive_speed()} (mm/s) (rpm)") + + print("Driving at 5 mm/s (expecting approx 5.6 rpm) 1/8 rev/s (45 deg/s)") + alvik.drive(5, 1/8, linear_unit='mm/s', angular_unit='rev/s') + sleep_ms(2000) + print(f"Current speed is {alvik.get_drive_speed()} (mm/s) (rpm)") + +except KeyboardInterrupt as e: + print('Test interrupted') + +finally: + alvik.stop() + print('END of measurement units test') diff --git a/examples/tests/test_version.py b/examples/tests/test_version.py index 1682316..52c0660 100644 --- a/examples/tests/test_version.py +++ b/examples/tests/test_version.py @@ -1,6 +1,6 @@ from arduino_alvik import ArduinoAlvik from time import sleep_ms -import sys + alvik = ArduinoAlvik() @@ -16,4 +16,4 @@ except KeyboardInterrupt as e: print('over') alvik.stop() - sys.exit() \ No newline at end of file + break \ No newline at end of file diff --git a/examples/update_firmware.py b/examples/update_firmware.py new file mode 100644 index 0000000..96845fe --- /dev/null +++ b/examples/update_firmware.py @@ -0,0 +1,8 @@ +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') \ No newline at end of file diff --git a/install.bat b/install.bat index efbd576..f8a4830 100644 --- a/install.bat +++ b/install.bat @@ -30,6 +30,7 @@ python -m mpremote %port_string% fs cp arduino_alvik/uart.py :lib/arduino_alvik/ echo Installing dependencies python -m mpremote %port_string% mip install github:arduino/ucPack-mpy +python -m mpremote %port_string% mip install github:arduino/arduino-runtime-mpy python -m mpremote %port_string% reset exit /b 0 diff --git a/install.sh b/install.sh index e606f57..837f7fd 100644 --- a/install.sh +++ b/install.sh @@ -55,5 +55,6 @@ $python_command -m mpremote $connect_string fs cp arduino_alvik/uart.py :lib/ard echo "Installing dependencies" $python_command -m mpremote $connect_string mip install github:arduino/ucPack-mpy +$python_command -m mpremote $connect_string mip install github:arduino/arduino-runtime-mpy $python_command -m mpremote $connect_string reset diff --git a/package.json b/package.json index 8c829cb..d09a258 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ ["arduino_alvik/stm32_flash.py", "github:arduino/arduino-alvik-mpy/arduino_alvik/stm32_flash.py"] ], "deps": [ - ["github:arduino/ucPack-mpy", "0.1.6"] + ["github:arduino/ucPack-mpy", "0.1.7"], + ["github:arduino/arduino-runtime-mpy", "0.4.0"] ], - "version": "1.1.0" + "version": "1.1.4" }