Giter VIP home page Giter VIP logo

softpwm's Introduction

SoftPWM Library


What's New?

Version 1.0.1

  • Changes from Paul Stoffregen
    • Use IntervalTimer on Teensy 3.x
    • Use LED_BUILTIN for WLED in example

Version 1.0.0

  • Initial release

Description

A Wiring Framework (and Arduino) 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 AVR, or IntervalTimer on Teensy 3.x) 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

Download and Installation

You can use the Arduino Library Manager (Sketch -> Include Library -> Manage Libraries...) to download the library.

Alternatively, you can download the library directly, and install it yourself.

Unzip the folder and rename it to SoftPWM, then move it to your arduinosketchfolder/libraries/ folder.


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 is 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:

Arduino SoftPWM example

rDuino LEDHead Bounce example - available as library example:

rDuino LEDHead SoftPWM example

More demos:

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


softpwm's People

Contributors

bhagman avatar paulstoffregen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

softpwm's Issues

SoftPWM_Wiring_HeartBeat

suggested add:

byte WLED = 13;

else you get:

Arduino: 1.8.5 (Linux), Board: "Arduino Nano, ATmega328P"

/home/pi/Arduino/libraries/SoftPWM/examples/SoftPWM_Wiring_HeartBeat/SoftPWM_Wiring_HeartBeat.pde: In function 'void setup()':
SoftPWM_Wiring_HeartBeat:8: error: 'WLED' was not declared in this scope
SoftPWMSet(WLED, 0);
^
/home/pi/Arduino/libraries/SoftPWM/examples/SoftPWM_Wiring_HeartBeat/SoftPWM_Wiring_HeartBeat.pde: In function 'void loop()':
SoftPWM_Wiring_HeartBeat:18: error: 'WLED' was not declared in this scope
SoftPWMSet(WLED, 255);
^
exit status 1
'WLED' was not declared in this scope

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

on is not on, i.e pwm of 255 have a short period of 0

"on" is not fully "on", i.e. pwm of 255 have a short period of 0

This is how i patched it to work for my application (DC motor - h-bridge with "break" and "coast" ):
Note: My "h-bridge" ic require "full width high" for a "break" and "full width low" for a "coast"

What I did is:

  1. Reset high and low when "++_isr_softcount == 0"
  2. Skip "hit width" validation test for "checkval == 0" and "checkval == 255"

see the modified interrupt function below:

{
  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
    for (i = 0; i < SOFTPWM_MAXCHANNELS; i++)
    {
      if (_softpwm_channels[i].fadeuprate > 0 || _softpwm_channels[i].fadedownrate > 0)
      {
        // we want to fade to the new value
        direction = _softpwm_channels[i].pwmvalue - _softpwm_channels[i].checkval;

        // we will default to jumping to the new value
        newvalue = _softpwm_channels[i].pwmvalue;

        if (direction > 0 && _softpwm_channels[i].fadeuprate > 0)
        {
          newvalue = _softpwm_channels[i].checkval + _softpwm_channels[i].fadeuprate;
          if (newvalue > _softpwm_channels[i].pwmvalue)
            newvalue = _softpwm_channels[i].pwmvalue;
        }
        else if (direction < 0 && _softpwm_channels[i].fadedownrate > 0)
        {
          newvalue = _softpwm_channels[i].checkval - _softpwm_channels[i].fadedownrate;
          if (newvalue < _softpwm_channels[i].pwmvalue)
            newvalue = _softpwm_channels[i].pwmvalue;
        }

        _softpwm_channels[i].checkval = newvalue;
      }
      else // just set the channel to the new value
        _softpwm_channels[i].checkval = _softpwm_channels[i].pwmvalue;

      // now set the pin low (checkval == 0x00) otherwise high 
      if (_softpwm_channels[i].checkval == 0x00)
      {
        if (_softpwm_channels[i].polarity == SOFTPWM_NORMAL)
          *_softpwm_channels[i].outport &= ~(_softpwm_channels[i].pinmask);
        else
          *_softpwm_channels[i].outport |= _softpwm_channels[i].pinmask;
      }
      else
      {
        if (_softpwm_channels[i].polarity == SOFTPWM_NORMAL)
          *_softpwm_channels[i].outport |= _softpwm_channels[i].pinmask;
        else
          *_softpwm_channels[i].outport &= ~(_softpwm_channels[i].pinmask);
      }
    }
  }

  for (i = 0; i < SOFTPWM_MAXCHANNELS; i++)
  {
    if (_softpwm_channels[i].pin >= 0) // if it's a valid pin
    {
      // skip hit on checkval 0 and 255
      if (_softpwm_channels[i].checkval != 0x00 && _softpwm_channels[i].checkval != 0xFF)
      {
        if (_softpwm_channels[i].checkval == _isr_softcount) // if we have hit the width
        {
          // turn off the channel
          if (_softpwm_channels[i].polarity == SOFTPWM_NORMAL)
            *_softpwm_channels[i].outport &= ~(_softpwm_channels[i].pinmask);
          else
            *_softpwm_channels[i].outport |= _softpwm_channels[i].pinmask;
        }
      }
    }
  }
}

Multiple Pins from one call

