My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
SoftPWMLibraryDocumentation  
Arduino/Wiring SoftPWM Library.
Updated Feb 13, 2012 by rogue.bh...@gmail.com

Arduino/Wiring SoftPWM Library



What's New?

Version 0005:

  • Fixed Arduino 1.0 mess.
  • Added Polarity control.
  • Up to 20 channels can be defined.

Download

SoftPWM Library - Latest Version

Installation

See: InstallingArduinoLibraries

Description

An Arduino and Wiring Library to produce PWM signals on any arbitrary pin.

It was originally designed for use controlling the brightness of LEDs, but could be modified to control servos and other low frequency PWM controlled devices as well.

It uses a single hardware timer (Timer 2) on the microcontroller to generate up to 20 PWM channels.

Features

  • Arbitrary output pins.
  • Up to 20 different channels can be created.
  • True zero level, i.e. off = off
  • Separate fade rates for on and off.

Notes:

This library hasn't been tested with servos, so beware that it may not work as you may expect if used to control servos.

Usage Example

#include <SoftPWM.h>

void setup()
{
  // Initialize
  SoftPWMBegin();

  // Create and set pin 13 to 0 (off)
  SoftPWMSet(13, 0);

  // Set fade time for pin 13 to 100 ms fade-up time, and 500 ms fade-down time
  SoftPWMSetFadeTime(13, 100, 500);
}

void loop()
{
  // Turn on - set to 100%
  SoftPWMSetPercent(13, 100);

  // Wait for LED to turn on - you could do other tasks here
  delay(100);

  // Turn off - set to 0%
  SoftPWMSetPercent(13, 0);

  // Wait for LED to turn off
  delay(500);
}

Function Descriptions

SoftPWMBegin([defaultPolarity])

  • Initializes the library - sets up the timer and other tasks.
  • optional defaultPolarity allows all newly defined pins to take on this polarity.
    • Values: SOFTPWM_NORMAL, SOFTPWM_INVERTED

SoftPWMSet(pin, value)

  • pin is the output pin.
  • value is a value between 0 and 255 (inclusive).

SoftPWMSetPercent(pin, percent)

  • pin is the output pin.
  • percent is a value between 0 and 100 (inclusive).

SoftPWMSetFadeTime(pin, fadeUpTime, fadeDownTime)

  • pin is the output pin.
  • fadeuptime is the time in milliseconds that it will take the channel to fade from 0 to 255.
    • Range: 0 to 4000
  • fadedowntime is the time in milliseconds that it will take the channel to fade from 255 to 0.
    • Range: 0 to 4000

SoftPWMSetPolarity(pin, polarity)

  • pin is the output pin.
  • polarity is the polarity for the given pin.

Notes

  • You can use ALL in place of the pin number to have the function act on all currently set channels.
    • e.g. SoftPWMSetFadeTime(ALL, 100, 400) - this will set all created channels to have a fade-up time of 100 ms and a fade-down time of 400.
  • The polarity setting of the pin is as follows:
    • SOFTPWM_NORMAL means that the pin LOW when the PWM value is 0, whereas SOFTPWM_INVERTED indicates the pin should be HIGH when the PWM value is 0.

Demonstrations


Arduino Duemilanove LED Blink example - available as library example:


rDuino LEDHead Bounce example - available as library example:


More demos:

http://www.youtube.com/view_play_list?p=33BB5D2E20609C52


Comment by danielf...@gmail.com, Dec 30, 2010

I tried and read your code: Seems you can optimize the ISR for speed a lot by using pointers and not using arrays: Arrays use a multiplication in the indexing slowing down the search An efficiency is achievd by doing:

