Two 7-segment displays crammed into my tiny breadb

Greetings all!

I've had my Arduino for about three weeks now and I've got a couple of projects going. One is trying to make a basic synth, the other is a digital thermometer using a OneWire thermometer, a HD44780 compatible display and a switchbutton. Displaying the current temperature, and pressing the button gives me highest, once more gives me the lowest, and again returns to current temperature. High/lows are stored in EEPROM so they are not reset when power is removed.

Anyhow, I had two 7-segment displays lying around and once I realised I would only need two transistors to make them both work at the same time I decided to try them out after stealing the transistors from an old velleman kit.

This isn't really the greatest achievement in the world, but I am a little proud of cramming it all onto my 170-hole small breadboard. I am ordering a bigger one, but for now it's what I have.

On another note, is there any library made for controlling one or more 7-segs? I made a couple of functions that made this quite easy, I will improve on them, to make them even better. (I'll post the code once I've cleaned it up).

Some photos and a video:

Imgur
Imgur
Imgur
The 7 Segment display works | Just to show that I did some c… | Flickr (video)

I have to say that is some very good breadboarding.

and if you have some good functions lying around, why not compile them into a nice seven segment library for yourself? Try making a setup function that allows the user to input the amount of display they're using. Read this if you need help: http://www.arduino.cc/en/Hacking/LibraryTutorial

This would be nice to see and use!

Ben

very nice work. How is it wired? Where do the transistors fit in and how come no current limiting resistors?

I ask because I was struggling with a 7 segment display recently.

PA Skins: I will look into that, a library would be nice.

bill2009: I will post a diagram of the wiring soon. The transistors are there to switch between the two displays, so if you only have one digit you won't need them.

-- EDIT

Actually, I think me drawing up the breadboard schemiatics in fritzing will just be a little overdoing things. This is the page with the information that enabled me to get things working and find out what to connect where.

Hopefully you have a larger breadboard?

-- done edit

The reason I don't have any resistors is actually because I have no clue wich to use, and I'm not running it for short periods at a time.

http://www.electrokit.se/download/kt10562.pdf

This is all the info I have on my displays, if anyone has info on what resistors to use please let me know.

Maybe I was being too fussy with all my resistors. This diagram certainly doesn't have any. I think if you were running it for any length of time you would need something. The value is dependant on the current rating of the leds. I was using 100 ohms to provide 30ma.

Resistors would be a good idea for this project, especially if left on for more than a few minutes. They can also help to make LEDs look better, as too much current can lead to washed-out brightness (especially in red LEDs).

If you really wanted to save space, one big current limiting resistor on the source from the transistor would do a trick.

Isn't it also good practice to put a resistor on the input of a transistor too? To stop over-powering it?

Ben

Always fit resistors in series with LEDs! I'm amazed at how often people just leave them out and hope they can get away with it. If you don't fit resistors, you will damage or destroy eirther the Arduino or the LED displays. Remember that as soon as one LED in a seven-segment display fails, the whole display is useless. As for resistor values, a typical value for a single LED on 5 Volts is between 150 and 330 Ohms.

A single resistor would cause large variations in current (and hence brightness) as the number of lit segments changes (digit 1 would be very bright; digit 8 would be dim). Always use one resistor per segment, and one for the decimal point. Some larger LED displays have two LEDs in series for the segments, and one for the decimal point; these displays require two different resistor values.

And yes, there should be a resistor in series with the base of the transistor, too, from about 470 Ohms to maybe 1k Ohms. Stricktly speaking, the circuit shown is an emitter follower (load is is the emitter circuit), whereas the usual arrangement is to put the load in the collector circuit. In this case, with common-anode displays, you'd need a PNP transistor.

Anachrocomputer:

I know this very well, and not knowing wich to use a poor excuse to not use any. So thank for the info on 150-330 Ohms. I am absolutely new in this area, all I have is programming experience and a small hobby electronics class back in school, where all I learned was to solder.

As I stated, I can't find any info on what exact amount of milliamps the leds on these 7-segments are rated for. I am right in my assumption that if I use 330 Ohm resistors I would at least be on the safer side then using 150 Ohm?

I am using two BC547 NPN transistors (not really sure if it's these exact ones, but they are BC547, so I am hoping it's sort of standard?) ON Semiconductor 128424, DS datasheet pdf Sending signals to the base pin, 5volts to the collector pin and the emitter sends power to the leds. Am I correct in understanding that I should place a resistor between the output on the arduino and the base pin, bringing the mA down to 40?

