Skip to content

Commit 7044475

Browse files
committed
feat: touch events
with 'noisy' UP button
1 parent 49bcd32 commit 7044475

File tree

2 files changed

+317
-2
lines changed

2 files changed

+317
-2
lines changed

arduino_alvik.py

+260-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class ArduinoAlvik:
1919

2020
_update_thread_running = False
2121
_update_thread_id = None
22+
_touch_events_thread_running = False
23+
_touch_events_thread_id = None
2224

2325
def __new__(cls):
2426
if not hasattr(cls, '_instance'):
@@ -68,6 +70,7 @@ def __init__(self):
6870
self._angular_velocity = None
6971
self._last_ack = ''
7072
self._version = [None, None, None]
73+
self._touch_events = _ArduinoAlvikTouchEvents()
7174

7275
@staticmethod
7376
def is_on() -> bool:
@@ -135,7 +138,7 @@ def _idle(self, delay_=1, check_on_thread=False) -> None:
135138
sys.exit()
136139
except Exception as e:
137140
pass
138-
#print(f'Unable to read SOC: {e}')
141+
# print(f'Unable to read SOC: {e}')
139142
finally:
140143
LEDR.value(1)
141144
LEDG.value(1)
@@ -179,6 +182,9 @@ def begin(self) -> int:
179182
self._idle(1000)
180183
self._begin_update_thread()
181184
sleep_ms(100)
185+
if self._touch_events.has_callbacks():
186+
print('Starting touch events')
187+
self._start_touch_events_thread()
182188
self._reset_hw()
183189
self._flush_uart()
184190
self._snake_robot(1000)
@@ -293,9 +299,12 @@ def stop(self):
293299
# turn off UI leds
294300
self._set_leds(0x00)
295301

296-
# stop the update thrad
302+
# stop the update thread
297303
self._stop_update_thread()
298304

305+
# stop touch events thread
306+
self._stop_touch_events_thread()
307+
299308
# delete _instance
300309
del self.__class__._instance
301310
gc.collect()
@@ -953,6 +962,99 @@ def print_status(self):
953962
continue
954963
print(f'{str(a).upper()} = {getattr(self, str(a))}')
955964

965+
def on_touch_ok_pressed(self, callback: callable, args: tuple = ()) -> None:
966+
"""
967+
Register callback when touch button OK is pressed
968+
:param callback:
969+
:param args:
970+
:return:
971+
"""
972+
self._touch_events.register_callback('on_ok_pressed', callback, args)
973+
974+
def on_touch_cancel_pressed(self, callback: callable, args: tuple = ()) -> None:
975+
"""
976+
Register callback when touch button CANCEL is pressed
977+
:param callback:
978+
:param args:
979+
:return:
980+
"""
981+
self._touch_events.register_callback('on_cancel_pressed', callback, args)
982+
983+
def on_touch_center_pressed(self, callback: callable, args: tuple = ()) -> None:
984+
"""
985+
Register callback when touch button CENTER is pressed
986+
:param callback:
987+
:param args:
988+
:return:
989+
"""
990+
self._touch_events.register_callback('on_center_pressed', callback, args)
991+
992+
def on_touch_up_pressed(self, callback: callable, args: tuple = ()) -> None:
993+
"""
994+
Register callback when touch button UP is pressed
995+
:param callback:
996+
:param args:
997+
:return:
998+
"""
999+
self._touch_events.register_callback('on_up_pressed', callback, args)
1000+
1001+
def on_touch_left_pressed(self, callback: callable, args: tuple = ()) -> None:
1002+
"""
1003+
Register callback when touch button LEFT is pressed
1004+
:param callback:
1005+
:param args:
1006+
:return:
1007+
"""
1008+
self._touch_events.register_callback('on_left_pressed', callback, args)
1009+
1010+
def on_touch_down_pressed(self, callback: callable, args: tuple = ()) -> None:
1011+
"""
1012+
Register callback when touch button DOWN is pressed
1013+
:param callback:
1014+
:param args:
1015+
:return:
1016+
"""
1017+
self._touch_events.register_callback('on_down_pressed', callback, args)
1018+
1019+
def on_touch_right_pressed(self, callback: callable, args: tuple = ()) -> None:
1020+
"""
1021+
Register callback when touch button RIGHT is pressed
1022+
:param callback:
1023+
:param args:
1024+
:return:
1025+
"""
1026+
self._touch_events.register_callback('on_right_pressed', callback, args)
1027+
1028+
def _start_touch_events_thread(self) -> None:
1029+
"""
1030+
Starts the touch events thread
1031+
:return:
1032+
"""
1033+
if not self.__class__._touch_events_thread_running:
1034+
self.__class__._touch_events_thread_running = True
1035+
self.__class__._touch_events_thread_id = _thread.start_new_thread(self._update_touch_events, (50,))
1036+
1037+
def _update_touch_events(self, delay_: int = 100):
1038+
"""
1039+
Updates the touch state so that touch events can be generated
1040+
:param delay_:
1041+
:return:
1042+
"""
1043+
while True:
1044+
if self.is_on() and self._touch_byte is not None:
1045+
self._touch_events.update_touch_state(self._touch_byte)
1046+
if not ArduinoAlvik._touch_events_thread_running:
1047+
break
1048+
sleep_ms(delay_)
1049+
1050+
@classmethod
1051+
def _stop_touch_events_thread(cls):
1052+
"""
1053+
Stops the touch events thread
1054+
:return:
1055+
"""
1056+
cls._touch_events_thread_running = False
1057+
9561058

