(SOLVED) Running a multi-stage bargraph via MAX7219

I have a bargraph unit that is grouped into what can be considered digits and segments (akin to a 7-segment display). My requirement is to be able to scroll the bargraph up and down, control its speed and endpoints, and potentially add additional animations.

I successfully mocked the entire circuit up on a breadbroad and run it through its paces using the LedControl.h library and the example found here: tronixstuff.com. By all accounts, the MAX7219 is running the bargraph correctly, so my hardware design checks out so there's no cause for alarm there.

The issue I've run into is that the Arduino has to be running other bits of software (looking for additional inputs, providing other outputs, and running other counters) as the bargraph animates, so loops specifically for the bargraph won't work (?). I am planning on using the methodology of the "Blink without Delay" example to control the time intervals between each segment of the bargraph changing state, as I can't use delay(), but beyond that, the code is just looking for state changes on inputs to change other outputs.

I believe I could brute-force the code using binary references [lc.setRow(0,0,B00000001); through lc.setRow(0,7,B11111111);], but that seems incredibly inefficient and extremely clunky, not to mention debugging or alterations would be a nightmare. Also, and it could very well be my error in how the MAX7219 would function with the program running at speed, but I have concerns that the bargraph would appear to be in a DOT mode, rather than a solid bar, using this method. I'm getting a bit frustrated; every idea I have seems to fall apart when I check its logic path, and I am by no means a software guy, so I bow to people with far more skill than I.

In short, is there a more elegant way to write code that will scroll this 8x8 bargraph display from [0,0] to [7,7] and back to [0,0], that can be run outside of something like the for() loop used in the example code?

How many bars do you have and how many segments in each?
What's the pinout on these displays?

The MAX7219 prefers to run setRow, as it keeps anode/"Segment" pins while running cathode/"Digit" pins before switching to the next anode.

If I understand you correctly, you want each bar to be cumulative, not just 1 moving segment but a fill of all below? Smoothness of that should be undetectable, but it would be best if each of your bars were pinned as common anode (hence asking what the pinout was).

I think you'll be fine as you may be underestimating how fast the Arduino runs loops and how fast the MAX7219 can refresh displays (800Hz, btw). Binary references for row states is simple, stick with it.

Definitely do away with delays in your code, though. You can define your functions separately and then call them in void loop, but you still have to tie them into void loop.

The MAX7219 prefers to run setRow,

No, it has no preferences at all. No matter what the data it will simply scan the matrix exactly the same.

I believe I could brute-force the code using binary references

But you could do that in a simple loop with the value you write starting off at 1 and changing by value = (value << 1) | 1 each time round the loop.

You're right, mike, I wasn't clear. Has more to do with the library. I was meaning that setRow works a slight bit more efficiently than setColumn which is what one might intuitively be attracted to to use just because it's a presumably columned bar graph.

I actually did set up the bargraph common(s) to be rows, for that exact reason, having read that setColumn is less efficient.

I completely forgot about bit-shifting, and that does seem like it would be pretty compact. I'm at work, so I don't actually have access to my IDE, let alone my test circuit, but threw the following together:

#include <binary.h>
#include <LedControl.h>

void setup()
{
	int BG_value = B00000001;			//bottom segment
	int BG_counter = 1;				
	int const BG_top = 8; 				//total segments
}

void loop()
{
lc.setRow(0,0,BG_value);				
if (BG_counter < BG_top)				//bargraph moves up
	{
	BG_value = (BG_value << 1)|1;
	BG_counter++;
	}
if (BG_counter >= BG_top)				//bargraph moves down
	{
	BG_value = (unsigned int)BG_value >> 1;
	BG_counter++;
	}
if (BG_counter >=14)					//resets counter
	{
	BG_counter = 1;
	}
}

The counter is there to essentially reset the behavior of the bargraph, but only goes to 14 to avoid unnecessary duplication of the endpoint behavior. Am I correct in the use of (unsigned int) on the bitshift right to insert 0 instead of 1?

Ok, so after troubleshooting some stupid mistakes I made on my breadboarded circuit, the following code works to make this bargraph climb:

#include <binary.h>
#include <LedControl.h>

LedControl lc=LedControl(12,11,10,1);
int BG_value0 = B00000001;		        //bottom segment DIG 0
int BG_value1 = B00000001;            		//bottom segment DIG 1
int BG_value2 = B00000001;            		//bottom segment DIG 2
int BG_value3 = B00000001;            		//bottom segment DIG 3
int BG_value4 = B00000001;            		//bottom segment DIG 4
int BG_value5 = B00000001;            		//bottom segment DIG 5
int BG_value6 = B00000001;            		//bottom segment DIG 6
int BG_counter = 1;				
byte BG_top = 8; 			       	//total segments per digit
byte BG_total = 51;                   		//total segments used
byte BG_digit = 0;


void setup()
{
  lc.shutdown(0,false);               		// turn off power saving, enables display
  lc.setIntensity(0,12);              		// sets brightness (0~15 possible values)
  lc.clearDisplay(0);                 		// clear screen  
}

void loop()
{
BG_digit = (BG_counter - 1) / BG_top;          	//determine digit

if (BG_digit == 0 && BG_counter <= 8)          	//digit 0
  {
  lc.setRow(0,BG_digit,BG_value0);       
  BG_value0 = (BG_value0 << 1)|1;
  BG_counter++;
  }
if (BG_digit == 1 && BG_counter <= 16)         	//digit 0+1
  {
  lc.setRow(0,0,B11111111);
  lc.setRow(0,BG_digit,BG_value1);       
  BG_value1 = (BG_value1 << 1)|1;
  BG_counter++;
  }
if (BG_digit == 2 && BG_counter <= 24)         	//digit 0+1+2
  {
  lc.setRow(0,0,B11111111);
  lc.setRow(0,1,B11111111);
  lc.setRow(0,BG_digit,BG_value2);       
  BG_value2 = (BG_value2 << 1)|1;
  BG_counter++;
  }
if (BG_digit == 3 && BG_counter <= 32)         	//digit 0+1+2+3
  {
  lc.setRow(0,0,B11111111);
  lc.setRow(0,1,B11111111);
  lc.setRow(0,2,B11111111);
  lc.setRow(0,BG_digit,BG_value3);       
  BG_value3 = (BG_value3 << 1)|1;
  BG_counter++;
  }
if (BG_digit == 4 && BG_counter <= 40)         	//digit 0+1+2+3+4
  {
  lc.setRow(0,0,B11111111);
  lc.setRow(0,1,B11111111);
  lc.setRow(0,2,B11111111);
  lc.setRow(0,3,B11111111);
  lc.setRow(0,BG_digit,BG_value4);       
  BG_value4 = (BG_value4 << 1)|1;
  BG_counter++;
  }
if (BG_digit == 5 && BG_counter <= 48)        	//digit 0+1+2+3+4+5
  {
  lc.setRow(0,0,B11111111);
  lc.setRow(0,1,B11111111);
  lc.setRow(0,2,B11111111);
  lc.setRow(0,3,B11111111);
  lc.setRow(0,4,B11111111);
  lc.setRow(0,BG_digit,BG_value5);       
  BG_value5 = (BG_value5 << 1)|1;
  BG_counter++;
  }
if (BG_digit == 6 && BG_counter <= BG_total)	//digit 0+1+2+3+4+5+6
  {
  lc.setRow(0,0,B11111111);
  lc.setRow(0,1,B11111111);
  lc.setRow(0,2,B11111111);
  lc.setRow(0,3,B11111111);
  lc.setRow(0,4,B11111111);
  lc.setRow(0,5,B11111111);
  lc.setRow(0,BG_digit,BG_value6);       
  BG_value6 = (BG_value6 << 1)|1;
  BG_counter++;
  }
delay(50);
}

It's functional, but a bit bulky and inelegant. Is there any way to condense the setRow commands? This sequence (as well as it decreasing in height) will all need to occur while other commands execute, so all delay() functions will be replaced with a millis() check.

Thanks for any help you can give.

This bit is rather verbose

  lc.setRow(0,0,B11111111);
  lc.setRow(0,1,B11111111);
  lc.setRow(0,2,B11111111);

Write a function where you pass into it a parameter giving how many lines to set and use hex rather than binary.

