From d8da0fcd85a0c3e153177f26ee0a0e0e635dcbe7 Mon Sep 17 00:00:00 2001 From: Sjoerd Dirk Meijer Date: Tue, 30 Apr 2013 16:47:16 +0200 Subject: [PATCH 01/13] Added ToDo --- README.md | 323 +++++++++++++++++++++++++++--------------------------- 1 file changed, 162 insertions(+), 161 deletions(-) diff --git a/README.md b/README.md index a69fa93..37b76b6 100644 --- a/README.md +++ b/README.md @@ -1,161 +1,162 @@ -# Python Arduino Command API - -The Python Arduino Command API is a light-weight Python library for -communicating with [Arduino microcontroller boards](http://www.arduino.cc/) from a connected computer using -standard serial IO, either physically -or wirelessly. It is written using a custom protocol, similar to [Firmata](http://firmata.org/wiki/Main_Page). - -This allows a user to quickly protoype programs for Arduino using Python code, or to -simply read/control/troubleshoot/experiment -with harware connected to an Arduino board without ever having to recompile and reload sketches to the board itself. - -Method names within the Python Arduino Command API are designed to be as close -as possible to their Arduino programming language counterparts. - -## Simple usage example (LED blink) -```python -#!/usr/bin/env python -""" - Blinks an LED on digital pin 13 - in 1 second intervals -""" - -from Arduino import Arduino -import time - -board = Arduino('9600') #plugged in via USB, serial com at rate 9600 - -while True: - board.digitalWrite(13, "LOW") - time.sleep(1) - board.digitalWrite(13, "HIGH") - time.sleep(1) -``` - -## Requirements: -- [Python](http://python.org/) 2.3 or higher (Python 3.x not yet tested, but would probably work) -- [pyserial](http://pyserial.sourceforge.net/) 2.6 or higher -- Any [Arduino compatible microcontroller](https://www.sparkfun.com/) with at least 14KB of flash memory - -## Setup: -1. Run `setup.py build install` to install the library -2. Verify that your Arduino board communicates at the baud rate specified in the -`setup()` function (line 243) in `prototype.ino`. Change it there if necessary. -3. Load the `prototype.ino` sketch onto your Arduino board, using the Arduino IDE. -4. Set up some kind of serial I/O communication between the Arduino board and your computer (via physical USB cable, -bluetooth, xbee, etc + associated drivers) -5. Add `from Arduino import Arduino` into your python script to communicate with your Arduino - -For a collection of examples, see `examples.py`. This file contains methods which replicate -the functionality of many Arduino demo sketches. - -## Classes -- `Arduino(baud)` - Set up communication with currently connected and powered -Arduino. - -```python -board = Arduino("9600") #Example -``` - -The device name / COM port of the connected Arduino will be auto-detected. -If there are more than one Arduino boards connected, -the desired COM port can be also be passed as an optional argument: - -```python -board = Arduino("9600", port = "COM3") #Windows example -``` -```python -board = Arduino("9600", port = "/dev/tty.usbmodemfa141") #OSX example -``` - -A time-out for reading from the Arduino can also be specified as an optional -argument: - -```python -board = Arduino("9600", timeout = 2) #Serial reading functions will -#wait for no more than 2 seconds -``` - -## Methods - -**Digital I/O** - -- `Arduino.digitalWrite(pin_number, state)` turn digital pin on/off -- `Arduino.digitalRead(pin_number)` read state of a digital pin - -```python -#Digital read / write example -board.digitalWrite(13, "HIGH") #Set digital pin 13 voltage -state_1 = board.digitalRead(13) #Will return integer 1 -board.digitalWrite(13, "LOW") #Set digital pin 13 voltage -state_2 = board.digitalRead(13) #Will return integer 0 -``` - -- `Arduino.pinMode(pin_number, io_mode)` set pin I/O mode -- `Arduino.pulseIn(pin_number, state)` measures a pulse -- `Arduino.pulseIn_set(pin_number, state)` measures a pulse, with preconditioning - -```python -#Digital mode / pulse example -board.pinMode(7, "INPUT") #Set digital pin 7 mode to INPUT -duration = board.pulseIn(7, "HIGH") #Return pulse width measurement on pin 7 -``` - -**Analog I/O** - -- `Arduino.analogRead(pin_number)` returns the analog value -- `Arduino.analogWrite(pin_number, value)` sets the analog value - -```python -#Analog I/O examples -val=board.analogRead(5) #Read value on analog pin 5 (integer 0 to 1023) -val = val / 4 # scale to 0 - 255 -board.analogWrite(11) #Set analog value (PWM) based on analog measurement -``` - -**Servo Library Functionality** -Support is included for up to 8 servos. - -- `Arduino.Servo.attach(pin, min = 544, max = 2400)` Create servo instance. Only 8 servos can be used at one time. -- `Arduino.Servo.read(pin)` Returns the angle of the servo attached to the specified pin -- `Arduino.Servo.write(pin, angle)` Move an attached servo on a pin to a specified angle -- `Arduino.Servo.writeMicroseconds(pin, uS)` Write a value in microseconds to the servo on a specified pin -- `Arduino.Servo.detach(pin)` Detaches the servo on the specified pin - -```python -#Servo example -board.Servo.attach(9) #declare servo on pin 9 -board.Servo.write(9, 0) #move servo on pin 9 to 0 degrees -print board.Servo.read(9) # should be 0 -board.Servo.detach(9) #free pin 9 -``` - -**Software Serial Functionality** - -- `Arduino.SoftwareSerial.begin(ss_rxPin,ss_txPin,ss_device_baud)` initialize software serial device on -specified pins. -Only one sofware serial device can be used at a time. Existing software serial instance will -be be overwritten by calling this method, both in Python and on the arduino board. -- `Arduino.SoftwareSerial.write(data)` send data using the arduino 'write' function to the existing software -serial connection. -- `Arduino.SoftwareSerial.read()` returns one byte from the existing software serial connection - -```python -#Software serial example -board.SoftwareSerial.begin(0,7,"19200") # Start software serial for transmit only (tx on pin 7) -board.SoftwareSerial.write(" test ") #Send some data -response_char = board.SoftwareSerial.read() #read response character -``` - -**Misc** - -- `Arduino.close()` closes serial connection to the Arduino. - -## To-do list: -- Expand software serial functionality (`print()` and `println()`) -- Add simple reset functionality that zeros out all pin values -- Add I2C / TWI function support (Arduino `Wire.h` commands) -- Add `tone()` / `noTone()` squarewave generator support for piezo type speakers currently testing code for this (thanks to Sjoerd Dirk Meijer.) -- Include a wizard which generates 'prototype.ino' with selected serial baud rate and Arduino function support -(to help reduce memory requirements). -- Multi-serial support for Arduino mega (`Serial1.read()`, etc) +# Python Arduino Command API + +The Python Arduino Command API is a light-weight Python library for +communicating with [Arduino microcontroller boards](http://www.arduino.cc/) from a connected computer using +standard serial IO, either physically +or wirelessly. It is written using a custom protocol, similar to [Firmata](http://firmata.org/wiki/Main_Page). + +This allows a user to quickly protoype programs for Arduino using Python code, or to +simply read/control/troubleshoot/experiment +with harware connected to an Arduino board without ever having to recompile and reload sketches to the board itself. + +Method names within the Python Arduino Command API are designed to be as close +as possible to their Arduino programming language counterparts. + +## Simple usage example (LED blink) +```python +#!/usr/bin/env python +""" + Blinks an LED on digital pin 13 + in 1 second intervals +""" + +from Arduino import Arduino +import time + +board = Arduino('9600') #plugged in via USB, serial com at rate 9600 + +while True: + board.digitalWrite(13, "LOW") + time.sleep(1) + board.digitalWrite(13, "HIGH") + time.sleep(1) +``` + +## Requirements: +- [Python](http://python.org/) 2.3 or higher (Python 3.x not yet tested, but would probably work) +- [pyserial](http://pyserial.sourceforge.net/) 2.6 or higher +- Any [Arduino compatible microcontroller](https://www.sparkfun.com/) with at least 14KB of flash memory + +## Setup: +1. Run `setup.py build install` to install the library +2. Verify that your Arduino board communicates at the baud rate specified in the +`setup()` function (line 243) in `prototype.ino`. Change it there if necessary. +3. Load the `prototype.ino` sketch onto your Arduino board, using the Arduino IDE. +4. Set up some kind of serial I/O communication between the Arduino board and your computer (via physical USB cable, +bluetooth, xbee, etc + associated drivers) +5. Add `from Arduino import Arduino` into your python script to communicate with your Arduino + +For a collection of examples, see `examples.py`. This file contains methods which replicate +the functionality of many Arduino demo sketches. + +## Classes +- `Arduino(baud)` - Set up communication with currently connected and powered +Arduino. + +```python +board = Arduino("9600") #Example +``` + +The device name / COM port of the connected Arduino will be auto-detected. +If there are more than one Arduino boards connected, +the desired COM port can be also be passed as an optional argument: + +```python +board = Arduino("9600", port = "COM3") #Windows example +``` +```python +board = Arduino("9600", port = "/dev/tty.usbmodemfa141") #OSX example +``` + +A time-out for reading from the Arduino can also be specified as an optional +argument: + +```python +board = Arduino("9600", timeout = 2) #Serial reading functions will +#wait for no more than 2 seconds +``` + +## Methods + +**Digital I/O** + +- `Arduino.digitalWrite(pin_number, state)` turn digital pin on/off +- `Arduino.digitalRead(pin_number)` read state of a digital pin + +```python +#Digital read / write example +board.digitalWrite(13, "HIGH") #Set digital pin 13 voltage +state_1 = board.digitalRead(13) #Will return integer 1 +board.digitalWrite(13, "LOW") #Set digital pin 13 voltage +state_2 = board.digitalRead(13) #Will return integer 0 +``` + +- `Arduino.pinMode(pin_number, io_mode)` set pin I/O mode +- `Arduino.pulseIn(pin_number, state)` measures a pulse +- `Arduino.pulseIn_set(pin_number, state)` measures a pulse, with preconditioning + +```python +#Digital mode / pulse example +board.pinMode(7, "INPUT") #Set digital pin 7 mode to INPUT +duration = board.pulseIn(7, "HIGH") #Return pulse width measurement on pin 7 +``` + +**Analog I/O** + +- `Arduino.analogRead(pin_number)` returns the analog value +- `Arduino.analogWrite(pin_number, value)` sets the analog value + +```python +#Analog I/O examples +val=board.analogRead(5) #Read value on analog pin 5 (integer 0 to 1023) +val = val / 4 # scale to 0 - 255 +board.analogWrite(11) #Set analog value (PWM) based on analog measurement +``` + +**Servo Library Functionality** +Support is included for up to 8 servos. + +- `Arduino.Servo.attach(pin, min = 544, max = 2400)` Create servo instance. Only 8 servos can be used at one time. +- `Arduino.Servo.read(pin)` Returns the angle of the servo attached to the specified pin +- `Arduino.Servo.write(pin, angle)` Move an attached servo on a pin to a specified angle +- `Arduino.Servo.writeMicroseconds(pin, uS)` Write a value in microseconds to the servo on a specified pin +- `Arduino.Servo.detach(pin)` Detaches the servo on the specified pin + +```python +#Servo example +board.Servo.attach(9) #declare servo on pin 9 +board.Servo.write(9, 0) #move servo on pin 9 to 0 degrees +print board.Servo.read(9) # should be 0 +board.Servo.detach(9) #free pin 9 +``` + +**Software Serial Functionality** + +- `Arduino.SoftwareSerial.begin(ss_rxPin,ss_txPin,ss_device_baud)` initialize software serial device on +specified pins. +Only one sofware serial device can be used at a time. Existing software serial instance will +be be overwritten by calling this method, both in Python and on the arduino board. +- `Arduino.SoftwareSerial.write(data)` send data using the arduino 'write' function to the existing software +serial connection. +- `Arduino.SoftwareSerial.read()` returns one byte from the existing software serial connection + +```python +#Software serial example +board.SoftwareSerial.begin(0,7,"19200") # Start software serial for transmit only (tx on pin 7) +board.SoftwareSerial.write(" test ") #Send some data +response_char = board.SoftwareSerial.read() #read response character +``` + +**Misc** + +- `Arduino.close()` closes serial connection to the Arduino. + +## To-do list: +- Expand software serial functionality (`print()` and `println()`) +- Add simple reset functionality that zeros out all pin values +- Add I2C / TWI function support (Arduino `Wire.h` commands) +- Add `tone()` / `noTone()` squarewave generator support for piezo type speakers currently testing code for this (thanks to Sjoerd Dirk Meijer.) +- Include a wizard which generates 'prototype.ino' with selected serial baud rate and Arduino function support +(to help reduce memory requirements). +- Multi-serial support for Arduino mega (`Serial1.read()`, etc) +- (sdmeijer) Add capacitive sensors (http://playground.arduino.cc/Code/CapacitiveSensor) From 397cc4aa373bd45bce61ea54aa8a07d9dfdff26a Mon Sep 17 00:00:00 2001 From: Sjoerd Dirk Meijer Date: Tue, 30 Apr 2013 16:48:41 +0200 Subject: [PATCH 02/13] Changed readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 37b76b6..3d790d1 100644 --- a/README.md +++ b/README.md @@ -156,6 +156,7 @@ response_char = board.SoftwareSerial.read() #read response character - Add simple reset functionality that zeros out all pin values - Add I2C / TWI function support (Arduino `Wire.h` commands) - Add `tone()` / `noTone()` squarewave generator support for piezo type speakers currently testing code for this (thanks to Sjoerd Dirk Meijer.) +-(sdmeijer) Add Python-code for Tone/NoTone. - Include a wizard which generates 'prototype.ino' with selected serial baud rate and Arduino function support (to help reduce memory requirements). - Multi-serial support for Arduino mega (`Serial1.read()`, etc) From 448768dcf2b7d806e1db7521c18061641d634de0 Mon Sep 17 00:00:00 2001 From: Sjoerd Dirk Meijer Date: Tue, 30 Apr 2013 16:50:50 +0200 Subject: [PATCH 03/13] My prototype.ino --- sketches/prototype/prototype.ino | 40 +++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/sketches/prototype/prototype.ino b/sketches/prototype/prototype.ino index 10a3066..c12b868 100644 --- a/sketches/prototype/prototype.ino +++ b/sketches/prototype/prototype.ino @@ -24,6 +24,35 @@ void split(String results[], int len, String input, char spChar) { } } +void Version(){ + Serial.println("version"); +} + +void Tone(String data){ + int idx = data.indexOf('%'); + int len = Str2int(data.substring(0,idx)); + String data2 = data.substring(idx+1); + int idx2 = data2.indexOf('%'); + int pin = Str2int(data2.substring(0,idx2)); + String data3 = data2.substring(idx2+1); + String melody[len*2]; + split(melody,len*2,data3,'%'); + + for (int thisNote = 0; thisNote < len; thisNote++) { + int noteDuration = 1000/Str2int(melody[thisNote+len]); + int note = Str2int(melody[thisNote]); + tone(pin, note, noteDuration); + int pause = noteDuration * 1.30; + delay(pause); + noTone(pin); + } +} + +void ToneNo(String data){ + int pin = Str2int(data); + noTone(pin); +} + void DigitalHandler(int mode, String data){ int pin = Str2int(data); if(mode<=0){ //read @@ -235,7 +264,16 @@ void SerialParser(void) { } else if (cmd == "svd") { SV_remove(data); - } + } + else if (cmd == "version") { + Version(); + } + else if (cmd == "to") { + Tone(data); + } + else if (cmd == "nto") { + ToneNo(data); + } } From bf563fefba20d7238b415f2acf97b02316937114 Mon Sep 17 00:00:00 2001 From: Sjoerd Dirk Meijer Date: Tue, 30 Apr 2013 16:52:47 +0200 Subject: [PATCH 04/13] My arduino.py --- Arduino/arduino.py | 781 ++++++++++++++++++++++++--------------------- 1 file changed, 426 insertions(+), 355 deletions(-) diff --git a/Arduino/arduino.py b/Arduino/arduino.py index 973444e..a76e321 100644 --- a/Arduino/arduino.py +++ b/Arduino/arduino.py @@ -1,355 +1,426 @@ -#!/usr/bin/env python -from serial.tools import list_ports -import serial, time - -class Arduino(object): - def __init__(self,baud,port="",timeout=2): - """ - Initializes serial communication with Arduino. - Attempts to self-select COM port, if not specified. - """ - self.baud = baud - self.timeout = timeout - self.ss_connected=False - if port == "": - self.findPort() - self.sr = serial.Serial(self.port, self.baud,timeout =self.timeout) - time.sleep(2) - self.SoftwareSerial = SoftwareSerial(self) - self.Servos = Servos(self) - - def findPort(self): - """ - Sets port to the first Arduino found - in system's device list - """ - for pt in list_ports.comports(): - if ("FTDIBUS" in pt[-1]) or ("usbserial" in pt[-1]): - self.port = pt[0] - return - - def digitalWrite(self,pin,val): - """ - Sends digitalWrite command - to digital pin on Arduino - ------------- - inputs: - pin : digital pin number - val : either "HIGH" or "LOW" - """ - if val=="LOW": - pin_ = -pin - else: - pin_ = pin - cmd_str=''.join(["@dw%",str(pin_),"$!"]) - try: - self.sr.write(cmd_str) - self.sr.flush() - except: - pass - - def analogWrite(self,pin,val): - """ - Sends analogWrite pwm command - to pin on Arduino - ------------- - inputs: - pin : pin number - val : integer 0 (off) to 255 (always on) - """ - if val>255: - val=255 - elif val<0: - val=0 - cmd_str=''.join(["@aw%",str(pin),"%",str(val),"$!"]) - try: - self.sr.write(cmd_str) - self.sr.flush() - except: - pass - - def analogRead(self,pin): - """ - Returns the value of a specified - analog pin. - inputs: - pin : analog pin number for measurement - returns: - value: integer from 1 to 1023 - """ - cmd_str=''.join(["@ar%",str(pin),"$!"]) - try: - self.sr.write(cmd_str) - self.sr.flush() - except: - pass - rd = self.sr.readline().replace("\r\n","") - try: - return int(rd) - except: - return 0 - - - def pinMode(self,pin,val): - """ - Sets I/O mode of pin - inputs: - pin: pin number to toggle - val: "INPUT" or "OUTPUT" - """ - if val=="INPUT": - pin_ = -pin - else: - pin_ = pin - cmd_str=''.join(["@pm%",str(pin_),"$!"]) - try: - self.sr.write(cmd_str) - self.sr.flush() - except: - pass - - def pulseIn(self,pin,val): - """ - Reads a pulse from a pin - - inputs: - pin: pin number for pulse measurement - returns: - duration : pulse length measurement - - """ - if val=="LOW": - pin_ = -pin - else: - pin_ = pin - cmd_str=''.join(["@pi%",str(pin_),"$!"]) - try: - self.sr.write(cmd_str) - self.sr.flush() - except: - pass - rd = self.sr.readline().replace("\r\n","") - try: - return float(rd) - except: - return -1 - - def pulseIn_set(self,pin,val): - """ - Sets a digital pin value, then reads the response - as a pulse width. - Useful for some ultrasonic rangefinders, etc. - - inputs: - pin: pin number for pulse measurement - val: "HIGH" or "LOW". Pulse is measured - when this state is detected - returns: - duration : pulse length measurement - - This method will automatically toggle - I/O modes on the pin and precondition the - measurment with a clean LOW/HIGH pulse. - Arduino.pulseIn_set(pin,"HIGH") is - equivalent to the Arduino sketch code: - - pinMode(pin, OUTPUT); - digitalWrite(pin, LOW); - delayMicroseconds(2); - digitalWrite(pin, HIGH); - delayMicroseconds(5); - digitalWrite(pin, LOW); - pinMode(pin, INPUT); - long duration = pulseIn(pin, HIGH); - """ - if val=="LOW": - pin_ = -pin - else: - pin_ = pin - cmd_str=''.join(["@ps%",str(pin_),"$!"]) - try: - self.sr.write(cmd_str) - self.sr.flush() - except: - pass - rd = self.sr.readline().replace("\r\n","") - try: - return float(rd) - except: - return -1 - - def close(self): - self.sr.close() - - def digitalRead(self,pin): - """ - Returns the value of a specified - digital pin. - inputs: - pin : digital pin number for measurement - returns: - value: 0 for "LOW", 1 for "HIGH" - """ - cmd_str=''.join(["@dr%",str(pin),"$!"]) - try: - self.sr.write(cmd_str) - self.sr.flush() - except: - pass - rd = self.sr.readline().replace("\r\n","") - try: - return 1 - int(rd) - except: - return 0 - -class Wires(object): - """ - Class for Arduino wire (i2c) support - """ - def __init__(self, board): - self.board = board - self.sr = board.sr - -class Servos(object): - """ - Class for Arduino servo support - 0.03 second delay noted - """ - def __init__(self, board): - self.board = board - self.sr = board.sr - self.servo_pos = {} - - def attach(self,pin,min = 544, max = 2400): - cmd_str=''.join(["@sva%",str(pin),"%",str(min),"%",str(max),"$!"]) - try: - self.sr.write(cmd_str) - self.sr.flush() - except: - pass - rd = self.sr.readline().replace("\r\n","") - try: - position = int(rd) - self.servo_pos[pin] = position - return 1 - except: - return 0 - - def detach(self,pin): - cmd_str=''.join(["@svd%",str(position),"$!"]) - try: - self.sr.write(cmd_str) - self.sr.flush() - except: - pass - del self.servo_pos[pin] - - def write(self,pin,angle): - position = self.servo_pos[pin] - cmd_str=''.join(["@svw%",str(position),"%",str(angle),"$!"]) - try: - self.sr.write(cmd_str) - self.sr.flush() - except: - pass - - def writeMicroseconds(self,pin,uS): - cmd_str=''.join(["@svw%",str(position),"%",str(uS),"$!"]) - try: - self.sr.write(cmd_str) - self.sr.flush() - except: - pass - - def read(self,pin): - if pin not in self.servo_pos.keys(): - self.attach(pin) - position = self.servo_pos[pin] - cmd_str=''.join(["@svr%",str(position),"$!"]) - try: - self.sr.write(cmd_str) - self.sr.flush() - except: - pass - rd = self.sr.readline().replace("\r\n","") - try: - angle = int(rd) - return angle - except: - return None - -class SoftwareSerial(object): - """ - Class for Arduino software serial functionality - """ - def __init__(self,board): - self.board=board - self.sr = board.sr - self.connected = False - - def begin(self,p1,p2,baud): - """ - Create software serial instance on - specified tx,rx pins, at specified baud - """ - cmd_str=''.join(["@ss%",str(p1),"%",str(p2),"%",str(baud),"$!"]) - try: - self.sr.write(cmd_str) - self.sr.flush() - except: - pass - response= self.sr.readline().replace("\r\n","") - if response == "ss OK": - self.connected = True - return True - else: - self.connected = False - return False - - def write(self,data): - """ - sends data to existing software serial instance - using Arduino's 'write' function - """ - if self.connected: - cmd_str=''.join(["@sw%",str(data),"$!"]) - try: - self.sr.write(cmd_str) - self.sr.flush() - except: - pass - response= self.sr.readline().replace("\r\n","") - if response == "ss OK": - return True - else: - return False - - def read(self): - """ - returns first character read from - existing software serial instance - """ - if self.connected: - cmd_str=''.join(["@sr%$!"]) - self.sr.write(cmd_str) - self.sr.flush() - response= self.sr.readline().replace("\r\n","") - if response: - return response - else: - return False - -if __name__=="__main__": - # quick test - board=Arduino(9600) - board.Servos.attach(9) - board.Servos.write(9,90) - time.sleep(1) - print board.Servos.read(9) - t=time.time() - board.Servos.write(9,1) - while True: - a=board.Servos.read(9) - if a == 1: - print "time",time.time() - t - break \ No newline at end of file +#!/usr/bin/env python +from serial.tools import list_ports +import serial, time +##SDM +import platform +if platform.system() == 'Windows': + import _winreg as winreg +if platform.system() == 'Linux': + import glob +import itertools + +def enumerate_serial_ports(): + """ Uses the Win32 registry to return a iterator of serial + (COM) ports existing on this computer. + """ + path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM' + try: + key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path) + except WindowsError: + raise IterationError + + for i in itertools.count(): + try: + val = winreg.EnumValue(key, i) + yield (str(val[1]))#, str(val[0])) + except EnvironmentError: + break +##SDM + +class Arduino(object): + def __init__(self,baud=9600,port="",timeout=2): + """ + Initializes serial communication with Arduino. + Attempts to self-select COM port, if not specified. + """ + self.baud = baud + self.timeout = timeout + self.ss_connected=False +##SDM + self.port = port + if self.port == "": + if platform.system() == 'Windows': + ports = enumerate_serial_ports() + if platform.system() == 'Linux': + ports = glob.glob("/dev/ttyUSB*") + for p in ports: + print 'Found ', p + try: + print 'Testing ', p + self.sr = serial.Serial(p, self.baud,timeout=self.timeout) + time.sleep(2) + cmd_str=''.join(["@version%$!"]) + try: + self.sr.write(cmd_str) + self.sr.flush() + except: + pass + version = self.sr.readline().replace("\r\n","") + #print version + if version != 'version': + raise Exception('This is not a Shrimp/Arduino!') + self.port = p + print p, 'passed' + break + except Exception, e: + print "Exception: ", e + pass +##SDM + #--self.sr = serial.Serial(self.port, self.baud,timeout =self.timeout) + #--time.sleep(2) + self.SoftwareSerial = SoftwareSerial(self) + self.Servos = Servos(self) + + def findPort(self): + """ + Sets port to the first Arduino found + in system's device list + """ + for pt in list_ports.comports(): + if ("FTDIBUS" in pt[-1]) or ("usbserial" in pt[-1]): + self.port = pt[0] + return + + def digitalWrite(self,pin,val): + """ + Sends digitalWrite command + to digital pin on Arduino + ------------- + inputs: + pin : digital pin number + val : either "HIGH" or "LOW" + """ + if val=="LOW": + pin_ = -pin + else: + pin_ = pin + cmd_str=''.join(["@dw%",str(pin_),"$!"]) + try: + self.sr.write(cmd_str) + self.sr.flush() + except: + pass + + def analogWrite(self,pin,val): + """ + Sends analogWrite pwm command + to pin on Arduino + ------------- + inputs: + pin : pin number + val : integer 0 (off) to 255 (always on) + """ + if val>255: + val=255 + elif val<0: + val=0 + cmd_str=''.join(["@aw%",str(pin),"%",str(val),"$!"]) + try: + self.sr.write(cmd_str) + self.sr.flush() + except: + pass + + def analogRead(self,pin): + """ + Returns the value of a specified + analog pin. + inputs: + pin : analog pin number for measurement + returns: + value: integer from 1 to 1023 + """ + cmd_str=''.join(["@ar%",str(pin),"$!"]) + try: + self.sr.write(cmd_str) + self.sr.flush() + except: + pass + rd = self.sr.readline().replace("\r\n","") + try: + return int(rd) + except: + return 0 + + + def pinMode(self,pin,val): + """ + Sets I/O mode of pin + inputs: + pin: pin number to toggle + val: "INPUT" or "OUTPUT" + """ + if val=="INPUT": + pin_ = -pin + else: + pin_ = pin + cmd_str=''.join(["@pm%",str(pin_),"$!"]) + try: + self.sr.write(cmd_str) + self.sr.flush() + except: + pass + + def pulseIn(self,pin,val): + """ + Reads a pulse from a pin + + inputs: + pin: pin number for pulse measurement + returns: + duration : pulse length measurement + + """ + if val=="LOW": + pin_ = -pin + else: + pin_ = pin + cmd_str=''.join(["@pi%",str(pin_),"$!"]) + try: + self.sr.write(cmd_str) + self.sr.flush() + except: + pass + rd = self.sr.readline().replace("\r\n","") + try: + return float(rd) + except: + return -1 + + def pulseIn_set(self,pin,val,numTrials=5): + """ + Sets a digital pin value, then reads the response + as a pulse width. + Useful for some ultrasonic rangefinders, etc. + + inputs: + pin: pin number for pulse measurement + val: "HIGH" or "LOW". Pulse is measured + when this state is detected + numTrials: number of trials (for an average) + returns: + duration : an average of pulse length measurements + + This method will automatically toggle + I/O modes on the pin and precondition the + measurment with a clean LOW/HIGH pulse. + Arduino.pulseIn_set(pin,"HIGH") is + equivalent to the Arduino sketch code: + + pinMode(pin, OUTPUT); + digitalWrite(pin, LOW); + delayMicroseconds(2); + digitalWrite(pin, HIGH); + delayMicroseconds(5); + digitalWrite(pin, LOW); + pinMode(pin, INPUT); + long duration = pulseIn(pin, HIGH); + """ + if val=="LOW": + pin_ = -pin + else: + pin_ = pin + cmd_str=''.join(["@ps%",str(pin_),"$!"]) + durations = [] + for s in range(numTrials): + try: + self.sr.write(cmd_str) + self.sr.flush() + except: + pass + rd = self.sr.readline().replace("\r\n","") + if rd.isdigit() == True: + if (int(rd) > 1) == True: + durations.append(int(rd)) + #print durations + if len(durations) > 0: + duration = int(sum(durations)) / int(len(durations)) + else: + duration = None + + try: + return float(duration) + except: + return -1 + + def close(self): + self.sr.close() + + def digitalRead(self,pin): + """ + Returns the value of a specified + digital pin. + inputs: + pin : digital pin number for measurement + returns: + value: 0 for "LOW", 1 for "HIGH" + """ + cmd_str=''.join(["@dr%",str(pin),"$!"]) + try: + self.sr.write(cmd_str) + self.sr.flush() + except: + pass + rd = self.sr.readline().replace("\r\n","") + try: + return 1 - int(rd) + except: + return 0 + +##SDM +class Shrimp(Arduino): + def __init__(self): + Arduino.__init__(self) +##SDM + +class Wires(object): + """ + Class for Arduino wire (i2c) support + """ + def __init__(self, board): + self.board = board + self.sr = board.sr + +class Servos(object): + """ + Class for Arduino servo support + 0.03 second delay noted + """ + def __init__(self, board): + self.board = board + self.sr = board.sr + self.servo_pos = {} + + def attach(self,pin,min = 544, max = 2400): + cmd_str=''.join(["@sva%",str(pin),"%",str(min),"%",str(max),"$!"]) + try: + self.sr.write(cmd_str) + self.sr.flush() + except: + pass + rd = self.sr.readline().replace("\r\n","") + try: + position = int(rd) + self.servo_pos[pin] = position + return 1 + except: + return 0 + + def detach(self,pin): + cmd_str=''.join(["@svd%",str(position),"$!"]) + try: + self.sr.write(cmd_str) + self.sr.flush() + except: + pass + del self.servo_pos[pin] + + def write(self,pin,angle): + position = self.servo_pos[pin] + cmd_str=''.join(["@svw%",str(position),"%",str(angle),"$!"]) + try: + self.sr.write(cmd_str) + self.sr.flush() + except: + pass + + def writeMicroseconds(self,pin,uS): + cmd_str=''.join(["@svw%",str(position),"%",str(uS),"$!"]) + try: + self.sr.write(cmd_str) + self.sr.flush() + except: + pass + + def read(self,pin): + if pin not in self.servo_pos.keys(): + self.attach(pin) + position = self.servo_pos[pin] + cmd_str=''.join(["@svr%",str(position),"$!"]) + try: + self.sr.write(cmd_str) + self.sr.flush() + except: + pass + rd = self.sr.readline().replace("\r\n","") + try: + angle = int(rd) + return angle + except: + return None + +class SoftwareSerial(object): + """ + Class for Arduino software serial functionality + """ + def __init__(self,board): + self.board=board + self.sr = board.sr + self.connected = False + + def begin(self,p1,p2,baud): + """ + Create software serial instance on + specified tx,rx pins, at specified baud + """ + cmd_str=''.join(["@ss%",str(p1),"%",str(p2),"%",str(baud),"$!"]) + try: + self.sr.write(cmd_str) + self.sr.flush() + except: + pass + response= self.sr.readline().replace("\r\n","") + if response == "ss OK": + self.connected = True + return True + else: + self.connected = False + return False + + def write(self,data): + """ + sends data to existing software serial instance + using Arduino's 'write' function + """ + if self.connected: + cmd_str=''.join(["@sw%",str(data),"$!"]) + try: + self.sr.write(cmd_str) + self.sr.flush() + except: + pass + response= self.sr.readline().replace("\r\n","") + if response == "ss OK": + return True + else: + return False + + def read(self): + """ + returns first character read from + existing software serial instance + """ + if self.connected: + cmd_str=''.join(["@sr%$!"]) + self.sr.write(cmd_str) + self.sr.flush() + response= self.sr.readline().replace("\r\n","") + if response: + return response + else: + return False + +##if __name__=="__main__": + # quick test +## board=Arduino(9600, 'COM9') +## board.Servos.attach(9) +## board.Servos.write(9,90) +## time.sleep(1) +## print board.Servos.read(9) +## t=time.time() +## board.Servos.write(9,1) +## while True: +## a=board.Servos.read(9) +## if a == 1: +## print "time",time.time() - t +## break From 32f2e22ec9d93c99ae3ba1dec4b005c4c89ca876 Mon Sep 17 00:00:00 2001 From: Sjoerd Dirk Meijer Date: Tue, 30 Apr 2013 20:42:48 +0200 Subject: [PATCH 05/13] Added Melody --- Arduino/__init__.py | 10 ++++---- Arduino/arduino.py | 56 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/Arduino/__init__.py b/Arduino/__init__.py index e440668..2942e63 100644 --- a/Arduino/__init__.py +++ b/Arduino/__init__.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python - - -from arduino import Arduino - +#!/usr/bin/env python + + +from arduino import Arduino,Shrimp + diff --git a/Arduino/arduino.py b/Arduino/arduino.py index a76e321..37aee72 100644 --- a/Arduino/arduino.py +++ b/Arduino/arduino.py @@ -267,6 +267,62 @@ def digitalRead(self,pin): except: return 0 + def Melody(self, pin, melody, durations): + """ + Plays a melody. + inputs: + pin: digital pin number for playback + melody: list of tones + durations: list of duration + length of melody should be of same + length as length of duration + + Melodies of the following lenght, can cause trouble + when playing it multiple times. + board.Melody(9,["C4","G3","G3","A3","G3",0,"B3","C4"],[4,8,8,4,4,4,4,4]) + Playing short melodies (1 or 2 tones) didn't cause trouble during testing + """ + NOTES = dict(B0=31,C1=33,CS1=35,D1=37,DS1=39,E1=41,F1=44,FS1=46,G1=49\ + ,GS1=52,A1=55,AS1=58,B1=62,C2=65,CS2=69,D2=73,DS2=78,E2=82\ + ,F2=87,FS2=93,G2=98,GS2=104,A2=110,AS2=117,B2=123,C3=131\ + ,CS3=139,D3=147,DS3=156,E3=165,F3=175,FS3=185,G3=196,GS3=208\ + ,A3=220,AS3=233,B3=247,C4=262,CS4=277,D4=294,DS4=311,E4=330\ + ,F4=349,FS4=370,G4=392,GS4=415,A4=440,AS4=466,B4=494,C5=523\ + ,CS5=554,D5=587,DS5=622,E5=659,F5=698,FS5=740,G5=784,GS5=831\ + ,A5=880,AS5=932,B5=988,C6=1047,CS6=1109,D6=1175,DS6=1245,E6=1319\ + ,F6=1397,FS6=1480,G6=1568,GS6=1661,A6=1760,AS6=1865,B6=1976,C7=2093\ + ,CS7=2217,D7=2349,DS7=2489,E7=2637,F7=2794,FS7=2960,G7=3136\ + ,GS7=3322,A7=3520,AS7=3729,B7=3951,C8=4186,CS8=4435,D8=4699,DS8=4978) + if (type(melody) == list) and (type(durations) == list): + length = len(melody) + cmd_str = "@to%"+str(length)+"%"+str(pin)+"%" + d = "" + if length == len(durations): + for note in range(length): + n = NOTES.get(melody[note]) + cmd_str = cmd_str+str(n)+"%" + for duration in range(len(durations)): + d = str(durations[duration]) + cmd_str = cmd_str+d+"%" + cmd_str = cmd_str[:-1]+"$!" + print cmd_str + try: + self.sr.write(cmd_str) + self.sr.flush() + except: + pass + cmd_str=''.join(["@nto%",str(pin),"$!"]) + print cmd_str + try: + self.sr.write(cmd_str) + self.sr.flush() + except: + pass + else: + return -1 + else: + return -1 + ##SDM class Shrimp(Arduino): def __init__(self): From becbfa413f9fe8008b5039d20ae8e5d9fe9baca6 Mon Sep 17 00:00:00 2001 From: Sjoerd Dirk Meijer Date: Tue, 30 Apr 2013 21:16:53 +0200 Subject: [PATCH 06/13] improved comment Tone() --- Arduino/arduino.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/arduino.py b/Arduino/arduino.py index 37aee72..755f224 100644 --- a/Arduino/arduino.py +++ b/Arduino/arduino.py @@ -273,7 +273,7 @@ def Melody(self, pin, melody, durations): inputs: pin: digital pin number for playback melody: list of tones - durations: list of duration + durations: list of duration (4=quarter note, 8=eighth note, etc.) length of melody should be of same length as length of duration From 2a05e458ff4f22ba72d860834f56b857013fc51c Mon Sep 17 00:00:00 2001 From: Sjoerd Dirk Meijer Date: Tue, 30 Apr 2013 21:52:51 +0200 Subject: [PATCH 07/13] added capacitivePin-feature --- sketches/prototype/prototype.ino | 69 +++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/sketches/prototype/prototype.ino b/sketches/prototype/prototype.ino index c12b868..a245952 100644 --- a/sketches/prototype/prototype.ino +++ b/sketches/prototype/prototype.ino @@ -28,6 +28,71 @@ void Version(){ Serial.println("version"); } +uint8_t readCapacitivePin(String data) { + int pinToMeasure = Str2int(data); + // readCapacitivePin + // Input: Arduino pin number + // Output: A number, from 0 to 17 expressing + // how much capacitance is on the pin + // When you touch the pin, or whatever you have + // attached to it, the number will get higher + // http://playground.arduino.cc/Code/CapacitiveSensor + // + // Variables used to translate from Arduino to AVR pin naming + volatile uint8_t* port; + volatile uint8_t* ddr; + volatile uint8_t* pin; + // Here we translate the input pin number from + // Arduino pin number to the AVR PORT, PIN, DDR, + // and which bit of those registers we care about. + byte bitmask; + port = portOutputRegister(digitalPinToPort(pinToMeasure)); + ddr = portModeRegister(digitalPinToPort(pinToMeasure)); + bitmask = digitalPinToBitMask(pinToMeasure); + pin = portInputRegister(digitalPinToPort(pinToMeasure)); + // Discharge the pin first by setting it low and output + *port &= ~(bitmask); + *ddr |= bitmask; + delay(1); + // Make the pin an input with the internal pull-up on + *ddr &= ~(bitmask); + *port |= bitmask; + + // Now see how long the pin to get pulled up. This manual unrolling of the loop + // decreases the number of hardware cycles between each read of the pin, + // thus increasing sensitivity. + uint8_t cycles = 17; + if (*pin & bitmask) { cycles = 0;} + else if (*pin & bitmask) { cycles = 1;} + else if (*pin & bitmask) { cycles = 2;} + else if (*pin & bitmask) { cycles = 3;} + else if (*pin & bitmask) { cycles = 4;} + else if (*pin & bitmask) { cycles = 5;} + else if (*pin & bitmask) { cycles = 6;} + else if (*pin & bitmask) { cycles = 7;} + else if (*pin & bitmask) { cycles = 8;} + else if (*pin & bitmask) { cycles = 9;} + else if (*pin & bitmask) { cycles = 10;} + else if (*pin & bitmask) { cycles = 11;} + else if (*pin & bitmask) { cycles = 12;} + else if (*pin & bitmask) { cycles = 13;} + else if (*pin & bitmask) { cycles = 14;} + else if (*pin & bitmask) { cycles = 15;} + else if (*pin & bitmask) { cycles = 16;} + + // Discharge the pin again by setting it low and output + // It's important to leave the pins low if you want to + // be able to touch more than 1 sensor at a time - if + // the sensor is left pulled high, when you touch + // two sensors, your body will transfer the charge between + // sensors. + *port &= ~(bitmask); + *ddr |= bitmask; + + //return cycles; + Serial.println(cycles); +} + void Tone(String data){ int idx = data.indexOf('%'); int len = Str2int(data.substring(0,idx)); @@ -274,9 +339,11 @@ void SerialParser(void) { else if (cmd == "nto") { ToneNo(data); } + else if (cmd == "cap") { + readCapacitivePin(data); + } } - void setup() { Serial.begin(9600); while (!Serial) { From 8cb14ea9ff068c988fae9777528d26d05c666433 Mon Sep 17 00:00:00 2001 From: Sjoerd Dirk Meijer Date: Wed, 1 May 2013 18:58:21 +0200 Subject: [PATCH 08/13] added capacitivePin-feature (Python-part) --- Arduino/arduino.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Arduino/arduino.py b/Arduino/arduino.py index 755f224..8e84ae7 100644 --- a/Arduino/arduino.py +++ b/Arduino/arduino.py @@ -323,6 +323,21 @@ def Melody(self, pin, melody, durations): else: return -1 + def capacitivePin(self, pin): + ''' + Input: + pin (int): pin to use as capacitive sensor + + Use it in a loop! + ''' + cmd_str="@cap%"+str(pin)+"$!" + self.sr.write(cmd_str) + rd = self.sr.readline().replace("\r\n","") + if rd.isdigit() == True: + #print "rd: " + str(rd) + return int(rd) + + ##SDM class Shrimp(Arduino): def __init__(self): From e1ad812775b22964696bcdd9eb6e2ef453658837 Mon Sep 17 00:00:00 2001 From: Sjoerd Dirk Meijer Date: Wed, 1 May 2013 19:32:07 +0200 Subject: [PATCH 09/13] updated readme --- Arduino/arduino.py | 6 ++++++ README.md | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Arduino/arduino.py b/Arduino/arduino.py index 8e84ae7..369aa45 100644 --- a/Arduino/arduino.py +++ b/Arduino/arduino.py @@ -329,6 +329,12 @@ def capacitivePin(self, pin): pin (int): pin to use as capacitive sensor Use it in a loop! + DO NOT CONNECT ANY ACTIVE DRIVER TO THE USED PIN ! + + the pin is toggled to output mode to discharge the port, + and if connected to a voltage source, + will short circuit the pin, potentially damaging + the Arduino/Shrimp and any hardware attached to the pin. ''' cmd_str="@cap%"+str(pin)+"$!" self.sr.write(cmd_str) diff --git a/README.md b/README.md index 3d790d1..fd91917 100644 --- a/README.md +++ b/README.md @@ -155,9 +155,9 @@ response_char = board.SoftwareSerial.read() #read response character - Expand software serial functionality (`print()` and `println()`) - Add simple reset functionality that zeros out all pin values - Add I2C / TWI function support (Arduino `Wire.h` commands) -- Add `tone()` / `noTone()` squarewave generator support for piezo type speakers currently testing code for this (thanks to Sjoerd Dirk Meijer.) --(sdmeijer) Add Python-code for Tone/NoTone. +- Add `tone()` / `noTone()` squarewave generator support for piezo type speakers currently testing code for this (thanks to Sjoerd Dirk Meijer.) +-(sdmeijer) Add Python-code for Tone/NoTone. - Include a wizard which generates 'prototype.ino' with selected serial baud rate and Arduino function support (to help reduce memory requirements). - Multi-serial support for Arduino mega (`Serial1.read()`, etc) -- (sdmeijer) Add capacitive sensors (http://playground.arduino.cc/Code/CapacitiveSensor) +- (sdmeijer) Add capacitive sensors (http://playground.arduino.cc/Code/CapacitiveSensor) From 7b51842e6ff931666dc333851a7f9a25ad3c3f38 Mon Sep 17 00:00:00 2001 From: Sjoerd Dirk Meijer Date: Wed, 1 May 2013 20:59:38 +0200 Subject: [PATCH 10/13] preventing playing melody from buffer on reset --- .gitattributes | 22 +++++++ Arduino/arduino.py | 5 +- MIT license.txt | 38 ++++++------ examples.py | 152 ++++++++++++++++++++++----------------------- 4 files changed, 120 insertions(+), 97 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..412eeda --- /dev/null +++ b/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/Arduino/arduino.py b/Arduino/arduino.py index 369aa45..cd7749a 100644 --- a/Arduino/arduino.py +++ b/Arduino/arduino.py @@ -70,6 +70,7 @@ def __init__(self,baud=9600,port="",timeout=2): #--time.sleep(2) self.SoftwareSerial = SoftwareSerial(self) self.Servos = Servos(self) + self.sr.flush() def findPort(self): """ @@ -305,14 +306,14 @@ def Melody(self, pin, melody, durations): d = str(durations[duration]) cmd_str = cmd_str+d+"%" cmd_str = cmd_str[:-1]+"$!" - print cmd_str + #print cmd_str try: self.sr.write(cmd_str) self.sr.flush() except: pass cmd_str=''.join(["@nto%",str(pin),"$!"]) - print cmd_str + #print cmd_str try: self.sr.write(cmd_str) self.sr.flush() diff --git a/MIT license.txt b/MIT license.txt index 366ef45..0e1f20e 100644 --- a/MIT license.txt +++ b/MIT license.txt @@ -1,19 +1,19 @@ -Copyright (c) 2012-2013 Tristan A. Hearn - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +Copyright (c) 2012-2013 Tristan A. Hearn + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/examples.py b/examples.py index b2c033f..8051b3c 100644 --- a/examples.py +++ b/examples.py @@ -1,77 +1,77 @@ -#!/usr/bin/env python -from Arduino import Arduino -import time - -def Blink(led_pin,baud, port = ""): - """ - Blinks an LED in 1 sec intervals - """ - board = Arduino(baud, port=port) - while True: - board.digitalWrite(led_pin,"LOW") - print board.digitalRead(led_pin) #confirm LOW (0) - time.sleep(1) - board.digitalWrite(led_pin,"HIGH") - print board.digitalRead(led_pin) #confirm HIGH (1) - time.sleep(1) - -def softBlink(led_pin,baud, port = ""): - """ - Fades an LED off and on, using - Arduino's analogWrite (PWM) function - """ - board=Arduino(baud, port=port) - i=0 - while True: - i+=1 - k=i%510 - if k%5==0: - if k>255: - k=510-k - board.analogWrite(led_pin,k) - -def adjustBrightness(pot_pin,led_pin,baud, port=""): - """ - Adjusts brightness of an LED using a - potentiometer - """ - board=Arduino(baud, port=port) - while True: - time.sleep(0.01) - val=board.analogRead(pot_pin)/4 - print val - board.analogWrite(led_pin,val) - - -def PingSonar(pw_pin,baud, port=""): - """ - Gets distance measurement from Ping))) - ultrasonic rangefinder connected to pw_pin - """ - board = Arduino(baud, port=port) - pingPin=pw_pin - while True: - duration = board.pulseIn(pingPin, "HIGH") - inches = duration/72./2. - cent = duration/29./2. - print inches,"inches" - time.sleep(0.1) - -def LCD(tx,baud,ssbaud,message, port=""): - """ - Prints to two-line LCD connected to - pin tx - """ - board = Arduino(baud, port=port) - board.SoftwareSerial.begin(0,tx,ssbaud) - while True: - board.SoftwareSerial.write(" test ") - - - - -if __name__=="__main__": - Blink(13,9600) - #LCD(5,9600,9600," test ") - #adjustBrightness(5,11,9600) +#!/usr/bin/env python +from Arduino import Arduino +import time + +def Blink(led_pin,baud, port = ""): + """ + Blinks an LED in 1 sec intervals + """ + board = Arduino(baud, port=port) + while True: + board.digitalWrite(led_pin,"LOW") + print board.digitalRead(led_pin) #confirm LOW (0) + time.sleep(1) + board.digitalWrite(led_pin,"HIGH") + print board.digitalRead(led_pin) #confirm HIGH (1) + time.sleep(1) + +def softBlink(led_pin,baud, port = ""): + """ + Fades an LED off and on, using + Arduino's analogWrite (PWM) function + """ + board=Arduino(baud, port=port) + i=0 + while True: + i+=1 + k=i%510 + if k%5==0: + if k>255: + k=510-k + board.analogWrite(led_pin,k) + +def adjustBrightness(pot_pin,led_pin,baud, port=""): + """ + Adjusts brightness of an LED using a + potentiometer + """ + board=Arduino(baud, port=port) + while True: + time.sleep(0.01) + val=board.analogRead(pot_pin)/4 + print val + board.analogWrite(led_pin,val) + + +def PingSonar(pw_pin,baud, port=""): + """ + Gets distance measurement from Ping))) + ultrasonic rangefinder connected to pw_pin + """ + board = Arduino(baud, port=port) + pingPin=pw_pin + while True: + duration = board.pulseIn(pingPin, "HIGH") + inches = duration/72./2. + cent = duration/29./2. + print inches,"inches" + time.sleep(0.1) + +def LCD(tx,baud,ssbaud,message, port=""): + """ + Prints to two-line LCD connected to + pin tx + """ + board = Arduino(baud, port=port) + board.SoftwareSerial.begin(0,tx,ssbaud) + while True: + board.SoftwareSerial.write(" test ") + + + + +if __name__=="__main__": + Blink(13,9600) + #LCD(5,9600,9600," test ") + #adjustBrightness(5,11,9600) #softBlink(11,9600) \ No newline at end of file From 40bd0d76852b71bd0f422793b2e773c6764be9e0 Mon Sep 17 00:00:00 2001 From: Sjoerd Dirk Meijer Date: Thu, 2 May 2013 21:59:45 +0200 Subject: [PATCH 11/13] moved version-check to function --- Arduino/arduino.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/Arduino/arduino.py b/Arduino/arduino.py index cd7749a..98f0ae2 100644 --- a/Arduino/arduino.py +++ b/Arduino/arduino.py @@ -45,18 +45,12 @@ def __init__(self,baud=9600,port="",timeout=2): ports = glob.glob("/dev/ttyUSB*") for p in ports: print 'Found ', p + version = None try: print 'Testing ', p self.sr = serial.Serial(p, self.baud,timeout=self.timeout) time.sleep(2) - cmd_str=''.join(["@version%$!"]) - try: - self.sr.write(cmd_str) - self.sr.flush() - except: - pass - version = self.sr.readline().replace("\r\n","") - #print version + version = self.version() if version != 'version': raise Exception('This is not a Shrimp/Arduino!') self.port = p @@ -71,6 +65,17 @@ def __init__(self,baud=9600,port="",timeout=2): self.SoftwareSerial = SoftwareSerial(self) self.Servos = Servos(self) self.sr.flush() + + def version(self): + cmd_str=''.join(["@version%$!"]) + try: + self.sr.write(cmd_str) + self.sr.flush() + except: + pass + version = self.sr.readline().replace("\r\n","") + return version + def findPort(self): """ @@ -245,6 +250,7 @@ def pulseIn_set(self,pin,val,numTrials=5): return -1 def close(self): + self.sr.flush() self.sr.close() def digitalRead(self,pin): From 017eb99c96a08fe3922c68ccc2a425bf92501b3f Mon Sep 17 00:00:00 2001 From: Sjoerd Dirk Meijer Date: Thu, 2 May 2013 22:26:10 +0200 Subject: [PATCH 12/13] code-cleanup --- Arduino/arduino.py | 51 +++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/Arduino/arduino.py b/Arduino/arduino.py index 98f0ae2..d33b207 100644 --- a/Arduino/arduino.py +++ b/Arduino/arduino.py @@ -1,7 +1,6 @@ #!/usr/bin/env python from serial.tools import list_ports import serial, time -##SDM import platform if platform.system() == 'Windows': import _winreg as winreg @@ -9,6 +8,7 @@ import glob import itertools + def enumerate_serial_ports(): """ Uses the Win32 registry to return a iterator of serial (COM) ports existing on this computer. @@ -25,7 +25,7 @@ def enumerate_serial_ports(): yield (str(val[1]))#, str(val[0])) except EnvironmentError: break -##SDM + class Arduino(object): def __init__(self,baud=9600,port="",timeout=2): @@ -36,7 +36,6 @@ def __init__(self,baud=9600,port="",timeout=2): self.baud = baud self.timeout = timeout self.ss_connected=False -##SDM self.port = port if self.port == "": if platform.system() == 'Windows': @@ -59,13 +58,11 @@ def __init__(self,baud=9600,port="",timeout=2): except Exception, e: print "Exception: ", e pass -##SDM - #--self.sr = serial.Serial(self.port, self.baud,timeout =self.timeout) - #--time.sleep(2) self.SoftwareSerial = SoftwareSerial(self) self.Servos = Servos(self) self.sr.flush() + def version(self): cmd_str=''.join(["@version%$!"]) try: @@ -86,6 +83,7 @@ def findPort(self): if ("FTDIBUS" in pt[-1]) or ("usbserial" in pt[-1]): self.port = pt[0] return + def digitalWrite(self,pin,val): """ @@ -107,6 +105,7 @@ def digitalWrite(self,pin,val): except: pass + def analogWrite(self,pin,val): """ Sends analogWrite pwm command @@ -127,6 +126,7 @@ def analogWrite(self,pin,val): except: pass + def analogRead(self,pin): """ Returns the value of a specified @@ -166,6 +166,7 @@ def pinMode(self,pin,val): self.sr.flush() except: pass + def pulseIn(self,pin,val): """ @@ -175,7 +176,6 @@ def pulseIn(self,pin,val): pin: pin number for pulse measurement returns: duration : pulse length measurement - """ if val=="LOW": pin_ = -pin @@ -192,6 +192,7 @@ def pulseIn(self,pin,val): return float(rd) except: return -1 + def pulseIn_set(self,pin,val,numTrials=5): """ @@ -238,7 +239,6 @@ def pulseIn_set(self,pin,val,numTrials=5): if rd.isdigit() == True: if (int(rd) > 1) == True: durations.append(int(rd)) - #print durations if len(durations) > 0: duration = int(sum(durations)) / int(len(durations)) else: @@ -248,10 +248,12 @@ def pulseIn_set(self,pin,val,numTrials=5): return float(duration) except: return -1 + def close(self): self.sr.flush() self.sr.close() + def digitalRead(self,pin): """ @@ -274,6 +276,7 @@ def digitalRead(self,pin): except: return 0 + def Melody(self, pin, melody, durations): """ Plays a melody. @@ -312,14 +315,12 @@ def Melody(self, pin, melody, durations): d = str(durations[duration]) cmd_str = cmd_str+d+"%" cmd_str = cmd_str[:-1]+"$!" - #print cmd_str try: self.sr.write(cmd_str) self.sr.flush() except: pass cmd_str=''.join(["@nto%",str(pin),"$!"]) - #print cmd_str try: self.sr.write(cmd_str) self.sr.flush() @@ -330,6 +331,7 @@ def Melody(self, pin, melody, durations): else: return -1 + def capacitivePin(self, pin): ''' Input: @@ -347,15 +349,13 @@ def capacitivePin(self, pin): self.sr.write(cmd_str) rd = self.sr.readline().replace("\r\n","") if rd.isdigit() == True: - #print "rd: " + str(rd) return int(rd) -##SDM class Shrimp(Arduino): def __init__(self): Arduino.__init__(self) -##SDM + class Wires(object): """ @@ -364,6 +364,7 @@ class Wires(object): def __init__(self, board): self.board = board self.sr = board.sr + class Servos(object): """ @@ -374,6 +375,7 @@ def __init__(self, board): self.board = board self.sr = board.sr self.servo_pos = {} + def attach(self,pin,min = 544, max = 2400): cmd_str=''.join(["@sva%",str(pin),"%",str(min),"%",str(max),"$!"]) @@ -389,6 +391,7 @@ def attach(self,pin,min = 544, max = 2400): return 1 except: return 0 + def detach(self,pin): cmd_str=''.join(["@svd%",str(position),"$!"]) @@ -399,6 +402,7 @@ def detach(self,pin): pass del self.servo_pos[pin] + def write(self,pin,angle): position = self.servo_pos[pin] cmd_str=''.join(["@svw%",str(position),"%",str(angle),"$!"]) @@ -407,6 +411,7 @@ def write(self,pin,angle): self.sr.flush() except: pass + def writeMicroseconds(self,pin,uS): cmd_str=''.join(["@svw%",str(position),"%",str(uS),"$!"]) @@ -415,6 +420,7 @@ def writeMicroseconds(self,pin,uS): self.sr.flush() except: pass + def read(self,pin): if pin not in self.servo_pos.keys(): @@ -433,6 +439,7 @@ def read(self,pin): except: return None + class SoftwareSerial(object): """ Class for Arduino software serial functionality @@ -442,6 +449,7 @@ def __init__(self,board): self.sr = board.sr self.connected = False + def begin(self,p1,p2,baud): """ Create software serial instance on @@ -460,6 +468,7 @@ def begin(self,p1,p2,baud): else: self.connected = False return False + def write(self,data): """ @@ -479,6 +488,7 @@ def write(self,data): else: return False + def read(self): """ returns first character read from @@ -493,18 +503,3 @@ def read(self): return response else: return False - -##if __name__=="__main__": - # quick test -## board=Arduino(9600, 'COM9') -## board.Servos.attach(9) -## board.Servos.write(9,90) -## time.sleep(1) -## print board.Servos.read(9) -## t=time.time() -## board.Servos.write(9,1) -## while True: -## a=board.Servos.read(9) -## if a == 1: -## print "time",time.time() - t -## break From 9231eb17006d1c5ebfe1dcc2e92b376b8772b85b Mon Sep 17 00:00:00 2001 From: Tristan Hearn Date: Sat, 4 May 2013 11:10:09 -0400 Subject: [PATCH 13/13] a bit of restructuring, fixed Linux check to cover OSX/Darwin and other unix shell OSs --- Arduino/arduino.py | 47 ++++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/Arduino/arduino.py b/Arduino/arduino.py index d33b207..c1cd67b 100644 --- a/Arduino/arduino.py +++ b/Arduino/arduino.py @@ -4,7 +4,7 @@ import platform if platform.system() == 'Windows': import _winreg as winreg -if platform.system() == 'Linux': +else: import glob import itertools @@ -38,26 +38,7 @@ def __init__(self,baud=9600,port="",timeout=2): self.ss_connected=False self.port = port if self.port == "": - if platform.system() == 'Windows': - ports = enumerate_serial_ports() - if platform.system() == 'Linux': - ports = glob.glob("/dev/ttyUSB*") - for p in ports: - print 'Found ', p - version = None - try: - print 'Testing ', p - self.sr = serial.Serial(p, self.baud,timeout=self.timeout) - time.sleep(2) - version = self.version() - if version != 'version': - raise Exception('This is not a Shrimp/Arduino!') - self.port = p - print p, 'passed' - break - except Exception, e: - print "Exception: ", e - pass + self.findPort() self.SoftwareSerial = SoftwareSerial(self) self.Servos = Servos(self) self.sr.flush() @@ -79,10 +60,26 @@ def findPort(self): Sets port to the first Arduino found in system's device list """ - for pt in list_ports.comports(): - if ("FTDIBUS" in pt[-1]) or ("usbserial" in pt[-1]): - self.port = pt[0] - return + if platform.system() == 'Windows': + ports = enumerate_serial_ports() + else: + ports = glob.glob("/dev/ttyUSB*") + for p in ports: + print 'Found ', p + version = None + try: + print 'Testing ', p + self.sr = serial.Serial(p, self.baud,timeout=self.timeout) + time.sleep(2) + version = self.version() + if version != 'version': + raise Exception('This is not a Shrimp/Arduino!') + self.port = p + print p, 'passed' + break + except Exception, e: + print "Exception: ", e + pass def digitalWrite(self,pin,val):