Tag-Archive: MAKE

1 Watt constant current LED driver shootout

1 Watt LED drivers

As many electronic hobbyists, I have always been fascinated by LEDs, especially the really bright ones. I could now ramble on about 50W or 100W LEDs, but to connect to the story of my previous post, I will talk a little about driving 1 Watt LEDs, the ones that come on a star shaped heatsink (e.g. the first Luxeon generation). While you could connect those with a current limiting resistor as you do with the small 20mA LEDs, it is not a really wise thing to do as you would need large resistors, withstanding an unhealthy amount of heat. So the device of choice is a constant current source – in this case one that provides 350mA constant current. I have three different ones and took some time to evaluate them from a users perspective (meaning ease of use, etc. – I will not talk about output ripple, stability, surges, etc.).

The good, the bad and the ugly?

1 Watt constant current LED driversI going to look at three different constant current sources:

They all work pretty straight forward, you supply them with a voltage between 9V and 30V (+/-) and they output 350mA of current with which you can drive one or more 1Watt LEDs in series (provided the combined forward voltage doesn’t exceed your input voltage). No suprise here, they all do that and work just fine. But what about dimming the LEDs? Each of the drivers has a dedicated pin for that. And here it get’s complicated…

Meanwell LDD-350L

This one is the most uncomplicated of the bunch. To use the dimming pin, simply apply a PWM signal (in my case from an Arduino), and the driver will dim the LED according to your PWM duty cycle. 10% duty cycle = 10% current (which is not neccesarily 10% brightness as the relationship between brightness and current is not linear with these LEDs), 50% duty cycle = 50% current, 100% duty cycle = 100% current. You catch my drift. The driver will align the output to the duty cycle (and even the PWM frequency) of the DIM pin.

LDD350L with 50% duty cycle on Arduino pin 5

LDD350L with 50% duty cycle on Arduino pin 5


LDD350L with 50% duty cycle on Arduino pin 3

LDD350L with 50% duty cycle on Arduino pin 3

Since pins 3/9/10/11 and 5/6 (on the Arduino UNO compatibles) use two different PWM frequencies, this is reflected in the above wave forms.


As mentioned in the previous post, the ZETEX chip an this current source is a little odd with regard to PWM control. In my tests, I found out that a duty cycle between 0% and about 45% gives you current control from 0% to 100% (using a 5V PWM signal). If you raise the duty cycle to more than 45%, the driver will exponentially increase the output current, thus overdriving the LED. A duty cycle of 55% will yield more than 520mA output current, guaranteeing premature ageing and death of your LED. So be careful. This driver also copies the PWM frequency from the input source, which is exactly what the datasheet said: Depending upon the control frequency, this will provide either a continuous (dimmed) or a gated output current. Since the PWM frequency is above 300Hz, we see a gated output waveform on the oscilloscope:

Anvilex CCS2 with 40% duty cycle on Arduino pin 3

Anvilex CCS2 with 40% duty cycle on Arduino pin 3

To work with this driver, you have to make sure to limit the PWM duty cycle to a maximum less than 50%, otherwise you might fry your LED (and maybe more…). This driver also produces hissing noises varying on the PWM duty cycle which may annoy you depending on your use case.

No-Name (with XLSemi XL4001 chip)

This is one of the cheap LED drivers you can get on ebay for just a couple of Euros. It has almost the same components as the CCS2, namely input/output smoothing caps, schottky diode, an inductor and some resistors to configure the chip. The only real difference is the XLSemi XL4001 chip that is used on this module. It it not per se a LED driver, it is a multipurpose DC/DC buck converter, but it features a current control loop, so that it can be used as a constant current source too. This driver can be dimmed using PWM as well, but the output waveform has nothing in common with the input waveform. In fact, it looks a little odd:

XLSemi XL4001 output waveform

XLSemi XL4001 output waveform

Dimming this driver offers some pitfalls: the PWM pin is the ENABLE pin of the chip, which is inverted. This means a PWM duty cycle of 0% will cause the driver to output a current level of 100% and a duty cycle of 100% will shut the driver down. Just keep that in mind when designing your sketch or whatever. The other thing: although the datsheet says, that the default state of the ENABLE pin is low, it will not return to that state if the chip already received a PWM signal and the signal wire is disconnected afterwards. Instead, it will spiral upwards, causing the output off excessive amounts of current to the LED, slowly killing it. So when experimenting with it, be sure not to pull out any wires while the circuit is still live.


