@@ -11,22 +11,38 @@ class ComponentPins(Enum):
1111 ANALOG_WRITE = 4
1212 RGB_LED_STRIP = 5
1313 SERVO = 6
14+ LED_MATRIX = 7
15+ DIGITAL_DISPLAY_TM = 8
16+ MOTOR = 9
17+ PASSIVE_BUZZER = 10
18+ STEPPER_MOTOR = 11
19+ BUTTON = 12
20+ IR_REMOTE = 13
21+ DIGITAL_READ = 14
22+ JOYSTICK = 16
23+ ULTRASONIC_SENSOR = 17
24+ RFID = 18
1425
1526class ElectroBlocks :
1627
1728 last_sense_data = ""
1829 verbose = False
1930 pins = {}
2031
32+
33+
2134 def __init__ (self , baudrate = 115200 , timeout = 2 , verbose = False ):
2235 self .ser = self ._auto_connect (baudrate , timeout )
2336 self .verbose = verbose
2437 self ._wait_for_ready ()
25-
38+ self ._cache = None
39+ self ._cache_time = 0
40+ self ._cache_ttl = 0.08 # 80 milliseconds
41+
2642 def _auto_connect (self , baudrate , timeout ):
2743 ports = list (serial .tools .list_ports .comports ())
2844 for p in ports :
29- if ( p .vid == 9025 and p .pid in (67 , 16 )) or ( p . vid == 6790 ): # Arduino Uno or Mega and Indian Arduino UNO
45+ if p .vid in ( 9025 , 6790 , 4292 ) or p .pid in (67 , 16 , 60000 ): # Arduino Uno or Mega and Indian Arduino UNO
3046 try :
3147 ser = serial .Serial (p .device , baudrate , timeout = timeout )
3248 time .sleep (2 ) # Give Arduino time to reset
@@ -63,12 +79,26 @@ def _wait_for_message(self, message):
6379 return ""
6480
6581 def _get_sensor_str (self ):
82+ now = time .monotonic ()
83+
84+ # If cached value is still fresh, return it
85+ if self ._cache and (now - self ._cache_time ) < self ._cache_ttl :
86+ if self .verbose :
87+ print ("Using cached sensor message" )
88+ return self ._cache
89+
90+ # Otherwise fetch new data
6691 self .ser .write (b"sense|" )
6792 message = self ._wait_for_message ("SENSE_COMPLETE" )
6893 if self .verbose :
69- print (f"FULL SENSOR MESSSAGE : { message } " )
94+ print (f"FULL SENSOR MESSAGE : { message } " )
7095 message = message .replace ("SENSE_COMPLETE" , "" )
7196 sensorsStr = message .split (";" )
97+
98+ # Update cache
99+ self ._cache = sensorsStr
100+ self ._cache_time = now
101+
72102 return sensorsStr
73103
74104 # return the result of pin read that is being sensed
@@ -93,45 +123,84 @@ def _send(self, cmd):
93123
94124 # Digital Write Method
95125 def config_digital_read (self , pin ):
96- self ._send (f"config:b={ pin } " )
126+ self ._add_pin (ComponentPins .DIGITAL_READ , pin )
127+ self ._send (f"register::dr::{ pin } " )
97128
98129 def digital_read (self , pin ):
99130 return self ._find_sensor_str (pin , "dr" ) == "1"
100131
101132 # RFID
102133 def config_rfid (self , rxPin , txPin ):
103- self ._send (f"config:rfid={ rxPin } ,{ txPin } " )
134+ self ._add_pin (ComponentPins .RFID , rxPin )
135+ self ._add_pin (ComponentPins .RFID , txPin )
136+ self ._send (f"register::rfi::{ rxPin } ::{ txPin } ::9600" )
104137
105138 def rfid_tag_number (self ):
106- return self ._find_sensor_str ("0" , "rfid" )
139+ pin = self .pins [ComponentPins .RFID ][0 ]
140+ tag = self ._find_sensor_str (pin , "rfi" )
141+ if tag == "0" :
142+ return ""
143+ else :
144+ return tag
107145
108146 def rfid_sensed_card (self ):
109- return len (self ._find_sensor_str ("0" , "rfid" )) > 0
147+ pin = self .pins [ComponentPins .RFID ][0 ]
148+ return self ._find_sensor_str (pin , "rfi" ) != "0"
110149
150+ # Joysick
151+ def config_joystick (self , x , y , sw ):
152+ self ._send (f"register::js::{ x } ::{ y } ::{ sw } " )
153+ self ._add_pin (ComponentPins .JOYSTICK , x )
154+ self ._add_pin (ComponentPins .JOYSTICK , y )
155+ self ._add_pin (ComponentPins .JOYSTICK , sw )
156+
157+ def joystick_angle (self ):
158+ pin = self .pins [ComponentPins .JOYSTICK ][0 ]
159+ [pressed , angle , engaged ] = self ._find_sensor_str (pin , "js" )
160+ return angle
161+
162+ def is_joystick_button_pressed (self ):
163+ pin = self .pins [ComponentPins .JOYSTICK ][0 ]
164+ [pressed , angle , engaged ] = self ._find_sensor_str (pin , "js" )
165+ return pressed
166+
167+ def is_joystick_engaged (self ):
168+ pin = self .pins [ComponentPins .JOYSTICK ][0 ]
169+ [pressed , angle , engaged ] = self ._find_sensor_str (pin , "js" )
170+ return pressed
171+
172+
111173 #IR Remote
112174
113175 def config_ir_remote (self , pin ):
114- self ._send (f"config:ir={ pin } " )
176+ self ._send (f"register::ir::{ pin } " )
177+ self ._add_pin (ComponentPins .IR_REMOTE , pin )
115178
116179 def ir_remote_has_sensed_code (self ):
117- return len (self ._find_sensor_str ("0" , "ir" )) > 0
180+ pin = self .pins [ComponentPins .IR_REMOTE ][0 ]
181+ return len (self ._find_sensor_str (pin , "ir" )) > 0
118182
119183 def ir_remote_get_code (self ):
120- return self ._find_sensor_str ("0" , "ir" )
184+ pin = self .pins [ComponentPins .IR_REMOTE ][0 ]
185+ return self ._find_sensor_str (pin , "ir" )
121186
122187 # Motion Sensors
123188 def config_motion_sensor (self , echoPin , trigPin ):
124- self ._send (f"config:m={ echoPin } ,{ trigPin } " )
189+ self ._add_pin (ComponentPins .ULTRASONIC_SENSOR , trigPin )
190+ self ._add_pin (ComponentPins .ULTRASONIC_SENSOR , echoPin )
191+ self ._send (f"register::ul::{ trigPin } ::{ echoPin } " )
125192
126193 def motion_distance_cm (self ):
127- return self ._find_sensor_str ("0" , "m" )
194+ pin = self .pins [ComponentPins .ULTRASONIC_SENSOR ][0 ]
195+ return self ._find_sensor_str (pin , "ul" )
128196
129197 # Button Methods
130198 def config_button (self , pin ):
131- self ._send (f"config:b={ pin } " )
199+ self ._send (f"register:bt::{ pin } " )
200+ self ._add_pin (ComponentPins .BUTTON , pin )
132201
133202 def is_button_pressed (self , pin ):
134- return self ._find_sensor_str (pin , "b " ) == "0"
203+ return self ._find_sensor_str (pin , "bt " ) == "0"
135204
136205 # Servo Methods
137206 def config_servo (self , pin ):
@@ -197,6 +266,69 @@ def analog_config(self, pin):
197266 self ._send (f"register::aw::{ pin } " )
198267 self ._add_pin (ComponentPins .ANALOG_WRITE , pin )
199268
269+ # LED MATRIX
270+
271+ def config_led_matrix (self , data_pin , cs_pin , clk_pin ):
272+ self ._add_pin (ComponentPins .LED_MATRIX , data_pin )
273+ self ._add_pin (ComponentPins .LED_MATRIX , cs_pin )
274+ self ._add_pin (ComponentPins .LED_MATRIX , clk_pin )
275+ self ._send (f"register::ma::{ data_pin } ::{ cs_pin } ::{ clk_pin } " )
276+
277+ def set_led_matrix_led (self , row , col , isOn ):
278+ pin = self .pins [ComponentPins .LED_MATRIX ][0 ]
279+ isLedOnNumber = "1" if isOn else "0"
280+ self ._send (f"write::ma::{ pin } ::1::{ col - 1 } ::{ 8 - row } ::{ isLedOnNumber } " )
281+
282+ # TM Digital Display
283+
284+ def config_digital_display (self , dio , clk ):
285+ self ._add_pin (ComponentPins .DIGITAL_DISPLAY_TM , dio )
286+ self ._add_pin (ComponentPins .DIGITAL_DISPLAY_TM , clk )
287+ self ._send (f"register::tm::{ dio } ::{ clk } " )
288+
289+ def set_digital_display (self , colonOn , message ):
290+ pin = self .pins [ComponentPins .DIGITAL_DISPLAY_TM ][0 ]
291+ colon = "1" if colonOn else "0"
292+ self ._send (f"write::tm::{ pin } ::{ colon } ::{ message } " )
293+
294+ # Stepper Motors
295+
296+ def config_stepper_motor (self , pin1 , pin2 , pin3 , pin4 , steps , speed ):
297+ self ._add_pin (ComponentPins .STEPPER_MOTOR , pin1 )
298+ self ._add_pin (ComponentPins .STEPPER_MOTOR , pin2 )
299+ self ._add_pin (ComponentPins .STEPPER_MOTOR , pin3 )
300+ self ._add_pin (ComponentPins .STEPPER_MOTOR , pin4 )
301+ self ._send (f"register::ste::{ pin1 } ::{ pin2 } ::{ pin3 } ::{ pin4 } ::{ steps } ::{ speed } " )
302+
303+ def move_stepper_motor (self , steps ):
304+ pin = self .pins [ComponentPins .STEPPER_MOTOR ][0 ]
305+ self ._send (f"write::ste::{ pin } ::{ steps } " )
306+
307+
308+ # Motors
309+
310+ def config_motor (self , en1 , in1 , in2 , en2 = None , in3 = None , in4 = None ):
311+ self ._add_pin (ComponentPins .MOTOR , en1 )
312+ self ._add_pin (ComponentPins .MOTOR , in1 )
313+ self ._add_pin (ComponentPins .MOTOR , in2 )
314+ if en2 == None or in3 == None or in4 == None :
315+ self ._send (f"register::mo::{ en1 } ::{ in1 } ::{ in2 } " )
316+ else :
317+ self ._add_pin (ComponentPins .MOTOR , en2 )
318+ self ._add_pin (ComponentPins .MOTOR , in3 )
319+ self ._add_pin (ComponentPins .MOTOR , in4 )
320+ self ._send (f"register::mo::{ en1 } ::{ in1 } ::{ in2 } ::{ en2 } ::{ in3 } ::{ in4 } " )
321+
322+ def move_motor (self , which_motor , direction , speed ):
323+ pin = self .pins [ComponentPins .MOTOR ][0 ]
324+ direction_num = "1" if direction == "clockwise" else "2"
325+ self ._send (f"write::mo::{ pin } ::{ which_motor } ::{ speed } ::{ direction_num } " )
326+
327+
328+ def stop_motor (self , which_motor ):
329+ pin = self .pins [ComponentPins .MOTOR ][0 ]
330+ self ._send (f"write::mo::{ pin } ::{ which_motor } ::0::3" )
331+
200332 # NEO PIXELS
201333
202334 def config_rgb_strip (self , pin , count , colorOrderString , brightness ):
@@ -223,6 +355,18 @@ def rgb_strip_show_all(self):
223355 pin = self .pins [ComponentPins .RGB_LED_STRIP ][0 ]
224356 self ._send (f"write::leds::{ pin } ::1" )
225357
358+ # Passive Buzzer
359+
360+ def config_passive_buzzer (self , pin ):
361+ self ._add_pin (ComponentPins .PASSIVE_BUZZER , pin )
362+ self ._send (f"register::bu::{ pin } " )
363+
364+ def play_passive_buzzer (self , pin , note ):
365+ self ._send (f"write::bu::{ pin } ::{ note } " )
366+
367+ def turn_off_buzzer (self , pin ):
368+ self ._send (f"write::bu::{ pin } ::0" )
369+
226370 # Helpers
227371
228372 def rgb_to_hex (self , red , green , blue ):
0 commit comments