Skip to content

Commit acd885b

Browse files
authored
Merge pull request #23 from arduino/generalize_events
mod: timer events starting right after thread is started
2 parents fba0e9f + 94c7c89 commit acd885b

File tree

6 files changed

+215
-41
lines changed

6 files changed

+215
-41
lines changed

arduino_alvik/arduino_alvik.py

Lines changed: 99 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,9 @@ def begin(self) -> int:
186186
sleep_ms(1000)
187187
self._idle(1000)
188188
self._begin_update_thread()
189+
189190
sleep_ms(100)
190-
if self._has_events_registered():
191-
print('Starting events thread')
192-
self._start_events_thread()
191+
193192
self._reset_hw()
194193
self._flush_uart()
195194
self._snake_robot(1000)
@@ -198,6 +197,9 @@ def begin(self) -> int:
198197
self.set_illuminator(True)
199198
self.set_behaviour(1)
200199
self._set_color_reference()
200+
if self._has_events_registered():
201+
print('Starting events thread')
202+
self._start_events_thread()
201203
self.set_servo_positions(0, 0)
202204
return 0
203205

@@ -1062,7 +1064,7 @@ def print_status(self):
10621064
print(f'LINEAR VEL: {self._linear_velocity}')
10631065
print(f'ANGULAR VEL: {self._angular_velocity}')
10641066

