bhagman / SoftPWM

A Wiring (and Arduino) Library to produce PWM signals on arbitrary pins.
MIT License
86 stars 31 forks source link

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

Open TechSgin opened 2 years ago

TechSgin commented 2 years ago

"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;
        }
      }
    }
  }
}