Setting custom PWM method or changing PWM frequency in timer0

Hey guys. I'm driving two motors that need to run CW and CCW with varying speed. Due two the nature of my project, I ended up using ports 9 and 10 for one motor and 5 and 6 for the other one. If I'm not mistaken, PWM frequency on ports 9 and 10 is controlled by TIMER1 and 5/6 by TIMER0. When I drive my motors at default PWM frequency I experience a lot of whining noise in duty cycles arround 50%. So I decided to change PWM frequency on these pins by setting dividers for the timers and buum! problem solved!

But I created another problem, since TIMER0 also controls millis function, so timing is completely messed up.

So 2 solutions I can think of, since I need to count time:

1 - create a custom PWM function instead of using analogWrite, that's simple enough (as far as I know) since I only need to count the time using either millis or micros and set the signals HIGH and LOW accordingly. This way I can define the frequency I want.

2 - use indeed TIMER0 with reduced frequency and setup TIMER2 to count time (don't know if that's even possible, just wondering).

Which solution you think is the best one? Any other suggestions?

PS: For those who might be asking why I don't use pins 3 and 11 (TIMER2) for controlling one motor is because I'm using both external interrupt pins (2 and 3) for motor encoders.

PS2: Since I'm using external interruptions, can my solution 1 be affected by that somehow?

What is your mcu - atmega328?
You can use interrupts on every pin of controller. See PCINT in manual

2 Likes

Option 3: accept that millis() is off, but correct for it. E.g. if your timer runs faster than it's supposed to do originally, you know that the 'millis() millisecond' will be shorter than an actual millisecond - and also by how much given how the timer frequencies relate to each other. So simply adjust the number of milliseconds you count in your code to account for the difference.

1 Like

Option 4: Change your motor controllers for ones that don't require 2x PWM pins, but only need 1x PWM pin (for speed) and 1x non-PWM pin (for direction) per motor.

Option 5: keep using your existing controllers but put a logic circuit between the controller and the Arduino so that you don't need 2x PWM pins per motor.

EDIT: do you in fact need 2x PWM pins per motor, even with crappy old L298 ? Don't you only need 2x non-PWM pins for direction (IN1, IN2) and 1x PWM pin (ENA)?

1 Like

Sorry, forgot to mention I’m using arduino nano, so atmega328. Didn’t know that was possible to use external interruptions on any pin. Will definitely check that out. thanks

Yeah that was one option I though about. But the multiplier I’m using makes frequency 244.14 Hz, it’s not even a multiple of 1kHz, which os the original frequency for milllis. Guess I’ll loose a little bit of precision then, but that’s indeed a solution. Thank you

Thanks for your reply Paul. Changing controllers is not an option. I’m using BTS7960 high current full bridge module. As far as I know it does not have this feature for switching directions while keeping same pwm pin.

But using a separate circuit for switching signals seems a good approach. Would have to think about it for a while but I guess simple bjt like bc548 / 558 would do the job. However that includes more components and change my existing PCB layout.

Once again thanks for the options!

The BTS7960 driver has a 3-wire mode to control motor, using only one PWM pin and two standard non-pwm pins.

1 Like

In fact, it sounds like you're running at exactly 1/4 millis() speed, which is not 1kHz, but a little less. Millis() compensates for this by periodically incrementing by 2 instead of 1. So 'your' millisecond is pretty much exactly 4ms. They only thing you'll lose is a little resolution, but no accuracy.

1 Like

Really? Wasn't aware of that. Didn't find the datasheet of the module anywere, only the main IC datasheet, and this 3-wire mode must be implemented by the other IC on the board. That wouldn't be an awesome solution since I would need to use another 2 pins, one for each motor, but I think I can make it work, I have RX and TX (D0 and D1) available. Will try your first suggestion though, about PCINT

I see. I'll give that a try, maybe with micros so I don't lose that much resolution. Thanks!

Not on classic Nano. They are used for uploading code and serial monitor.

I was thinking logic chips like 74hc00 etc.

But if @b707 is correct (usually is) you won't need to worry about it.

1 Like

See this, look at "Control method 3" at the second page:
https://psc.byu.edu/00000179-d3e7-d7a6-a5fb-ffefc2af0001/bts-7960-motor-driver

1 Like

Decided to follow with option 5. Tested with 74LS00 and an additional bc547 (since I need 5 NAND gates to make a 1:2 demux) and it works like a charm, with a single PWM pin and a standard I/O I can control 1 motor back and forth. Thanks for the suggestions.

So that's 4x 74LS00 and 4 transistors for your 4 motors?

You could go with 2x 74HC08 quad AND gates and 1x 74HC04 hex inverters. (If you have 4 spare non-PWM pins, you won't need the inverters.)

HC series far superior to LS in almost all respects. Avoid buying LS.

If he have a 4 spare pins, he could use the module without any additional hardware, as stated in the link in #13

1 Like

Option 6: use PCA9685 to give you lots of PWM pins!

1 Like

I only use 2 motors, so 2 74hc00 and 2 transistors it is. Oh and LS instead of HC was because I found one among my electronics stuff. I’ll make sure to choose HC when I buy more parts for the project, if I find HC on my local electronics supplier. Thanks

Yes, I though about following along with that, but datasheet states it’s the least efficient control mode, so I followed Paul’s suggestion. But yours was nice too, thank you

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.