How to control multiple LEDs on an arduino
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 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);
}
}
Maybe you can consider using Maxuino - which is a special combination of Arduino software and Max patch for control.
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
I don't have problems with Maxuino under Max 6 - you sure you have the latest version?
Hi,
Yes, I have the latest version. Hmm, I wonder how you installed it?
Best,
Ana
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).
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.
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
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).
/*
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);
}
}
}
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
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++;
}
char establishContact(void){
if (Serial.available() > 0) {
char checkup = Serial.read();
if (checkup==99) return 1;
else return 0;
}
else return 0;
}
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 ...
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;
}
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
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
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);
}
"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.
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);
}
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.
Hello,
if you need I made a patch. The Arduino code is inside.
Enjoy it.
Claudio