RP2040 - Wiping through a char variable, duplicated characters appear

Using a WaveShare RP2040 Zero, two buttons, and an SSD1306 128x64 OLED.

I'm "wiping" over "const char Characters", it has uppercase, lowercase, and numbers.

if I scroll left, I see the first four character from Characters are repeated. But if I scroll all the way right to the point it wraps around or all the way left, the duplicated characters do not appear.

I'm super new to C++ and simply cannot see the issue.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Pin definitions for buttons
const int button1Pin = 28;
const int button2Pin = 27;

int button1state = 0;
int button2state = 0;

// Characters set
int slider = 5;

int leftleftchar_index = slider-2;
int leftchar_index = slider-1;
int mid_index = slider;
int rightchar_index = slider+1;
int rightrightchar_index = slider+2;
const char characters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";

// Function to update the display
void updateDisplay() {
  display.clearDisplay();
  display.fillRect(49, 0, 24, 100, SSD1306_WHITE); // Fill rectangle with solid white
  
  display.setTextSize(4); 
  display.setCursor(1, 30); 
  display.setTextColor(SSD1306_WHITE);
  display.print(characters[leftleftchar_index % strlen(characters)]); 

  display.setTextSize(4); 
  display.setCursor(26, 20); 
  display.setTextColor(SSD1306_WHITE); 
  display.print(characters[leftchar_index % strlen(characters)]); 

  display.setTextSize(4); 
  display.setCursor(51, 15); 
  display.setTextColor(SSD1306_BLACK); // Set text color to black with white background
  display.print(characters[mid_index % strlen(characters)]); ; 

  display.setTextSize(4); 
  display.setCursor(76, 20);
  display.setTextColor(SSD1306_WHITE); 
  display.print(characters[rightchar_index % strlen(characters)]); 

  display.setTextSize(4); 
  display.setCursor(101, 30); 
  display.setTextColor(SSD1306_WHITE); 
  display.print(characters[rightrightchar_index % strlen(characters)]); 

  display.display(); // Update the display with the new data
}

void setup() {
  // Initialize I2C and the display
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
    // if display doesn't initialize
    for(;;); // Don't proceed, loop forever
  }
  display.clearDisplay();

  
  // Set button pins as input
  pinMode(button1Pin, INPUT_PULLUP);
  pinMode(button2Pin, INPUT_PULLUP);


  // Initial character display
  updateDisplay();
}

void loop() {
    // Check button states
    if (digitalRead(button1Pin) == LOW) { // Button 1 pressed
        if (button1state == 0) {
            leftleftchar_index--;
            leftchar_index--;
            mid_index--;
            rightchar_index--;
            rightrightchar_index--;
            updateDisplay();
            button1state = 1;

        }
    } else {
        button1state = 0; // Reset state when button is released
    }

    if (digitalRead(button2Pin) == LOW) { // Button 2 pressed
        if (button2state == 0) {
            leftleftchar_index++;
            leftchar_index++;
            mid_index++;
            rightchar_index++;
            rightrightchar_index++;
            updateDisplay();
            button2state = 1;
            
        }
    } else {
        button2state = 0; // Reset state when button is released
    }
    delay(10);  // Debounce delay
}

What does that mean?

Why have all these variables? You only need to remember the 'mid_index'. The rest you can compute on the fly.

Nothing in your code appears to check whether your index is going out of bounds. When going left, when the index hits zero, you probably want it to jump back to the end of the character array. Conversely, when going right and hitting upon the last position, you probably want it to bounce back to 0.

Well, that would be one way. The other option of course is to hit the limit and then refuse to go further left/right. Depends on what you have in mind.

When calculating the array positions to the left and the right of the index, you should also take into account this wraparound behavior, of course.

Wiping. "moving" the variable under the 5 text positions.
Here's a video of how the "wiping" looks - LINK TO GOOGLE DRIVE

The leftleftchar int bit was a nooby way of tracking all my variables. its a readability thing for just me.

and I thought I was tracking the out of bounds using the modulus operator on the string length.

  display.print(characters[leftleftchar_index % strlen(characters)]); 

I understand. It doesn't add anything useful and will end up being more confusing than helping. You'll understand once you start working more on your code, doing modifications etc., at which point you'll overlook one or two variables when doing an update, and then scratching your head for a couple of hours looking for the error.

The usual way of doing this is using two if-statements: one that checks out of bounds on the left side, and one that checks on the right side. The left-bound if-statement you put in the button1Pin routine, the right-bound if-statement in button2Pin.

I'll quickly whip out the Modulus bit, try two IFs, and report back!

1 Like

In principle, your modulo approach should work - but I'm not so sure how robust it is when going to negative values of the index.

For testing small snippets, I sometimes use cpp.sh: https://cpp.sh/
Consider this:

#include <iostream>

const char* str = {"ABCD"};
int main()
{
  std::cout << "Right\n";
  for (int i = 0; i < 16; i ++) {
      std::cout << str[i % 4];
  }
  std::cout << "\nLeft\n";
  for (int i = 0; i > -16; i --) {
      std::cout << str[i % 4];
  }
}

Which generates the following output:

Right
ABCDABCDABCDABCD
Left
A FNA FNA FNA FN 

As you can tell, things break down when the index is negative.

This is the basis for my fix.

I used an IF to convert any negative number the to the highest value in my Characters var.

now the modulus works as intended, as the numbers never go negative.

Thanks again for pointing me away from my beloved Modulus :smiley: .

1 Like

There you go, sometimes you can have your cake and eat it!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.