2

I am currently implementing the following setup:

Arduino Mega 2650 -- DRV8834 -- Stepper motor

Everything works fine, however since it can provide a higher torque I want to run the stepper in half step mode. Each step is triggered by a single pulse coming from the Arduino to the driver. If one uses the Digital Pins for this purpose as done by AccelStepper, the maximum frequency is around 1000 pps (points per second). This is a third of what I want to achieve. The second option would be to use the PWM of the Arduino which naturally runs at 16 MHz (way to high). There is a way to downgrade this frequency, however the steps are only discrete and not accurate enough for a nice speed control.

Therefore I want to do the following

Arduino Mega 2650 -- Controller -- DRV8834 -- Stepper motor

whereby the Controller is creating a PWM with a frequency (100 to 3000 Hz) depending on some signal coming from the Arduino (I2C, voltage level or something else). I was now searching two days for a component and have no clue what I could use.

How can I create a PWM from 100 to 3000Hz with an arduino?


Edit 1: I have to read out sensors while the motor is running. Therefore, the so called "bit banging" PWM

void loop(){
digitalWrite(pinSTEP, HIGH);
delayMicroseconds(T/2); 
digitalWrite(pinSTEP, LOW);
delayMicroseconds(T/2);
}

where T = 1 / f is not feasible since I have to read out a sensor in the loop which destroys the motor timing.


Edit 2: There is a method to change the register of the timers. One can adapt a so called prescalar values (from 0 to 7) which will define the frequency of our PWM. However with only seven discrete steps this leads to the following freuquencies:

prescalar = 1 ---> PWM frequency is 31000 Hz
prescalar = 2 ---> PWM frequency is 4000 Hz
prescalar = 3 ---> PWM frequency is 490 Hz (default value)
prescalar = 4 ---> PWM frequency is 120 Hz
prescalar = 5 ---> PWM frequency is 30 Hz
prescalar = 6 ---> PWM frequency is <20 Hz

which is not sufficient for my application.

For more about this method:


Sometimes a solution is so easy that it hurts ;) Based on the input of this wonderful community I found my solution. Code:

#include <TimerThree.h>
// TimerThree PWM Pins 2, 3, 5

#define pinPWM       2
#define pinM0        22
#define pinM1        24
#define pinSleepnot  28
#define pinDir       30

void setup(void){

  // Define output pins
  pinMode(pinM0, OUTPUT);
  digitalWrite(pinM0, HIGH);
  pinMode(pinM1, OUTPUT);
  digitalWrite(pinM1, LOW);
  pinMode(pinSleepnot, OUTPUT);
  digitalWrite(pinSleepnot, HIGH);
  pinMode(pinDir, OUTPUT);

  // Initialize serial communication
  Serial.begin(9600);

}

void loop(void){

  for (float frequency = 500; frequency < 3000; frequency = frequency + 1) {
    float T = 1 / frequency * 1000000;
    Serial.print("Frequency: ");
    Serial.println(frequency);
    Timer3.initialize(T);
    Timer3.pwm(pinPWM, 100);
    delay(5);
  }
}
5
  • Do you need to count steps? Do you just use it for speed control or do you have an encoder? If you only need to control speed, maybe a voltage to frequency converter would do the trick. E.g. ti.com/product/LM331
    – AngeloQ
    Commented Feb 24, 2017 at 16:17
  • Dive into the Mega 2560 PWM hardware. I am sure it can be run at some speed suitable to you. But you might need to do it yourself instead of relying on the Arduino libraries.
    – Wouter van Ooijen
    Commented Feb 24, 2017 at 17:01
  • The premise of your question is based on misunderstanding, you can toggle digital pins a lot faster than 1 KHz. Commented Feb 24, 2017 at 17:28
  • I do not need to count steps. I have a position read out system for that. I will have a look at the PWM hardware stuff. I had a look at that one already: arduino.cc/en/Tutorial/SecretsOfArduinoPWM but it seemed to me that the steps are quiet big between the discrete frequency levels, but perhaps i got it wrong. The problem with the toggling is somehow that it will block the microcontrollers processor (please correct me if I am wrong) and I could not continue reading out my sensors at the same time.
    – h_uat
    Commented Feb 24, 2017 at 20:59
  • @AngeloQ: which voltage to frequency converter would you have in mind? I had a look at the other comments and i think it is not working with that. (see my edits in the post)
    – h_uat
    Commented Feb 25, 2017 at 7:16

3 Answers 3

0

How can I create a PWM from 100 to 3000Hz with an arduino?

Your question is really "How can I create a PWM from 100 to 3000Hz with an Atmega2560"?

The Atmega has various timers which can be configured in many ways. You can alter the prescaler (ratio of processor clocks to timer ticks) and the amount it counts up to. Certainly you can change the frequency and duty cycle.

I have a page about timers which may help you.


I have to read out sensors while the motor is running. Therefore, the so called "bit banging" PWM ... is not feasible

Yes, don't do "bit banging" when you have 5 hardware timers.


One can adapt a so called prescalar values (from 0 to 7) which will define the frequency of our PWM.

Adapt the prescaler and the timer configuration. Between them you have very fine control.

1
  • Thank you very much sir! Sometimes a solution is so easy that it hurts if you find it ;)
    – h_uat
    Commented Feb 25, 2017 at 9:48
1

You might need to move away from the AccelStepper library, and 'roll your own', but as others have pointed out, the MCU certainly has the bandwidth to do this directly. I understand that PWM resolution may not give smooth ramping, but I would probably look into using a timer interrupt. The timer ISR would count steps and you would only need to adjust the timer compare register to change the step frequency.

2
  • I will have a look into this tomorrow. But the AccelStepper library is really not suitable. I thought the 1000 pps limit would be related to the hardware. I also tested the stepper with an oscilloscope and it worked at very high freuquencies quiet smooth. Thanks for the input!
    – h_uat
    Commented Feb 24, 2017 at 20:53
  • 1
    If you want to see what people squeeze out of ATmegas in the way of stepper control, look into open source 3D printer firmwares. Beyond that there are various ARM parts easily pushing 6 if not 10 times the clock rate that could make things easier, where you aren't trying to maintain a legacy tradition. Commented Feb 24, 2017 at 21:10
0

the maximum frequency is around 1000 pps

Arduino pin operations takes about 100 ticks. Or 400 ticks for four pins. No more than another 100 ticks for processing and logic ops. So I would expect 500 ticks or 30k on a 16mhz Arduino.

Much faster if you use direct pin ops.

So maybe the code you used isn't well written or your Arduino is doing lots of other things?

edit:

I found my solution. Code:

there is no reason for you to repeatedly initialize the module. this thing is simple, and others have laid out the thought process for you. write a set of routines that spin the motor - spin it left, spin it right. and then call those routines in a timer isr. nothing fancy here.

2
  • I use the AccelStepper library. I will try to find a software work around :) Thanks for the input!
    – h_uat
    Commented Feb 24, 2017 at 20:54
  • Please see my edits in the post. I think this method is not working for me. Do you have anything else in mind?
    – h_uat
    Commented Feb 25, 2017 at 7:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.