softPWMChannel & currchannel = softpwm_channelsi?;
if (currchannel.fadeuprate > 0 || currchannel.fadedownrate > 0)
{
// we want to fade to the new value

etc another idea would be a pointer to the beginning of the array for (softPWMChannel currchannel = &softpwm_channels0?; and even having a pointer to the base saved somewhere...

Danny

Comment by chiv...@gmail.com, Mar 17, 2011

I downloaded and installed the library. When I verify the code it says "softpwmbegin () not declared in this scope" using an arduino duemil.

Comment by project member rogue.bh...@gmail.com, Mar 17, 2011

Make sure you use SoftPWMBegin() instead of softpwmbegin()

Comment by frank.le...@googlemail.com, Apr 8, 2011

Great Library! I used this one to control some LEDs mounted on my staircase. Unfortunately, digital pin 0 can not be accessed although I used the fixed r116 version of the library. SoftPWMSet(ALL, 0); just sets any other pin to zero, but pin 0 is still in a high state. Is there any quick fix available for this issue? I would really like to use every digital pin ;)

Comment by project member rogue.bh...@gmail.com, Apr 8, 2011

More than likely, you'll need to do Serial.end(); in setup(). This will remove the hardware control on pin 0 and 1.

Try it, and let us know how it goes.

Comment by freekkal...@gmail.com, Apr 10, 2011

Why can you only go up to 16 channels?

Comment by project member rogue.bh...@gmail.com, Apr 10, 2011

No direct reason - it was chosen arbitrarily. You could do some math to figure out what the limit would be. It's just a calculation for the main interrupt loop - as you add more loops, the more time is taken in the interrupt routine, leaving less time in the main application.

@ 16 channels, approximately 20% of CPU cycles are spent in the interrupt routine. I'd have to spend some time looking at the routine in detail to get the exact figures, but that's a decent rough estimate.

Comment by dmacc...@gmail.com, Jul 19, 2011

Brett:

I don't know if you're still supporting this library, but if you are, could you look at my posting at Arduino.cc?

http://arduino.cc/forum/index.php/topic,66941.0.html

Thanks.

\dmc

Comment by joaoquar...@netcabo.pt, Jul 27, 2011

Hello Brett,

Have you plans to port this Library ChipKIT, I've tried and it doesn't work.

Best regards,

Joao Quaresma.

Comment by project member rogue.bh...@gmail.com, Jul 27, 2011

Probably not - Besides Rogue, Wiring is where I am putting all of my efforts these days. Wiring will eventually (within a year) have support for PIC, and hopefully others. The latest Wiring API hasn't been adopted by Arduino, and hence ChipKIT, so the current version of SoftPWM will require some work to get it functioning on ChipKIT.

For more information about where we are going with Wiring, check out http://wiring.org.co/

Comment by emiliano...@gmail.com, Jul 30, 2011

Hi, Im working on an RGB LED cube, with an Atmega644 with ArduinoBootloader?, I need 25 PWM channels, how can I get them with your library? will using 2 timers help? thanks!

Comment by m...@baseggio.ca, Oct 13, 2011

I just tried to use this with an attiny85 chip -- with a bunch of compile errors. Oh well, it was worth a shot :)

Any chance you'll be releasing one that is attiny85 compatible?

Comment by project member rogue.bh...@gmail.com, Oct 14, 2011

We are working on the Atmel ATtiny core series in Wiring. No ETA on the release yet.

Comment by div....@gmail.com, Nov 6, 2011

C:\Users\Ivan\Documents\Arduino\libraries\SoftPWM\SoftPWM.cpp: In function 'void SoftPWMBegin()': C:\Users\Ivan\Documents\Arduino\libraries\SoftPWM\SoftPWM.cpp:123: error: 'TIFR2' was not declared in this scope C:\Users\Ivan\Documents\Arduino\libraries\SoftPWM\SoftPWM.cpp:124: error: 'TCCR2B' was not declared in this scope C:\Users\Ivan\Documents\Arduino\libraries\SoftPWM\SoftPWM.cpp:125: error: 'TCCR2A' was not declared in this scope C:\Users\Ivan\Documents\Arduino\libraries\SoftPWM\SoftPWM.cpp:126: error: 'OCR2A' was not declared in this scope C:\Users\Ivan\Documents\Arduino\libraries\SoftPWM\SoftPWM.cpp:127: error: 'TIMSK2' was not declared in this scope C:\Users\Ivan\Documents\Arduino\libraries\SoftPWM\SoftPWM.cpp:127: error: 'OCIE2A' was not declared in this scope Why? Arduino IDE 0022. Code copypasted from the example.

