Using switch-case with encoder and 7-segment display

Hi All,

This is my first post. I am new to arduino and programming in general.

I am trying to display a number on a seven segment display based on the position of an encoder. As I am only displaying one digit, I am turning on each segment individually for a given "case" as opposed to using a bcd decoder or library to try and simplify things.

The code I have below is a combination of two examples which I have attempted to modify in order to work together.

The intent of the program is that the number displayed on the serial monitor (newPos), should result in the outcome of one of the 4 cases.

The encoder part of the program appears to be working as it displays the correct position in the serial monitor, however the "case" does not seem to update the 7-segment display based on encoder position.

I have confirmed the 7-segment display is wired correctly as I can turn on the segments manually.

Any input or direction would be appreciated.

Thanks

#include <RotaryEncoder.h>

#define ROTARYSTEPS 1
#define ROTARYMIN 1
#define ROTARYMAX 4

int lastPos = -1;

RotaryEncoder encoder(A2, A3);


void setup() {

  Serial.begin(57600);
  
  pinMode(39, OUTPUT);
  pinMode(41, OUTPUT);
  pinMode(43, OUTPUT);
  pinMode(45, OUTPUT);
  pinMode(47, OUTPUT);
  pinMode(49, OUTPUT);
  pinMode(51, OUTPUT);
  pinMode(53, OUTPUT);

  Serial.println("Encoder Position");
  encoder.setPosition(1 / ROTARYSTEPS); // start with the value of 1.

}


void loop() {

  encoder.tick();

  // get the current physical position and calc the logical position
  int newPos = encoder.getPosition() * ROTARYSTEPS;

  if (newPos < ROTARYMIN) {
    encoder.setPosition(ROTARYMIN / ROTARYSTEPS);
    newPos = ROTARYMIN;

  } else if (newPos > ROTARYMAX) {
    encoder.setPosition(ROTARYMAX / ROTARYSTEPS);
    newPos = ROTARYMAX;
  }

  if (lastPos != newPos) {
    Serial.print(newPos);
    Serial.println();
    lastPos = newPos;
  }


  // read encoder:
  int sensorReading = newPos;
  // map the sensor range to a range of four options:
  int range = map(sensorReading, 1, 2, 3, 4);

  // do something different depending on the range value:
  switch (range) {
    case 0:    // your hand is on the sensor
      digitalWrite(39, HIGH);
      digitalWrite(41, HIGH);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, HIGH);
      digitalWrite(53, HIGH);
      break;
      
    case 1:    // your hand is close to the sensor
      digitalWrite(39, LOW);
      digitalWrite(41, HIGH);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, HIGH);
      digitalWrite(53, HIGH);
      break;

    case 2:    // your hand is close to the sensor
      digitalWrite(39, LOW);
      digitalWrite(41, LOW);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, HIGH);
      digitalWrite(53, HIGH);
      break;

    case 3:    // your hand is close to the sensor
      digitalWrite(39, LOW);
      digitalWrite(41, LOW);
      digitalWrite(43, LOW);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, HIGH);
      digitalWrite(53, HIGH);
      break;
  }
  delay(1);        //



}
  // read encoder:
  int sensorReading = newPos;

That does not read the encoder.

  // map the sensor range to a range of four options:
  int range = map(sensorReading, 1, 2, 3, 4);

RTFM. That is NOT what map() does.

map() doesn't return a range. It returns a value IN a range.

  switch (range) {
    case 0:    // your hand is on the sensor

Even if map() did work as your comment thinks it does, and returned 1, 2, 3, or 4, why do you have a case for range = 0?

    case 1:    // your hand is close to the sensor

WTF? That comment has nothing to do with anything.

Okay, firstly, sorry for the confusing comments, like I said, I had tried to merge two programs and I forgot to remove the irrelevant comments.

I have looked at the map function and now understand how I have used it incorrectly, thank you.

I have got the program working now.

#include <RotaryEncoder.h>

#define ROTARYSTEPS 1
#define ROTARYMIN 1
#define ROTARYMAX 9

int lastPos = -1;

RotaryEncoder encoder(A2, A3);


void setup() {

  Serial.begin(57600);
  
  pinMode(39, OUTPUT);
  pinMode(41, OUTPUT);
  pinMode(43, OUTPUT);
  pinMode(45, OUTPUT);
  pinMode(47, OUTPUT);
  pinMode(49, OUTPUT);
  pinMode(51, OUTPUT);
  pinMode(53, OUTPUT);

  Serial.println("Encoder Position");
  encoder.setPosition(1 / ROTARYSTEPS); // start with the value of 1.

}


void loop() {

  encoder.tick();

  // get the current physical position and calc the logical position
  int newPos = encoder.getPosition() * ROTARYSTEPS;

  if (newPos < ROTARYMIN) {
    encoder.setPosition(ROTARYMIN / ROTARYSTEPS);
    newPos = ROTARYMIN;

  } else if (newPos > ROTARYMAX) {
    encoder.setPosition(ROTARYMAX / ROTARYSTEPS);
    newPos = ROTARYMAX;
  }

  if (lastPos != newPos) {
    Serial.print(newPos);
    Serial.println();
    lastPos = newPos;
  }

  
  switch (newPos) {
    case 1:    
      digitalWrite(39, LOW);
      digitalWrite(41, LOW);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, LOW);
      digitalWrite(51, LOW);
      digitalWrite(53, LOW);
      break;
      
    case 2:    
      digitalWrite(39, HIGH);
      digitalWrite(41, HIGH);
      digitalWrite(43, LOW);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, LOW);
      digitalWrite(53, HIGH);
      break;

    case 3:    
      digitalWrite(39, LOW);
      digitalWrite(41, HIGH);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, LOW);
      digitalWrite(53, HIGH);
      break;

    case 4:    
      digitalWrite(39, LOW);
      digitalWrite(41, LOW);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, LOW);
      digitalWrite(51, HIGH);
      digitalWrite(53, HIGH);
      break;

    case 5:    
      digitalWrite(39, LOW);
      digitalWrite(41, HIGH);
      digitalWrite(43, HIGH);
      digitalWrite(47, LOW);
      digitalWrite(49, HIGH);
      digitalWrite(51, HIGH);
      digitalWrite(53, HIGH);
      break;

    case 6:    
      digitalWrite(39, HIGH);
      digitalWrite(41, HIGH);
      digitalWrite(43, HIGH);
      digitalWrite(47, LOW);
      digitalWrite(49, HIGH);
      digitalWrite(51, HIGH);
      digitalWrite(53, HIGH);
      break;

    case 7:    
      digitalWrite(39, LOW);
      digitalWrite(41, LOW);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, LOW);
      digitalWrite(53, LOW);
      break;

    case 8:    
      digitalWrite(39, HIGH);
      digitalWrite(41, HIGH);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, HIGH);
      digitalWrite(53, HIGH);
      break;

    case 9:    
      digitalWrite(39, LOW);
      digitalWrite(41, LOW);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, HIGH);
      digitalWrite(53, HIGH);
      break;            
      
  }
  delay(1);        



}

I have now incorporated this in to a larger program, which includes an LED strip. However with my limited programming knowledge, I have run into a problem. The aim of the program is to have an LED strip light up, chasing from one end to the other continuously. The speed at which the led chases can be increased or decreased by rotating the encoder, the speed is also displayed in the serial monitor as well as on a seven segment display.

The program does all of the above, however when rotating the encoder, if you rotate just a little bit too fast it skips increments, so you may have incremented the encoder 5 steps while the arduino only registers 2 steps.

When running the code above, without the led strip, I do not have this problem.

When I run the code below, I do have this problem.

Any guidance would be appreciated.

Thank you.

#include "FastLED.h"

#if defined(FASTLED_VERSION) && (FASTLED_VERSION < 3001000)
#warning "Requires FastLED 3.1 or later; check github for latest code."
#endif

#define DATA_PIN    8
//#define CLK_PIN   4
#define LED_TYPE    WS2811
#define COLOR_ORDER GRB
#define NUM_LEDS    60
CRGB leds[NUM_LEDS];

#define BRIGHTNESS         200
#define FRAMES_PER_SECOND  120

#include <RotaryEncoder.h>

#define ROTARYSTEPS 1
#define ROTARYMIN 1
#define ROTARYMAX 9

// Setup a RoraryEncoder for pins A2 and A3:
RotaryEncoder encoder(A2, A3);

// Last known rotary position.
int lastPos = -1;


void setup() {

  delay(3000);

  Serial.begin(57600);

  // tell FastLED about the LED strip configuration
  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);


  // set master brightness control
  FastLED.setBrightness(BRIGHTNESS);

  Serial.println("Led Speed");
  encoder.setPosition(1 / ROTARYSTEPS);

  pinMode(39, OUTPUT);
  pinMode(41, OUTPUT);
  pinMode(43, OUTPUT);
  pinMode(45, OUTPUT);
  pinMode(47, OUTPUT);
  pinMode(49, OUTPUT);
  pinMode(51, OUTPUT);
  pinMode(53, OUTPUT);
}



uint8_t gHue = 0;



void loop() {

  // Call the current pattern function once, updating the 'leds' array
  sinelon();

  // send the 'leds' array out to the actual LED strip
  FastLED.show();
  // insert a delay to keep the framerate modest
  FastLED.delay(1000 / FRAMES_PER_SECOND);

  // do some periodic updates
  EVERY_N_MILLISECONDS( 40 ) {
    gHue++;  // slowly cycle the "base color" through the rainbow
  }
}






void sinelon()
{

  encoder.tick();

  // get the current physical position and calc the logical position
  int newPos = encoder.getPosition() * ROTARYSTEPS;

  if (newPos < ROTARYMIN) {
    encoder.setPosition(ROTARYMIN / ROTARYSTEPS);
    newPos = ROTARYMIN;

  } else if (newPos > ROTARYMAX) {
    encoder.setPosition(ROTARYMAX / ROTARYSTEPS);
    newPos = ROTARYMAX;
  }

  if (lastPos != newPos) {
    Serial.print(newPos);
    Serial.println();
    lastPos = newPos;
  }

  // a colored dot sweeping back and forth, with fading trails
  fadeToBlackBy( leds, NUM_LEDS, 50);
  int pos = beatsin16( newPos + 2, 0, NUM_LEDS - 1 );
  leds[pos] += CHSV( gHue, 255, 192);

  switch (newPos) {
    case 1:
      digitalWrite(39, LOW);
      digitalWrite(41, LOW);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, LOW);
      digitalWrite(51, LOW);
      digitalWrite(53, LOW);
      break;

    case 2:
      digitalWrite(39, HIGH);
      digitalWrite(41, HIGH);
      digitalWrite(43, LOW);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, LOW);
      digitalWrite(53, HIGH);
      break;

    case 3:
      digitalWrite(39, LOW);
      digitalWrite(41, HIGH);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, LOW);
      digitalWrite(53, HIGH);
      break;

    case 4:
      digitalWrite(39, LOW);
      digitalWrite(41, LOW);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, LOW);
      digitalWrite(51, HIGH);
      digitalWrite(53, HIGH);
      break;

    case 5:
      digitalWrite(39, LOW);
      digitalWrite(41, HIGH);
      digitalWrite(43, HIGH);
      digitalWrite(47, LOW);
      digitalWrite(49, HIGH);
      digitalWrite(51, HIGH);
      digitalWrite(53, HIGH);
      break;

    case 6:
      digitalWrite(39, HIGH);
      digitalWrite(41, HIGH);
      digitalWrite(43, HIGH);
      digitalWrite(47, LOW);
      digitalWrite(49, HIGH);
      digitalWrite(51, HIGH);
      digitalWrite(53, HIGH);
      break;

    case 7:
      digitalWrite(39, LOW);
      digitalWrite(41, LOW);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, LOW);
      digitalWrite(53, LOW);
      break;

    case 8:
      digitalWrite(39, HIGH);
      digitalWrite(41, HIGH);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, HIGH);
      digitalWrite(53, HIGH);
      break;

    case 9:
      digitalWrite(39, LOW);
      digitalWrite(41, LOW);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, HIGH);
      digitalWrite(53, HIGH);
      break;

  }
  delay(1);


}

The speed at which the led chases can be increased or decreased by rotating the encoder, the speed is also displayed in the serial monitor as well as on a seven segment display.

You are REALLY going to have to explain the relationship between the encoder reading and a "speed" to me AND to anyone viewing the display.

void setup() {

  delay(3000);

Immediately after applying power, stuff your head in the sand for three seconds. You REALLY, REALLY need to get out of the habit of using useless delay()s.

I can't see the relationship between what sinelon() does and the LED strip.

I've never used the FastLED library, and after seeing this code, I can assure you that I never will.

You are REALLY going to have to explain the relationship between the encoder reading and a "speed" to me AND to anyone viewing the display.

The output of the encoder (input to arduino) is the variable "newPos", this variable is used as an input below, as the value of newPos changes by rotating the encoder, so does the movement speed of the LED's:

int pos = beatsin16( newPos + 2, 0, NUM_LEDS - 1 );

Immediately after applying power, stuff your head in the sand for three seconds. You REALLY, REALLY need to get out of the habit of using useless delay()s.

Most of this code has been pieced together from examples, as I am still learning myself, I honestly am not sure about the original authors reasoning for the delays.

Hopefully that clarifies.

You're polling the encoder. It doesn't take a lot of other stuff going on to see this - the more time spent elsewhere in the code the less there is, proportionally for any one part. You could try running the encoder as an interrupt - there are several libraries available to handle that for you.

I like Rotary encoders, done properly.

YMMV

You're polling the encoder. It doesn't take a lot of other stuff going on to see this - the more time spent elsewhere in the code the less there is, proportionally for any one part. You could try running the encoder as an interrupt - there are several libraries available to handle that for you.

I like Rotary encoders, done properly.

Thanks dougp, I changed the code to use the interrupt code example in the "Rotary encoders, done properly" library, my program is now working perfectly.

Thank you for the input PaulS.

#include "FastLED.h"

#if defined(FASTLED_VERSION) && (FASTLED_VERSION < 3001000)
#warning "Requires FastLED 3.1 or later; check github for latest code."
#endif

#define DATA_PIN    8
#define LED_TYPE    WS2811
#define COLOR_ORDER GRB
#define NUM_LEDS    60
CRGB leds[NUM_LEDS];

#define BRIGHTNESS         200
#define FRAMES_PER_SECOND  120

#include <Rotary.h>

// Rotary encoder is wired with the common to ground and the two
// outputs to pins 2 and 3.
Rotary rotary = Rotary(2, 3);

// Counter that will be incremented or decremented by rotation.
int counter = 3;

int upperLimit = 9;
int lowerLimit = 0;

void setup() {

  Serial.begin(57600);
  attachInterrupt(0, rotate, CHANGE);
  attachInterrupt(1, rotate, CHANGE);

  // tell FastLED about the LED strip configuration
  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);


  // set master brightness control
  FastLED.setBrightness(BRIGHTNESS);

  Serial.println("Led Speed");


  pinMode(39, OUTPUT);
  pinMode(41, OUTPUT);
  pinMode(43, OUTPUT);
  pinMode(45, OUTPUT);
  pinMode(47, OUTPUT);
  pinMode(49, OUTPUT);
  pinMode(51, OUTPUT);
  pinMode(53, OUTPUT);
}

uint8_t gHue = 0;

void loop() {

  // Call the current pattern function once, updating the 'leds' array
  sinelon();

  // send the 'leds' array out to the actual LED strip
  FastLED.show();
  // insert a delay to keep the framerate modest
  FastLED.delay(1000 / FRAMES_PER_SECOND);

  // do some periodic updates
  EVERY_N_MILLISECONDS( 40 ) {
    gHue++;  // slowly cycle the "base color" through the rainbow
  }
}

void rotate() {

  unsigned char result = rotary.process();
  if (result == DIR_CW) {
    counter++;
    if (counter > upperLimit) counter = upperLimit;
    Serial.println(counter);
  } else if (result == DIR_CCW) {
    counter--;
    if (counter < lowerLimit) counter = lowerLimit;
    Serial.println(counter);
  }
}

void sinelon() {

  // a colored dot sweeping back and forth, with fading trails
  fadeToBlackBy( leds, NUM_LEDS, 50);
  int pos = beatsin16( counter + 2, 0, NUM_LEDS - 1 );
  leds[pos] += CHSV( gHue, 255, 192);

  switch (counter) {
    case 0:
      digitalWrite(39, HIGH);
      digitalWrite(41, HIGH);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, HIGH);
      digitalWrite(53, LOW);
      break;

    case 1:
      digitalWrite(39, LOW);
      digitalWrite(41, LOW);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, LOW);
      digitalWrite(51, LOW);
      digitalWrite(53, LOW);
      break;

    case 2:
      digitalWrite(39, HIGH);
      digitalWrite(41, HIGH);
      digitalWrite(43, LOW);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, LOW);
      digitalWrite(53, HIGH);
      break;

    case 3:
      digitalWrite(39, LOW);
      digitalWrite(41, HIGH);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, LOW);
      digitalWrite(53, HIGH);
      break;

    case 4:
      digitalWrite(39, LOW);
      digitalWrite(41, LOW);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, LOW);
      digitalWrite(51, HIGH);
      digitalWrite(53, HIGH);
      break;

    case 5:
      digitalWrite(39, LOW);
      digitalWrite(41, HIGH);
      digitalWrite(43, HIGH);
      digitalWrite(47, LOW);
      digitalWrite(49, HIGH);
      digitalWrite(51, HIGH);
      digitalWrite(53, HIGH);
      break;

    case 6:
      digitalWrite(39, HIGH);
      digitalWrite(41, HIGH);
      digitalWrite(43, HIGH);
      digitalWrite(47, LOW);
      digitalWrite(49, HIGH);
      digitalWrite(51, HIGH);
      digitalWrite(53, HIGH);
      break;

    case 7:
      digitalWrite(39, LOW);
      digitalWrite(41, LOW);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, LOW);
      digitalWrite(53, LOW);
      break;

    case 8:
      digitalWrite(39, HIGH);
      digitalWrite(41, HIGH);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, HIGH);
      digitalWrite(53, HIGH);
      break;

    case 9:
      digitalWrite(39, LOW);
      digitalWrite(41, LOW);
      digitalWrite(43, HIGH);
      digitalWrite(47, HIGH);
      digitalWrite(49, HIGH);
      digitalWrite(51, HIGH);
      digitalWrite(53, HIGH);
      break;

  }

}

JamieDemos:
Thanks dougp, I changed the code to use the interrupt code example in the "Rotary encoders, done properly" library, my program is now working perfectly.

Good show!