7 segments display Multiplexed + potentiometer => Dimming/ flickering numbers

Hi !

I'm having some problems to make work simultaneously a multiplexed 7 segments display and other functions (like for example a simple potentiometer reading and printing function).

The 7seg. display works great, I multiplexed it and it displays different numbers rightly and in the right order, no flicker, no dimming light but only if I don't manipulate other things on my project.

As soon as I manipulate other elements, ie a potentiometer, the digits on the 7seg display start dimming (or have irregular light intensity);

precisely, while I manipulate my potentiometer, the first digit (the 8 in the example code) become brighter, and the others dim.

here is my code (just the void loop) :

void loop() {   
 
 SevenSeg();

// and the potentiometer function (potentiometer "potard_BPM" is read by a 4051 analog muxer called "mux_A")

mux_A.SelectPin(0);
potard_BPM = mux_A.AnalogRead();
if (potard_BPM > 2){
  if (potard_BPM < (prev_potard_BPM - 5 ) || potard_BPM > (prev_potard_BPM +5)){
    Serial.print(String("<bpm>")+potard_BPM);
    Serial.println("</bpm>");
    prev_potard_BPM = potard_BPM;
    }
}

}

// here is the 7 Segment Function, displaying "978" on a 3 digits 7 segment display

  void SevenSeg(){    

  SevenSeg_9();
  digitalWrite(44,HIGH);
  digitalWrite(45,LOW);
  digitalWrite(46,LOW);    
  delay(1);


  SevenSeg_7();
  digitalWrite(44,LOW);  
  digitalWrite(45,HIGH);  
  delay(1);


  SevenSeg_8();
  digitalWrite(45,LOW);  
  digitalWrite(46,HIGH);    
  delay(1);
  }

To control (on/off) the 3 grounds of my 7 segments digits I use 3 of these components :
BC547B

each central pins linked to the 44,45 end 46 digital PWN pins of my mega (through a 220 ohm resistor for each)

Does anybody have an idea of what I did wrong ?

crasse2:

void loop() {   

mux_A.SelectPin(0);
 potard_BPM = mux_A.AnalogRead();  <--- Problem is here
}



Does anybody have an idea of what I did wrong ?

The problem you are having is caused by the AnalogRead() function. It takes a long time and really slows down how many times your loop is called each second.

For example your loop may run 40,000 or 50,000 times per second before you add AnalogRead(). After adding AnalogRead() your loop may slow down to as little as 700 loops per second or less.

You can make the loop run at 40,000 times per second again by reducing the number of times you call AnalogRead() each second. You can do that by using the 'Blink without delay' example and only calling AnalogRead() once every 5 to 10 milliseconds.

Thank you Sir ! that worked, I used the millis() method as you suggested and add a millis() "delay" of 50 ms to the analogRead function (enough for what I intend to do with the potentiometer values) and it works like a charm now ! :smiley:

Hi again !

So I added millis() "delay" to all my analogRead, but I got another problem of flickering/dimming of my 7 segments display coming from another function that not seems to be solvable the same way.

in my project, I also have an ethernet Shield on my Mega that receive OSC bundled data from my computer. Everything works fine with it (receiving OSC data and using them), but each time I bang/Send an OSC bundle from my Computer to the Ethernet Shield, the 7 segment display flicker (one flickering for one send).

So I assume the problem may come from the fact that parsing and interpreting OSC Bundles is an heavy task to handle for the arduino and so each time it has to do it (each time I send something from my computer via OSC to the arduino) it create a drop in the void loop cadency ?

here is my udp/osc receiving function :

 int packetSize=Udp.parsePacket();
 OSCBundle msgIN;
 
  if( packetSize>0){
    
   //Serial.print("msgOSC : "); 
    while(packetSize--){  
      byte n = Udp.read();
      msgIN.fill(n);
      //Serial.print((char)n);         
    }
    msgIN.route("/bpm A", OscBPM_A);
    msgIN.route("/bpm B", OscBPM_B);
    msgIN.route("/bpm C", OscBPM_C);
    msgIN.route("/TrLev1", OscTrLev1);
    msgIN.route("/TrLev2", OscTrLev2);
    msgIN.route("/TrLev3", OscTrLev3);
    msgIN.route("/TrLev4", OscTrLev4);
    msgIN.route("/TrLev5", OscTrLev5);
    msgIN.route("/TrLev6", OscTrLev6);
    msgIN.route("/RandLed", RandLed);
    } 
 }

So if you would like to see what is happening you can count and print the number of loops per second. Then you can see how many loops per second you when removing the ethernet code and how many after adding it back in.

unsigned long loopCount = 0;

void loop() {
	if ((millis() - timer_t) > 1000) {
		Serial.print("Your loop code ran ");
		Serial.print(loopCount);
		Serial.println(" times over the last second");
		loopCount = 0;
		timer_t = millis();
	}
	loopCount++;
}

Hi !

thanks for your help !

I used your code to monitor the void loop cadency and it ran 754 times while not receiving anything from OSC, and the 7segment digit display is working fine.

I tested by adding a heavy function (not related to ethernet, just an heavy dummy calculation), and it can go done to 60/80 times per second without having observable problem on the 7segment digit display.

However if I send data through OSC to the arduino, there is a flicker on the display (each time i send data) and the void loop rate only goes down to 716 per second when I send it just one time per second to 400 at high speed rate continuous sending. So not even close to the 60/80 rate tested before but still causing issues with the 7segment digits display.

I was wondering, maybe there is a power supply problem ? does the ethernet shield use a lot of energy to receive or send data ? (i'm only supplying the arduino through the usb) because having a flicker on the 7segment display each I send just one bundle of data, one time per second, is weird ?

You can not depend on loop() resident processes to perform time critical tasks, unless you can guarantee a maximum latency for the other tasks . Display multiplexing is a time critical task. The only dependable solution is to use a hardware timer and interrupt driven display update.

Thanks for answer !

I'm not sure I understood what you mean ; If I interrupt by any way the display update, It would interrupt the loop through the multiplexed digits and so it won't display any numbers during the interruption ?

crasse2:
Thanks for answer !

I'm not sure I understood what you mean ; If I interrupt by any way the display update, It would interrupt the loop through the multiplexed digits and so it won't display any numbers during the interruption ?

You move all the display code out of loop(), except for numeric conversion routines.

ok !

I didn't know about this method (i'm still a novice) but i found something about it with this 7 digit librairy :

where it says :

This Arduino library makes it easy to drive a multiple digit 7 segment display without having to worry about constantly redrawing the digits. To avoid this the library uses the timer 1 interrupt to refresh the display. In addition to the interrupt driven refresh, which frees up the main loop from refreshing the displays, it has many helper functions to make writing to the display easy.

I'll check how it works, to understand this method, thanks for the guidance Aarg !

Be careful, though. I haven't checked it out myself but I think the ethernet library is also interrupt driven. Part of using interrupts is that while one interrupt is running it disables all other interrupts. Just be aware so you don't go chasing your tail if things go really crazy.

If it were me, I would just cough up the dough for a MAX7219 or MAX7221.

MAX7219, $3 here, takes on all the multiplexing for you, leaves the processor free for other stuff.
http://www.taydaelectronics.com/catalogsearch/result/?q=max7219
Simple write to 1 of 8 registers to update 1 of 8 digits. Common cathode digits are easiest, common anode is possible also.
Can be used to drive discrete LEDs also if not using it to drive digits.

Hi !

Thanks for your help and advices !