Comment by stvan...@gmail.com, Dec 11, 2011

well done! and thank you

Comment by denleybi...@gmail.com, Jan 13, 2012

I am having the same problem with pin number 0. I can see in the SoftPWM.cpp file that it is a bug. On line 158 the code find the pins for pin<0 and then for pin>0 (it is missing the pin=0 case).

I am new to open source stuff so I will have a quick look to see if I can fix it myself but I dunno if I will be able to figure it out, so someone else may like to fix it or submit it as a bug report or whatever.

Comment by denleybi...@gmail.com, Jan 13, 2012

I submitted it under "Issues". Will have to just change my copy for now.

Comment by ronny.dl...@gmail.com, Jan 13, 2012

Hey, nice library!

It works really fine, but if I connect a xbee module on the Pins 0 and 1 the arduino crash every few seconds. Is there any chance to use this pins and the SoftPWM library?

Best Regards, Ronald Dlapka

Comment by j...@jabawoki.com, Feb 13, 2012

Using 0.2x of the Arduino IDE my sketches work fine with your library, but with a fresh install of the 1.0 IDE I get compile errors with the same sketches starting with a lookup for wiring.h:

\SoftPWM.cpp:27:20: error: wiring.h: No such file or directory \SoftPWM.cpp: In function 'void SoftPWMSet(int8_t, uint8_t, uint8_t)': \SoftPWM.cpp:177: error: 'digitalPinToPort' was not declared in this scope \SoftPWM.cpp:177: error: 'portOutputRegister' was not declared in this scope \SoftPWM.cpp:178: error: 'digitalPinToBitMask' was not declared in this scope \SoftPWM.cpp:183: error: 'digitalWrite' was not declared in this scope \SoftPWM.cpp:184: error: 'OUTPUT' was not declared in this scope \SoftPWM.cpp:184: error: 'pinMode' was not declared in this scope \SoftPWM.cpp: In function 'void SoftPWMEnd(int8_t)': \SoftPWM.cpp:198: error: 'digitalWrite' was not declared in this scope \SoftPWM.cpp:199: error: 'INPUT' was not declared in this scope \SoftPWM.cpp:199: error: 'pinMode' was not declared in this scope

Have you confirmed compatibility with a fresh 1.0 install?

Comment by j...@jabawoki.com, Feb 13, 2012

Fixed, perfect - lifesaver.

Comment by pieter.s...@gmail.com, Feb 13, 2012

Heya,

I love your library and try to use it to control 10 RGB leds on an Arduino Mega. I use common cathode RGB leds, so I need a digital HIGH state to turn them off completely (sending a PWM value of 255 just won't do). Is there a place I can add an if-else structure that sends digital HIGH if it gets a 255 PWM value? I don't fully understand where the values you send with SoftPWMSet are applied...

Thanks! Pieter

Comment by pieter.s...@gmail.com, Feb 13, 2012

For those of you who have the same issues after upgrading to version 1.0 of the Arduino IDE:

change "#include <wiring.h>" in SoftPWM.cpp to "#include <wiring_private.h>".

Comment by project member rogue.bh...@gmail.com, Feb 13, 2012

I just updated the library. Several fixes:

  • The Arduino 1.0 fix (bleh, why "Arduino.h"??? - what a mess). Can someone verify that this works on Arduino 1.0 - I refuse to install 1.0 :) I use Wiring.
  • Added polarity for pins. This means, for people like Pieter, you can change the polarity on the pin, and get a solid HIGH value when the value is 0 - this might mean you have to invert your logic, but at least you can get a solid HIGH value.
  • Up to 20 channels can be defined. You can also change this to whatever you want, inside of SoftPWM.h.