I would like to activate multiple pins at once using soft pwm...

maybe the ability to pass an array instead of a single value?

Would this be possible?

No compatible with ATMEGA4809 based boards (NANO_EVERY, etc.)

The library works with Arduino Nano and Teensy (AVR/ARM) but not with EVERY boards (MEGAAVR).
When compiling, following error is given...

In file included from Arduino\libraries\SoftPWM\SoftPWM.cpp:44:0:
Arduino\libraries\SoftPWM\SoftPWM.cpp: In function 'void SoftPWMBegin(uint8_t)':
Arduino\libraries\SoftPWM\SoftPWM_timer.h:39:3: error: 'TIFR2' was not declared in this scope
TIFR2 = (1 << TOV2); /* clear interrupt flag */ \

LED doesn't go off entirely!

even if I set the PWM to 255 the LED doesn't go off entirely. Its always lighting a bit! What can be the reason? I used a sink configuration with the ATMEGA GPIO to GND.
img_20180607_155247

Change PWM frequency

Hi there!
Is there an option to increase the frequency of the PWM signal? I'm trying to control small DC motors using this library, but there are significant vibrations going on to the motor with using the PWM. I suppose it is cause of the low frequency of the PWM signal. If yes, how can I do that?

Pins don't go HIGH anymore

PWM 255 as well as digitalWrite(PIN,HIGH) isn't HIGH any more.
Now there is a PWM spike on the signal. Seems that PWM 254 is the maximum HIGH level now.
LOW Level works (as mentioned within the README.md "True zero level, i.e. off == off").
HIGH Level is not mentioned :-)
I really appreciate the purpose of this library.

More than 20 pins on Mega2560

Hello,

Would it be possible to control more than 20 pins (I'd need 24 pins) on Mega2560?
I don't have it yet so I can't test, just want to know if possible and how.

Thanks!

SoftPWMServo.h: No such file or directory

Arduino: 1.8.12 (Mac OS X), Board: "ChipKit uC32"

RoomControlCode:2:10: fatal error: SoftPWMServo.h: No such file or directory
#include <SoftPWMServo.h>
^~~~~~~~~~~~~~~~
compilation terminated.
exit status 1
SoftPWMServo.h: No such file or directory

SoftPWM does not work with IRremote library?

I wanted to use the library in a sketch including the IRremote library. Both librarys dont anymore as soon as they are enabled using irrecv.enableIRIn(); respectively SoftPWMBegin();.

I can assume some reasons for that behavior, but I am devinitely not able to tear down the exact reason.

avr/io.h is missing

Hi, the sample shows me the following error message:
libraries\SoftPWM\SoftPWM.cpp:41:10: fatal error: avr/io.h: No such file or directory
#include <avr/io.h>
^~~~~~~~~~
compilation terminated.
exit status 1

anything additional that needs to be considered?
thanks

millis() stops working when using more than 4 LEDs with SoftPWM

Hi Brett
I like your SoftPWM-library for arduino a lot. Just today I found out, that millis() stops working, as soon as more than 4 LEDs are controlled using our library. I wasn't able to find a solution to that problem. Do you have an idea?
Best regards,
Dani

I used your example-code (), which uses 8 LEDs:
When checking with the serial monitor, I get constantly

26
26
26

Here is the code that doesn't work:

#include <SoftPWM.h>

#define DELAY 100
uint8_t leds[8] = {11,12,13,18,17,16,15,10};

void setup()
{
  Serial.begin(57600);
  SoftPWMBegin();

  for (int i = 0; i < 8; i++)
    SoftPWMSet(leds[i], 0);

  SoftPWMSetFadeTime(ALL, 50, 400);
}

void loop()
{
  int i;
  Serial.println(millis());
  for (i = 0; i < 7; i++)
  {
    SoftPWMSet(leds[i+1], 255);
    SoftPWMSet(leds[i], 0);
    delay(DELAY);
  }

  delay(400);

  for (i = 7; i > 0; i--)
  {
    SoftPWMSet(leds[i-1], 255);
    SoftPWMSet(leds[i], 0);
    delay(DELAY);
  }
  delay(400);
}

As soon as I change the code, so that it uses only 4 LEDs, it works as expected:

3014
5851
8695

Here is the code that works:

#include <SoftPWM.h>

#define DELAY 100
uint8_t leds[8] = {11,12,13,18,17,16,15,10};

void setup()
{
  Serial.begin(57600);
  SoftPWMBegin();

  for (int i = 0; i < 4; i++)
    SoftPWMSet(leds[i], 0);

  SoftPWMSetFadeTime(ALL, 50, 400);
}

void loop()
{
  int i;
  Serial.println(millis());
  for (i = 0; i < 3; i++)
  {
    SoftPWMSet(leds[i+1], 255);
    SoftPWMSet(leds[i], 0);
    delay(DELAY);
  }

  delay(400);

  for (i = 3; i > 0; i--)
  {
    SoftPWMSet(leds[i-1], 255);
    SoftPWMSet(leds[i], 0);
    delay(DELAY);
  }
  delay(400);
}

No longer viable

The lib compiles fine on Arduino CREATE but fails to upload.
It is NOT a CREATE problem but appears to be with the samples.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.