Control 4 RGB Leds individually

Hello,
Just "because", I am creating a 4 station soil monitor with 4 RGB leds.
What I am trying to do is loop through each sensor get moisture level, then set the color to the corresponding led based on that moisture level.

I set up 4 arrays with the pins of the colors of each led.

int LED01 = {1,2,3};
int LED02 = {4,5,6};
int LED03 = {7,8,9};
int LED04 = {10,11,12};

for (int x = 1; x<=4; x++) {
  // Could not get this to "evaluate" and saw online can't do it
  LED0 + x = ... // Concat x value to string and evaluate to get LED01, LED02, LED03, LED04
}

So I added an array of arrays, basically...

int LEDS = {LED01, LED02, LED03, LED04};
Loop through the LEDS array to get the pins of LED01, LED02, LED03, LED04 to analogWrite the colors.

But that is not working either. Getting error messages, can't convert from int to int*, etc

How would I go about this?
Is there a better way or...sigh. I had strokes several years ago and once I "get an idea", I can't think or change the idea, anymore. I hate that.
Thank you.

it is not array definition;

Try :

int LED01 [] = {1,2,3};
int LED02 []= {4,5,6};
int LED03 []= {7,8,9};
int LED04 []= {10,11,12};

and

int LEDS [] = {LED01, LED02, LED03, LED04};

Post your complete code and a project schematic wiring.

You could use for instance a 2-dimensional array for this. Goes like this:

int LED_PINS = {
  {1,2,3},  //LED01
  {4,5,6},  //LED02
  {7,8,9},  //LED03
  {10,11,12}  //LED04
};

This way, LED_PINS[0] will be the array of pins for LED01, i.e. {1,2,3};
A 2-dimensional array is really an "array of arrays" (let that sink in for a minute). In this case, it's an array that contains sub-arrays that contain the pin numbers for your RGB LEDs.

The main thing you need to realize is that variable names have no meaning and in fact no longer exist in the 'mind' of the microcontroller once your code is compiled, linked and uploaded. Hence, it cannot 'concatenate' variable names, since it has no concept of these names to begin with.

If you use a 2-dimensional array, you could do something like this:

for (int x = 0; x < 4; x ++) {
  digitalWrite(LED_PINS[x][0], HIGH); //This will set the first pin of the LED (01, 02, 03, 04) HIGH
}

Or, you could even set all pins HIGH/LOW with only a few lines of code:

for (int led = 0; led < 4; led ++) {  //Cycle through the 4 RGB LEDs
  for (int pin = 0; pin < 3; pin ++) {  //Cycle through the 3 pins of the current LED
    digitalWrite(LED_PINS[led][pin], HIGH); //This will set pin "#pin" of led "#led" to HIGH;
  }
}

Oops.
I think something is missing here!
It would be like this:

int LED_PINS [][]= {
  {1,2,3},  //LED01
  {4,5,6},  //LED02
  {7,8,9},  //LED03
  {10,11,12}  //LED04
};

Sorry, yes.

Well, actually something like

or

You can't leave both dimensions undefined in size; at least the inner/latter one needs to be of defined size.

2 Likes

on Uno and Nano better not using pins 0 and 1

Still waiting for that full code and your schematic. Without both of those we are only guessing. Real help requires real cooperation from you.

1 Like

Hallo actos-mike

Welcome to the best Arduino Forum ever :slight_smile:

This task calls for a solution in OOP.
You have N monitors, each of which controls an RGB LED.
A common service is used to initialize and control the colors.

//https://forum.arduino.cc/t/control-4-rgb-leds-individually/1276197
//https://europe1.discourse-cdn.com/arduino/original/4X/7/e/0/7e0ee1e51f1df32e30893550c85f0dd33244fb0e.jpeg
#define ProjectName "Control 4 RGB Leds individually"
#define NotesOnRelease "Arduino MEGA tested"
//make names
enum Colours {Red, Green, Blue, maxColour};
enum Monitor {Mon1, Mon2, Mon3, Mon4};
// make variables
uint32_t  currentMillis {millis()};
//-----------------------------------------
// make structs
struct RGB
{
  uint8_t rgbs[maxColour];
  void make()
  {
    for (auto rgb : rgbs)  pinMode(rgb, OUTPUT);
  }
  void setLed(Colours colour)
  {
    for (auto rgb : rgbs) digitalWrite(rgb, LOW);
    digitalWrite (rgbs[colour], HIGH);
  }
};
// add port pin addresses per monitor
RGB rgbs[]
{
  {9, 10, 11},  // monitor 1
  
};

