some help with using a double 7 segment display

good day to all of you, now then i wanted to ask for some help with displaying multiple numbers on a 7 segment display, some context; for a univerisity project i am required to code absolutely everything in c only; we are not allowed to use any arduino functions whatsoever; so that means the use of anything from the functions section on the resources page is completely prohibited and we get 0 marks right off the bat. anyway back on topic i am using a arduino mega 2560 and i wanted to display the numbers 1-16, i was wondering how i would do that with a double 7 segment display with c only; i did some searching around on here and the best i could find was this thread;https://forum.arduino.cc/index.php?topic=371999.0 but i saw it was a bit dated so i felt it was best to start a new thread than revive that older thread considering.

i haven't starting coding it just yet however i can supply some details; the double 7 segment is a ACD8143 one, it has 14 pins and can display in RGB (pretty fancy for the first one i found and brought if i am being honest) here is a link to the data sheet;http://www.adh-tech.com.tw/files/ACD8143.pdf i have successfully got it displaying using a battery only so i know it works but now i want to take it a step further so i was thinking of wiring with the common cathodes of each respective 7 segment to their own pins drawing low (cathode needs to be grounded for the leds to work) so 4,7,8 going to pin 23 and 10, 11, 14 going to pin 22, the remaining 8 control the seven segments and the decimal points, they have been wiring in order of A to DP following the datasheet from pin 2 to pin 9.

now for the questions; (a) in particular i read on the previous one that a limiting resistor needs to be used, can i ask about a recommendation for the a minimum rated resistor? (b) i read that it is impossible to display two separate numbers at the exact same time on the device i have can i ask as to how i would go about multiplexing it instead in c only? finally (c) can i ask how i would go about activating the fast pwm mode in c only code for pins 2 - 9? if i can do that i can use it to set the intensity of the leds so knowing would be a huge help as deciphering the arduino mega 2560 datasheet is painful a task indeed.

sorry about all the questions and/or if i am asking in the wrong area i really appreciate any and all contribution made to this in order to help me out even if it is to nudge me in the right direction :)

Sincerely, Tragical

i have successfully got it displaying using a battery only

Then you may already have damaged it. Always use a series resistor when testing LEDs. The value of the series resistor depends on the battery voltage and the type of led. 1K should be safe enough for most batteries and LEDs.

Interesting challenge.

No Arduino functions, eh?

That is going to get very interesting, as setup() and loop() are in fact, themselves specific Arduino functions which perform many important tasks which you may need.

I would think the Mega 2560 is a poor choice; a Nano would be more practical.

The RGB display is rather cute, but it is not a great idea to attempt to use PWM; that will complicate matters substantially as you have to set up the timers to do so - as well as implementing the effect of analogWrite. In particular, you have to multiplex the display, so the multiplexing and PWM would clash badly. In fact, you would be better off to do your own PWM in software.

For multiplexing - and for a number of other things - you would want a timing system. That involves setting up timers and interrupts - by direct register manipulation. Again, it gets tricky.

The (practical) alternative is to time by "spin" loops. Even there it gets tricky, as aggressive "C" compilers may actually "optimise" and remove such "do nothing" loops.

Of course you will need current limiting resistors - you insert them in series with each of the lines you will activate at once. In this case, if you are driving up to eight segment anodes at a time, each of these must have a 1k resistor in series to limit the total current sunk in turn by one of the six common cathodes as they are alternately selected, to 20 mA.

Lots of luck!

Your question (a).

To calculate the minimum series resistor, you need to know the forward voltage of the led segment, the maximum forward current of the segment, the supply voltage and the maximum supply current.

If you are lighting a single segment with a single Arduino Uno pin, then the supply voltage would be 5V and max supply current would be 40mA in theory, but 30mA for long term use. Let's say the forward voltage of the segment is 3V and the maximum current is 20mA. 20mA is less than 30mA, so 20mA is the maximum current we want to flow through the segment and series resistor. The segment will drop 3V so the series resistor will drop the other 2V. Using Ohm's law, R=V/I=2/0.020=100R.

However! If you light multiple segments at once, that may mean an Arduino pin must source or sink the current for several segments at the same time. For example a single Arduino pin might have to sink the current for a whole digit with 8 segments lit the same time. In this case, the maximum supply current has to be shared by 8 segments, so it's only 30mA/8=~4mA per segment. This is important to consider. If you forget this and exceed the maximum current of an Arduino pin, it will not self-limit the current to protect itself, it will be damaged.

a) around 330 Ohm for the red, 470for the green, and 470 for the blue LED. But if you start with much higher values, it will not make any damage.

b) do you really want to multiplex it manually? why not use a dedicated chip like a HT16K33 or an MAX7219? It might get somehow tricky to work out which column is which digit in which color, but in the end the IC will care about all the multiplexing. If you just want to lit the LED either r, g or b and no really color mixing this might be a easiest option.

we are not allowed to use any arduino functions whatsoever; so that means the use of anything from the functions section on the resources page

If I were you, I would attempt to get around that rule like this: first write your code using the standard Arduino functions like pinMode(), digitalWrite(), analogWrite(), delay(), millis() etc. Once you have it working, then go find the source code for those functions from the repositories, copy them into your code and change the names slightly ;)

You need to multiplex between the digits, if you are only going to use one color you can do with a 2 phase multiplexing, for all colors you need a 6 phase multiplexing.

The way to do the multiplexing is to make a ram buffer (2 or 6 bytes) and use a interrupt routine to: 1) Turn of voltage to common pin (4, 7, 8, 10, 11, 14) 2) Copy one byte from the ram to the 8 output bits that is connected to 1, 2, 3, 5, 6, 9, 12, 13 3) Turn on voltage to on common pin (4, 7, 8, 10, 11, 14) depending on the actual ram location 4) Change to next byte in ram buffer and loop when the end is reached.

This routine will have to run a couple 100 times each second with stable timing (The display will flicker if the timing is unstable).

There has to be resistors between the processor and the 1, 2, 3, 5, 6, 9, 12, 13 pins.

Now you can just place the segment values in the ram buffer and it will display.

hi there everyone; thanks for all your help!

i did set this up to email me with responses but well i got no response, i was playing around with it while i was waiting for responses and found some interesting things out; the only two that like to play together are red on the first one and green on the other one; not sure why but none of the others seem to work,

now then when i was initially using it i am gonna be honest i thought i had too!! i plugged it all in and saw a blinding light then poof!!! it was in that moment i realised i forgot the limiting resistors; i rewired as such and it still seemed to work; the only miracle was that i wired it incorrectly; i read “cathode” and thought “positive” i have later learn otherwise when it comes to leds (probs knew it but slipped my mind) so it was fine.

anyway i got it multiplexing and working using the normal arduino code to begin with and after doing some research i can say for certain i have done overkill on the resistors; only ones i had lying around were 10ks so i used them thinking they were 1210 ohm resistors. all in all here is the look of the code in arduino stanard for the number 12 should give a idea of what i’m working with

const int PINS[10] = {2, 3, 4, 5, 6, 7, 8, 9, 22, 23};
void setup() {
  // put your setup code here, to run once:
  pinMode(PINS[0], OUTPUT);
  pinMode(PINS[1], OUTPUT);
  pinMode(PINS[2], OUTPUT);
  pinMode(PINS[3], OUTPUT);
  pinMode(PINS[4], OUTPUT);
  pinMode(PINS[5], OUTPUT);
  pinMode(PINS[6], OUTPUT);
  pinMode(PINS[7], OUTPUT);
  pinMode(PINS[8], OUTPUT);
  pinMode(PINS[9], OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  //print 12
  digitalWrite(PINS[0], LOW);
  digitalWrite(PINS[1], HIGH);
  digitalWrite(PINS[2], HIGH);
  digitalWrite(PINS[3], LOW);
  digitalWrite(PINS[4], LOW);
  digitalWrite(PINS[5], LOW);
  digitalWrite(PINS[6], LOW);
  digitalWrite(PINS[7], LOW);
  digitalWrite(PINS[8], LOW);
  delay(1);
  digitalWrite(PINS[0], LOW);
  digitalWrite(PINS[1], LOW);
  digitalWrite(PINS[2], LOW);
  digitalWrite(PINS[3], LOW);
  digitalWrite(PINS[4], LOW);
  digitalWrite(PINS[5], LOW);
  digitalWrite(PINS[6], LOW);
  digitalWrite(PINS[7], LOW);
  digitalWrite(PINS[8], HIGH);
  digitalWrite(PINS[9], HIGH);
  delay(1);
  digitalWrite(PINS[0], HIGH);
  digitalWrite(PINS[1], HIGH);
  digitalWrite(PINS[2], LOW);
  digitalWrite(PINS[3], HIGH);
  digitalWrite(PINS[4], HIGH);
  digitalWrite(PINS[5], LOW);
  digitalWrite(PINS[6], HIGH);
  digitalWrite(PINS[7], LOW);
  digitalWrite(PINS[9], LOW);
  delay(1);
  digitalWrite(PINS[0], LOW);
  digitalWrite(PINS[1], LOW);
  digitalWrite(PINS[2], LOW);
  digitalWrite(PINS[3], LOW);
  digitalWrite(PINS[4], LOW);
  digitalWrite(PINS[5], LOW);
  digitalWrite(PINS[6], LOW);
  digitalWrite(PINS[7], LOW);
  digitalWrite(PINS[8], HIGH);
  digitalWrite(PINS[9], HIGH);
  delay(1);
}

i know it seems all long winded and stuff but believe me i think this will work. if i’m thinking right the 10k limiting resistors would more than cover the system for current right? if so i’ll leave it as is and call this a case closed, thanks again to everyone tried to help!!

noiasca: a) around 330 Ohm for the red, 220 for the green, and 220 for the blue LED.

Did you read the data sheet that the OP attached? The max forward currents were, to me, surprisingly low. I think your suggested resistor values may damage the display (if the OP hasn't already damaged it). I would suggest 330R for red but 470R for green & blue. However, those values will make it impossible to get something close to white, so increase red series resistors to 680R.

i'll leave it as is and call this a case closed

but...

use of anything from the functions section on the resources page is completely prohibited and we get 0 marks

with that code, you are likely to get expelled!

PaulRB: but...with that code, you are likely to get expelled!

in its current state yes but i ws more referring to using the 10k resistors; i'm trying to jump through all sorts of rings to figure out how to port forward correctly rn tbh

Tragical:
in its current state yes but i ws more referring to using the 10k resistors; i’m trying to jump through all sorts of rings to figure out how to port forward correctly rn tbh

If you want to see something about setting up interrupt and scanning display, you can check my library the HC595 part. It streams the bit serially to an external driver, you have to replace that with parallel output to your display as I wrote before.

PaulRB: I would suggest 330R for red but 470R for green & blue. However, those values will make it impossible to get something close to white, so increase red series resistors to 680R.

If you use that single resistor for each colour, then the brightness will vary with how many segments are lit - unless you multiplex one segment at a time. :astonished:

Is that what you are suggesting? :roll_eyes:

I was talking about the value of the series resistors, rather than the number and placement of them. But it’s a pertinent question. From the data sheet:

The series resistors will have to go on the cathode side, because different values for red, green and blue are needed, and because one resistor for each parallel led is needed.

It is a interesting display to control, you could scan segments instead of digits, the it would be perfectly fine with the resistor in the DIG wires.

The maximum continuous forward current of the segments is low: 5mA for green & blue, 10mA for red but for balance limit that to 5mA also. Peak current is 3 times that, but no limit on the pulse length is given, or the pulse frequency.

A per-segment strategy would work, I guess, but that would mean a 1:8 duty cycle, which would limit the maximum brightness. A per-digit strategy would mean 1:2 duty cycle, but as Paul__B pointed out, it would cause inconsistent brightness depending on the number of segments lit.

PaulRB: A per-digit strategy would mean 1:2 duty cycle

Not if you want to use all the segments, then it is 1:6 and that is not that different from 1:8.

Your project is simply impossible. If you use Arduino, or any C coded device, you have to une some functions, because everything that do something in C is a function in a specific library, so don't put your time in the rubbish like this

Silente:
Your project is simply impossible. If you use Arduino, or any C coded device, you have to une some functions, because everything that do something in C is a function in a specific library, so don’t put your time in the rubbish like this

hey there mate they were more less talking about digitalwrite and other arduino unique functions, i think i can get away with loop and setup as i can see it is used by the teacher themself so i am gonna do it like that, anyway here is the updated code and i can say i have hit a roadblock; not too sure why it isn’t working, can someone see my mistake in here at all?

void setup() {
  // put your setup code here, to run once:
  DDRA &= ((1 << DDA0) /*pin 22*/ | (1 << DDA1) /*pin 23*/);
  PORTA &= ((1 << PA0) /*pin 22*/ | (1 << PA1) /*pin 23*/);
  DDRE &= ((1 << DDE3) /*pin 5*/ | (1 << DDE4) /*pin 2*/ | (1 << DDE5) /*pin 3*/);
  PORTE |= ~((1 << PE3) /*pin 5*/ | (1 << PE4) /*pin 2*/ | (1 << PE5) /*pin 3*/);
  DDRG &= (1 << DDG5); /*pin 4*/
  PORTG |= ~(1 << PG5); /*pin 4*/
  DDRH &= ((1 << DDH3) /*pin 6*/ | (1 << DDH4) /*pin 7*/ | (1 << DDH5) /*pin 8*/ | (1 << DDH6) /*pin 9*/);
  PORTH |= ~((1 << PH3) /*pin 6*/ | (1 << PH4) /*pin 7*/ | (1 << PH5) /*pin 8*/ | (1 << PH6) /*pin 9*/);
}

void loop() {
  // put your main code here, to run repeatedly:
  PORTE &= ~((1 << PE4) | (1 << PE5));
  PORTG &= ~(1 << PG5);
  PORTH &= ~((1 << PH3) | (1 << PH4) | (1 << PH5) | (1 << PH6));
  PORTA &= ~(1 << PA0);
  _delay_ms(10);
  PORTE &= ~((1 << PE4) | (1 << PE5));
  PORTG &= ~(1 << PG5);
  PORTH &= ~((1 << PH3) | (1 << PH4) | (1 << PH5) | (1 << PH6));
  PORTA &= ~((1 << PA0) | (1 << PA1));
  _delay_ms(10);
  PORTE &= (~(1 << PE4) | (1 << PE5));
  PORTG |= (1 << PG5);
  PORTH &= ~((1 << PH3) | (1 << PH4) | (1 << PH5) | (1 << PH6));
  PORTA &= ~(1 << PA1);
  _delay_ms(10);
  PORTE &= ~((1 << PE4) | (1 << PE5));
  PORTG &= ~(1 << PG5);
  PORTH &= ~((1 << PH3) | (1 << PH4) | (1 << PH5) | (1 << PH6));
  PORTA &= ~((1 << PA0) | (1 << PA1));
  _delay_ms(10);
//one();
}
void zero() {
  
}
void one() {
  PORTE |= ~((1 << PE4) | (1 << PE5));
  PORTG |= ~(1 << PG5);
  PORTH |= ~((1 << PH3) | (1 << PH4) | (1 << PH5) | (1 << PH6));
  PORTA |= ~(1 << PA0);
  _delay_ms(10);
  PORTE |= ~((1 << PE4) | (1 << PE5));
  PORTG |= ~(1 << PG5);
  PORTH |= ~((1 << PH3) | (1 << PH4) | (1 << PH5) | (1 << PH6));
  PORTA |= ~((1 << PA0) | (1 << PA1));
  _delay_ms(10);
  PORTE |= (~(1 << PE4) | (1 << PE5));
  PORTG |= (1 << PG5);
  PORTH |= ~((1 << PH3) | (1 << PH4) | (1 << PH5) | (1 << PH6));
  PORTA |= ~(1 << PA1);
  _delay_ms(10);
  PORTE |= ~((1 << PE4) | (1 << PE5));
  PORTG |= ~(1 << PG5);
  PORTH |= ~((1 << PH3) | (1 << PH4) | (1 << PH5) | (1 << PH6));
  PORTA |= ~((1 << PA0) | (1 << PA1));
  _delay_ms(10);
}
void two() {

}
void three() {

}
void four() {

}
void five() {

}
void six() {

}
void seven() {

}
void eight() {

}
void nine() {

}

i was trying to get it working in a function so i could simply call it when i needed it instead of some stupid switch statement or a if else chain etc. but it isn’t working, i went back to the digitalwrite version again and that worked just fine so it ain’t the led so can anyone care to see where i went wrong and explain it to me? oh and if you are wondering i moved the code to the loop after the facct to check to see if it was just being special in the function or if it wasn’t worked which it turned out to be the latter.

if it helps its supposed to be displaying the number one in thjs case so i’m not too sure what has gone wrong.

EDIT: i figured it out; it ain’t pretty but the masks were not working so i went directly to binary instead and its working now (thank chirst) here is the working code now;

void setup() {
  // put your setup code here, to run once:
  DDRA |= ((1 << DDA0) /*pin 22*/ | (1 << DDA1) /*pin 23*/);
  //PORTA &= ((1 << PA0) /*pin 22*/ | (1 << PA1) /*pin 23*/);
  DDRE |= ((1 << DDE3) /*pin 5*/ | (1 << DDE4) /*pin 2*/ | (1 << DDE5) /*pin 3*/);
  //PORTE |= ~((1 << PE3) /*pin 5*/ | (1 << PE4) /*pin 2*/ | (1 << PE5) /*pin 3*/);
  DDRG |= (1 << DDG5); /*pin 4*/
  //PORTG |= ~(1 << PG5); /*pin 4*/
  DDRH |= ((1 << DDH3) /*pin 6*/ | (1 << DDH4) /*pin 7*/ | (1 << DDH5) /*pin 8*/ | (1 << DDH6) /*pin 9*/);
  //PORTH |= ~((1 << PH3) /*pin 6*/ | (1 << PH4) /*pin 7*/ | (1 << PH5) /*pin 8*/ | (1 << PH6) /*pin 9*/);
}

void loop() {
  // put your main code here, to run repeatedly:
  /**/
one();
}
void zero() {
  
}
void one() {
  PORTE = B00000000;
  PORTG = B00000000;
  PORTH = B00000000;
  PORTA = B00000011;
  _delay_ms(1);
  PORTE = B00000000;
  PORTG = B00000000;
  PORTH = B00000000;
  PORTA = B00000011;
  _delay_ms(1);
  PORTE = B00100000;
  PORTG = B00100000;
  PORTH = B00000000;
  PORTA = B00000001;
  _delay_ms(1);
  PORTE = B00000000;
  PORTG = B00000000;
  PORTH = B00000000;
  PORTA = B00000000;;
  _delay_ms(1);
}
void two() {

}
void three() {

}
void four() {

}
void five() {

}
void six() {

}
void seven() {

}
void eight() {

}
void nine() {

}

Tragical: i think i can get away with loop and setup as i can see it is used by the teacher themself so i am gonna do it like that

Looks like they are just playing games with you then.

Lots of luck! :grinning: