How do I make something occur once while count is in a range

Hi everyone,

Here's my issue, I have a TFT shield that displays a number when my encoder count is within a certain range. The problem is that the draw time is slow so I do not want the number being redrawn every count the encoder is within its range. Heres an example of how this will function:

EncoderCount < 100 {display 'Position 1' }
EncoderCount >= 100 && EncoderCount < 200 {display 'Position 2' }
EncoderCount >= 200 && EncoderCount < 300 {display 'Position 3' }
EncoderCount >= 300 && EncoderCount < 400 {display 'Position 4' }

Theoretically I could make it so that as soon as the threshold is crossed, the position number can be drawn only once and the rest of the range will be exempt. The problem with that is encoders can sometimes skip counts and hence may miss the small window ( >=100 && < 101 )

So I'm wondering if there is a function that I'm missing that will allow me to draw the position number once while the encoder count is within a certain range, but not redraw anything until the count crosses another threshold.

My first solution was to create another variable count that will track the position, which works, but only in one direction. The encoder will be counting up and down at times. Below is my current code, using a simple counter to simulate the encoder.

Thanks in advance for your help.

*thought just now: Would OOP help me with this issue?

#include <stdint.h>
#include <TFTv2.h>
#include <SPI.h>

int drawnNumber = 0;

void setup() {
    TFT_BL_ON;      // turn on the background light
    Tft.TFTinit();  // init TFT library

    Tft.drawChar('1',80,40,20,WHITE);

}

void loop() {
    for (int i = 1; i < 1000; i++) {
        displayEnc(i);
        drawBigNum(i);
//        delay(1);
    }
}

int drawBigNum(long encCounter) {
    if (encCounter < 100 && drawnNumber == 0) {
        drawOneWht();
        drawnNumber = 1;
    }
    if (encCounter >= 100 && encCounter < 200 && drawnNumber == 1) {
        drawOneRed();
        drawnNumber = 2;
    }

    if (encCounter >= 200 && encCounter < 300 && drawnNumber == 2) {
        drawTwoWht();
        drawnNumber = 3;
    }
    if (encCounter >= 300 && encCounter < 400 && drawnNumber == 3) {
        drawTwoRed();
        drawnNumber = 4;
    }

    if (encCounter >= 400 && encCounter < 500 && drawnNumber == 4) {
        drawThreeWht();
        drawnNumber = 5;
    }
    if (encCounter >= 500 && encCounter < 600 && drawnNumber == 5) {
        drawThreeRed();
        drawnNumber = 6;
    }
}

void displayEnc(long encCount) {
    Tft.fillRectangle(8, 230, 150,45,BLACK);
    Tft.drawNumber(encCount,10,240,4,WHITE);
}

void drawOneWht() {
    Tft.fillRectangle(70, 30, 170,170,BLACK);
    Tft.drawChar('1',80,40,20,WHITE);
}
void drawOneRed() {
    Tft.fillRectangle(70, 30, 170,170,BLACK);
    Tft.drawChar('1',80,40,20,RED);
}

void drawTwoWht() {
    Tft.fillRectangle(70, 30, 170,170,BLACK);
    Tft.drawChar('2',80,40,20,WHITE);
}
void drawTwoRed() {
    Tft.fillRectangle(70, 30, 170,170,BLACK);
    Tft.drawChar('2',80,40,20,RED);
}

void drawThreeWht() {
    Tft.fillRectangle(70, 30, 170,170,BLACK);
    Tft.drawChar('3',80,40,20,WHITE);
}
void drawThreeRed() {
    Tft.fillRectangle(70, 30, 170,170,BLACK);
    Tft.drawChar('3',80,40,20,RED);
}

So I'm wondering if there is a function that I'm missing that will allow me to draw the position number once while the encoder count is within a certain range, but not redraw anything until the count crosses another threshold.

There is not a function, per se. There is a procedure. You need to keep track of the previous range. On any given pass through loop(), determine the current range. Compare that to the previous range. If different, re-draw. Update the previous range with the current range.

How is illustrated in the state change detection example.