//-----------------------------------------
// make support
void heartBeat(const uint8_t LedPin, uint32_t currentMillis)
{
  static bool setUp = false;
  if (setUp == false) pinMode (LedPin, OUTPUT), setUp = true;
  digitalWrite(LedPin, (currentMillis / 500) % 2);
}
// make application
void setup()
{
  Serial.begin(115200);
  for (uint8_t n = 0; n < 32; n++) Serial.println("");
  Serial.print("Source: "), Serial.println(__FILE__);
  Serial.print(ProjectName), Serial.print(" - "), Serial.println(NotesOnRelease);
  // make RGB monitors
  for (auto rgb : rgbs) rgb.make();
  delay(2000);

  // TEST

  // set red led for monitor 1
  rgbs[Mon1].setLed(Red);
  delay(2000);
  // set blue  led for monitor 1
  rgbs[Mon1].setLed(Blue);

  Serial.println(" =-> and off we go\n");
}
void loop()
{
  currentMillis = millis();
  heartBeat(LED_BUILTIN, currentMillis);
}
//------

Expand, try and play with this program example for your project.

2 Likes

Sorry.

Here is the basic code. The pins for all 4 RGB Leds point to the same pins for this example. I found part of the problem I was having that I asked for help. It seemed the "fake pins" I was using earlier was causing a problem with the analogWrite function. When I changed all the pins to the sample led pins, I get better results.

As far as a schematic, I do not have one. The idea was basically designed in my head. 1 soil moisture sensor + 1 RGB led per each potted plant. (4 in total). But for now, just have 1 as "proof of concept"...to get it working. I need like the equivalent to Large Print books for the things. So small.

Thank you, everyone for all your help.

/*
* Read sensors then light RGB LEDs based on values
*/

#include "BluetoothSerial.h"
BluetoothSerial SerialBT;

#define threshold_dry 3100  // Sensor reading of 3000+
#define threshold_optimal 2250  // Sensor reading of 2250
#define threshold_wet 1500  // Sensor reading of 1500 covered in water

int sensor_pins[] = {1,2,3,4};  // data pins on sensors

// Define colors
int BLACK[3] = {0,0,0};
int GREEN[3] = {0,255,0};
int YELLOW[3] = {230,230,0};
int MAGENTA[3] = {80,0,80};
int RED[3] = {255,0,0};

int LED_PINS [4][3]= {
  {21,22,23},  //LED01
  {21,22,23},  //LED02
  {21,22,23},  //LED03
  {21,22,23}  //LED04
};

void setup() {
  Serial.begin(9600);
  SerialBT.begin("ESP Temp Monitor");

}

void loop() {

String dataOutput = "";
srand (time(NULL));

  for (int x=0; x < 4; x++) {
    //loop through sensors
    int sp = analogRead(sensor_pins[x]);
    int moistureLevel = map(sp, threshold_dry, threshold_wet, 0,100);
    moistureLevel = rand()%100 + 1; // for testing LED colors

    int *color = setLEDValue(moistureLevel);
    int *lp = LED_PINS[x];

    // int r = LED_PINS[x][0];
    // int g = LED_PINS[x][1];
    // int b = LED_PINS[x][2];

    // activateLED(r,g,b,color);
    activateLED(x, lp,color);
    dataOutput += "Sensor " + String(x +1) + ": " + String(moistureLevel) + "\n";
    //Serial.print(dataOutput);

  }

  // For bluetooth
  // for(int i = 0; i < dataOutput.length(); i++)
  // {
  //   SerialBT.write(dataOutput.c_str()[i]);
  //   //Serial.write(dataOutput.c_str()[i]);
  // }
  printf("\n________________________________________\n");
  delay(10000);

} // loop()

