Adding zeros before an int

Antti Ikonen's icon

Hey,

I'm trying to send this kind of date from Max to Arduino over serial port.
https://www.youtube.com/watch?v=hAFv7o5cG2o&t

So I would need to convert numbers 1 to 001, 2 to 002, 10 to 010 and so on.

I found this thread from the forum which was sort of about the same issue, but it didn't solve it.
https://cycling74.com/forums/format-date-number-to-2-digits-01-02-03-09-10-etc

There is the patch so far. There are four different values between 0 and 180, that would need to be formatted from 10 2 40 180 to 010002040180. It works other ways, except it drops the first zeros out.

sprintf test.maxpat
Max Patch

Source Audio's icon

what is exactly the problem ?
Max will not allow you to use numbers with leading zeros, only as symbol.
But that is not a problem to send to arduino or ?

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

Antti Ikonen's icon

So, I'm trying to control multiple servos in arduino by sending data from Max. I haven't tried yet, that is it possible to send the data symbols. I think Arduino might think the quotation marks as some symbols as well. I'm very new to arduino and so far I've only succeeded to control one servo from Max. I have an Adafruit's PWM servo driver and I'm trying to add part of this patch to my patch in Arduino IDE.
https://www.youtube.com/watch?v=hAFv7o5cG2o&t

I have understood that the command string.read in Arduino would be one option, but I haven't really found any good examples how would it work in practice.

Source Audio's icon

I am sorry, but I don't have time to watch any youtube videos.
Controlling servos in arduino has been done and it works, there is no mistery about it.
No matter where serial data come from.
You need to set serial communication and decide how to address individual channels
you either allways send 4 values as list ( and forget that leading zeroes)
and collect the 4 values in arduino, then dispatch them to 4 servo outputs.
Or you prepend something like a b c d for each servo
and then in arduino route the value to servo 1 if it was prepended by a.

Source Audio's icon

here is one example how it could look like :

void setup() {
Serial.begin(115200); // set baud depending on speed needed ...
}

void loop() {
if (Serial.available() > 0) {
int SERVO-0 = Serial.parseInt();
int SERVO-1 = Serial.parseInt();
int SERVO-2 = Serial.parseInt();
int SERVO-3 = Serial.parseInt();
if (Serial.read() == '\n') {
pwm.setPWM(0, 0, SERVO-0); pwm.setPWM(1, 0, SERVO-1); pwm.setPWM(2, 0, SERVO-2); pwm.setPWM(3, 0, SERVO-3);
}}}
----------------
This is just part of serial communication.
when list of 4 numbers gets received, the values get sent to
servos 0 1 2 3

in max just send a list with 4 values
like 100 22 33 128

Antti Ikonen's icon

Amazing! Thank you very much! I'll try to include that to my old patch.

Source Audio's icon

As alternative, and in case many units need to be controlled fast,
one would go different path, prepending ID for each channel
or adding "master" control

This is one example using 10 softPWMs to fade leds

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

It can be easily adapted for other things, and reduced or expanded.
Main goal is to avoid sending full list for all channels if just one or few changed...

Antti Ikonen's icon

So, I've been trying to get your example code implemented to my earlier working patch, but it doesn't work for some reason. Can you spot where did I go wrong?

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

#define SERVOMIN0 155 // This is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX0 557 // This is the 'maximum' pulse length count (out of 4096)

#define SERVOMIN1 175 // This is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX1 520 // This is the 'maximum' pulse length count (out of 4096)

#define SERVOMIN2 155 // This is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX2 557 // This is the 'maximum' pulse length count (out of 4096)

#define SERVOMIN3 155 // This is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX3 557 // This is the 'maximum' pulse length count (out of 4096)

#define SERVO_FREQ 50 // Analog servos run at ~50 Hz updates

int val0;
int val1;
int val2;
int val3;

int pulse0;
int pulse1;
int pulse2;
int pulse3;

int angle0;
int angle1;
int angle2;
int angle3;

void setup() {
Serial.begin(9600);

pwm.begin();

pwm.setPWMFreq(SERVO_FREQ); // Analog servos run at ~50 Hz updates

yield();
}

void loop() {

pulse0 = map(angle0, 0, 180, SERVOMIN0, SERVOMAX0);
//Serial.print("Angle0: ");Serial.print(angle0);
//Serial.print(" pulse0: ");Serial.println(pulse0);
pwm.setPWM(0, 0, pulse0);

pulse1 = map(angle1 ,0, 180, SERVOMIN1, SERVOMAX1);
//Serial.print("Angle1: ");Serial.print(angle1);
//Serial.print(" pulse1: ");Serial.println(pulse1);
pwm.setPWM(1, 0, pulse1);

pulse2 = map(angle2 ,0, 180, SERVOMIN2, SERVOMAX2);
//Serial.print("Angle2: ");Serial.print(angle2);
//Serial.print(" pulse2: ");Serial.println(pulse2);
pwm.setPWM(2, 0, pulse2);

pulse3 = map(angle3 ,0, 180, SERVOMIN3, SERVOMAX3);
//Serial.print("Angle3: ");Serial.print(angle3);
//Serial.print(" pulse3: ");Serial.println(pulse3);
pwm.setPWM(3, 0, pulse3);

if (Serial.available() > 0 ) {
val0 = Serial.parseInt();
Serial.println(val0);
val1 = Serial.parseInt();
Serial.println(val1);
val2 = Serial.parseInt();
Serial.println(val2);
val3 = Serial.parseInt();
Serial.println(val3);

if (Serial.read() == '\n') {
angle0 =val0;
angle1 =val1;
angle2 =val2;
angle3 =val3;
}
}
}