9571059
class _ArduinoAlvikWheel:
9581060

@@ -1065,3 +1167,159 @@ def set_color(self, red: bool, green: bool, blue: bool):
10651167
self._led_state[0] = led_status
10661168
self._packeter.packetC1B(ord('L'), led_status & 0xFF)
10671169
uart.write(self._packeter.msg[0:self._packeter.msg_size])
1170+
1171+
1172+
class _ArduinoAlvikEvents:
1173+
"""
1174+
This is a generic events class
1175+
"""
1176+
1177+
def __init__(self):
1178+
self._callbacks = dict()
1179+
1180+
def register_callback(self, event_name: str, callback: callable, args: tuple = None):
1181+
"""
1182+
Registers a callback to execute on an event
1183+
:param event_name:
1184+
:param callback: the callable
1185+
:param args: arguments tuple to pass to the callable. remember the comma! (value,)
1186+
:return:
1187+
"""
1188+
self._callbacks[event_name] = (callback, args,)
1189+
1190+
def has_callbacks(self) -> bool:
1191+
"""
1192+
True if the _callbacks dictionary has any callback registered
1193+
:return:
1194+
"""
1195+
return bool(self._callbacks)
1196+
1197+
def execute_callback(self, event_name: str):
1198+
"""
1199+
Executes the callback associated to the event_name
1200+
:param event_name:
1201+
:return:
1202+
"""
1203+
if event_name not in self._callbacks.keys():
1204+
return
1205+
self._callbacks[event_name][0](*self._callbacks[event_name][1])
1206+
1207+
1208+
class _ArduinoAlvikTouchEvents(_ArduinoAlvikEvents):
1209+
"""
1210+
This is the event class to handle touch button events
1211+
"""
1212+
1213+
available_events = ['on_ok_pressed', 'on_cancel_pressed',
1214+
'on_center_pressed', 'on_left_pressed',
1215+
'on_right_pressed', 'on_up_pressed',
1216+
'on_down_pressed']
1217+
1218+
def __init__(self):
1219+
self._current_touch_state = 0
1220+
super().__init__()
1221+
1222+
@staticmethod
1223+
def _is_ok_pressed(current_state, new_state) -> bool:
1224+
"""
1225+
True if OK was pressed
1226+
:param current_state:
1227+
:param new_state:
1228+
:return:
1229+
"""
1230+
return not bool(current_state & 0b00000010) and bool(new_state & 0b00000010)
1231+
1232+
@staticmethod
1233+
def _is_cancel_pressed(current_state, new_state) -> bool:
1234+
"""
1235+
True if CANCEL was pressed
1236+
:param current_state:
1237+
:param new_state:
1238+
:return:
1239+
"""
1240+
return not bool(current_state & 0b00000100) and bool(new_state & 0b00000100)
1241+
1242+
@staticmethod
1243+
def _is_center_pressed(current_state, new_state) -> bool:
1244+
"""
1245+
True if CENTER was pressed
1246+
:param current_state:
1247+
:param new_state:
1248+
:return:
1249+
"""
1250+
return not bool(current_state & 0b00001000) and bool(new_state & 0b00001000)
1251+
1252+
@staticmethod
1253+
def _is_up_pressed(current_state, new_state) -> bool:
1254+
"""
1255+
True if UP was pressed
1256+
:param current_state:
1257+
:param new_state:
1258+
:return:
1259+
"""
1260+
return not bool(current_state & 0b00010000) and bool(new_state & 0b00010000)
1261+
1262+
@staticmethod
1263+
def _is_left_pressed(current_state, new_state) -> bool:
1264+
"""
1265+
True if LEFT was pressed
1266+
:param current_state:
1267+
:param new_state:
1268+
:return:
1269+
"""
1270+
return not bool(current_state & 0b00100000) and bool(new_state & 0b00100000)
1271+
1272+
@staticmethod
1273+
def _is_down_pressed(current_state, new_state) -> bool:
1274+
"""
1275+
True if DOWN was pressed
1276+
:param current_state:
1277+
:param new_state:
1278+
:return:
1279+
"""
1280+
return not bool(current_state & 0b01000000) and bool(new_state & 0b01000000)
1281+
1282+
@staticmethod
1283+
def _is_right_pressed(current_state, new_state) -> bool:
1284+
"""
1285+
True if RIGHT was pressed
1286+
:param current_state:
1287+
:param new_state:
1288+
:return:
1289+
"""
1290+
return not bool(current_state & 0b10000000) and bool(new_state & 0b10000000)
1291+
1292+
def update_touch_state(self, touch_state: int):
1293+
"""
1294+
Updates the internal touch state and executes any possible callback
1295+
:param touch_state:
1296+
:return:
1297+
"""
1298+
1299+
if self._is_ok_pressed(self._current_touch_state, touch_state):
1300+
self.execute_callback('on_ok_pressed')
1301+
1302+
if self._is_cancel_pressed(self._current_touch_state, touch_state):
1303+
self.execute_callback('on_cancel_pressed')
1304+
1305+
if self._is_center_pressed(self._current_touch_state, touch_state):
1306+
self.execute_callback('on_center_pressed')
1307+
1308+
if self._is_up_pressed(self._current_touch_state, touch_state):
1309+
self.execute_callback('on_up_pressed')
1310+
1311+
if self._is_left_pressed(self._current_touch_state, touch_state):
1312+
self.execute_callback('on_left_pressed')
1313+
1314+
if self._is_down_pressed(self._current_touch_state, touch_state):
1315+
self.execute_callback('on_down_pressed')
1316+
1317+
if self._is_right_pressed(self._current_touch_state, touch_state):
1318+
self.execute_callback('on_right_pressed')
1319+
1320+
self._current_touch_state = touch_state
1321+
1322+
def register_callback(self, event_name: str, callback: callable, args: tuple = None):
1323+
if event_name not in self.__class__.available_events:
1324+
return
1325+
super().register_callback(event_name, callback, args)