Thanks for your reply, I've solved the problem by creating two counters, one that tracks the position ranges, and another that increments upon the position range being displayed.

I am still curious however if there is a more efficient solution.

#include <stdint.h>
#include <TFTv2.h>
#include <SPI.h>

int drawnNumber1 = 0;
int drawnNumber2 = 0;

void setup() {
    TFT_BL_ON;      // turn on the background light
    Tft.TFTinit();  // init TFT library
}

void loop() {
    for (int i = 1; i <= 600; i++) {
        displayEnc(i);
        drawBigNum(i);
//        delay(1);
    }
    for (int i = 600; i >= 00; i--) {
        displayEnc(i);
        drawBigNum(i);
    }
}

int drawBigNum(long encCounter) {
    if (encCounter < 100) {drawnNumber1 = 1;}
    if (encCounter >= 100 && encCounter < 200) {drawnNumber1 = 2;}
    if (encCounter >= 200 && encCounter < 300) {drawnNumber1 = 3;}
    if (encCounter >= 300 && encCounter < 400) {drawnNumber1 = 4;}
    if (encCounter >= 400 && encCounter < 500) {drawnNumber1 = 5;}
    if (encCounter >= 500 && encCounter < 600) {drawnNumber1 = 6;}
  

    if (encCounter < 100 && drawnNumber1 == 1 && (drawnNumber2 == 0 || drawnNumber2 == 2)) {
        drawOneWht();
        drawnNumber2 = 1;
    }
    if (encCounter >= 100 && encCounter < 200 && drawnNumber1 == 2 && (drawnNumber2 == 1 || drawnNumber2 == 3)) {
        drawOneRed();
        drawnNumber2 = 2;
    }

    if (encCounter >= 200 && encCounter < 300 && drawnNumber1 == 3 && (drawnNumber2 == 2 || drawnNumber2 == 4)) {
        drawTwoWht();
        drawnNumber2 = 3;
    }
    if (encCounter >= 300 && encCounter < 400 && drawnNumber1 == 4 && (drawnNumber2 == 3 || drawnNumber2 == 5)) {
        drawTwoRed();
        drawnNumber2 = 4;
    }

    if (encCounter >= 400 && encCounter < 500 && drawnNumber1 == 5 && (drawnNumber2 == 4 || drawnNumber2 == 6)) {
        drawThreeWht();
        drawnNumber2 = 5;
    }
    if (encCounter >= 500 && encCounter < 600 && drawnNumber1 == 6 && (drawnNumber2 == 5 || drawnNumber2 == 0)) {
        drawThreeRed();
        drawnNumber2 = 6;
    }
}

void displayEnc(long encCount) {
    Tft.fillRectangle(8, 230, 150,45,BLACK);
    Tft.drawNumber(encCount,10,240,4,WHITE);
}

void drawOneWht() {
    Tft.fillRectangle(70, 30, 170,170,BLACK);
    Tft.drawChar('1',80,40,20,WHITE);
}
void drawOneRed() {
    Tft.fillRectangle(70, 30, 170,170,BLACK);
    Tft.drawChar('1',80,40,20,RED);
}

void drawTwoWht() {
    Tft.fillRectangle(70, 30, 170,170,BLACK);
    Tft.drawChar('2',80,40,20,WHITE);
}
void drawTwoRed() {
    Tft.fillRectangle(70, 30, 170,170,BLACK);
    Tft.drawChar('2',80,40,20,RED);
}

void drawThreeWht() {
    Tft.fillRectangle(70, 30, 170,170,BLACK);
    Tft.drawChar('3',80,40,20,WHITE);
}
void drawThreeRed() {
    Tft.fillRectangle(70, 30, 170,170,BLACK);
    Tft.drawChar('3',80,40,20,RED);
}

I am still curious however if there is a more efficient solution.

Yes. There is. There are 6 ranges. Having two variables, currRange and prevRange, seems far more intuitive.

// Determine the current range (1 to 6).
if(currRange != prevRange)
{
   // Do some drawing
}
prevRange = currRange;

But of course. Silly me.

Thanks a lot for your help.