void setR(byte numberOfRows){
for(int i =0;i< numberOfRows; i++){
    lc.setRow(0,i,0xff);
}

Then call the function in each section giving it a different number each time.

Okay, not to necropost, but I dusted off (literally) this project the other day, and completely forgot what my thought process was.

The goal is to run an array of 50 LEDs from a MAX7219. The physical array is 1x50, but broken into 7 groups (DIG0-DIG6) of 8 segments (SEGDP-SEGG). It should illuminate from 1 to 50 and back down.

My physical circuit functions as needed, but after I started to debug my code and observing the serial monitor, I'm getting odd results I can't decipher. It's so close to working, I'm just wholly frustrated. The only thing that works at intended is the switch from 1-50 to 50-1.

I'm fairly certain there's a much more efficient way to code this, so I'm open to suggestions.

#include <binary.h>
#include <LedControl.h>

//Bargraph Pin Assignments
  LedControl lc=LedControl(12,11,10,1);
  
  int BG_value0 = B00000001;                    //bottom segment DIG 0
  int BG_value1 = B00000001;                    //bottom segment DIG 1
  int BG_value2 = B00000001;                    //bottom segment DIG 2
  int BG_value3 = B00000001;                    //bottom segment DIG 3
  int BG_value4 = B00000001;                    //bottom segment DIG 4
  int BG_value5 = B00000001;                    //bottom segment DIG 5
  int BG_value6 = B00000001;                    //bottom segment DIG 6
  int BG_full = B11111111;
  int BG_counter = 1;        
  int const BG_top = 8;                         //total segments
  int  const BG_total = 50;                     //total segments used
  int BG_digit = 0;
  int BG_direction = 1;                         //0 = down, 1 = up

//Timing
  unsigned long currentMillis = 0;
  unsigned long previousBG1 = 0;
  const long delayBG1 = 200;

void setup() {
      
//Bargraph Initialization
  lc.shutdown(0,false);                       // turn off power saving, enables display
  lc.setIntensity(0,12);                      // sets brightness (0~15 possible values)
  lc.clearDisplay(0);                         // clear screen

  Serial.begin(9600);
}

void loop()
{
  currentMillis = millis();
  if(currentMillis - previousBG1 >= delayBG1)
  {
    Serial.println(BG_digit);
    Serial.println(BG_value0, BIN);
    Serial.println(BG_value1, BIN);
    Serial.println(BG_value2, BIN);
    Serial.println(BG_value3, BIN);
    Serial.println(BG_value4, BIN);
    Serial.println(BG_value5, BIN);
    Serial.println(BG_value6, BIN);    
    Serial.print("--------");
    Serial.println(BG_counter);
    if(BG_counter < BG_total && BG_direction == 1)
    {
      BG_up();
    }
    else if(BG_direction == 0)
    {
      BG_down();
    }
    if (BG_counter == BG_total)
    {
      BG_direction = 0;
    }
    if (BG_counter == 1)
    {
      BG_direction = 1;
    }
        previousBG1 = currentMillis;
   }
}

void BG_up() 
{  
  BG_digit = (BG_counter-1) / BG_top;           //determine digit
  if (BG_digit == 0 && BG_counter <= 8)         //digit 0
    {
    lc.setRow(0,BG_digit,BG_value0);       
    BG_value0 = ((BG_value0 << 1)|1);
    BG_counter++;
    }
  if (BG_digit == 1 && BG_counter <= 16)        //digit 0+1
    {
    lc.setRow(0,0,BG_full);
    lc.setRow(0,BG_digit,BG_value1);       
    BG_value1 = (BG_value1 << 1)|1;
    BG_counter++;
    }
  if (BG_digit == 2 && BG_counter <= 24)        //digit 0+1+2
    {
    lc.setRow(0,0,BG_full);
    lc.setRow(0,1,BG_full);
    lc.setRow(0,BG_digit,BG_value2);       
    BG_value2 = (BG_value2 << 1)|1;
    BG_counter++;
    }
  if (BG_digit == 3 && BG_counter <= 32)        //digit 0+1+2+3
    {
    lc.setRow(0,0,BG_full);
    lc.setRow(0,1,BG_full);
    lc.setRow(0,2,BG_full);
    lc.setRow(0,BG_digit,BG_value3);       
    BG_value3 = (BG_value3 << 1)|1;
    BG_counter++;
    }
  if (BG_digit == 4 && BG_counter <= 40)        //digit 0+1+2+3+4
    {
    lc.setRow(0,0,BG_full);
    lc.setRow(0,1,BG_full);
    lc.setRow(0,2,BG_full);
    lc.setRow(0,3,BG_full);
    lc.setRow(0,BG_digit,BG_value4);       
    BG_value4 = (BG_value4 << 1)|1;
    BG_counter++;
    }
  if (BG_digit == 5 && BG_counter <= 48)        //digit 0+1+2+3+4+5
    {
    lc.setRow(0,0,BG_full);
    lc.setRow(0,1,BG_full);
    lc.setRow(0,2,BG_full);
    lc.setRow(0,3,BG_full);
    lc.setRow(0,4,BG_full);
    lc.setRow(0,BG_digit,BG_value5);       
    BG_value5 = (BG_value5 << 1)|1;
    BG_counter++;
    }
  if (BG_digit == 6 && BG_counter <= BG_total)  //digit 0+1+2+3+4+5+6
    {
    lc.setRow(0,0,BG_full);
    lc.setRow(0,1,BG_full);
    lc.setRow(0,2,BG_full);
    lc.setRow(0,3,BG_full);
    lc.setRow(0,4,BG_full);
    lc.setRow(0,5,BG_full);
    lc.setRow(0,BG_digit,BG_value6);       
    BG_value6 = (BG_value6 << 1)|1;
    BG_counter++;
    }  
}

void BG_down() 
{  
  BG_digit = (BG_counter - 1) / BG_top;         //determine digit
  if (BG_digit == 0 && BG_counter <= 8)         //digit 0
    {
    lc.setRow(0,BG_digit,BG_value0);       
    BG_value0 = (BG_value0 >> 1)|1;
    BG_counter--;
    }
  if (BG_digit == 1 && BG_counter <= 16)        //digit 0+1
    {
    lc.setRow(0,0,BG_full);
    lc.setRow(0,BG_digit,BG_value1);       
    BG_value1 = (BG_value1 >> 1)|1;
    BG_counter--;
    }
  if (BG_digit == 2 && BG_counter <= 24)        //digit 0+1+2
    {
    lc.setRow(0,0,BG_full);
    lc.setRow(0,1,BG_full);
    lc.setRow(0,BG_digit,BG_value2);       
    BG_value2 = (BG_value2 >> 1)|1;
    BG_counter--;
    }
  if (BG_digit == 3 && BG_counter <= 32)        //digit 0+1+2+3
    {
    lc.setRow(0,0,BG_full);
    lc.setRow(0,1,BG_full);
    lc.setRow(0,2,BG_full);
    lc.setRow(0,BG_digit,BG_value3);       
    BG_value3 = (BG_value3 >> 1)|1;
    BG_counter--;
    }
  if (BG_digit == 4 && BG_counter <= 40)        //digit 0+1+2+3+4
    {
    lc.setRow(0,0,BG_full);
    lc.setRow(0,1,BG_full);
    lc.setRow(0,2,BG_full);
    lc.setRow(0,3,BG_full);
    lc.setRow(0,BG_digit,BG_value4);       
    BG_value4 = (BG_value4 >> 1)|1;
    BG_counter--;
    }
  if (BG_digit == 5 && BG_counter <= 48)        //digit 0+1+2+3+4+5
    {
    lc.setRow(0,0,BG_full);
    lc.setRow(0,1,BG_full);
    lc.setRow(0,2,BG_full);
    lc.setRow(0,3,BG_full);
    lc.setRow(0,4,BG_full);
    lc.setRow(0,BG_digit,BG_value5);       
    BG_value5 = (BG_value5 >> 1)|1;
    BG_counter--;
    }
  if (BG_digit == 6 && BG_counter <= BG_total)  //digit 0+1+2+3+4+5+6
    {
    lc.setRow(0,0,BG_full);
    lc.setRow(0,1,BG_full);
    lc.setRow(0,2,BG_full);
    lc.setRow(0,3,BG_full);
    lc.setRow(0,4,BG_full);
    lc.setRow(0,5,BG_full);
    lc.setRow(0,BG_digit,BG_value6);       
    BG_value6 = (BG_value6 >> 1)|1;
    BG_counter--;    
    }  
}

I should add that I'm not dead set on moving bits right to left. In fact, left to right may work more easily, having thought about it.

Well I think this three years is a personal record for the OP getting back to me. :slight_smile:

I'm getting odd results I can't decipher.

How do you expect anyone else to decipher them if you do not say what these results are?
Can you give some simple results and say what you expect them to be please.

When I watch the serial monitor, BGvalue0 goes from (0000000)1, (000000)11, etc, but goes all the way to 111111111 (9 places). The remaining BGValue# all behave according and only go to 8 places, maximum. I've done all sorts of things with the BG_counter and BG_total values, changing the limits in the "if" portions, and subtractive/additive bits in various places, but none of it solved the problem.

The output from the serial monitor should be (with the code as is):

0
1
1
1
1
1
1
1
------1
0
11
1
1
1
1
1
1
------2
0
111
1
1
1
1
1
1
------3

through to

6
11111111
11111111
11111111
11111111
11111111
11111111
11
------50

It should be noted that leading zeros are truncated.

Instead, the final result is something like (I don't have the circuit here at the moment):

6
111111111 <------extra place
11111111
11111111
11111111
11111111
11111111
1
------50

The direction then switches correctly to descend.

When counting down, the DIG never completely switch off, with the first and eighth segments remaining on in the actual circuit. I've not observed the serial monitor in this portion, because the BG_up is not functioning correctly yet.

Try this (untested):

#include <LedControl.h>

//Bargraph Pin Assignments
LedControl lc = LedControl(12, 11, 10, 1);

byte BG_value[7] = {B00000001,B00000001,B00000001,B00000001,B00000001,B00000001,B00000001};
byte BG_full = B11111111;
byte BG_counter = 1;
const byte BG_top = 8;                         //total segments
const byte BG_total = 50;                     //total segments used
byte BG_digit = 0;
byte BG_segment = 0;
char BG_direction = 1;                         //0 = down, 1 = up

//Timing
unsigned long currentMillis = 0;
unsigned long previousBG1 = 0;
const unsigned long delayBG1 = 200;

void setup() {

  //Bargraph Initialization
  lc.shutdown(0, false);                      // turn off power saving, enables display
  lc.setIntensity(0, 12);                     // sets brightness (0~15 possible values)
  lc.clearDisplay(0);                         // clear screen

  Serial.begin(9600);
}

void loop()
{
  currentMillis = millis();
  if (currentMillis - previousBG1 >= delayBG1)
  {
    BG_display();
    Serial.println(BG_digit);
    for (byte d = 0; d < 7; d++) Serial.println(BG_value[d], BIN);
    Serial.print("--------");
    Serial.println(BG_counter);
    BG_counter += BG_direction;
    if (BG_counter >= BG_total || BG_counter < 0) BG_counter = -BG_counter;
    previousBG1 = currentMillis;
  }
}

void BG_display()
{
  
  BG_digit = BG_counter / BG_top;         //determine digit
  BG_segment = BG_counter % BG_top;       //determine segment
  
  for (byte d = 0; d < 7; d++) {
    if (d < BG_digit)
      BG_value[d] = BG_full;
    else if (d > BG_digit)
      BG_value[d] = 0;
    else  
      BG_value[d] = (1 << (BG_segment + 1)) - 1;
    lc.setRow(0, d, BG_value[d]);  
  }
}

Its still a bit clunky, but I didn't want to change too much at once, to avoid bamboozling you.

PaulRB:
Try this (untested):

#include <LedControl.h>

//Bargraph Pin Assignments
LedControl lc = LedControl(12, 11, 10, 1);

byte BG_value[7] = {B00000001,B00000001,B00000001,B00000001,B00000001,B00000001,B00000001};
byte BG_full = B11111111;
byte BG_counter = 1;
const byte BG_top = 8;                         //total segments
const byte BG_total = 50;                     //total segments used
byte BG_digit = 0;
byte BG_segment = 0;
char BG_direction = 1;                         //0 = down, 1 = up

//Timing
unsigned long currentMillis = 0;
unsigned long previousBG1 = 0;
const unsigned long delayBG1 = 200;

void setup() {

//Bargraph Initialization
 lc.shutdown(0, false);                      // turn off power saving, enables display
 lc.setIntensity(0, 12);                     // sets brightness (0~15 possible values)
 lc.clearDisplay(0);                         // clear screen

Serial.begin(9600);
}

void loop()
{
 currentMillis = millis();
 if (currentMillis - previousBG1 >= delayBG1)
 {
   BG_display();
   Serial.println(BG_digit);
   for (byte d = 0; d < 7; d++) Serial.println(BG_value[d], BIN);
   Serial.print("--------");
   Serial.println(BG_counter);
   BG_counter += BG_direction;
   if (BG_counter >= BG_total || BG_counter < 0) BG_counter = -BG_counter;
   previousBG1 = currentMillis;
 }
}

void BG_display()
{
 
 BG_digit = BG_counter / BG_top;         //determine digit
 BG_segment = BG_counter % BG_top;       //determine segment
 
 for (byte d = 0; d < 7; d++) {
   if (d < BG_digit)
     BG_value[d] = BG_full;
   else if (d > BG_digit)
     BG_value[d] = 0;
   else  
     BG_value[d] = (1 << (BG_segment + 1)) - 1;
   lc.setRow(0, d, BG_value[d]);  
 }
}



Its still a bit clunky, but I didn't want to change too much at once, to avoid bamboozling you.

It runs, but the first step starts at "11" instead of "1"

DIGIT - 0
11
0
0
0
0
0
0
--------1
DIGIT - 0
111
0
0
0
0
0
0
--------2

should be

DIGIT - 0
1
0
0
0
0
0
0
--------1
DIGIT - 0
11
0
0
0
0
0
0
--------2

It winds up offsetting everything down the line, so it never seems to switch direction, though I'm sort of seeing the approach..

Ok, try initializing BG_counter to zero:

byte BG_counter = 0;

Also I can see I messed this line up:

if (BG_counter >= BG_total || BG_counter < 0) BG_direction = -BG_direction;

PaulRB:
Ok, try initializing BG_counter to zero:

byte BG_counter = 0;

Also I can see I messed this line up:

if (BG_counter >= BG_total || BG_counter < 0) BG_direction = -BG_direction;

Setting the counter to 0 does work, but it's a bit non-intuitive; I'd like it to start on step 1, not zero, so I can trace where it is for external code. Not sure if I can offset that in BG_display(), or what.

I see the thinking behind the descending portion, but it doesn't seem to work; the cycle just starts over with decrementing.

Okay, I have it working. Here is the code, tweaked from what PaulRB posted:

#include <LedControl.h>

//Bargraph Pin Assignments
LedControl lc = LedControl(12, 11, 10, 1);

byte BG_value[7] = {B00000001,B00000001,B00000001,B00000001,B00000001,B00000001,B00000001};
byte BG_full = B11111111;
byte BG_counter = 1;
const byte BG_top = 8;                         //total segments
const byte BG_total = 50;                     //total segments used
byte BG_digit = 0;
byte BG_segment = 0;
char BG_direction = 1;                         //0 = down, 1 = up

//Timing
unsigned long currentMillis = 0;
unsigned long previousBG1 = 0;
const unsigned long delayBG1 = 100;

void setup() {

  //Bargraph Initialization
  lc.shutdown(0, false);                      // turn off power saving, enables display
  lc.setIntensity(0, 12);                     // sets brightness (0~15 possible values)
  lc.clearDisplay(0);                         // clear screen

  Serial.begin(9600);
}

void loop()
{
  currentMillis = millis();
  if (currentMillis - previousBG1 >= delayBG1)
  {
    BG_display();
    Serial.print("DIGIT - ");
    Serial.println(BG_digit);
    for (byte d = 0; d < 7; d++) Serial.println(BG_value[d], BIN);
    Serial.print("--------");
    Serial.println(BG_counter);
    //BG_counter += BG_direction;
    if (BG_counter >= BG_total || BG_counter <= 0) BG_direction = -BG_direction;
    BG_counter += BG_direction;
    previousBG1 = currentMillis;
  }
}

void BG_display()
{
 
  BG_digit = (BG_counter / BG_top);         //determine digit
  BG_segment = (BG_counter % BG_top);       //determine segment
 
  for (byte d = 0; d < 7; d++) {
    if (d < BG_digit)
      BG_value[d] = BG_full;
    else if (d > BG_digit)
      BG_value[d] = 0;
    else 
      BG_value[d] = (1 << (BG_segment)) - 1;
    lc.setRow(0, d, BG_value[d]); 
  }
}
}

What's odd is that it doesn't seem like the location of "BG_counter += BG_direction" matters, but that doesn't make sense to me.

So here's another thing I'm wrestling with. I want to be able to have an input that will allow the bargraph to top out, but then be held there until that input changes. So I added a switch input to pin 6 and edited the code. When the switch goes high, the bargraph immediately climbs to the top, as intended. The issue I'm running into is that when the switch input goes back to low, the bargraph just stays static. Looking at the code, the line

if (BG_counter >= BG_total || BG_counter < 1) BG_direction = -BG_direction;

should switch the direction of the bargraph, and it should resume its normal up-down operation, but it doesn't. What am I missing here? The entire code is listed below.

#include <LedControl.h>

//Pin Assignments

const int SW_INT = 6;

//Bargraph Pin Assignments
LedControl lc=LedControl(12,11,10,1);

byte BG_value[7] = {B00000001,B00000001,B00000001,B00000001,B00000001,B00000001,B00000001};
byte BG_full = B11111111;
byte BG_counter = 1;
const byte BG_top = 8;             //total segments
byte BG_total = 50;                  //total segments used
byte BG_digit = 0;
byte BG_segment = 0;
char BG_direction = 1;              //-1 = down, 1 = up

//Constants
const long delayBG1 = 100;

//Timing
unsigned long currentMillis = 0;
unsigned long previousBG1 = 0;

//Variable Modes
byte modeINT = 0;

void setup() {

//Pin Modes
pinMode(6,INPUT);

    
//Bargraph Initialization
lc.shutdown(0,false);                       // turn off power saving, enables display
lc.setIntensity(0,7);                      // sets brightness (0~15 possible values)
lc.clearDisplay(0);                         // clear screen

}

void loop()
{
  currentMillis = millis();
  modeINT = digitalRead(SW_INT);
  
  if (modeINT == 0)                   
  {
    if (currentMillis - previousBG1 >= delayBG1)
    {
      BG_display();
      BG_counter += BG_direction;
      if (BG_counter >= BG_total || BG_counter < 1) BG_direction = -BG_direction;
      previousBG1 = currentMillis;
    }
  }
  else if (modeINT == 1)
  {
    if (currentMillis - previousBG1 >= delayBG1)
      {
      BG_display();
      if (BG_counter <= BG_total)
        {
        BG_counter += abs(BG_direction);
        previousBG1 = currentMillis;
        }
      }

    }
}


void BG_display()
{
  BG_digit = ((BG_counter) / BG_top);         //determine digit
  BG_segment = (BG_counter % BG_top);       //determine segment
 
  for (byte d = 0; d < 7; d++)
  {
    if (d < BG_digit)
      BG_value[d] = BG_full;
    else if (d > BG_digit)
      BG_value[d] = 0;
    else 
      BG_value[d] = (1 << (BG_segment)) - 1;
    lc.setRow(0, d, BG_value[d]); 
  }
}

Maybe pin 6 is floating. Did you add a pull-up or -down resistor?

PaulRB:
Maybe pin 6 is floating. Did you add a pull-up or -down resistor?

It has a 10k pulldown resistor, yes.

the line:-
if (BG_counter >= BG_total || BG_counter < 1) BG_direction = -BG_direction;

should switch the direction of the bargraph, and it should resume its normal up-down operation, but it doesn't.

Yes it does.
Insert

Serial.print(BG_counter); Serial.print(" "); Serial.println((int)BG_direction);

After that line, and you will see it count correctly both up and down. Use Serial.begin in the setup function to set the baud rate. Note the cast in the printing of the BG_direction variable is just to make it show up as 1 and -1, otherwise it shows up as a null ( not printable ) and an upside down question mark 0xFF, but it still counts correctly.

Using Serial.print is a good way of seeing your program variables and program flow.

This is what I see :-

42 1
43 1
44 1
45 1
46 1
47 1
48 1
49 1
50 -1
49 -1
48 -1
47 -1
46 -1
45 -1
44 -1

Thanks, Mike. I screwed around a bit based on what my Serial was telling me, and tweaked some bounds so it's working properly now. Until I tweak something else and give myself more issues, that is.