t r o n i x s t u f f

fun and learning with electronics

The MAX7219 LED display controller – real or fake?

Introduction

If you’re experimenting with various Arduino or other projects and working with LED matrices or lots of LEDs – you may have come across the Maxim MAX7219 “Serially Interfaced, 8-Digit, LED Display Driver” IC. It’s a great part that can drive an 8 x 8 LED matrix or eight digits of seven-segment LED displays very easily. However over the last few years the price has shot up considerably. Supply and demand doing their thing – and for a while there was also the Austria Microsystems AS1107 drop-in replacement, which could be had for a few dollars less. But no more.

So where does the budget-minded person go from here? Charlieplexing? Lots of shift registers? Or dig a little deeper to find some cheaper units. With a MAX7219 heading north of US$10 in single units, they may turn to ebay or other grey-market suppliers in the Far East. Everyone likes to save money – and who can blame them? However with the proliferation of counterfeiting, “third shift” operations and other shifty practices – is buying those cheaper examples worth it?

A few people have been asking me of late, and there’s only one way to find out … so over the last month I ordered eight random “MAX7219s” from different suppliers on ebay and will compare them to the real thing using somewhat unscientific methods, then see how they work. The funny thing was that after five weeks only six of the eight arrived – so there’s risk number one: if it doesn’t come from a reputable supplier, it might not come at all. Funny stuff. Anyhow, let’s get started by looking at the differences between the real MAX7219 and the others.

