0

I am working on a stereo controller and have 1 rotary encoder with a push button. When I push the button it cycles through the options and the rotary encoder lets me set the intensity. I want the individual intensities to remain when I am switching back and forth. When I turn the bass to 50% and then set the volume to 80% I want to come back and the base still be at 50%. The problem I am having is that the intensities are transferring over.

For prototyping I am using 3 LEDS. I can set individual brightness but when I go to change the next LED it automatically changes to the intensity of the previous LED.

The reasoning behind this is that when I set the bass and treble and the volume I don't want the values jumping around when I come back to change something. I want to pick off where it left off.

I think the structure I am going for is a counter based on cases. A common variable outside the case is incremented by the rotary encoder and then stored in case if that is possible.

/*
** Rotary Encoder Example
 ** Use the Sparkfun Rotary Encoder to vary brightness of LED
 **
 ** Sample the encoder at 200Hz using the millis() function
 */

int brightness = 0;    // how bright the LED is, start at half brightness
int fadeAmount = 30;    // how many points to fade the LED by
unsigned long currentTime;
unsigned long loopTime;
const int pin_A = 4;  // pin 12
const int pin_B = 5;  // pin 11
 unsigned char encoder_A;
unsigned char encoder_B;
unsigned char encoder_A_prev=0;
const int green = 11;
const int blue = 10;
const int red=9;
int last_bright=0;

int mode = 0; // Selector State (Initial state = ALL OFF)
int val = 0; // Pin 13 HIGH/LOW Status
int butState = 0; // Last Button State
int modeState = 0; 
int selected=710;
int greenvol=0;
int redvol=0;
int bluevol=0;
int select_bright=0;

void setup()  {
  // declare pin 9 to be an output:
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(pin_A, INPUT);
  pinMode(pin_B, INPUT);
  currentTime = millis();
  loopTime = currentTime; 
} 

void loop()  {
  // get the current elapsed time
  currentTime = millis();

  brightness=select_bright;
  if(currentTime >= (loopTime + 5)){
    // 5ms since last check of encoder = 200Hz  
    encoder_A = digitalRead(pin_A);    // Read encoder pins
    encoder_B = digitalRead(pin_B);   
    if((!encoder_A) && (encoder_A_prev)){
      // A has gone from high to low 
      if(encoder_B) {
        // B is high so clockwise
        // increase the brightness, dont go over 255
        if(brightness + fadeAmount <= 255) brightness += fadeAmount;               
      }   
      else {
        // B is low so counter-clockwise      
        // decrease the brightness, dont go below 0
        if(brightness - fadeAmount >= 0) brightness -= fadeAmount;               
      }   

    }   
    encoder_A_prev = encoder_A;     // Store value of A for next time    

    // set the brightness of pin 9:
    analogWrite(selected, brightness);
    last_bright=brightness;   

    loopTime = currentTime;  // Updates loopTime
  }



  // end of rotary encoder


  val = digitalRead(8);
  delay(5);

  // If we see a change in button state, increment mode value
  if (val != butState && val == HIGH){
    mode++;
  }

  butState = val; // Keep track of most recent button state

  // No need to keep setting pins *every* loop
    if (modeState != mode)

    // If no keys have been pressed yet don't execute
    // the switch code below
  {

    switch ( mode ) {


    case 2:
      selected=red;
      select_bright=redvol;
      redvol=last_bright;

      break;


    case 3:
      selected=green;
      select_bright=greenvol;
      greenvol = last_bright;
      break;


    default:
      selected=blue;
      select_bright=bluevol;
      bluevol = last_bright;

      mode = 1;
     break;


    }                         
  }
}
Zach
  • 3
  • 2

1 Answers1

0

I'd store the brightness value in an array and then use an index to change only one led.

Here is a (i hope) working example. Try it and see if it fits your needs ;)

I made some other changes (you can see them in the comments). Anyway I suggest you to add at least

  1. debouncing on the encoder and the button pins
  2. the complete encoder checking, i.e. check if either A or B changed, and in both directions.

Here is the code; just let me know ;)

byte fadeAmount = 30;

const byte pin_button = 8;
const byte pin_A = 4;  // pin 12
const byte pin_B = 5;  // pin 11
unsigned long loopTime;

unsigned char encoder_A;
unsigned char encoder_B;
unsigned char encoder_A_prev=0;

// Array to store the brightness of the
// red (0), green (1) and blue (2) leds
byte brightnesses[3];
byte lastbrightnesses[3];
byte currentLed;

// Pins for red (0), green (1) and blue (2) leds
byte led_pins[] = {9, 10, 11};

void setup()  {
    pinMode(pin_button, INPUT);
    pinMode(pin_A, INPUT);
    pinMode(pin_B, INPUT);

    // set the brightnesses to their initial states
    // and the lastbrightnesses to ANOTHER value
    for (currentLed=0; currentLed<3; i++)
    {
        pinMode(led_pins[currentLed], OUTPUT);
        brightnesses[currentLed] = 255;
        lastbrightnesses[currentLed] = 0;
    }
    currentLed = 0;

    loopTime = millis() - 5;
} 

void loop()  {
    // I prefer this instead of yours
    // because this is overflow-safe
    if((millis() - loopTime) >= 5) {
        loopTime += 5;

        // Check encoder
        encoder_A = digitalRead(pin_A);
        encoder_B = digitalRead(pin_B);   
        if((!encoder_A) && (encoder_A_prev)){
            // A has gone from high to low 
            if(encoder_B) {
                // B is high so clockwise
                // Again, this is overflow-safe
                // And it compensates for not reaching the end of the values
                if(brightnesses[currentLed] <= 255 - fadeAmount)
                    brightnesses[currentLed] += fadeAmount;
                else
                    brightnesses[currentLed] = 255;
            }   
            else {
                // B is low so counter-clockwise      
                // decrease the brightness, dont go below 0
                if(brightnesses[currentLed] >= fadeAmount)
                    brightnesses[currentLed] -= fadeAmount;
                else
                    brightnesses[currentLed] = 0;
            }
        }   
        encoder_A_prev = encoder_A;     // Store value of A for next time    

        // I'd read the button every 5ms too
        val = digitalRead(pin_button);
        if (val != butState && val == HIGH){
            currentLed++;
            if (currentLed >= 3) currentLed = 0;
            butState = val;
        }
    }

    // Here you can also check only currentLed instead
    // of every led if you can only change it through
    // the encoder
    byte i;
    for (i=0; i<3; i++)
    {
        if (lastbrightnesses[i] != brightnesses[i])
        {
            analogWrite(led_pins[i], brightnesses[i]);
            lastbrightnesses[i] = brightnesses[i];
        }
    }
}
frarugi87
  • 2,826
  • 1
  • 20
  • 41