Atmega with Stepper motor (DRVB885 driver)

Go To Last Post
17 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm currently working at a project for school with three stepper motors, for this I'm using a nema17 stepper motor and a DRVB885 stepper motor driver. The driver is controlled by an arduino mega 2560. I want to control three things, the steps from the motor (number of PWM pulses), the speed of the motor (PWM period time) and the direction of the motor. I wrote a program to do these three things, unfortunatly my program doenst work. I get no errors or warnings (like most of the time in c) and its very hard to rotate the shaft of the stepper motor when the program is running. the motor doenst make any noise, this pushes me in to direction that the motor is being directed but duration of the pulses or setup is wrong. anyone an idea?

this is the code that I wrote:

 

#define F_CPU 16000000ul 

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "basic_help.h"

#define motor_a 1
#define dir_a_pin 1 //A1 - F
#define step_a_pin 3 //6 - H


void motor_setup() {
    
    pinmodeOutput(step_a_pin, &DDRH);
    pinmodeOutput(dir_a_pin, &DDRF);
    
    digitalWrite(en_a_pin,1,&DDRD); // disable motor
    digitalWrite(dir_a_pin,0,&DDRF); // set initial motor direction
    
    TCCR3A = 0;
    TCCR3B = 0;
    TCCR3A = (1<<COM3A1) | (1<<COM3B1) | (1<<WGM31) | (1<<WGM30); //clear timer on compare match & set timer at bottom - set pwm to fast pwm - 
    TCCR3B = (1<<CS30) | (1<<CS32) | (1<<WGM33) | (1<<WGM32);  //internal clock with CLK/1024 prescaling
    TIMSK3 = (1<<OCIE3A) | (1<<OCIE3B); //generate intterrupt when matches B register
    
};

int aantal_stappen;

ISR(TIMER0_COMPA_vect)      //PWM => COMPA  MAX, COMPB
{
    if(aantal_stappen>0)
    {
        digitalWrite(dir_a_pin,1,&DDRF); // enable direction
        digitalWrite(step_a_pin,1,&DDRH); // set pin PWM
        aantal_stappen--;
        
    }
    else if(aantal_stappen<0)
    {
        digitalWrite(dir_a_pin,0,&DDRF); // disable direction
        digitalWrite(step_a_pin,1,&DDRH); // set pin PWM
        aantal_stappen++;
    }
        
}
ISR(TIMER0_COMPB_vect)
{
    digitalWrite(step_a_pin,0,&DDRH); // reset pin PWM
}

int main(void)
{
    motor_setup();
    OCR0B = 156;   // clock of 16Mhz ==> prescaler 1024 ==> 15625  divided by 156 ==> 100hz 
    OCR0A = 50;     
    
    sei();
    aantal_stappen = 1000;
    
    while (1)
    {
    }
}


.c file basic_functions

void pinmodeOutput(int pin_nr, volatile uint8_t *ddr){
    *ddr |= (1<<pin_nr);
}

void digitalWrite(char pin_nr, int highLow, volatile uint8_t *port){
    if(highLow) {
        *port |= (1<<pin_nr);
        } else {
        *port &= ~(1<<pin_nr);
    }
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Welcome to AVRFreaks!

 

Hummm, I'm a little confused, I'll assume you meant you are using a TI DRV8885 stepper motor driver, with that chip you only need to set one pin h/l for forward/backward direction, and send a clock pulse for it to move with each clock pulse, the driver chip does the rest, what do you need PWM for? 

 

Suggest you post either a picture of your setup, and/or schematic of your circuit, then we may be able to help. 

You said it was a school project, most posters say they can not use arduino for class, although it is an excellent platform for such things, and we would suggest you use one to test your h/w with using known good s/w (arduino sketch for stepper using DRV8885 controller) That way you are only solving one problem at a time (i.e. your software) and not trying to also verify your h/w works at the same time!!!!

Once you know the h/w works, then you can proceed to solve your s/w issues, and have a working example to work from.

 

Have you read any of the app notes on stepper motors so you know how they work?

 

Jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 I want to control three things, the steps from the motor (number of PWM pulses), the speed of the motor (PWM period time) and the direction of the motor. 

Well, that goes without saying...it is a stepper motor...if you want to move it you have no choice!!  As mentioned, the chip has the smarts, so PWM is not really part of your activities.  You tell it when to take a step & which way to move.

PWM & timer are closely related, so you might really be meaning timer when you say pwm?  Such as, set the timer to make a step pulse every 10ms, or whatever you like.

One thing you can control, that you don't mention,  is acceleration (how fast you ramp up//down the step rate.

 

Have you written any program that just outputs a few step pulses? Nothing fancy, just a few lines of code, timers not even needed (other than delay).  You need to first, so that you can see if the motor even moves at all.  Lots of chances for bad wiring, weak supplies, ground bounce, etc.

low

delay

high  take a step 

delay

low

delay

high

delay take a step

low

 

Or make a loop....probably better..take 100 steps...does it move?

 

Do NOT try working with 3 steppers right now, get ONE working. Forget about the others. You can add a lot of confusion or port problems dealing with 3 all at once.

So far you haven't controlled anything...get one working well. 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Fri. Oct 30, 2020 - 07:58 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
 digitalWrite(en_a_pin,1,&DDRD); // disable motor

If your comments are correct, that writing a '1' does indeed 'disable' the motor, I don't see it being re-enabled anywhere.  That it's 'stiff' - hard to turn - implies that it has actually been enabled.   S.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are using a PWM Fast mode that uses OCR3A as top, you then set OCR0A to 50 and OCR0B to 156, which I assume you mean to use OCR2A/OCR3B except you will never get to 156 since TOP is 50.

 

You also show en_a_pin which is not defined anywhere, so I guess this is not actual code. And if it was defined, you appear to be disabling the motor by setting a pullup on that pin (since the pin is still an input). There is no other reference to this pin, so maybe the enable pin is not used.

 

Your code-

https://godbolt.org/z/TMY4Pe

slight mods to make it compile, gave en_a_pin a value, also made some functions static, and swapped setting OCR3A/B so A is 156 (and changed from using OCR0A/B). Still have to deal with en_a_pin in some way.

Last Edited: Fri. Oct 30, 2020 - 08:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks for your reply, the reason why I use pwm is to control the speed as well. As you mentioned the driver has only dir en step pin, so in orther to regulate the speed has to be done by pwm. Maybe the most important reason if there is an another way of doing it is because my teacher told to do it with pwm. We got a program where only the functions where defined so whe got an idea from the flow of the program. I filled it in basicly with the pin numbers, calculations to do the pwm with the prescalers, setup of the pwm. Maybe there's another way but I think I'm not allowed to change that like I want . If it is possible I would like to get I running this way smiley  The driver is indead a  TI DRV8885 , i uploaded a photo of the schematic as well. PS: it is not homework, it is a project from school. only thing is whe got a week 'vacation' now but i need this to move on with the project.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks for your answer! I wrote a simple script in arduino to see if it worked, the simple program made it more easier to understand the principle as well. problem is I need to control the speed and it needs to be integrated in a project that is written in atmel studio. The code has variables to control 3 motors, so if I want I can run this function in the future for the three of them, like you said one up and running is enouf for now.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, you are totally right, this is the code that is used in the project, only pin that isnt connected is the enable pin. reason why I did this is because I travel a lot by train, every wire that gets lose or lost is one to much. To program on the train easely to I make those setups with only the essential connections. Anyway thanks a lot for your modifications, I tested them but unfortunatly there's something esle not right. with a simple arduino the program runs, so think the setup is right. But on atmel the motor doenst run with you modified code.....

Last Edited: Fri. Oct 30, 2020 - 09:11 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

so in orther to regulate the speed has to be done by pwm.

No, pulse width has nothing to do with the speed per se. When you give it a pulse it takes a step, the width makes no difference whatsoever.  The speed is controlled by how MANY pulses you give it in a second, this is set by your timer config. 

So in other words, the duty cycle can be 1% or 88%, the only thing that matters is the timer portion (or frequency).  There are many timer modes that can set different pulse rates.  Now PWM does prevent you from generating excessively high frequencies, since it  uses a timer with a divider (like up to 8 ,9, 10 bits), so that severely limits the max frequency (to KHz).    Does that make more sense?  When you use PWM with these drivers, you are only using its rate, not width.  In the old days with "dumb" drivers, it would eb a different story.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Fri. Oct 30, 2020 - 09:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ow okay sorry then I was competly wrong. I thought that it therefore that I had to use the fast pwm....

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ow okay sorry then I was competly wrong. I thought that it therefore that I had to use the fast pwm....

You could take a doorbell button and tap  tap tap & should see steps.  Any contact bounce might be too fast to cause much extra steppings---not sure.

 

They prob asked you to use pwm, since that is one easy way to make a steady frequency.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Fri. Oct 30, 2020 - 09:21 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The usual reference for calculating stepper acceleration, etc: 

http://web.archive.org/web/20140...

and

https://www.embedded.com/generat...

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The reference code for controlling a number of motors would be GRBL methinks. You might want to have a look at that project to see how they control the motors.

 

As the others have mentioned, pwm is not what you really want. If you want to try something simple, just use a delay to generate the pulse timing, then move to using a timer.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can control the acceleration of the motor very simply by using another timer.  Each tick IRQ,  just set the frequency (speed) of the main timer generating steps to a faster or slower value.  Say every 10ms increase the stepper speed by 2 rpm   ...in one second you'll be running 200 rpm faster. So if you are winding up a rope to lift a bucket of AVR chips, it will move faster and faster.  You can set the numbers to whatever level suit your fancy.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Fri. Oct 30, 2020 - 11:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AVR446 is all you need.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Further notes in. re. acceleration: 

 

Stepper motors do very well with a nice step acceleration ramp.  You can't just splat a high frequency on the 'step' pin and expect it to work - it won't, it'll make bad noises and stay put.

 

I use a binary rate multiplier for (simple) stepper motor speed control.  Basically, you have a large accumulator A, and add a smaller (or equal) number X to it on a regular basis - generated by a timer T.  Every T you add X to A.  When A overflows, you output a step.  Obviously, if X is small, A will overflow very rarely.  If X is large (as large as A) then it will overflow every T, and therefore T is your maximum frequency.

 

Given (say) a 16-bit A and a 65(.536)kHz T, you can have a range of speeds from 1Hz (X = 1) to 65kHz-ish (X=216-1).  Increment X to accelerate, decrement X to slow down.  When X = 0 it will go nowhere - even if the algorithm keeps running.

 

I find that a bit simpler than most folks' algorithms.  Maybe not perfectly linear...  smiley  S.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you just want to ramp up to speed (say you are making a pump for a mustard dispenser for your hamburger), you just slowly increase the speed setting (generated pulses/sec) over time by some means: counter, timer, or otherwise. Anytime you increase the speed, that's acceleration & you can easily get an average linear accel over a relatively long (many steps) interval. You don't necessarily know how "far" you traveled during this time & don't really care, you just want to get to the target speed over a reasonable timeline.   You don't have a particular location in mind.   When you need to hit a specific target at a specific place or time (or both), of course it is much tougher  (I need to accel/decel so to arrive at house next door in 5.38 sec), equations become your friend.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!