[Update 17/5/2013 - Thanks for reading this article. Have had some interesting feedback both pro-Maxim, pro-China and anti-me. (Hater's gonna hate). I'm out of town for a few days but will return next week and do some more testing and hopefully have some feedback coming from Maxim as well.]

Pricing differences

The easiest hint is the price. The non-originals are always cheaper. And if you wonder how much the real ones are in bulk, the quickest indicator is to check the Maxim website and that of a few larger distributors  For example the Maxim “sticker price” for 1000 units is US$4.18 each:

maxpricing

How much at Digikey? Lots of 500 for US$4.67 each:

digikey

And you wouldn’t buy just one from element14 at this price:

aue14pricing

However in fairness to element14 they will price match if you’re buying in volume. So if you can get a “MAX7219″ delivered for US$1.50 – there’s something wrong. Moving on, let’s examine some of those cheap ones in more detail.

Visual differences

If you’ve never seen a real MAX7219 – here it is, top and bottom:

realtopss

realbottomss

And here’s our rogue’s gallery of test subjects:

testsubjectsss

In a few seconds the differences should be blindingly obvious – look at the positioning of the printed bar across the part, the printing of the logo, and the general quality and positioning of the printing. Next, those circles embedded in the top of the body at both ends of the part, and the semi-circle at the top end. And if you turn them over, there’s nothing on the bottom. Furthermore, there isn’t a divot indicating pin 1 on the fakes, as shown on the real part:

divot

Oh – did you notice the legs on the real one? Look closely again at the image above, then consider the legs on the others below:

fakelegsss

Finally, the non-originals are shorter. The Maxim width can fall between 28.96 and 32.13 mm – with our original test MAX7219 being 32 mm:

realwidthss

and all the test subjects are narrower, around 29.7 mm:

fakewidthss

Fascinating. Finally, I found the quality of the metal used for the legs to be worse than the original, they were easier to bend and had trouble going into an IC socket. You can find all the physical dimensions and other notes in the data sheet available from the Maxim website. Finally, this packaging made me laugh – knock-offs in knock-off tubes? (Maxim purchased Dallas Semiconductor a while ago)

faketubingss

Weight difference

Considering that they’re shorter, they must weigh less. In the following video I put the original on the scales, tare it to zero then place each test subject – you can see the difference in weigh. The scales are out a bit however the differences are still obvious:

However over time the manufacturers may go to the effort of making copies that match the weight, size and printing – so future copies may be much better. However you can still fall back to the price to determine a copy.

Do they actually work? 

After all that researching and measuring – did they work? One of the subjects came with a small LED matrix breakout board kit:

matrixassembledss

… so I used that with a simple Arduino sketch that turned on each matrix LED one at a time, then went through the PWM levels – then left them all on at maximum brightness.

#include "LedControl.h"
LedControl lc=LedControl(12,11,10,1); // data, clock, load, 1 MAX7219
void setup() 
{
 lc.shutdown(0,false);
 lc.setIntensity(0,15);
 lc.clearDisplay(0);
}
void single() {
 for(int row=0;row<8;row++) {
 for(int col=0;col<8;col++) {
 delay(25);
 lc.setLed(0,row,col,true);
 delay(25);
 for(int i=0;i
void loop() 
{ 
 single();
 for (int n=0; n<5; n++)
 {
 for (int z=0; z<16; z++)
 {
 lc.setIntensity(0,z);
 delay(100);
 }
 for (int z=15; z>-1; --z)
 {
 lc.setIntensity(0,z);
 delay(100);
 }
 }
 lc.setIntensity(0,15);
 do { }  while(1);
}

Here’s the real MAX7219 running through the test:

And test subjects one through to six running it as well:

Well that was disheartening. I was hoping and preparing for some blue smoke, dodgy displays or other faults. However the little buggers all worked, didn’t overheat or play up at all.

Conclusion

Six random samples from ebay – and they all worked. However your experience may vary wildly. Does this tell us that copies are OK to use? From my own personal opinion – you do what you have to do with respect to your own work and that for others. In other words – if you’re making something for someone, whether it be a gift or a commercial product, or something you will rely on – use the real thing. You can’t risk a fault in those situations.  If you’re just experimenting, not in a hurry, or just don’t have the money – try the cheap option. But be prepared for the worst – and know you’re supporting an industry that ethically shouldn’t exist.

I’m sure everyone will have an opinion on this, so let us know about it in the moderated comments section below.  And if you made it this far – check out my new book “Arduino Workshop” from No Starch Press.

In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column? And join our friendly Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

May 16, 2013 Posted by | arduino, as1107, COM-09622, counterfeit, max7219, maxim, part review, product review, supplier review, tronixstuff, Uncategorized | , , , , , , , , , , , , , , , | 17 Comments

Tutorial – Arduino and MC14489 LED Display Driver

Learn how to use MC14489 LED display driver ICs with Arduino in chapter fifty-one of a series originally titled “Getting Started/Moving Forward with Arduino!” by John Boxall – A tutorial on the Arduino universe. The first chapter is here, the complete series is detailed here.

Updated 12/05/2013

Introduction

Recently we’ve been looking at alternatives to the MAX7219 LED display driver IC due to pricing and availability issues (stay tuned for that one) – and came across an old but still quite useful IC – the MC14489 from Motorola (now Freescale Semiconductor). The MC14489 can drive five seven-segment LED numbers with decimal point, or a combination of numbers and separate LEDs. You can also daisy-chain more than one to drive more digits, and it’s controlled with a simple serial data-clock method in the same way as a 74HC595 shift register. Sourcing the MC14489 isn’t too difficult – it’s available from element14, Newark, Digikey, and so on – or if you’re not in a hurry, try the usual suspects like Futurlec.

For the purpose of the tutorial we’ll show you how to send commands easily from your Arduino or compatible board to control a five-digit 7-segment LED display module - and the instructions are quite simple so they should translate easily to other platforms. Once you have mastered the single module, using more than one MC14489 will be just as easy. So let’s get started.

Hardware

Before moving forward, download the data sheet (pdf). You will need to refer to this as you build the circuit(s). And here’s our subject in real life:

mc14489

For our demonstration display we’ll be using a vintage HP 5082-7415 LED display module. However you can use almost any 7-segment modules as long as they’re common-cathode - for example, Sparkfun part number COM-11405. If you’re using a four-digit module and want an extra digit, you can add another single digit display. If you want a ruler, the design files are here.

Connecting the MC14489 to an LED display isn’t complex at all. From the data sheet consider Figure 9 (click the image to enlarge):

schematic

Each of the anode control pins from the MC14489 connect to the matching anodes on your display module, and the BANK1~5 pins connect to the matching digit cathode pins on the display module. You can find the MC14489 pin assignments on page 1 of the data sheet. Seeing as this is chapter fifty-one  - by now you should be confident with finding such information on the data sheets, so I will be encouraging you to do a little more of the work.

Interesting point – you don’t need current-limiting resistors. However you do need the resistor Rx – this controls the current flow to each LED segment. But which value to use? You need to find out the forward current of your LED display (for example 20 mA) then check Figure 7 on page 7 of the data sheet (click image to enlarge):

currentgraph

To be conservative I’m using a value of 2k0 for Rx, however you can choose your own based on the data sheet for your display and the graph above.  Next – connect the data, clock and enable pins of the MC14489 to three Arduino digital pints – for our example we’re using 5, 6 and 7 for data, clock and enable respectively. Then it’s just 5V and GND to Arduino 5V and GND – and put a 0.1uF capacitor between 5V and GND. Before moving on double-check the connections – especially between the MC14489 and the LED display.

Controlling the MC14489

To control the display we need to send data to two registers in the MC14489 – the configuration register  (one byte) and the display register (three bytes). See page 9 of the data sheet for the overview. The MC14489 will understand that if we send out one byte of data it is to send it the configuration register, and if it receives three bytes of data to send it to the display register. To keep things simple we’ll only worry about the first bit (C0) in the configuration register – this turns the display outputs on or off. To do this, use the following:

 digitalWrite(enable, LOW);
 shiftOut(data, clock, MSBFIRST, B00000001); // used binary for clarity, however you can use decimal or hexadecimal numbers
 digitalWrite(enable, HIGH);
 delay(10);

and to turn it off, send bit C0 as zero. The small delay is necessary after each command.

Once you have turned the display on – the next step is to send three bytes of data which represent the numbers to display and decimal points if necessary. Review the table on page 8 of the data sheet. See how they have the binary nibble values for the digits in the third column. Thankfully the nibble for each digit is the binary value for that digit. Furthermore you might want to set the decimal point – that is set using three bits in the first nibble of the three bytes (go back to page 9 and see the display register). Finally you can halve the brightness by setting the very first bit to zero (or one for full brightness).

As an example for that – if you want to display 5.4321 the three bytes of data to send in binary will be:

1101 0101 0100 0011 0010 0001

Let’s break that down. The first bit is 1 for full brightness, then the next three bits (101) turn on the decimal point for BANK5 (the left-most digit). Then you have five nibbles of data, one for each of the digits from left to right. So there’s binary for 5, then four, then three, then two, then one.

 digitalWrite(enable, LOW); 
 shiftOut(data, clock, MSBFIRST, B11010101); // D23~D16 
 shiftOut(data, clock, MSBFIRST, B01000011); // D15~D8
 shiftOut(data, clock, MSBFIRST, B00100001); // D7~D0
 digitalWrite(enable, HIGH);
 delay(10);

To demonstrate everything described so far, it’s been neatly packaged into our first example sketch – Example 51.1:

// Example 51.1
// Motorola MC14489 with HP 5082-7415 5-digit, 7-segment LED display
// 2k0 resistor on MC14489 Rx pin
// John Boxall 2013 CC by-sa-nc
// define pins for data from Arduino to MC14489
// we treat it just like a 74HC595
int data = 5;
int clock = 6;
int enable = 7;
void setup()
{
 pinMode(data, OUTPUT);
 pinMode(enable, OUTPUT);
 pinMode(clock, OUTPUT);
 displayOn(); // display defaults to off at power-up
}
void displayTest1()
// displays 5.4321
{
 digitalWrite(enable, LOW); // send 3 bytes to display register. See data sheet page 9
 // you can also insert decimal or hexadecimal numbers in place of the binary numbers
 // we're using binary as you can easily match the nibbles (4-bits) against the table
 // in data sheet page 8
 shiftOut(data, clock, MSBFIRST, B11010101); // D23~D16 
 shiftOut(data, clock, MSBFIRST, B01000011); // D15~D8
 shiftOut(data, clock, MSBFIRST, B00100001); // D7~D0
 digitalWrite(enable, HIGH);
 delay(10);
}
void displayTest2()
// displays ABCDE
{
 digitalWrite(enable, LOW); // send 3 bytes to display register. See data sheet page 9
 // you can also insert decimal or hexadecimal numbers in place of the binary numbers
 // we're using binary as you can easily match the nibbles (4-bits) against the table
 // in data sheet page 8
 shiftOut(data, clock, MSBFIRST, B10001010); // D23~D16 
 shiftOut(data, clock, MSBFIRST, B10111100); // D15~D8
 shiftOut(data, clock, MSBFIRST, B11011110); // D7~D0
 digitalWrite(enable, HIGH);
 delay(10);
}
void displayOn()
// turns on display
{
 digitalWrite(enable, LOW);
 shiftOut(data, clock, MSBFIRST, B00000001);
 digitalWrite(enable, HIGH);
 delay(10);
}
void displayOff()
// turns off display
{
 digitalWrite(enable, LOW);
 shiftOut(data, clock, MSBFIRST, B00000000);
 digitalWrite(enable, HIGH);
 delay(10);
}
void loop()
{
 displayOn();
 displayTest1();
 delay(1000);
 displayTest2();
 delay(1000);
 displayOff();
 delay(500);
}

… with the results in the following video:


Now that we can display numbers and a few letters with binary, life would be easier if there was a way to take a number and just send it to the display.

So consider the following function that takes an integer between 0 and 99999, does the work and sends it to the display:

void displayIntLong(long x)
// takes a long between 0~99999 and sends it to the MC14489
{
 int numbers[5];
 byte a=0; 
 byte b=0; 
 byte c=0; // will hold the three bytes to send to the MC14489 

 // first split the incoming long into five separate digits
 numbers[0] = int ( x / 10000 ); // left-most digit (will be BANK5)
 x = x % 10000; 
 numbers[1] = int ( x / 1000 );
 x = x % 1000; 
 numbers[2] = int ( x / 100 );
 x = x % 100; 
 numbers[3] = int ( x / 10 );
 x = x % 10; 
 numbers[4] = x % 10; // right-most digit (will be BANK1)

 // now to create the three bytes to send to the MC14489
 // build byte c which holds digits 4 and 5
 c = numbers[3];
 c = c << 4; // move the nibble to the left
 c = c | numbers[4];
 // build byte b which holds digits 3 and 4
 b = numbers [1];
 b = b << 4;
 b = b | numbers[2];
 // build byte a which holds the brightness bit, decimal points and digit 1
 a = B10000000 | numbers[0]; // full brightness, no decimal points

 // now send the bytes to the MC14489
 digitalWrite(enable, LOW);
 shiftOut(data, clock, MSBFIRST, a);
 shiftOut(data, clock, MSBFIRST, b);
 shiftOut(data, clock, MSBFIRST, c); 
 digitalWrite(enable, HIGH);
 delay(10); 
}

So how does that work? First it splits the 5-digit number into separate digits and stores them in the array numbers[]. It then places the fourth digit into a byte, then moves the data four bits to the left – then we bitwise OR the fifth digit into the same byte. This leaves us with a byte of data containing the nibbles for the fourth and fifth digit. The process is repeated for digits 2 and 3. Finally the brightness bit and decimal point bits are assigned to another byte which then has the first digit’s nibble OR’d into it. Which leaves us with bytes a, b and c ready to send to the MC14489. Note that there isn’t any error-checking – however you could add a test to check that the number to be displayed was within the parameter, and if not either switch off the display (see example 51.1) or throw up all the decimal points or … whatever you want.

You can download the demonstration sketch for the function – Example 51.2, and view the results in the following video:

You can also display the letters A to F by sending the values 10 to 15 respectivel to each digit’s nibble. However that would be part of a larger application, which you can (hopefully) by now work out for yourself. Furthermore there’s some other characters that can be displayed – however trying to display the alphabet using 7-segment displays is somewhat passé. Instead, get some 16-segment LED modules or an LCD.

Finally, you can cascade more than one MC14489 to control more digits. Just run a connection from the data out pin on the first MC14889 to the data pin of the second one, and all the clock and enable lines together. Then send out more data – see page 11 of the data sheet. If you’re going to do that in volume other ICs may be a cheaper option and thus lead you back to the MAX7219.

Conclusion

For a chance find the MC14489 is a fun an inexpensive way to drive those LED digit displays. We haven’t covered every single possible option or feature of the part – however you will now have the core knowledge to go further with the MC14489 if you need to move further with it. And if you enjoy my tutorials, or want to introduce someone else to the interesting world of Arduino – check out my new book “Arduino Workshop” from No Starch Press.

In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column? And join our friendly Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

May 12, 2013 Posted by | arduino, COM-11405, freescale, LED, mc14489, motorola, tronixstuff, tutorial, vintage | , , , , , , , , , , , , , , , | 3 Comments

Tutorial – Arduino and ILI9325 colour TFT LCD modules

Learn how to use inexpensive ILI9325 colour TFT LCD modules in chapter fifty of a series originally titled “Getting Started/Moving Forward with Arduino!” by John Boxall – A tutorial on the Arduino universe. The first chapter is here, the complete series is detailed here.

Introduction

Colour TFT LCD modules just keep getting cheaper, so in this tutorial we’ll show you how to get going with some of the most inexpensive modules we could find. The subject of our tutorial is a 2.8″ 240 x 320 TFT module with the ILI9325 LCD controller chip. If you look in ebay this example should appear pretty easily, here’s a photo of the front and back to help identify it:

There is also the line “HY-TFT240_262k HEYAODZ110510″ printed on the back of the module. They should cost less than US$10 plus shipping. Build quality may not be job number one at the factory so order a few, however considering the cost of something similar from other retailers it’s cheap insurance. You’ll also want sixteen male to female jumper wires to connect the module to your Arduino.

Getting started

To make life easier we’ll use an Arduino library “UTFT” written for this and other LCD modules. It has been created by Henning Karlsen and can be downloaded from his website. If you can, send him a donation – this library is well worth it. Once you’ve downloaded and installed the UTFT library, the next step is to wire up the LCD for a test.

Run a jumper from the following LCD module pins to your Arduino Uno (or compatible):

  • DB0 to DB7 > Arduino D0 to D7 respectively
  • RD > 3.3 V
  • RSET > A2
  • CS > A3
  • RW > A4
  • RS > A5
  • backlight 5V > 5V
  • backlight GND > GND

Then upload the following sketch – Example 50.1. You should be presented with the following on your display:

If you’re curious, the LCD module and my Eleven board draws 225 mA of current. If that didn’t work for you, double-check the wiring against the list provided earlier. Now we’ll move forward and learn how to display text and graphics.

Sketch preparation

You will always need the following before void setup():

#include "UTFT.h"
UTFT myGLCD(ILI9325C,19,18,17,16); // for Arduino Uno

and in void setup():

myGLCD.InitLCD(orientation); 
myGLCD.clrScr();

with the former command, change orientation to either LANDSCAPE to PORTRAIT depending on how you’ll view the screen. You may need further commands however these are specific to features that will be described below. The function .clrScr() will clear the screen.

Displaying Text

There are three different fonts available with the library. To use them add the following three lines before void setup():

extern uint8_t SmallFont[];
extern uint8_t BigFont[];
extern uint8_t SevenSegNumFont[];

When displaying text you’ll need to define the foreground and background colours with the following:

myGLCD.setColor(red, green, blue); 
myGLCD.setBackColor(red, green, blue);

Where red, green and blue are values between zero and 255. So if you want white use 255,255,255 etc. For some named colours and their RGB values, click here. To select the required font, use one of the following:

  myGLCD.setFont(SmallFont); // Allows 20 rows of 40 characters
  myGLCD.setFont(BigFont); // Allows 15 rows of 20 characters
  myGLCD.setFont(SevenSegNumFont); // allows display of 0 to 9 over four rows

Now to display the text use the function:

 myGLCD.print("text to display",x, y);

where text is what you’d like to display, x is the horizontal alignment (LEFT, CENTER, RIGHT) or position in pixels from the left-hand side of the screen and y is the starting point of the top-left of the text. For example, to start at the top-left of the display y would be zero. You can also display a string variable instead of text in inverted commas.

You can see all this in action with the following sketch – Example 50.2, which is demonstrated in the following video:

Furthremore, you can also specify the angle of display, which gives a simple way of displaying text on different slopes. Simply add the angle as an extra parameter at the end:

  myGLCD.print(“Hello, world”, 20, 20, angle);

Again, see the following sketch – Example 50.2a, and the results below:

Displaying Numbers

Although you can display numbers with the text functions explained previously, there are two functions specifically for displaying integers and floats.

You can see these functions in action with the following sketch – Example 50.3, with an example of the results below:

example50p3

Displaying Graphics

There’s a few graphic functions that can be used to create required images. The first is:

myGLCD.fillScr(red, green, blue);

which is used the fill the screen with a certain colour. The next simply draws a pixel at a specified x,y location:

myGLCD.drawPixel(x,y);

Remember that the top-left of the screen is 0,0. Moving on, to draw a single line, use:

myGLCD.drawLine(x1,0,x2,239);

where the line starts at x1,y1 and finishes at x2,y2. Need a rectangle? Use:

myGLCD.drawRect(x1,y2,x2,y2); // for open rectangles
myGLCD.fillRect(x1,y2,x2,y2); // for filled rectangles

where the top-left of the rectangle is x1,y1 and the bottom-right is x2, y2. You can also have rectangles with rounded corners, just use:

myGLCD.drawRoundRect(x1,y2,x2,y2); // for open rectangles
myGLCD.fillRoundRect(x1,y2,x2,y2); // for filled rectangles

instead. And finally, circles – which are quite easy. Just use:

myGLCD.drawCircle(x,y,r); // draws open circle
myGLCD.fillCircle(x,y,r); // draws a filled circle

where x,y are the coordinates for the centre of the circle, and r is the radius. For a quick demonstration of all the graphic functions mentioned so far, see Example 50.4 – and the following video:

Displaying bitmap images

If you already have an image in .gif, .jpg or .png format that’s less than 300 KB in size, this can be displayed on the LCD. To do so, the file needs to be converted to an array which is inserted into your sketch. Let’s work with a simple example to explain the process. Below is our example image:

jrt3030

Save the image of the puppy somewhere convenient, then visit this page. Select the downloaded file, and select the .c and Arduino radio buttons, then click “make file”. After a moment or two a new file will start downloading. When it arrives, open it with a text editor – you’ll see it contains a huge array and another #include statement – for example:

cfile

Past the #include statement and the array into your sketch above void setup(). After doing that, don’t be tempted to “autoformat” the sketch in the Arduino IDE. Now you can use the following function to display the bitmap on the LCD:

myGLCD.drawBitmap(x,y,width,height, name, scale);

Where x and y are the top-left coordinates of the image, width and height are the … width and height of the image, and name is the name of the array. Scale is optional – you can double the size of the image with this parameter. For example a value of two will double the size, three triples it – etc. The function uses simple interpolation to enlarge the image, and can be a clever way of displaying larger images without using extra memory. Finally, you can also display the bitmap on an angle – using:

myGLCD.drawBitmap(x,y,width,height, name, angle, cx, cy);

where angle is the angle of rotation and cx/cy are the coordinates for the rotational centre of the image.

The bitmap functions using the example image have been used in the following sketch – Example 50.5, with the results in the following video:

Unfortunately the camera doesn’t really do the screen justice, it looks much better with the naked eye.

Running out of space or I/O? Use an Arduino Mega

By now you may have noticed that the library for the LCDs uses up a fair amount of memory, which could be a problem. And using bitmaps eats up memory as well.  And the I/O requirements are quite heavy. The solution is to use an Arduino Mega or compatible board – as they have up to eight times the sketch memory available. However the wiring is a little different – so when using a Mega, run a jumper from the following LCD module pins to your Mega (or compatible):

  • DB0 to DB7 > Mega D22 to D29 respectively
  • RD > 3.3 V
  • RSET > D41
  • CS > D40
  • RW > D39
  • RS > D38
  • backlight 5V > 5V
  • backlight GND > GND

You will also need to change the line

UTFT myGLCD(ILI9325C,19,18,17,16);  // for Uno

to

UTFT myGLCD(ILI9325C,38,39,40,41);  // for Mega

What about the SD card socket and touch screen?

The SD socket didn’t work, and I won’t be working with the touch screen at this time.

Conclusion

So there you have it – an incredibly inexpensive and possibly useful LCD module. Thank you to Henning Karlsen for his useful library, and if you found it useful – send him a donation via his page.

In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column? And join our friendly Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

April 26, 2013 Posted by | arduino, bitmap, display, ILI9325, LCD, mega, TFT, tronixstuff, tutorial | , , , , , , , , , , , , , , , , , | 20 Comments

Project: Clock Four – Scrolling text clock

Introduction

Time for another instalment in my highly-irregular series of irregular clock projects.  In this we have “Clock Four” – a scrolling text clock. After examining some Freetronics Dot Matrix Displays in the stock, it occurred to me that it would be neat to display the time as it was spoken (or close to it) – and thus this the clock was born. It is a quick project – we give you enough to get going with the hardware and sketch, and then you can take it further to suit your needs.

Hardware

You’ll need three major items – An Arduino Uno-compatible board, a real-time clock circuit or module using either a DS1307 or DS3232 IC, and a Freetronics DMD. You might want an external power supply, but we’ll get to that later on.

The first stage is to fit your real-time clock. If you are unfamiliar with the operation of real-time clock circuits, check out the last section of this tutorial. You can build a RTC circuit onto a protoshield or if you have a Freetronics Eleven, it can all fit in the prototyping space as such:

If you have an RTC module, it will also fit in the same space, then you simply run some wires to the 5V, GND, A4 (for SDA) and A5 (for SCL):

By now I hope you’re thinking “how do you set the time?”. There’s two answers to that question. If you’re using the DS3232 just set it in the sketch (see below) as the accuracy is very good, you only need to upload the sketch with the new time twice a year to cover daylight savings (unless you live in Queensland). Otherwise add a simple user-interface – a couple of buttons could do it, just as we did with Clock Two. Finally you just need to put the hardware on the back of the DMD. There’s plenty of scope to meet your own needs, a simple solution might be to align the control board so you can access the USB socket with ease – and then stick it down with some Sugru:

With regards to powering the clock – you can run ONE DMD from the Arduino, and it runs at a good brightness for indoor use. If you want the DMD to run at full, retina-burning brightness you need to use a separate 5 V 4 A power supply. If you’re using two DMDs – that goes to 8 A, and so on. Simply connect the external power to one DMD’s terminals (connect the second or more DMDs to these terminals):

The Arduino Sketch

You can download the sketch from here. It was written only for Arduino v1.0.1. The sketch has the usual functions to set and retrieve the time from DS1307/3232 real-time clock ICs, and as usual with all our clocks you can enter the time information into the variables in void setup(), then uncomment setDateDs1307(), upload the sketch, re-comment setDateDs1307, then upload the sketch once more. Repeat that process to re-set the time if you didn’t add any hardware-based user interface.

Once the time is retrieved in void loop(), it is passed to the function createTextTime(). This function creates the text string to display by starting with “It’s “, and then determines which words to follow depending on the current time. Finally the function drawText() converts the string holding the text to display into a character variable which can be passed to the DMD.

And here it is in action:

Conclusion

This was a quick project, however I hope you found it either entertaining or useful – and another random type of clock that’s easy to reproduce or modify yourself. We’re already working on another one which is completely different, so stay tuned.

In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column? And join our friendly Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

March 15, 2013 Posted by | arduino, clocks, dmd, ds1307, DS3232, freetronics, learning electronics, microcontrollers, projects, scrolling, time clock, timing, tutorial | , , , , , , , , , , , , , | 2 Comments

Tutorial: Arduino and the MSGEQ7 Spectrum Analyzer

This is a tutorial on using the MSGEQ7 Spectrum Analyser with Arduino, and chapter forty-eight of a series originally titled “Getting Started/Moving Forward with Arduino!” by John Boxall – A tutorial on the Arduino universe. The first chapter is here, the complete series is detailed here.

Updated 30/01/2013

In this article we’re going to explain how to make simple spectrum analysers with an Arduino-style board. (Analyser? Analyzer? Take your pick).

First of all, what is a spectrum analyser? Good question. Do you remember what  this is?

It’s a mixed graphic equaliser/spectrum analyser deck for a hi-fi system. The display in the middle is the spectrum analyser, and roughly-speaking it shows the strength of  different frequencies in the music being listened to – and looked pretty awesome doing it. We can recreate displays similar to this for entertainment and also as a base for creative lighting effects. By working through this tutorial you’ll have the base knowledge to recreate these yourself.

We’ll be using the MSGEQ7 “seven band graphic equaliser IC” from Mixed Signal Integration. Here’s the MSGEQ7 data sheet (.pdf).  This little IC can accept a single audio source, analyse seven frequency bands of the audio, and output a DC representation of each frequency band. This isn’t super-accurate or calibrated in any way, but it works. You can get the IC separately, for example:


and then build your own circuit around it… or like most things in the Arduino world – get a shield. In this case, a derivative of the original Bliptronics shield by Sparkfun. It’s designed to pass through stereo audio via 3.5mm audio sockets and contains two MSGEQ7s, so we can do a stereo analyser:

As usual Sparkfun have saved a few cents by not including the stackable header sockets, so you’ll need to buy and solder those in yourself. There is also space for three header pins for direct audio input (left, right and common), which are useful – so if you can add those as well.

So now you have a shield that’s ready for use. Before moving forward let’s examine how the MSGEQ7 works for us. As mentioned earlier, it analyses seven frequency bands. These are illustrated in the following graph from the data sheet:

It will return the strengths of the audio at seven points – 63 Hz, 160 Hz, 400 Hz, 1 kHz, 2.5 kHz, 6.25 kHz and 16 kHz – and as you can see there is some overlap between the bands. The strength is returned as a DC voltage – which we can then simply measure with the Arduino’s analogue input and create a display of some sort. At this point audio purists, Sheldonites and RF people might get a little cranky, so once again – this is more for visual indication than any sort of calibration device.

However as an 8-pin IC a different approach is required to get the different levels. The IC will sequentially give out the levels for each band on pin 3- e.g. 63 Hz then 160 Hz then 400 Hz then 1 kHz then 2.5 kHz then 6.25 kHz  then 16 kHz then back to 63 Hz and so on. To start this sequence we first reset the IC by pulsing the RESET pin HIGH then low. This tells the IC to start at the first band. Next, we set the STROBE pin to LOW, take the DC reading from pin 3 with analogue input, store the value in a variable (an array), then set the STROBE pin HIGH. We repeat the strobe-measure sequence six more times to get the rest of the data, then RESET the IC and start all over again. For the visual learners consider the diagram below from the data sheet:

To demonstrate this process, consider the function

readMSGEQ7()

in the following example sketch (download):

// Example 48.1 - tronixstuff.com/tutorials > chapter 48 - 30 Jan 2013 
// MSGEQ7 spectrum analyser shield - basic demonstration
int strobe = 4; // strobe pins on digital 4
int res = 5; // reset pins on digital 5
int left[7]; // store band values in these arrays
int right[7];
int band;
void setup()
{
 Serial.begin(115200);
 pinMode(res, OUTPUT); // reset
 pinMode(strobe, OUTPUT); // strobe
 digitalWrite(res,LOW); // reset low
 digitalWrite(strobe,HIGH); //pin 5 is RESET on the shield
}
void readMSGEQ7()
// Function to read 7 band equalizers
{
 digitalWrite(res, HIGH);
 digitalWrite(res, LOW);
 for(band=0; band <7; band++)
 {
 digitalWrite(strobe,LOW); // strobe pin on the shield - kicks the IC up to the next band 
 delayMicroseconds(30); // 
 left[band] = analogRead(0); // store left band reading
 right[band] = analogRead(1); // ... and the right
 digitalWrite(strobe,HIGH); 
 }
}
void loop()
{
 readMSGEQ7();
 // display values of left channel on serial monitor
 for (band = 0; band < 7; band++)
 {
 Serial.print(left[band]);
 Serial.print(" ");
 }
 Serial.println();
// display values of right channel on serial monitor
 for (band = 0; band < 7; band++)
 {
 Serial.print(right[band]);
 Serial.print(" ");
 }
 Serial.println();
}

If you follow through the sketch, you can see that it reads both left- and right-channel values from the two MSGEQ7s on the shield, then stores each value in the arrays left[] and right[]. These values are then sent to the serial monitor for display – for example:

If you have a function generator, connect the output to one of the channels and GND – then adjust the frequency and amplitude to see how the values change. The following video clip is a short demonstration of this – we set the generator to 1 kHz and adjust the amplitude of the signal. To make things easier to read we only measure and display the left channel:


Keep an eye on the fourth column of data – this is the analogRead() value returned by the Arduino when reading the 1khz frequency band. You can also see the affect on the other bands around 1 kHz as we increase and decrease the frequency. However that wasn’t really visually appealing – so now we’ll create a small and large graphical version.

First we’ll use an inexpensive LCD, the I2C model from akafugu reviewed previously. To save repeating myself, also review how to create custom LCD characters from here.

With the LCD with have two rows of sixteen characters. The plan is to use the top row for the levels, the left-channel’s on … the left, and the right on the right. Each character will be a little bar graph for the level. The bottom row can be for a label. We don’t have too many pixels to work with, but it’s a compact example:

We have eight rows for each character, and the results from an analogueRead() fall between 0 and 1023. So that’s 1024 possible values spread over eight sections. Thus each row of pixels in each character will represent 128 “units of analogue read” or around 0.63 V if the Arduino is running from true 5 V (remember your AREF notes?). The sketch will again read the values from the MSGEQ7, feed them into two arrays – then display the required character in each band space  on the LCD.

Here’s the resulting sketch (download):

// Example 48.2 - tronixstuff.com/tutorials > chapter 48 - 30 Jan 2013 
// MSGEQ7 spectrum analyser shield and I2C LCD from akafugu
// for akafugu I2C LCD
#include 
#include "TWILiquidCrystal.h"
LiquidCrystal lcd(50);
// create custom characters for LCD
byte level0[8] = { 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111};
byte level1[8] = { 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111};
byte level2[8] = { 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111};
byte level3[8] = { 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111};
byte level4[8] = { 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};
byte level5[8] = { 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};
byte level6[8] = { 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};
byte level7[8] = { 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};
int strobe = 4; // strobe pins on digital 4
int res = 5; // reset pins on digital 5
int left[7]; // store band values in these arrays
int right[7];
int band;
void setup()
{
 Serial.begin(9600);
 // setup LCD and custom characters
 lcd.begin(16, 2);
 lcd.setContrast(24);
 lcd.clear();
lcd.createChar(0,level0);
 lcd.createChar(1,level1);
 lcd.createChar(2,level2);
 lcd.createChar(3,level3);
 lcd.createChar(4,level4);
 lcd.createChar(5,level5);
 lcd.createChar(6,level6);
 lcd.createChar(7,level7);
 lcd.setCursor(0,1);
 lcd.print("Left");
 lcd.setCursor(11,1);
 lcd.print("Right");
 pinMode(res, OUTPUT); // reset
 pinMode(strobe, OUTPUT); // strobe
 digitalWrite(res,LOW); // reset low
 digitalWrite(strobe,HIGH); //pin 5 is RESET on the shield
}
void readMSGEQ7()
// Function to read 7 band equalizers
{
 digitalWrite(res, HIGH);
 digitalWrite(res, LOW);
 for( band = 0; band < 7; band++ )
 {
 digitalWrite(strobe,LOW); // strobe pin on the shield - kicks the IC up to the next band 
 delayMicroseconds(30); // 
 left[band] = analogRead(0); // store left band reading
 right[band] = analogRead(1); // ... and the right
 digitalWrite(strobe,HIGH); 
 }
}
void loop()
{
 readMSGEQ7();
// display values of left channel on LCD
 for( band = 0; band < 7; band++ )
 {
 lcd.setCursor(band,0);
 if (left[band]>=895) { lcd.write(7); } else
 if (left[band]>=767) { lcd.write(6); } else
 if (left[band]>=639) { lcd.write(5); } else
 if (left[band]>=511) { lcd.write(4); } else
 if (left[band]>=383) { lcd.write(3); } else
 if (left[band]>=255) { lcd.write(2); } else
 if (left[band]>=127) { lcd.write(1); } else
 if (left[band]>=0) { lcd.write(0); }
 }
 // display values of right channel on LCD
 for( band = 0; band < 7; band++ )
 {
 lcd.setCursor(band+9,0);
 if (right[band]>=895) { lcd.write(7); } else
 if (right[band]>=767) { lcd.write(6); } else
 if (right[band]>=639) { lcd.write(5); } else
 if (right[band]>=511) { lcd.write(4); } else
 if (right[band]>=383) { lcd.write(3); } else
 if (right[band]>=255) { lcd.write(2); } else
 if (right[band]>=127) { lcd.write(1); } else
 if (right[band]>=0) { lcd.write(0); }
 }
}

If you’ve been reading through my tutorials there isn’t anything new to worry about. And now for the demo, with sound -

That would look great on the side of a Walkman, however it’s a bit small. Let’s scale it up by using a Freetronics Dot Matrix Display - you may recall these from Clock One. For some background knowledge check the review here.  Don’t forget to use a suitable power supply for the DMD – 5 V at 4 A will do nicely. The DMD contains 16 rows of 32 LEDs. This gives us twice the “resolution” to display each band level if desired. The display style is subjective, so for this example we’ll use a single column of LEDs for each frequency band, with a blank column between each one.

We use a lot of line-drawing statements to display the levels, and clear the DMD after each display. With this and the previous sketches, there could be room for efficiency – however I write these with the beginner in mind. Here’s the sketch (download):

// Example 48.3 - tronixstuff.com/tutorials > chapter 48 - 30 Jan 2013 
// MSGEQ7 spectrum analyser shield with a Freetronics DMD
// for DMD
#include  // for DMD
#include  // SPI.h must be included as DMD is written by SPI (the IDE complains otherwise)
#include  
#include "SystemFont5x7.h" // keep next two lines if you want to add some text
#include "Arial_black_16.h"
DMD dmd(1, 1); // creates instance of DMD to refer to in sketch
void ScanDMD() // necessary interrupt handler for refresh scanning of DMD
{ 
 dmd.scanDisplayBySPI();
}
int strobe = 4; // strobe pins on digital 4
int res = 5; // reset pins on digital 5
int left[7]; // store band values in these arrays
int right[7];
int band;
void setup()
{
 // for DMD
 //initialize TimerOne's interrupt/CPU usage used to scan and refresh the display
 Timer1.initialize( 5000 ); //period in microseconds to call ScanDMD. Anything longer than 5000 (5ms) and you can see flicker.
 Timer1.attachInterrupt( ScanDMD ); //attach the Timer1 interrupt to ScanDMD which goes to dmd.scanDisplayBySPI() 
 dmd.clearScreen( true ); //true is normal (all pixels off), false is negative (all pixels on)

 // for MSGEQ7
 pinMode(res, OUTPUT); // reset
 pinMode(strobe, OUTPUT); // strobe
 digitalWrite(res,LOW); // reset low
 digitalWrite(strobe,HIGH); //pin 5 is RESET on the shield
}
void readMSGEQ7()
// Function to read 7 band equalizers
{
 digitalWrite(res, HIGH);
 digitalWrite(res, LOW);
 for( band = 0; band < 7; band++ )
 {
 digitalWrite(strobe,LOW); // strobe pin on the shield - kicks the IC up to the next band 
 delayMicroseconds(30); // 
 left[band] = analogRead(0); // store left band reading
 right[band] = analogRead(1); // ... and the right
 digitalWrite(strobe,HIGH); 
 }
}
void loop()
{
 int xpos;
 readMSGEQ7();
 dmd.clearScreen( true ); 
 // display values of left channel on DMD
 for( band = 0; band < 7; band++ )
 {
 xpos = (band*2)+1;
 if (left[band]>=895) { dmd.drawLine( xpos, 15, xpos, 1, GRAPHICS_NORMAL ); } else
 if (left[band]>=767) { dmd.drawLine( xpos, 15, xpos, 3, GRAPHICS_NORMAL ); } else
 if (left[band]>=639) { dmd.drawLine( xpos, 15, xpos, 5, GRAPHICS_NORMAL ); } else
 if (left[band]>=511) { dmd.drawLine( xpos, 15, xpos, 7, GRAPHICS_NORMAL ); } else
 if (left[band]>=383) { dmd.drawLine( xpos, 15, xpos, 9, GRAPHICS_NORMAL ); } else
 if (left[band]>=255) { dmd.drawLine( xpos, 15, xpos, 11, GRAPHICS_NORMAL ); } else
 if (left[band]>=127) { dmd.drawLine( xpos, 15, xpos, 13, GRAPHICS_NORMAL ); } else
 if (left[band]>=0) { dmd.drawLine( xpos, 15, xpos, 15, GRAPHICS_NORMAL ); }
 }

 // display values of right channel on DMD
 for( band = 0; band < 7; band++ )
 {
 xpos = (band*2)+18;
 if (right[band]>=895) { dmd.drawLine( xpos, 15, xpos, 1, GRAPHICS_NORMAL ); } else
 if (right[band]>=767) { dmd.drawLine( xpos, 15, xpos, 3, GRAPHICS_NORMAL ); } else
 if (right[band]>=639) { dmd.drawLine( xpos, 15, xpos, 5, GRAPHICS_NORMAL ); } else
 if (right[band]>=511) { dmd.drawLine( xpos, 15, xpos, 7, GRAPHICS_NORMAL ); } else
 if (right[band]>=383) { dmd.drawLine( xpos, 15, xpos, 9, GRAPHICS_NORMAL ); } else
 if (right[band]>=255) { dmd.drawLine( xpos, 15, xpos, 11, GRAPHICS_NORMAL ); } else
 if (right[band]>=127) { dmd.drawLine( xpos, 15, xpos, 13, GRAPHICS_NORMAL ); } else
 if (right[band]>=0) { dmd.drawLine( xpos, 15, xpos, 15, GRAPHICS_NORMAL ); }
 }
}

… and here it is in action:

Conclusion

At this point you have the knowledge to use the MSGEQ7 ICs to create some interesting spectrum analysers for entertainment and visual appeal – now you just choose the type of display enjoy the results.

Have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column, or join our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

January 31, 2013 Posted by | analyser, analyzer, arduino, BLIPTRONICS, com-10468, dev-10306, education, graphic, lesson, MSGEQ7, sparkfun, spectrum, tutorial | , , , , , , , , , , , , , , , , , , , , , , | 7 Comments

Kit Review – akafugu Simpleclock

Introduction

Finally another kit review! Thanks to akafugu in Japan (the people who brought us the Akafuino-X) we have a new clock kit to assemble – the Simpleclock. But first, what is it?

A clock – yes. You can never have too many clocks. Also, a digital thermometer and an alarm clock. It is based on the Atmel ATmega328 and Arduino IDE, with open-source firmware. The real-time clock uses the DS1307 circuit with battery backup that we know and love. This means you can completely modify the clock or concoct a completely different use for your Simpleclock. Countdown timer? There’s an idea…

Furthemore, the display module is their individual I2C-interface TWI Display. Therefore you have a clock as well as some Arduino-based hardware to experiment with later on. However, let’s assemble it first.

Assembly

Putting it all together was quite straight-forward. You can follow the detailed instructions at the akafugu site. All the parts required to make a functional clock as advertised are included with the kit:

Here are the brains of the operation – the pre-programmed microcontroller and the DS1307 real-time clock IC: 

You do receive an IC socket for the MCU, but not for the RTC – however this shouldn’t be an issue – just double-check your soldering and have some confidence. The PCBs are nicely laid out with solder-masking and a clear silk-screen:

The PCB on the left in the images above is for the display module – it runs an ATtiny microcontroller than can be worked with separately. Moving forward, you start with the lowest-profile components including the resistors and capacitors:

Take note of the vice – these are great, and light years ahead of the “helping hands” things you see around the traps. This was a Stanley model from element14. The resistors sit in nicely:

The next step is to put a blob of solder on the solder pad which will be beneath the backup battery holder – this forces contact between the negative side of the coin cell battery and the PCB:

Everything else went smoothly – I did have a small worry about the pin spacing for the USB power socket, however a clean tip and a steady hand solved that problem:

The rest of the clock board is much easier – just follow the instructions, take your time and relax. Soon enough you’ll be finished:

However I did have one “oops” moment – I left the PTC in too tall, so it needed to be bent over a little to give way for the display module when inserted:

The next task is to solder the four digit display to the display PCB – nothing new here:

Which leaves you with the standalone display module:

Using the Simpleclock

The firmware for clock use as described in the product page is already loaded in the MCU, so you can use it without needing and programming time or effort. It is powered via a mini-USB cable which you will need to acquire yourself. Frankly the design should have a DC socket and regulator – perhaps for the second revision :)  With second thought, it’s better running from USB. When I turn on the computer in the morning the Simpleclock beeps and ‘wakes up’. The menu system is simple and setting the time and alarm is deceptively so. Some thought has been put into the user interface so once assembled, you could always give the clock away as a gift without fear of being asked for help. However mine is staying on top of the monitor for the office PC:

And here it is in action on the bench:

If you get the urge to modify and update the code, it is easily done. As the Simpleclock kit is open source, all the data required is available from Akafugu’s github page. Please read the notes and other documentation before updating your clock. The easiest way to physically upload the new code will be with a 5V FTDI to USB adaptor or cable.

Conclusion

The Simpleclock was easy to assemble and works very well. It would make a fun kit for those learning to solder, as they have something that once completed is a reminder of their success and useful in daily life. Apart from using USB for power instead of a DC socket – it’s a great kit and I would recommend it to anyone interested in clocks, enjoys kit assembly, or as a gift to a young one to introduce them to electronics and microcontrollers.

Note – the Simpleclock kit was a promotional consideration from akafugu.jp, however the opinions stated are purely my own.

In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column? And join our friendly Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

June 5, 2012 Posted by | akafugu, arduino, clocks, I2C, kit review | , , , , , , , , , , , , | 2 Comments

April 2012 Competition Results

April is well and truly over so time to announce the results of our April 2012 Competition!

The winner of the First Prize is Michael F from Germany who will receive a new Freetronics DMD – Dot Matrix Display as reviewed recently and used in Clock One:

The DMD consists of 16 rows of 32 LEDs that can run directly from an Arduino-compatible board, or at a much higher brightness using an external power supply. It is simple to program for yet a load of fun to use. Specifications include:

  • 32 x 16 high brightness Red LEDs (512 LEDs total) on a 10mm pitch
  • 5V operation
  • Viewable over 12 metres away
  • Tough plastic frame
  • Controller ICs on board, simple clocked data interface
  • Arduino compatible library, graphics functions and example support
  • Dimensions: 320(W) x 160(H) x 14(D)mm (30mm(D) including rear connectors)

DMDs are also available in blue, as shown below:

The winner of the Second Prize is Hendrik from Germany (!) who will receive one each of the eleven modules from the Freetronics Module/Sensor range, as reviewed recently:

With this range of modules you will be able to sense temperature, humidity, magnetic fields, light and sound pressure levels, sound and shock. Plus light up with the RGB LED, get more I/O with the expansion module, interface with the level shifter board, control high currents with the N-MOSFET, and power the lot with the tiny switch mode power supply. Available from Freetronics or a reseller near you.

For the curious, the questions and answers were:

  1. Name three HP calculators that use LED displays – There are many. Just scroll through the list available here.
  2. What does CPLD stand for? Complex programmable logic device. (Why CPLD? We were going to review some CPLD gear but it didn’t work out)
  3. In which year was Tektronix founded? 1946.
  4. Which company introduced the term “numitron”? RCA.
  5. Which company invented Bluetooth? Ericsson.

Thanks to Freetronics for the prizes!

In the meanwhile, follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column, or join our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

May 14, 2012 Posted by | arduino, competition | , , , , , , , , , , | Leave a Comment

Arduino and FFD51 Incandescent Displays

In this article we examine another style of vintage display technology – the incandescent seven-segment digital display. We are using the FFD51 by the IEE company (data sheet.pdf) – dating back to the early 1970s. Here is a close-up of our example:

You can see the filaments for each of the segments, as well as the small coiled ‘decimal point’ filament at the top-right of the image above.  This model has pins in a typical DIP format, making use in a solderless breadboard or integration into a PCB very simple:

It operates in a similar manner to a normal light bulb – the filaments are in a vacuum, and when a current is applied the filament glows nicely. The benefit of using such as display is their brightness – they could be read in direct sunlight, as well as looking good inside.  At five volts each segment draws around 30mA. For demonstration purposes I have been running them at a lower voltage (3.5~4V), as they are old and I don’t want to accidentally burn out any of the elements. Using these with an Arduino is very easy as they segments can be driven from a 74HC595 shift register using logic from Arduino digital out pins. (If you are unfamiliar with doing so, please read chapters four and five of my tutorial series). For my first round of experimenting, a solderless breadboard was used, along with the usual Freetronics board and some shift register modules:

Although the modules are larger than a DIP 74HC595, I like to use these instead. Once you solder in the header pins they are easier to insert and remove from breadboards, have the pinouts labelled clearly, are almost impossible to physically damage, have a 100nF capacitor for smoothing and a nice blue LED indicating power is applied.

Moving forward – using four shift register modules and displays, a simple four-digit circuit can be created. Note from the datasheet that all the common pins need to be connected together to GND. Otherwise you can just connect the outputs from the shift register (Q0~Q7) directly to the display’s a~dp pins.

Some of you may be thinking “Oh at 30mA a pin, you’re exceeding the limits of the 74HC595!”… well yes, we are. However after several hours they still worked fine and without any heat build-up. However if you displayed all eight segments continuously there may be some issues. So take care. As mentioned earlier we ran the displays at a lower voltage (3.5~4V) and they still displayed nicely. Furthermore at the lower voltage the entire circuit including the Arduino-compatible board used less than 730mA with all segments on –  for example:

 For the non-believers, here is the circuit in action:

Here is the Arduino sketch for the demonstration above (download):

// IED FF1 incandescent display demonstration
// using four displays connected to four 74HC595s
int clockPin = 7;
int latchPin = 8;
int dataPin = 9;
int dd=400;
// array for anodes (to display 0~9)
// the bits represent segments a~dp from left to right
// if you add one to the number (or turn on the last bit) the decimal point turns on
byte numbers[]={
 B11111100, // digit zero
 B01100000,
 B11011010,
 B11110010,
 B01100110,
 B10110110,
 B10111110,
 B11100000,
 B11111110,
 B11110110}; // digit nine
void setup()
{
 pinMode(clockPin, OUTPUT);
 pinMode(latchPin, OUTPUT);
 pinMode(dataPin, OUTPUT);
}
void allOn()
// turns on all segments of all displays. Used for testing
{
 digitalWrite(latchPin, LOW);
 shiftOut(dataPin, clockPin, LSBFIRST, 255); // digit 4 
 shiftOut(dataPin, clockPin, LSBFIRST, 255); // digit 3 
 shiftOut(dataPin, clockPin, LSBFIRST, 255); // digit 2
 shiftOut(dataPin, clockPin, LSBFIRST, 255); // digit 1
 digitalWrite(latchPin, HIGH);
}
void clearDigits()
{
 digitalWrite(latchPin, LOW);
 shiftOut(dataPin, clockPin, LSBFIRST, 0);
 shiftOut(dataPin, clockPin, LSBFIRST, 0); 
 digitalWrite(latchPin, HIGH);
}
void loop()
{ 
 for (int a=0; a<10; a++)
 {
 digitalWrite(latchPin, LOW);
 shiftOut(dataPin, clockPin, LSBFIRST, numbers[a]); // digit 4 (add 1 for decimal point)
 shiftOut(dataPin, clockPin, LSBFIRST, numbers[a]); // digit 3 
 shiftOut(dataPin, clockPin, LSBFIRST, numbers[a]); // digit 2
 shiftOut(dataPin, clockPin, LSBFIRST, numbers[a]); // digit 1
 digitalWrite(latchPin, HIGH);
 delay(dd);
 }
for (int a=0; a<10; a++)
 {
 digitalWrite(latchPin, LOW);
 shiftOut(dataPin, clockPin, LSBFIRST, numbers[a]+1); // digit 4 (add 1 for decimal point)
 shiftOut(dataPin, clockPin, LSBFIRST, numbers[a]+1); // digit 3 
 shiftOut(dataPin, clockPin, LSBFIRST, numbers[a]+1); // digit 2
 shiftOut(dataPin, clockPin, LSBFIRST, numbers[a]+1); // digit 1
 digitalWrite(latchPin, HIGH);
 delay(dd);
 }
}

Now for the prototype of something more useful – another clock. :) Time to once again pull out my Arduino-compatible board with onboard DS1307 real-time clock. For more information on the RTC IC and getting time data with an Arduino please visit chapter twenty of my tutorials. For this example we will use the first two digits for the hours, and the last two digits for minutes. The display will then rotate to showing the numerical day and month of the year – then repeat.

Operation is simple – just get the time from the DS1307, then place the four digits in an array. The elements of the array are then sent in reverse order to the shift registers. The procedure is repeated for the date. Anyhow, here is the sketch (download):

#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68
// note the digital pins of the arduino that are connected to the nixie driver
int clockPin = 7;
int latchPin = 8;
int dataPin = 9;
int clockArray[5]; // holds the digits to display
int a=0;
// the bits represent segments a~dp from left to right
// if you add one to the number (or turn on the last bit) the decimal point turns on
byte numbers[]={
 B11111100, // digit zero
 B01100000,
 B11011010,
 B11110010,
 B01100110,
 B10110110,
 B10111110,
 B11100000,
 B11111110,
 B11110110}; // digit nine
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
 return ( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
 return ( (val/16*10) + (val%16) );
}
void setDateDs1307(byte second, // 0-59
byte minute, // 0-59
byte hour, // 1-23
byte dayOfWeek, // 1-7
byte dayOfMonth, // 1-28/29/30/31
byte month, // 1-12
byte year) // 0-99
{
 Wire.beginTransmission(DS1307_I2C_ADDRESS);
 Wire.send(0);
 Wire.send(decToBcd(second)); // 0 to bit 7 starts the clock
 Wire.send(decToBcd(minute));
 Wire.send(decToBcd(hour)); 
 Wire.send(decToBcd(dayOfWeek));
 Wire.send(decToBcd(dayOfMonth));
 Wire.send(decToBcd(month));
 Wire.send(decToBcd(year));
 Wire.send(0x10); // sends 0x10 (hex) 00010000 (binary) to control register - turns on square wave
 Wire.endTransmission();
}
// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
 // Reset the register pointer
 Wire.beginTransmission(DS1307_I2C_ADDRESS);
 Wire.send(0);
 Wire.endTransmission();
 Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
 // A few of these need masks because certain bits are control bits
 *second = bcdToDec(Wire.receive() & 0x7f);
 *minute = bcdToDec(Wire.receive());
 *hour = bcdToDec(Wire.receive() & 0x3f); // Need to change this if 12 hour am/pm
 *dayOfWeek = bcdToDec(Wire.receive());
 *dayOfMonth = bcdToDec(Wire.receive());
 *month = bcdToDec(Wire.receive());
 *year = bcdToDec(Wire.receive());
}
void setup()
{
 byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
 pinMode(latchPin, OUTPUT);
 pinMode(clockPin, OUTPUT);
 pinMode(dataPin, OUTPUT);
 Wire.begin();
// Change these values to what you want to set your clock to.
 // You probably only want to set your clock once and then remove
 // the setDateDs1307 call.
second = 00;
 minute = 35;
 hour = 17;
 dayOfWeek = 5;
 dayOfMonth = 29;
 month = 4;
 year = 12;
 // setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
}
void showTime()
{
 byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
 getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);

 if (hour<10)
 {
 clockArray[1]=0;
 clockArray[2]=hour;
 }
 if (hour>9)
 {
 clockArray[1]=int(hour/10);
 clockArray[2]=hour%10;
 } 
 if (minute<10)
 {
 clockArray[3]=0;
 clockArray[4]=minute;
 }
 if (minute>9)
 {
 clockArray[3]=int(minute/10);
 clockArray[4]=minute%10;
 }
 displayArray();
}
void showDate()
{
 byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
 getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);

 if (dayOfMonth<10)
 {
 clockArray[1]=0;
 clockArray[2]=dayOfMonth;
 }
 if (dayOfMonth>10)
 {
 clockArray[1]=int(dayOfMonth/10);
 clockArray[2]=dayOfMonth%10;
 }
 if (month<10)
 {
 clockArray[3]=0;
 clockArray[4]=month;
 }
 if (month>10)
 {
 clockArray[3]=int(month/10);
 clockArray[4]=month%10;
 }
 displayArray();
}
void displayArray()
// sends the data from clockArray[] to the shift registers
{
 digitalWrite(latchPin, LOW);
 shiftOut(dataPin, clockPin, LSBFIRST, numbers[clockArray[4]]); // digit 4 
 shiftOut(dataPin, clockPin, LSBFIRST, numbers[clockArray[3]]); // digit 3 
 shiftOut(dataPin, clockPin, LSBFIRST, numbers[clockArray[2]]+1); // digit 2 and decimal point
 shiftOut(dataPin, clockPin, LSBFIRST, numbers[clockArray[1]]); // digit 1
 digitalWrite(latchPin, HIGH);
}
void loop()
{
 showTime(); // display the time 
 delay(5000);
 showDate(); // display the date (day and month) for two seconds
 delay(2000);
}

