step motor ivmelenme algoritması

Başlatan berkay_91, 18 Ekim 2015, 14:39:32

berkay_91

mrb, nette step motor ramping ile ilgili bir çok matematiksel açıklama var ama C ile yazılmış anlaşılabilir bir hızlanma algoritması bulamadım. Atmel microdenetleyici ve A4988 kullanarak Nemanın(LINIX 42BYGHD444 ) step motorunu biraz hızlı döndürmek istiyorum bunun için bana herhangi bir link  veya step motor için C ile yazılmış ramping algoritması tavsiye edicek olan var mı?

magnetron

trapez şeklinde hız profili çalışmıyor mu ?

DaRt

Kaç devire çıkıyorsunuz ve hedefiniz kaç devir.

mufitsozen

Alıntı yapılan: berkay_91 - 18 Ekim 2015, 14:39:32
merhaba, nette step motor ramping ile ilgili bir çok matematiksel açıklama var ama C ile yazılmış anlaşılabilir bir hızlanma algoritması bulamadım. Atmel microdenetleyici ve A4988 kullanarak Nemanın(LINIX 42BYGHD444 ) step motorunu biraz hızlı döndürmek istiyorum bunun için bana herhangi bir link  veya step motor için C ile yazılmış ramping algoritması tavsiye edicek olan var mı?

