Multitasking with a display and neopixels

Hi everyone! I could use a bit of help with some code that i’m writing for one of my projects. The project is a wearable name tag that has an oled display and some Neopixels. It is going to scroll through some text, while also at the same time have some Neopixels light up the area around the name tag, pretty straightforward. I have gotten the neopixels to fade through a rainbow pattern, and gotten the display to scroll the text, however, the function to get the rainbow effect of the neopixels uses a delay, and of course I can’t have that becuase it makes my display update wayy to slow. I have tried implementing a system like in the blinkWithoutDelay example, but I havent had any luck. The neopixel just stays on a red color, but the screen works like normal. Any help is greatly appreciated!

Here is the code, the are that need work on is the main loop function, and the rainbow function.

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

Adafruit_SSD1306 display(4);
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(1, 13, NEO_RGB + NEO_KHZ800);

char message[] = "Eric"; // the message to display
int positionx = -128; // the farthest left the text will go before going back to the right
int directionx = 1; //this is used to change the direction in which the text scrolls across the display
int speedx = 2; //recomended to be 1 for smoothest display, 2 has noticable tearing

unsigned long previousMillis = 0; //for timing of the neopixel
const long interval = 10; //interval of 10 miliseconds

void setup()   {                
  
  pixels.begin(); //initialise pixels
  pixels.setBrightness(60); //turn down the brightness so they dont burn your eyes
  pixels.show(); //show nothing
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C
  display.setTextSize(9); //set the font very large so it fills the display
  display.setTextColor(WHITE); 
  display.setTextWrap(false);
  display.display(); //display the splash screen
  delay(2000);
  display.clearDisplay();
  
  
}


void loop() {

  scrollText(); //function to animate the message across the display
  
  unsigned long currentMillis = millis(); //record the current time

  if (currentMillis - previousMillis >= interval) { 
    previousMillis = currentMillis;
    rainbow(); //execute the rainbow function 
  }
    
}


void scrollText(){

  if (positionx >= 128){ //if the text gets to the far right edge of the display (128), then change the direction
    directionx = -1; 
  }
  if (positionx <= -210){ ////if the text gets to the far left edge of the display (-210), then change the direction
    directionx = 1;
  }
  
  display.setCursor(positionx,0); //move the cursor to the new position
  display.print(message); //print the message at the new position
  display.display(); //refresh display
  positionx = (positionx + (speedx * directionx));//get the new position for next refresh
  display.clearDisplay(); //clear display
}
  
void rainbow() { //function to get a rainbow pattern on the neopixels

  for (int color=0; color<255; color++) {
    for (int i=0; i<pixels.numPixels(); i++) {
      pixels.setPixelColor(i, Wheel(color));
      }
  pixels.show(); 
  delay(10); // this delay cuases the screen to refresh very slowly
  }  
}

  
uint32_t Wheel(byte WheelPos) { //function to get the colours for the rainbow
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
   return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else if(WheelPos < 170) {
    WheelPos -= 85;
   return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  } else {
   WheelPos -= 170;
   return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  }
}

See Several things at the same time

Get rid of the call to delay and the for loops

Great!, I figured it out. I removed the for loops as suggested, and now it works as it should. The Several things at the same time post is also very usefull. Thanks!

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

Adafruit_SSD1306 display(4);
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(1, 13, NEO_RGB + NEO_KHZ800);

char message[] = "Eric"; // the message to display
int positionx = -128; // the farthest left the text will go before going back to the right
int directionx = 1; //this is used to change the direction in which the text scrolls across the display
int speedx = 2; //recomended to be 1 for smoothest display, 2 has noticable tearing

unsigned long previousMillis = 0; //for timing of the neopixel
const long interval = 10; //interval of 10 miliseconds
int color = 0;

void setup()   {                
  
  pixels.begin(); //initialise pixels
  pixels.setBrightness(50); //turn down the brightness so they dont burn your eyes
  pixels.show(); //show nothing
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C
  display.setTextSize(9); //set the font very large so it fills the display
  display.setTextColor(WHITE); 
  display.setTextWrap(false);
  display.display(); //display the splash screen
  delay(2000);
  display.clearDisplay(); 
}

void loop() {

  scrollText(); //function to animate the message across the display
  rainbow();   
}

void scrollText(){

  if (positionx >= 128){ //if the text gets to the far right edge of the display (128), then change the direction
    directionx = -1; 
  }
  if (positionx <= -210){ ////if the text gets to the far left edge of the display (-210), then change the direction
    directionx = 1;
  }
  
  display.setCursor(positionx,0); //move the cursor to the new position
  display.print(message); //print the message at the new position
  display.display(); //refresh display
  positionx = (positionx + (speedx * directionx));//get the new position for next refresh
  display.clearDisplay(); //clear display
}
  
void rainbow() { //function to get a rainbow pattern on the neopixels

  unsigned long currentMillis = millis(); //record the current time

  if (currentMillis - previousMillis >= interval) { 
    previousMillis = currentMillis;
    pixels.setPixelColor(0, Wheel(color));
    color ++ ;
    if (color == 255){
      color = 0;
    }
    pixels.show(); 
  }
}

  
uint32_t Wheel(byte WheelPos) { //function to get the colours for the rainbow
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
   return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else if(WheelPos < 170) {
    WheelPos -= 85;
   return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  } else {
   WheelPos -= 170;
   return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  }
}