Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PWM control for Vibro Motor #33

Closed
Shooter0423 opened this issue Feb 25, 2020 · 5 comments
Closed

PWM control for Vibro Motor #33

Shooter0423 opened this issue Feb 25, 2020 · 5 comments

Comments

@Shooter0423
Copy link

Wonder if anyone has worked on using pwm to control the vibration motor. A few weeks back someone mentioned it in a post they made, but I cant seem to find it now, and @erichiggins has mention it a time or two. I am trying a rewrite of motor.js to use pwm as implemented in rpio. This doc is what i'm using https://www.npmjs.com/package/rpio reference. I have got the program to not throw any errors when loading but not to actually run the vibro motor. I am unsure what numbers to use for .pwmSetClockDivider (), I used 4096 which is the max allowed and gives the minimum freq of 4.7 kHz. And for .pwmSetRange I used 100, then a point you select in .pwmSetData becomes the On Time (duty cycle)

@erichiggins
Copy link
Contributor

I created a separate branch for you called feature/pwm-motor which includes a PWM-based rewrite of the motor control.

Hopefully that helps you to explore.

@erichiggins
Copy link
Contributor

erichiggins commented Apr 20, 2020

Edit: I corrected a few statements I made in my original post to reflect that PWM is still useful, but the frequencies available are too fast to match those that the Open Trickler uses today. All this means is that PWM can't be a drop-in replacement to achieve the same ON/OFF cycles that I coded by hand. Instead, PWM could potentially be used to speed up and slow down the motor more smoothly.


I just did a deep-dive to investigate PWM a bit more, hoping that I could incorporate it and close this out. There's a problem: PWM control runs too fast to match the current ON/OFF frequencies.

I'll provide an explanation w/ the simplest math I can provide, but first, some facts upfront:

  • The clock speed for PWM on the Raspberry Pi is 19.2Mhz
  • There are three controls for working with PWM:
    • Refresh Rate: rpio.pwmSetClockDivider()
    • Range : rpio.pwmSetRange()
    • Data: rpio.pwmSetData()
  • You can use PWM to turn the motor full ON (100%) or full OFF (0%)

Let's run through an example using PWM to make the motor run as fast as it can. Put another way, the shortest possible ON pulse.
First, we have to set the refresh rate using rpio.pwmSetClockDivider(). The value that gives us the fastest option is 2. Here's the math:

19,200,000 hz / 2 = 9,600,000 hz (9.6 Mhz)
Total pulse width = 1 second / 9.6Mhz = 0.000000104 seconds * 1000 = 0.000104 milliseconds

Regardless of what we do next, a 50% duty cycle here would turn the motor ON for half of this total pulse width, in this case 0.000104ms / 2 = 0.000052 ms.
Obviously this is way too dang fast and the numbers are too crazy to even focus on the rest of our controls.

Let's look at the slowest possible setting, to use PWM to make the motor run as slow as it can. Put another way, the longest OFF cycle. The highest possible value we can use to set the refresh rate is 4096.

19,200,000 hz / 4096 = 4687.5 hz (4.7 Khz)
Total pulse width = 1 second / 4687.5 = 0.000213  seconds * 1000 = 0.213 milliseconds

We'll continue with the other functions in a moment, but realize that with this pulse width (the slowest we can get), a 50% duty cycle would turn the motor ON for 0.1 ms and OFF for 0.1 ms.
If we used a 1% duty cycle, the motor would be ON for 0.002 ms and OFF for 0.211 ms.

This is still way way way too fast. Regardless, let's keep learning about the other two functions.

The usual next step would be to set the Range with rpio.pwmSetRange(). This basically just gives you more resolution from the total pulse width you just set by dividing it by the value you use here.

pulse resolution = total pulse width / range

For a simple example, let's do 100:

4687.5 hz / 100 = 468.8 hz
Pulse resolution = 0.213 milliseconds / 100 = 0.00213 milliseconds

What you use to set the range is meaningless on it's own, but it is useful with the next function. You can use rpio.pwmSetData() to set the number of pulse resolutions that the motor should be ON. Valid options are from 0 (off) to the Range you set.

Carrying on with our example:

  • 1% Duty: Setting data to 1 would turn the motor ON for 0.00213 ms
  • 50% Duty: Setting data to 50 would turn the motor ON for 0.1065 ms

So, I hope this helps others to understand what I just learned, which is that PWM probably isn't a great drop-in fit because (as far as I can tell) it's not capable of running at as as slow of a frequency as it runs now.

References:

@erichiggins
Copy link
Contributor

One more clarification here:

The clock division setting seems to define the actual PWM frequency, which isn't affected by other settings.

e.g. If you divide the 19.2MHz clock by 512, the result is a PWM frequency of 37.5kHz. No matter what Range you use (10, 100, or 1000), and no matter what Data you use to set a duty cycle, there will only be one ON and one OFF setting for each waveform. That means that the frequency doesn't really change with the Range and Data functions.

Changing the Range gives you more or less resolution for the Data setting.
Changing the Data setting is what controls the duty cycle (0% to 100% of the Range). The duty cycle roughly translates to an average output voltage of the 3.3V or 5V supply (50% of 3.3V = 1.65V).

I need to conduct some actual tests, but based on a little Googling, the ideal frequency for these motors should be in the range of 3-30kHz, though it may depend on the motor used. That limits the clock division options to the following:

  • 512 (37.50 kHz)
  • 1024 (18.75 kHz)
  • 2048 (9.38 kHz)
  • 4096 (4.69 kHz)

I don't know how much the Range actually matters. It seems like using 100 would make the duty cycle % math pretty easy to understand so I'll probably start there.

@erichiggins
Copy link
Contributor

With the motors I'm using, the clock divisions of 256 and 512 seemed to give the best results at a 10% duty cycle. They were barely audible, but perhaps enough to slowly trickle single kernels. Anything higher than that (1024 +) seemed to be too fast to even activate the motor with a 10% duty cycle.

@erichiggins
Copy link
Contributor

PWM motor control is now fully supported!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants