LM3909 – An IC Just to Flash an LED

So during my placement year I was getting really into old electronics, and old IC’s, especially those no longer in production. We were also on a project where we were trying to design a circuit that would flash an LED for a short period of time from the charge on a small super capacitor. The big issue we had was how to minimise current flow, and power an LED at really low voltages, less than 2V. This on the face of it seems like a simple problem, until you start to think about it.

Million Mile Light
Products like the Million Mile Light, a flashing low powered, high brightness LED indicator need to flash for long periods of time on very little charge, much like the problem I faced. Credit: Million Mile Light

There are two go to ways that most engineers would go with to make a flashing LED with a constant flash rate. First is to use a small microcontroller, such as an ATTiny, or a Pic12F series, and use software to flash the LED. This seems good on the surface (and it is what we used in the end product) but it has a big drawback, it can only output a voltage less than the power rail. some versions of the PIC12LF’s can function down to 1.8V, perfect for our power supply needs, but LED’s need upwards of 2.7V (usually) before they start to light, so although our micro will work the LED wont. The second go to way to make an LED flash would be to use the classic 555 timer, one of the most manufactured chips of all time. There is a good reason it is famous, it is extremely versatile. You can decide the frequency based purely on the capacitor and resistor choices. We still have a similar drawback though, a 555 timer needs at least 4.5v as a power supply. So with our potential sub 2V power supply, neither the IC or the LED will turn on. That is one way to conserve energy!

schematic
A cut out from the datasheet, with a basic view of the circuit inside the IC, which I will go through in another post, and a pinout diagram, very useful for prototyping. Credit: National Semiconductor.

This is where the LM3909 came in to play. You have to remember that this chip was developed prior to 1995 (so it is older than me) when the electronics market was very different. Battery technology was not the same, and nowhere near as cheap. It was much more common for people to want to use off the shelf single use batteries such as AA, C and D batteries, or even coin cells in most projects. If you wanted something with a little flashing light on it there were plenty of applications for it. There are buoys in the ocean, store signs and displays, and Christmas lights, all of which would benefit from minimising weight of batteries, but lasting for serious amounts of time. Just as a reference, you could get to 4.5V (to power a 555) by using 3 AA batteries, but the voltage across them would soon dip below this, so you would need at least 4 in most applications. 4 AA batteries take up a lot of space, and weight, not great for many of these applications. Plus most of the chips we have discussed use a fair amount of power, the 555 uses at least 3mA while running, not including the dissipation in the resistors, and all of the power charging the capacitor wasted.

1.5v schematic
A snippet of the datasheet, showing the simplest connection diagram, and a graph of typical current consumption with relation to the battery voltage. It also has a great table describing how long standard batteries tend to last in this configuration, up to 2 years! Credit: National Semiconductor.

So how does the LM3909 solve these issues? well it makes use of a clever concept similar to the 555 of charging up a capacitor. The difference is that the 3909 uses that charge in the capacitor to flash the LED. Although it is slightly more complex than the below schematic, you can think of it as there being a switch inside that oscillates between two states. We will go through how it actually works in a future post. To start with the capacitor is in series with the battery, and in parallel with the LED. The LED wont light, but the capacitor charges up to near the power supply voltage. Once charged, the switch inside flips, and now the power supply, charged capacitor, and LED are in series with each other. To the LED it now sees the capacitor (charged to 1.5V) plus the 1.5V power supply, equivilent to 3V, more than the forward voltage it needs to turn on. As there is a very small resistance, the LED will be on as long as the capacitor has some charge, which isn’t very long as it will discharge fairly quickly. This is the “flash”, as once the cap is discharged the LED will turn off, and the switch will flip back. The capacitor starts charging again, and the whole process restarts. This goes on for as long as the battery has power to give.

Rob Paisley
A great description of the basic principle of how the LM3909 works, charging the capacitor up, and then releasing all that energy through the LED, with increased voltage. Credit: Rob Paisley.

A couple of points to note, the timing and the brightness of the flashing is based upon the capacitor you use, which is quite clever. There are two settings, depending in the pin you put the capacitor in will also double (or halve) the time the cap will take to charge. This means slower flashing, but longer lifetime. Having a smaller capacitor will mean faster, but less bright flashing, and a bigger cap will therefore be slower and much brighter flashing. The design of the chip also means that only two external components are needed for it to work, a capacitor and the LED, compared to the many resistors and extra cap needed on things like a 555 timer. The fact it can use less than 1.5V power source means we can use a single AA battery to power this device, and according to the data sheet it can last up to 6 months on one battery! I have one on my desk that has lasted longer than this.

my LM3909 circuit
My version of this circuit fit into a AA battery box, with it being powered by a single AA battery. It has a switch meaning I can turn it on and off. Poundland LED lights are a good source of these!

All in all I can see why National Semiconductor decided to make this chip, it filled a gap, and was used widely for a long time. Developments in battery technology, and more complex designs needed for the applications this was for has meant that they no longer make the LM3909, but they are still available on Ebay and some Chinese manufactures make them. There is also a design out there to make a discrete version of the LM3909, and I may try that for a future post, as it looks interesting.

Thank you for reading, take a look at my other posts if you are interested in space, electronics, or military history. If you are interested, follow me on Twitter to get updates on projects I am currently working on.

Follow @TheIndieG
Tweet to @TheIndieG

Interfacing a PIC and a 16×2 LCD

So in a recent project I had to implement a 16×2 LCD  on a PIC16F1827, but the system will work on most PIC microcontrollers, with slight changes to the code. For this project I am using MPLAB X v3.40, a free development environment, and a PICKIT 3, which can be bought at a number of stores online.

Setting up the MPLAB project

  1. Start off by loading up MPLAB X, if you don’t have it already, install it from the Microchip website microchip.com/mplab/mplab-x-ide.
  2. Start a new project, by going to File->New Project… or by pressing Ctrl+Shift+Nnew project
  3. The project we want is a standalone project, it should be chosen by default. Next choose the device we want, write in the box PIC16F1827 there should only be one. We want to use the PicKit 3 for the programmer. I am using XC8 as the compiler, this is available from the Microchip to9 stawebsite. Finally choose the name of the project, and where you want to keep it. Then click finish.
  4. It wont look like mush at the moment, but under Projects on the right, there should now be your newly created project, with a drop down, and a set of folders. Something like this: 
  5. To start the project, we need a main.c. So right click on Source Files, go to New->C Main File… then in the Dialog, change the name to main. After pressing okay, it should look like this: 

Connecting the LCD

LCDs have what is known as a parallel connection. This means that we send data 8 bits at a time, rather than serial where it is one at a time. The datasheet for the PIC is found on the microchip website here. The pinout is found on page 4.

PIC pinout

Register Select (RS) pin, this decides which of the two registers that is getting written to. Either the instruction register (what the screen does) or the data register (what is shown on the screen). This is connected to A4 on the PIC.

Read/Write (RW) pin, this decides whether you are writing to or reading from the LCD. This is connected to pin A3.

Enable (E) pin, is to tell the LCD when data needs to be transferred. Pulsing this pin will write or read to the registers the data on the data pins. This is connected to pin  A2.

These pins are defined at the top of the code, to make life easier for us later on.

#define LCD_RS LATAbits.LATA4   //LCD Command/Data Control
#define LCD_RW LATAbits.LATA3   //LCD Read/Write Select
#define LCD_E LATAbits.LATA2    //LCD Enable Line

Data Pins (D0-D7), are the pins that transfer the information between the LCD and the PIC. These are connected to pins B0-B7. So B0 is connected to D0, and so on until B7 is connected to D7.

Vdd and Vss are connected to 5v and GND respectively.

Contrast (Vo) is connected to a 10k pot between the 5v  and  GND.

If the LCD you are using has connections for a backlight, follow the datasheet for instructions, on mine I connect it t0 5v and GND.

The Code

Below is the function I create to send data to the LCD.

#define LCD_CMD 0
#define LCD_TXT 1 

void LCD_DATA (unsigned char data, int type)
{
    __delay_ms(100);   // short delay

    LATB = 0x00;       // reset the register to 0
    LATB = data;       // set B output to the data we want to send
    __delay_ms(1);     // short delay for data to set

    if (type == LCD_CMD)
    {
        LCD_RS = 0;    // command mode
    }
    else
    {
        LCD_RS = 1;    // character/data mode
    }

    LCD_RW = 0;        // start the pulse
    __delay_ms(1);     // small delay
    LCD_E = 1;         // enable LCD data line
    __delay_ms(1);     // small delay
    LCD_E = 0;         // disable LCD data line
    __delay_ms(5);
}

Calling this function in the main, like follows will send data to the LCD. Notice the #define at the top, these are declaring LCD_CMD and LCD_TXT. Basically, when the type is LCD_CMD the LCD is sent into command mode, by setting the RS pin. Equally, sending LCD_TXT will clear the RS pin, putting the LCD in character mode.

The information on the data pins will then get written to the LCD, by clearing RW. To actually tell the LCD that it needs to be sent new instructions the enable pin needs to be pulsed. Once this happens, the screen should be updated with the new information.

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>

#define _XTAL_FREQ 500000

#define LCD_RS LATAbits.LATA4   //LCD Command/Data Control
#define LCD_RW LATAbits.LATA3   //LCD Read/Write Select
#define LCD_E LATAbits.LATA2    //LCD Enable Line

#define LCD_CMD 0
#define LCD_TXT 1 

void LCD_DATA (unsigned char data, int type)
{
    __delay_ms(100);   // short delay

    LATB = 0x00;       // reset the register to 0
    LATB = data;       // set B output to the data we want to send
    __delay_ms(1);     // short delay for data to set

    if (type == LCD_CMD)
    {
        LCD_RS = 0;    // command mode
    }
    else
    {
        LCD_RS = 1;    // character/data mode
    }

    LCD_RW = 0;        // start the pulse
    __delay_ms(1);     // small delay
    LCD_E = 1;         // enable LCD data line
    __delay_ms(1);     // small delay
    LCD_E = 0;         // disable LCD data line
    __delay_ms(5);
}


int main(int argc, char** argv) {
 
    // write "hello world!" on the first line
    LCD_DATA('h', LCD_TXT);
    LCD_DATA('e', LCD_TXT);
    LCD_DATA('l', LCD_TXT);
    LCD_DATA('l', LCD_TXT);
    LCD_DATA('o', LCD_TXT);
    LCD_DATA(' ', LCD_TXT);
    LCD_DATA('w', LCD_TXT);
    LCD_DATA('o', LCD_TXT);
    LCD_DATA('r', LCD_TXT);
    LCD_DATA('l', LCD_TXT);
    LCD_DATA('d', LCD_TXT);
    LCD_DATA('!', LCD_TXT);
 
    while (1)
    {
 
    }
 
 return (EXIT_SUCCESS);
}