1065-
def timer(self, mode: str, period: int, callback: callable, args: tuple = ()) -> None:
1067+
def set_timer(self, mode: str, period: int, callback: callable, args: tuple = ()) -> None:
10661068
"""
10671069
Register a timer callback
10681070
:param mode: _ArduinoAlvikTimerEvents.PERIODIC or .ONE_SHOT
@@ -1075,6 +1077,14 @@ def timer(self, mode: str, period: int, callback: callable, args: tuple = ()) ->
10751077
self._timer_events = _ArduinoAlvikTimerEvents(period)
10761078
self._timer_events.register_callback(mode, callback, args)
10771079

1080+
@property
1081+
def timer(self):
1082+
"""
1083+
Gives access to the timer object
1084+
:return:
1085+
"""
1086+
return self._timer_events
1087+
10781088
def on_touch_ok_pressed(self, callback: callable, args: tuple = ()) -> None:
10791089
"""
10801090
Register callback when touch button OK is pressed
@@ -1208,6 +1218,8 @@ def _start_events_thread(self) -> None:
12081218
"""
12091219
if not self.__class__._events_thread_running:
12101220
self.__class__._events_thread_running = True
1221+
self._timer_events.reset() # resets the timer before starting
1222+
self._move_events.reset(_ArduinoAlvikMoveEvents.NZ_TILT) # resets the orientation to -Z tilted
12111223
self.__class__._events_thread_id = _thread.start_new_thread(self._update_events, (50,))
12121224

12131225
def _update_events(self, delay_: int = 100):
@@ -1441,8 +1453,68 @@ def __init__(self, period: int):
14411453
self._last_trigger = ticks_ms()
14421454
self._period = period
14431455
self._triggered = False
1456+
self._stopped = False
14441457
super().__init__()
14451458

1459+
def is_triggered(self):
1460+
"""
1461+
Returns the trigger state
1462+
:return:
1463+
"""
1464+
return self._triggered
1465+
1466+
def is_stopped(self):
1467+
"""
1468+
Return True if timer is stopped
1469+
:return:
1470+
"""
1471+
return self._stopped
1472+
1473+
def set(self, start=None, period: int = None):
1474+
"""
1475+
Sets the last trigger time
1476+
:param start:
1477+
:param period:
1478+
:return:
1479+
"""
1480+
self._last_trigger = start if start is not None else ticks_ms()
1481+
if period is not None:
1482+
self._period = period
1483+
1484+
def reset(self, start=None, period: int = None):
1485+
"""
1486+
Resets the timer. Use just before starting the events thread or if you want to restart the Timer
1487+
:param start:
1488+
:param period:
1489+
:return:
1490+
"""
1491+
self._last_trigger = start if start is not None else ticks_ms()
1492+
if period is not None:
1493+
self._period = period
1494+
self._triggered = False
1495+
1496+
def stop(self):
1497+
"""
1498+
Stops the timer
1499+
:return:
1500+
"""
1501+
1502+
self._stopped = True
1503+
1504+
def resume(self):
1505+
"""
1506+
Resumes the timer
1507+
:return:
1508+
"""
1509+
self._stopped = False
1510+
1511+
def get(self) -> int:
1512+
"""
1513+
Returns the time passed since the last trigger in ms
1514+
:return:
1515+
"""
1516+
return ticks_diff(ticks_ms(), self._last_trigger)
1517+
14461518
def register_callback(self, event_name: str, callback: callable, args: tuple = None):
14471519
"""
14481520
Repeated calls to register_callback will overwrite the timer's behaviour. The Timer can be either PERIODIC
@@ -1455,30 +1527,32 @@ def register_callback(self, event_name: str, callback: callable, args: tuple = N
14551527
self._callbacks = dict()
14561528
super().register_callback(event_name, callback, args)
14571529

1458-
def _is_period_expired(self, now=ticks_ms()) -> bool:
1530+
def _is_period_expired(self, now=None) -> bool:
14591531
"""
14601532
True if the timer period is expired
14611533
:return:
14621534
"""
14631535

1464-
if ticks_diff(now, self._last_trigger) > self._period:
1465-
self._last_trigger = now
1466-
return True
1536+
if now is None:
1537+
now = ticks_ms()
1538+
return ticks_diff(now, self._last_trigger) > self._period
14671539

1468-
return False
1469-
1470-
def update_state(self, state):
1540+
def update_state(self, ticks):
14711541
"""
14721542
Updates the internal state of the events handler and executes the related callback
14731543
:return:
14741544
"""
14751545

14761546
if list(self._callbacks.keys()) == [self.PERIODIC]:
1477-
if self._is_period_expired(state):
1478-
self.execute_callback(self.PERIODIC)
1547+
if self._is_period_expired(ticks):
1548+
self._last_trigger = ticks
1549+
if not self._stopped:
1550+
self.execute_callback(self.PERIODIC)
14791551
elif list(self._callbacks.keys()) == [self.ONE_SHOT] and not self._triggered:
1480-
if self._is_period_expired(state):
1481-
self.execute_callback(self.ONE_SHOT)
1552+
if self._is_period_expired(ticks):
1553+
self._last_trigger = ticks
1554+
if not self._stopped:
1555+
self.execute_callback(self.ONE_SHOT)
14821556
self._triggered = True
14831557

14841558

@@ -1608,10 +1682,20 @@ class _ArduinoAlvikMoveEvents(_ArduinoAlvikEvents):
16081682
available_events = ['on_shake', 'on_x_tilt', 'on_y_tilt', 'on_z_tilt',
16091683
'on_nx_tilt', 'on_ny_tilt', 'on_nz_tilt']
16101684

1685+
NZ_TILT = 0x80
1686+
16111687
def __init__(self):
16121688
self._current_state = 0
16131689
super().__init__()
16141690

1691+
def reset(self, state: int = 0x00):
1692+
"""
1693+
Sets the initial state
1694+
:param state:
1695+
:return:
1696+
"""
1697+
self._current_state = state
1698+
16151699
@staticmethod
16161700
def _is_shaken(current_state, new_state) -> bool:
16171701
"""

examples/move_events.py renamed to examples/movement_events.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,35 @@
33
import sys
44

55

6-
def toggle_left_led(custom_text: str = '') -> None:
7-
global value
8-
value = (value + 1) % 2
9-
alvik.left_led.set_color(value, 0, 0)
10-
print(f"RED BLINKS! {custom_text}")
6+
def toggle_value():
7+
"""
8+
This function yields a generator object that toggles values between 0 and 1.
9+
:return:
10+
"""
11+
value = 0
12+
while True:
13+
yield value % 2
14+
value += 1
15+
16+
17+
def toggle_left_led(custom_text: str, val) -> None:
18+
"""
19+
This function toggles the lef led in the red channel. It also writes some custom text.
20+
:param custom_text: your custom text
21+
:param val: a toggle signal generator
22+
:return:
23+
"""
24+
led_val = next(val)
25+
alvik.left_led.set_color(led_val, 0, 0)
26+
print(f"RED {'ON' if led_val else 'OFF'}! {custom_text}")
1127

1228

1329
def simple_print(custom_text: str = '') -> None:
1430
print(custom_text)
1531

1632

1733
alvik = ArduinoAlvik()
18-
alvik.on_shake(toggle_left_led, ("ALVIK WAS SHAKEN... YOU MAKE ME SHIVER :)", ))
34+
alvik.on_shake(toggle_left_led, ("ALVIK WAS SHAKEN... YOU MAKE ME SHIVER :)", toggle_value(), ))
1935
alvik.on_x_tilt(simple_print, ("TILTED ON X",))
2036
alvik.on_nx_tilt(simple_print, ("TILTED ON -X",))
2137
alvik.on_y_tilt(simple_print, ("TILTED ON Y",))

examples/read_orientation.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from arduino_alvik import ArduinoAlvik
2+
from time import sleep_ms
3+
import sys
4+
5+
alvik = ArduinoAlvik()
6+
alvik.begin()
7+
8+
while True:
9+
try:
10+
roll, pitch, yaw = alvik.get_orientation()
11+
print(f'ROLL: {roll}, PITCH: {pitch}, YAW: {yaw}')
12+
sleep_ms(50)
13+
except KeyboardInterrupt as e:
14+
print('over')
15+
alvik.stop()
16+
sys.exit()

examples/timer_one_shot_events.py

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,32 @@
22
from time import sleep
33
import sys
44

5-
value = 0
65

6+
def toggle_value():
7+
"""
8+
This function yields a generator object that toggles values between 0 and 1.
9+
:return:
10+
"""
11+
value = 0
12+
while True:
13+
yield value % 2
14+
value += 1
715

8-
def toggle_left_led(custom_text: str = '') -> None:
9-
global value
10-
value = (value + 1) % 2
11-
alvik.left_led.set_color(value, 0, 0)
12-
print(f"RED BLINKS! {custom_text}")
16+
17+
def toggle_left_led(custom_text: str, val) -> None:
18+
"""
19+
This function toggles the lef led in the red channel. It also writes some custom text.
20+
:param custom_text: your custom text
21+
:param val: a toggle signal generator
22+
:return:
23+
"""
24+
led_val = next(val)
25+
alvik.left_led.set_color(led_val, 0, 0)
26+
print(f"RED {'ON' if led_val else 'OFF'}! {custom_text}")
1327

1428

1529
alvik = ArduinoAlvik()
16-
alvik.timer('one_shot', 10000, toggle_left_led, ("10 seconds have passed... I won't do this again", ))
30+
alvik.set_timer('one_shot', 10000, toggle_left_led, ("10 seconds have passed... I won't do this again", toggle_value(), ))
1731

1832
alvik.begin()
1933

@@ -42,6 +56,15 @@ def toggle_left_led(custom_text: str = '') -> None:
4256
print(f'Left wheel degs: {alvik.left_wheel.get_position()}')
4357
print(f'Right wheel degs: {alvik.right_wheel.get_position()}')
4458

59+
if alvik.timer.is_triggered():
60+
alvik.timer.reset(period=1000)
61+
alvik.timer.stop()
62+
for _ in range(0, 10):
63+
if _ == 2:
64+
alvik.timer.resume()
65+
print(f'TRIGGERED:{alvik.timer.is_triggered()} STOPPED:{alvik.timer.is_stopped()} TIME: {alvik.timer.get()}')
66+
sleep(1)
67+
4568
except KeyboardInterrupt as e:
4669
print('over')
4770
alvik.stop()

examples/timer_periodic_events.py

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,32 @@
22
from time import sleep
33
import sys
44

5-
value = 0
65

6+
def toggle_value():
7+
"""
8+
This function yields a generator object that toggles values between 0 and 1.
9+
:return:
10+
"""
11+
value = 0
12+
while True:
13+
yield value % 2
14+
value += 1
715

8-
def toggle_left_led(custom_text: str = '') -> None:
9-
global value
10-
value = (value + 1) % 2
11-
alvik.left_led.set_color(value, 0, 0)
12-
print(f"RED BLINKS! {custom_text}")
16+
17+
def toggle_left_led(custom_text: str, val) -> None:
18+
"""
19+
This function toggles the lef led in the red channel. It also writes some custom text.
20+
:param custom_text: your custom text
21+
:param val: a toggle signal generator
22+
:return:
23+
"""
24+
led_val = next(val)
25+
alvik.left_led.set_color(led_val, 0, 0)
26+
print(f"RED {'ON' if led_val else 'OFF'}! {custom_text}")
1327

1428

1529
alvik = ArduinoAlvik()
16-
alvik.timer('periodic', 500, toggle_left_led, ("500 ms have passed...", ))
30+
alvik.set_timer('periodic', 500, toggle_left_led, ("500 ms have passed...", toggle_value(), ))
1731

1832
alvik.begin()
1933

@@ -42,6 +56,14 @@ def toggle_left_led(custom_text: str = '') -> None:
4256
print(f'Left wheel degs: {alvik.left_wheel.get_position()}')
4357
print(f'Right wheel degs: {alvik.right_wheel.get_position()}')
4458

59+
alvik.timer.reset(period=1000)
60+
alvik.timer.stop()
61+
for _ in range(0, 20):
62+
if _ == 5:
63+
alvik.timer.resume()
64+
print(f'TRIGGERED:{alvik.timer.is_triggered()} STOPPED:{alvik.timer.is_stopped()} TIME: {alvik.timer.get()}')
65+
sleep(1)
66+
4567
except KeyboardInterrupt as e:
4668
print('over')
4769
alvik.stop()

0 commit comments

Comments
 (0)