From d7b5b616fb7371089988d7d81bb9292cb4815d1d Mon Sep 17 00:00:00 2001 From: Sayamindu Dasgupta Date: Sun, 13 Dec 2009 16:55:35 +0000 Subject: Add Arduino support (no localization support yet) --- diff --git a/firmata.py b/firmata.py new file mode 100755 index 0000000..756c714 --- /dev/null +++ b/firmata.py @@ -0,0 +1,167 @@ +#! /usr/bin/env python + +""" +Python API for the Firmata protocol +Copyright (C) 2008 laboratorio (info@laboratorio.us) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +""" + +__version__ = "0.3" + +import time +import serial + +DIGITAL_MESSAGE = 0x90 # send data for a digital port +ANALOG_MESSAGE = 0xE0 # send data for an analog pin (or PWM) +REPORT_ANALOG = 0xC0 # enable analog input by pin # +REPORT_DIGITAL = 0xD0 # enable digital input by port +SET_PIN_MODE = 0xF4 # set a pin to INPUT/OUTPUT/PWM/etc +REPORT_VERSION = 0xF9 # report firmware version +SYSTEM_RESET = 0xFF # reset from MIDI +START_SYSEX = 0xF0 # start a MIDI SysEx message +END_SYSEX = 0xF7 # end a MIDI SysEx message + +# pin modes +INPUT = 0 +OUTPUT = 1 +PWM = 2 +SERVO = 3 + +LOW = 0 +HIGH = 1 +MAX_DATA_BYTES = 32 + +class Arduino: + + def __init__(self, port, baudrate=115200): + + self.serial = serial.Serial(port, baudrate, bytesize=8, timeout=2) + + self.wait_for_data = 0 + self.exec_multibyte_cmd = 0 + self.multibyte_channel = 0 + self.stored_input_data = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0 ] + self.parsing_sysex = False + self.sysex_bytes_read = 0 + self.digital_output_data = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + self.digital_input_data = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + self.analog_input_data = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + self.major_version = 0 + self.minor_version = 0 + self.__report() + + def __str__(self): + return "Arduino: %s" % self.serial.port + + def pin_mode(self, pin, mode): + """Setting mode to pin""" + self.serial.write(chr(SET_PIN_MODE)) + self.serial.write(chr(pin)) + self.serial.write(chr(mode)) + + def digital_read(self, pin): + """Reading from digital pin""" + return (self.digital_input_data[pin >> 3] >> (pin & 0x07)) & 0x01 + + def digital_write(self, pin, value): + """Writing to a digital pin""" + + port_number = (pin >> 3) & 0x0F + + if value == 0: + self.digital_output_data[port_number] = self.digital_output_data[port_number] & ~(1 << (pin & 0x07)) + else: + self.digital_output_data[port_number] = self.digital_output_data[port_number] | (1 << (pin & 0x07)) + + self.serial.write(chr(DIGITAL_MESSAGE | port_number)) + self.serial.write(chr(self.digital_output_data[port_number] & 0x7F)) + self.serial.write(chr(self.digital_output_data[port_number] >> 7)) + + def analog_read(self, pin): + """Reading from analog pin""" + return self.analog_input_data[pin] + + def analog_write(self, pin, value): + """Writing to a analog pin""" + self.serial.write(chr(ANALOG_MESSAGE | (pin & 0x0F))) + self.serial.write(chr(value & 0x7F)) + self.serial.write(chr(value >> 7)) + + def set_version(self, major, minor): + """Setting a minor and major version""" + self.major_version = major + self.minor_version = minor + + def available(self): + """Checking serial connection status""" + return self.serial.isOpen() + + def delay(self, secs): + """Waiting in seconds""" + time.sleep(secs) + + def parse(self): + """Preparing the data to be handled""" + data = self.serial.read() + if data != "": + self.__process(ord(data)) + + def __process(self, input_data): + """Handling input data""" + command = None + + if self.parsing_sysex: + if input_data == END_SYSEX: + self.parsing_sysex = False + else: + self.stored_input_data[self.sysex_bytes_read] = input_data + self.sysex_bytes_read += 1 + + elif self.wait_for_data > 0 and input_data < 128: + self.wait_for_data -= 1 + self.stored_input_data[self.wait_for_data] = input_data + + if self.exec_multibyte_cmd != 0 and self.wait_for_data == 0: + if self.exec_multibyte_cmd == DIGITAL_MESSAGE: + self.digital_input_data[self.multibyte_channel] = (self.stored_input_data[0] << 7) + self.stored_input_data[1] + elif self.exec_multibyte_cmd == ANALOG_MESSAGE: + self.analog_input_data[self.multibyte_channel] = (self.stored_input_data[0] << 7) + self.stored_input_data[1] + elif self.exec_multibyte_cmd == REPORT_VERSION: + self.set_version(self.stored_input_data[1], self.stored_input_data[0]) + else: + if input_data < 0xF0: + command = input_data & 0xF0 + self.multibyte_channel = input_data & 0x0F + else: + command = input_data # commands in the 0xF* range don't use channel data + + if command == DIGITAL_MESSAGE or \ + command == ANALOG_MESSAGE or \ + command == REPORT_VERSION: + self.wait_for_data = 2 + self.exec_multibyte_cmd = command + + def __report(self): + """Reporting analog and digital pins""" + + self.delay(2) + for port in range(6): + self.serial.write(chr(REPORT_ANALOG | port)) + self.serial.write(chr(1)) + + for port in range(2): + self.serial.write(chr(REPORT_DIGITAL | port)) + self.serial.write(chr(1)) diff --git a/images/arduinomask.png b/images/arduinomask.png new file mode 100644 index 0000000..564e48f --- /dev/null +++ b/images/arduinomask.png Binary files differ diff --git a/images/en/arduino/analogread.svg b/images/en/arduino/analogread.svg new file mode 100644 index 0000000..22c97ea --- /dev/null +++ b/images/en/arduino/analogread.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + analog + + + read + + diff --git a/images/en/arduino/analogwrite.svg b/images/en/arduino/analogwrite.svg new file mode 100644 index 0000000..c0b4916 --- /dev/null +++ b/images/en/arduino/analogwrite.svg @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + analog + write + + + pin + + + value + + diff --git a/images/en/arduino/arduinogroup.svg b/images/en/arduino/arduinogroup.svg new file mode 100644 index 0000000..dc98a92 --- /dev/null +++ b/images/en/arduino/arduinogroup.svg @@ -0,0 +1,1015 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + X + + + Arduino + + + + + + + + + pin + + + mode + + + pin + + + mode + + + + + + + + + delay + + + + + + + + + analog + + + write + + + pin + + + value + + + + + + + + + + digital + + + write + + + pin + + + value + + + + + + analog + + + pin + + + + + digital + + + pin + + + + + + + HIGH + + + + + + LOW + + + + + + INPUT + + + + + + OUTPUT + + + + + + PWM + + + + + + SERVO + + + + + + read + + + read + + diff --git a/images/en/arduino/arduinomask.png b/images/en/arduino/arduinomask.png new file mode 100644 index 0000000..51a1453 --- /dev/null +++ b/images/en/arduino/arduinomask.png Binary files differ diff --git a/images/en/arduino/arduinomask.svg b/images/en/arduino/arduinomask.svg new file mode 100644 index 0000000..9c1d1bf --- /dev/null +++ b/images/en/arduino/arduinomask.svg @@ -0,0 +1,977 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Arduino + + + + + + + + + pin + + + mode + + + pin + + + mode + + + + + + + delay + + + + + + + + + analog + + + write + + + pin + + + value + + + + + + + + + + digital + + + write + + + pin + + + value + + + + + + analog + + + pin + + + + + digital + + + pin + + + + + HIGH + + + + + + LOW + + + + + + INPUT + + + + + + OUTPUT + + + + + + PWM + + + + + + SERVO + + + + read + + + read + + diff --git a/images/en/arduino/color.svg b/images/en/arduino/color.svg new file mode 100644 index 0000000..c65df50 --- /dev/null +++ b/images/en/arduino/color.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + color + + diff --git a/images/en/arduino/delay.svg b/images/en/arduino/delay.svg new file mode 100644 index 0000000..fc97bf0 --- /dev/null +++ b/images/en/arduino/delay.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + delay + + diff --git a/images/en/arduino/digitalread.svg b/images/en/arduino/digitalread.svg new file mode 100644 index 0000000..411d084 --- /dev/null +++ b/images/en/arduino/digitalread.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + digital + + + read + + diff --git a/images/en/arduino/digitalwrite.svg b/images/en/arduino/digitalwrite.svg new file mode 100644 index 0000000..a6be1d0 --- /dev/null +++ b/images/en/arduino/digitalwrite.svg @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + digital + write + + + pin + + + value + + diff --git a/images/en/arduino/high.svg b/images/en/arduino/high.svg new file mode 100644 index 0000000..20d1915 --- /dev/null +++ b/images/en/arduino/high.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + HIGH + + diff --git a/images/en/arduino/input.svg b/images/en/arduino/input.svg new file mode 100644 index 0000000..8de85ca --- /dev/null +++ b/images/en/arduino/input.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + INPUT + + diff --git a/images/en/arduino/low.svg b/images/en/arduino/low.svg new file mode 100644 index 0000000..15b412f --- /dev/null +++ b/images/en/arduino/low.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + LOW + + diff --git a/images/en/arduino/output.svg b/images/en/arduino/output.svg new file mode 100644 index 0000000..8f23a4f --- /dev/null +++ b/images/en/arduino/output.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + OUTPUT + + diff --git a/images/en/arduino/pwm.svg b/images/en/arduino/pwm.svg new file mode 100644 index 0000000..8fa2162 --- /dev/null +++ b/images/en/arduino/pwm.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + PWM + + diff --git a/images/en/arduino/servo.svg b/images/en/arduino/servo.svg new file mode 100644 index 0000000..271f7fa --- /dev/null +++ b/images/en/arduino/servo.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + SERVO + + diff --git a/images/en/arduino/setpinmode.svg b/images/en/arduino/setpinmode.svg new file mode 100644 index 0000000..33b2e4b --- /dev/null +++ b/images/en/arduino/setpinmode.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + pin + mode + + + pin + + + mode + + diff --git a/images/palette/arduinooff.svg b/images/palette/arduinooff.svg new file mode 100644 index 0000000..0373f46 --- /dev/null +++ b/images/palette/arduinooff.svg @@ -0,0 +1,3686 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/palette/arduinoon.svg b/images/palette/arduinoon.svg new file mode 100644 index 0000000..f647d42 --- /dev/null +++ b/images/palette/arduinoon.svg @@ -0,0 +1,3686 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/taarduino.py b/taarduino.py new file mode 100644 index 0000000..f6b6474 --- /dev/null +++ b/taarduino.py @@ -0,0 +1,50 @@ +import firmata + +class TAArduino(object): + def __init__(self, dev='/dev/ttyUSB0', baud=115200): + object.__init__(self) + self._dev = dev + self._baud = baud + self._arduino = None # Do not initialize this now + + self.HIGH = firmata.HIGH + self.LOW = firmata.LOW + self.INPUT = firmata.INPUT + self.OUTPUT = firmata.OUTPUT + self.PWM = firmata.PWM + self.SERVO = firmata.SERVO + + def _check_init(self): + if self._arduino is None: + self._arduino = firmata.Arduino(port = self._dev, \ + baudrate=self._baud) + self._arduino.parse() + + def delay(self, secs): + # Do not use this. The firmata module uses time.sleep() to + # implement this, which breaks gtk+ (unresponsive window) + self._check_init() + self._arduino.delay(secs) + + def pin_mode(self, pin, mode): + self._check_init() + self._arduino.pin_mode(int(pin), mode) + + def analog_write(self, pin, value): + self._check_init() + self._arduino.analog_write(int(pin), int(value)) + + def digital_write(self, pin, value): + self._check_init() + self._arduino.digital_write(int(pin), value) + + def analog_read(self, pin): + self._check_init() + self._arduino.parse() #XXX: Not sure why I have to do this here. + return self._arduino.analog_read(int(pin)) + + def digital_read(self, pin): + self._check_init() + return self._arduino.digital_read(int(pin)) + + diff --git a/talogo.py b/talogo.py index 16002d7..3275ce3 100644 --- a/talogo.py +++ b/talogo.py @@ -570,6 +570,22 @@ def lcNew(tw): show_template7(lc, x, y, z, a, b)) defprim(lc,'hideblocks', 0, lambda lc: hideblocks(lc)) + # arduino primitives + defprim(lc,'delay', 1, prim_wait, True) + defprim(lc,'setpinmode', 2, lambda lc, x, y: lc.tw.arduino.pin_mode(x, y)) + defprim(lc,'analogwrite', 2, lambda lc, x, y: \ + lc.tw.arduino.analog_write(x, y)) + defprim(lc,'digitalwrite', 2, lambda lc, x, y: \ + lc.tw.arduino.digital_write(x, y)) + defprim(lc,'analogread', 1, lambda lc, x: lc.tw.arduino.analog_read(x)) + defprim(lc,'digitalread', 1, lambda lc, x: lc.tw.arduino.digital_read(x)) + defprim(lc,'high', 0, lambda lc: lc.tw.arduino.HIGH) + defprim(lc,'low', 0, lambda lc: lc.tw.arduino.LOW) + defprim(lc,'input', 0, lambda lc: lc.tw.arduino.INPUT) + defprim(lc,'output', 0, lambda lc: lc.tw.arduino.OUTPUT) + defprim(lc,'pwm', 0, lambda lc: lc.tw.arduino.PWM) + defprim(lc,'servo', 0, lambda lc: lc.tw.arduino.SERVO) + lc.symtype = type(intern(lc, 'print')) lc.listtype = type([]) lc.symnothing = intern(lc, '%nothing%') diff --git a/tasetup.py b/tasetup.py index 174c897..fe1f9a2 100644 --- a/tasetup.py +++ b/tasetup.py @@ -165,7 +165,21 @@ selectors = ( ('template4','tp8','tp1',_('title'),'None'), ('hideblocks','hideblocks','noarg2'), # not selectable, but here for backward compatability - ('sound','sound','sound','None')))) + ('sound','sound','sound','None'))), + ('arduino', 55, + (('delay', 'delay', '1arg', 1), + ('setpinmode', 'setpinmode', 'twoargs'), + ('analogwrite', 'analogwrite', 'twoargs'), + ('digitalwrite', 'digitalwrite', 'twoargs'), + ('analogread', 'analogread', 'arduinoread', 5), + ('digitalread', 'digitalread', 'arduinoread', 13), + ('high','high','num'), + ('low','low','num'), + ('input','input','num'), + ('output','output','num'), + ('pwm','pwm','num'), + ('servo','servo','num')))) + dockdetails = { 'noarg': (('flow',True,37,5),('flow',False,37,44)), @@ -241,7 +255,9 @@ dockdetails = { 'tp7': (('flow',True,37,5),('string',False,10,26), \ ('media',False,10,73),('media',False,90,73),('media',False,10,130), \ ('media',False,90,130),('flow',False,37,167)), - 'string1': (('flow',True,37,5),('string',False,10,29),('flow',False,37,55)) + 'string1': (('flow',True,37,5),('string',False,10,29),('flow',False,37,55)), + 'arduinoread': (('num',True,0,31,'('), ('num',False,150,31), \ + ('numend',False,279,31,')')) } def count_up(self): diff --git a/tawindow.py b/tawindow.py index 7b25335..c626fb9 100644 --- a/tawindow.py +++ b/tawindow.py @@ -38,6 +38,7 @@ class taWindow: pass from math import atan2, pi DEGTOR = 2*pi/360 +from taarduino import * from tasetup import * from tasprites import * from talogo import * @@ -141,6 +142,7 @@ def twNew(win, path, lang, parent=None): tw.cartesian = False tw.polar = False tw.spr = None # "currently selected spr" + tw.arduino = TAArduino() return tw # -- cgit v0.9.1