PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : PWM ---100% dutycycle , aber immernoch minnipulse?varriable



biele01
23.03.2010, 08:26
Hallo bastler.

Ich habe ein kleines problem mit meinem Arduino 2009 Board. Das Arduino hat von haus aus 6 PWM Ports zur verfügung. 2 davon können als HighPWM Port genutzt werden, indem ich ihre taktung intern durch gesetzte Register erhöhe. dazu habe ich einen timer der jede s bis 65535 zählt(allerdingds ist der timer irgendwie mit der frequenz des PWMPortes verknüpft)keine ahnung..... erreicht mein timer die hälfte der zu zählenden werte, setzt er den PWM Dutycycle auf 100% als 255. Sonst is er 0. Das heißt ich habe jetzt einen Pulse von 1Hz- die Frequenz kann ich mit einer varriablen regeln (mein eingelesener wert werte von 0 - 15000) indem ich nach jedemmal zählen den aktuell gemessenen wert dem counter dazu addiere. also eine geregelte Frequenz.

Jetzt funktioniert das hervorragend mit einer LED und Einen PiezzoLautsprecher. aber ich brauche das ganze um eine Schrittmotorensteuerung zu befeuern. (also ein Flankenwechsel von 3,4-5V zu <0,8V löst ein schritt aus.) und das ergebniss ist das mein Motor total verrückt spielt als würde er unzählige verschiedene impulse bekommen. Daraus schließe ich das das 100% dutycycle nicht aus einem Durchgängigen signal besteht sondern aus 65535 kleinen Flankenwechseln.???kann das sein?

habe einen kleinen Kondensator mal zwischen meinen Impulsausgang und SM Steuerung geklemmt, und siehe da das Flattern und summen ist fast weg aber komisch verhalten tut sich der Motor trotzdem noch. zb macht keine ichtigen Microschritte wie er soll. der code sieht etwa so aus...


void writetakt( uint8_t val ) {
OCR1A = (val);
}
uint16_t phase = 0;
uint16_t speed = 0;
uint8_t sample = 0;

SIGNAL(TIMER1_OVF_vect){
writetakt(sample);
phase += speed;

if(phase >= 32768)
sample = 0;
else
sample = 255;
if (frequenzkurve < 1 )
sample = 255;
}

wobei frequenzkurve mein eingelesener drehregler ist.
completter Code ist:

unsigned int frequenzkurve = 0;

void writetakt( uint8_t val ) {
OCR1A = (val);
}
uint16_t phase = 0;
uint16_t speed = 0;
uint8_t sample = 0;

SIGNAL(TIMER1_OVF_vect){
writetakt(sample);
phase += speed;

if(phase >= 32768)
sample = 0;
else
sample = 255;
if (frequenzkurve < 1 )
sample = 255;
}
////////////////////////////////////////////////////////////////////////////////////////////
unsigned int frequenzkurve_out = 0;

unsigned int frequenzkurve_B = 0;
unsigned int frequenzkurve_C = 0;
unsigned int frequenzkurve_D = 0;
unsigned int frequenzkurve_E = 0;
unsigned int frequenzkurve_F = 0;
/////////////////////////// IN und OUTPUT pins vergeben ///////////////////////////////////
int i=0;
int taktPin = 9; //Frequenz ausgang
int RCPin = 2; //PWM eingang
int Motor_drehrichtung = 13; // Richtungs Ausgang High = Linksrum Low = Rechtsrum
////////////////////////// zum einlesen des RC Signals //////////////////////////////////////
int timeX = 250;
int timeX_old = 250;
int timeX_old_B = 250;
int timeX_old_C = 250;
int timeX_fehler = 250;

int Toleranz_PWM = 20;


int timeX_final = 250;
int timeX_final_old = 250;
int timeX_final_old_B = 250;
int timeX_final_old_C = 250;
int timeX_final_old_D = 250;
int timeX_final_old_E = 250;
int timeX_final_old_F = 250;

float timeX_final_negativ = 250;
float timeX_halb = 250;


long lastPulseX = 0; // die Zeit in Millisecunden des letzten Pulses
long mstime = 0; // Liest die zeit in Millisecunden
long hptime = 0;
extern volatile unsigned long timer0_overflow_count;
unsigned long hpticks (void)
{
return (timer0_overflow_count << 8) + TCNT0;


}
////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
Serial.begin(115200); // Kommunikationsgeschwindigkeit Pc

pinMode (taktPin, OUTPUT);
pinMode(RCPin, INPUT); //R/C Pin als Input setzten
pinMode(Motor_drehrichtung, OUTPUT); //LED simuliet Rückwärtslauf (pin High versteht Schrittmotorsteuerung als RW)

TCCR1A = _BV(WGM10) | _BV(COM1A1);
TCCR1B = _BV(CS10) | _BV(WGM12);

