Skip to content

Commit

Permalink
Merge cf822e5 into 265a6d6
Browse files Browse the repository at this point in the history
  • Loading branch information
Vido committed Jul 6, 2015
2 parents 265a6d6 + cf822e5 commit 7201238
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 15 deletions.
55 changes: 40 additions & 15 deletions pingo/arduino/firmata.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@
Works on Arduino
"""

import time
import platform

import pingo
from pingo.board import Board, AnalogInputCapable, DigitalPin, AnalogPin
from pingo.board import Board, DigitalPin, AnalogPin, PwmPin
from pingo.board import AnalogInputCapable, PwmOutputCapable
from pingo.detect import detect
from util_firmata import pin_list_to_board_dict

PyMata = None

PIN_STATES = {
False: 0,
Expand All @@ -35,11 +40,11 @@ def get_arduino():
return ArduinoFirmata(serial_port)


class ArduinoFirmata(Board, AnalogInputCapable):
class ArduinoFirmata(Board, AnalogInputCapable, PwmOutputCapable):

def __init__(self, port=None):
try:
from PyMata.pymata import PyMata
from PyMata.pymata import PyMata as PyMata # noqa
except ImportError:
msg = 'pingo.arduino.Arduino requires PyMata installed'
raise ImportError(msg)
Expand All @@ -48,14 +53,18 @@ def __init__(self, port=None):
self.port = port
self.firmata_client = PyMata(self.port, verbose=VERBOSE)

detected_digital_pins = len(self.firmata_client._command_handler.digital_response_table)
detected_analog_pins = len(self.firmata_client._command_handler.analog_response_table)
self.firmata_client.capability_query()
time.sleep(10) # TODO: Find a small and safe value
capability_query_results = self.firmata_client.get_capability_query_results()
capability_dict = pin_list_to_board_dict(capability_query_results)

self._add_pins(
[DigitalPin(self, location)
for location in range(detected_digital_pins)] +
for location in capability_dict['digital']] +
[PwmPin(self, location)
for location in capability_dict['pwm']] +
[AnalogPin(self, 'A%s' % location, resolution=10)
for location in range(detected_analog_pins)]
for location in capability_dict['analog']]
)

def cleanup(self):
Expand All @@ -77,6 +86,22 @@ def _set_digital_mode(self, pin, mode):
self.firmata_client.DIGITAL
)

def _set_analog_mode(self, pin, mode):
pin_id = int(pin.location[1:])
self.firmata_client.set_pin_mode(
pin_id,
self.firmata_client.INPUT,
self.firmata_client.ANALOG
)

def _set_pwm_mode(self, pin, mode):
pin_id = int(pin.location)
self.firmata_client.set_pin_mode(
pin_id,
self.firmata_client.PWM,
self.firmata_client.DIGITAL
)

def _get_pin_state(self, pin):
_state = self.firmata_client.digital_read(pin.location)
if _state == self.firmata_client.HIGH:
Expand All @@ -89,14 +114,14 @@ def _set_pin_state(self, pin, state):
PIN_STATES[state]
)

def _set_analog_mode(self, pin, mode):
pin_id = int(pin.location[1:])
self.firmata_client.set_pin_mode(
pin_id,
self.firmata_client.INPUT,
self.firmata_client.ANALOG
)

def _get_pin_value(self, pin):
pin_id = int(pin.location[1:])
return self.firmata_client.analog_read(pin_id)

def _set_pwm_duty_cycle(self, pin, value):
pin_id = int(pin.location)
firmata_value = int(value * 255)
return self.firmata_client.analog_write(pin_id, firmata_value)

def _set_pwm_frequency(self, pin, value):
raise NotImplementedError
83 changes: 83 additions & 0 deletions pingo/arduino/util_firmata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"""
Copied from:
https://github.com/tino/pyFirmata/blob/master/pyfirmata/util.py
"""


def pin_list_to_board_dict(capability_query_response):
"""
Capability Response codes:
INPUT: 0, 1
OUTPUT: 1, 1
ANALOG: 2, 10
PWM: 3, 8
SERV0: 4, 14
I2C: 6, 1
"""

board_dict = {
'digital': [],
'analog': [],
'pwm': [],
'servo': [],
'i2c': [],
'disabled': [],
}

# i split pins of list:
pin_list = [[]]
for b in capability_query_response:
if b == 127:
pin_list.append([])
else:
pin_list[-1].append(b)

# Finds the capability of each pin
for i, pin in enumerate(pin_list):
if not pin:
board_dict['disabled'] += [i]
board_dict['digital'] += [i]
continue

for j, _ in enumerate(pin):
# Iterate over evens
if j % 2 == 0:
# This is safe. try: range(10)[5:50]
if pin[j:j + 4] == [0, 1, 1, 1]:
board_dict['digital'] += [i]

if pin[j:j + 2] == [2, 10]:
board_dict['analog'] += [i]

if pin[j:j + 2] == [3, 8]:
board_dict['pwm'] += [i]

if pin[j:j + 2] == [4, 14]:
board_dict['servo'] += [i]

if pin[j:j + 2] == [6, 1]:
board_dict['i2c'] += [i]

# We have to deal with analog pins:
# - (14, 15, 16, 17, 18, 19)
# + (0, 1, 2, 3, 4, 5)
diff = set(board_dict['digital']) - set(board_dict['analog'])
board_dict['analog'] = [n for n, _ in enumerate(board_dict['analog'])]

# Digital pin problems:
# - (2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)
# + (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)

board_dict['digital'] = [n for n, _ in enumerate(diff)]
# Based on lib Arduino 0017
board_dict['servo'] = board_dict['digital']

# Turn lists into tuples
# Using dict for Python 2.6 compatibility
board_dict = dict([
(key, tuple(value))
for key, value
in board_dict.items()
])

return board_dict

0 comments on commit 7201238

Please sign in to comment.