Sensor input displayed via RGB LED

Sorry for the length, just trying to be as thorough as possible

Hello everyone, I'd first like to start off by saying I'm as new as it gets to this. I'd really like to learn but as this is a school project my deadline is coming up very quickly and this is just one part of a much bigger and complex architectural model I'm working on. However, I've devoted a tremendous amount of time to this and I cannot get it to work for the life of me. I've been looking all over the internet and tried to study other sketches, have tried some cut and paste of a bunch of sketches, etc.

Anyway, what I'm working on is basically a water level sensor. I have a small fish tank set up and will be pumping water into it. I would like an RGB LED to change color based on the height of the water.

For tests, I've been using a potentiometer

Here is my code so far. Also worth noting is I've been working on this for about 2 weeks and have dropped my expectations pretty far as to what I'm hoping for this to do. I've also tried all kinds of small variations to things that I think might be the problem (ie in this latest attempt I used code like "else if(1 < sensorValue < 341)" instead of "else if(sensorValue < 341)" but since I don't have any coding experience I don't know what's right and what's not.

int sensorPin = A0;  // Analog input, (using a potentiometer for testing)
int redPin = 11;     // Output pins that the LEDs are connected to
int greenPin = 10;
int bluePin = 9;

int sensorValue = 0;       // value read from the sensor
int colorValue = 0;        // value output to the PWM (analog out) pin
int redValue = 0;          // values being output to the LED
int greenValue = 0;
int blueValue = 0;


void setup() {
  Serial.begin(9600);           // readouts to the serial monitor
  pinMode(redPin, OUTPUT);      // setting pins as outputs
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
}


void loop() {
  sensorValue = analogRead(sensorPin);                 // reading the value from the sensor (potentiometer for test)
  colorValue = map(sensorValue, 0, 1023, 0, 255);      // remapping 0-1023 to read as RGB values
  redValue = analogRead(redPin);                       // reads what values go into each of the RGB pins
  greenValue = analogRead(greenPin);
  blueValue = analogRead(bluePin);
    
  if(sensorValue == 0)
  {
     analogWrite(redPin, 255);
     analogWrite(greenPin, 255);
     analogWrite(bluePin, 255);
  }
  else if(1 < sensorValue < 341)
  {
     analogWrite(redPin, 0);
     analogWrite(greenPin, 255);
     analogWrite(bluePin, 0);
  }
  else if(342 < sensorValue < 682)
  {
     analogWrite(redPin, 255);
     analogWrite(greenPin, 153);
     analogWrite(bluePin, 0);
  }
  else
  {
     analogWrite(redPin, 255);
     analogWrite(greenPin, 0);
     analogWrite(bluePin, 0);
  }
  
  Serial.print("sensor = " );
  Serial.print(sensorValue);
  Serial.print("\t");
  Serial.print("mapped as = " );
  Serial.print(colorValue);
  Serial.print("\t");
  Serial.print("red = " );
  Serial.print(redValue);
  Serial.print("\t");
  Serial.print("green = " );
  Serial.print(greenValue);
  Serial.print("\t");
  Serial.print("blue = " );
  Serial.println(blueValue);
  delay(1000);
}

So let me explain, as I mentioned, I'm working on a water level sensor and would like RGB LED to visually display the height of the water based on the following:

When no water in the tank, I would like R=255, G=255, B=255 (white) as I assume the sensor would be reading as 0

I've divided 1023 (analog output max) by 3 (representing low water level, medium water level, high water level). This is where 341 (low) and 682 (medium) come from, with 1023 representing high.

I would like low to be represented as green (0,255,0). Medium as orange (255,153,0). Lastly high as red (255,0,0)

Originally I wanted the colors to fade in and out of each other so I was using the following code where I thought mapping the changes separately would both give the colors I wanted and each water level and fade them in and out of each other.

int sensorPin = A0;  // Analog input, water level sensor
int redPin = 11;     // Output pins that the LEDs are connected to
int greenPin = 10;
int bluePin = 9;

int sensorValue = 0;       // value read from the sensor
int colorValue = 0;        // value output to the PWM (analog out) pin
int redValue = 0;
int greenValue = 0;
int blueValue = 0;


void setup() {
  Serial.begin(9600);
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
}

void loop() {
  sensorValue = analogRead(sensorPin);
  redValue = analogRead(redPin);
  greenValue = analogRead(greenPin);
  blueValue = analogRead(bluePin);
    
  if(sensorValue == 0)
  {
     analogWrite(redPin, 255);
     analogWrite(greenPin, 255);
     analogWrite(bluePin, 255);
  }
  else if(sensorValue <= 341)
  {
     analogWrite(redPin, map(sensorValue, 1, 341, 255, 0));
     analogWrite(greenPin, 255);
     analogWrite(bluePin, map(sensorValue, 1, 341, 255, 0));
  }
  else if(sensorValue <= 682)
  {
     analogWrite(redPin, map(sensorValue, 342, 682, 0, 255));
     analogWrite(greenPin, map(sensorValue, 342, 682, 0, 153));
     analogWrite(bluePin, 0);
  }
  else
  {
     analogWrite(redPin, 255);
     analogWrite(greenPin, 0);
     analogWrite(bluePin, 0);
  }
  
  Serial.print("input = " );
  Serial.print(sensorValue);
  Serial.print("\t");
  Serial.print("red = " );
  Serial.print(redValue);
  Serial.print("\t");
  Serial.print("green = " );
  Serial.print(greenValue);
  Serial.print("\t");
  Serial.print("blue = " );
  Serial.println(blueValue);
  delay(1000);
}

I've basically been working on them simultaneously hoping one would work. As I mentioned before, I've been trying small changes hoping I'm just not using the right syntax. But after over 2 weeks I've got nothing. Needless to say, my professor isn't happy. Before you start bashing on my professor, lets just please keep this about the code.


Current Setup:
Since I don't know how to draw those fancy diagrams I'll just quickly explain it here.
Using an Arduino Uno
RGB LED is Common Anode, using 220 resistors, ground is going into 3.3V
For testing I'm using a potentiometer (10k I believe), plugged into the 5V


Problem:
I've either been getting no color or shades of purple.

Also the readings I've been getting from the first code I uploaded are when the pot is set to 0 the serial monitor says it's reading (roughly) 100,190,216 which is a dull cyan type of a color, however the LED isn't even on.

When pot is at 341 the serial monitor reads roughly 327,336,334 which shouldn't even be giving me a color (rgb max is 255) but the LED is lit up to a purple.

When pot is at 682 the serial monitor reads roughly 590,533,504 and the LED is still purple


I'll take any help I can get.

Thank you for taking the time to read this in advance.
-E

  redValue = analogRead(redPin);
  greenValue = analogRead(greenPin);
  blueValue = analogRead(bluePin);

Why are you trying to do analogRead on digital output pins?

RGB LED is Common Anode, using 220 resistors, ground is going into 3.5V

Ground is going where? Should be going to ground shouldn't it?

Problem:
I've either been getting no color or shades of purple.

Also the readings I've been getting from the first code I uploaded are when the pot is set to 0 the serial monitor says it's reading (roughly) 100,190,216 which is a dull cyan type of a color, however the LED isn't even on.

When pot is at 341 the serial monitor reads roughly 327,336,334 which shouldn't even be giving me a color (rgb max is 255) but the LED is lit up to a purple.

When pot is at 682 the serial monitor reads roughly 590,533,504 and the LED is still purple

Those numbers are pretty meaningless. They are coming from your misguided attempt to read your PWM values back out of pins that can't be read analog.

Instead of that, set redValue, greenValue, and blueValue to where you want in the if / else statements. Don't do any analogWrite there, just put the values you want in those variables.

Then after the if / else section, do one set of analogWrite

analogWrite(redPin, redValue);
analogWrite(greenPin, greenValue);
analogWrite(bluePin, blueValue);

That way, the values coming out on the serial monitor will have something to do with the color you see and you'll be able to figure out what's going on.

Thank you for responding so quickly Delta_G

Delta_G:
Ground is going where? Should be going to ground shouldn't it?

From what I've read, Common Cathodes go to ground and Common Anodes (like the RGB LED I'm using) go to power source

Delta_G:
Instead of that, set redValue, greenValue, and blueValue to where you want in the if / else statements. Don't do any analogWrite there, just put the values you want in those variables.

Then after the if / else section, do one set of analogWrite

analogWrite(redPin, redValue);

analogWrite(greenPin, greenValue);
analogWrite(bluePin, blueValue);

I'm sorry but I'm not sure if I follow.

Do you mean something like:

if(sensorValue == 0)
  {
     redValue = 255);
     greenValue = 255);
     blueValue = 255);
  }
  else if(1 < sensorValue < 341)
  {
     redValue = 0);
     greenValue = 255);
     blueValue = 0);
  }
  else if(342 < sensorValue < 682)
  {
     redValue = 255);
     greenValue = 153);
     blueValue = 0);
  }
  else
  {
     redValue = 255);
     greenValue = 0);
     blueValue = 0);
  }

analogWrite(redPin, redValue);
analogWrite(greenPin, greenValue);
analogWrite(bluePin, blueValue);

I'll give this a try in the meantime. But if I'm mistaken could you please elaborate on this?

So I gave the code a try and the serial monitor now uses the values I've assigned to it based on the pot. HOWEVER the LED is still purple

Nope that's exactly what I meant. But without those errant close parenthesis.

Do you have the leds connected between 5V and ground now? Or are they still between 5V and 3.5V?

Delta_G:
Do you have the leds connected between 5V and ground now? Or are they still between 5V and 3.5V?

The LED is only connected to the 3.3V, common anode RGB LEDs get connected to a V+

I tried doing it the other way and it doesn't even light up

ebmartinez:
The LED is only connected to the 3.3V, common anode RGB LEDs get connected to a V+

I tried doing it the other way and it doesn't even light up

No no no. A LED has TWO leads. One goes to power and the other goes to ground. You may be using one of the output pins to supply the power or ground, but you have to have both ends connected.

Up above in the first post you say that one side of the LED is connected to 5V and the other is to 3.5V.

You literally said this:

RGB LED is Common Anode, using 220 resistors, ground is going into 3.5V

but it appears you have changed that.

Either way, one end of that LED goes to pin 9, 10, or 11 right?

The thing is, if the anode is connected to 5V and the cathode goes to the PWM pin 9 or 10 or 11, then lower PWM values turn on the LED and higher values turn it off. Setting the pin to 5V puts power on both terminals, nothing flows light is off. Putting the pin closer to 0V means the current flows and the light lights up. If that is indeed the case then it appears you have all your math backwards.

Delta_G:
No no no. A LED has TWO leads. One goes to power and the other goes to ground. You may be using one of the output pins to supply the power or ground, but you have to have both ends connected.

Up above in the first post you say that one side of the LED is connected to 5V and the other is to 3.5V.

You literally said this: but it appears you have changed that.

Either way, one end of that LED goes to pin 9, 10, or 11 right?

The thing is, if the anode is connected to 5V and the cathode goes to the PWM pin 9 or 10 or 11, then lower PWM values turn on the LED and higher values turn it off. Setting the pin to 5V puts power on both terminals, nothing flows light is off. Putting the pin closer to 0V means the current flows and the light lights up. If that is indeed the case then it appears you have all your math backwards.

I think there's a bit of misunderstanding somewhere. It could very easily be from me, so please correct me if I'm wrong.

I'm using an RGB LED. Like this one below:

or better yet this one:

\

As you can see in from the images, it has 4 leads. The one I am using is a common anode therefore the longest lead, which seems to be called the ground as far as I can tell, has to go to a power source.

Up above I said the LED is connected to the 3.3V and the potentiometer is connected to the 5V, as its been since I posted this. Looks something similar to this:

Which means I have one pin going to 11, one going to 10, and one going to 9.

Now as for the math backwards part, yes, you are right. I've actually already changed the values to reflect that and was going to mention it on here but saw you posted already.

But now I am only getting white when the potentiometer reads 0 and green on every other input. I cannot get it to produce the last half of the if...else statement

else if(342 < sensorValue < 682)
  {
     analogWrite(redPin, 0);
     analogWrite(greenPin, 102);
     analogWrite(bluePin, 255);
  }
  else
  {
     analogWrite(redPin, 0);
     analogWrite(greenPin, 255);
     analogWrite(bluePin, 255);
  }

Can anyone else help?

if(342 < sensorValue < 682)

Syntax error. You can only have one comparison at a time. You can string them together with && (AND) or || (OR).

I think you want:

if((342 < sensorValue) && (sensorValue < 682))

Delta_G:

if(342 < sensorValue < 682)

Syntax error. You can only have one comparison at a time. You can string them together with && (AND) or || (OR).

I think you want:

if((342 < sensorValue) && (sensorValue < 682))

THANK YOU. Yes, that was the problem. Thank you for all your help, seriously.

Now tomorrow I can try to tackle the fading between colors problem. But at least I have the minimum of what I wanted to do. So again, thank you very much.

Awesome.

One last tip for you:

When you're doing these type of range testing things, it's often easier to use else if and organize the values so you only need to test one thing. Damn that's confusing to write, I can't imagine how it reads. Here's an example.

if(x < 342) {
    // Do something because x is less than 342
}
else if (x < 682) {
    //  runs for values between 342 and 681
   // No need to also test that it is greater than 342.  If it was less than 342 it would have caught the last    condition and we couldn't possibly be here thanks to the else.
}
else if(x < 1000) {
    // similarly, this would only run for values between 682 and 999
}

Delta_G:
One last tip for you:

When you're doing these type of range testing things, it's often easier to use else if and organize the values so you only need to test one thing. Damn that's confusing to write, I can't imagine how it reads. Here's an example.

Okay, I see how that works. Thank you again for your help.