1

As of now I have code that takes a value from a potentiometer and maps it from 0-9. Based on this mapped value a number will be displayed on the seven segment display.

Currently, if I quickly turn the pot completely then back to zero it will show everything very quickly and then show 0 until I change the pot value again. What I am trying to do is make it so if it's quickly turned completely then back to 0, after a second it will display all the number from 0-9 then back down to 0, each for a second.

I was given a hint to use arrays to create a FIFO queue but I am not sure how to go about doing this and I have been stuck on this for a while. Here's my code:

// Pin 2-8 is connected to the 7 segments of the display.
// Pin 0 is for potentiometer
int potval;
int pinA = 2;
int pinB = 3;
int pinC = 4;
int pinD = 5;
int pinE = 6;
int pinF = 7;
int pinG = 8;
int i;

// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pins as outputs.
  pinMode(pinA, OUTPUT);     
  pinMode(pinB, OUTPUT);     
  pinMode(pinC, OUTPUT);     
  pinMode(pinD, OUTPUT);     
  pinMode(pinE, OUTPUT);     
  pinMode(pinF, OUTPUT);     
  pinMode(pinG, OUTPUT);     
}

void loop() {
  potval=map(analogRead(A0),0,921,0,9);
  if (potval==0){
    //0
    digitalWrite(pinA, LOW);   
    digitalWrite(pinB, LOW);   
    digitalWrite(pinC, LOW);   
    digitalWrite(pinD, LOW);   
    digitalWrite(pinE, LOW);   
    digitalWrite(pinF, LOW);   
    digitalWrite(pinG, HIGH); 
  }
  if (potval==1){
    //1
    digitalWrite(pinA, HIGH);   
    digitalWrite(pinB, LOW);   
    digitalWrite(pinC, LOW);   
    digitalWrite(pinD, HIGH);   
    digitalWrite(pinE, HIGH);   
    digitalWrite(pinF, HIGH);   
    digitalWrite(pinG, HIGH);
  }
  if (potval==2){
    //2
    digitalWrite(pinA, LOW);   
    digitalWrite(pinB, LOW);   
    digitalWrite(pinC, HIGH);   
    digitalWrite(pinD, LOW);   
    digitalWrite(pinE, LOW);   
    digitalWrite(pinF, HIGH);   
    digitalWrite(pinG, LOW);
  }
  if (potval==3){
    //3
    digitalWrite(pinA, LOW);   
    digitalWrite(pinB, LOW);   
    digitalWrite(pinC, LOW);   
    digitalWrite(pinD, LOW);   
    digitalWrite(pinE, HIGH);   
    digitalWrite(pinF, HIGH);   
    digitalWrite(pinG, LOW);
  }
  if (potval==4){
    //4
    digitalWrite(pinA, HIGH);   
    digitalWrite(pinB, LOW);   
    digitalWrite(pinC, LOW);   
    digitalWrite(pinD, HIGH);   
    digitalWrite(pinE, HIGH);   
    digitalWrite(pinF, LOW);   
    digitalWrite(pinG, LOW); 
  }
  if (potval==5){
    //5
    digitalWrite(pinA, LOW);   
    digitalWrite(pinB, HIGH);   
    digitalWrite(pinC, LOW);   
    digitalWrite(pinD, LOW);   
    digitalWrite(pinE, HIGH);   
    digitalWrite(pinF, LOW);   
    digitalWrite(pinG, LOW);  
  }
  if (potval==6){
    //6
    digitalWrite(pinA, LOW);   
    digitalWrite(pinB, HIGH);   
    digitalWrite(pinC, LOW);   
    digitalWrite(pinD, LOW);   
    digitalWrite(pinE, LOW);   
    digitalWrite(pinF, LOW);   
    digitalWrite(pinG, LOW); 
  }
  if (potval==7){
    //7
    digitalWrite(pinA, LOW);   
    digitalWrite(pinB, LOW);   
    digitalWrite(pinC, LOW);   
    digitalWrite(pinD, HIGH);   
    digitalWrite(pinE, HIGH);   
    digitalWrite(pinF, HIGH);   
    digitalWrite(pinG, HIGH); 
  }
  if (potval==8){
    //8
    digitalWrite(pinA, LOW);   
    digitalWrite(pinB, LOW);   
    digitalWrite(pinC, LOW);   
    digitalWrite(pinD, LOW);   
    digitalWrite(pinE, LOW);   
    digitalWrite(pinF, LOW);   
    digitalWrite(pinG, LOW);  
  }
  if (potval==9){
    //9
    digitalWrite(pinA, LOW);   
    digitalWrite(pinB, LOW);   
    digitalWrite(pinC, LOW);   
    digitalWrite(pinD, HIGH);   
    digitalWrite(pinE, HIGH);   
    digitalWrite(pinF, LOW);   
    digitalWrite(pinG, LOW);  
  }
}
1

Without seeing the code it is bit difficult to help. Please edit your answer and include the relevant parts of the code, otherwise we will end up (re)writing your code for you.

