Establishing serial communication between Max and Arduino

jennawhelan's icon

Hi all,

I'm intermediate level Max and Arduino. I've done lots of standalone work in each. However, I've been working on a sound installation for a while which uses both programs, and I'm looking for some guidance re a Max patch that will read and transmit serial data from Arduino.

The hardware currently has 12 touch sensors, which are coming from a " target="_blank">MPR121 cap sensor chip. This input data is read by Arduino. And the next step is to bring it into Max.

I've been using the Serial object in Max, and selecting my USB/Arduino as the port, however data is not transmitting. I have two main questions:

1) Any ideas on what I might be doing wrong re transmission of data? (baud rates are same, I've thought of all the obvious stuff - to my knowledge!)

2) Is it necessary to go another route and use a product such as Maxuino?

Thanks in advance for your time and thoughts.

jennawhelan's icon

Apologies, Arduino code is here below; https://www.sparkfun.com/products/9695 is the link for the Capacitive Touch Sensor chips, which is less relevant...

/*!
* @filename capactivite_prox_sensor_mpr121.ino
* @author Julio Terra
* @date May 22, 2013
* @version 1.0.1
*
* Please check-out the read-me for details about how to hook-up the Arduino and the MPR121
* breakout boards.
*
*/

#include "mpr121.h"
#include

#define SENSORS 13
#define TOU_THRESH 0x1F
#define REL_THRESH 0x1A
#define PROX_THRESH 0x3f
#define PREL_THRESH 0x3c

// variables: capacitive sensing
bool touchStates[SENSORS]; // holds the current touch/prox state of all sensors
bool activeSensors[SENSORS] = {1,1,1,1,1,1,1,1,1,1,1,1,1}; // holds which sensors are active (0=inactive, 1=active)
bool newData = false; // flag that is set to true when new data is available from capacitive sensor
int irqpin = 2; // pin that connects to notifies when data is available from capacitive sensor

void setup(){

// attach interrupt to pin - interrupt 1 is on pin 2 of the arduino (confusing I know)
attachInterrupt(0, dataAvailable, FALLING);

// set-up the Serial and I2C/Wire connections
Serial.begin(57600);
Wire.begin();

// set the registers on the capacitive sensing IC
setupCapacitiveRegisters();
}

void loop(){
readCapacitiveSensor();
}

/**
* dataAvailable Callback method that runs whenever new data becomes available on from the capacitive sensor.
* This method was attached to the interrupt on pin 2, and is called whenever that pins goes low.
*/
void dataAvailable() {
newData = true;
}

