Suffice it to say, an early criticism of mine from Part 1 was a lack of decent documentation for the board itself. Oh how I'm forced to eat my words as I realize that there actually is a perfectly good board manual from Infineon that you can grab from here. To be completely fair, I have gone back and added the link for it back into Part 1 - but as to why I didn't find it when I was doing my searches still remains a mystery.

 

The manual itself fully details the board's design topology, capabilities, but more importantly, the I2C command-set and the parameter optimizations necessary to match the driver to your LEDs.

 

The Board Topology

 

The board itself uses a buck converter architecture, but the actual details as to its implementation only become clear with further examination of the board manual. In this posting, I will excerpt many relevant block diagrams from the manual - these are made by Infineon.

Channel-Schematic.PNG

Each channel has a topology as shown above, somewhat simplified. The top part forms the current freewheel loop, with a sense resistor to ground and a MOSFET to control the on-part of the cycle and provide feedback. The current control loop has a counter which controls the off time and can be configured, and the reference current value can be configured to accommodate different forward current needs. A sigma delta block generates the pulse-density modulation which is combined to drive the MOSFET.

Ripple-Output.PNG

Because of this control loop, there is a problem of stability and propagation delay - which is why some optimization is required to ensure the best results (i.e. less overshoot, lower ripple).

 

Measuring the Current Waveform and Optimizing the LEDs

 

I had initially just loaded the sample sketch, thinking that it was all "safe values" and there won't be anything bad. After some closer inspection, I saw the current value was set to 0x80 for a value of 780mA. Yikes. Don't just blindly load the sketch if your LEDs aren't capable! That is what got me onto the whole line of optimization and current waveform measuring.

 

The whole of Chapter 6 of the board manual covers the optimization process and is well worth a read to ensure you aren't overstressing your LEDs or the board itself, and you minimise the ripple current. You will need an oscilloscope with a current probe but you might be able to get away with something less. The optimizations need to be performed on a channel by channel basis, and will result in different values for different input voltages, and LEDs. There is a reference table of values, if you are using the modules they have, although that is somewhat unlikely.

 

Of course, part of the optimization process involves setting a given colour channel to fully on. You can use RGBLEDS.SETCOLOR, but be warned, as red and blue are the expected values, green is not 0x0fff for the green channel! It took me a moment of going through the library to work out that you need to use Lime if you want 0x0fff on the green. Alternatively, you can just directly specify the R, G, B values, with a dimming value of 0x0fff to ensure they get passed "as is" to the channel.

Green-Lime.PNG

Of course, to do the optimization, you will need to have a current probe and an oscilloscope. I decided to use the Picoscope 2205A that I had been awarded in a prior RoadTest as the oscilloscope.

 

In a hack, I grabbed a spare 0.1 ohm wire-wound resistor from the shelf and added some terminal connector blocks to it. I'm sure the more experienced guys will be jumping up and down right now going don't do that - and I know what you're thinking. I just had to do it for myself to see why.

20150216-1018-3622.jpg

For those who haven't had the lightbulb moment, the problem is that wire-wound resistors are themselves inductive and will severely affect the operation of the circuit by adding inductance to the system. Also, not to mention, the thing has 10% tolerance for values. Initially, I thought that it would only induce a small error into the result, and it would be better to get a reading than none. I filmed a whole video, and in it, we get rather strong ripples and strange behaviour. I didn't expect it to be that bad. This is a frame grab from the original video.

Inductive-R.png

Of course, there was no way the shield was performing this poorly after optimization. I really needed to get a non-inductive shunt of some sort. I scoured my room for some composition resistors, and I found 11 metal film type 1.1 ohm 1% precision resistors. Whacking them all in parallel for another ugly hack, and we have a 0.1 ohm shunt with a (likely) <1% tolerance (statistically speaking).

20150216-1511-3623.jpg

If you looked at the topology above, you might just think "why not measure across the feedback sense resistor?" The thought did occur to me, but there's actually an issue. If you look at the PCB itself, the sense resistor is paralleled with a capacitor to smooth out transients and stabilize the feedback system. As a result, it's not possible to capture the ripples accurately if you use the feedback resistor, and you won't capture the freewheeling current part of the cycle either.

 

There's another complication with measurement as well - as the Infineon's power supply ground is connected to the Arduino ground, and the Arduino ground's connected to the USB ground, and the USB ground is connected to the Picoscope's ground, to perform the measurement would require using ground as the ground, and measuring one side of the resistor with Ch A, the other with Ch B and doing the subtraction, multiplication (for scaling) to get your values. This is possible, but not my favourite way.

 

I decided to get lazy, knowing the potential difference is 12v with 2A current (from the limited power supply), so I used a laptop with the PicoScope, unplugged from the mains, and not plugged into the Arduino either, so it was operating floating. I connected the ground of the Ch A to the 12v + side of the LED drive, and the negative side to the other side of the sense resistor so it would read an inverted value. This was done purely out of habit - I could have hooked it up the other way, but I generally like having either + or - as a ground, rather than an intermediate node. I set up the Math channels to read -10*A to provide the current in Amps.

 