There is no winner to be named here, these drivers all do what they were made to do. If I had to pick a favorite, it would be the Meanwell LDD-350L because it is *so* uncomplicated to work with and there a no suprises. You can work with the others as well, but be sure to read up on the special traits of each driver/chip so you can avoid nasty surprises.

How to blow up electronics #1 – with power LEDs

So the other day I started working on a custom high power LED strip, using red, green and blue 1 Watt power LEDs. Nothing really fancy, just 7 LEDs in series per color, each driven by a 350mA constant current source at about 24 volts. I decided to throw in an Arduino for brightness control, since the cc sources have PWM dimming capability. Fun fact: I didn’t need to buy any additional components, everything I needed I had lying around somewhere (don’t ask…).

The setup

The setup is pretty straight forward: the thing is powered by 12V DC which is then boosted to 24V by some beefy boost converter. Those 24V are then hooked up to three Anvilex CCS2-350 constant current drivers. Each string of 7 LEDs – with blue haven the highest forward voltage, thus 7×3.5V ~= 24V – is connected to one of these drivers.

Arduino power LED control box

Power LED control box

Dimming with the Arduino

Enter the Arduino: for testing purposes I added a classic Freeduino (Duemilanove clone), connecting it to the 12V input voltage and attaching the PWM ports to the DIM ports of the CCS2s. There are some caveats using the CCS2 and the data sheet doesn’t make it very easy to understand them (either this or I am a rather slow learner…). Anyway. The CCS2 uses the Zetex ZXLD1366 LED driver chip and this chip provides the DIM pin. This pin is some sort of „jack of all trades“ and accepts analog voltages, PWM modulated voltages or PWM gating.

Fun with the ZXLD1366 specs

The ADJ pin will accept either a DC voltage or a PWM waveform. Depending upon the control frequency, this will provide either a continuous (dimmed) or a gated output current. — from the ZXLD1366 datasheet

What the hell does that mean? It means you can either

  • suppy a true analog voltage or
  • a PWM signal which will cause
    • true analog current control at a low frequency (< 300 MHz) or
    • gated output control (meaning „chopped“ on/off/on/off cyles relation to your PWM signal)

Since the lowest PWM frequency you can get on the Arduino is 490 MHz (not using any timer manipulation or soft PWM), we will have gated output control.

That doesn’t sound so bad – but there is another drawback to trip over: the DIM pin can withstand voltages up to 6 volts, BUT the output current will reach the designated maximum value (in my case 350mA) at a voltage of 1.25V. The chip will shutdown to power saving when the voltage drops below 0.2 volts. And (here it comes): anything between 1.25V und 2.5V will further increase the current output up to twice the maximum (700 mA). Voltage increases above 2.5V have no further effect.

Congratulations, we have just found the means of blowing up our LEDs. So I had to limit the PWM range to 0-63 (256 steps/5 Volts * 1.25V ~= 63). No problem here, we are just losing some resolution.

Blowing stuff up

I wrote a small test sketch to see if everything worked an it surely did. I the replaced the bulky Freeduino with a soldered in Pro Mini that will actually fit inside the enclosure. I fired everything up again and there it was: a well audible bzzzt and then silence. Followed by some erratic flashing on the power LED side. The Pro Mini had gone out with a bang (you have to see volume in relation to the size of the components…). But why? Frantically checking everything it turned out the Atmega328 was fried. Interestingly enough, also one of the power LEDs got killed in the process. I realised that when I connected the Freeduino again and the red LED string wouldn’t come on anymore.

I replaced the faulty LED and ran everything again and it all worked fine. I then replaced the Freeduino with another Pro Mini and measured everything without the LEDs attached and it surely would work. I then reattached the LEDs and … bzzzt. Another Pro Mini dead. And another power LED. WTF?

Once more measuring everything after hooking up the Freeduino again. This time I also used my trusty pocket oscilloscope. And what did I find? I was betrayed by my love for cheap components…

WTF? Why?

Some electronic components I fried

The components I fried