/**
* readCapacitiveSensor Reads the capacitive sensor values from the MP121 IC. It makes a request to
* the sensor chip via the I2C/Wire connection, and then parses the sensor values which are stored on
* the first 13 bits of the 16-bit response msg.
*/
void readCapacitiveSensor(){
if(newData){
//read the touch state from the MPR121
Wire.requestFrom(0x5A,2);
byte tLSB = Wire.read();
byte tMSB = Wire.read();
uint16_t touched = ((tMSB << 8) | tLSB); //16bits that make up the touch states

for (int i = 0; i < SENSORS; i++){ // Check what electrodes were pressed
if (activeSensors[i] == 0) continue;
char sensor_id [] = {'','',''};
switch (i) {
case 12:
sensor_id[0] = 'P';
break;
default:
if (i < 10) {
sensor_id[0] = char( i+48 );
}
else if (i < 12) {
sensor_id[0] = char('1');
sensor_id[1] = char( ( i % 10 ) + 48 );
}
}
if (sensor_id != '') {
// read the humidity level

// if current sensor was touched (check appropriate bit on touched var)
if(touched & (1<
// if current pin was not previously touched send a serial message
if(touchStates[i] == 0){
Serial.print(sensor_id);
Serial.print(":");
Serial.println("touched");
}
touchStates[i] = 1;
} else {
// if current pin was just touched send serial message
if(touchStates[i] == 1){
Serial.print(sensor_id);
Serial.print(":");
Serial.println("not touched");
}
touchStates[i] = 0;
}
}
}
newData = false;
}
}

/**
* setupCapacitiveRegisters Updates all of configurations on the MP121 capacitive sensing IC. This includes
* setting levels for all filters, touch and proximity sensing activation and release thresholds, debounce,
* and auto-configurations options. At the end it activates all of the electrodes.
*/
void setupCapacitiveRegisters(){

set_register(0x5A, ELE_CFG, 0x00);

// Section A - filtering when data is > baseline.
// touch sensing
set_register(0x5A, MHD_R, 0x01);
set_register(0x5A, NHD_R, 0x01);
set_register(0x5A, NCL_R, 0x00);
set_register(0x5A, FDL_R, 0x00);

// prox sensing
set_register(0x5A, PROX_MHDR, 0xFF);
set_register(0x5A, PROX_NHDAR, 0xFF);
set_register(0x5A, PROX_NCLR, 0x00);
set_register(0x5A, PROX_FDLR, 0x00);

// Section B - filtering when data is < baseline.
// touch sensing
set_register(0x5A, MHD_F, 0x01);
set_register(0x5A, NHD_F, 0x01);
set_register(0x5A, NCL_F, 0xFF);
set_register(0x5A, FDL_F, 0x02);

// prox sensing
set_register(0x5A, PROX_MHDF, 0x01);
set_register(0x5A, PROX_NHDAF, 0x01);
set_register(0x5A, PROX_NCLF, 0xFF);
set_register(0x5A, PROX_NDLF, 0xFF);

// Section C - Sets touch and release thresholds for each electrode
set_register(0x5A, ELE0_T, TOU_THRESH);
set_register(0x5A, ELE0_R, REL_THRESH);

set_register(0x5A, ELE1_T, TOU_THRESH);
set_register(0x5A, ELE1_R, REL_THRESH);

set_register(0x5A, ELE2_T, TOU_THRESH);
set_register(0x5A, ELE2_R, REL_THRESH);

set_register(0x5A, ELE3_T, TOU_THRESH);
set_register(0x5A, ELE3_R, REL_THRESH);

set_register(0x5A, ELE4_T, TOU_THRESH);
set_register(0x5A, ELE4_R, REL_THRESH);

set_register(0x5A, ELE5_T, TOU_THRESH);
set_register(0x5A, ELE5_R, REL_THRESH);

set_register(0x5A, ELE6_T, TOU_THRESH);
set_register(0x5A, ELE6_R, REL_THRESH);

set_register(0x5A, ELE7_T, TOU_THRESH);
set_register(0x5A, ELE7_R, REL_THRESH);

set_register(0x5A, ELE8_T, TOU_THRESH);
set_register(0x5A, ELE8_R, REL_THRESH);

set_register(0x5A, ELE9_T, TOU_THRESH);
set_register(0x5A, ELE9_R, REL_THRESH);

set_register(0x5A, ELE10_T, TOU_THRESH);
set_register(0x5A, ELE10_R, REL_THRESH);

set_register(0x5A, ELE11_T, TOU_THRESH);
set_register(0x5A, ELE11_R, REL_THRESH);

// Section D - Set the touch filter Configuration
set_register(0x5A, FIL_CFG, 0x04);

// Section E - Set proximity sensing threshold and release
set_register(0x5A, PRO_T, PROX_THRESH); // sets the proximity sensor threshold
set_register(0x5A, PRO_R, PREL_THRESH); // sets the proximity sensor release

// Section F - Set proximity sensor debounce
set_register(0x59, PROX_DEB, 0x50); // PROX debounce

// Section G - Set Auto Config and Auto Reconfig for prox sensing
set_register(0x5A, ATO_CFGU, 0xC9); // USL = (Vdd-0.7)/vdd*256 = 0xC9 @3.3V
set_register(0x5A, ATO_CFGL, 0x82); // LSL = 0.65*USL = 0x82 @3.3V
set_register(0x5A, ATO_CFGT, 0xB5); // Target = 0.9*USL = 0xB5 @3.3V
set_register(0x5A, ATO_CFG0, 0x0B);

// Section H - Start listening to all electrodes and the proximity sensor
set_register(0x5A, ELE_CFG, 0x3C);
}

/**
* set_register Sets a register on a device connected via I2C. It accepts the device's address,
* register location, and the register value.
* @param address The address of the I2C device
* @param r The register's address on the I2C device
* @param v The new value for the register
*/
void set_register(int address, unsigned char r, unsigned char v){
Wire.beginTransmission(address);
Wire.write(r);
Wire.write(v);
Wire.endTransmission();
}

Nat's icon

Are you banging the serial object with a metro ? (the serial object needs to be polled by a bang at a regular interval to get data)

jennawhelan's icon

Thanks Nat. Yeah I am. It's strange it's not working. I'm currently working on editing the Max Communication Tutorial 2, screenshot attached of the serial object (port d is my USB connection)

- PS: If the Arduino code I already uploaded has a baud rate of 56700 I've already changed it to 9600!

Screen-Shot-2014-05-10-at-12.55.13.png
png
brendan mccloskey's icon

Hi
have you tried connecting a [print] object to the outlet of the [serial] object briefly, to actually visualise what, if anything, your sensors and code are sending to Max?

A quick guess, if the code and circuit are solid, would be a stream of sensor headers, followed by zeros or ones (representing contact state), delimited by a colon character.

I would begin with the Arduino serial monitor window first, to try to edit the code such that YOU impose the style and syntax of transmitted data. I haven't the time or resources to hack your circuit and code sadly but, avoiding Max first, see if you can get the Arduino code to print something like this in your serial monitor window:

1 0
2 0
3 1
4 0
5 0
.....
13 10

representing sensor identifiers (on the left) and contact state second - here it looks like sensor 3 is touched; the entire package is terminated with a carriage return. Search this forum for "Arduino" "multiple sensors" etc for further help.

Good luck

jennawhelan's icon

Hi guys,

Thanks for the info. A great help. So I've got Max reading the incoming data through the serial object. (Delighted to know that I don't have to employ Maxuino or any other outsourcing.)

