Package PyMata :: Module pymata
[hide private]
[frames] | no frames]

Source Code for Module PyMata.pymata

  1  __author__ = 'Copyright (c) 2013 Alan Yorinks All rights reserved.' 
  2   
  3  """ 
  4  Copyright (c) 2013-14 Alan Yorinks All rights reserved. 
  5   
  6  This program is free software; you can redistribute it and/or 
  7  modify it under the terms of the GNU  General Public 
  8  License as published by the Free Software Foundation; either 
  9  version 3 of the License, or (at your option) any later version. 
 10   
 11  This library is distributed in the hope that it will be useful, 
 12  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 14  Lesser General Public License for more details. 
 15   
 16  You should have received a copy of the GNU Lesser General Public 
 17  License along with this library; if not, write to the Free Software 
 18  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
 19  """ 
 20   
 21  from collections import deque 
 22  import threading 
 23  import sys 
 24  import time 
 25  import os.path 
 26   
 27  import ino_uploader 
 28  from pymata_serial import PyMataSerial 
 29  from pymata_command_handler import PyMataCommandHandler 
 30   
 31  SCRIPT_PATH = os.path.dirname( __file__ ) 
 32  SKETCHES_DIR = SCRIPT_PATH + "/ArduinoSketch" 
 33  if not os.path.exists( SKETCHES_DIR ): 
 34      SKETCHES_DIR = SCRIPT_PATH + "/../ArduinoSketch"    # Assume library hasn't been installed 
 35   
 36  STANDARD_FIRMATA_DIR = SKETCHES_DIR + "/Firmata/examples/StandardFirmata" 
 37  STANDARD_FIRMATA_LIBS = [ 
 38      SKETCHES_DIR + "/Firmata" 
 39  ] 
 40   
 41  NOT_SO_STANDARD_FIRMATA_DIR = SKETCHES_DIR + "/NotSoStandardFirmata/examples/NotSoStandardFirmata" 
 42  NOT_SO_STANDARD_FIRMATA_LIBS = [ 
 43      SKETCHES_DIR + "/AdaEncoder", 
 44      SKETCHES_DIR + "/ByteBuffer", 
 45      SKETCHES_DIR + "/cbiface", 
 46      SKETCHES_DIR + "/cppfix", 
 47      SKETCHES_DIR + "/MemoryFree", 
 48      SKETCHES_DIR + "/NotSoStandardFirmata", 
 49      SKETCHES_DIR + "/ooPinChangeInt" 
 50  ] 
 51   
 52  # For report data formats refer to http://firmata.org/wiki/Protocol 
 53   