TIMSK1 |= _BV(TOIE1);


}
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
void loop() {
//////////////////////////////////// RC einlesen erster Durchlauf (timeX_0ld)/////////////////////////////////////////

if(millis() - lastPulseX >= 5)
{ while(!digitalRead(RCPin) == HIGH) //Auf das Nächste RC Signal von RCPin Warten
{continue;}

mstime = millis();
hptime = hpticks(); //wenn das Signal Ankommt, Beginn der Startzeit aufzeichnun
while(!digitalRead(RCPin) == LOW)
{continue;}

mstime = millis();
timeX = (hpticks()) - hptime - 220; //Hier wird der unterschied zwischen start und endzeit ermittelt, Das Ergebnis ist das Rc Signal.

hptime = 0;
lastPulseX = millis();
}



///////////////////////////////////////////////////////////////////////////////////////////////
if (timeX > (timeX_old_C + Toleranz_PWM))
{

Serial.println("-ABGEFANGEN---");
Serial.println( timeX );
timeX_fehler = timeX ;
timeX = (0.2*timeX_old)+(0.3*timeX_old_B)+(0.5*timeX_old_C );
Serial.println("X");
Serial.println("-ANGEGLICHEN----");
Serial.println( timeX);
Serial.println("----------------------------");
if ( timeX == timeX_old_C)
{timeX =timeX_fehler;}
}
if (timeX < (timeX_old_C - Toleranz_PWM))
{
Serial.println("-ABGEFANGEN---");
Serial.println( timeX);
timeX_fehler = timeX ;
timeX = (0.2*timeX_old)+(0.3*timeX_old_B)+(0.5*timeX_old_C );
Serial.println("X");
Serial.println("-ANGEGLICHEN----");
Serial.println( timeX);
Serial.println("----------------------------");
if ( timeX == timeX_old_C)
{timeX =timeX_fehler;}
}
/////////////////////////////////////////////////////////////////
timeX_final = (timeX * 0.05) + (timeX_final_old * 0.05) + (timeX_final_old_B * 0.10)+
(timeX_final_old_C * 0.10)+ (timeX_final_old_D * 0.15) + (timeX_final_old_D * 0.20) + (timeX_final_old_D * 0.35);


if (timeX_final > 500)
{timeX_final = 500;}

if (timeX_final < 0)
{timeX_final = 0;}



if (timeX_final < 245)
{
timeX_final_negativ = timeX_final-(timeX_final * 2)+255;
frequenzkurve = ((timeX_final_negativ) * (timeX_final_negativ)*(0.1*timeX_final_negativ)/108);
digitalWrite (Motor_drehrichtung,HIGH);

}



if (timeX_final >= 250)
{
timeX_halb = timeX_final - 245;
frequenzkurve = ((timeX_halb) * (timeX_halb)* (0.1*timeX_halb)/91);
digitalWrite (Motor_drehrichtung,LOW);
}

frequenzkurve_out = (frequenzkurve * 0.05) + (frequenzkurve_B * 0.10) + (frequenzkurve_C * 0.15)+
(frequenzkurve_D * 0.20)+ (frequenzkurve_E * 0.20) + (frequenzkurve_F * 0.30);

timeX_old_C = timeX_old_B;
timeX_old_B = timeX_old;
timeX_old = timeX;

timeX_final_old_F = timeX_final_old_E;
timeX_final_old_E = timeX_final_old_D;
timeX_final_old_D = timeX_final_old_C;
timeX_final_old_C = timeX_final_old_B;
timeX_final_old_B = timeX_final_old;
timeX_final_old = timeX_final;

frequenzkurve_F = frequenzkurve_E;
frequenzkurve_E = frequenzkurve_D;
frequenzkurve_D = frequenzkurve_C;
frequenzkurve_C = frequenzkurve_B;
frequenzkurve_B = frequenzkurve;




speed = frequenzkurve_out;

/////////////////////////////////////////////////////////////////////////////////////////

/* Serial.print(timeX);
Serial.print("-------");
Serial.print(timeX_final);
Serial.print("-------");
Serial.println(frequenzkurve_out);
*/


}







also ich lese hier ein RC Signal ein(pin 2), glätte es in mehreren Stufen(0,1* erster wet+0,9*zweiterwert), filter ungewünschte fehlmessungen raus, erzeuge den counter und gebe eine frequenz aus(pin 9), und ein richtungssignal( auf pin 13).is etwas chaotisch.


Wie kann ich ein sauberes Rechtecksignal bekommen, oder es zumindest so glätten das ich 15kHz noch ausgeben kann aber alle frequenzen die weit darüber liegen geglättet werden.---Kondensator aber welchen?)

Richard
23.03.2010, 10:44
PWM ist eher für DC Motore als für Schrittmotore geeignet. Warum nimmst
Du nicht einfach einen Timer zur Frequenzerzeugung? Bei PWM würde
ich nicht das Puls/Pausen Verhältnis ändern, dabei bleibt ja die Frequenz
gleich. Da müsste dann die Wiederhohlfrequenz angepasst werden.


