Serial port data coming in as one huge number

nicnut's icon

Hi,

I am a long time Max user, but I have never used serial data from a sensor with Max so I'm having a problem.

I have an Arduino with a sensor. The readings are coming into Max with the serial object, but they are coming in as one really long string of integers. I am having a problem splitting this up into a list.

For example, I am getting: .1315.1315.1315.1315.1315.1315.1315.1315.1315.1315.1315.1315.1315.1315.1315.1315

If I touch the sensor this value changes, but it's basically a big huge number. I tried zl group to break it down to 4 digits, but it seems like the decimal point will move around, like 1.315 315.1 15.13, etc.

Ideally I would like the look at the numbers, take an average, and the highest and lowest value within a given time frame, like every 30 seconds or something.

Can anyone suggest something to remedy this situation so I can break this data down into a list? I looked at the Communications tutorial 2 already. The patch I have is sort of based on that.

Here's my arduino sketch:

#define Version 11 // version, 1.0 or 1.1, which depands on your board you use as it is
const int pinO2 = A0;

#if Version==11
const int AMP = 121;
#elif Version==10
const int AMP = 201;
#endif

const float K_O2 = 7.43;

void setup()
{
Serial.begin(115200); //Start the Serial connection
}

void loop()
{
float sensorValue;
float sensorVoltage;
float Value_O2;

sensorValue = analogRead(A0);
sensorVoltage =(sensorValue/1024.0)*3.3;
sensorVoltage = sensorVoltage/(float)AMP*10000.0;
Value_O2 = sensorVoltage/K_O2;


Serial.print(Value_O2); // this is the value I am using

delay(50); // I seem to get better values with the delay
}

Here is my max patch

Max Patch
Copy patch and select New From Clipboard in Max.

Source Audio's icon

As first use this

Serial.println(Value_O2);

that would allow you to output single floats in max,
which you can later group and calculate averrage etc.

Max Patch
Copy patch and select New From Clipboard in Max.

To ease serial flow a bit, you could send values from arduino only if it changes, instead of using delay...

nicnut's icon

@sourceaudio, thank you very much for the reply.

