Analog readings from pots not going to zero

Greetings all. I’ve got a circuit where an arduino nano reads analog inputs from three potentiometers, converts these readings into a scale of 0-255, and displays them on an LCD 1602A IC2. The three potentiometers are controlling the red, green, and blue values for a strip of addressable LEDs (NeoPixels). The circuit is designed to let me choose color values for LED projects without having to upload values to the board, adjust, and then repeat continuously.

When the circuit first powers up, the red, green, and blue values on the LCD are all zero, and when turned up to maximum they are all 255. This works great. But when I turn them back down to zero, the numbers on the LCD don’t fall all the way to zero, which looks sloppy.

Here’s the code:

#include <Adafruit_NeoPixel.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
int red, green, blue = 0;

//I2C pins declaration
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

// IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIN 2
#define NUMPIXELS 5

//Initialize the neopixel strip
Adafruit_NeoPixel strip(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  //Set the pins connected to the potentiometer as inputs
  pinMode(A0, INPUT);
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);


//LCD
  lcd.begin(16, 2);
  lcd.backlight();
  lcd.setCursor(0,0); //Defining positon to write from first row,first column
  lcd.print("Home again,"); //You can write 16 Characters per line
  delay(1000);
  lcd.setCursor(0,1);
  lcd.print("home again");
  delay(1000);
  lcd.setCursor(0,0);
  lcd.print("jiggity jig.");
  lcd.setCursor(0,1); 
  lcd.print("            "); 
  delay(2000);
  lcd.clear();
  delay(500);
  lcd.setCursor(0,0); 
  lcd.print("Good evening,"); 
  lcd.setCursor(0,1); 
  lcd.print("Thomas.");
  delay(3000);
  lcd.clear();

//NeoPixels
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  rainbowCycle(1);//Flash rainbows at the begining

}

void loop() {

  //Read and store the potentiometer values
  //We are scaling them from a 12bit scale to an 8 bit scale
  red = map(analogRead(A0), 0, 4095, 0, 255);
  green = map(analogRead(A2), 0, 4095, 0, 255);
  blue = map(analogRead(A3), 0, 4095, 0, 255);

  //set colors of all the eight neopixles
  for (int pixel = 0; pixel < 16; pixel++)
  {
    strip.setPixelColor(pixel, red, green, blue);
  }
  strip.show();//Update the strip with new color values
  delay(50);

 //LCD code
  lcd.setCursor(0,0); //Defining positon to write from first row,first column.
  lcd.print("Red ");
  lcd.print(analogRead(A0)/4); 
  lcd.setCursor(8, 0);
  lcd.print("Grn ");
  lcd.print(analogRead(A2)/4);
  lcd.setCursor(0, 1);
  lcd.print("Blue ");
  lcd.print(analogRead(A3)/4);
}


