How to control multiple LEDs on an arduino


    Apr 20 2012 | 7:00 am
    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);
    }
    }

    • Apr 20 2012 | 10:32 am
      Maybe you can consider using Maxuino - which is a special combination of Arduino software and Max patch for control.
    • Apr 20 2012 | 11:07 am
      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
    • Apr 20 2012 | 11:08 am
      I don't have problems with Maxuino under Max 6 - you sure you have the latest version?
    • Apr 20 2012 | 11:10 am
      Hi,
      Yes, I have the latest version. Hmm, I wonder how you installed it?
      Best,
      Ana
    • Apr 20 2012 | 11:12 am
      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).
    • Apr 20 2012 | 3:18 pm
      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.
    • Apr 20 2012 | 9:43 pm
      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:
      and have you tried the Arduino forum itself? Naturally.
      Sorry not to have better news :(
      Brendan
    • Apr 20 2012 | 11:15 pm
      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);
      }
      }
      }
    • Apr 21 2012 | 7:21 pm
      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
    • Apr 21 2012 | 9:31 pm
      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
      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;
      }
    • Apr 21 2012 | 9:38 pm
      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 ...
    • Apr 21 2012 | 9:38 pm
      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
      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;
      }
    • Apr 22 2012 | 11:26 am
      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
    • Apr 22 2012 | 6:20 pm
      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
    • Apr 22 2012 | 7:41 pm
      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:
      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);
      }
    • Apr 22 2012 | 7:47 pm
      "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.
    • Apr 22 2012 | 10:43 pm
      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);
      }
    • Apr 10 2013 | 3:26 pm
      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.
    • Oct 26 2016 | 1:13 pm
      Hello,
      if you need I made a patch. The Arduino code is inside.
      Enjoy it.
      Claudio