LDR with 7 seg display and PWM output

PaulRB:
No, I think that’s the DS for the 8000 round leds you bought from China, not the 0.5" 4-digit display…

Oops, I’m so sorry. I’ll attach the link to the 7 segment display in this reply.

sa05-11ewa_7segment_display_common_anode.pdf (226 KB)

Hi.

I'm wondering if someone can still answer my question above - I think it may have got lost in the thread.

There is a specification sheet attached in the note above for common cathode 7 segment digits I'm experimenting with. I'm trying to multiplex 4 digits and attain near max (safe) brightness. The spec sheets says the digits can go to 160mA max at 1/10 duty cycle and 0.1ms pulse width. I'm trying to convert this to my 4 digits (hence 1/4 duty cycle).

As each digit can be 20mA max, then to get this cycling 4 digits it should be around 4 x 20mA = 80mA (I think).

Interpolating the spec sheet figures, would this be the equivalent then of 80mA peak at 1/4 duty cycle and 0.08ms pulse width?

If so, how do you do a delay of 0.08ms. Does this mean I have to do delays between each common 80uS?

Can someone please answer this …

I’ve done a bit more reading of related threads and still haven’t resolved my dilemma, so I’ve tried to do this graphically.

Can someone please tell me if my thinking is correct for working out max intensity I can push a 7 segment display based on peak forward current, duty cycle and pulse width (also refer attached specification sheet for this display). I’m really stuck…

sa05-11ewa_7segment_display_common_anode.pdf (226 KB)

cjcj:
No one’s answering me :’( …

In my experience of this forum, the most likely reason is that no-one here knows.

cjcj:
Can someone please tell me if my thinking is correct for working out max intensity I can push a 7 segment display based on peak forward current, duty cycle and pulse width (also refer attached specification sheet for this display). I’m really stuck…

I’m not sure you are even asking the right question.

I would phrase the question like this:

“We know the max continuous current is 30mA.
We know the max current is 160mA with pulse width 0.1ms and 1/10 duty cycle
What is the max current at pulse width 2ms and 1/4 duty cycle?”

And one answer you might get from the forum would be “if maximum brightness is really so important, don’t multiplex”.

I think its all to do with heat dissipation. The higher the current, the faster you are heating the leds. The temperature they reach depends on the length of the pulse, what temperature they were at the start of the pulse, and how fast they loose heat during the pulse. The temperature at the start of the pulse depends on what rate they cool. The rate at which they cool depends on the temperature at any instant. Its all horribly complicated.

But every time the led heats up and cools again, it looses a tiny part of its life. The hotter it gets, the larger that part of life is lost.

My advice would be that if you are building something for you own use, you can afford to push the limits. If you are designing something to be mass-manufactured and sold, you have to be much more conservative if you can’t get a definitive answer to your question.

If it were me, I would go to maybe double the max continuous current with a 2ms pulse and 1/4 duty cycle, and be prepared for the possible consequences, but take comfort in the knowledge that the manufacturer’s data sheet figures will be conservative.

If you exceed this on-time and current Peak Forward Current [1] 160 mA 1. 1/10 Duty Cycle, 0.1ms Pulse Width.

you will burn the parts out. If you want 20mA all the time, use daisy chained, high current shift registers, TPIC6C595 or TPIC6B595. Can then use them for higher voltage (multiple LEDS/segment) with a larger display as well.

Also makes the coding easier - just shift out 4 bytes whenever you need the display updated. I'd use SPI for that:

// time for a display update?
digitalWrite (latchPin, LOW); // RCLK from SS on pin 10
for (x=0; x<4; x=x+1){
SPI.transfer(displayData[x]); // data from MOSI pin 11, SRCLK from SCK on pin 13
}
digitalWrite (latchPin, HIGH); // SS on pin 10

If you are sending font characters, can pull data from a look up table

// time for a display update?
digitalWrite (latchPin, LOW); // RCLK from SS on pin 10
for (x=0; x<4; x=x+1){
SPI.transfer(fontArray[displayData[x]]); // data from MOSI pin 11, SRCLK from SCK on pin 13
}
digitalWrite (latchPin, HIGH); // SS on pin 10
byte fontArray[] = {
0b00111111, // 0, with 1 = segment on, DP-g-f-e-d-c-b-a
0b00000110, // 1        a
0b01011011, // 2    f        b
0b01001111, // 3        g
:                            e        c
:                                d         dp
0b01101111, // 9
0b01110111, // A
: // etc.
};

This may be of interest, although it doesn't really answer my version of your question.

Paul, thanks for re-wording my question- yes it wasn't clear.

Your absolutely right about that if I want bright, consider not multiplexing. Originally I just used a heap of outputs, but then I learnt about multiplexing, so that seemed to work well for saving pins. However the compromise is dimmer display. You have a valid point that if I want the digits to last, the lower the current the better. This is therefore more academic exercise. I'll do some experimenting.

Your link to bryanduxbury yes is relevant and I already read it last week. This is what I'm trying and I think I have enough info to experiment.

Crossroads, I do agree that the way forward on my ultimate project is with shift registers for the reasons both you and Paul outlined.

I will soon need some help with my 24v common anode digits and driving them with shift registers (and MOSFETS). I might start up another thread when I'm up to that. Thanks guys. :)

cjcj: 24v common anode digits and driving them with shift registers (and MOSFETS)

Before you purchase components, work out the current the digits will draw. The tpic6*595 shift registers have built-in mosfets, so as long as the current is within their capability, you can keep the circuit really simple. Wiring lots of leds in series with 24V supply should help keep the current down.

tpic6c595: 100mA per segment tpic6b595: 150mA per segment tpic6595: 250mA per segment tpic6a595: 350mA per segment

Note: these chips can only sink this current, they cannot source any current.

Thanks Paul. Yes, I definately will check currents before hand. You did mention earlier also about using the tpic6c595 high-current shift registers. In - built mosfets - excellent. Before I order anything, I'll run through the specs with you if that's ok.

Right now I'm just experimenting with multiplexing single LEDs, checking strobing and currents. I'm finding it just flickers at 50Hz, but stops at 60. So I assume 100Hz would be safe. I read somewhere that it should be 1000Hz

I've attached a sheet that I drew up earlier outlining how my 24V 7 segment displays are setup along with current draw, etc. From your notes above, I assume I will use tpic6b595's? I would assume then that I'd be using 2 of these per 4 digits. (ultimately I have 15 digits - timer, clock, home score, away score and temperature).

cjcj: I've attached a sheet that I drew up earlier outlining how my 24V 7 segment displays are setup along with current draw, etc. From your notes above, I assume I will use tpic6b595's? I would assume then that I'd be using 2 of these per 4 digits. (ultimately I have 15 digits - timer, clock, home score, away score and temperature).

You forgot the attachment!

If not multiplexing you will need one shift register per digit. If multiplexing, one for every 2, 4 or perhaps even 8 digits, but you know the penalty for doing that. Also if multiplexing, you will need some high-side p-channel mosfets with high-current capacity, along with something to drive the mosfets (e.g Arduino pins + pnp transistors, or an extra tpic chip).

Bob (CrossRoads) is the real expert in these chips. He may even have a suitable product you could use.

I have a board that has a '328P set up like an Uno, with offboard USB/Serial adapter, and 12 shift registers for driving large high voltage displays based on LED strips with built-in current limit resistors. Could be expanded to 15 digits and add in current limit resistors for 7-segment displays. http://www.crossroadsfencing.com/BobuinoRev17/ |500x455

Sorry about attachment. I’ve added it here. Please do take a look at it.

I took a quick look at the chip (aaaatpic6b595) before - I think I had multiplexing on the brain, hence I assumed it was for 2 digits. Yes, 8 drains, so 1 digit. I’ll new quite a few of these, but if it saves a stack of MOSFETs, it’ll be worth it.

I’d be happy for Bobs help with these chips.

_16_inch digit schematic.pdf (60.9 KB)

Yes, TPIC6B595 can handle these currents: Segments A, D & G = 7 x 8 (rows) of LEDs = 8x15 = 120mA each Segments B, C, E & F = 7 x 7 (rows) of LEDs = 105mA each

Need one shift register per digit.

15 digits, daisy chain them all and send out 15 bytes when an update is needed. I often use a data array to hold the value, 0 to 9, for each digit, and a font look up array to map the value to the needed segments.

byte dataArray[15]; // 15 bytes holding 0-9 for each digit, time, score, period, whatever

byte fontArray[] = {
0b00111111, // 0, with  DP-g-f-e-d-c-b-a, 1 = segment on
0b00000110, // 1       a
etc.                        f       b
0b01101111, // 9       g
};                          e      c
                                 d     DP

// time for an update?
digitlalWrite (ssPin, LOW); // D10 to RCLK pin, D11 to Ser data, D13 to SRCLK
for (x=0; x<15; x=x+1){
SPI.transfer (fontArray[dataArray[x]]);
}
digitlalWrite (ssPin, HIGH);  // outputs updated on this rising edge
// MRCLR tied High, OE/ tied Low, or to a PWM pin for brightness control

Thanks for that info Bob and I like the look of your board - I’ll aim to make mine similar. I’m feeling more confident now and getting excited for my build! I’ve found the following:

  • 15 x TPIC6B595N from RS components @ $2.30 (AU) each - LINK_1 - assuming “N” is appropriate???
  • 15 x 20 way IC DIP sockets @ $1.75 (AU) each - LINK - I assume these are suitable too?
  • Headers and decoupling capacitors - I have some already
  • Printed circuit board - time to start drawing, printing, then get out the wife’s iron again!

Sorry but I now have a few more questions if I can:

  • I have 5 functions to run - a 2 digits home score, 2 digit away score, 4 digit count down timer (MM:SS), clock (HH:MM) and temperature. Should I run each of these with a separate Arduino board. I think I need 45 pins for data,latch and clock, plus I’ll need some for operations such as reset scores, advance time, start timer, etc, etc
  • If I write separate code for each of the 5 functions above (work in progress), and maybe your suggestion is to use less boards (such as 2 x Mega), then is it possible (or even advisable) to merge the code?
  • Similar to your board above however, I too would love to “build” the arduino setup as well - not that I know how to do that yet. Your suggestion?
  • On my current setup, I’m using a 12 channel remote control to operate the board LINK. Could I instead build something similar using arduino?
  • I also assume on my board I’ll have to build a 5V supply (with a voltage regulator). Again is this advisable, or a completely separate supply
  • Lastly, with the PICs, can I still control “dimming” of all displays via an LDR still? I was originally doing this with a PWM output on the board

Sorry for the zillion questions, but I’m just learning and this is a big challenge for me.

TPIC6B595N.pdf (485 KB)

20 way IC Dip socket.pdf (469 KB)

One Arduino will be fine - Uno/Nano/Pro Mini as you like. You will only need 3 pins to run all 15 shift registers.

If you want to "roll you own" arduino, you could use an atmega328 and regulator circuit. But a Nano for example comes with built-in usb for easy re-programming and a regulator to provide it with 5V (just be careful not to use much current from the 5V supply, or the built-in regulator could overheat, given the 24V input voltage).

You can buy very cheap ir remotes and sensor kits for Arduino on eBay. Also you can find ds3231 rtc modules which have a built-in temperature sensor.

ir remote kit

rtc with temperature sensor

For dimming, you can use an ldr connected to an analog input, and connect an Arduino pwm output to the "OE" pins on the shift registers.

cjcj, your first 2 links won't open for me. You can do all 15 digits in one sketch. Standalono arduino is simple - you can see the parts: 16 MHz crystal, 22pF caps, 0.1uF cap, 10K resistor. I add ICSP header for bootloading as an Uno, or for Upload Using Programmer after bootloading (bootloading also sets fuses); add FTDI header if you want serial access for debugging (recommended!) and serial downloading after bootloading.

Can read relay closures the same as button presses:

pinMode (pinX, INPUT_PULLUP);

if (digitalRead(pinX) == LOW){
// relay closure connects pin to Gnd
// advance a score or something
}

5V supply - how much current is expected? Maybe 5V linear regulator (78005 type), maybe 5V switching regulator from a higher input voltage source, such as http://www.digikey.com/product-detail/en/OKI-78SR-5%2F1.5-W36-C/811-2196-5-ND/2259781

Use PWM to control brightness, determine value from 255 (full dim) to 0 (full bright) however you'd like, as PaulRB indicated.

Bob, I've tried to fix the first link with a "longer" web address, but couldn't change the 2nd. Plan B - I've attached a PDF of them both.

Once I've done the code for the 5 functions, I will therefore try to combine them.

Paul - 3 pins to run all 15 registers - thats fantastic, I had no idea I could. Not sure how to do that yet, but I'll start by taking small steps. I know that the arduino is all setup with the 5V supply, USB, etc as you say, but I am "tempted" to consider creating that circuitry as well in my board (as Bob suggested). But again, that will come later.

I did buy an RF trasmitter / receiver module earlier this year to experiment with (link here), but your link with keypad is brilliant.

I also did buy the DS3231 AT24C32 clock (link here). Just received a battery for it last week, but haven't tried it yet. I did however write code in a sketch to run my clock - and I was so proud of doing it. Is it better I use this module? Isn't that sort of cheating and relying on pre made components! And I didn't know it did temperature too - excellent - another bit of research for me / homework.

Dimming - OE pins - also excellent. This is all sounding so promising. Chris.

$2.30 per part - you guys down under get hosed on prices. Same for me is $1.74 http://www.digikey.com/product-search/en?pv69=80&k=tpic6b595&mnonly=0&newproducts=0&ColumnSort=0&page=1&quantity=0&ptm=0&fid=0&pageSize=25

3 pins to run all 15 registers - thats fantastic, I had no idea I could. Not sure how to do that yet,

Did you look at the code I posted in #32?

CrossRoads: Did you look at the code I posted in #32?

I did read it, however I assumed that each register "linked" but needed at least 3 to 4 wires each. As for the code, I'm not too hot at the moment reading code. I loosely understand what you've written in principle, however I have to actually write this up and apply it in context to fully understand it. I'll order the shift registers, mock up 15 small led displays with it, then write the code to learn how to do it.

Below for instance is an example of the code I've written for a MM:SS timer. You'll look at it and think it's quite long winded. But self taught, so far it's the best I can do.

/* COMMON ANODE TIMER (with start, pause and reset):
   This Arduino code drives 4 separate 7 segment common ANODE LED displays
   Via a pushbutton switch, it starts a timer display from 00:00
   (mm:ss) to 59:59.  The button also pauses the timer.
   Holding the button in for greater than 2 seconds resets
   There is a built-in debounce to limit bouncing of pulses via the pushbutton.
   Includes an LDR to control the intensity of the digits
   Create by Chris in Feb 2015
*/

//--------------------------------------------------------------------------------------------

int A = 1;                   // Set to 0 (LOW) for common cathode.  Set to 1 for common anode digits
int B = 0;                   // Set to 1 (HIGH) for common cathode.  Set to 0 for common anode digits
int ldrIn = 14;              // Analog input pin A0.  Attach to first leg of LDR and 10K to GND
int aValue = 0;               // A variable used in controlling the light intensity value
int dValue = 0;               // A variable used in controlling the light intensity value

int buttonChange = 15;       // Analog in pin (A1) used to pause, restart and reset timer
                             // Other end of led to GND via a 10K resistor
int state = LOW;             // The current state of the output pin
int reading;                 // The current reading of the input pin
int previous = HIGH;         // The previous reading from the input pin
int check = 0;               // Used to pause the clock when the button is preassed - whilst reset
int delayMp = 2;             // Used to delay the muliplexing
int sec_ones = 0;            // Used to indicate what number the digit is set to
int sec_tens = 0;            // Used to increment the tens unit
int min_ones = 0;            // Used to increment the min_ones units
int min_tens = 0;            // Used to increment the min_tens units
long time1 = 0;              // Used in delaying for debouncing of pushbutton
long time2 = 0;              // Used in delaying the increment clock time
long secondMicro = 996000;   // One second increment clock time
long debounce = 500;         // Debounce time - longer than usual so it works for me
unsigned long currentMillis = 0;  //
unsigned long previousMillis = 0; //
int stepMultiplex = 1;       // Variable used to step through each segment
int reset = 2000;            // Duration required for button press to reset time
int firstTime = 1;           // Used in recording button press duration
unsigned long startTime = 0; // Used in recording button press duration
unsigned long pressTime = 0; // Used in recording button press duration


// the following array is used to define each led common
byte commons [4] = {6,9,10,11};   // pins to each digit common (these are PWM outputs)

// the following array is used to define each led segment for number 0 to 9
byte sevenSegmentPin[7] = {2,3,4,5,7,8,12};
byte sevenSegment[10][7] = {
  {B,B,B,B,B,B,A},    // this is 0
  {A,B,B,A,A,A,A},    // this is 1
  {B,B,A,B,B,A,B},    // this is 2
  {B,B,B,B,A,A,B},    // this is 3
  {A,B,B,A,A,B,B},    // this is 4
  {B,A,B,B,A,B,B},    // this is 5
  {B,A,B,B,B,B,B},    // this is 6
  {B,B,B,A,A,A,A},    // this is 7
  {B,B,B,B,B,B,B},    // this is 8
  {B,B,B,A,A,B,B},    // this is 9
};  


void setup()  //--------------------------------------------------
{
  Serial.begin(9600);
  for (byte i=0; i<7; i++)
  pinMode(sevenSegmentPin[i],OUTPUT); // this sets pins 2,3,4,5,6,8 and 12 as outputs

  for(byte i=0; i<4; i++)
  pinMode(commons[i], OUTPUT);         // this sets pins 6,9, 10 and 11 as outputs

  for (byte i=0; i<7; i++) {
    digitalWrite(sevenSegmentPin[i], sevenSegment[0][i]); // this sets pins 2,3,4,5,6 and 8 as 0
  }
}

// This is code for displaying the incremental digit for the "sec_ones"
void sevenSegWrite_1(byte sec_ones) {
  for (byte i=0; i<7; i++) {
    digitalWrite(sevenSegmentPin[i], sevenSegment[sec_ones][i]);
  }
}

// This is code for displaying the incremental digit for the "sec_tens"
void sevenSegWrite_2(byte sec_tens) {
  for (byte i=0; i<7; i++) {
    digitalWrite(sevenSegmentPin[i], sevenSegment[sec_tens][i]);
  }
}

// This is code for displaying the incremental digit for the "min_ones"
void sevenSegWrite_3(byte min_ones) {
  for (byte i=0; i<7; i++) {
    digitalWrite(sevenSegmentPin[i], sevenSegment[min_ones][i]);
  }
}

// This is code for displaying the incremental digit for the "min_tens"
void sevenSegWrite_4(byte min_tens) {
  for (byte i=0; i<7; i++) {
    digitalWrite(sevenSegmentPin[i], sevenSegment[min_tens][i]);
  }
}


void loop()  //--------------------------------------------------
{
  aValue = analogRead(ldrIn);              // Read the LDR analogue value on analog pin and
                                          // store the value between 0 and 1023
//  Serial.print("0l to 1023 value = ");
//  Serial.println(aValue);
  aValue = constrain (aValue, 20, 300);   // Constrain the value between 900 and 1010
  dValue = map (aValue, 20, 300, 0, 255); // The digital pin outputs values from 0 to 255
                                          // so convert the value received in the above line
  
  reading = digitalRead(buttonChange); // Check the state of the button
  currentMillis = millis();            // Set variable for multiplexing timing

  
// Used to toggle starting and pausing the clock...

if (reading == HIGH && previous == LOW && millis() - time1 > debounce) {
    if (state == HIGH) {
      state = LOW;
      time1 = millis ();
    }
    else {
      state = HIGH;
      time1 = millis();
    }
  }
  previous = reading;


// Used to check if the button is pressed long enough to reset the time

 if (reading == HIGH) {
   if (firstTime == 1) {
     startTime = millis();
     firstTime = 0;
   }
   pressTime = millis () - startTime;
 }
 else if (firstTime == 0) {
   firstTime = 1;
 }

 if (pressTime > 2000) {
    state = LOW;
    sec_ones=0;
    sec_tens=0;
    min_ones=0;
    min_tens=0;
    time1 = 0;
 }

//-------------------------------------------------------------------

  if(stepMultiplex == 1 && (currentMillis - previousMillis) >= delayMp) {
    digitalWrite(commons [0],B);  // Turn off the previous digit once time expires
    previousMillis=currentMillis;
    sevenSegWrite_1(sec_ones);
    analogWrite(commons [3],dValue);  // Turn on the sec_one digit
    stepMultiplex=2;
  }
  
  if(stepMultiplex == 2 && (currentMillis - previousMillis) >= delayMp) {
    digitalWrite(commons [3],B);  // Turn off the previous digit once time expires
    previousMillis=currentMillis;
    sevenSegWrite_2(sec_tens);
    analogWrite(commons [2],dValue);  // Turn on the sec_tens digit
    stepMultiplex=3;
  }
   
  if(stepMultiplex == 3 && (currentMillis - previousMillis) >= delayMp) {
    digitalWrite(commons [2],B);  // Turn off the previous digit once time expires
    previousMillis=currentMillis;
    sevenSegWrite_3(min_ones);
    analogWrite(commons [1],dValue);  // Turn on the min_one digit
    stepMultiplex=4;
  }

  if(stepMultiplex == 4 && (currentMillis - previousMillis) >= delayMp) {
    digitalWrite(commons [1],B);  // Turn off the previous digit once time expires
    previousMillis=currentMillis;
    sevenSegWrite_4(min_tens);
    analogWrite(commons [0],dValue);  // Turn on the min_tens digit
    stepMultiplex=1;
  }

//  The next few lines are used to advance the clock
  
  if (micros() - time2 > secondMicro && state == HIGH) {
    check=1;                            //this is used to pause the clock while the button is pressed
    if (check == 1 & reading == LOW) {
      sec_ones++;
      check=0;
    }
    
    if(sec_ones >9) {
      sec_ones=0;
      sec_tens++;
    }
    
    if(sec_tens>5) {
      sec_tens=0;
      min_ones++;
    }
    
    if(min_ones>9) {
      min_ones=0;
      min_tens++;
    }
    
    if(min_tens>5) {
      sec_ones=0;
      sec_tens=0;
      min_ones=0;
      min_tens=0;
    }
    time2 = micros();
  }
}

cjcj: I also did buy the DS3231 AT24C32 clock... I did however write code in a sketch to run my clock - and I was so proud of doing it. Is it better I use this module? Isn't that sort of cheating and relying on pre made components!

Why get a dog and bark yourself? The RTC module has several important advantages over using the Arduino as a clock. It will be much more accurate over long term, Arduino will probably loose/gain several mintues per day, vs several minutes per year with ds3231. RTC has battery back-up, so doesn't need re-setting every time Arduino is powered up/reset.

cjcj: I'll order the shift registers, mock up 15 small led displays with it, then write the code to learn how to do it.

Make sure to buy common-anode individual/single-digit 7-seg displays for your mock-up. You won't be able to use multi-digit displays without multiplexing them, and that wouldn't be an accurate mock-up of your final curcuit.

cjcj: Below for instance is an example of the code I've written for a MM:SS timer. You'll look at it and think it's quite long winded. But self taught, so far it's the best I can do.

Its good that you are practising your coding skills, but little of that code will be suitable for your project. You won't be multiplexing, you will be using shift registers and an RTC connected to the i2c bus. For now, better to spend your time getting the code for that RTC module working. Just send the output to serial monitor for now.