Problems With Serial Communication to Arduino
Hi All,
Long time reader, first time poster. I have a question in regard to serial communication from Max MSP to Arduino which controls some servo motors. (I am also going to post the same question in the Arduino forum)
I have tested the Max patch serial output and it is reading correctly in the Max Window. When I then use it with Arduino, I can see the Tx/Rx LED's flash when a number has been output. However, when I add the final component, the servo, it doesn't want to work/move.
To give some context, I have a matrix in Max with 4 rows and 32 columns. Each row is assigned a 'bit number' for the purposes of communicating to a specific servo. when the patch is run, each time a highlighted matrix point is passed, it sends the assigned 'bit number' out of the serial port.
Arduino then reads the 'bit number' and goes through it's code and sends it to the specific pin to move the servo motor.
When I use the serial monitor with Arduino and send the bit number manually, the servo moves.
Example of code below using 'bit number' 120 as dummy number and moving the servo to 45 degrees and then back to Zero. (virtually tested using TinkerCAD (manual number assignment).
Here is my patch (v6.1 as i am usings OSx 10.10)
#include <Servo.h>
Servo myServo;
int pos = 45;
int incomingByte = 0;
void setup() {
Serial.begin(9600);
myServo.attach(9);
myServo.write(0);
}
void loop() {
for(pos = 0; pos <= 45; pos += 1)
if(Serial.available()) {
int incomingByte = Serial.parseInt();
if(incomingByte == 120) {
myServo.write(pos);
delay(1000);
myServo.write(0);
delay(1000);
}
}
}
1- you have 6 serial objects in that patch ???
2- the patchers pairs are not included, so one can't see what you are sending out.
I guess you have no atoi object inside, or ?
and don't send line feed after the number ?
-------
then ...
running pos 0 - 45 at loop beginn, and if 120 is received
grab current pos, write it to servo, del 1000, send to zero, del 1000.
is that really what you want ?
current pos at the moment 120 got received could be any number between 0 and 45
Hi SOURCE AUDIO, thank you for your reply!
1- OK, so I don't have 6 serial objects that need to read the data, only 1. However I thought if I added them all it would save any fault finding later because Max would automatically find the correct port available. But since you have pointed this out, I do realise it is a bit stupid and I should just stick to the port I am working with.
2- Pairs subpatch attached for reference.
3- I was re working the code yesterday and found a better solution to what I am trying to do. But essentially I want the servo's to wait at position 0 until relevant data to the pin on Arduino is read and then move to 45, delay, move back to 0, and wait again until its number is called.
The issue that I am having is that everything works when I test individually;
- Max is outputting numbers i want
- Arduino is receiving data
- When using Arduino serial monitor and manually typing incomingByte, servo moves to 45 and back
However when I test all in sequence and connected, the servo refuses to move. I did see in another forum that code needs to be uploaded to Arduino, and Arduino software closed BEFORE Max is opened. This fixed my problem with Arduino receiving data but had no effect on the servo's movement.
I suppose my question is, is why would everything work logically/individually but not in sequence? Is there something I am missing somewhere?
Wiring is standard 5vOUT to servo power, GND to servo GND, PIn9 to Servo data. Could it be that I am powering the Arduino via USB and not external power source? Or is something inherently wrong with the patch?
Thanks again for the reply and I hope I am starting to make sense.
New code below
#include <Servo.h>
Servo myServo;
int pos = 45;
byte incomingByte = 0;
boolean newData = false;
void setup() {
Serial.begin(9600);
myServo.attach(9);
myServo.write(0);
Serial.println("born and ready for action");
}
void loop() {
recvData();
moveServo();
}
void recvData() {
if(Serial.available() > 0) {
incomingByte = Serial.read();
newData = true;
}
}
void moveServo() {
if(newData == true && incomingByte == 3) {
Serial.println(incomingByte);
myServo.write(pos);
delay(100);
myServo.write(0);
delay(100);
newData = false;
}
}
"- Max is outputting numbers i want
- Arduino is receiving data"
As first you are missing the most important thing:
max serial objects sends data to arduino as ascii bytes.
if you simply input integer into serial object,
it will become decimal code for the ascii char.
120 in you dummy example would be letter x.
you must insert atoi object between data you want to send and serial object.
In other words, you think that serial object is sending the number,
because you print and see it in max console, but that has nothing to do
with serial object's output.
120 should be sent out as 49 50 48 - 3 digits.
arduino has to parse that into integer.
parse.int in arduino has few drawbacks, as it has to wait till
all digits are collected into a single int, and must receive either a
non digit ascii char or linefeed at the end, to collect all digits into a int.
if it does not receive that, it will wait for default timeout
of 1000 ms and output zero.
-----------
that is one part of your problem.
the other is that none of your 2 arduino sketches can function.
the second one because you don't
parse the int.
number 3 would be ascii 51.
the line if(newData == true && incomingByte == 3)
That could work for single digit number, but as soon
should be
if(newData == true && incomingByte == 51)-------
as you need 2 or more digits it would fail.
--------
This would be sending part in max

in arduino :
#include <Servo.h>
Servo myServo;
int pos = 45;
int incomingByte = 0;
void setup(){Serial.begin(9600); myServo.attach(9);myServo.write(0);
}
void loop() {if(Serial.available() > 0) {
int incomingByte = Serial.parseInt();
if (Serial.read() == '\n'){if(incomingByte == 3)
{myServo.write(pos); delay(100); myServo.write(0);}
}}}
--------
Depending on number of servos in use,
I would send numbers to directly move THAT servo
from max, and no need for if bla bla then.
for example by putting servo pins into array.
P.S.
that pairs patchers are also not ok.
each slice of 4 column cells used to set 2 kicks and 2 snares
outputs something on match, and you get double results
if for example 1 kick and 1 snare are active in one step.
that 2 fast numbers get sent to serial object one after another.
maybe you want to do that 4 bit binary to int way , or to simply trigger 4 servos which represent the 4 cells ?
Hi SOURCE AUDIO,
Thanks again for the info!
To comment on your first point re; ascii bytes. As I was playing around with the code I did notice that when I input 120 to the Arduino serial monitor, it did in fact output 49, 50, 48 and the servo moved multiple times. I then changed the code to be if(newData == true && incomingByte == 51) and found that key press '3' was outputting 51 in serial monitor. Once I added more servo's to the test circuit and input '234' the servo's ran in sequence one after the other and output 50, 51, 52 in the monitor - which is fine as the servo's are not supposed to be triggered at the same time (but something that may be of use in the future). The number 120 was just an arbitrary value and it doesn't need to be that. If I was to scale the project to use more servo's, I wouldn't use more than 10 servo's (0-9). But at the moment, 4 is what I will be using for the foreseeable future.
To comment on your second point about the subpatch, I wasn't thinking too much when I was implementing it (as I was following a tutorial and was amending as I was going to how I thought I could use it). In saying that, when I first ran the patch and monitored the output in Max, I did notice that when 2 cells are selected on the same column the output number increased to higher values than expected and confused me. But in honesty I didn't think anything of it. Again, now that it has been pointed out to me, oh how silly of me! I will definitely implement your suggestion and not run any 'pairs', and will target individual servo's with single digit numbers in the output.
I will update the code and the patch and let you know how I go.
Again, thank you so much for responding so quickly and providing info. I greatly appreciate it!