void activateLED(int sensor, int pin[], int color[]) {
  String info = "";

  for (int x = 0; x <3; x++) {
    analogWrite(pin[x], color[x]);
    info += "x: " + String(x) + "\t\tpin: " + String(pin[x]) + "\t\tColor value: " + String(color[x]) + "\t\t";
    printf("Sensor: %d  x: %d  Pin: %d   Color Val: %3d", sensor, x, pin[x], color[x]);
    //Serial.print(info);
  }
  //Serial.println(info);
} // activateLED()

int *setLEDValue(int sensorReading) {

  if (sensorReading >= 80) return GREEN;
  if (sensorReading <= 79 && sensorReading >= 40) return YELLOW;
  if (sensorReading <= 39 && sensorReading >= 20) return MAGENTA;
  if (sensorReading <= 19) return RED;

} // setLEDValue()



You are using DIO Pin 1. You should not.

1 Like

That is the single worst idea you ever had. Especially when you are going to ask for help.

I spent most my life as a University lecturer trying to persuade students to draw a circuit diagram of anything they are making. I can't make anything without a schematic and I have had over 55 years in electronics. What makes you think you are better than me?

This is a rhetorical question because you are not. Remember you are the one asking questions here not me.

Time to do some learning, have a look at these two trusty stalwarts.

Reading a schematic

Colin's Lab video on reading a schematic

With a schematic we could have easly seen that you were thinking that any pin would work with an analogWrite command.

What sort of Arduino are you using? On a UNO you only have 6 pins capable of producing a PWM output, so you only have enough pins to control two LEDs and you want to control twice that number, so this project is doomed from the outset, without using extra hardware to produce the missing PWM capabilities.

One good board for this is the 16 channel servo board:-

Note it can also be setup to light LEDs as well as control servos.

1 Like

then you should also put your 4 of RGB LEDs in an array like @rsmls has proposed.

use uint8_t for pins - not an int.

1 Like

This will not help if you have an insufficient number of PWM capable pins to start off with.

Well it saves you a byte, hardly mission critical.

However if @actos-mike only wants the LEDs to show one of its three possible colours then he can do that by just using a digitalWrite on any pin(best not use pins 0 & 1). It is only the analogWrite that needs PWM capable pins.

1 Like

I am sorry. I know I should start with a schematic. I have some basic knowledge. The pin connections were just an example for my code. 23, 22, 21 are the only functional pins in my example. Do you have a recommendation for a good schematic program ? Because of my "issue"...ha. I have trouble writing. I could use the mouse and type on a keyboard before I could walk again. I was piecmealing different code from different examples online to try an understand later. It is hard for me to understand properly if the code I get uses the wrong variable definitions.

I am using an ESP32 DEVKITV1. Some generic I bought from wish.

I created a test circuit using 1 Soil Monitor and 1 RGB Led with the chip.

What I did for this was cycle through 3 different colors... and moisture will give a value, depending on if in water or dry...

/*
 * This ESP32 code is created by esp32io.com
 *
 * This ESP32 code is released in the public domain
 *
 * For more detail (instruction and wiring diagram), visit https://esp32io.com/tutorials/esp32-soil-moisture-sensor
 */

#define AOUT_PIN 4 // ESP32 pin GPIO36 (ADC0) that connects to AOUT pin of moisture sensor
#define dry 3100
#define wet 1500

#define r 21
#define g 22
#define b 23

// #define BLACK setColor(0,0,0);
// #define GREEN setColor(0,255,0);
// #define YELLOW setColor(240,240,0);
// #define RED setColor(255,0,0);

int LED_01[] = {21,22,23};

int BLACK[] = {0,0,0};
int GREEN[] = {0,255,0};
int YELLOW[] = {230,230,0};
int RED[] = {255,0,0};


const int red_pin = 21;   
const int green_pin = 22; 
const int blue_pin = 23; 
const int pin = 21;


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

void loop() {
  int value = analogRead(AOUT_PIN); // read the analog value from sensor

  float percentageHumididy = map(value, dry, wet, 0, 100);


// New way 06/25/2024
activateLED(LED_01, GREEN);
activateLED(LED_01, YELLOW);
activateLED(LED_01, RED);



  Serial.print("Moisture value: ");
  Serial.print(value);
  Serial.print(", ");
  Serial.print(percentageHumididy);
  Serial.println("%");
  delay(2500);

  // for (int i=255; i>=0;i--) {

  //   analogWrite(red_pin,80);
  //   analogWrite(green_pin,0);
  //   analogWrite(blue_pin,80);
    
  //   //Serial.println(i);
  //   delay(1);
  // }

  //BLACK;
  // analogWrite(red_pin,0);
  // analogWrite(green_pin,0);
  // analogWrite(blue_pin,0);
  activateLED(LED_01, BLACK);


  delay(2500);
}

void setColor(int red, int green, int blue) {
  analogWrite(red_pin, red);
  analogWrite(green_pin, green);
  analogWrite(blue_pin, blue);
}

void activateLED(int led[3], int color[3]) {
  analogWrite(led[0], color[0]);
  analogWrite(led[1], color[1]);
  analogWrite(led[2], color[2]);
  delay(2500);

}

The colors cycle using analogWrite, with pins D23, D22, D21 on the board. Will any pin D work for this? I was thinking if I ran out of pins, I would use a shift register IC, based on a google search, but I haven't thought that far yet.

I really would like to learn the "proper way" so thank you for taking the time. This is just "something to do" between my naps before my brain hurts from thinking too much. :slight_smile:
And yes, to me, "Everything is a joke." now. In reality, I should have been dead, but it wasn't my time. I guess I had to look after my parents until...so I do not take things seriously at all anymore. I can, if I must, but if an opportunity arises to say something "funny", I will.

Thank you,
Mike

OK now I know you "only" have an ESP32 processor, you face another very real problem.

All ESPxx processors work at 3V3 (three point three volts), so yes you will have trouble driving an LED from that, especially the blue LEDs.

So if you want to use a digital output you will need to drive the LEDs through a transistor to get the voltage to the right voltage to drive the LED. Also the current capacity of these processors is only a fraction of what the Arduino UNO can supply. So check the data sheet of your particular processor to see what current you can draw from a pin.

Probably the best solution is if you read this

3_3vto5vAnalogTipsnTricksBrchr.pdf (952.8 KB)

Know what you mean here.
Last year I had a stroke, could have killed me or left me severely disabled. As I was lucky I was left with a right hand where the sense of touch was converted into pain in two fingers (the ones I use to give my opinion on politics) and they won't move where I want them to.

Thank you for the information. But the led works and loops through the different colors. Would it not drive 4 leds, but will drive 1 ok?
While thinking would I need 1 220 ohm resistor for each pin on each led (12 in total) or can I connect 1 resistor to the red pin of the 4 leds, 1 resistor to the green pin of the leds, etc?

If you are using analogWrite then as I said the limiting factor is how much current you can get from a single pin, and you need to look that up in the data sheet of your device.

If the current you get through an individual pin is greater than the maximum, then you need to increase the value of the current limiting resistors, so as to limit the current a single pin can supply to about 80% of the maximum current shown in the data sheet. This is called "de-rating" a component and 80% is a common figure to use for this.

I am not sure I understand the difference between the two cases you are trying to make in this question.

If you have understood the de-rating calculations I mentioned above, then the current limiting resistor should be reduced anyway. Each LED should have its own current limiting resistor.

That was what I was looking for. These are RGB leds, so each pin (red, green, blue) should have the resistor? So, 4 RGB Leds = 12 resistors.

Heh. That's what I get from buying from Wish. No datasheet. It just references "ESP-32 Development Board", but the actual chipset shows "ESP-WROOM-32", so maybe I can look up that datasheet.

I did something interesting, to me, anyway. I connected my multimeter to the RED Pin (after the resistor) and ground, just to see the actual values being generated. When the RGB led shows colors that had high values of red, it would be in the 2.7 volts or higher range. Pure RED (RED 255, 0, 0) was 3.1 volts, which was expected. Then I selected mA. Again, different colors gave different values, colors having more red in them, the mA was lower. Like for green, the mA for the red pin was 0. A little confused about that. Then, when RED is supposed to be shown, the led was off and no mA. But, if I turned the meter off, the red color showed again. That was something I didn't expect.

Did you do any changes to the wiring when you selected the mA? You should have.

You can only measure current when the meter is in series with circuit. When you switch from volts to amps the meter goes from being a very high impedance to almost a dead short circuit. So:-

So what ever the the meter was across was like you had connected a wire instead of a meter. Hence:-

That is something you should expect. If you are still confused look up how to measure current with a multi-meter.