/* for simulation we use stepper motor, model 28BYJ-48, that has 64 steps per round. It includes a gear unit with 64:1 ratio, so
that for 1 rotation of the output shaft we need to generate 64*64=4096 steps */
const long f = 1000000; //frequency of the counter;
int Km = 64, reduktor = 64, K = Km*reduktor,kasni=66;
// dspeed [rad/s]-desired speed, acce [rad/s^2]-acceleration
// dece[rad/s^2]-deceleration, ugao[deg]-angle
float dspeed = 3, acce = 0.5, dece = 1.5, ugao = 0;
double alfa = TWO_PI/K, Co, Cm, Ci,Ra,Rd;
long imaK = 0,N = 0,nad = 0,na = 0, nd = 0, np = 0, broj = 0;
boolean smjer = true, acc = true, stoj = true;
//uni-polar motor – we use microstepping manner of stepping
byte cw[] = {0x01,0x03,0x02,0x06,0x04,0x0C,0x08,0x09};
byte duzcw = sizeof(cw), kk = 0, maska = 0xF0; //
char chh;
//
void setup(){
Serial.begin(9600);
Serial.println("Enter some of the following commands:");
Serial.print("Uxxxx, - ");
Serial.println("desired angle[deg]x10");
Serial.print("Bxx, - ");
Serial.println("desired speed [rad/s]x10");
Serial.print("Axx, -");
Serial.println("acceleration[rad/s^2]x10");
Serial.print("Dxx, -");
Serial.println("deceleration[rad/s^2]x10");
Serial.print("S, - ");Serial.println("STOP");
Serial.print("M,- ");Serial.println("MOVE");
DDRB = 0x0F;//pins 8,9,10,11 of the Arduino are outputs
PORTB &= 0xF0;//four low bits of PORTB are zero
}
//
void loop(){
if (!stoj){ oneStep(smjer);
delayMicroseconds(Ci - ((Ci == Cm) ? 4 : kasni) );
Ci = solveC();
if (++np >= N) { np = 0; kk = 0; Ci = Co; stoj = true;
Serial.print("Steps = ") ;Serial.print(imaK);
Serial.print(", angle = ");Serial.println(imaK*360/K);
}
}
}
//one step in the desired direction, where 'desno' is direction
void oneStep(boolean desno){
if (desno) {PORTB=(PORTB& maska) | cw[kk++]; imaK++;}
else {PORTB=(PORTB & maska) | cw[duzcw-1-kk++];imaK--;} if ( kk == duzcw ) kk = 0;
}
//solve the time delay
double solveC(){ if (na == 0) return (Cm);
if ( (np<=na)||(np>=nd) ){//acceleration and deceleration phase
double q = 1+( (np<=na)?Ra:Rd )*Ci*Ci; Ci = Ci/q;kasni=66;
if ( ( (np>= 1 && (np<= 5)) || ((N-np <= 5) && ( N-np >= 1)))
{ Ci = Ci*(1+0.08/np) ; kasni=120;}//correction
if (Ci < Cm) Ci = Cm; //using variable 'kasni' we take into
} else Ci = Cm; return Ci; //account all delays occurred during
} /the call and execute of program
//this procedure calculate the parameters of the motion'
void init(float degU){
Ra=acce/(alfa*f*f); Rd=-dece/(alfa*f*f); Cm=alfa*f/dspeed;
N = (long) degU*K/360.0 - imaK; stoj = false;
if (N == 0) {stoj = true; return; }
if (N > 0) smjer = true;
if (N < 0) {smjer = false; N = -N;}
if (N == 1) oneStep(smjer);
// trajectory planning
if (acce != 0){// acceleration exists
nad = (long)(N*dece)/(acce+dece);
na = (long)(dspeed*dspeed)/(2*alfa*acce);
if (nad > na) { nd = N - na * acce/dece; }//case (i)
else { na = nad; nd = na; } //case (ii)
Co = f * sqrt(2*alfa/acce); Ci = Co;//Co is initial time delay
} else {//without acceleration
na = 0; nd = N; Ci = Cm;
}
if (nd < na) { // this is might be due to rounding
long np=na; na=nd;nd=np;//exchange the values of 'na' and 'nd'
} np = 0;
}
//this function is called for every cycle in the loop procedure
void serialEvent(){ //command of the stepper motor
if (Serial.available() > 0 ){
char ch = toupper(Serial.read());
if ((ch == 'S') || (ch == 'M')) chh = ch;
if ((ch == 'U') || (ch == 'B') || (ch == 'A') || (ch == 'D')){
chh = ch; broj = 0;
}
//if ch is alphanumeric than calculate of the parameter value
if (ch >= '0' && ch <= '9') broj = broj * 10 + (int)ch-'0';
if (ch == ','){//comma is denoted end of command
if (chh == 'U') {ugao = broj/10.0; init(ugao);}
if (chh == 'B') dspeed = broj/10.0;
if (chh == 'A') acce = broj/10.0;
if (chh == 'D') dece = broj/10.0;
if (chh == 'S') stoj = true; //STOP moving
if (chh == 'M') stoj = false; //continuoe the moving
broj = 0;
}
}
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

berkay_91

Alıntı YapKaç devire çıkıyorsunuz ve hedefiniz kaç devir.

devir için bir hedefim yok, çıktığım max. deviride henüz ölçmedim, şuanda hız kontrolünü pot ile sağlıyorum belli bir değerden sonra motor iyice hızlanıyor ve duruyor tabi bunun nedeni şuanki programda herhangi bir ivme döngüsü yok, sinyal kontrolünüde PWM ile sağlıyorum amacım basit bir lineer veya exponansiyel ivme döngüsü ekleyerek biraz daha hızlı dönmesini sağlamak

engerex

 Motor ivmelenmede ne çeşit algoritmalar kullanılıyor?


iyildirim

7500 RPM de  dönsün yeter.   :)
Step BLDC farketmez.

@berkay_91
Anladığım kadarı CNC, eksen vs gibi birşeyler yok.
Bu durumda uygulanabilecek en basit yol PWM frekansını yavaş yavaş arttırmak.
Bunun için de timer kesmesinde frekansı belirleyen register değerini, belli bir limite kadar  üçer beşer azaltmak olabilir. PWM ile aynı timer ı kullanabilirsiniz ama  hızlanma lineer olmaz, gittikçe artar  Ayrı bir timer ile lineerlik vs de sağlanabilir istenirse.

CNC eksen gibi şeyler sözkonusu ise, adım sayısı da önemli ise alttaki dökümanın 4. sayfasındaki (dökümanda 27 denmiş.) tabloda gösterilen 5 durumu da kontrol etmek gerekli.
http://www.ti.com/general/docs/lit/getliterature.tsp?baseLiteratureNumber=slyt482&fileType=pdf


Alttaki döküman iki step arasındaki beklemeyi ivmeye göre formüle ediyor. @mufitsozen hocamın verdiği örnekteki algoritma da buna benzer.
http://www.google.com.tr/url?sa=t&rct=j&q=&esrc=s&source=web&cd=11&cad=rja&uact=8&ved=0CGYQFjAKahUKEwiCj-i8zMzIAhVLFSwKHVCHAcg&url=http%3A%2F%2Fhwml.com%2FLeibRamp.pdf&usg=AFQjCNFjdT8OSt-XbFXgRxUjEFxQYxYHTQ&sig2=scsyRuD0hlH0_TmVU5EN_g


Karamel

#8
hocam y=x seklinde değilde. mesela y=(x^3)/16 seklinde artis saglasak nasil olur? hayatimda elektrik motoru gormedim desem yeridir. sadece bunu brainstorming yapmak icin dusundum.  :-\

plot:



mesaj birleştirme:: 19 Ekim 2015, 00:00:10

az once deneyini yaptim. exponential olarakta guzel bir artis elte edilebiliyor.

mesela: y = e^((x/2)-3)

berkay_91

#9
motoru döndüren programı, Attiny 84 de aşağıdaki program üzerine kurdum. aşağıdaki programıda ben yazdım netten bulmadım eksikler olabilir ama çalışıyor...

#define F_CPU 1000000UL
#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>

volatile unsigned long F_PWM;

#define PWM_RESOLUTION (unsigned char)(F_CPU / (F_PWM*1024UL))

void pwm_init();
int Read_adc();
void adc_init();


void pwm_init(){ // MODE 15, prescalar is 256, Timer1 16 bit

   TCCR1A=(1<<WGM10)|(1<<WGM11)|(1<<COM1B1);
   TCCR1B=(1<<WGM12)|(1<<WGM13)|(1<<CS12);
}

void adc_init(){
	
  ADMUX = 0x00; // adc pin is selected ADC0 and referance voltage is VCC
  ADCSRA = (1<<ADEN)|(1<<ADPS0)|(1<<ADPS1);  // prescalar is used 8
  ADCSRB = (1<<ADLAR); // 8 Bit ADC için
}

int Read_adc(){
	
	ADCSRA |= 0x40;			// start the adc conversion
	while(ADCSRA & 0x40);  
	return ADCH;         // ADCW = adc low bits + adc high bits
}


int main(){
	
	DDRA=(1<<5); // OC2B
	adc_init();
	pwm_init();
	
	while(1){
		
		F_PWM=Read_adc()+5;
		
		OCR1A=PWM_RESOLUTION - 1;
		OCR1B=(PWM_RESOLUTION/2)-1; // % 50 duty sycle
	
	}		
	return 0;			
}


bu gibi bir programda motoru döndüren döngüden önce şöyle bir döngü eklesem ivme için nasıl olur

        F_PWM=Read_adc()+5;
	
	int kontrol=5;
	
	while(F_PWM>=kontrol-1){ // hızlanma rampası
	
	      F_PWM=kontrol;
	      OCR1A=PWM_RESOLUTION - 1;
	      OCR1B=(PWM_RESOLUTION/2)-1; // % 50 duty sycle
	      kontrol++;
	      _delay_ms(1);
         }