SoftPWM library

Hi,

I’m using the softPWM library from Bhagman ( http://arduino.cc/forum/index.php/topic,19451.msg142425.html#msg142425 , read-only )

I want to control a basic RGB led strip from Dealextreme cut in 3 parts. I use PWM output to command a couple of ULN2003.

I made some test with the full strip but since I want to put it at the back of my monitor, I cut it in 3 part and I need 9 PWM outputs. My arduino have just 6 of them.

My code is ok, but now that is tapped behind my monitor, the refresh frequency seems to be to low, like old monitor at 60Hz.

Can we have higher frequency with softPWM ?

I tried to change the beginning of SoftPWM.cpp but I doesn’t seems to change anything

#if F_CPU
#define SOFTPWM_FREQ 60UL
#define SOFTPWM_OCR (F_CPU/(8UL*256UL*SOFTPWM_FREQ))
#else
// 130 == 60 Hz (on 16 MHz part)
#define SOFTPWM_OCR 130
#endif

with

#if F_CPU
#define SOFTPWM_FREQ 120UL
#define SOFTPWM_OCR (F_CPU/(8UL*256UL*SOFTPWM_FREQ))*2
#else
// 130 == 60 Hz (on 16 MHz part)
#define SOFTPWM_OCR 130*2
#endif

Here is my code

#include <SoftPWM.h>

int pin1[] = { 5 , 3 , 4 };
int pin2[] = { 8 , 7 , 9 };
int pin3[] = { 10 , 12 , 13 };

int current [3] = { 100 , 0 , 0 };
int target [3] ;

void randomize( int r[] )
{
  for( int x = 0 ; x < 3 ; x++ )
  {
    r[x] = random( 100 );
  }
}


void setup()
{
  SoftPWMBegin();
  
  pinMode(0, INPUT);  
  
  randomSeed(analogRead(0));

  randomize( target ) ;

  afficheCouleur( current );
  
  int dureeTest = 500 ;
  
  delay( dureeTest );
  current[0] = 0 ; current[1] = 100 ;
  afficheCouleur( current );
  delay( dureeTest );
  current[1] = 0 ; current[2] = 100 ;
  afficheCouleur( current );
  delay( dureeTest );
  
}

void afficheCouleur( int color[3] )
{
  for( int x = 0 ; x < 3 ; x++ )
  {
    SoftPWMSetPercent(pin1[x], color[x]);    
    SoftPWMSetPercent(pin2[x], color[x]);    
    SoftPWMSetPercent(pin3[x], color[x]);    
  }
}

void loop()
{
  // Si la couleur cible est égale à la couleur courante, on attend X secondes et on la change 
  if( current[0] == target[0] && current[1] == target[1] && current[2] == target[2] )
  {
    randomize( target ) ;
    delay( 5000 );
  }

  // On prend prend chaque composante R,G et B et on la rapproche de la couleur cible  
  for( int x = 0 ; x < 3 ; x++ )
  {
    if( current[x] < target[x] )
    {
      current[x]++;
    }
    else if( current[x] > target[x] )
    {
      current[x]-- ;
    }
  }
  
  afficheCouleur( current );
  
  delay( 500 );
}

In SoftPWMBegin() try changing:

  TCCR2B = (1 << CS21);         // start timer (ck/8 prescalar)

to

  TCCR2B = (1 << CS20);         // start timer (ck/1 prescalar)

This will cause the timer2 interrupt the library uses to be called at 8 times the frequency - however I think that means it will consume all the CPU…

You might want to simply change SOFTPWM_OCR to about 40 or so (smaller is faster BTW) - comment out the conditional #defines and replace by just

#define SOFTPWM_OCR 40

If that hogs all the CPU increase the value until it copes.

There are much better techniques to generate PWM for LEDs than constant frequency constant duty-cycle - SoftPWM is needing 256 interrupts per cycle of output and each interrupt takes 200 cpu cycles - over 3ms of cpu - so that the max theoretical PWM frequency is 300Hz or so. Its not hard to do lots better with dithering techniques.

#define SOFTPWM_OCR 40

Hi, thank you very much, this look nice enough with this change.

I will take a look at the dithering technique if I need to relaese some CPU with another project :)

Thx