I think I tried serial.println and it seemed to only give me values if the Arduino application was open (i'm using a mac). I will try it again though, maybe I did something wrong.
That's a great idea to only send values if they change, I will implement that.

Another thing I did last night was just use the "SimpleAnalogFirmata" example, from the Arduino Firmata examples on the Arduino side, and Maxuino on the max side. It worked really well with barely any set up. The only thing is that I am not sure if I am getting the correct values from the sensor, and it is also scaled way down so the values are pretty different. I will look into that today because it's pretty easy, but I want to make sure I am reading the sensor correctly, and it's kind of weird because it's not a sensor I can just touch or apply pressure to, as it measures the conductivity of human skin, so it's sort of weird to work with.

Source Audio's icon

I would try to avoid using maxuino.

Only one application at a time can talk to serial port.
If you have arduino app running, you must close serial monitor in order
to use serial port in max.
If you want to keep max patch open and upload code to the board
or use serial monitor, you must close serial port in max.
And activate it again using port a or port d ,
whatever assigned number message.
-------
Indeed that patch looks a bit overcomplicated, scaling and dividing is made several times.
Which board do you use ?

You can of course send raw analog readout to max and do the math there.
You are dividing the Input range 0-1024 to 0. 1., than multiplying by 3.3,
then dividing by 121, again multiplying by 10000. , then again dividing by 7.43 ???
could that not be a bit simpler ?

This is all you need in arduino :

// --------------
int sensor;
int EXsensor;

void setup() { Serial.begin(115200);}

void loop() {sensor = analogRead(A0);
if (sensor != EXsensor) {Serial.println(sensor); EXsensor = sensor;}
delay(10);}
// --------------

Max Patch
Copy patch and select New From Clipboard in Max.

nicnut's icon

Hi Source Audio,

I downloaded that Arduino sketch and just adapted it a little. I didn't even look at the math, but damn, you are right! crazy math and number scaling.

I implemented your previous suggestions, using Serial.println, which gave me one number at a time, and only sending a value when the sensor value changes, using an "if" statement, and that simplified things A LOT. Now everything seems ok and I can use the data and get it into Max OK.

There is an issue with the decimal point moving around, like sometimes I get:

.15.10
15.10.
1.510.

Not sure what I can do about that. I might clean up that math that you pointed out, but I don't really know what this sensor is doing so I feel unsure of changing any of those numbers. Thank you very much for your help by the way. At least now I am getting some usable data.

Source Audio's icon

What sensor is it exactly ?
If you look at the formula,
as first range 0 -1024 gets scaled to float 0. -1.
and then multiplied by 3.3 which could indicate
interpreting input as dc voltage 0 - 3.3
the rest then ...
There is no library included that would make anything special
about that defined constants AMP, pin02 etc.
defining :
float sensorValue;
float sensorVoltage;
float Value_O2;
at the beginning of each loop iteration is not a good thing to do,
float calculations with high precision are not the highlight of ATMEGA based arduinos.
That sketch is all but well done.
I would really suggest using raw output from arduino and do the rest in Max.

Just think how many calculations could be avoided if you average 8 integers 0 - 1024
and just calculate the result at the end ?
Analog reading won't give you any terrible precision
with 1024 steps.
That formula at the end scales 0 -1023 to 0. - 36.670383
using 1024 steps.

Max Patch
Copy patch and select New From Clipboard in Max.

nicnut's icon

Hi Source Audio,

It's a Seed studio Grove GSR sensor. It measures conductivity on your skin, which is supposed to measure stress levels:

I basically downloaded that sketch from Grove, but it was for an Oxygen sensor. I didn't modify it much.

OK, so I should probably declare those variables global, and not have them in the loop of the Arduino sketch. And try and do all the math in Max. I am fine with working with integers, it might even be easier. The scaling part is very easy to do in Max.

Ok I will try and implement some changes and post what I have for my Arduino sketch

nicnut's icon

Here's the Arduino sketch. I moved the variables to be globally declared.

I am a little nervous about messing with the math/scaling, as I don't know what it's supposed to do. The 3.3 part might have to do with voltage, so I don't want to touch that. And I don't know what the AMP variable is for, but maybe I should leave it there in case I need to change that value (if I ever figure out what it is). I could always comment everything out and see what happens of course, it's easy enough to change.

I did include the "if" statement to send a value to Max only if something changes.

// test Grove – I am using GSR sensor

#define Version 11 // version, 1.0 or 1.1, which depands on your board you use as it is
const int pinO2 = A0; // Connect Grove – Gas Sensor(O2) to A0. GSR sensor

#if Version==11
const int AMP = 121;
#elif Version==10
const int AMP = 201;
#endif

float sensorValue;
float sensorVoltage;

const float K_O2 = 7.43;
float Value;
float previousValue = 10;

void setup()
{
Serial.begin(115200); //Start the Serial connection
}

void loop()
{

sensorValue = analogRead(A0);
sensorVoltage = (sensorValue / 1024.0) * 3.3;
sensorVoltage = sensorVoltage / (float)AMP * 10000.0;
Value = sensorVoltage / K_O2;

// only transmit Value_02 if the input has changed

if ( Value != previousValue) {
previousValue = Value;
Serial.println(Value, 3);
}
}

Source Audio's icon

using code of gas sensor for resistance sensor ?
what do you expect from that ?
by chance I had once to deal with that oxigen sensor.
All example code were simply shit, not working and wrong.
maybe that changed in the meantime, I don't know.

Why don't you use examples for GSR sensor instead ?

https://wiki.seeedstudio.com/Grove-GSR_Sensor/

there it simply averages 10 readings of plain analog readout
and prints it out.
but you can also use the code I posted...


nicnut's icon

Source Audio, OK I'm gonna look into that code.

I don't have that base station that you use for those Seed Studio sensors, so I connected the sensor to the arduino with jumper cables. The O2 sensor code is the only example code I could find for connecting it that way.

You are absolutely right, I should try and get some different example code. The one in the link you pointed to looks good, and I don't think I need the base station. You are again giving me some really valuable info. Thank you so much!

Source Audio's icon

You will get that running in no time.
If your arduino board is 5 volt version, than feed 5 volt to the sensor V in pin.
Sensor will then output 0 - 5 v
if arduino is 3.3 volt type, than just use 3.3 v to power the sensor board.
Again sensor outputs min 0, max 3.3 v
No need to adjust or divide anything.
Analog readout also depends on board, older arduinos max at 0 - 1023 (10bit)
some boards have 0 - 4095 (12bit) range
(most of the ARM-based devices like  Zero, Due, Teensy etc )
-----
For that GSR sensor it is very important, to adjust the sens trim pot in free air
(not touching it)
so that output reads middle of the scale, in case of 10bit ADC exactly 512.
otherwise the given formula to get resistance in ohm will not work:

((1024+2*Serial_Port_Reading)*10000)/(512-Serial_Port_Reading)

The values 1024 and 512 are set for use on 10bit ADC arduino models.
Serial_Port_Reading is the input which would not exceed 512 if adjusted so in free air.

in max use expr object :
expr ((1024+2*$i1)*10000)/(512-$i1)

output is then in Ohm.
divide by 1000. to get kilo ohm and again by 1000. to show mega ohm range
At input 0 it says 20 kohm, at input 512 it is 20.48 mega ohm.
----------
If your arduino has 12bit resolution, divide it in arduino sketch :

int sensor = analogRead(A0 / 4);

nicnut's icon

@SourceAudio, Wow amazingly helpful info thanks. I have an Uno and it's connected to 3.3V so I should be good. I will follow these instructions. I didn't even notice the trim pot.

Thank You!!

Source Audio's icon

Arduino UNO is 5 volt device if I remember correctly.
So power the sensor with 5 volt to have analog readout correct.
If you power the sensor with 3.3 volt, than you would need to change
analog input voltage reference to 3.3 volt.
There is really no need for that as GSR sensor works with 5 volt.

nicnut's icon

I'm sorry, I miss spoke. I have Arduino Uno Rev 3. It has 3.3v