Arduino Real PWM vs CPU-PWM

Hi all,

I have read this article

He speaks about using normal digital pins to act as PWM.

I am interested to try this to see if it fits my needs.

I am sure this code would give the Arduino processor a workout!!! So any changes to code would need to keep it efficient as to not ruin the speeds etc…
My method usually is to duplicate entire chunks of code with different variables where I’m pretty sure adding a line or two to the original code would suffice… it’s just my coding skills and understanding is very poor… as to why if I was to go this route I’d want to do it properly

I have some questions.
Using his code on an Arduino Mega.
Would I overload the CPU if I used the standard 15 PWM pins plus created 15 additional digital converted cpu-PWM pins?

What’s code edits are required to expand his single converted PWM into 15 of them…

What is he using, what would I use to talk to said pins…
Currently I command my pwm via analogWrite
What do I need to replace analogWrite with?

Many thanks…

The CPU runs at fixed speed. The only way to 'heat' it, is to draw/sink current from its i/o pins.

To get very low energy consumption.. look at sleep states.

toxsickcity:
Would I overload the CPU if I used the standard 15 PWM pins plus created 15 additional digital converted cpu-PWM pins?

Difficult to tell; I guess that FlexiTimer2 library is using a timer interrupt to handle IO pins to do the PWM, but the amount of time that takes in interrupt is unknown.

You can estimate how much time is being used in interrupts by simply counting over a fixed period in main code and see how the count reduces as you add interrupt overhead
e.g.

// loop and count for one second
// - excessive interrupts will reduce this number
void countsInOneSecond()
{
  uint32_t start= millis();
  uint32_t count=0;

  while( (millis() - start) < 1000 )
    count++;

  Serial.print("Counts in 1000mS= "); Serial.println( count );
}

Call that function and record the count, then add some interrupt overhead (some PWM channels) and see what effect it has on the count. i.e. when the count reduces by 1/2, that means 1/2 of the CPU time is being spent in interrupt. I would not go beyond around 80% of CPU time in interrupt.

Yours,
TonyWilk

@knut

knut_ny:
The CPU runs at fixed speed. The only way to ‘heat’ it, is to draw/sink current from its i/o pins.
To get very low energy consumption… look at sleep states.

Did you reply to the wrong post, because that makes no sense whatsoever.

Depending on what else you’re doing, i’ve run an 8MHz PIC processor with 72 channels of PWM for LEDs. And yes, the CPU was pretty busy!

I did manage a number of sequencing and color-flow patterns with RGB palette mixing in there…

Only 24 of the driven PWM channels are shown… 8x R+G+B LEDs)

I can’t remember the PWM frequency that I managed (years ago), but it certainly wasn’t visible.
The code is pretty straightforward - maintain a counter, and target value for each channel.
Run the channel counters ‘continuously’ and when they reach the target ‘value’, reset them individually.

Hi all,

I don’t understand the code at all.

1:   // AnyPWM by Nick Borko  
2:   // This work is licensed under a Creative Commons  
3:   // Attribution-ShareAlike 3.0 Unported License  
4:    
5:   // Manually do PWM using FlexiTimer2  
6:   // (http://www.arduino.cc/playground/Main/FlexiTimer2)  
7:   #include <FlexiTimer2.h>  
8:    
9:   // LED to pulse (non-PWM pin)  
10:  #define LED 13  
11:    
12:  // Period of the PWM wave (and therefore the number of levels)  
13:  #define PERIOD 256  
14:    
15:  namespace AnyPWM {  
16:   extern volatile byte pinLevel[12];  
17:   void pulse();  
18:   void analogWrite(byte pin, byte level);  
19:   void init();  
20:  }  
21:    
22:  // Variables to keep track of the pin states  
23:  volatile byte AnyPWM::pinLevel[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };  
24:    
25:  // Set a digital out pin to a specific level  
26:  void AnyPWM::analogWrite(byte pin, byte level) {  
27:   if (pin > 1 && pin < 14 && level >= 0 && level < PERIOD) {  
28:    pin -= 2;  
29:    AnyPWM::pinLevel[pin] = level;  
30:    if (level == 0) {  
31:     digitalWrite(pin + 2, LOW);  
32:    }  
33:   }  
34:  }  
35:    
36:  // Initialize the timer routine; must be called before calling  
37:  // AnyPWM::analogWrite!  
38:  void AnyPWM::init() {  
39:   // (PERIOD * 64) Hertz seems to be a high enough frequency to produce  
40:   // a steady PWM signal on all 12 output pins  
41:   FlexiTimer2::set(1, 1.0/(PERIOD * 64), AnyPWM::pulse);  
42:   FlexiTimer2::start();  
43:  }  
44:    
45:  // Routine to emit the PWM on the pins  
46:  void AnyPWM::pulse() {  
47:   static int counter = 0;  
48:   for(int i = 0; i < 12; i += 1) {  
49:    if (AnyPWM::pinLevel[i]) {  
50:     digitalWrite(i + 2, AnyPWM::pinLevel[i] > counter);  
51:    }  
52:   }  
53:   counter = ++counter > PERIOD ? 0 : counter;  
54:  }  
55:    
56:  void setup() {  
57:   AnyPWM::init();    // initialize the PWM timer  
58:   pinMode(LED, OUTPUT); // declare LED pin to be an output  
59:  }  
60:    
61:  byte brightness = 0;  // how bright the LED is  
62:  byte fadeAmount = 5;  // how many points to fade the LED by  
63:    
64:  void loop() {  
65:   // set the brightness of the LED:  
66:   AnyPWM::analogWrite(LED, brightness);  
67:    
68:   // change the brightness for next time through the loop:  
69:   brightness = brightness + fadeAmount;  
70:    
71:   // reverse the direction of the fading at the ends of the fade:   
72:   if (brightness == 0 || brightness == 255) {  
73:    fadeAmount = -fadeAmount;  
74:   }  
75:   // wait for 30 milliseconds to see the dimming effect  
76:   delay(30);  
77:  }

The only things in this code that look familiar at all, is the following 3 parts.

*#define LED 13… is on pin 13… So he is using the 13th pin as a pwm

*AnyPWM::analogWrite … is what he is using instead of analogWrite, so I would use this as analog write on the NON PWM pins

*brightness = brightness + fadeAmount;
I’ve seen this code used to fade LEDs count less times, I am familiar here.

I wouldn’t know where to begin adding a 2nd or 3rd PWM to the code except for the simple stuff

Can someone please help me, I have high interest here and it might solve a few things.

#define LED 13
If I was to change that part to add additional 3 pwm

#define LED 13
#define LED 12
#define LED 8
#define LED 7

And added 3 more AnyPWM

AnyPWM::analogWrite
AnyPWM2::analogWrite
AnyPWM3::analogWrite
AnyPWM4::analogWrite

Can anyone help me with the part of the code which runs the PWM…

I don’t want to copy and paste the code over and over making it inefficient.
I need to know the efficient way of making the code do more as is.

I can create my own fades I’ve done that before.

Thank you
Shaun

EDIT: do I need to edit FlexiTimer2.h ?