Then, Noob_Meister, on your advice I have used a print object to print the incoming data. Thank you. Re my Arduino, I do indeed have the Arduino printing that sensor data in the serial monitor window.

Now, if any light could be shed on this! - when one sensor is touched I get a stream of data/numbers, screenshot attached, what is necessary, however, is 1) for the data transmitted to read that the sensor has been touched, and 2) what number sensor has been touched.

I am sure you all have better things to be doing that dealing with my serial problems, but if anyone can point me in the right direction that would be fantastic. My guess is that it's to do with the parsing of data perhaps? Does anyone know an object that can help with this, or does anyone know if this is a problem starting on the Arduino end of things.

Sorry for the questions! I've never worked with serial communication before.

Screen-Shot-2014-05-10-at-14.23.41.png
png
jennawhelan's icon

Right, my guess is zl, iota or fromsymbol objects to make sense of the data - and then an object that will unpack this data?

Am I on the right track?

Nat's icon

the match object will also group data according to a pattern

jennawhelan's icon

Okay, thank you guys. I'm going to read everything on all of these objects and hopefully gain some clarity on the matter.

Nat, I saw your response beneath my other post, will get back to that soon!

jennawhelan's icon

Didn't want to keep bothering you guys about this, have brought up a different topic re sensors here https://cycling74.com/forums/sensor-mapping-in-max/

Thanks for the info!

Emilio Andreozzi's icon

Hi JONNYB, how did you succeed in making Max and Arduino communicate through serial port?
I really can't understand why it's not working: I used the serial objetct [serial a 9600] , enabling the "autoopen", and with the [print] message I verified that the port was COM17, the one used by my Arduino Uno. I verified that by Arduino side it's all right, because I used the serial communication with Matlab software and with Labview software and in both cases I succeeded in reading the messages sent by arduino on COM17 serial port.

To have a regular polling for reading serial data I connected, like everyone did as I see, a metro object [metro 100] to the serial object, and I sent a bang to the metro object with a pushbutton.

I really can't undestand why this patch is not giving any good results.

Please help me! :(

serial-MAX.png
png
jennawhelan's icon

Hi Emilio,

What results are you getting from the serial port (if any)?

Do you have the baud rate 9600 matched on the arduino end?

The data that serial object receives from arduino in Max, needs to be sorted with a few other objects.

Here's what works for me, attached

Good luck!

Screen-Shot-2015-10-13-at-22.16.38.png
png
agustin genoud's icon

Hi all,
been dealing with this the whole week, don't know why really but I doesn't get anything from the serial object, I've checked with the terminal reading the port, processing and even pd; and I could see the data, but nothing with max. A few minutes ago, while reading this post and trying to understand why I've connected a attrui and check what was in there, when I clicked the "dtr" checkbox the data appeared(!)

so, I have no idea what's that but my problem is gone now, hope this helps,

best!

Screen-Shot-2016-05-25-at-6.23.11-PM.png
png
spacessound's icon

Hi All

Also having some serial problems.

Unfortunately the DTR trick hasn't worked for me. I resurrected a patch that reads a sensor (via xbee then arduino) to max and it doesn't work anymore. I tried the MAX serial tutorial and that didn't work until I updated to the latest MAX version. All fixed I thought. Went back to my original sketch and patch but still nothing. I tried opening in MAX 6 ...same result, nada.

I see the data as expected in my serial monitor called up from Arduino but no life in MAX. Any clues where I should be looking to fix this?