and the clock in action:

So there you have it – another older style of technology dragged into the 21st century. If you enjoyed this article you may also like to read about vintage HP LED displays. Once again, I hope you found this article of interest. Thanks to the Vintage Technology Association website for background information.

Have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column, or join our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

April 29, 2012 Posted by | arduino, vintage | , , , , , , , , , , , , , , , , , , , , | 2 Comments

Arduino and TM1640 LED Display Modules

Introduction

The purpose of this article is to demonstrate the use of the second (here’s the first) interesting LED display module I discovered on the dealextreme website, for example:

As you can see the display unit holds a total of sixteen seven-segment LED digits using four modules. However thanks to the use of the TM1640 controller IC

… the entire display is controlled with only four wires – 5V, GND, data in and clock:

Here is the data sheet for the TM1640. The board also ships with the 30cm long four-wire lead and fitted plug. Finally, there is a ‘power on’ LED on the right-hand end of the board:

Getting Started

Now to make things happen. From a hardware perspective – it couldn’t be easier. Connect the 5V and GND leads to … 5V and GND. The data and clock leads will connect to two Arduino digital pins. That’s it. The maximum current drawn by the display with all segments on is ~213mA:

So you should be able to drive this from a normal Arduino-compatible board without any hassle. Please note that the TM1640 IC does heat up somewhat, so you may want to consider some sort of heatsink if intending to max out the display in this manner.

From the software side of things you will need to download and install the TM1638 library (yes) which also handles the TM1640 chip. To simply display text from a string on the display, examine the following sketch:

#include "TM1638.h"// yes you need both
#include "TM1640.h"
// define a module on data pin 7, clock pin 8
TM1640 module(7, 8);
void setup()
{
 // nothing to do here
}
void loop()
{
 String name = "0123456789012345";
 module.setDisplayToString(name, 0b0000000000000000);
 delay(32766);
}

Which will display:

The sixteen digit binary number in the module.setDisplayToString() line controls the decimal points – 0 for off and 1 for on. For example, changing it to

0b1010101010101010

will display:

You can also display text in a somewhat readable form – using the characters available in this list.

Displaying numbers is very easy, you can address each digit individually using:

module.setDisplayDigit(x, y, true/false);

where x is the digit, y is the position (0~15), and true/false is the decimal point. At this time you can’t just send a long integer down to the display, so you will need to either convert your numbers to a string or failing that, split it up into digits and display them one at a time.

In the following example sketch we display integers and unsigned integers by using the C command sprintf(). Note the use of %i to include an integer, and %u for unsigned integer:

#include "TM1638.h"  // required because the way arduino deals with libraries
#include "TM1640.h"
// define a module on data pin 7, clock pin 8
TM1640 module(7, 8);
void setup()
{
 // nothing to do here
}
void loop()
{
 char text[17];
 int z;
for (z=0; z<5; z++)
 {
 int a=32767;
 sprintf(text, "INTEGER %i",a);
 module.setDisplayToString(text); 
 delay(1000);
 module.clearDisplay();
unsigned int ui=65535;
 sprintf(text, "UNSIGNED %u",ui);
 module.setDisplayToString(text);
 delay(1000);
 module.clearDisplay();
 }

 for (z=0; z<32767; z++)
 {
 sprintf(text, "COUNTING %i",z);
 module.setDisplayToString(text); 
 delay(10);
 }
}

And the resulting output:

Now you have an idea of what is possible, a variety of display options should spring to mind. For example:

Again, this display board was a random, successful find. When ordering from dealextreme, do so knowing that your order may take several weeks to arrive as they are not the fastest of online retailers; and your order may be coming from mainland China which can slow things down somewhat. Otherwise the module worked well and considering the minimal I/O and code requirements, is a very good deal.

Have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column, or join our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

April 9, 2012 Posted by | arduino, part review, TM1640 | , , , , , , , , , , , , , , , , | 10 Comments

Hewlett-Packard 5082-7415 LED Display from 1976

In this article we examine a five digit, seven-segment LED display from Hewlett-Packard, the 5082-7415:

According to the data sheet (HP 5082-series.pdf) and other research this was available for a period of time around 1976 and used with other 5082-series modules in other HP products. Such as the Hewlett-Packard 3x series of calculators, for example:

Using the display is very easy – kudos to the engineers at HP for making a simple design that could be reusable in many applications. The 5082-7415 is a common-cathode unit and wiring is very simple – there are the usual eight anodes for segments a~f and the decimal point, and the five cathodes.

As this module isn’t too easily replaceable, I was very conservative with the power supply – feeding just under 1.6V at 10mA to each of the anode pins. A quick test proved very promising:

Excellent – it worked! But now to get it displaying some sort of interesting way. Using the following hardware…

  • Freetronics Eleven Arduino-compatible board
  • Two 74HC595 shift registers
  • Eight 560 ohm resistors
  • Five 1k ohm resistors
  • Five BC548 transistors
  • A large solderless breadboard and plenty of wires

… it was connected in the same method as a four-digit display (except for the extra digit) as described in my tutorial. Don’t forget to use the data sheet (HP 5082-series.pdf). You don’t have to use Arduino – any microcontroller with the appropriate I/O can take care of this.

Here is a simple Arduino sketch that scrolls through the digits with and then without the decimal point (download):

// Arduino sketch to demonstrate HP 5082-7415 LED Display unit
 // John Boxall, April 2012
int clockPin=6;
 int latchPin=7;
 int dataPin=8;
// array for cathodes - sent to second shift register
 byte digits[]={
 B10000000,
 B01000000,
 B00100000,
 B00010000,
 B00001000,
 B11111000}; // use digits[6] to turn all on
// array for anodes (to display 0~0) - sent to first shift register
 byte numbers[]={
 B11111100,
 B01100000,
 B11011010,
 B11110010,
 B01100110,
 B10110110,
 B10111110,
 B11100000,
 B11111110,
 B11110110};