Comment by pieter.s...@gmail.com, Feb 14, 2012

Hey Rogue,

thanks for these updates!

  • Working fine on Arduino 1.0
  • Polarity is ok: After starting with SoftPWMBegin(1) it worked perfect!
  • Easy to use 30 channels now

Greetz, Pieter

Comment by dave.pat...@googlemail.com, Feb 22, 2012

Just installed on Arduino 1.0. Running 14 pins on an Uno, no problems.

Comment by local_da...@yahoo.com, Mar 1, 2012

Hey Rogue

Thank you for the great library. I'm running it on a teensy++ 2.0 with great pleasure. You mention the amount of CPU-work the library uses. Are these 20% also used when no leds are being PWMed at a given moment or are the 20% used at any time as soon as SoftPWMBegin() is called?

Thank you very much,

Dani

Comment by local_da...@yahoo.com, Mar 1, 2012

Rogue, I'm trying to add a feature to your library (ISR-Routine) specifically for my project, where - dependent on variables from the main-file, something should be written periodically. Unfortunately, the variables from the main file are of course unknown in the scope of your ISR-routine.

`ISR(SOFTPWM_TIMER_INTERRUPT) #endif {

uint8_t i; int16_t newvalue; int16_t direction;

if(++isr_softcount == 0) {
// set all channels high - let's start again // and accept new checkvals
// Zusatzfunktion Backlight des LCD in Abhängigkeit der Helligkeit --------------------- if(lichtindex == 0){
analogWrite(backlightPin, 255-analogRead(ldrPin)/2);
} // ENDE Zusatzfunktion Backlight des LCD------------------------------------------------
for (i = 0; i < SOFTPWM_MAXCHANNELS; i++) {
`

Is there a quick way you know on how to get to the values «lichtindex», «backlightPin» and «ldrPin»? Thank you very much, Dani

Comment by metoo11...@gmail.com, Mar 15, 2012

Hi!

Just tried the lib 005 on a Nano v3.0 in combination with Serial for debugging and SoftSerial? to remote control 3 LEDs (RGB) via bluetooth HC-05. Works quite well from my android phone (with BlueTerm? app) and PC. Dimming sometimes is not running smooth - maybe due to serial interrupt priority of SoftSerial? lib.

According to dimming I'd suggest the following. It seems to me, that dimming is done in a linear way, whereas the eye is not. Maybe it would be a good idea to extend the %-dimming with translation table to get perceptually linear result. You may find information on this at

Thanks for the nice piece of software, Alex.

Comment by duncan.m...@gmail.com, Jun 6, 2012

Great library, thanks for putting it out there. I have two hopefully simple questions.

First are the fade rates only for a full fade from 0-255 or 255-0 or will it take that amount of time to fade between any values. I suspect if I take an led to 50% brightness it will take half the fade up delay to get there, but I wanted to confirm.

Also I feel like there may be a way to tweak the library for using chips at 8mhz vs. 16mhz so you still get the same PWM resolution. There is a section in the library to change the CLK and OCR but I'm not sure what changes should be made for an 8mhz chip.

Any help is awesome. Thanks!

Comment by project member rogue.bh...@gmail.com, Jun 6, 2012

@ Alex (metoo11.MT): I'm not exactly sure what you have going on, but you might benefit from the "hardset" parameter from SoftPWMSet (3rd parameter). It will ensure that the count for that channel is cleared for the next pass.

@ duncan_mccloud: yes, the fad rates are for the amount of time to go from 0 to 255 or 255 to 0. So, for example, if you set the fade rate to 200 ms, it means that for the channel to go from 0 to 127, it will take 100 ms.

The code will try to set the cycle rate to 60 Hz. So, you don't have to worry about changing it (unless you want something other than 60 Hz).

-- Brett

Comment by Justinly...@gmail.com, Jun 12, 2012