On a general note, I have started working on making a library, however I am having trouble with the tutorial linked above, but I will bring that up in the appropreate forum section.

One way to know that you’re putting too much current through a red LED is that it will appear orange or some other color rather than red.

When using 7-segment displays with the arduino, I make it a habit to use common - cathode devices because well the code makes more sense to me that way. Also using some sort of driver IC or transistor array is important rather than driving directly with the arduino. So far I’ve only used numbers (I made a temperature sensor with an LM34) so I used an IC I remember from high school, the 74LS48. It takes a BCD number (only valid from 0 - 9, 10-15 is gibberish since it’s not a hexadecimal driver) and converts it to the 7 signals needed to drive a display. Its a TTL device, so it is fairly resilient. This way you can drive two displays with 8 bits of data byeither using pins directly on the arduino or by using 3 pins and one 8-bit serial-in parallel-out shift register.

There are much better ways of driving displays, but its a good basic method if all you’re doing is controlling a couple things (with the remaining pins) and reading temperature. 3 displays are needed for a more useful temperature sensor, but requires 12 pins, basically all of your digital pins.

Oh and if you’ve got a 1k potentiometer hanging around, I might put a 150 ohm in series with it for adjustable brightness.

Also, I hadn’t seen the picture with the displays on at first. You will definitely burn those displays out very quickly.

I’d be interested to know how you are only using 5 pins for each display.

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1235965293
might learn something from that, I didn’t use a resistor there because of the driver IC, but I added a pot later.

I am right in my assumption that if I use 330 Ohm resistors I would at least be on the safer side then using 150 Ohm?

Yes, using 330 Ohms will be safest, although most LEDs are OK with anything from 10 to 20 mA of current.

Am I correct in understanding that I should place a resistor between the output on the arduino and the base pin

