RGB LED and photocell- help with script

Hi,

I have a photocell as an input and an analogue RGB LED as the output for a project I am working on. I would like the RGB LED to become brighter the darker it is at the sensor. However, I want the colour it lights up to be a particular purple (110, 0, 255) for (red, green, blue).
I am not very experienced with scripting, and have been trying to use this script from one of Ladyada's tutorials as a starting point (found at How to use photocells, LDRs, CdS cells, photoresistors!). It does exactly what I want it to do, aside from being able to function with the 3 separate colours of the RGB LED.

int photocellPin = 0;     // the cell and 10K pulldown are connected to a0
int photocellReading;     // the analog reading from the sensor divider
int LEDpin = 11;          // connect Red LED to pin 11 (PWM pin)
int LEDbrightness;        // 
void setup(void) {
  // We'll send debugging information via the Serial monitor
  Serial.begin(9600);   
}
 
void loop(void) {
  photocellReading = analogRead(photocellPin);  
 
  Serial.print("Analog reading = ");
  Serial.println(photocellReading);     // the raw analog reading
 
  // LED gets brighter the darker it is at the sensor
  // that means we have to -invert- the reading from 0-1023 back to 1023-0
  photocellReading = 1023 - photocellReading;
  //now we have to map 0-1023 to 0-255 since thats the range analogWrite uses
  LEDbrightness = map(photocellReading, 0, 1023, 0, 255);
  analogWrite(LEDpin, LEDbrightness);
 
  delay(100);
}

So far my script reads as below, but when verified it comes up saying ' expected primary-expression before '[' token' with 'analogWrite(LEDAnalog, , LEDbrightness);' highlighted

//RGB LED pins
int LEDAnalog[] = {3, 5, 6}; //the three pins of the analog LED 3 = redPin, 5 = greenPin, 6 = bluePin
int photocellPin = 0;     // the cell and 10K pulldown are connected to a0
int photocellReading;     // the analog reading from the sensor divider
int LEDbrightness;        // 

//Defined Colors (different RGB (red, green, blue) values for colors
const byte PURPLE[] = {110, 0, 255};

void setup() {
  for(int i = 0; i < 3; i++){
    pinMode(LEDAnalog[i], OUTPUT);}    //Set the three LED pins as outputs
  Serial.begin(9600);   
}
 
void loop(void) {
  photocellReading = analogRead(photocellPin);  
 
  Serial.print("Analog reading = ");
  Serial.println(photocellReading);     // the raw analog reading
 
  // LED gets brighter the darker it is at the sensor
  // that means we have to -invert- the reading from 0-1023 back to 1023-0
  photocellReading = 1023 - photocellReading;
  //now we have to map 0-1023 to 0-255 since thats the range analogWrite uses
  LEDbrightness = map(photocellReading, 0, 1023, 0, 255);
  analogWrite(LEDAnalog, [PURPLE], LEDbrightness);
 
  delay(100);
}

If anyone could help me get this simple script working it would be amazing!
Thankyou :slight_smile:
Zana

zanaobscura:

  analogWrite(LEDAnalog, [PURPLE], LEDbrightness);

you cannot give 3 parameters to analogWrite. analogWrite needs 2 parameters, the pin no. on which you want the analog signal and the other is the brightness. Look it up in detail at Look up the syntax at http://arduino.cc/en/Reference/analogWrite.

So it should be:

  for(int i=0;i<3;i++)
    analogWrite(LEDAnalog[i], PURPLE[i]);

If you are still confused with the working of analogWrite, start with the basics again and with a red LED and the inbuilt fade example.

If you got it, then it gets a bit tougher:
This will just show a constant purple colour of (110, 0, 255) which you wanted. these levels simply mean that the Red LED in the RGB LED is at brightness 110 out of max 255, Green LED is off, and Blue LED is shining at full brightness. So the total brightness of the LED is very complex composed of the combination of brightness of Red, Green and Blue LED brightnesses. Although this is not required, the combined brightness is calculated by the formula:

brightness = sqrt( .241R2 + .691G2 + .068*B2 )

So there is no simple way to change the brightness of the same purple color using RGB values directly. To change the brightness, you will have to change the values for R, G and B. For that, we need to convert the RGBs into HSL(Hue, Saturation, Lightness) values. That is a VERY complex process. You can take a look at explanation for HSL at HSL and HSV - Wikipedia. If you want the code to convert RGB to HSL and vice versa, look at Deneme Bonusu Veren Bahis Siteleri - En iyi Bonus Veren Siteler Nelerdir?. But you will need to tweak it a bit to work with Arduino.

There is another simpler way. You can enter your RGB value in The RGB Color Calculator / Web Page Color Choosing Tool / HTML Color Code Generator and click on calculate. The background will turn your favourite shade of purple :smiley:
Now it will also give HSV values in the text boxes below RGB value. Select an increment value from the dropdown and keep pressing V- and noting the R&B values(no need for G as its zero) till you get R=0 and B=0. Save this in your code and display these values at certain levels of analog signal read. That ought to do it.

There are even simpler ways but then your purple will not remain purple as we change the brightness but more of bluish-purple or reddish-purple.

Thanks Antzy!
All vey helpful and interesting information.
So I gather I should be mapping particular photocell values (between 0-1023) to a particular Red Blue value? for example, using 39x '+/-V' increment values from the website, with [photocell value = (R,B)] : [<100, >0 = (110,255)]; [<200, >100 = (93, 216)];...[<900, >800 = (9,21)]; [<1023, >900 = (0,0)].
As this is the one of the first scripts I have written I am just a little unsure as to where and how exactly to insert this into my code...? Sorry- really enthusiastic to learn from someone with experience though
Zana

I'm no expert either. :blush: I'm not much experienced with arduino. But I can find my way around with codes.
Arduino - Wikipedia says arduino uno has 2kB RAM. We need an array of 2 colums(1 for red and other for blue). And max value is 255 for each variable, so we can use datatype byte. So we can have maximum (2*1024)/2=1024 columns. So we can very safely use an array of 100x2. That means you can have 100 different brightness levels for RGB LED and will need 100 RGB values. But you will also need to get 100 values for increasing brightness from the site. So you can set this to lesser value if you like.
Also, instead of creating so many if-else loops to check whther the photocell value is inbetween 0-99 or 100-199 or 200-299, you can divide the value by 100. then if the quotient comes out to be 0, its in 0-99, if its 1, its in 100-199 and so on. So the code could be something like:

byte RGB_values[100][2]={ {0,0},{2,5},{4,10},.........{108,250},{109,252},{110,255} };
int range;

//your codes...

  range=photocellReading/100;
  analogWrite(LEDAnalog[0], RGB_values[range][0]);
  analogWrite(LEDAnalog[1], 0);
  analogWrite(LEDAnalog[2], RGB_values[range][1]);
}

Do tell me if it works when you try it out.