SHWotever / SimHub

Multi sim dashboard, bass shaker driver, ....
http://www.simhubdash.com/
778 stars 97 forks source link

[Feature request] Support 3 PWM Fans on Pro Micro (ATMega32u4) #1630

Closed gusmd closed 2 months ago

gusmd commented 3 months ago

Is your feature request related to a problem? Please describe. I want to have L, C, R PWM fans on ShakeIt Wind on SimHub. I'm using Pro Micro boards which support PWM on pins 3, 5, 6, 9, 10, but the sketch will only work with pins 9 and 10 on the Pro Micro.

Describe the solution you'd like I would like to be able to connect an extra PWM fan to one of the other PWM pins on the Pro Micro. The Sketch already supports up to 4 channels.

Describe alternatives you've considered Right now I'm simply using 2 boards, which is not ideal as it requires more wiring and an extra USB port.

Additional context I did some research on why only pins 9 and 10 would be supported and I figure it is about only pins 9 and 10 working with a 16-bit timer, while other pins are 8-bit. Some googling seems to suggest that it should be possible to achieve the 25 kHz PWM frequency with the 8-bit counter as resolution/precision isn't really that important in this application. Unfortunately my embedded software/hardware skills are not enough for me to figure this one out myself.

SHWotever commented 3 months ago

Hi !

This is a technical limitation, PWM fans needs a 25khz signal, which is not an out of the box arduino pwm signal. To match the standard this is using some internal timers manipulations (https://github.com/PaulStoffregen/TimerOne) , this does make it only available to a very limited set of pins and is not my explicit choice. On the pro micro unlike the leonardo unfortunately the last 11 pin is not user available.

image

gusmd commented 3 months ago

Hi there, thanks for the quick response. I understand this is a limitation of TimerOne. I've been looking at whether we could use another library to handle the timers instead of TimerOne, as the hardware is in theory capable of doing multiple PWM signals at once with some manipulation. Thanks and I'll let you know if I figure this out :)

gusmd commented 3 months ago

Hi there! I finally got this working! My C++ days are long gone, but they came in handy :)

All I had to do was use this port of TimerOne/Three called TimerFour32u4! It uses, as the name implies, Timer4 on the 32u4, which is also capable of 25 kHz PWM on several pins. My changes to the sketch were minimal: added TimerFour to the frozen library folder in the SimHub/Arduino directory, imported it on SHShakeitPWMFans.h, initialized Timer4 on begin with the same 40 us period, and replaced all Timer1.pwm calls with this helper method:

  void setPwm(byte pin, unsigned int value) {
    if (pin == 6) {
      Timer4.pwm(pin, value);
    } else {
      Timer1.pwm(pin, value);
    }
  }

Now, of course the above is pretty dumb as I hardcoded my pin 6 number there :D But with this code I have PWM working on SimHub with my single Pro Micro on pins 6, 9, and 10 at the same time! I measured the frequency, duty cycle, and voltage with a multimeter and everything is perfectly consistent with the SimHub values.

I should mention that for some reason pin 5 didn't work too well... Sometimes it would stop working randomly. Given that this works for me, I'll stop here. But please feel free to use this however you wish :)

And thanks for the great piece of software!

https://www.arduino.cc/reference/en/libraries/timerfour32u4 / https://github.com/samverstraete/TimerFour