Trouble adding seven-segment display functionality to RPi project

Hey all, this is my first post here, so give me any constructive feedback on formatting or anything else really. My only programming experience is with simple Arduino projects and I’m basically trying to learn C++, OF and GLSL by trial-and-error.

So, I’ve been modifying this existing video feedback project (strange-loop/src at master · meltdream/strange-loop · GitHub) which loads videos from a thumb drive or USB camera to a GLSL texture and allows you to manipulate buffer-based feedback effects with several knobs and joysticks. The limitation with the code is it only allows you to advance the video to the next by alphanumeric order. What I’ve been trying to do is add a rotary encoder and a 4 digit 14-segment display to scroll through filenames and make it easy change to whichever video you want.

I almost have everything working: I’ve got the rotary encoder code figured out, got a string array of filenames without extensions to pull from, and I’ve been able to get the display to scroll through a file name using the ‘quadalphanum’ example from this Arduino library (GitHub - adafruit/Adafruit_LED_Backpack: Adafruit LED Backpack Library for our various LED backpacks.) modified to use WiringPI I2C instead of the Arduino Wire library.

My issue is that either the 14-seg display doesn’t show anything, or the video doesn’t play. I’ve tried using a threadedFunction so the 200ms sleep between each digit update doesn’t interrupt the rest of the program, but this is when I’m seeing the display not show, and it seems that isThreadRunning() is not returning true though I called startThread() in the setup of this QuadAlpha.cpp file

#include "QuadAlpha.h"


QuadAlpha::QuadAlpha(){
nameIsNew = true;
namelength = 64;
blinkrate = 0;
ch = 'c';
file = "test";
}



void QuadAlpha::setup() {
  alpha4.begin(0x70);  // pass in the address

//lights up each digit sequentially
  alpha4.writeDigitRaw(3, 0x0);
  alpha4.writeDigitRaw(0, 0xFFFF);
  alpha4.writeDisplay();
  delay(100);
  alpha4.writeDigitRaw(0, 0x0);
  alpha4.writeDigitRaw(1, 0xFFFF);
  alpha4.writeDisplay();
  delay(100);
  alpha4.writeDigitRaw(1, 0x0);
  alpha4.writeDigitRaw(2, 0xFFFF);
  alpha4.writeDisplay();
  delay(100);
  alpha4.writeDigitRaw(2, 0x0);
  alpha4.writeDigitRaw(3, 0xFFFF);
  alpha4.writeDisplay();
  delay(100);
  alpha4.clear();
  alpha4.writeDisplay();
  startThread();
}

void QuadAlpha::update(std::string fileName, int b){
//when new file name is passed in

alpha4.clear(); //clears the display buffer
nameIsNew = true;

file = fileName + "  ";
namelength = file.length();
blinkrate = b; //I2C value for changing blink rate

nameIsNew = false;
}

void QuadAlpha::threadedFunction(){
		while((isThreadRunning() && (nameIsNew == false))){
	
			for(int i=0; i < namelength; i++){

 				  ch = file.at(i); //scrolls through the filename by char

				  // scroll down display
		  
				  displaybuffer[0] = displaybuffer[1];
				  displaybuffer[1] = displaybuffer[2];
				  displaybuffer[2] = displaybuffer[3];
				  displaybuffer[3] = ch;
		 
				  // set every digit to the buffer
				  alpha4.writeDigitAscii(0, displaybuffer[0]);
				  alpha4.writeDigitAscii(1, displaybuffer[1]);
				  alpha4.writeDigitAscii(2, displaybuffer[2]);
				  alpha4.writeDigitAscii(3, displaybuffer[3]);

				  // write it out!
				  //alpha4.blinkRate(blinkrate);
				  alpha4.writeDisplay();
				  sleep(200);

		}
	}
}

The program uses threads for the potentiometer and button control and I used a thread for the rotary encoder as well. Is this a case where I shouldn’t use a thread, or am I making some error? I can post the rest of my modified code on github if more context is needed. I appreciate any feedback or advice anyone can offer.

One suggestion: in the case you don’t need threads you can do something like this:

float nextDisplayUpdate = 0;

// inside update or draw
if (ofGetElapsedTimef() > nextDisplayUpdate) {
	nextDisplayUpdate = ofGetElapsedTimef() + 0.2;
	updateDisplay();
}

Hi @veneering , wow what a fun project! I love using OF with RPis and the wiringPi library. And shaders are awesome and work well on the PIs too (usually).

dimitre’s suggestion is a fantastic way to approach intermittent things in an app. Another way is to use a modulus:

// in ofApp::update()
    int frames = 60 * 0.2; // 60 fps * 200ms
    if(ofGetFrameNum() % frames == 0){
        // write to the display
    }

The threadedFunction() of ofThread is kind of like a mini program that runs independently inside of the main OF app. ofThread can’t use any openGL calls, which can be limiting. And shared resources (containers, variables, etc) often need to be locked so that only 1 thread at a time can access them. This will often slow one or both threads down while they wait to get the lock to continue their tasks. So these are cases where you wouldn’t want to use ofThread.

If you haven’t already, maybe have a look at the threadExample project in /examples/threads. It’s well commented and it has a basic design pattern for how to use a class derived from ofThread, including locks and how to use the std::condition_variable.

Sometimes it helps to build a small and simple version, and slowly add complexity in stages. In this case, you could get the threadedFunction() working properly by itself in an OF app, and then add the video player, and then other stuff, compiling and testing as you go.

That worked after I added your code and fixed some minor scope issues too. The display is looking great! Thank you for the suggestion.