Antti Ikonen's icon

This is the earlier working patch that has only one servo.

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

#define SERVOMIN 155 // This is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX 557 // This is the 'maximum' pulse length count (out of 4096)
#define SERVO_FREQ 50 // Analog servos run at ~50 Hz updates

int val;
int angle;
int pulse;

void setup() {
Serial.begin(9600);
pwm.begin();
pwm.setPWMFreq(SERVO_FREQ); // Analog servos run at ~50 Hz updates

yield();
}

void loop() {

angle =val;
pulse = map(angle,0, 180, SERVOMIN, SERVOMAX);
//Serial.print("Angle: ");Serial.print(angle);
//Serial.print(" pulse: ");Serial.println(pulse);
pwm.setPWM(0, 0, pulse);

if (Serial.available()) {
val = Serial.read();
Serial.println(val);
}
}

Source Audio's icon

You need to post max patch as well.
I need to see how you send the list to serial object,
both for single Servo example and for 4 servos.

Source Audio's icon

Try this:

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
#define SERVOMIN0 155
#define SERVOMAX0 557
#define SERVOMIN1 175
#define SERVOMAX1 520
#define SERVOMIN2 155
#define SERVOMAX2 557
#define SERVOMIN3 155
#define SERVOMAX3 557
#define SERVO_FREQ 50
int angle0; int angle1; int angle2; int angle3;
int pulse0; int pulse1; int pulse2; int pulse3;

void setup() {Serial.begin(9600); pwm.begin();
pwm.setPWMFreq(SERVO_FREQ);}

void loop() {
pwm.setPWM(0, 0, pulse0);
pwm.setPWM(1, 0, pulse1);
wm.setPWM(2, 0, pulse2);
wm.setPWM(3, 0, pulse3);
if (Serial.available() > 0 ) {
angle0 = Serial.parseInt();
angle1 = Serial.parseInt();
angle2 = Serial.parseInt();
angle3 = Serial.parseInt();
if (Serial.read() == '\n'){
pulse0 = map(angle0, 0, 180, SERVOMIN0, SERVOMAX0);
pulse1 = map(angle1 ,0, 180, SERVOMIN1, SERVOMAX1);
pulse2 = map(angle2 ,0, 180, SERVOMIN2, SERVOMAX2);
pulse3 = map(angle3 ,0, 180, SERVOMIN3, SERVOMAX3);
} } }
-------------- This is if 4 ints list is sent from Max
You chose 9600 Baud, so set it in max too.

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

If you want I could send the code with prepended IDs

Source Audio's icon

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
#define SERVOMIN0 155
#define SERVOMAX0 557
#define SERVOMIN1 175
#define SERVOMAX1 520
#define SERVOMIN2 155
#define SERVOMAX2 557
#define SERVOMIN3 155
#define SERVOMAX3 557
#define SERVO_FREQ 50
byte inByte;
int angle0; int angle1; int angle2; int angle3;
int pulse0; int pulse1; int pulse2; int pulse3;

void setup() {Serial.begin(9600); pwm.begin(); pwm.setPWMFreq(SERVO_FREQ);
}
void loop() {
pwm.setPWM(0, 0, pulse0); pwm.setPWM(1, 0, pulse1);
pwm.setPWM(2, 0, pulse2); pwm.setPWM(3, 0, pulse3);
if (Serial.available() > 0 ) {
inByte = Serial.read();
if (inByte == 'A') {angle0 = Serial.parseInt();
pulse0 = map(angle0, 0, 180, SERVOMIN0, SERVOMAX0);}
if (inByte == 'B') {angle1 = Serial.parseInt();
pulse1 = map(angle1 ,0, 180, SERVOMIN1, SERVOMAX1);}
if (inByte == 'C') {angle2 = Serial.parseInt();
pulse2 = map(angle2 ,0, 180, SERVOMIN2, SERVOMAX2);}
if (inByte == 'D') {angle3 = Serial.parseInt();
pulse3 = map(angle3 ,0, 180, SERVOMIN3, SERVOMAX3);}
}}

max patch

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

Antti Ikonen's icon

Super! Thanks, I'll try them!

Antti Ikonen's icon

Last one that you sent works perfectly! Thank you very much!

Source Audio's icon

You are welcome.
You say that last one works, does that mean that the first one does not ?
Makes me wonder if not , why ...

Antti Ikonen's icon

I only tested the last one. I have to give the first one also a try later.

Source Audio's icon

ok, thanks.
the last one is a better choice for performance I think,
but it is also handy to see how to collect and route incoming list
as first one does.

Antti Ikonen's icon

Hey there, so the first one works as well! If I'm not incorrect, I assume that I can add more "channels" to the arduino patch by just copying the code and changing the letters to E, F, G, H and so on?

Source Audio's icon

Sure, as many as channels on servo board.
just don't forget to multiply angle and pulse as well