Saturday, November 05, 2016

Notes on Teensy, Arduino, Max and USB Serial

There is some nuance to using USB Serial with Arduino and Teensy together with Max that is worth highlighting

I have tested a setup with Teensy 3.5 hardware and Windows 10 as a virtual machine, as seen below. The setup should be comparable when also using Teensy 2.0, LC, 3.2 and 3.6, and Windows 8.0 and 8.1. 
 





In general, the process to get this working is as follows.

Write Arduino Code and Upload to Teensy


  • Select Tools > Teensy 2.0 (or LC, or whichever board is being used)
    • In the example video, this is Teensy 3.5
  • Select Tools > USB Type Serial
  • Select Tools > CPU Speed > 16MHz (or 48MHz, or whichever CPU speed is the native CPU speed)
    • In the example video, this is 120MHz
  • In the setup(), open a Serial port by using Serial.begin(57600) - or at any other baud rate. 57600 should be functionally solid and fast enough.
    • In the example video, this is 57600 baud
  • In the loop(), use Serial.write() to send a value as an unsigned int or byte in the range 0 - 255 to the serial port to Max
    • In the example, a number is incremented from 0 to 255. This number is then sent to the serial port output of the Teensy using the Serial.write() function.
    • This number that is sent could be a value from elsewhere (analog pin, digital pin, random value, value from the i2c bus, value from the SPI bus etc).
    • Note that Serial.print(), Serial.println and Serial.write() are not equivalent.
    • The function used will depend on where the data should end up after it exits the serial port of the Teensy:
      • Serial.print() is most useful when sending serial data from Teensy to the Serial Monitor in the Arduino IDE without generating a line break. This is not useful for sending data to Max. 
      • Serial.print() will send the input argument as a series of ASCII character code bytes. For example, Serial.print(150) - where 150 is a byte or an int - will cause the Teensy to send the ASCII character '1' (which is represented by the byte value 49), followed by the ASCII character '5' (which is represented by the byte value 53), followed by the ASCII character '0' (which is represented by the byte value 48).
      • Three values are sent, and the Arduino IDE reads these three values and prints out the human-readable number 150. Learn more about ASCII values here: http://www.asciitable.com/ and learn more about Serial.print() here https://www.arduino.cc/en/Serial/Print
      • Serial.println() is most useful when sending serial data from Teensy to the Serial Monitor in the Arduino IDE including a line break. This means that each new Serial.println() function will be printed on a new line in the Arduino IDE, making for an easy-to-read list of vertical values and strings. This is not useful for sending data to Max.
      • Serial.print() will send the input argument as a series of ASCII character code bytes. For example, Serial.println(150) - where 150 is a byte or an int - will cause the Teensy to send the ASCII character '1' (which is represented by the byte value 49), followed by the ASCII character '5' (which is represented by the byte value 53), followed by the ASCII character '0' (which is represented by the byte value 48), followed by an ASCII carriage return (which is represented by the byte value 13), followed by an ASCII new line (which is represented by the byte value 13)
      • Five values are sent, and the Arduino IDE reads these five values and prints out the human-readable number 150 followed by a completely new line. Learn more about Serial.println() here https://www.arduino.cc/en/Serial/Println
      • Serial.write() will send all data value from 0 - 255 as discrete byte values, and is most useful for sending data to Max, but will generate unreadable data for the Arduino IDE.
      • Serial.write() will send just the one value, so long as it is in the range 0 - 255. For example, Serial.write(150) - where 150 is a byte or an int - will cause the Teensy to send the byte value 150.
      • Only one value is sent, and this is a number from 0 - 255. Max can easily use this value. Learn more about Serial.write() here https://www.arduino.cc/en/Serial/Write
  • Once the code is ready, upload the code to the Teensy. Select Sketch > Upload. The Arduino IDE will compile the code for the target board, USB speed and type as previously selected. The Teensy loader app should automatically open and then upload the compiled code to the Teensy. It may or may not be necessary to press the reset button on the Teensy, depending on what the Teensy is doing and how it is connected to the computer


Make a Max Patch that Uses the Serial Object




  • Create a new Max patch in Max 7. Communication with the Teensy when in USB Serial mode is accomplished via the serial object. First, it is necessary to find or confirm the correct port letter of the Teensy serial connection.
  • Create a serial object with no arguments. Open the help file for the serial object by alt or option clicking on the serial object, and then click on the print message in the help file.
  • Show the Max console. Select Window > Sidebar Max Console. The Max console should show a list of letters and associated serial ports that are available on that particular computer.
  • Depending on the version of the operating system, Teensy, Arduino, etc, the name of the relevant serial port name may be obvious or it may be necessary to experiment with a few different options. Take note of the letter of the serial port of the Teensy, and close the serial help file.
  • In the Max patch, adjust the serial object, so that it has two arguments.
    • The first argument of the serial object should be the serial port letter as designated above.
      • In the example video, this is c.
    • The second argument of the serial object should be the baud rate as set in the Arduino code.
      • In the example video, this is 57600 baud.
  • To read data into Max that has been sent from the Teensy (using the Serial.write() function in the Arduino code):
    • Simply send a bang to the serial c 57600 (or equivalent)
    • It is recommended to send a bang at regular intervals so as to flush the input buffer of Max and the USB bus of the computer.
      • In the example video, a metro 1 object is used that is turned on / off by a toggle
    • The serial object will output any data that has been received to its single outlet.
  • To send data from Max to the Teensy, simply send a value from 0 - 255 as an integer into the inlet of the serial object.
  • Serial Object Open / Close
    • Note that the serial port on the Teensy can only every be used by a single application on the computer.
      • For example, if Max has a serial object that is active (and set to the Teensy) and open, then the Arduino IDE will not be able to program the Teensy, as the serial port is in use by the Arduino IDE
      • For example, if the Arduino IDE has the serial monitor active and open (and set to the Teensy), then Max will not be able to use a serial object with that particular serial port, as the serial port is in use by the Arduino IDE serial monitor
    • This limitation can be overcome in Max by manually managing the status of the serial object using an 'open' message and a 'close' message
      • Send the 'close' message to the serial object before updating the code of the Teensy via Arduino; read the data input using Arduino IDE serial monitor; or use the serial port with some other software / hardware.
      • Send the 'open' message to the serial object to start using that particular serial port and object again.


Overall, the serial connection on the Teensy / Arduino may seem more difficult to use than expected. The above steps should act as a starting point for both setup and troubleshooting.

1 comments:

Enith said...

Thanks Seb, saving my life in IDSA rn!