Gruß Richard

biele01
23.03.2010, 11:12
naja genaugenommen, bleibt ja das puls/pausenverhältniss gleich (glaube zumindest annähernd.) Ich bediene mich ja nur einen kleinen tricks. ich habe meine "Grund PWM Frequenz auf 65535 gesetzt. dann sage ich timerwerte von 0 bis 32768 ist das puls/pausenverhältniss 0, allso komplett kein strom.alle größeren timerzahlen sind 100% Strom. (eigentlich). dan sage ich ja das jenachdem wiehoch meine "Steuerzahl" ist den counter um diesen wert erhöht wird,bei jeden durchlauf(counter lauft schneller., was allerdings vermutlich zu einen ungleichen pulspausenverhältniss führt (brauche ja 50/50). glaube die art und weise wie ich das rechtecksignal generiere ist falsch, da es je nach wert niemals 50/50 ist.womöglich ist das der fehler.
Könnte es klappen wenn ich meinen timer 65535 mal jede secunde zählen lasse(konstant) und löse einen interrupt aus wenn meinen steuerzahl erreicht ist(die dann auch eine range bis 65535 haben muss) die beim 1 mal von high auf low setzt und beim 2. mal im gleichen zeitabstand wieder zurück auf High. somit hätte ich immer ein 50/50 Pulspausen verhältniss.????
vieleicht sind es ja nicht kleine minni Flankenwechsel, sondern meine schrittmotoren steuerung kommt mit den ständigwächselnden Pulspausenverhältnissen nicht zurecht?? ist das möglich? würde mir zumindest auch als fehlerquelle vorschweben.
Hab mich jetzt bisschen kompliziert ausgedrückt ich hoffe habts trotzdem verstanden was ich meine....

Richard
23.03.2010, 11:57
"Hab mich jetzt bisschen kompliziert ausgedrückt " Jaaaaa........:-)

Das kommt auf Deinen Prtozessor und den Quarz mit dem er
betrieben wird an. Du brauchst auch nicht wirklich ein 50/50
Verhältnis, solltest Dich aber für ein festes entscheiden.
Ein Schritt Motor schaltet dann bei jedem Tackt HI/LO einen
Schritt weiter. Wie lang der Schritt ist sollte (halbwegs) egal
sein. Wichtig ist die Wiederholfrequenz, ist die zu hoch verliert
der Motor Schritte und der Motor braucht auch eine Höhere
Spannung (Gegeninduktion)....Im RN Wissen Bereich ist (glaube ich)
ein Frequenzrechner mit den man ausrechnen kann was für einen
Teiler man für welchen Quarz nehmen muss um eine bestimmte
Frequenz zu erreichen. Deine 65535 werden bei z.B. 1600000Hz
alle 0,004s erreicht.......Womit Programmierst Du eigentlich?

Gruß Richard

biele01
23.03.2010, 14:48
also ich glaube ich werde es heut abend mal mit der statischen counterrate versuchen. so wie ich es jetzt habe ist eigentlich klar das das nichts richtiges werden kann ich hab absolut unregelmäßige pulspausenverhältnisse je höher mein eingelesener wert meines Steuerhebels ist. ..naja ich sag mal bescheid wies gelaufen is...
Ich Programiere Mit dem Arduino, dessen Programmiersprache ebenfalls Arduino heißt. basiert auf C++ und Processing.
( http://www.arduino.cc/en/Main/ArduinoBoardDuemilanove )
Also ich kann dir jetzt was erzählen aber wie gesagt ich hab damit erst vor ein paar wochen damit angefangen, und vorher nie was mit programmieren gemacht. Das Arduino ist echt super für einsteiger, da es speziel für Bastler und designer gemacht ist... Ich bin jedenfalls total begeister von.... Ich glaube mit einem C controll oder einem Anderen umgänglichen board wäre ich nicht soschnell zurecht gekommen...

Naja..soviel zu schleichwerbung....:-)

biele01
23.03.2010, 14:50
http://de.wikipedia.org/wiki/Arduino-Plattform

biele01
24.03.2010, 16:44
Hallo, also ich hab das problem gelöst. es war nicht das die Frequenz zu ungleichmäßig war. es waren die minni Flankenwechsel, wei jeden Interrupt aufruf. Ich hab die Funktion zum Schreiben auf pin 9 an einer falschenstelle vergeben. somit wurde die funktion 65535 mal aufgerufen in der sekunde, und nicht je gewünschten Rechteckimpuls..( writetakt(sample);) ist schuld gewesen.. der musste in die IF schleifen mit rein...

(auszug alter code)....
SIGNAL(TIMER1_OVF_vect){
writetakt(sample);
phase += speed;

if(phase >= 32768)
sample = 0;
else
sample = 255;
if (frequenzkurve < 1 )
sample = 255;
}

trotzdem danke fürs mitnachdenken-....