So I think I'll follow your advices about the MAX7219 chips and buy 2 of them as I intend to control 4 7seg displays at the end ! I've looked around drivers and tutorials about those chips and they seems to be doing a great job for that as you say ! (and If you're right about the possible interrupt conflicts between displays functions and the ethernet librairy, I sure would like to avoid it as I intend for my project to send 40/60 times per second OSC data through ethernet shield)

however I've tried to work with timer1, as it's new to me and seems quite useful, and did manage to make my display nearly working (without understanding exactly what i was doing in every details... xD ) , it was flickering in a new way, but not so far from working, but that sure is something I should look at for further projects.

however, for the future, here is what I did, trying to control the 7seg display using the interrupt/timer method :

I tried to run the interrupt function in CTC mode while my 3 digit were "spaced" by 5 ms (so the timer1 should run every 15 ms if I'm not mistaken). However with my below code, it's flickering (more slowly than before, and isn't affect by other activities in the arduino, such as OSC bundle reception and parsing, which is good) :

void setup(){
cli();
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;

  OCR1A = 124; // (around 15ms on a 1024 prescaler if i'm not wrong...)
  TCCR1B |= (1 << WGM12); // CTC mode
  TCCR1B |= (1 << CS10);
  TCCR1B |= (1 << CS12); // 
  TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
  sei();
}

ISR(TIMER1_COMPA_vect){

  TimeISR = millis();

  Digit_triple_1 = digitalRead(44);
  Digit_triple_2 = digitalRead(45);
  Digit_triple_3 = digitalRead(46);

if((Digit_triple_3 == HIGH)&&(Time-prevTime_7Digit_Triple >= interval_5)){
  SevenSeg_CharA();
  digitalWrite(44,HIGH);
  digitalWrite(45,LOW);
  digitalWrite(46,LOW);    
  prevTime_7Digit_Triple = Time;
}else if ((Digit_triple_1 == HIGH)&&(Time-prevTime_7Digit_Triple >= interval_5)) {
  SevenSeg_CharB();
  digitalWrite(44,LOW);  
  digitalWrite(45,HIGH);  
  prevTime_7Digit_Triple = Time;
}else if ((Digit_triple_2 == HIGH)&&(Time-prevTime_7Digit_Triple >= interval_5)) {
  SevenSeg_CharC();
  digitalWrite(45,LOW);  
  digitalWrite(46,HIGH);    
  prevTime_7Digit_Triple = Time;
}

mstanley:
Be careful, though. I haven't checked it out myself but I think the ethernet library is also interrupt driven. Part of using interrupts is that while one interrupt is running it disables all other interrupts. Just be aware so you don't go chasing your tail if things go really crazy.

True. Other interrupts will disrupt the display timing. Really, the main advantage of interrupt driven multiplexing is that the timing is more precise.

Personally, I don't understand why most displays essentially require you to multiplex. I wonder how much it would really cost to include a shift register or something in with the display unit to eliminate the need for multiplexing.

Of course, you could just display the data using binary-coded decimal: you would need only four pins per digit.

odometer:
Personally, I don't understand why most displays essentially require you to multiplex. I wonder how much it would really cost to include a shift register or something in with the display unit to eliminate the need for multiplexing.

Of course, you could just display the data using binary-coded decimal: you would need only four pins per digit.

I'm building one (half complete now). It has four large blue 7 segment digits. Each digit will have its own TPIC6B595 8 bit IC. It's easier than multiplexing because the LEDs need more than 5V to operate. The open collector drivers allow the digits to run on a 9 or 12V supply. The LED commons can easily be connected together and PWM'ed if needed for dimming. I paid US$0.50 per IC. It did cross my mind that it would be cool to have absolutely no flicker at full brightness.

I like the 7219 chip personally as its real easy to program. My last project used 3 chips running 6 x 4 digit displays using the led-control library. (uses 3 pins on the arduino). The 7219 maintains the number so I only have to write to it when the displays need to be updated thus no flashing. One down side I did notice is that you can not mix colors on the same chip as the resistor is calculated on the 7 segment led color.