54 -class PyMata:
55 """ 56 This class contains the complete set of API methods that permit control of an Arduino 57 Micro-Controller utilizing Firmata or its derivatives. 58 59 For information about the Firmata protocol, refer to: http://firmata.org/wiki/Protocol 60 """ 61 # some state variables 62 HIGH = 1 # digital pin state high value 63 LOW = 0 # digital pin state low value 64 65 REPORTING_ENABLE = 1 # enable reporting for REPORT_ANALOG or REPORT_DIGITAL message sent to firmata 66 REPORTING_DISABLE = 0 # disable reporting for REPORT_ANALOG or REPORT_DIGITAL message sent to firmata 67 68 # Shared Resources - data structures, controlling mechanisms, and reference variables 69 70 # Commands and data received from Firmata via the serial interface are placed into the command deque. 71 # The pymata_command_handler class removes and processes this information. 72 _command_deque = deque() 73 74 # This is the instance reference to the _command_handler 75 _command_handler = None 76 77 # This is the instance reference to the communications port object 78 _arduino = None 79 80 # This is a thread lock to assure data integrity when reading or writing to the data response tables 81 # (defined in the CommandHandler class). It shared by the pymata class and the pymata_command_handler class. 82 _data_lock = threading.Lock() 83 84 # I2C command operation modes 85 I2C_WRITE = 0B00000000 86 I2C_READ = 0B00001000 87 I2C_READ_CONTINUOUSLY = 0B00010000 88 I2C_STOP_READING = 0B00011000 89 I2C_READ_WRITE_MODE_MASK = 0B00011000 90 91 # Tone commands 92 TONE_TONE = 0 # play a tone 93 TONE_NO_TONE = 1 # turn off tone 94 95 # pin modes - these will map to the command handler values so as to have just one set of data 96 INPUT = None 97 OUTPUT = None 98 ANALOG = None 99 PWM = None 100 SERVO = None 101 I2C = None 102 TONE = None 103 SONAR = None 104 IGNORE = None 105 ENCODER = None 106 DIGITAL = None 107 108 # each byte represents a digital port and its value contains the current port settings 109 digital_output_port_pins = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] 111 112 STANDARD_FIRMATA = ( STANDARD_FIRMATA_DIR, STANDARD_FIRMATA_LIBS ) 113 NOT_SO_STANDARD_FIRMATA = ( NOT_SO_STANDARD_FIRMATA_DIR, NOT_SO_STANDARD_FIRMATA_LIBS ) 114 115 #noinspection PyPep8Naming
116 - def __init__(self, port_id='/dev/ttyACM0', max_wait_time=30, 117 program_if_needed=True, board_model="uno", firmata_type=NOT_SO_STANDARD_FIRMATA ):
118 """ 119 The constructor tries to connect to an Arduino or Arduino compatible running 120 Firmata. If Firmata is not found on the Arduino, then we can optionally try to 121 program the Arduino with the Firmata sketch 122 @param port_id: Communications port specifier (COM3, /dev/ttyACM0, etc) 123 @param max_wait_time: Maximum time to wait when trying to connect to Firmata 124 @param program_if_needed: Attempt to upload the Firmata sketch if it's not found 125 on the Arduino. 126 @param board_model: The type of Arduino being used. This is only needed if the 127 board is to be programmed. Run 'ino list-models' at the command line for a 128 list of available boards. 129 @param firmata_type: A directory containing the firmata sketch, and a list of supporting 130 libs that are used when uploading firmata 131 """ 132 133 if not self.connect_to_firmata( port_id, max_wait_time ): 134 135 able_to_connect = False 136 137 if program_if_needed: 138 if not self.upload_firmata_sketch( port_id, board_model, firmata_type ): 139 140 raise Exception( "Unable to upload Firmata sketch" ) 141 142 else: 143 144 able_to_connect = self.connect_to_firmata( port_id, max_wait_time ) 145 146 if not able_to_connect: 147 148 raise Exception( "Unable to connect to Firmata" )
149
150 - def connect_to_firmata( self, port_id, max_wait_time ):
151 """ 152 This routine instantiates the entire interface. It starts the operational threads for the serial 153 interface as well as for the command handler. 154 @param port_id: Communications port specifier (COM3, /dev/ttyACM0, etc) 155 @return: True if the connection was successful and False otherwise 156 """ 157 # Currently only serial communication over USB is supported, but in the future 158 # wifi and other transport mechanism support is anticipated 159 160 # Instantiate the serial support class 161 self._arduino = PyMataSerial(port_id, self._command_deque) 162 163 # Attempt opening communications with the Arduino micro-controller 164 self._arduino.open() 165 time.sleep(1) 166 167 # Start the data receive thread 168 self._arduino.start() 169 170 # Instantiate the command handler 171 self._command_handler = PyMataCommandHandler(self._arduino, self._command_deque, self._data_lock) 172 173 ######################################################################## 174 # constants defined locally from values contained in the command handler 175 ######################################################################## 176 177 # pin modes 178 self.INPUT = self._command_handler.INPUT 179 self.OUTPUT = self._command_handler.OUTPUT 180 self.PWM = self._command_handler.PWM 181 self.SERVO = self._command_handler.SERVO 182 self.I2C = self._command_handler.I2C 183 self.TONE = self._command_handler.TONE 184 self.IGNORE = self._command_handler.IGNORE 185 self.ENCODER = self._command_handler.ENCODER 186 self.DIGITAL = self._command_handler.DIGITAL 187 self.SONAR = self._command_handler.SONAR 188 189 # Data latch state constants to be used when accessing data returned from get_latch_data methods. 190 # The get_latch data methods return [pin_number, latch_state, latched_data, time_stamp] 191 # These three constants define possible values for the second item in the list, latch_state 192 193 # this pin will be ignored for latching - table initialized with this value 194 self.LATCH_IGNORE = self._command_handler.LATCH_IGNORE 195 # When the next pin value change is received for this pin, if it matches the latch criteria 196 # the data will be latched. 197 self.LATCH_ARMED = self._command_handler.LATCH_ARMED 198 # Data has been latched. Read the data to re-arm the latch. 199 self.LATCH_LATCHED = self._command_handler.LATCH_LATCHED 200 201 # 202 # These constants are used when setting a data latch. 203 # Latch threshold types 204 # 205 self.DIGITAL_LATCH_HIGH = self._command_handler.DIGITAL_LATCH_HIGH 206 self.DIGITAL_LATCH_LOW = self._command_handler.DIGITAL_LATCH_LOW 207 208 self.ANALOG_LATCH_GT = self._command_handler.ANALOG_LATCH_GT 209 self.ANALOG_LATCH_LT = self._command_handler.ANALOG_LATCH_LT 210 self.ANALOG_LATCH_GTE = self._command_handler.ANALOG_LATCH_GTE 211 self.ANALOG_LATCH_LTE = self._command_handler.ANALOG_LATCH_LTE 212 213 # constants to be used to parse the data returned from calling 214 # get_X_latch_data() 215 216 self.LATCH_PIN = 0 217 self.LATCH_STATE = 1 218 self.LATCHED_DATA = 2 219 self.LATCHED_TIME_STAMP = 3 220 221 # Start the command processing thread 222 self._command_handler.start() 223 224 # Command handler should now be prepared to receive replies from the Arduino, so go ahead 225 # detect the Arduino board 226 227 print 'Please wait while Arduino is being detected. This can take up to {0} seconds ...'.format( max_wait_time ) 228 229 # perform board auto discovery 230 231 if not self._command_handler.auto_discover_board( max_wait_time ): 232 # board was not found so shutdown 233 print "Board Auto Discovery Failed!" 234 self._command_handler.stop() 235 self._arduino.stop() 236 self._command_handler.join() 237 self._arduino.join() 238 239 return False 240 241 else: 242 243 return True
244
245 - def upload_firmata_sketch( self, port_id, board_model, firmata_type ):
246 """ 247 Uses the Ino library to upload Firmata to the Arduino attached to the given serial port 248 @param port_id: The serial port to use 249 """ 250 251 firmata_dir, firmata_libs = firmata_type 252 return ino_uploader.upload( firmata_dir, port_id, board_model, firmata_libs )
253
254 - def analog_mapping_query(self):
255 """ 256 Send an analog mapping query message via sysex. Client retrieves the results with a 257 call to get_analog_mapping_request_results() 258 """ 259 self._command_handler.send_sysex(self._command_handler.ANALOG_MAPPING_QUERY, None)
260
261 - def analog_read(self, pin):
262 """ 263 Retrieve the last analog data value received for the specified pin. 264 @param pin: Selected pin 265 @return: The last value entered into the analog response table. 266 """ 267 self._data_lock.acquire(True) 268 data = self._command_handler.analog_response_table[pin][self._command_handler.RESPONSE_TABLE_PIN_DATA_VALUE] 269 self._data_lock.release() 270 return data
271
272 - def analog_write(self, pin, value):
273 """ 274 Set the specified pin to the specified value. 275 @param pin: Pin number 276 @param value: Pin value 277 @return: No return value 278 """ 279 280 if self._command_handler.ANALOG_MESSAGE + pin < 0xf0: 281 command = [self._command_handler.ANALOG_MESSAGE + pin, value & 0x7f, value >> 7] 282 self._command_handler.send_command(command) 283 else: 284 self.extended_analog(pin, value)
285
286 - def capability_query(self):
287 """ 288 Send a Firmata capability query message via sysex. Client retrieves the results with a 289 call to get_capability_query_results() 290 The Arduino can be rather slow in responding to this command. For 291 the Mega 2560 R3 it has taken up to 25 seconds for a response. 292 """ 293 self._command_handler.send_sysex(self._command_handler.CAPABILITY_QUERY, None)
294
295 - def close(self):
296 """ 297 This method will close the transport (serial port) and exit 298 @return: No return value, but sys.exit(0) is called. 299 """ 300 self.reset( reset_sleep_time=0.1 ) 301 302 self._command_handler.stop() 303 self._arduino.stop() 304 self._command_handler.join() 305 self._arduino.join() 306 307 print "PyMata close(): Calling sys.exit(0): Hope to see you soon!" 308 sys.exit(0)
309
310 - def digital_read(self, pin):
311 """ 312 Retrieve the last digital data value received for the specified pin. 313 NOTE: This command will return values for digital, pwm, etc, pin types 314 @param pin: Selected pin 315 @return: The last value entered into the digital response table. 316 """ 317 self._data_lock.acquire(True) 318 data = self._command_handler.digital_response_table[pin][self._command_handler.RESPONSE_TABLE_PIN_DATA_VALUE] 319 self._data_lock.release() 320 return data
321
322 - def digital_write(self, pin, value):
323 """ 324 Set the specified pin to the specified value. 325 @param pin: pin number 326 @param value: pin value 327 @return: No return value 328 """ 329 # The command value is not a fixed value, but needs to be calculated using the 330 # pin's port number 331 # 332 # 333 port = pin / 8 334 335 calculated_command = self._command_handler.DIGITAL_MESSAGE + port 336 mask = 1 << (pin % 8) 337 # Calculate the value for the pin's position in the port mask 338 if value == 1: 339 self.digital_output_port_pins[port] |= mask 340 341 else: 342 self.digital_output_port_pins[port] &= ~mask 343 344 # Assemble the command 345 command = (calculated_command, self.digital_output_port_pins[port] & 0x7f, 346 self.digital_output_port_pins[port] >> 7) 347 348 self._command_handler.send_command(command)
349 350 351
352 - def disable_analog_reporting(self, pin):
353 """ 354 Disables analog reporting for a single analog pin. 355 @param pin: Analog pin number. For example for A0, the number is 0. 356 @return: No return value 357 """ 358 command = [self._command_handler.REPORT_ANALOG + pin, self.REPORTING_DISABLE] 359 self._command_handler.send_command(command)
360
361 - def disable_digital_reporting(self, pin):
362 """ 363 Disables digital reporting. By turning reporting off for this pin, reporting 364 is disabled for all 8 bits in the "port" - 365 @param pin: Pin and all pins for this port 366 @return: No return value 367 """ 368 port = pin / 8 369 command = [self._command_handler.REPORT_DIGITAL + port, self.REPORTING_DISABLE] 370 self._command_handler.send_command(command)
371
372 - def enable_analog_reporting(self, pin):
373 """ 374 Enables analog reporting. By turning reporting on for a single pin, 375 @param pin: Analog pin number. For example for A0, the number is 0. 376 @return: No return value 377 """ 378 command = [self._command_handler.REPORT_ANALOG + pin, self.REPORTING_ENABLE] 379 self._command_handler.send_command(command)
380
381 - def enable_digital_reporting(self, pin):
382 """ 383 Enables digital reporting. By turning reporting on for all 8 bits in the "port" - 384 this is part of Firmata's protocol specification. 385 @param pin: Pin and all pins for this port 386 @return: No return value 387 """ 388 port = pin / 8 389 command = [self._command_handler.REPORT_DIGITAL + port, self.REPORTING_ENABLE] 390 self._command_handler.send_command(command)
391 392
393 - def encoder_config(self, pin_a, pin_b):
394 """ 395 This command enables the rotary encoder (2 pin + ground) and will 396 enable encoder reporting. 397 398 NOTE: This command is not currently part of standard arduino firmata, but is provided for legacy 399 support of CodeShield on an Arduino UNO. 400 @param pin_a: Encoder pin 1. 401 @param pin_b: Encoder pin 2. 402 @return: No return value 403 """ 404 data = [pin_a, pin_b] 405 self._command_handler.digital_response_table[pin_a][self._command_handler.RESPONSE_TABLE_MODE] \ 406 = self.ENCODER 407 self._command_handler.digital_response_table[pin_b][self._command_handler.RESPONSE_TABLE_MODE] \ 408 = self.ENCODER 409 self._command_handler.send_sysex(self._command_handler.ENCODER_CONFIG, data)
410
411 - def extended_analog(self, pin, data):
412 """ 413 This method will send an extended data analog output command to the selected pin 414 @param pin: 0 - 127 415 @param data: 0 - 0xfffff 416 """ 417 analog_data = [pin, data & 0x7f, (data >> 7) & 0x7f, data >> 14] 418 self._command_handler.send_sysex(self._command_handler.EXTENDED_ANALOG, analog_data)
419
420 - def get_analog_latch_data(self, pin):
421 """ 422 A list is returned containing the latch state for the pin, the latched value, and the time stamp 423 [pin_num, latch_state, latched_value, time_stamp] 424 If the the latch state is LATCH_LATCHED, the table is reset (data and timestamp set to zero) 425 @param pin: Pin number. 426 @return: [pin, latch_state, latch_data_value, time_stamp] 427 """ 428 return self._command_handler.get_analog_latch_data(pin)
429
431 """ 432 Call this method after calling analog_mapping_query() to retrieve its results 433 @return: raw data returned by firmata 434 """ 435 return self._command_handler.analog_mapping_query_results
436
438 """ 439 This method returns a list of lists representing the current pin mode and 440 associated data values for all analog pins. 441 All configured pin types, both input and output will be listed. Output pin data will contain zero. 442 @return: The last update of the digital response table 443 """ 444 return self._command_handler.get_analog_response_table()
445
447 """ 448 Retrieve the data returned by a previous call to capability_query() 449 @return: Raw capability data returned by firmata 450 """ 451 return self._command_handler.capability_query_results
452
453 - def get_digital_latch_data(self, pin):
454 """ 455 A list is returned containing the latch state for the pin, the latched value, and the time stamp 456 [pin_num, latch_state, latched_value, time_stamp] 457 If the the latch state is LATCH_LATCHED, the table is reset (data and timestamp set to zero) 458 @param pin: Pin number. 459 @return: [pin, latch_state, latch_data_value, time_stamp] 460 """ 461 return self._command_handler.get_digital_latch_data(pin)
462
464 """ 465 This method returns a list of lists representing the current pin mode 466 and associated data for all digital pins. 467 All pin types, both input and output will be listed. Output pin data will contain zero. 468 @return: The last update of the digital response table 469 """ 470 return self._command_handler.get_digital_response_table()
471
472 - def get_firmata_version(self):
473 """ 474 Retrieve the firmata version information returned by a previous call to refresh_report_version() 475 @return: Firmata_version list [major, minor] or None 476 """ 477 return self._command_handler.firmata_version
478 479
481 """ 482 Retrieve the firmware id information returned by a previous call to refresh_report_firmware() 483 @return: Firmata_firmware list [major, minor, file_name] or None 484 """ 485 return self._command_handler.firmata_firmware
486
488 """ 489 This method returns the results of a previous call to pin_state_query() and then resets 490 the pin state query data to None 491 492 @return: Raw pin state query data 493 """ 494 r_data = self._command_handler.last_pin_query_results 495 self._command_handler.last_pin_query_results = [] 496 return r_data
497 498 #noinspection PyMethodMayBeStatic
499 - def get_pymata_version(self):
500 """ 501 Returns the PyMata version number in a list: [Major Number, Minor Number] 502 503 @return: 504 """ 505 return [1, 5]
506 507 508 # noinspection PyMethodMayBeStatic
509 - def get_sonar_data(self):
510 """ 511 Retrieve Ping (HC-SR04 type) data. The data is presented as a dictionary. 512 The 'key' is the trigger pin specified in sonar_config() and the 'data' is the 513 current measured distance (in centimeters) 514 for that pin. If there is no data, the value is set to IGNORE (127). 515 516 @return: active_sonar_map 517 """ 518 return self._command_handler.active_sonar_map
519 520
521 - def i2c_config(self, read_delay_time=0, pin_type=None, clk_pin=0, data_pin=0):
522 """ 523 NOTE: THIS METHOD MUST BE CALLED BEFORE ANY I2C REQUEST IS MADE 524 This method initializes Firmata for I2c operations. 525 It allows setting of a read time delay amount, and to optionally track 526 the pins as I2C in the appropriate response table. 527 To track pins: Set the pin_type to ANALOG or DIGITAL and provide the pin numbers. 528 If using ANALOG, pin numbers use the analog number, for example A4: use 4. 529 530 @param read_delay_time: an optional parameter, default is 0 531 @param pin_type: ANALOG or DIGITAL to select response table type to track pin numbers 532 @param clk_pin: pin number (see comment above). 533 @param data_pin: pin number (see comment above). 534 @return: No Return Value 535 """ 536 data = [read_delay_time & 0x7f, read_delay_time >> 7] 537 self._command_handler.send_sysex(self._command_handler.I2C_CONFIG, data) 538 539 # If pin type is set, set pin mode in appropriate response table for these pins 540 if pin_type: 541 if pin_type == self.DIGITAL: 542 self._command_handler.digital_response_table[clk_pin][self._command_handler.RESPONSE_TABLE_MODE] \ 543 = self.I2C 544 self._command_handler.digital_response_table[data_pin][self._command_handler.RESPONSE_TABLE_MODE] \ 545 = self.I2C 546 else: 547 self._command_handler.analog_response_table[clk_pin][self._command_handler.RESPONSE_TABLE_MODE] \ 548 = self.I2C 549 self._command_handler.analog_response_table[data_pin][self._command_handler.RESPONSE_TABLE_MODE] \ 550 = self.I2C
551
552 - def i2c_read(self, address, register, number_of_bytes, read_type):
553 """ 554 This method requests the read of an i2c device. Results are retrieved by a call to 555 i2c_get_read_data() 556 @param address: i2c device address 557 @param register: register number (can be set to zero) 558 @param number_of_bytes: number of bytes expected to be returned 559 @param read_type: I2C_READ or I2C_READ_CONTINUOUSLY 560 """ 561 data = [address, read_type, register & 0x7f, register >> 7, 562 number_of_bytes & 0x7f, number_of_bytes >> 7] 563 self._command_handler.send_sysex(self._command_handler.I2C_REQUEST, data)
564
565 - def i2c_write(self, address, *args):
566 """ 567 Write data to an i2c device. 568 @param address: i2c device address 569 @param args: A variable number of bytes to be sent to the device 570 """ 571 data = [address, self.I2C_WRITE] 572 for item in args: 573 data.append(item) 574 self._command_handler.send_sysex(self._command_handler.I2C_REQUEST, data)
575
576 - def i2c_stop_reading(self, address):
577 """ 578 This method stops an I2C_READ_CONTINUOUSLY operation for the i2c device address specified. 579 @param address: address of i2c device 580 """ 581 data = [address, self.I2C_STOP_READING] 582 self._command_handler.send_sysex(self._command_handler.I2C_REQUEST, data)
583
584 - def i2c_get_read_data(self, address):
585 """ 586 This method retrieves the i2c read data as the result of an i2c_read() command. 587 @param address: i2c device address 588 @return: raw data read from device 589 """ 590 if self._command_handler.i2c_map.has_key(address): 591 return self._command_handler.i2c_map[address]
592
593 - def pin_state_query(self, pin):
594 """ 595 This method issues a pin state query command. Data returned is retrieved via 596 a call to get_pin_state_query_results() 597 @param pin: pin number 598 """ 599 self._command_handler.send_sysex(self._command_handler.PIN_STATE_QUERY, [pin])
600
601 - def play_tone(self, pin, tone_command, frequency, duration):
602 """ 603 This method will call the Tone library for the selected pin. 604 If the tone command is set to TONE_TONE, then the specified tone will be played. 605 Else, if the tone command is TONE_NO_TONE, then any currently playing tone will be disabled. 606 It is intended for a future release of Arduino Firmata 607 @param pin: Pin number 608 @param tone_command: Either TONE_TONE, or TONE_NO_TONE 609 @param frequency: Frequency of tone 610 @param duration: Duration of tone in milliseconds 611 @return: No return value 612 """ 613 614 # convert the integer values to bytes 615 if tone_command == self.TONE_TONE: 616 # duration is specified 617 if duration: 618 data = [tone_command, pin, frequency & 0x7f, frequency >> 7, duration & 0x7f, frequency >> 7] 619 620 else: 621 data = [tone_command, pin, frequency & 0x7f, frequency >> 7] 622 623 self._command_handler.digital_response_table[pin][self._command_handler.RESPONSE_TABLE_MODE] = \ 624 self.TONE 625 # turn off tone 626 else: 627 data = [tone_command, pin] 628 self._command_handler.send_sysex(self._command_handler.TONE_PLAY, data)
629
630 - def refresh_report_version(self):
631 """ 632 This method will query firmata for the report version. 633 Retrieve the report version via a call to get_firmata_version() 634 """ 635 self._command_handler.send_sysex(self._command_handler.REPORT_VERSION, None)
636
637 - def refresh_report_firmware(self):
638 """ 639 This method will query firmata to report firmware. Retrieve the report via a 640 call to get_firmata_firmware_version() 641 """ 642 self._command_handler.send_sysex(self._command_handler.REPORT_FIRMWARE, None)
643
644 - def reset(self,reset_sleep_time=2):
645 """ 646 This command sends a reset message to the Arduino. The response tables will be reinitialized 647 @return: No return value. 648 """ 649 # set all output pins to a value of 0 650 for pin in range(0, self._command_handler.total_pins_discovered): 651 if self._command_handler.digital_response_table[self._command_handler.RESPONSE_TABLE_MODE] \ 652 == self.PWM: 653 self.analog_write(pin, 0) 654 elif self._command_handler.digital_response_table[self._command_handler.RESPONSE_TABLE_MODE] \ 655 == self.SERVO: 656 self.analog_write(pin, 0) 657 else: 658 self.digital_write(pin, 0) 659 self._command_handler.system_reset(reset_sleep_time)
660
661 - def set_analog_latch(self, pin, threshold_type, threshold_value):
662 """ 663 This method "arms" an analog pin for its data to be latched and saved in the latching table 664 @param pin: Analog pin number (value following an 'A' designator, i.e. A5 = 5 665 @param threshold_type: ANALOG_LATCH_GT | ANALOG_LATCH_LT | ANALOG_LATCH_GTE | ANALOG_LATCH_LTE 666 @param threshold_value: numerical value - between 0 and 1023 667 @return: True if successful, False if parameter data is invalid 668 """ 669 if self.ANALOG_LATCH_GT <= threshold_type <= self.ANALOG_LATCH_LTE: 670 if 0 <= threshold_value <= 1023: 671 self._command_handler.set_analog_latch(pin, threshold_type, threshold_value) 672 return True 673 else: 674 return False
675
676 - def set_digital_latch(self, pin, threshold_type):
677 """ 678 This method "arms" a digital pin for its data to be latched and saved in the latching table 679 @param pin: Digital pin number 680 @param threshold_type: DIGITAL_LATCH_HIGH | DIGITAL_LATCH_LOW 681 @return: True if successful, False if parameter data is invalid 682 """ 683 if 0 <= threshold_type <= 1: 684 self._command_handler.set_digital_latch(pin, threshold_type) 685 return True 686 else: 687 return False
688
689 - def set_pin_mode(self, pin, mode, pin_type):
690 """ 691 This method sets a pin to the desired pin mode for the pin_type. 692 It automatically enables data reporting. 693 NOTE: DO NOT CALL THIS METHOD FOR I2C. See i2c_config(). 694 @param pin: Pin number (for analog use the analog number, for example A4: use 4) 695 @param mode: INPUT, OUTPUT, PWM, SERVO, ENCODER or TONE 696 @param pin_type: ANALOG or DIGITAL 697 @return: No return value 698 """ 699 command = [self._command_handler.SET_PIN_MODE, pin, mode] 700 self._command_handler.send_command(command) 701 #enable reporting for input pins 702 if mode == self.INPUT: 703 if pin_type == self.ANALOG: 704 705 # set analog response table to show this pin is an input pin 706 707 self._command_handler.analog_response_table[pin][self._command_handler.RESPONSE_TABLE_MODE] = \ 708 self.INPUT 709 self.enable_analog_reporting(pin) 710 # if not analog it has to be digital 711 else: 712 self._command_handler.digital_response_table[pin][self._command_handler.RESPONSE_TABLE_MODE] = \ 713 self.INPUT 714 self.enable_digital_reporting(pin) 715 716 else: # must be output - so set the tables accordingly 717 if pin_type == self.ANALOG: 718 self._command_handler.analog_response_table[pin][self._command_handler.RESPONSE_TABLE_MODE] = mode 719 else: 720 self._command_handler.digital_response_table[pin][self._command_handler.RESPONSE_TABLE_MODE] = mode
721
722 - def set_sampling_interval(self, interval):
723 """ 724 This method sends the desired sampling interval to Firmata. 725 Note: Standard Firmata will ignore any interval less than 10 milliseconds 726 @param interval: Integer value for desired sampling interval in milliseconds 727 @return: No return value. 728 """ 729 data = [interval & 0x7f, interval >> 7] 730 self._command_handler.send_sysex(self._command_handler.SAMPLING_INTERVAL, data)
731 732
733 - def servo_config(self, pin, min_pulse=544, max_pulse=2400):
734 """ 735 Configure a pin as a servo pin. Set pulse min, max in ms. 736 @param pin: Servo Pin. 737 @param min_pulse: Min pulse width in ms. 738 @param max_pulse: Max pulse width in ms. 739 @return: No return value 740 """ 741 self.set_pin_mode(pin, self.SERVO, self.OUTPUT) 742 command = [self._command_handler.SERVO_CONFIG, pin, min_pulse & 0x7f, min_pulse >> 7, max_pulse & 0x7f, 743 max_pulse >> 7] 744 745 self._command_handler.send_command(command)
746
747 - def sonar_config(self, trigger_pin, echo_pin, ping_interval=50):
748 """ 749 Configure the pins, and ping interval for an HC-SR04 type device. 750 Single pin configuration may be used. To do so, set both the trigger and echo pins to the same value. 751 Up to a maximum of 6 SONAR devices is supported 752 If the maximum is exceeded a message is sent to the console and the request is ignored. 753 NOTE: data is measured in centimeters 754 :param trigger_pin: The pin number of for the trigger (transmitter). 755 :param echo_pin: The pin number for the received echo. 756 :param ping_interval: Minimum interval between pings. Lowest number to use is 33 ms.Max is 127 757 """ 758 data = [trigger_pin, echo_pin, ping_interval] 759 self.set_pin_mode(trigger_pin, self.SONAR, self.INPUT) 760 self.set_pin_mode(echo_pin, self.SONAR, self.INPUT) 761 # update the ping data map for this pin 762 if len(self._command_handler.active_sonar_map) > 6: 763 print "sonar_config: maximum number of devices assigned - ignoring request" 764 return 765 else: 766 self._data_lock.acquire(True) 767 self._command_handler.active_sonar_map[trigger_pin] = self.IGNORE 768 self._data_lock.release() 769 770 self._command_handler.send_sysex(self._command_handler.SONAR_CONFIG, data)
771