examples/touch_events.py

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from arduino_alvik import ArduinoAlvik
2+
from time import sleep
3+
import sys
4+
5+
value = 0
6+
7+
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}")
13+
14+
15+
def simple_print(custom_text: str = '') -> None:
16+
print(custom_text)
17+
18+
alvik = ArduinoAlvik()
19+
alvik.on_touch_ok_pressed(toggle_left_led, ("OK WAS PRESSED... THAT'S COOL", ))
20+
alvik.on_touch_center_pressed(simple_print, ("CENTER PRESSED",))
21+
alvik.on_touch_cancel_pressed(simple_print, ("CANCEL PRESSED",))
22+
alvik.on_touch_up_pressed(simple_print, ("UP PRESSED",))
23+
alvik.on_touch_left_pressed(simple_print, ("LEFT PRESSED",))
24+
alvik.on_touch_down_pressed(simple_print, ("DOWN PRESSED",))
25+
alvik.on_touch_right_pressed(simple_print, ("RIGHT PRESSED",))
26+
27+
alvik.begin()
28+
29+
alvik.left_wheel.reset()
30+
alvik.right_wheel.reset()
31+
32+
while True:
33+
try:
34+
alvik.left_wheel.set_position(30)
35+
sleep(2)
36+
print(f'Left wheel degs: {alvik.left_wheel.get_position()}')
37+
print(f'Right wheel degs: {alvik.right_wheel.get_position()}')
38+
39+
alvik.right_wheel.set_position(10)
40+
sleep(2)
41+
print(f'Left wheel degs: {alvik.left_wheel.get_position()}')
42+
print(f'Right wheel degs: {alvik.right_wheel.get_position()}')
43+
44+
alvik.left_wheel.set_position(180)
45+
sleep(2)
46+
print(f'Left wheel degs: {alvik.left_wheel.get_position()}')
47+
print(f'Right wheel degs: {alvik.right_wheel.get_position()}')
48+
49+
alvik.right_wheel.set_position(270)
50+
sleep(2)
51+
print(f'Left wheel degs: {alvik.left_wheel.get_position()}')
52+
print(f'Right wheel degs: {alvik.right_wheel.get_position()}')
53+
54+
except KeyboardInterrupt as e:
55+
print('over')
56+
alvik.stop()
57+
sys.exit()

0 commit comments

Comments
 (0)