Lambolico Posted August 17, 2012 Report Share Posted August 17, 2012 (edited) Hello, I'm planning to build a dj midibox controller. I'm just at design's first stage. I have this quick question which I couldn't answer looking at the web or forums. Can DOUT module provide PWM led brightness control? Or do I have to use the AOUT module instead of PWM? Best Regards. Edited August 17, 2012 by Lambolico Quote Link to comment Share on other sites More sharing options...
bill Posted August 18, 2012 Report Share Posted August 18, 2012 I guess it depends of the different levels of intensity you want to get, but i'm sure you can 'dim' a led pretty easily, with a simple DOUT module, by powering the led at different short intervals. And in the end it would be much easier than using a AOUT module ! Quote Link to comment Share on other sites More sharing options...
Lambolico Posted August 18, 2012 Author Report Share Posted August 18, 2012 Thanks Bill. I plan to drive some RGB leds and get a few more colors other than red, green and blue. So a great dim resolution is not required. Quote Link to comment Share on other sites More sharing options...
nebula Posted August 19, 2012 Report Share Posted August 19, 2012 Depending on how much coding you don't want to do, another option is to use more than one DOUT pin connected to each LED, through different values of current-limiting resistors. Not as economical, but probably easier to code (and no flickering) Quote Link to comment Share on other sites More sharing options...
Lambolico Posted August 21, 2012 Author Report Share Posted August 21, 2012 Coding is not a problem. But flickering is! I thought that using a pwm frequency high enough it wouldn't be noticed. Isn't it? Quote Link to comment Share on other sites More sharing options...
Hawkeye Posted August 21, 2012 Report Share Posted August 21, 2012 If it is high enough, it won´t be noticed by the human eye, but certain camcorders/webcams can be affected by it, when both pwm and cam run at fixed "frame" rates, it creates interference, kind of a "moiré effect" over time, hard to explain :) Quote Link to comment Share on other sites More sharing options...
Lambolico Posted August 21, 2012 Author Report Share Posted August 21, 2012 (edited) If it is high enough, it won´t be noticed by the human eye, but certain camcorders/webcams can be affected by it, when both pwm and cam run at fixed "frame" rates, it creates interference, kind of a "moiré effect" over time, hard to explain :) Yeah, I know what you mean, but I'm not going to care about how cameras see my midibox :) On the other hand is this (Next time I'll do my homework better!): http://www.midibox.org/dokuwiki/doku.php?id=questions_and_answers#can_i_use_pwm_to_control_individual_led_brightness The short answer is that using PWM on DOUT to do individual brightness control on a large number of LEDs is not possible as it would overload the Core. However, I suppose this was written with the PIC core in mind. Is this also a problem with the LPC17 core? Thank you all. Edited August 21, 2012 by Lambolico Quote Link to comment Share on other sites More sharing options...
Hawkeye Posted August 22, 2012 Report Share Posted August 22, 2012 (edited) Interesting! If it was a problem for the old core, it is likely still a problem for the new one and a specialized led driver ic is recommendable - as the processing power has risen, but not by magnitudes.... What I don´t understand is, why are 10khz update rates necessary to achieve "flicker-free" 3 bit pwm brightness? Say, a human eye regards illuminated->non-illuminated pattern changes with a 100hz refresh rate as flicker-free... The darkest illumination pattern for 3 bit brightness would be: on off off off off off off off -> cycle Then, all eight steps should happen within a 1/100th second timeframe to be perceived as flicker-free. So, the individual pulse pattern steps should cycle at 800hz, not with 10khz? Without further inspection, I guess this should be possible even on an old Core8... But me iz probably missing a key point somewhere, maybe someone can enlighten us... :-) Many greets, Peter Edited August 22, 2012 by Hawkeye Quote Link to comment Share on other sites More sharing options...
sneakthief Posted August 22, 2012 Report Share Posted August 22, 2012 Seems Arduino uses 490-500Hz for PWM: http://arduino.cc/en/Reference/analogWrite http://neuroelec.com/2011/03/high-pwm-frequency-for-led-good-or-bad/ Quote Link to comment Share on other sites More sharing options...
Duggle Posted August 22, 2012 Report Share Posted August 22, 2012 (edited) Yes, it is possible to implement PWM on a Core32 on any number of LED's with absolutely negligible CPU overhead. In terms of performance, the frequency of PWM is 1/(NumberLevels*DoutPeriod) . With the standard 1ms DOUT refresh rate and 8 brightness levels gives 1/(8*0.001)=125Hz NumberLevels does not include OFF so this example may be considered as 9 levels. The method involves a 2 dimensional array: think of it as DoutArray[ PageIndex][LEDIndex] The DMA interrupt routine simply increments PageIndex 0 to 7each interrupt. The DMA process automagically shifts out the LEDIndex values to the DOUT chain. Of course when a LED has it's brightness changed there are a number of array accesses executed by the write function. These can be done in a low priority task, however probably not even necessary. When there is no change there is no CPU load. With this scheme it is beneficial to used PDM (Pulse Density Modulation) this means distributing the on/offs across the cycle e.g 50% brightness is 0x0x0x0x rather than 000xxxx etc,etc. It results in less possibility of perceptable flicker. In fact here is the thread that explored this idea. (I have code I can share if anyone is interested) Edited August 22, 2012 by Duggle Quote Link to comment Share on other sites More sharing options...
Lambolico Posted August 24, 2012 Author Report Share Posted August 24, 2012 Those are good news for me :) I plan to drive 100-150 leds, no need to extra hardware is nice. I will ask for your code when I get into the software stage. Thank you all. Quote Link to comment Share on other sites More sharing options...
Duggle Posted August 24, 2012 Report Share Posted August 24, 2012 Those are good news for me :) I plan to drive 100-150 leds, no need to extra hardware is nice. I will ask for your code when I get into the software stage. Thank you all. If using RGB Leds, I suggest that you experiment with the different value of R,G, and B current limiting resistors before soldering 100's of resistors for LEDs. I think the sensitivity/brightness of the Red, Green, Blue is usually not matched. With, for example, only 8 levels of brightness digitally, it is best if you can normalize the RGB colour balance with the resistors. Basically with all RGB LED's "on" you want to see pure "white"! I'll post the code to this thread in a day or two. (I don't have access ATM). Quote Link to comment Share on other sites More sharing options...
Lambolico Posted August 25, 2012 Author Report Share Posted August 25, 2012 If using RGB Leds, I suggest that you experiment with the different value of R,G, and B current limiting resistors before soldering 100's of resistors for LEDs. I think the sensitivity/brightness of the Red, Green, Blue is usually not matched. With, for example, only 8 levels of brightness digitally, it is best if you can normalize the RGB colour balance with the resistors. Basically with all RGB LED's "on" you want to see pure "white"! I'll post the code to this thread in a day or two. (I don't have access ATM). Thanks for the advice! The code will sure be welcome. Quote Link to comment Share on other sites More sharing options...
Duggle Posted September 15, 2012 Report Share Posted September 15, 2012 (Unfortunately) there are changes to MIOS32 files necessary (albeit minor changes) but allow for compatibility by using mios32_config.h switches: The modified mios32 files are attached below. I've highlighted the changes in this post for explanation. They consist of dout driver modification (mios32_srio.c,.h) and array access (mios32_dout.c,h). The application specific layer above this e.g void SetLed(u32 LedIndex, u32 Level) is written by you! #define MIOS32_USE_PAGED_DOUT #define DOUT_NUM_BUFPAGES 4 This means that 4 pages are used e.g an LED may be off, or have a brightness of 1,2,3 or 4. In mios_srio.h (file is attahced) the array is declared: #ifdef MIOS32_USE_PAGED_DOUT extern volatile u8 mios32_srio_dout_bufpages[DOUT_NUM_BUFPAGES][MIOS32_SRIO_NUM_SR]; #endif mios32_srio.c (file is attached with this post ) for reference I'll highlight the changes here: Define two dimensional array: #ifdef MIOS32_USE_PAGED_DOUT volatile u8 mios32_srio_dout_bufpages[DOUT_NUM_BUFPAGES][MIOS32_SRIO_NUM_SR]; #endif ... // inside s32 MIOS32_SRIO_Init(u32 mode) array is initialised: for(i=0; i<MIOS32_SRIO_NUM_SR; ++i) { #ifdef MIOS32_USE_PAGED_DOUT for(j=0;j<DOUT_NUM_BUFPAGES;++j) mios32_srio_dout_bufpages[j]=0; #endif mios32_srio_dout = 0x00; // passive state (LEDs off) mios32_srio_din = 0xff; // passive state (Buttons depressed) mios32_srio_din_buffer = 0xff; // passive state (Buttons depressed) mios32_srio_din_changed = 0; // no change } Now the guts of it all in s32 MIOS32_SRIO_ScanStart(void *_notify_hook) where the next page is indexed, and it's address loaded into the DMA process: current_bufpage=(++current_bufpage)%DOUT_NUM_BUFPAGES; //roll through page range u8 *dout_address = (u8 *)&mios32_srio_dout_bufpages[current_bufpage][0]; //set pointer // start DMA transfer MIOS32_SPI_TransferBlock(MIOS32_SRIO_SPI, dout_address, (u8 *)&mios32_srio_din_buffer[0], MIOS32_SRIO_NUM_SR, MIOS32_SRIO_DMA_Callback); Now in mios32_dout.h the paged array access functions are dedclared (for some reason I included NR (not bit reversed) versions of these functions as well): extern s32 MIOS32_DOUT_SRSet_Paged(u32 pg, u32 sr, u8 value); extern s32 MIOS32_DOUT_SRGet_Paged(u32 pg, u32 sr); extern s32 MIOS32_DOUT_SRSet_Paged_NR(u32 pg, u32 sr, u8 value); extern s32 MIOS32_DOUT_SRGet_Paged_NR(u32 pg, u32 sr); The paged array access functions as they appear in mios32_dout.c: #ifdef MIOS32_USE_PAGED_DOUT s32 MIOS32_DOUT_SRGet_Paged(u32 pg, u32 sr) { // check if SR available if( sr >= MIOS32_SRIO_NUM_SR ) return -1; return mios32_dout_reverse_tab[mios32_srio_dout_bufpages[pg][MIOS32_SRIO_NUM_SR - sr - 1]]; } s32 MIOS32_DOUT_SRSet_Paged(u32 pg, u32 sr, u8 value) { // check if SR available if( sr >= MIOS32_SRIO_NUM_SR ) return -1; mios32_srio_dout_bufpages[pg][MIOS32_SRIO_NUM_SR - sr - 1]=mios32_dout_reverse_tab[value]; return 0; } // NON REVERSED (range check on SR also removed) s32 MIOS32_DOUT_SRGet_Paged_NR(u32 pg, u32 sr) { return mios32_srio_dout_bufpages[pg][MIOS32_SRIO_NUM_SR - sr - 1]; } s32 MIOS32_DOUT_SRSet_Paged_NR(u32 pg, u32 sr, u8 value) { mios32_srio_dout_bufpages[pg][MIOS32_SRIO_NUM_SR - sr - 1]=value; return 0; } #endif So now the more application specific part you have to write for yourself for example: void SetLed(u32 LedIndex, u32 Level) would copy a bit pattern into the pages at LedIndex according to Level. These routines can be used to drive matrix arrays by having a column/row mask on each page. This can be combined with PWM/PDM values as well for e.g RGB full colour array! Please note these modified files need to replace the existing ones. The mios32_config.h config switches mean that other applications will compile and run as before. Take care that you merge any changes (although unlikely) to these mios32 files. Perhaps Thorsten can suggest a better way of managing this? mios32_srio.h mios32_srio.c mios32_dout.h mios32_dout.c Quote Link to comment Share on other sites More sharing options...
TK. Posted September 16, 2012 Report Share Posted September 16, 2012 The best way would be if you would merge your changes into the official branch! :) They are selected via #ifdef anyhow, so that the danger is low that it disturbs an existing function. Best Regards, Thorsten. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.