SparkMax does not work with PWM inputs

I’m trying to drive a SparkMax with the PWM input feature. But I’m seeing the exact same problem as this post:

Below is one of the many waveforms I have tried.

Per this documentation, this waveform should drive the motor in reverse and 50% speed:

Has anyone had any luck using SparkMax with PWM inputs?

What does the LED show when supplying that waveform?

Note the valid pulse frequency range is 50 - 200 Hz. The waveform you are generating is much higher.

1 Like

Not sure what you are using to generate the PWM but if it’s an Arduino or Roborio I recommend just using a servo library. It will work how you expect

1 Like

We tried using PWM from the roboRIO with Spark Maxes driving NEOs earlier this year (thinking that it would simple for prototyping) but saw twitchy motion. Switching to CAN resolved the problem entirely for us, but doesn’t explain why PWM didn’t work.

It’s also not the right pulse width for 50% output. -50% would correspond to a pulse width of 1250us.

This! Use the writeMicroSeconds() function and not analogWrite or anything else. This is true for the TalonSRX and VictorSPX motor controllers as well.

1 Like

I should add, this is not for our robot, but for a test board that allows the kids to rapidly prototype ideas without a roboRIO, laptop, etc.

The chart is a little confusing. So if I want to drive in the forward direction slowly, I should have a pulse width of 1600 us. So instead of changing the duty cycle I need to change the period (1/frequency)? If I want to go full speed forward, I drive with a pulse of 2000 us at a duty cycle of 100, but that is just a DC waveform. What am I missing.

I think what you are missing is you are trying to generate a periodic waveform based on duty cycle. But duty cycle is not what is being measured here, its just the pulse width. The frequency must be between 50Hz and 200Hz. The pulse must be between 1000us and 2000us. In this configuration, the line will never be low or high all the time. The pulse width and the frequency are not related to eachother and must be in spec independently.

From the servo control wikipedia

except instead of -90 to 90 degrees, is drive percent (full forward vs full reverse)

4 Likes

Id highly recommend getting an Arduino Mega. They are cheap, lots of IO and PWM capable lines. Easily adaptable and are well known in the community. We have used them for robotic test boardsfor non FRC projects but with FRC motor controllers and motors. It has not failed us yet.

Additionally if you have an RC transmitter and receiver these typically use the same signals. The receivers will have a Signal line for each axis/channel that will output servo friendly PWM. So for just a quick motor tester it’s perfect. We have a set of these for this exact purpose or to take it into the Arduino as an input and mix the axis to then drive motor controllers through the same Arduino. Home brew Teleop

hobbyking-2-4ghz-mode-2-4ch-tx-_-rx-v2-radios-hk-t4a-m2-2

Hey! I’m the author of the original problem post you linked to. This doesn’t help solve the problem, but we never figured out that this was potentially due to the duty cycle. We tried both Arduino and RoboRIO PWM outputs with correct libraries and never got it to work. All other motor controllers (Victor SPX, Talon SRX, Talon FX) worked perfectly with both types of PWM signals we could generate, but the Spark MAXes just refused to play nice.

It sucked because we eventually gave up on them and switched entirely to Falcon 500s over CAN for the drivetrain and Talon SRXs for the mechanisms and other motors.

So I spent quite a bit of time figuring this out and I thought I would leave a detailed answer for others. First, thanks for all that replied. I made a bad assumption about how the PWM signal works in the SparkMax. It is a bit different than what we use professionally for high end motor control, LED dimming, etc.

Problem one I encounter is the Vih (Voltage input high) is greater than 3.3V. So you need to drive that PWM signal with a 0 to 5V signal. I had some N-MOS FETs laying around, which I was able to use. But if you use an N-MOS FET, it will invert the signal, so make sure you invert the duty cycle of your PWM signal as explained below.

Will Toth, posted a really good picture above. The SparkMax has the following interface via the PWM input:

What this is saying is the time between pulses must be 50 Hz (20 ms) to 200 Hz (5 ms). Then a neutral motor is a pulse width in the range of 1475 to 1525 us. Or put a different way. If we pick 100 Hz as your frequency (period in PWM parlance), then the neutral duty cycle is 1.5 ms / 10 ms or 15% duty cycle. If you generate a 100 Hz (10 ms period) PWM signal with a duty cycle of 15%. You will get a neutral (stopped) motor. Now if you increase the duty cycle from 15% to 20%, the motor will go from stopped to 100% speed in the forward direction. Likewise, if you reduce the duty cycle from 15% to 10%, it will go from stopped to full reverse.

Lets look at some pictures. It is REALLY hard to see the difference from the pictures, so look at the +width value. This is what a neutral signal looks like:

No if we slightly increase the duty cycle of the PWM signal to 1540 microseconds or 15.4% duty cycle, the motor should start to spin.

As we increase the duty cycle of the PWM signal, the motor will increase in speed until we hit the max:

If we want to spin the motor in reverse, you need to decrease the duty cycle from 15% to something less. The image below shows full max speed in the reverse direction:

As others have said. I would NEVER use the PWM signals to control motors via the Spark Max on an actual robot. We always use CAN. It is more robust, insensitive to EMC noise, much more flexible, and easier to use.

As far as development environments go, you can use anything that generates a PWM signal. Someone mentioned Ardiuno. I personally like Pi Pico’s running Micropython. They are super easy to use, setup, debug, etc. Or full blown Raspberry Pi’s, which can be a bit more difficult to setup and use. I have used Linux professionally for over 20 years, so they feel like home to me.

I hope that helps others.

PWM signal for servo controls goes back to radio control planes in the analog world. The earliest form uses a manual push button and an one channel AM transmitter. On pushed the servo one way and off went the other. It used carbon control (A human) to vary the ON period the get the result they wanted. Time moved on and people invented a pulse generator that you could set by a potentiometer transmitted by the one channel AM transmitter. See that the ON pulse width was the control, not duty cycle or frequency. Some smart person figured out that you could multiplex several PWM signals unto one channel of an AM transmitter, and demultiplex on your RC airplane giving you Multi channels of control from a one channel AM transmitter. This is why the servo PWM control signal is why it is. Why the 5V? That was the voltage of your RC servo back in the day. Thus showing modern man is not nearly as smart as a cave man.

1 Like

I was able to use PWM using firmware 1.4.0 or 1.6.2 on the SparkMax. This allowed me to use these as drive motors run directly from a Sky Fly receiver. It may not be the best solution but we are not in FIRST and in our competition a compact powerful drive motor is a bonus. We use the Spark Max with Neo brushless motors