Yes, anything from 470 Ohms to 1000 Ohms, it's not critical. Using an NPN transistor such as the BC547 will work OK in this circuit, becase it's all at 5 Volts. People sometimes get into a muddle when trying to switch, say, 12 Volts with an emitter-follower (which doesn't work when driven from 5V logic).

Thanks for the reply Anachrocomputer. I've put in resistors where needed, and it even makes the display more easier on the eye :slight_smile:

Scott S:

I'm using the same 8 pins for both displays, alternating them on and off with the transistors.

I'll post the code I'm using along with the library I just finished writing up later on tonight, just have to tidy things a bit. It doesn't support common cathode right now since I have no way of testing it, but in reality that would be just a couple of minor edits.

Thanks again for your comments and replies, I said I’d put up the library on saturday, but I got a little distracted. But here we are.

I’ve uploaded a zip-file with the library, including keywords and an example - http://blogspatter.com/arduino/SevenSegment-0.1.zip

This is the code for my counter, using my new SevenSegment library

#include <SevenSegment.h>

#define SWITCH1 3
#define SWITCH2 4

SevenSegment display(9, 6, 5, 10, 11, 12, 7, 8); // setting up the 7-segment class

// for the counter
long time;
int countDelay = 1000;
int count = 0;

void setup() {
  pinMode(SWITCH1, OUTPUT); // transistor 1
  pinMode(SWITCH2, OUTPUT); // transistor 2
  digitalWrite(SWITCH1, LOW); // turning them low so the display is off when starting
  digitalWrite(SWITCH2, LOW);
}

void loop() {
  display.clear();

  digitalWrite(SWITCH1, HIGH); // turning on LCD 1
  digitalWrite(SWITCH2, LOW); // turning off LCD 2
  
  if (count < 10) {
    display.write(count);
  } else {
    display.write(count % 10);
  }
    
  display.clear();
  
  digitalWrite(SWITCH2, HIGH); TURNING ON LCD 2
  digitalWrite(SWITCH1, LOW); TURNING OFF LCD 1

  if (count < 10) {
    display.write(0);
  } else {
    display.write(count / 10);
  }
  
  if (millis() - time > countDelay) {
    count++;
    time = millis();
  }
  if (count > 99) {
    count = 0;
  }
}

I just noted that I am might be turning things on and off in a slightly strange manner, which may give one really quick blink of a digit on the wrong display, I’ll have to look into that :slight_smile:

This is the library, for those who just want to look and not download:
SevenSegment.cpp

/*
  SevenSegment.cpp - 7-Segment Library
  Copyright (C) 2009 stian Hole.  All rights reserved.
 
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  See file LICENSE.txt for further informations on licensing terms.
*/

#include "SevenSegment.h"

SevenSegment::SevenSegment(int dot, int a, int b, int c, int d, int e, int f, int g)
{
  pinMode(dot, OUTPUT);
  pinMode(a, OUTPUT);
  pinMode(b, OUTPUT);
  pinMode(c, OUTPUT);
  pinMode(d, OUTPUT);
  pinMode(e, OUTPUT);
  pinMode(f, OUTPUT);
  pinMode(g, OUTPUT);
  
  _dot = dot;
  _a = a;
  _b = b;
  _c = c;
  _d = d;
  _e = e;
  _f = f;
  _g = g;
  
  _on = LOW;
  _off = HIGH;
}

void SevenSegment::clear()
{
  digitalWrite(_dot, _off);
  digitalWrite(_a, _off);
  digitalWrite(_b, _off);
  digitalWrite(_c, _off);
  digitalWrite(_d, _off);
  digitalWrite(_e, _off);
  digitalWrite(_f, _off);
  digitalWrite(_g, _off);
}

void SevenSegment::write(int val)
{
  if (val == 2 || val == 3 || val == 4 || val == 5 || val == 6 || val == 8 || val == 9) {
    digitalWrite(_g, _on);
  }
  if (val == 0 || val == 4 || val == 5 || val == 6 || val == 8 || val == 9) {
    digitalWrite(_f, _on);
  }
  if (val == 0 || val == 2 || val == 6 || val == 8) {
    digitalWrite(_e, _on);
  }
  if (val == 0 || val == 2 || val == 3 || val == 5 || val == 6 || val == 8) {
    digitalWrite(_d, _on);
  }
  if (val != 2) {
    digitalWrite(_c, _on);
  }
  if (val == 0 || val == 1 || val == 2 || val == 3 || val == 4 || val == 7 || val == 8 || val == 9) {
    digitalWrite(_b, _on);
  }
  if (val == 0 || val == 2 || val == 3 || val == 5 || val == 6 || val == 7 || val == 8 || val == 9) {
    digitalWrite(_a, _on);
  }
}

SevenSegment.h

/*
  SevenSegment.cpp - 7-Segment Library
  Copyright (C) 2009 stian Hole.  All rights reserved.
 
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  See file LICENSE.txt for further informations on licensing terms.
*/

#ifndef SevenSegment_h
#define SevenSegment_h

#include "WProgram.h"

class SevenSegment
{
  public:
    SevenSegment(int dot, int a, int b, int c, int d, int e, int f, int g);
    void clear();
    void write(int);
  private:
    int _dot;
    int _a;
    int _b;
    int _c;
    int _d;
    int _e;
    int _f;
    int _g;
    int _on;
    int _off;
};

#endif

I haven’t put it up on the playground yet, I might have done everything horribly wrong, and I think maybe I’ll be needing to do some added changes. It does not have functionality for more then one digit, which one would have to mange like I’ve done it, and it does also not support common cathode.

I notice that your code never switches a segment off, but presumably relies on the user caling "clear()" before displaying a digit. If you add a bunch of "else digitalWrite(_b, _off);"-type statements in your "write" member function, then you won't need to call "clear" first.

Very true, thanks for pointing that out. I am also thinking that if the digit it beeing asked to write is the same as the one currently beeing displayed, then there is not reason to go through the ifs turning them on, a waste of precious CPU time.

Another thing is common cathode, would I be correct in thinking that for the actual displays the signals just needs to be reversed? So _on is HIGH instead of LOW? If so, it would be rather trivial to add a boolean value for the class, so one can specify common anode or common cathode, and have it set the _on/_off values appropriatly.

By the way, you can do both digitalWrite(x, HIGH) and digitalWrite(x, LOW) in one statement.

Instead of:

if (val == 2 || val == 3 || val == 4 || val == 5 || val == 6 || val == 8 || val == 9) {
    digitalWrite(_g, _on)
}

Do this:

digitalWrite(_g, [glow](val == 2 || val == 3 || val == 4 || val == 5 || val == 6 || val == 8 || val == 9)[/glow]);

You can also reduce that expression:

digitalWrite(_g, [glow](val != 0 && val != 1 && val != 7)[/glow]);

For common cathodes, your idea of flipping _on and _off values will work. However, you can also just put a ! before the expression:

digitalWrite(_g, [glow]![/glow](val != 0 && val != 1 && val != 7));

I have better solution hov drive display. You ought to use PNP transistor BC 556B. Emitter to +5V, and collector to anode (3) of display, base through 10k ohm you can drive by LOW on P3.0 (P3.1) which open transistor and release current through the LED. You ought to use minimum 220 ohm rezistor (330 ohm may be better for Arduino) to lower LEDs current.