In fact, it was such an interesting experiment on its own that I spent the time to recreate the video with the less-inductive resistors after I had spent a few hours uploading the first one with the inductive resistor problem. This one is a little more concise, but leads you through the optimization process and provides some basic measurements of waveform frequency and modulation which is related to flicker. I hope you enjoy, and it comes in useful. You might want to view this one full-screen so you can read the values.

 

After I had hand optimized the channels, I made a few discoveries which corroborate well with the lessons taught by the manual. For one, if your input voltage is > 4x the voltage drop of the LED, you will have difficulty achieving good ripple performance. This was an issue to some extent on the red channel, where according to the datasheet, my LED was specified for 2.5v typical forward voltage drop at 1000mA (less for 700mA of course). The values I got for the green and blue channels were fairly similar, and on checking, their forward voltage must have been as well with the green specified for 2.7 to 4.25v at 700mA, and the blue specified for 3.3v typical at 1000mA. The final measured ripple values were about 30-50mA, which corresponds to a ripple percentage of 4% to 7% which is generally considered good! I suppose 12v would better suit pairs of these LEDs in series.

 

The shield is capable of driving almost any LED current value up to 700mA, but because of the ripple, it's not advisable to use any LED with less than a 350mA forward current rating, as the maximum current could be exceeded during optimization to the point of damage. Safe values from the datasheet are actually lower than the ones in the sketch, so it may pay to replace the values in the sketch with the ones in the manual first before trying it out.

 

All in all, I was able to show that the worst case flicker is a 1khz flicker at the lowest brightness - well above the flicker fusion threshold. The ripple from the buck topology was reduced to nearly insignificant levels, and itself cycles at 2.2Mhz which is exceptionally high.

 

The Command-Set

 

Thanks to finding the board manual, we have a full description of the command set on this board. Importantly, many of the commands are more advanced direct-register access, pertain to the DMX bus which is not fitted by default, or are about reading values from the shield which you really don't need to have. This reduces the commands we need to know about to just a short list - excerpted from the Infineon Board Manual.

Command-List-Excerpt.PNG

In fact, you probably don't even need the first three, as INTENSITY_RGB can perform the same function. WALKTIME, DIMMINGLEVEL, FADERATE are global to all channels. CHANGEADDRESS is only necessary if you wish to run several boards on the same I2C bus, or you have a conflict of address for some reason. Full details are in the board manual, of course.

 

The global dimming level function deserves a little mention here - it's an interesting function because it's exponentially weighted, and it affects all channels at once, allowing you to keep a constant colour while reducing the brightness by scaling each of the channels by the global dimming value / 4095, so you don't have to do it by yourself.

Global-Dimming.PNG

Another nice function is the walk-time which allows you to set the amount of time, in 0.01024 second units, that the board takes to transition to the next colour value.

Walk-Colour.PNG

 

Library and Sketch Clean-Up

 

After examining the command set, there doesn't really seem to be much of a need ever to actually read anything back from the shield via I2C unless you plan on doing read-modify-write style operations. To simplify operation, we can live with just using write based commands to set the values required - the main values being for INTENSITY_RGB, FADERATE, DIMMINGLEVEL, WALKTIME, OFFTIME_RED, OFFTIME_GREEN, OFFTIME_BLUE and CURRENT_RGB. I've ignored the fact that the shield itself does also accept values for overwriting the NVRAM defaults which might save you from reprogramming the one-off parameters (i.e the last four that I listed).

 

The example code provided seems to handle all reads by dumping the result to the serial port - this is why the Serial.begin(9600) command is invoked in setup. Ideally, I'd like to free the serial port in case I needed it - say to push RGB+Walk+Fade+Dim values to the Uno via the USB port.

 