Hint: why not, when you detect a change in the pot, take the new reading, and then count down/up slowly (at the rate that you desire) from the currently displayed reading to the new measured reading - using a for loop, which contains a delay()? With each iteration of the loop you can display the new value. Easy!

However, this sounds like a terrible idea

Note that your code won't do anything else whilst the display is incrementing and decrementing, using this method. So, if you were to spend a lot of time twiddling with the knob, then the code wouldn't get much time to actually do any real work, apart from displaying the updated value.

In order for your code to do real work, whilst displaying the new updated value, you would either need interrupts, or integrate the display updating procedure into the loop(), such that each iteration of the loop() updates the display (or upon each n iterations of loop(), as loop() will probably be looping to quickly. You will probably need to use millis()).

NOTE: From a UX aspect, although it all sounds very 1960's-James-Bond-evil-guy-equipment, the whole notion of the displayed value slowly following the actual location of the knob sounds, at best, extremely infuriating, if not down right dangerous (depending upon the context). Human feedback should be as fast as possible. Else the user will constantly be turning the knob to reach the value that they which to achieve, when in fact they have already passed that value, and may be over compensating, and it is just the fancy display graphics that is showing the wrong value.

Assuming that the knob is controlling something else (actuator, motor, heater, etc.), and not just a pretty display in itself, unless, you are actually outputting the delayed displayed digital value, and not the knob's actual current analogue value, I would seriously recommend against doing this.

I may be wrong, and it would probably require a separate question on SE.UX, although, I would imagine that it has been asked already.

  • Code was added and the pot is just being used to control a 7 segment – Taha A Jun 14 '17 at 7:44
  • Usually anything with a slower refresh rate than 100-60ms is considered laggy and should be avoided. So you could implement some smoothing (say only allow decreasing values) to make the counter seem smoother, otherwise it's quite pointless, human motion itself is rather smooth already if you sample fast enough. – Avamander Aug 14 '17 at 15:00
0

First of all, that way of writing the displays is quite horrible to me ;) Better to use a matrix (and, please, no ints for small variables like pin numbers, and make them constant). This is the code fixed with these improvements:

// Pin 2-8 is connected to the 7 segments of the display.
// Pin 0 is for potentiometer
int potval;
const byte pinA = 2;
const byte pinB = 3;
const byte pinC = 4;
const byte pinD = 5;
const byte pinE = 6;
const byte pinF = 7;
const byte pinG = 8;

byte Matrix[][7] = { { LOW , LOW , LOW , LOW , LOW , LOW , HIGH}, // potval 0
                     { HIGH, LOW , LOW , HIGH, HIGH, HIGH, HIGH}, // potval 1
                     ... fill with the other rows ...
                     { LOW , LOW , LOW , HIGH, HIGH, LOW , LOW }  // potval 9
                    };


// the setup routine runs once when you press reset:
void setup() {                
// initialize the digital pins as outputs.
pinMode(pinA, OUTPUT);     
pinMode(pinB, OUTPUT);     
pinMode(pinC, OUTPUT);     
pinMode(pinD, OUTPUT);     
pinMode(pinE, OUTPUT);     
pinMode(pinF, OUTPUT);     
pinMode(pinG, OUTPUT);     
}

void loop() {
    potval=map(analogRead(A0),0,921,0,9);

    digitalWrite(pinA, Matrix[potval][0]);   
    digitalWrite(pinB, Matrix[potval][0]);   
    digitalWrite(pinC, Matrix[potval][0]);   
    digitalWrite(pinD, Matrix[potval][0]);   
    digitalWrite(pinE, Matrix[potval][0]);   
    digitalWrite(pinF, Matrix[potval][0]);   
    digitalWrite(pinG, Matrix[potval][0]);
}

You can further improve it by not having seven variables but only an array to iterate over, but .. ok, let's keep this.

Ok, now you want to do a "slow movement". In order to do this you can use a variable to track the current position, and let it move towards the target value once every XX ms. This is the approach used, for instance, in CNCs and 3d printers movements.

// Pin 2-8 is connected to the 7 segments of the display.
// Pin 0 is for potentiometer
int potval;
const byte pinA = 2;
const byte pinB = 3;
const byte pinC = 4;
const byte pinD = 5;
const byte pinE = 6;
const byte pinF = 7;
const byte pinG = 8;

unsigned long int prevMillis;
const int delayBetweenMovement = 200;

byte Matrix[][7] = { { LOW , LOW , LOW , LOW , LOW , LOW , HIGH}, // potval 0
                     { HIGH, LOW , LOW , HIGH, HIGH, HIGH, HIGH}, // potval 1
                     ... fill with the other rows ...
                     { LOW , LOW , LOW , HIGH, HIGH, LOW , LOW }  // potval 9
                    };


// the setup routine runs once when you press reset:
void setup() {                
// initialize the digital pins as outputs.
pinMode(pinA, OUTPUT);     
pinMode(pinB, OUTPUT);     
pinMode(pinC, OUTPUT);     
pinMode(pinD, OUTPUT);     
pinMode(pinE, OUTPUT);     
pinMode(pinF, OUTPUT);     
pinMode(pinG, OUTPUT);
prevMillis = millis() - delayBetweenMovement;
}

void loop() {
    if ((millis() - prevMillis) >= delayBetweenMovement)
    {
        prevMillis += delayBetweenMovement;

        potval=map(analogRead(A0),0,921,0,9);
        static int CurrentPotVal = potval;

        if (potval > CurrentPotVal)
            CurrentPotVal++;
        if (potval < CurrentPotVal)
            CurrentPotVal--;


        digitalWrite(pinA, Matrix[CurrentPotVal][0]);   
        digitalWrite(pinB, Matrix[CurrentPotVal][0]);   
        digitalWrite(pinC, Matrix[CurrentPotVal][0]);   
        digitalWrite(pinD, Matrix[CurrentPotVal][0]);   
        digitalWrite(pinE, Matrix[CurrentPotVal][0]);   
        digitalWrite(pinF, Matrix[CurrentPotVal][0]);   
        digitalWrite(pinG, Matrix[CurrentPotVal][0]);
    }
}

The delayBetweenMovement constant makes a delay between the readings. With this method, if you quickly turn it to 9 and then to 0 you will not arrive to 9. For instance you put a 9, the display starts doing 0..1..2..3, then you switch to 0 and the count will not reach 9, but start going back to 0. Reaching 9 will require some more structures; if you need it ask and I'll make some modifications

EDIT: as requested, here is a version that can memoryze up to 20 states and reproduce them. If you need them just increase the FIFO size.

Note: I haven't tested these programs. In the other two I was pretty confident I hadn't made any major bug, but this one is a bit more complicated. There can be some bugs left..

// Pin 2-8 is connected to the 7 segments of the display.
// Pin 0 is for potentiometer
const byte pinA = 2;
const byte pinB = 3;
const byte pinC = 4;
const byte pinD = 5;
const byte pinE = 6;
const byte pinF = 7;
const byte pinG = 8;

unsigned long int prevMillis;
const int delayBetweenMovement = 200;

byte Matrix[][7] = { { LOW , LOW , LOW , LOW , LOW , LOW , HIGH}, // potval 0
                     { HIGH, LOW , LOW , HIGH, HIGH, HIGH, HIGH}, // potval 1
                     ... fill with the other rows ...
                     { LOW , LOW , LOW , HIGH, HIGH, LOW , LOW }  // potval 9
                    };

const byte FifoSize = 20;
byte TargetFifo[FifoSize];
byte FifoHead = 0, FifoTail = 0;

byte potval;

// the setup routine runs once when you press reset:
void setup() {                
    // initialize the digital pins as outputs.
    pinMode(pinA, OUTPUT);     
    pinMode(pinB, OUTPUT);     
    pinMode(pinC, OUTPUT);     
    pinMode(pinD, OUTPUT);     
    pinMode(pinE, OUTPUT);     
    pinMode(pinF, OUTPUT);     
    pinMode(pinG, OUTPUT);
    prevMillis = millis() - delayBetweenMovement;
}

byte FifoAvailableForWrite()
{
    if (FifoTail > FifoHead)
        return (FifoSize - FifoTail + FifoHead);
    else
        return (FifoHead - FifoTail);
}

void loop() {
    potval=map(analogRead(A0),0,921,0,9);
    static byte prevPotVal = potval;
    static int CurrentPotVal = potval;

    if ((prevPotVal != potval) && (FifoAvailableForWrite() > 1))
    {
        TargetFifo[FifoTail] = potval;
        prevPotVal = potval;
        FifoTail = (FifoTail + 1) % FifoSize;
    }

    if ((millis() - prevMillis) >= delayBetweenMovement)
    {
        prevMillis += delayBetweenMovement;

        if (FifoHead != FifoTail)
        {
            if (TargetFifo[FifoHead] > CurrentPotVal)
                CurrentPotVal++;
            if (TargetFifo[FifoHead] < CurrentPotVal)
                CurrentPotVal--;
            while (TargetFifo[FifoHead] == CurrentPotVal)
                FifoHead = (FifoHead + 1) % FifoSize;
        }

        digitalWrite(pinA, Matrix[CurrentPotVal][0]);   
        digitalWrite(pinB, Matrix[CurrentPotVal][0]);   
        digitalWrite(pinC, Matrix[CurrentPotVal][0]);   
        digitalWrite(pinD, Matrix[CurrentPotVal][0]);   
        digitalWrite(pinE, Matrix[CurrentPotVal][0]);   
        digitalWrite(pinF, Matrix[CurrentPotVal][0]);   
        digitalWrite(pinG, Matrix[CurrentPotVal][0]);
    }
}
  • Thank you for this! However, I do need it to go to 9 then back to 0 so if you could grab back to me on how to do it or with the code that would be greatly appreciated. Thanks once again. – Taha A Jun 14 '17 at 12:54
  • @TahaA I tried to develop a fifo based solution.. See if that works.. – frarugi87 Jun 14 '17 at 15:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.