So, here’s what happened: I am using a rather cheap 30W 12V power supply. It is supposed to power 21 Watts of LEDs and assuming that to boost converter operates at an optimistic 85% efficiency rate, it would need to provide a least 25 Watts of power. And it does. During a brief period when the circuit is already powered and the Arduino has booted, the CCS2 will power the LEDs at full brightness (I guess that’s by design). So the whole thing draws 25 Watts right from the start. The power supply compensates for the sudden demand, but there is a slight voltage spike of ~13V as it does. That spike is no problem for the 7805 on the Freeduino and it would also be no problem for the MIC5205 (up to 16 Volts VIN) on the Pro Mini had I been using a genuine one and not some cheap clones. The clones come with a MIC5219 or some other cheaper regulator that allows only 12 Volts at VIN.

So the regulator was fried by the voltage spike. That in turn damaged the Atmega chip and made it send more than 2.5V to the DIM pins. The LED current was doubled and one LED sacrified itself so that the others could survive. On the second attempt, uregulated voltage was flowing everywhere and even killed one of the constant current sources. Yay! No…

Lessons learned

So, what do I take with me from this whole mess? Well, I guess I could have avoided those mistakes by thinking a little bit more before soldering. Measure twice, cut once they say. I say: But cutting is more fun than measuring :-). So better luck next time. Here are the two major learnings:

  • Don’t rely on the linear voltage regulator of your Arduino, especially not on tiny, cheap Arduino clones. Either use a standalone 7805 regulator or – and that is the preferred way – use a switching step-down (or even a really fancy step-up/step-down) converter such as the Pololu D24V5F5 or the S10V4F5. They can take at least 18 Volts and are have builtin safeties.
  • Use a voltage divider circuit for the PWM signal on the DIM pin. This gives you the full resolution of 256 steps on the PWM (although atmittedly you really can’t see any difference in brightness using only a single step) and it protects the DIM pin – and your LEDs – against over-voltage/current.

Presenting the ICMI MAX7219 Arduino library

For my current project, the ICMI Service Status Monitor, I have chosen the Maxim MAX7219 IC to drive the indicator LEDs. This little chip comes with several nice out of the box features such as adjustable LED current, 16 level brightness control, special decode mode for seven segment displays and so on. The main reason I chose it is because it contains a multiplex scan mechanism implemented in hardware. This frees my own code from a lot of additional complexity that I would encounter if I chose to implement multiplex scanning in software (which is not impossible of course and I’ve already done it – check the code samples for my ICMI Seven Segment Board – but it’s nice not having to do it and besides that, the focus of this projects lies more on the PC/Arduino communication).

Control issues

The downside of using the MAX7219 is the more complex communication with the chip required to make things work. The IC uses various registers to store its configuration state and when sending data, you also have to address the proper register and pass the data in a format specified in the data sheet. To make things easier, I chose to implement this communication in form of an Arduino library that makes using the MAX7219 a whole lot easier by hiding the complexity behind a neat API. Others have implemented such a library before more of course and some of them also offer additional functionality such as multi-chip configuration or CODE B digit decoding. I do not intend to compete with them (at least not yet), I merely took the opportunity of extending my skills.

The code for this library along with example code is available on github at https://github.com/hmbusch/ICMI-MAX7219-Arduino

API description

This section describes the methods available to the user when importing this library. Again: don’t get confused by the uint8_t data type – it is the same as byte in Arduino and can hold an integer value between 0 and 255.

Constructor Max7219(uint8_t dataPin, uint8_t clockPin, uint8_t loadPin, uint8_t digitCount)

This constructor is used to create a new „control instance“ for the connected MAX7219 chip. The IC required 3 Arduino pins – the data pin, the clock pin and the load pin (pins 1, 13 and 12 of the MAX7219) that you need to pass to the constructor. In addition, you have to tell it, how many digits (when using seven segment displays) or rows (that’s what we want) are connected to the driver. This value is used internally to verify the parameters of later method calls. Example (Arduino connected with pins 5, 6 and 7):


Method void enable(boolean enable)

The whole LED driver can be shutdown by disabling it. All its settings and the current state are preserved, the chip just ceases to operate. After a power reset, the chip is disabled by default so you will need to call max7219.enable(true) (assuming the control instance was constructed with the name  max7219  as in the constructor example above) if you want it to show something. If you omit this call, all your configuration commands will still configure the chip but you simply won’t see it. Enabling and disabling the driver can also be used to flash the whole display.

Methods void setDigitRaw(uint8_t which, uint8_t value) / void setRow(uint8_t which, uint8_t value)

These two methods are actually only one method with two names. I introduced these names so a user could call whichever method best fits in the context of his program. If your program controls a LED matrix, calls to setDigitRaw() might seem a little strange so you could use setRow() instead.

This is the method that actually tells the driver what to display. You have to specify the index of the row/digit that you want to set (ranging from 0-7, limited by the row/digit count you gave in the constructor) and the value you want to set it to. To make things easier, the method performs a bit level translation of the value from your value to what the MAX7219 expects. This way, the bit order equals the segment or column order. Bit 0 (the rightmost bit, also called the least significant bit) corresponds to segment A (column 1), bit 1 corresponds to segment B (column 2) and so on. To display the number 7 on the fourth digit of a seven segment display, you would pass 3 as the index and  B00000111  (segment A-C lit).

Although the MAX7219 supports it, the library currently does not offer a way to pass a BCD number to the chip. When using BCD mode, you could display a 7 by actually passing a 7 as value and the chip will take care of the decoding to segments. This feature may be included in future releases. The current lack of this feature is the reason why this method is called  setDigitRaw()  and not just setDigit() .

Method void setIntensity(uint8_t level)

The MAX7219 offers a built-in brightness control for the display with a 16 step resolution. This method allows you to set the brightness level for the display and accepts value from 1 (darkest) to 16 (brightest). Any value below 1 will be treated as 1, any value above 16 will be treated as 16. It is not possible to switch off the display, even the darkest setting is still visible and does not stand for „off“. If you want to turn of the display, call  enable(false)  instead. The constructor will set the chip to the highest brightness. This is a sort of safety precaution I created, because the IC’s initial brightness setting defaults to the lowest level. During testing, I wrecked my head trying to figure out why the LEDs were so dim, not realising the brightness settings. For others to avoid this mistake, I reversed the default brightness value in my library implementation.

Method  void testDisplay(boolean testDisplay)

This method can be used to toggle the internal test mode of the MAX7219 on and off. When enabling test mode, the IC switches on all LEDs (regardless of the row/digit count passed to the constructor) and sets brightness to maximum. Enabling the test mode will not overwrite any settings made before entering the test mode, which means when switching back to normal mode, the display will revert to the exact setting that it hade before entering test mode. This method is useful for verifying your LED display and to be able to quickly switch to a fully lit LED panel without having to change each row and saving the state of the display in order to return to that state later.

Method void clearDisplay()

This method does exactly what the name promises: it clears the display by turning all LEDs in all rows off. This operation cannot be undone, that means once you clear the display, you have to reprogram it again, you cannot simply switch back to a previous state.

Method uint8_t version()

In order to provide some hint to a users program regarding the compatibility of the library, this method returns the current version number of the library. This can be used to check programmatically, if the user needs to update to a newer version and it can be used to prevent incompatibility issues.

Using the library

Using this library for your own projects is a two-step process. First, you need to install the library to your Arduino IDE and then you need to import it into you sketch.

Installing the library to the Arduino IDE

Use a file manager to navigate to the directory where your Arduino IDE resides (e.g. D:\Development\Arduino-1.0). Go into the folder called libraries and create a new folder there called ICMIMax7219. Copy the Max7219.cpp and .h files as well as the examples folder into the newly created directory. If your IDE was running at that time, you have to restart it for the changes to take effect. After the restart, go the File => Examples menu. If everything succeeded, you should see and entry called ICMIMax7219 and you can open the BasicFunctionExample from there.

Note: If you have another library for the MAX7219 installed, you may encounter naming clashes when the files of the other library are also named Max7219.*. When encountering this, remove the other MAX7219 library from your Arduino IDE. I will address this problem in the second release of the library.

Using the library in your code

To use the library in your own sketch, you need to import the header file. Do this by placing the line

at the very top of your sketch. This enables you to access the libraries functionality. In order to do so, you need to create an instance of the Max7219 class somewhere in you project. You can do this by calling the constructor as follows

First, the example defines some integer constants to represents the Arduino pins the IC is connected to and the digit/row count. The last line then creates an instance with the name max7219 which can subsequently be used to control the IC with calls like

In order to see a full, working sketch that uses the library, please refer to the BasicFunctionDemo sketch in the examples folder. The video embedded at the start of the post shows you what the output of this sketch will look like on an 8×8 LED matrix.

Building the Service Status Monitor display prototype

Update 2012/11/08: Fixed some mistakes in the code example. The second division should have been a modulo and instead of the dynamically determined offset, the static one was used. Both errors are now corrected.

OK, enough talking – time to actually do something: let’s build the display prototype for the Service Status Monitor. The final version will have a variable amount of indicators (up to 16 with the current design), but to test the functionality and prototype the project, 4 indicators are enough to start with.

Confusing vocabulary

Alright, I got into a little labeling problem. In the first post, I called each combination of three LEDs a segment. Since the IC we’re going to use also uses the word segment but with a different meaning, I’m having trouble to name things without confusion. What was previously called segment will now be called indicator. This should help to keep things seperated from each other.

Hardware choices

In order to minimize the number of parts needed and to make the software design less complex, the display uses one of the modern marvels of integrated circuits, the MAX7219, a LED display driver IC with serial interface. To save power, the circuit will use the POV (persistence-of-vision) effect to display the status indicators (more on that further down) and the MAX7219 has this mechanism built-in. The IC can control up to eight seven-segment digits or up to 64 LEDs arranged in a matrix. It also provides a current control mechanism, making current limiting resistors (and another source of power loss) unnecessary. I admit, the MAX7219 may not be the cheapest IC to use (5-10 US dollars a piece), but you save a lot of time that you’d normally spend on creating „boiler plate code„, as software engineers like to call it. For a cheaper alternative, you could check out my LED-Matrix-Controller over at github. It uses a decade count/shift register/darlington array combination to achieve the same purpose.

Welcome to the matrix

The MAX7219 requires the arrangement of all the LEDs in a matrix, with a maximum of 8 columns and 8 rows. Please note: when talking of a matrix, this always means the electrical connections. This has absolutely nothing to do with the physical placement of the LEDs later on. When the MAX7219 displays something using a matrix, it only shows one row at a time. This row is configured by switching on or off the segments of this row. The IC then switches to the next configured row and to the next and the next and so on. It does this with up to 800 MHz which is way too fast for the human eye to acutally see and thus it looks like all the rows are lit together. This is called the persistence-of-vision effect and is the foundation of modern display technology.

To form a matrix, we need to form rows and columns. Internally, the IC has eight registers, one for each row. Each register holds the binary state of each segment, an 8 bit number. We want a low complexity in the software so we will arrange the indicators in rows. That way, we only need to write the value for one row to update an indicator. Actually, we will have two indicators per row because we would be wasting pins on the IC. The cathodes of the two indicators in a row are connected together, as are the anodes of the corresponding LEDs of each indicator across the rows. The cathodes form the digit lines, the anodes are the segment lines. An individual LED can be addressed by selecting its digit and its column. This picture does some explanation:

Status monitor indicators arranged as LED matrixAs shown in the picture, segment D and segment H (or DP) are not used. They may later be used to connect a fourth LED to each indicator.

Pics, or it doesn’t exist

Whats describes above in theory can be seen on these pictures in reality. The first shows the schematic done in Fritzing, the other one my real world prototype on a breadboard.

Dude, where’s my LED?

The arrangment of the LEDs as a matrix also comes in handy when writing the software and adressing each indicator. The state of all indicators will be held as several 8-bit numbers, one for each row (and thus for each two indicators). We change the state of an indicator by bit manipulation in either the lower or the upper 4 bits of that number. Example: B00010001 means that the two indicators both show green. If the second one were to switch to red, we would need to put a zero at bit 4 and a one at bit 6 (note: the rightmost bit is bit 0 or the least significant bit).

First, we would need to determine the row in which to find the specified indicator. When the first indicator is assigned the number zero, we can find the row by dividing the indicator index by two (integer division). For indicators 0 & 1 this yields 0, for indicator 2 & 3 this yields 1, and so on. Next step is to find the offset of the indicator within the row. We do this by calculating the modulo of (the index + 1) and 2. When the modulo (which is a remainder division) comes up with the result 0, we know that the second indicator in the row is addressed, when the result is 1, the first indicator is addressed. The LED states of the first indicator start at bit zero, so no offset is required, for the second indicator an offset of 4 is required. Here is the code on how to do this:

The above example introduces some required constants (so that you don’t have to remember if yellow was a 1 or a 4 or something else), then updates the displayState for indicator number 3 (second indicator in second row). The function changeIndicator(which, color)  works exactly as described in the paragraph above. It also contains one additional mechanism not mentioned: it would be too complicated to find out which LED is currently lit in the indicator and switch it off. Instead, the complete indicator is switched off and the desired color switched on. Don’t get confused with the uint8_t type. This is the type same as  byte , but I think it is a little easier to understand because all its properties (8-bit unsigned integer) are contained in the name.

As usual, the files used or mentioned in this post can be obtained from the projects github site: https://github.com/hmbusch/ICMI-ServiceStatusMonitor. The Arduino code is not yet complete and will be made available for the next post.

Alright, enough for this post. Up next: writing a small library to control the MAX7219 and implementing a complete Arduino sketch.

New project: ICMI Service Status Monitor

Monitoring your IT health

Several years ago, a colleague and I discussed the idea of installing a traffic light in the hallway that should signal the overall health of our IT infrastructure. We never got really far with this, but it was a nice idea. Yeah, true, you could just install a monitor in the hallway and show a nice dashboard, but where would be the fun in that? A traffic light is very clear in what it signals, even to non-IT people or managers ;-).

Traffic lights revisited

With physical computing becoming more and more easier, thanks to Arduino, PICAXE and others, we now have the means to revisit this idea of a traffic light and put it into reality. OK, I admit, this project is not really innovative and presumably not really complicated, but I will do it anyway, as an example and also because it will look cool in the hallway once it is done. So here’s the basic idea:

ICMI Status Monitor Logical Overview

Several services are monitored by a custom application on a computer somewhere. This software communicates with an Arduino board via serial link and tells the Arduino what to display on the health monitor. The health monitor itself consists of one or more segments, each capable of mimicking a traffic light, i.e. displaying green, yellow or red. For those with color blindness, the colors use can simply be changed. (This btw. is the reason why Jenkins CI displays blue circles for healthy projects and not green ones).

Segmenting segments

As mentioned, the health display itself will consist of several „traffic light“ segments. For simply monitoring the availability of a service, a single segment is enough. In my case, in addition to knowing that the database is up and running, I also would like some indicator that reflects the current load on the system. For this purpose, I should be able to assign more than one segment to this services, resulting in a finer resolution of the service status.

In addition to the three colors available in hardware, we could get several additional „interpolated“ states as well, e.g. amber as a mix of yellow and red or we could flash the indicator. Perhaps we even might add a fourth color in hardware, e.g. blue. But these are expansion options.

ICMI Status Monitor States explained


I’ve broken the project down into several steps with their own „deliverables“:

  • Lay down the idea and operation basics. This is done in this post.
  • Create a prototype of the display hardware. This step should result in a multi-segment display and an Arduino sketch that can translate commands like setServiceHealth(1, HEALTH_GOOD)  into the corresponding visual indicators.
    • Enable the sketch to control a single segment indicator
    • Enable the sketch to control a multi-segment indicator
  • Enable control of display prototype via serial port. A simple protocol will be created to send update commands to the display over the serial link. For testing purposes, this will be done using the serial monitor of the Arduino IDE.
  • Write control program to test the display from a computer without the Arduino IDE. Now this is the real deal: I will write a Java program that does the communication with the Arduino. The first version will be a simple GUI with some buttons to set the service indicator. The focus of this stage of development lies on the serial communication.
  • Write control program with monitoring API. Using the previous program as a basis, the service control will be extracted into an interface and corresponding service. In addition, the program will receive an API that allows various monitoring services to be implemented against a simple interface.
  • Write monitoring services, e.g. for the database, for Jenkins, etc.
  • Put everything together and make it nice. This is the hardest part 😉 And I already started with this one, not the wisest choice but what’s done is done.

All files related to this project are available on github at: https://github.com/hmbusch/ICMI-ServiceStatusMonitor

And by the way: ICMI of course stands for I can MAKE IT.