void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
    for (i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

// Helper function for rainbows
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if (WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

I should also mention that some of the LCD readouts jump outside of the 0-255 range, seemingly at random—my gut tells me these problems are related. Any ideas how to fix these issues?

Is it because you’re not printing leading spaces?

That’s easy to fix.

  lcd.setCursor(0,0); //Defining positon to write from first row,first column.
  lcd.print("Red ");
  lcd.print("    "); // 4 spaces
  lcd.setCursor(4,0);
  lcd.print(analogRead(A0)/4);

tbird_forever: I've got a circuit where an arduino nano reads analog inputs from three potentiometers...

A Nano has a 10-bit A/D, so the 12-bit (4096) part of the code is wrong. See this snippet (untested), and correct your code accordingly. Leo..

void setup() {
  // print static text in setup, to prevent flicker
  lcd.setCursor(0, 0);
  lcd.print("Red ");
  lcd.setCursor(8, 0);
  lcd.print("Grn ");
  lcd.setCursor(0, 1);
  lcd.print("Blue ");
}


void loop {
  //Read and store the potentiometer values
  //We are scaling them from a 10bit scale to an 8 bit scale
  red = analogRead(A0) >> 2; // 10 to 8 = shift two bits
  green = analogRead(A2) >> 2;
  blue = analogRead(A3) >> 2;

  ...
// only print the values, using the variable/values you already have
  lcd.setCursor(4, 0); // move cursor just behind the static word "RED "
  lcd.print("   "); // 3 spaces to clear previous value
  lcd.setCursor(4, 0); // back to pos 5 again
  lcd.print(red); // print value
  lcd.setCursor(13, 0);
  lcd.print("   ");
  lcd.setCursor(13, 0);
  lcd.print(green);
  lcd.setCursor(5, 1);
  lcd.print("   ");
  lcd.setCursor(5, 1);
  lcd.print(blue);  
}

Wawa: A Nano has a 10-bit A/D, so the 12-bit (4096) part of the code is wrong. See this snippet (untested), and correct your code accordingly. Leo..

void setup() {
  // print static text in setup, to prevent flicker
  lcd.setCursor(0, 0);
  lcd.print("Red ");
  lcd.setCursor(8, 0);
  lcd.print("Grn ");
  lcd.setCursor(0, 1);
  lcd.print("Blue ");
}

void loop {   //Read and store the potentiometer values   //We are scaling them from a 10bit scale to an 8 bit scale   red = analogRead(A0) >> 2; // 10 to 8 = shift two bits   green = analogRead(A2) >> 2;   blue = analogRead(A3) >> 2;

  ... // only print the values, using the variable/values you already have   lcd.setCursor(4, 0); // move cursor just behind the static word "RED "   lcd.print("  "); // 3 spaces to clear previous value   lcd.setCursor(4, 0); // back to pos 5 again   lcd.print(red); // print value   lcd.setCursor(13, 0);   lcd.print("  ");   lcd.setCursor(13, 0);   lcd.print(green);   lcd.setCursor(5, 1);   lcd.print("  ");   lcd.setCursor(5, 1);   lcd.print(blue);  }

Thank you for this—your code works beautifully!

One more question: the numbers on the LCD (the converted analog readings) sometimes jitter between two digits, presumably because the analog reading is not a whole number. This isn't a big problem for functionality, but it looks a bit sloppy on my part. Any ideas how to resolve this?

Jitter is caused by successive readings being different, which will always be possible for an analog signal that's quantized into steps.

Hysteresis is the way to solve this - only update the value if the current reading is more than one count different from the existing value.

tbird_forever:
One more question: the numbers on the LCD (the converted analog readings) sometimes jitter between two digits, presumably because the analog reading is not a whole number. This isn’t a big problem for functionality, but it looks a bit sloppy on my part. Any ideas how to resolve this?

Hysteresis can solve this.
Try this.
Leo…

change
  int red, green, blue;
to
  int red, green, blue, newRed, newGreen, newBlue;

change this block
  red = analogRead(A0) >> 2; // 10 to 8 = shift two bits
  green = analogRead(A2) >> 2;
  blue = analogRead(A3) >> 2;
to
  newRed = analogRead(A0);
  if (newRed < (red - 2) || newRed > (red + 2)) red = newRed >> 2;
  newGreen = analogRead(A2);
  if (newGreen < (green - 2) || newGreen > (green + 2)) green = newGreen >> 2;
  newBlue = analogRead(A3);
  if (newBlue < (blue - 2) || newBlue > (blue + 2)) blue = newBlue >> 2;

Wawa:
Hysteresis can solve this.
Try this.
Leo…

change

int red, green, blue;
to
  int red, green, blue, newRed, newGreen, newBlue;

change this block
  red = analogRead(A0) >> 2; // 10 to 8 = shift two bits
  green = analogRead(A2) >> 2;
  blue = analogRead(A3) >> 2;
to
  newRed = analogRead(A0);
  if (newRed < (red - 2) || newRed > (red + 2)) red = newRed >> 2;
  newGreen = analogRead(A2);
  if (newGreen < (green - 2) || newGreen > (green + 2)) green = newGreen >> 2;
  newBlue = analogRead(A3);
  if (newBlue < (blue - 2) || newBlue > (blue + 2)) blue = newBlue >> 2;

Many thanks for the code. Unfortunately, it doesn’t solve the problem. I’m new to hysteresis, so I’ll dig into doing some research on that.

That code is obviously wrong as red/green/blue are 8 bit and newRed/newGreen/newBlue are 10 bit, so cannot be compared. Lose the ">> 2"'s and do everything 10 bit.

Convert to 8-bit when you drive the LEDs.

Duh, of course.
Try to move the >> 2 to the lcd.print and the LED code.
Leo…

if (newRed < (red - 2) || newRed > (red + 2)) red = newRed;

lcd.print(red >> 2);

Wawa:
Duh, of course.
Try to move the >> 2 to the lcd.print and the LED code.
Leo…

if (newRed < (red - 2) || newRed > (red + 2)) red = newRed;

lcd.print(red >> 2);

I appreciate the code, but still doesn’t solve the problem. It also introduces a stepping effect in the LED’s as the pots are adjusted. :frowning:

Will do some research into this and report back.