I first used this on a atmega168 chip to fade LED's and it works perfectly, when I upload the same code to a atmega328 the fading kind of works but it blinks very fast. I figure it has something to do with the timing and how the pwm is made on each chip. is there any way to fix this by editing the library?

thanks -Justin

Comment by JvL...@gmail.com, Jul 7, 2012

Is there a way to make this library compatible with the Atmega8-16pu?

Thanks in advance. Joël

Comment by 722...@gmail.com, Jul 30, 2012

re- being able to change the max number of pwm pins in SoftPWM.h you have no idea how much this has saved my life. This is probs the most useful arduino library I have come across. THANK YOU

/Rom

Comment by bede...@gmail.com, Aug 9, 2012

Brilliant library!

Could you implement the Zero-cross functionality for dimming the 230V things with MOS-FET?

Comment by duncan.m...@gmail.com, Aug 14, 2012

I'm curious if when the library tries to auto set its cycle rate to 60Hz if it takes into account a clock being divided in software. For example this runs fine at 8mhz, but if I divide my clock to 4mhz in software the PWM gets choppy. I wonder if this is just because the library doesn't see my slower clock when it sets up the cycle rate.

Comment by rick.bro...@gmail.com, Aug 20, 2012

What is the default period of the PWM signal? Is there a way to set it for each pin?

Comment by misterlo...@gmail.com, Oct 3, 2012

Is there a way to override the fade time for one operation? I'd like to normally fade the LED every time it turns off or on, but if a switch is opened, have it go to LOW immediately. If I use analogWrite or digitalWrite, it works but comes back to whatever SoftPWM thinks the value should be when the switch is closed again (instead of staying at 0) so I'd like to do this within SoftPWM.

Comment by deceli...@gmail.com, Oct 26, 2012

no need to say how useful is the library. so thanks again. does anyone know if there's a way to make fade time longer then 4000 ?? something like 8000 or+?

thx r

Comment by jalexacu...@gmail.com, Dec 17, 2012

Just curious if you ever got around to making alternate versions of this library using timer1 or timer0. I'm running into an issue where I'd like to use timer2 for something else and thought it would be handy to just move the softPWM wholesale to timer1.

Thanks!

Comment by Marcel.M...@gmail.com, Feb 15, 2013

He, first: great work, but is it possible to make this lib run on Attiny85?

Comment by bcre...@yahoo.fr, Mar 1, 2013

Thanks a lot, This is exactly what I needed for my project because I use 6 RGB leds on 18 pins that doesn't support them ! Your library perfectly works with my mega 2560 R3.

Comment by lukjanov...@gmail.com, Apr 19, 2013

