Schrittmotorsteuerung Atmega32

ANZEIGE

Anbei findet Ihr ein Programmierbeispiel in C für die Schrittmotorsteuerung mit Atmega32 Mikrocontroller. Programmiert habe ich die Steuerungssoftware in AVR Studio von Atmel.

Die Schrittmotor-Software ist in 5 Blöcke aufgeteilt:
1. main.c: Hauptprogramm. Hier wird die Sollposition des Kreuztisches vorgegeben.
2. speed_cntrl.c: Umsetzung der Steuerbefehle in Schrittmotorbewegung
3. speed_cntrl.h: Header Datei für speed_cntrl.c
4. endschalter.h: Definition der Referenzschalter für Nullpunkteinstellung
5. endschalter.c: Referenzfahrt an die Endschalter für Nullpunktbestimmung

Für den Quelltext

____________________________________________________________________________
Start main.c

#ifndef F_CPU
#define F_CPU 8000000 /* CPU Takt in HZ PROGRAMM FÜR 8MHZ OPTIMIERT*/
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
#include "speed_cntrl.h"
#include "endschalter.h"
#include <util/delay.h>
void initialisiere(void)
{
DDRB &=~(1<<PB0); // Endschalterpin y-Achse auf Eingang setzen
DDRB &=~(1<<PB1); // Endschalterpin x-Achse auf Eingang setzen
PORTB |=(1<<PB0); //Pullup an für Endschalter y-Achse
PORTB |=(1<<PB1); //Pullup an für Endschalter x-Achse
 
DDRC |= (1<<PC3)|(1<<PC4)|(1<<PC5); // y-Achse Schrittmotorsteuerungspins als Ausgänge setzen
PORTC |= (1<<PC3);// y- Achse Enable AUS
DDRD |= (1<<PD4)|(1<<PD5)|(1<<PD6); // x-Achse Schrittmotorsteuerungspins als Ausgänge setzen
PORTD |= (1<<PD4); //x-Achse Enable AUS
 
x.pos=50000; //maximale Endposition x-Achse
x.soll=0;
x.dir=0;
x.status=STOP;
x.stepcounter=0;
x.steps=0;
 
y.pos=50000; //maximale Endposition y-Achse
y.soll=0;
y.dir=0;
y.status=STOP;
y.stepcounter=0;
y.steps=0;
 
referenzx=0;
referenzy=0;
}
 
void main()
{
int h=0;
int s=0;
uint16_t sollx[]={19200,19200,19200,21733,21733,21733,24266,24266,24266};//Vorgabepositionen x-Achse
uint16_t solly[]={19750,17850,15950,15950,17850,19750,19750,17850,15950};//Vorgabepositionen y-Achse
 
initialisiere();
for(h=0;h<100;h++) //100 mal diese Schleife durchlaufen um insgesam1 100*30ms zu warten vor Programmstart
{
_delay_ms(30); //30ms warten
}
sei();// Interrupts global anschalten
 
next=2;
while(1)
{
endschalter_check(); //Referenzfahrt zu Endschaltern beginnen
while(next<9){
speed_cntrl_move(sollx[next],solly[next]); //definierte Position anfahren
do_anything();
next++; // nächste Sollposition anfahren
}
next=0; //Zurücksetzen der Zählervariable next
}
}
 
}

Ende main.c
____________________________________________________________________________
Start speed_cntrl.c

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "speed_cntrl.h"
#include <avr/pgmspace.h>
volatile static int ramp[] ={0,0,0,0,0,0,0,0,0,0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 95, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100};//Rampenwerte für Beschleunigen des Schrittmotors
volatile static int ramplength=51; //Anzahl der Rampenwerte
 
volatile int i=0; //Laufvariable für schrittx()
volatile int j=0; //laufvariable für schritty()
volatile int k=0; //laufvariable
 
void schrittx() //schrittimpuls für x-Achse
{
{
switch(x.dir)
{
 
case CCW:
PORTD |= (1<<PD6); //Direction x is positive
PORTD|=(1<<PD5);//high
PORTD&=~(1<<PD5);//low
x.pos++;
x.stepcounter++;
break;
 
case CW:
PORTD &=~ (1<<PD6); //Direction x is negative
PORTD|=(1<<PD5);//high
PORTD&=~(1<<PD5);//low
x.pos--;
x.stepcounter++;
break;
 
}
}
}
 
