I have yet to see a nice simple and expandable approach to communication between Pd and Arduino, especially one that sends more than one value. It can be tricky, especially on the Pd side.
This example reads in 3 digital pins, 3 analog pins and sends out 3 values which then are used to drive 3 PWM outputs, however each of these can be easily changed to support more or less I/O.
This will be posted in three parts, first digital, then analog and lastly writing data from Pd back to an Arduino.
Reading in digital values:
In the Arduino code an array is used to list the pins which are to be read. You can change this as needed and everything else should take care of itself on the Arduino side. There is a loop based on the size of the array which will read through all these digital pins and print them to the Serial port.
First the Arduino code must initialize the serial port. This example uses 115200 baud but you can change it. However note that if you go too slow you can see issues depending on how much data you are sending. Here is the Arduino code:
This code sends a “D” followed by the digital values it reads on 3 of the pins (in a for loop) then a lower-case “d” is sent to indicate the end of the packet.
NOTE: all the data sent to Pd uses Serial.println()
This is because Pd does not have great ways to parse strings and characters. Everything comes in as a byte and so it is tricky to keep track of things since depending on the number there will be a different number of bytes (i.e. the number 5 is one byte, the number 15 is two bytes). There are other ways of dealing with this, this is mine.
This is based on an approach found here by Alexandros Drymonitis.
The Pd patch
On the Pd side serial communication uses the [comport] object. Create a new object named: [comport 4 115200]
The comport object can read and write to a serial port. In this case I specified port 4 and a baud rate of 115200. On your machine the port may be different. To see the list of ports create a message box with the message [devices<
Connect this to the [comport] object and click on the message box. You should get a list of the serial ports in the Pd window. Here’s mine:
The port with tty.usbserial* is my Arduino.
I also put a [close< and [open 4< message boxes in to open and close communications with Arduino. (The 4 here again is where my Arduino shows up).
With the port open the data should flow into the Pd patch.
Formatting the digital inputs:
The capital “D” which is being sent before the digital values is used to format the data. A capital “D” is 68 in ASCII. So first I look for a 68 coming through. This opens a gate and resets the list in the[list append] object.
The 3 values received are packed into a list which can then be “unpacked” to individual outputs. This is done with a few more objects [list prepend], [t l] and [unpack]. When the “d” is seen the gate closes.
You need an “f” in the [unpack] object for every value you are reading. So if you are using 12 digital inputs there should be 12 “f”s.
This is what it looks like inside the read_digital sub-patch. The parse-start-stop.pd file can take in two creation arguments. The start and stop bytes which surround the packet of data. These can be changed to whatever you need. If you want to use different characters to begin and end a packet, just figure out what the ASCII value is and make the changes in the parse-start-stop object.
The 3 values come out of the [unpack f f f] object.
Part 2 of this tutorial will add 3 Analog values.