Hello friend. Please add support Atmega16/32. More pins from PWM outputs! Atmega16 Errors (((((

C:\Dropbox\Public\arduino-1.0.4\libraries\SoftPWM\SoftPWM.cpp: In function 'void SoftPWMBegin(uint8_t)': C:\Dropbox\Public\arduino-1.0.4\libraries\SoftPWM\SoftPWM.cpp:157: error: 'TIFR2' was not declared in this scope C:\Dropbox\Public\arduino-1.0.4\libraries\SoftPWM\SoftPWM.cpp:157: error: 'TCCR2B' was not declared in this scope C:\Dropbox\Public\arduino-1.0.4\libraries\SoftPWM\SoftPWM.cpp:157: error: 'TCCR2A' was not declared in this scope C:\Dropbox\Public\arduino-1.0.4\libraries\SoftPWM\SoftPWM.cpp:157: error: 'OCR2A' was not declared in this scope C:\Dropbox\Public\arduino-1.0.4\libraries\SoftPWM\SoftPWM.cpp:157: error: 'TIMSK2' was not declared in this scope C:\Dropbox\Public\arduino-1.0.4\libraries\SoftPWM\SoftPWM.cpp:157: error: 'OCIE2A' was not declared in this scope

Comment by newsfr...@gmail.com, Apr 24, 2013

Please add #include <Arduino.h> in the header files

Comment by drnickyo...@gmail.com, Apr 29, 2013

Getting an error when trying to use Tone and SoftPWM:

core.a(Tone.cpp.o): In function `vector_7': /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/Tone.cpp:535: multiple definition of `vector_7' SoftPWM/SoftPWM.cpp.o:/Users/nickyoung/Documents/Arduino/libraries/SoftPWM/SoftPWM.cpp:70: first defined here

Comment by hepa...@gmail.com, Jun 5, 2013

Error Compiling

core.a(Tone.cpp.o): In function `vector_13': C:\Workspace\Arduino\arduino-1.0.5\hardware\arduino\cores\arduino/Tone.cpp:535: multiple definition of `vector_13' SoftPWM\SoftPWM.cpp.o:C:\sketches\libraries\SoftPWM/SoftPWM.cpp:70: first defined here c:/workspace/arduino/arduino-1.0.5/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/bin/ld.exe: Disabling relaxation: it will not work with multiple definitions

Comment by xero...@gmail.com, Oct 6, 2013

Is there a way to set the frequency of the PWM? preferably for every single channel? I'm trying to make a square wave synth with at least 6 OSCs

Comment by philipp....@googlemail.com, Nov 25, 2013

Hi,

I have tested SoftPWM successfully on an Arduino Nano, using 14 Pins. Now I would like to extend my activities on a Mega, where I need 42 Pins, because I want to fade 42 LEDs. Now I see, there is a limit at 20 Channels. Can you help me, what to do to overcome this?

Thanks and best regards, Philipp

Comment by liveatme...@gmail.com, Dec 15, 2013

Phillip: Just change the limit SOFTPWM_MAXCHANNELS to 42 in SoftPWM.h

Comment by U...@ist-einmalig.de, Dec 19, 2013

hey, is it possible to have a fade time greater than 4000msec? I Need a fadetime between 72-144sec per percent. The time from 0% to 100% would be between 120 and 240 minutes.

Thanks and best regards, Rob

Comment by cka3...@gmail.com, Dec 28, 2013

It looks like this library conflicts with IRremote library... SoftPWM\SoftPWM.cpp.o: In function `vector_7': d:\Documents\Arduino\libraries\SoftPWM/SoftPWM.cpp:70: multiple definition of `vector_7' IRremote\IRremote.cpp.o:d:\Documents\Arduino\libraries\IRremote/IRremote.cpp:311: first defined here

Comment by esteb...@gmail.com, Feb 14, 2014

Thank you! works great in Wiring S. I am controlling RGB LED strips with it. Is there a noticeable difference on the values if you are using an "original" PWM Vs. the softPWM? In other words...should for example analogWrite( red4, 100) and SoftPWMSet(red4, 100) give the same result? In my experience with I got different results, so decided to use softPWM for all.

Comment by bdumagu...@gmail.com, Feb 28, 2014

Thank you for this library Sir. Works okay on a Gizduino X v2.0 (atMega 1281). Going to hook up around 20 LEDs. Will see how it fairs.

Comment by rene.vip...@gmail.com, Jun 7, 2014

Works great! fixed all my problems, and added a few new possibilities. :)

Thank you very much.

Comment by artline....@gmail.com, Jun 16, 2014

Hi, thanx for the great library. Unfortunately when I enable the library by "SoftPWMBegin()" even without using it, i'm encoutering few problems with ALL tone libraries, that I've found ("tone", "NewTone?", "TimerFreeTone?"..) In fact first one official Arduino "Tone library" doesn't work at all, because use same timer2 and conflicts with SoftPWM library, and while using other two libraries, sound produced by piezo buzzer (I use it for Alarm), which is nice and clear without SoftPWM, sounds very "choppy" and unnatural.

I tried to desable the library by using : SoftPWMStop(), but it doesn't change anything, like if it simply does not desable the library. Can you help me to solve that issue ? Regards

Comment by john.tor...@gmail.com, Jun 20, 2014

Please make a attiny85 release. Even a beta one...


Sign in to add a comment
Powered by Google Project Hosting