void schritty() //schrittimpuls für x-Achse
{
{
switch(y.dir)
{
case CW:
PORTC |= (1<<PC5); //Direction y is positive
PORTC|=(1<<PC4);//high
PORTC&=~(1<<PC4);//low
y.pos++;
y.stepcounter++;
break;
 
case CCW:
PORTC &=~ (1<<PC5); //Direction y is negative
PORTC|=(1<<PC4);//high
PORTC&=~(1<<PC4);//low
y.pos--;
y.stepcounter++;
break;
}
}
}
 
ISR(TIMER2_OVF_vect) //wenn Timer 0 (Achse x) überläuft
{
TCNT2=ramp[i];
switch(x.status)
{
case STOP:
PORTD |= (1<<PD4);//Motor_x Disable
i=0;
break;
 
case ACCEL:
i++;
if (i==1)
{
PORTD &=~ (1<<PD4);//Motor_x Enable } schrittx(); if(i>=(ramplength-1))
{
x.status=RUN;
}
if(x.stepcounter>=(x.steps-ramplength))//Prüfen, ob abgebremst werden muss
{
x.status=DECEL;
}
break;
 
case RUN:
i=ramplength;
schrittx();
if(x.stepcounter>=(x.steps-ramplength))//Prüfen, ob abgebremst werden muss
{
x.status=DECEL;
}
break;
 
case DECEL:
i--;
schrittx();
if(x.stepcounter==x.steps)//Prüfen, ob Motor gestoppt werden muss
{
x.status=STOP;
i=0;
}
break;
}
if(i<0)
{
i=0;
}
}
 
ISR(TIMER0_OVF_vect) //wenn Timer 2 (Achse y) überläuft
{
TCNT0=ramp[j];
 
switch(y.status)
{
case STOP:
PORTC |= (1<<PC3);//Motor_y Disable
j=0;
break;
 
case ACCEL:
j++;
if (j==1)
{
PORTC &=~ (1<<PC3);//Motor_y Enable } schritty(); if(j>=(ramplength-1))
{
y.status=RUN;
}
if(y.stepcounter>=(y.steps-ramplength))//Prüfen, ob abgebremst werden muss
{
y.status=DECEL;
}
break;
 
case RUN:
j=ramplength;
schritty();
if(x.stepcounter>=(y.steps-ramplength))//Prüfen, ob abgebremst werden muss
{
y.status=DECEL;
}
break;
 
case DECEL:
j--;
schritty();
if(y.stepcounter==y.steps)//Prüfen, ob Motor gestoppt werden muss
{
y.status=STOP;
j=0;
}
break;
}
if(j<0)
{
j=0;
}
}
 
int speed_cntrl_move(int32_t sollposix, int32_t sollposiy)
{
do
{
x.soll=sollposix;
y.soll=sollposiy;
 
if(set==0)//Diese Schleife wird nur 1 pro Positionierungfahrt durchlaufen, um Anzahl der notwendigen Schritte vorab zu bestimmen
{
//Für x-Achse:
x.steps=x.soll-x.pos;
if(x.steps<0)
{
x.steps=(-1)*x.steps;
}
x.stepcounter=0;
x.status=ACCEL;
//Für y-Achse:
y.steps=y.soll-y.pos;
if(y.steps<0)
{
y.steps=(-1)*y.steps;
}
y.stepcounter=0;
y.status=ACCEL;
set=1;
speed_cntrl_init_timer0();//Timer für x-Achse initialisieren
speed_cntrl_init_timer2();//Timer für y-Achse initialisieren
}
 
if(x.soll<x.pos) { x.dir=CW; } else if(x.soll>x.pos)
{
x.dir=CCW;
}
else
{
x.status=STOP;
}
 
if(y.soll<y.pos) { y.dir=CCW; } else if(y.soll>y.pos)
{
y.dir=CW;
}
else
{
y.status=STOP;
}
}while((x.status!=STOP)|(y.status!=STOP));
speed_cntrl_stop_timer();
 
set=0;
return 1;
}
 
void speed_cntrl_stop_timer(void)
{
TCCR0 &=~ (1<<CS02)|(1<<CS01)|(1<<CS00); // Timer0 anhalten
TCCR2 &=~ (1<<CS22)|(1<<CS21)|(1<<CS20);;// Timer2 anhalten
}
 
void speed_cntrl_init_timer0(void)
{
TCNT0=0;//Timer0 auf 0 zurücksetzen
TCCR0 |= (1<<CS01)|(1<<CS00); // Timer0, Prescaling 64
TIMSK |= (1<<TOIE0); //Interrupt für Timer0 freischalten
}
 
void speed_cntrl_init_timer2(void)
{
TCNT2=0;//Timer2 auf 0zurücksetzen
TCCR2 |= (1<<CS22);// Timer2, Prescaling 64
TIMSK |= (1<<TOIE2); //Interrupt für Timer 2 freischalten
}

Ende speed_cntrl.c
____________________________________________________________________________

Beginn speed_cntrl.h

#ifndef SPEED_CNTRL_H
#define SPEED_CNTRL_H
#define STOP 0
#define ACCEL 1
#define DECEL 2
#define RUN 3
#define CCW 1
#define CW 2
 
typedef struct {
int32_t pos;
int32_t soll;
int dir;
unsigned char status;
uint16_t stepcounter;
int16_t steps;
} axisdata;
 
volatile axisdata x;
volatile axisdata y;
int set;
void speed_cntrl_init_timer0(void);
void speed_cntrl_init_timer2(void);
void speed_cntrl_stop_timer(void);
int speed_cntrl_move(int32_t sollposix, int32_t sollposiy);
int next;
 
#endif

Ende speed_cntrl.c
____________________________________________________________________________
Beginn endschalter.h

#ifndef ENDSCHALTER_H
#define ENDSCHALTER_H
void endschalter_referenzfahrt_x(void);
void endschalter_referenzfahrt_y(void);
void endschalter_check(void);
int referenzx;
int referenzy;
#endif

Ende endschalter.h
____________________________________________________________________________
Beginn endschalter.c

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "speed_cntrl.h"
#include "endschalter.h"
#include <avr/pgmspace.h>
 
void endschalter_referenzfahrt_x(void)
{
        int32_t temp=0;
        temp=x.pos-1;
        speed_cntrl_move(temp,y.pos);
}
 
 
void endschalter_referenzfahrt_y(void)
{
        int32_t temp=0;
        temp=y.pos-1;
        speed_cntrl_move(x.pos,temp);
}
 
void endschalter_check(void)
{
        if (referenzy==0)
        {
            endschalter_referenzfahrt_y();
            if ((~PINB&(1<<PB1))==0)
            {
            referenzy=1;
            y.pos=0;
            }
        }
        if (referenzx==0&&referenzy==1)
        {
        endschalter_referenzfahrt_x();
            if ((~PINB&(1<<PB0))==0)
            {
            referenzx=1;
            x.pos=0;
            }
        }
}

____________________________________________________________________________
Die Steuerung auf Basis des Atmega32 Mikrocontrollers kannst Du im folgenden Bild sehen.

Bild der Mikrocontrollersteuerung

Steuerung mit Atmega 32 Mikrocontroller

Der Mikrocontroller gibt die Signale an die Schrittmotorendstufe aus, welche die Signale verstärkt. Als Schrittmotorendstufe habe ich in meinem Projekt folgende verwendet:

Schrittmotorendstufe

Schrittmotorendstufe für die CNC Achse

Hinterlass‘ mir einfach einen Kommentar, wenn Du Fragen zum Programmcode der Atmega32 Schrittmotorsteuerung hast!

ANZEIGE

Du willst noch mehr nützliche Tipps?

Tritt jetzt 200 Abonennten bei

CNC Fräsen leicht gemacht!
Die besten Tipps und Tricks kostenlos per E-Mail


 
   Keine Sorge. Spam ist für Affen. Aber wir sind echte Macher!
 
14 Comments

Kommentar hinzufügen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.




Blogverzeichnis - Blog Verzeichnis bloggerei.de by Toni