How to control multiple LEDs on an arduino

anamaria's icon

Hi,

I did the dimmer tutorial, where I can get one LED light to light up. What if I want to control two or more LED lights? Then I guess I need to give the brightness data an address? I guess from max I can send a list with an address name and then the brightness value of the LED, but how do I deal with the address and the LED value on the arduino code side?

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

max code:

arduino code:

const int ledPin1 = 9; // the pin that the LED is attached to
const int ledPin2 = 10; // the pin that the LED is attached to
// how do I define the address name of multiple LED's and map the
// brightness values from the two sliders in max to teh right LED pin?

void setup()
{
// initialize the serial communication:
Serial.begin(9600);
// initialize the ledPin as an output:
pinMode(ledPin1, OUTPUT);
}

void loop() {
byte brightness;

// check if data has been sent from the computer:
if (Serial.available()) {
// read the most recent byte (which will be from 0 to 255):
brightness = Serial.read();
// set the brightness of the LED:
analogWrite(ledPin1, brightness);
}
}

mrkva's icon

Maybe you can consider using Maxuino - which is a special combination of Arduino software and Max patch for control.

anamaria's icon

Hi,

Yes, Maxuino works with max 5, but NOT max 6 (as far as I can see), so I am trying to make more simple solution.

If I send a message from max into an arduino (the message contains the number of the LED light and a brightness value, then in the arduino code I need to map the brightness of light 1 to pin 9, the brightness of light 2 to pin 10 aso.

The messages that are sent from max through the serial object could be something like this:
"1 100" (set the brightness of the light at pin 9 to 100)
or "2 50" (set the brightness of the light at pin 10 to 50)

In the arduino dimmer tutorial, I need to somehow unpack those messages. How do I do that?

- or should I use a completely different approach?

ana

mrkva's icon

I don't have problems with Maxuino under Max 6 - you sure you have the latest version?

anamaria's icon

Hi,

Yes, I have the latest version. Hmm, I wonder how you installed it?

Best,

Ana

mrkva's icon

You have to drop the Maxuino files to max-externals folder and than run 'Maxuino-help.maxpat' for example. Be sure that you don't have any other application blocking the serial communication (Arduino.app for example).

anamaria's icon

Hmm, I still cannot get it to work. Also, maxuino may be a bit overkill for what I need to do ... so I am still looking for a more simple solution both on the arduino side, but especially on the max side.

brendan mccloskey's icon

Hi anamaria
this has been bugging me, as the solution should be simple. Unfortunately, my only experience with Max/Arduino is sending data in the opposite direction. At the Max end I always use [zl group 2] to bundle together the header (address or token) and the value coming from Arduino. What you need on the Arduino end is the equivalent code to bundle a header and a value and then unpack or de-tokenize them. I'm thinking an array. Sorry not to be more help, but if your coding chops are better than mine you should be able to hack the code that accompanies Maxuino. This looks useful too:
http://www.instructables.com/id/Sending-a-multi-byte-integer-to-Arduinos-serial/

and have you tried the Arduino forum itself? Naturally.

Sorry not to have better news :(
Brendan

Scott Fitzgerald's icon

Here's a sketch and max patch that illustrates how to control multiple LEDs on an arduino. This particular example also allows you to control the brightness of the three LEDs through PWM (attached to digital pins 9,10,11).

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

/*
Serial RGB LED controller
by Tom Igoe
adaboed by Scott Fitzgerald
Controls three LEDs whose legs are
connected to pins 9, 10, and 11.
*/
// constants to hold the output pin numbers:
const int LEDone = 9;
const int LEDtwo = 10;
const int LEDthree = 11;
int currentPin = 0; // current pin to be faded
int brightness = 0; // current brightness level
void setup() {
// initiate serial communication:
Serial.begin(9600);
// initialize the LED pins as outputs:
pinMode(LEDone, OUTPUT);
pinMode(LEDtwo, OUTPUT);
pinMode(LEDthree, OUTPUT);
}
void loop() {
// if there's any serial data in the buffer, read a byte:
if (Serial.available() > 0) {
int inByte = Serial.read();
Serial.write(inByte);
// respond to the values 'a', 'b', 'c', or '0' through '9'.
// you don't care about any other value:
if (inByte == 'a') {
currentPin = LEDone;
}
if (inByte == 'b') {
currentPin = LEDtwo;
}
if (inByte == 'c') {
currentPin = LEDthree;
}
if (inByte >= '0' && inByte
// map the incoming byte value to the range of the analogWrite() command
brightness = map(inByte, '0', '9', 0, 255);
// set the current pin to the current brightness:
analogWrite(currentPin, brightness);
}
}
}

anamaria's icon

Thanks for the example code. Hmm, however, a resolution at 9 is not very good. Also, the LED takes a big jump in brightness from 0 to 1. I wonder, instead of sending byte values as LED brightness values, why it is not possible to send an address name from max with a brightness value at the 0 to 255 resolution?

ana

anamaria's icon

Hi,

I also tried to combine the SensorBox max / arduino code with the dimmer max / arduino code. Here I cannot get the LED to light up ... I wonder if I have done something wrong in the arduino code (it compiles fine, however).

const int ledPin1 = 9; // the pin that the LED is attached to
const int ledPin2 = 10; // the pin that the LED is attached to
// how do I define the address name of multiple LED's and map the
// brightness values from the two sliders in max to teh right LED pin?

// Code for Getting all the Arduino inputs into MaxMSP
//Andrew Benson
//http://pixlpa.com

char analogValue[12];//array of analog values
char current=0;//current position of analog value in array
int digVal;//digital pins bits are packed into a single variable
char imask = 128;//index bytes start with 1
char theEnd = 255;//byte to signal message end to Max patch

void setup(void) {
// initialize the ledPin as an output:
pinMode(ledPin1, OUTPUT);

Serial.begin(57600);
digVal=0;
for (int i = 2;i
digitalWrite(i,HIGH);//enable pullups
}
while (establishContact()==0){delay(100);} //wait for 99 byte
}

//uses serial.write() to avoid needless symbol creation in MaxMSP
void loop() {
byte brightness;

// check if data has been sent from the computer:
if (Serial.available()) {
// read the most recent byte (which will be from 0 to 255):
brightness = Serial.read();
// set the brightness of the LED:
analogWrite(ledPin1, brightness);
}

digVal=0; //reset digital value to 0
//read digital pins
for (int i = 0;i
digVal |= (digitalRead(i+2)<
}

//read analog pins
for (int g = 0;g
packValue(g);
}
char total = current+1;
sendOFF(total);//send everything to Max
current=0;//reset analog value counter
delay(10);//wait 10 milliseconds
//see if someone tried to turn us off:
if(establishContact()==1) {
while(establishContact()==0) {delay(100);}//go into idle mode
}
}

void sendOFF(char total){
//Send analog values in the format 0x81 a1 a2.....0xFF
Serial.write(imask|1);
for (int i = 0;i
Serial.write(analogValue[i]);
}
Serial.write(theEnd);//ends analog stream

Serial.write((imask|2));
Serial.write((digVal&127));
Serial.write(digVal>>7);
Serial.write(theEnd);//ends digital message
}

//read an analog pin and then pack into low/high bytes
void packValue(int index) {
int tempA = analogRead(index);
analogValue[current]=tempA & 127;
current++;
analogValue[current] = (tempA>>7);
current++;
}

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

char establishContact(void){
if (Serial.available() > 0) {
char checkup = Serial.read();
if (checkup==99) return 1;
else return 0;
}
else return 0;
}

anamaria's icon

Hmm, another try: The new arduino code posted below does change the brightness of the LED, but then there is no sensor data coming in ...

anamaria's icon

const int ledPin1 = 9; // the pin that the LED is attached to
const int ledPin2 = 10; // the pin that the LED is attached to
// how do I define the address name of multiple LED's and map the
// brightness values from the two sliders in max to teh right LED pin?

// Code for Getting all the Arduino inputs into MaxMSP
//Andrew Benson
//http://pixlpa.com

char analogValue[12];//array of analog values
char current=0;//current position of analog value in array
int digVal;//digital pins bits are packed into a single variable
char imask = 128;//index bytes start with 1
char theEnd = 255;//byte to signal message end to Max patch

void setup(void) {
// initialize the ledPin as an output:
pinMode(ledPin1, OUTPUT);

Serial.begin(57600);
digVal=0;
for (int i = 2;i
digitalWrite(i,HIGH);//enable pullups
}
while (establishContact()==0){delay(100);} //wait for 99 byte
}

//uses serial.write() to avoid needless symbol creation in MaxMSP
void loop() {
byte brightness;

// check if data has been sent from the computer:
//if (Serial.available()) {
// read the most recent byte (which will be from 0 to 255):
//brightness = Serial.read();
// set the brightness of the LED:
//analogWrite(ledPin1, brightness);
//}

digVal=0; //reset digital value to 0
//read digital pins
for (int i = 0;i
digVal |= (digitalRead(i+2)<
}

//read analog pins
for (int g = 0;g
packValue(g);
}
char total = current+1;
sendOFF(total);//send everything to Max
current=0;//reset analog value counter
delay(10);//wait 10 milliseconds
//see if someone tried to turn us off:
if(establishContact()==1) {
while(establishContact()==0) {delay(100);}//go into idle mode
}
}

void sendOFF(char total){
//Send analog values in the format 0x81 a1 a2.....0xFF
Serial.write(imask|1);
for (int i = 0;i
Serial.write(analogValue[i]);
}
Serial.write(theEnd);//ends analog stream

Serial.write((imask|2));
Serial.write((digVal&127));
Serial.write(digVal>>7);
Serial.write(theEnd);//ends digital message
}

//read an analog pin and then pack into low/high bytes
void packValue(int index) {
int tempA = analogRead(index);
analogValue[current]=tempA & 127;
current++;
analogValue[current] = (tempA>>7);
current++;
}

char establishContact(void){
if (Serial.available() > 0) {
byte brightness;
// read the most recent byte (which will be from 0 to 255):
brightness = Serial.read();
// set the brightness of the LED:
analogWrite(ledPin1, brightness);

char checkup = Serial.read();
if (checkup==99) return 1;
else return 0;
}
else return 0;
}

De Fenestrated's icon

So the initial thread is how to control multiple LEDs. I have the same issue. Have you found a solution or are you abandoning the problem?
thanks

anamaria's icon

Hi, yes, I am still working on it. So far I have used maxuino that actually does work with max 6, if you install the osc-route object.

However, I think that it is problematic to be dependant on the maxuino framework, so I am still working on trying to control multiple LED's from max. I am still trying to figure out how I can send a message to the arduino from max, where the message contains an address and a brightness value. The problem is that you are sending things in bytes, so I donøt know how to send multiple messages with addresses and brightness values through bytes to the arduino and how to "unpack" these addresses and brightness values on the arduino side ...

If there are more of you all that have the same problem (and solved it somehow) please let me know and share your experiences :-)

ana

De Fenestrated's icon

Hello,
I am also not interested in using MAXUINO for this project.
So, I've culled the forums to find a way of sorting serial data sent from Max to Arduino to control 3 RGB values for LEDs. It is not pins I need but just a way of assigning a byte-sized (0-255) value to 3 variables. [the LEDs are driven by a Neuroelec shield (http://neuroelec.com/hp-rgb-led-shield/ver-2-0-manual/) and an Arduino library is included.] So don't worry 'bout my libraries and weird function calls in the setup.

The examples I've found and tried are, in terms of MAX objects:
slider->number box->serial //to drive a single LED 0-255
and the one posted earlier by Scott:
slider->number box->t i b->message box->atoi->serial

This last one works up to an integer value of 9. However, the atoi object is sending the ASCII value so by adding another digit, you are adding another ASCII value. So I guess it is a string which can then be sorted back into an INT, but that seems silly at first glance while the first example I tried is just so simple:
http://arduino.cc/en/Tutorial/Dimmer

So piecing both examples together: In ARDUINO, I changed the variable-type receiving the value to BYTE. The variable-type receiving the ASCII is still INT. In MAX, I just patched the cord from the trigger (t i b) directly to the serial object to by-pass the ASCII.

The MAX print monitor should confirm that the ASCII is the first byte to arrive, followed by the value.

The code for both is below. If someone can suggest some things to make it better, please do! I've figured out stuff with MAX and serial before, but I've kind-of just forgotten. :P m sure if i up the baud rate it would be smoother, etc. But, tomorrow...zzzz

In
#include
#include

HPRGB ledShield; // default mcp4728 id(0) and default PCA9685 id(0)

int p;
byte v;
byte red;
byte green;
byte blue;

void setup()
{
// initialize the serial communication:
Serial.begin(9600);
ledShield.begin();
ledShield.setCurrent(350,350,350); // set maximum current for channel 1-3 (mA)
ledShield.setFreq(600);// operation frequency of the LED driver (KHz)
ledShield.eepromWrite();// write current settings to EEPROM
delay(100); // wait for EEPROM writing
ledShield.goToRGB(0,0,0);
}

void loop()
{
if (Serial.available()>= 1) {
p = Serial.read();
}
if (Serial.available()>=1) {
v = Serial.read();
}
if(p == 'R'){
    red = v;
}
else if(p == 'G'){
    green = v;
}
else if(p == 'B'){
blue = v;
}
ledShield.goToRGB(red,green,blue);

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

}

De Fenestrated's icon

"I just patched the cord from the trigger (t i b) directly to the serial object to by-pass the ASCII."

Sorrry, m sleepy... the letter is still converted to ASCII. The patch cord of the INT out(from number box) by-passes the conversion.

Scott Fitzgerald's icon
Max Patch
Copy patch and select New From Clipboard in Max.

Here's another way of doing this using a call and response method, so you just need to send six bytes. It's more of a sketch than anything else as you'll need to reset the arduino once the patch has started running, but this will hopefully give people here more than enough to get started.

//create an array
unsigned int PWMData[]=
{
0,0,0,0,0,0};

void setup()
{
//start serial communication
Serial.begin(57600);

//set PWM pins as outputs
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
//make sure there's a computer connected
establishContact();
}

void establishContact() {
//if there's nothing in the buffer, do nothing!
//once there's something in there, go for it
while (Serial.available()
Serial.print('A'); // send a capital A
delay(300);
}
}

void readSerial(){
//if we have 6 bytes
//put them in the PWM array
if(Serial.available()==6){

for(int x=0;x
PWMData[x]=Serial.read();
}
//request more bytes
Serial.write(65);
//make the lights.... light
DoLights();
}

}

void DoLights(){

//set the value for each of the lights
analogWrite(3, PWMData[0]);
analogWrite(5, PWMData[1]);
analogWrite(6, PWMData[2]);
analogWrite(9, PWMData[3]);
analogWrite(10, PWMData[4]);
analogWrite(11, PWMData[5]);

}

void loop()
{
readSerial();
delay(10);
}

devslashnull's icon

I have used the "Messenger" library on the Arduino side to break apart the lists being sent via Max Serial object. Not sure that is exactly what you are looking to do.

2t2l's icon

Hello,
if you need I made a patch. The Arduino code is inside.
Enjoy it.
Claudio

3_Leds_Arduino_MAXMSP.maxpat
Max Patch