The first step was to open Infineon.cpp and comment out (by preceeding with //) the lines that invoke Serial functions. Those are line #'s 209-212, 266-269, 395-398. Additionally, line #2 which states #include <Arduino.h> can also be commented out now that Serial is no longer needed. Once that is done (I've attached a copy to this post), then you don't have to invoke Serial.begin(9600) if you don't want to have the serial port, and or otherwise use it solely for your own purposes.

 

The next thing was to clean up the sketch. It's not the easiest to read, as I've stripped out most to all comments (as I don't like clutter) and I have particularly oddball styling which is a carry-over from my CS days, but I've removed needless initializations and created a new function setLEDColour and rangeClip which allow me to set the LED colour, fade, walk and dim values by invoking a single command, and it filters for out of range conditions (also attached).

 

#include <Infineon.h>

#include <Wire.h>

 

Infineon RGBLEDS = Infineon();

 

void setup() {               

    Wire.begin();

    while (RGBLEDS.on != 1) {

      RGBLEDS.I2CWRITE2BYTES (ADDRESS, FADERATE, 0x0000);

      RGBLEDS.I2CWRITE2BYTES (ADDRESS, DIMMINGLEVEL, 0x0000);

      RGBLEDS.on = RGBLEDS.I2CREAD(ADDRESS, READ_DIMMINGLEVEL);

      if (RGBLEDS.message == 1 && RGBLEDS.on == 0) {

        RGBLEDS.message = 0;

        RGBLEDS.on = 1;

      }

    }

    RGBLEDS.I2CWRITE2BYTES (ADDRESS, OFFTIME_RED, 0x10);

    RGBLEDS.I2CWRITE2BYTES (ADDRESS, OFFTIME_GREEN, 0x06);

    RGBLEDS.I2CWRITE2BYTES (ADDRESS, OFFTIME_BLUE, 0x06);

    RGBLEDS.I2CWRITE6BYTES (ADDRESS, CURRENT_RGB, 0x60, 0x5E, 0x5A);

    RGBLEDS.I2CWRITE2BYTES (ADDRESS, FADERATE, 0x0000);

    RGBLEDS.I2CWRITE2BYTES (ADDRESS, WALKTIME, 0x0000);

    RGBLEDS.I2CWRITE6BYTES (ADDRESS, INTENSITY_RGB, 0x0555, 0x0555, 0x0555);

    RGBLEDS.I2CWRITE2BYTES (ADDRESS, DIMMINGLEVEL, 0x0FFF);

    RGBLEDS.I2CWRITE6BYTES (ADDRESS, INTENSITY_RGB, 0x0, 0x0, 0x0);

    delay(500);   

}

 

void loop() {

   // Set random R,G,B value, Walk 1s, No Fade, No Dimming, Every 3s

   setLEDColour(random(0,4096), random(0,4096), random(0,4096), 97, 0, 4096);

   delay(3000);    

 

void setLEDColour (int r, int g, int b, int walk, int fade, int dim) {

    r=rangeClip(r);

    g=rangeClip(g);

    b=rangeClip(b);

    walk=rangeClip(walk);

    fade=rangeClip(fade);

    dim=rangeClip(dim);

    RGBLEDS.I2CWRITE2BYTES (ADDRESS, FADERATE, fade);  

    RGBLEDS.I2CWRITE2BYTES (ADDRESS, DIMMINGLEVEL, dim);

    RGBLEDS.I2CWRITE2BYTES (ADDRESS, WALKTIME, walk);

    RGBLEDS.I2CWRITE6BYTES (ADDRESS, INTENSITY_RGB, r, g, b);

    return;

}

 

int rangeClip (int value) {

  if (value > 4095) {

    value = 4095;

  } else if (value < 0) {

    value = 0;

  }

  return (value);

}

 

I did discover something strange which pertains to unreliable or inconsistent shield operations if certain lines are removed - specifically in setup():

RGBLEDS.I2CWRITE6BYTES (ADDRESS, INTENSITY_RGB, 0x0555, 0x0555, 0x0555);

RGBLEDS.I2CWRITE6BYTES (ADDRESS, INTENSITY_RGB, 0x0, 0x0, 0x0);

 

These two lines really don't seem to do anything critical as they set the output brightness values, before setting the dimming level and after setting the dimming level - however, I have discovered that removing them will result in inconsistent shield operation where reloading a sketch on the Arduino results in no light output or only certain RGB values working. A power cycle restores the operation but doesn't allow for sketch reloading otherwise you get the strange result again. Leaving these lines in, however, seems to cure the issue and I'm not entirely sure as to why. In the interests of having it work, I'm not going to tinker with it any more.

 

Needless to say, now I have a colour changing desk lamp which changes colour every 3 seconds to a random colour with a 1 second "transition" period (value 97 * 0.01024 = 0.99328s). I added a pad of white gauze over the LEDs which makes the colour mix a little better but does cut down on the light significantly. I might need to find some opalescent perspex or something better ...

20150216-1927-3624.jpg20150216-1927-3627.jpg

20150216-1927-3628.jpg

 

Conclusion

 

Sometimes, tinkering with things can get addictive, and you just can't put it down even when you should. The whole issue of ripple current and actual current in buck converter topology, and the modulation waveform had been an intriguing element, which has been well documented in the Infineon Board Manual, but I felt that I really needed to delve into it on my own. In the process, I discovered, and performed the relevant optimizations required to match the shield to my LEDs, and further understood why there were some matching issues.

 

Further delving into the manual gave me a better understanding of the command-set available, and just how few of these commands really matter. By cleaning up the library and wrapping some code in as a basic function, I have prepared myself better (as far as my experience goes) into allowing some sort of computerized control. In the end, I didn't end up bothering implementing computerized control on the Uno, although it should be as easy as writing a simple Serial command receiver, instead just relying on the Arduino to produce some random RGB values and write them into the shield to make a colour-changing lamp (3 second change interval, 1 second fades between colours).

 

Thanks for reading - the next part will probably deal with the Arduino Yun, when time permits.

---

Feel free to visit me at my personal blog at http://goughlui.com