void setup()
 {
 pinMode(clockPin, OUTPUT);
 pinMode(latchPin, OUTPUT);
 pinMode(dataPin, OUTPUT);
 }
void loop()
 {
 int i;
 for ( i=0 ; i<10; i++ )
 {
 digitalWrite(latchPin, LOW);
 shiftOut(dataPin, clockPin, LSBFIRST, digits[6]);
 shiftOut(dataPin, clockPin, LSBFIRST, numbers[i]);
 digitalWrite(latchPin, HIGH);
 delay(250);
 }
 // now repeat with decimal point
 for ( i=0 ; i<10; i++ )
 {
 digitalWrite(latchPin, LOW);
 shiftOut(dataPin, clockPin, LSBFIRST, digits[6]);
 shiftOut(dataPin, clockPin, LSBFIRST, numbers[i]+1);
 digitalWrite(latchPin, HIGH);
 delay(250);
 }
 }

And the results:

Now for something more useful. Here is a function that sends a single digit to a position on the display with the option of turning the decimal point on or off:

void displayDigit(int value, int posit, boolean decPoint)
// displays integer value at digit position posit with decimal point on/off
{
 digitalWrite(latchPin, LOW);
 shiftOut(dataPin, clockPin, LSBFIRST, digits[posit]);
 if (decPoint==true)
 {
 shiftOut(dataPin, clockPin, LSBFIRST, numbers[value]+1); 
 } 
 else 
 {
 shiftOut(dataPin, clockPin, LSBFIRST, numbers[value]); 
 }
 digitalWrite(latchPin, HIGH);
}

So if you wanted to display the number three in the fourth digit, with the decimal point – use

  displayDigit(3,3,true);

with the following result:

We make use of the displayDigit() function in our next sketch. We introduce a new function

displayInteger(number,cycles);

It accepts a long integer between zero and 99999 (number) and displays it on the module for cycles times. You can download the sketch from here.

// Arduino sketch to demonstrate HP 5082-7415 LED Display unit
// Displays numbers on request
// John Boxall, April 2012
int clockPin=6;
int latchPin=7;
int dataPin=8;
// array for cathodes - sent to second shift register
byte digits[]={
 B10000000,
 B01000000,
 B00100000,
 B00010000,
 B00001000,
 B11111000}; // use digits[6] to turn all on
// array for anodes (to display 0~0) - sent to first shift register
byte numbers[]={
 B11111100,
 B01100000,
 B11011010,
 B11110010,
 B01100110,
 B10110110,
 B10111110,
 B11100000,
 B11111110,
 B11110110};
void setup()
{
 pinMode(clockPin, OUTPUT);
 pinMode(latchPin, OUTPUT);
 pinMode(dataPin, OUTPUT);
 randomSeed(analogRead(0));
}
void clearDisplay()
// turns off all digits
{
 digitalWrite(latchPin, LOW);
 shiftOut(dataPin, clockPin, LSBFIRST, 0);
 shiftOut(dataPin, clockPin, LSBFIRST, 0); 
 digitalWrite(latchPin, HIGH);
}
void displayDigit(int value, int posit, boolean decPoint)
// displays integer value at digit position posit with decimal point on/off
{
 digitalWrite(latchPin, LOW);
 shiftOut(dataPin, clockPin, LSBFIRST, digits[posit]);
 if (decPoint==true)
 {
 shiftOut(dataPin, clockPin, LSBFIRST, numbers[value]+1); 
 } 
 else 
 {
 shiftOut(dataPin, clockPin, LSBFIRST, numbers[value]); 
 }
 digitalWrite(latchPin, HIGH);
}
void displayInteger(long number,int cycles)
// displays a number 'number' on the HP display. 
{
 long i,j,k,l,z;
 float f;
 clearDisplay();
 for (z=0; z
void loop()
{
 long l2;
 l2=random(0,100001);
 displayInteger(l2,400);
}

For demonstration purposes the sketch displays random numbers, as shown in the video below:

Update – 23/04/2012

Finally after some more hunting around I found some four-digit (possible knock-off versions of the) HP QDSP-6064 display units on eBay (item #120876219746) as shown below:

They worked very nicely and can be driven in the same method as the 5082-7415s descibed earlier. In the following video we have run the same sketches with the new displays:

In the meanwhile, I hope you found this article of interest. Thanks to the Vintage Technology Association website and the Museum of HP Calculators for background information and Freetronics for the use of the Eleven.

Have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column, or join our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

April 7, 2012 Posted by | 5082-7415, hardware hacking, part review, vintage | , , , , , , , , , , , , , , | 6 Comments

Follow

Get every new post delivered to your Inbox.

Join 3,836 other followers

%d bloggers like this: