Kannst du uns den Quelltext zeigen? Der Fehler liegt vermutlich an anderer Stelle ...
Klar - im Prinzip. Aber sechstausend Zeilen Quelltext ist halt etwas viel . . . Vielleicht reichen diese Auszüge:
Auszug main
Code:
// - - - - - - - - - - - - - - -
// Ports+Pins als Ein- (0) oder Ausgänge (1) konfigurieren, Pull Ups (1) aktiv.
// A = Ausgang, E = Eingang ohne , EU = Eingang MIT PullUp
DDRB = 0b11111111; // siehe aktuell oben oder Fortschrittsbericht
PORTB = 0b00000000; // und Port/Pull Ups (1) aktivieren
//
DDRC = 0b11000010; // PC0 .. 6 , kein PC6+7-Pin bei m168/328 in THT
PORTC = 0b00000000; // PC0, ~2 und ~3 sind ADC-Eingänge ##>> OHNE Pullup !!
//
DDRD = 0b11000000; // RX+TX Eingang mit Pullup
PORTD = 0b00111111; // Pull Ups aktivieren, mit pololuMot AUCH bei INT0/~1
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
for(i=0; i<10; i++) // gLED2(PB5) blinken lassen bevor Interrupts erlaubt sind
{ // um ungewollte Resets u.ä. besser erkennen zu können
SetBit(PgLED, L1g); // gnLED1 schalten EIN, HELL, aktuelle PC1
SetBit(PORTB, 3 ); // ###>>> TEST
wms (3); // ###>>> Die onBoard-LEDs schalten A<->Portpin <<<###
ClrBit(PgLED, L1g); // gnLED1 schalten AUS, Dunkel
ClrBit(PORTB, 3 ); // ###>>> TEST
wms (97); //
} // Ende von for(i=0; i<10; i++)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Izthrznt = 20000; // Der ZeitHorizont für ISR(TIMER2_COMPA_vect)
//ncx0 = 128; // Messwert-Pointer auf "keine Messwerterfassung"
ncxP = 200; // Prescaler für 1/100 sec bei Messwerterfassung
ncxF = 1; // Messertflag; 1 <=> Wert darf gespeichert werden
Izeit_1 = Izthrznt; //
Isecundn = 1; // Sekundenzähler, max 9 Stunden - NUR hier nullen
TC2TMR_init(); // Init Timer/Cntr2-Interrupt 20 kHz/50 µsec tmr
// ISR gibt auf PB2 ein Servosignal aus
// - - - - - - - - - - - - - - -// Hier die notwendigen Werte für Motorbetrieb=Encoder, Regelfaktoren etc
// .. erforderlich VOR Initialisierung der externen Interrupts und Regelung
nenc0 = 0; // Encoder-Prescaler, nur jeden nenc0-ten Übergang zählen
nenc1 = 0;
Kp12 = 1; // Regelfaktor P-Anteil !!! Divisor, lt fahrtest = 4 (1/4)
Kp34 = 1; // Regelfaktor P-Anteil !!! Divisor ### war 5
Ki12=Ki34 = 22; // Regelfaktor I-Anteil !!! Divisor
Kd12=Kd34 = 4; // Regelfaktor D-Anteil !!! Divisor
//ATSfak = 1856; // AnTriebsStrang-faktor => Umrechnung von mm/s auf stupsi
ATSfak = 619; // AnTriebsStrang-faktor => Umrechnung von mm/s auf stupsi
regel12=regel34 = 0; // Ein-Ausschalter Regelung, regel = 1 => Regelung ist EIN
rglsv12 = regel12; rglsv34 = regel34; // Regelflag, Sicherung
XTI_0_1_init( ); // Init extINT 0 und 1 mot
TC0CMPit(); // Init TmrCnt0 CmprMtchA, Regelungsaufruf 100Hz/Kanal tmr
TC1PWM_init(); // Init Tmr/Cntr1 für PWMs/Mot12 + Mot34 mot
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
sei(); //Globalen Interrupt freigeben
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
inKOlst(); // Initialisierung, KOnstanten-Liste = div. Vorgaben kal
// Aufruf NACH sei(), weil evtl irDME´s abgefragt werden.
init_uart0 ( F_CPU / BAUD / 16 - 1 ); // Init UART0 (NICHT nach PDannegger)
I2C_init (); // I2C-Buffer initialisieren, I2C-Slave-Init I2C
// - - - - - - - - - - - - - - -
wms ( 1000); // Zeit fürs Startinfo - NUR FÜR TESTphase ! ! !
info01(); // Startinfo über USART ausgeben main
Auszug *com*.h
Code:
volatile s16 M12ocr; // temporärer Stellwert für OCR1A -255...255
volatile s16 M12inc; // vorzeichenbehaft. Incr, default: -1, +1
volatile s16 tdek1; // Timer-Dekrement = Vorgabe für tmot1
volatile s16 P4soll; // PWMsollwert bei Aufruf wird aus speed übernommen,
// speed wird nicht weiter verwendet
volatile s16 M34ocr; // temporärer Stellwert für OCR1A -255...255
volatile s16 M34inc; // vorzeichenbehaft. Incr, default: -1, +1
volatile s16 tdek4; // Timer-Dekrement = Vorgabe für tmot4
inKOlst
Code:
// ============================================================================== =
void inKOlst (void) // Initialisierungen
{ //
// war 50 bis 30. Dez. 2013
tdek1 = 6; // default Startwert PWM-Timer - wird dekrementiert
tdek4 = 6; // default Startwert PWM-Timer - wird dekrementiert
return; //
} //
// ============================================================================== =
Auszug Timer
Code:
// ============================================================================= =
// === Nicht unterbrechbare ISR für timer2 =================================== */
// Takt 20 Ips bei 20Mhz - Routine für regelmässige Abläufe mit
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ISR(TIMER2_COMPB_vect) // Vekt 0x008, Timerroutine für "allgemeine Zwecke"
{ // .. die nicht so eng zeitgebunden sind
// - - - - - - - - - - - - - - - -
Izeit_2 --; // ###>>> Izeit_2 ist aktuell int16_t ==>>
if ( !Izeit_2 ) // WENN Izeit_2 != Null => wahr => Anweisung ausgeführen
{ // Eine Sekunde ist voll => Izeit_2 auf Hrznt_2 setzen
Izeit_2 = Hrznt_2; // ansonsten: Rückstellen auf Zeithorizont2
} // Ende if ( !Izeit_2 )
// - - - - - - - - - - - - - - - -
// PWM-Rampe für Motor1/Mot12 - wird über tmoti/tdeki gesteuert
if ( tmot1 ) // Ist der Rampencounter != 0 ?
{ //
tmot1 --; // ... dann dekrementiere ihn bis
if ( !tmot1 ) // ... der Rampenwert abgelaufen ist
{ //
M12ocr = M12ocr + M12inc; //##>>Übegang zu NEGATIVEn M12ocr möglich
// Es folgt Drehrichtungsumkehr NACH Nulldurchgang
// war if (( M12ocr < 0) && (-1 == M12ocr)) Mrechtszur (); und sinngemäß //
if (-1 == M12ocr) Mrechtszur (); //
if ( 1 == M12ocr) Mrechtsvor (); //
// Setze OCR1A aus vorzeichenbehaftetem M12ocr
if (M12ocr >= 0) OCR1A = M12ocr; //
else OCR1A = -1*M12ocr; //
if (M12ocr == P1soll) tmot1 = 0; // Rampe12: Ende mit Sollwert erreicht
else tmot1 = tdek1; // ansonsten ReInit Timer auf Rampenwert
} // Ende if ( !tmot1 )
} // Ende von if ( tmot1 )
// - - - - - - - - - - - - - - - -
// PWM-Rampe für Motor4/Mot34
if ( tmot4 ) // Rampencounter > 0
{ //
tmot4 --; //
if ( !tmot4 ) // Wenn Rampenwert abgelaufen ist
{ //
M34ocr = M34ocr + M34inc; //##>>Übergang zu NEGATIVEn M34ocr möglich
// Es folgt Drehrichtungsumkehr NACH Nulldurchgang (siehe auch oben)
if (-1 == M34ocr) Mlinksvor (); //
if ( 1 == M34ocr) Mlinkszur (); //
// Setze OCR1A aus vorzeichenbehaftetem M34ocr
if (M34ocr >= 0) OCR1B = M34ocr; //
else OCR1B = -1*M34ocr; //
if (M34ocr == P4soll) tmot4 = 0; // Rampe34: Ende mit Sollwert erreicht
else tmot4 = tdek4; // ansonsten ReInit Timer auf Rampenwert
} // Ende if ( !tmot4 )
} // Ende von if ( tmot4 )
// - - - - - - - - - - - - - - - -
return;
} // Ende ISR(TIMER2_COMPA_vect)
// ============================================================================= =
Quelltext sprung (kplt) - hier wurde der falsche Wert entdeckt:
Code:
// ============================================================================= =
// == Fahre Sprungfunktion, messe Sprungantwort Aufruf aus r1n/do_MOSTL2
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void sprung ( u8 m_buff[14] ) // Fahre Sprungfunktion, messe Sprungantwort
{ //
// - - - - - - - - - - - - - - - -
//char abc[12]; // Übersetzungsfeld für Werteausgabe UART
char s[10]; // lok. String zum Dekodieren der SOLLFAHRT mm/sec
s16 s16mot = 0; // SOLLfahrt Motor, 2 Bytes : unsigned int16_t
u8 i = 0; // Variable
u8 motNR; // MotorNummer 1 (mot12) oder 4 (mot34)
u8 vz = 0; // Drehrichtungscode: 45 = li, 43 = re, 112 = aus
// - - - - - - - - - - - - - - - -
// ncx0 wird mit Wert 255 im main initialisiert und damit "abgeschaltet"
// WENN ncx0 < 128 ist (erstes Bit ist 0) dann wird im Timer0 incrementiert
//ncx0 = 255; // Initialisiere Pointer auf 1 vor Überlauf
// - - - - - - - - - - - - - - - -
// Die aufrufenden Parameter als Kontrolle/Bestätigung auf UART ausgeben
for ( i=0; i<9; i++) { s[i] = m_buff [i]; } // Aufrufparameter kopieren
s[9] = 0; // Markiere Stringende "0"=letzten Bitfeldelement
uputs0 ("\r\t>>\t");uputs0 ( s );
// - - - - - - - - - - - - - - - -
// Regelungen und sonstige Parameter abschalten:
regel12 = regel34 = 0; // BEIDE REGELUNGen ausschalten
// - - - - - - - - - - - - - - - -
// Dekodiere PWM-Vorzeichen und PWM-Stellwert
vz = m_buff[3]; // Drehrichtungscode: 45 = '-' => math neg
for ( i=0; i<=2; i++) { s[i] = m_buff [i+3]; } // im Byte 2 bis 5 {0-5}
s[3] = 0; // Markiere Stringende "0"
s16mot = atoi ( s ); // vorzeichenbehafteter Motor-/PWM-Stellwert
// - - - - - - - - - - - - - - - -
// Motor NR dekodieren und Daten melden
motNR = m_buff[1] - 48; // nmot ist die Motornummer 1 (12) oder 4 (34)
if ( !(motNR == 1) && !(motNR == 4) ) return; // NUR mot12 oder mot34
uputs0 ("\r\tmotNR "); uputs0i ( motNR ); // Nenne Motorkennung
uputs0 ("\tSprung=> ");
uputs0 ("\tPWM/tdek ");
if ( s16mot < 0 ) s16mot = 0 - s16mot; // s16mot MUSS positiv werden
// - - - - - - - - - - - - - - - -
// Motor auswählen, einschalten und Test fahren;
// Anmerkung: die Auswahl "5"<=> beide Motoren ist für die Messung der
// Sprungantwort nicht sinnvoll wegen der Datenerfassung
switch ( motNR ) // Fallunterscheidung nach Motornummer
{ //
case 1: // Anmerkung: ASCIIcode: 45 = '-' => math neg
Mrechtsaus (); // Zur Sprungaufnahme erstmal stoppen und
wms ( 1000); // Auslauf abwarten
uputs0i(s16mot);uputs0 ("/");uputs0i(tdek1);
break; //
case 4: //
Mlinksaus (); // Zur Sprungaufnahme erstmal stoppen und
wms ( 1000); // Auslauf abwarten
while ( Izeit_1 <= 15000 ) { } // Nix tun, wenn Zeit zu kurz
uputs0i(s16mot);uputs0 ("/");uputs0u(tdek4); // #####
break; //
default:
break;
} // Ende switch ( motNR )
//uputs0 ("\t\tMot=on"); // Gefahr von Zeitverzug beim Starten, daher
// diese Meldung lieber erstmal nicht ausgeben
// - - - - - - - - - - - - - - - -
// Warten um nicht mit der Messung in einen Zeitüberlauf zu kommen
while ( Izeit_1 <= 15000 ) { } // Nix tun, wenn Zeit zu kurz, damit
// die Messung nicht in einen Time-Überlauf läuft
// Fünf Messungen IM STILLSTAND VOR DEM MOTORSTART
switch ( motNR ) // Fallunterscheidung nach Motornummer
{ //
case 1: // Anmerkung: ASCIIcode: 45 = '-' => math neg
for ( i = 0; i < 6; i++ ) //
{ //
messdat1 [ i] = Izeit_1; // Zeit = volatile s16 messdat1..3[100]
messdat2 [ i] = IencB0; // s16 - Encoderstand
// messdat3 [ i] = OCR1A; // PWM-Wert
wms ( 2); // Ungefährer Messwert-Abstand
} // Ende for ( i = 1; i < 100; i++ )
if (vz==45) Mrechtszur (); // Motortreiber 1 auf '+' math pos stellen
else Mrechtsvor (); // Motortreiber 1 auf '-' math neg stellen
OCR1A = s16mot; //
break; //
case 4: //
for ( i = 0; i < 6; i++ ) //
{ //
messdat1 [ i] = Izeit_1; // Zeit = volatile s16 messdat1..3[100]
messdat2 [ i] = IencB1; // s16 - Encoderstand
// messdat3 [ i] = OCR1B; // PWM-Wert
wms ( 2); // Ungefährer Messwert-Abstand
} // Ende for ( i = 1; i < 100; i++ )
if (vz==45) Mlinksvor (); // Motortreiber 4 auf '+' math pos stellen
else Mlinkszur (); // Motortreiber 4 auf '-' math neg stellen
OCR1B = s16mot; //
break; //
default:
break;
} // Ende switch ( motNR )
// - - - - - - - - - - - - - - - -
// ####>>>> Der Motor läuft jetzt, Daten also SOFORT beim Hochlaufen erfassen
// danach ne WEile warten !!! UND den Motor wieder ausschalten !!!
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Es werden jetzt die aktuellen Daten festgehalten für Messfahrt
// Beispiel von ..C2\D01-3_40\D01-3_40_mot_x23.c vom 15. Oktober 2009, 11:12:46
// ##>> Der folgende, aktuelle Code ist neu gestaltet
switch ( motNR ) // Fallunterscheidung nach Motornummer
{ //
case 1: // Anmerkung: ASCIIcode: 45 = '-' => math neg
for ( i = 6; i < 30; i++ ) //
{ //
messdat1 [ i] = Izeit_1; // Zeit = volatile s16 messdat1..3[100]
messdat2 [ i] = IencB0; // s16 - Encoderstand
// messdat3 [ i] = OCR1A; // PWM-Wert
wms ( 2); // Ungefährer Messwert-Abstand
} // Ende for ( i = 1; i < 100; i++ )
break; //
case 4: //
for ( i = 6; i < 30; i++ ) //
{ //
messdat1 [ i] = Izeit_1; // Zeit = volatile s16 messdat1..3[100]
messdat2 [ i] = IencB1; // s16 - Encoderstand
// messdat3 [ i] = OCR1B; // PWM-Wert
wms ( 2); // Ungefährer Messwert-Abstand
} // Ende for ( i = 1; i < 100; i++ )
break; //
default:
break;
} // Ende switch ( motNR )
switch ( motNR ) // Fallunterscheidung nach Motornummer
{ //
case 1: // Anmerkung: ASCIIcode: 45 = '-' => math neg
for ( i = 30; i < 100; i++ ) //
{ //
messdat1 [ i] = Izeit_1; // Zeit = volatile s16 messdat1..3[100]
messdat2 [ i] = IencB0; // s16 - Encoderstand
// messdat3 [ i] = OCR1A; // PWM-Wert
wms ( 4); // Ungefährer Messwert-Abstand
} // Ende for ( i = 1; i < 100; i++ )
uputs0 ("\r\tiMessg\tIzeit_0\tIencB0\tOCR1A");
break; //
case 4: //
for ( i = 30; i < 100; i++ ) //
{ //
messdat1 [ i] = Izeit_1; // Zeit = volatile s16 messdat1..3[100]
messdat2 [ i] = IencB1; // s16 - Encoderstand
// messdat3 [ i] = OCR1B; // PWM-Wert
wms ( 4); // Ungefährer Messwert-Abstand
} // Ende for ( i = 1; i < 100; i++ )
uputs0 ("\r\tiMessg\tIzeit_0\tIencB1\tOCR1B");
break; //
default:
break;
} // Ende switch ( motNR )
// - - - - - - - - - - - - - - - -
//uputs0 ("\r\tiMessg\tIzeit_0\tIencB0");
for ( i = 0; i < 100; i++ )
{ //
uputs0 ("\r\t"); uputs0i ( i );
uputs0 ("\t"); uputs0u (messdat1[i]);
uputs0 ("\t"); uputs0u (messdat2[i]);
// uputs0 ("\t"); uputs0u (messdat3[i]);
} // Ende for ( i = 0; i < 100; i++ )
wms ( 2000); // Warte Sprungantwort ab
switch ( motNR ) // Motor aus mit Fallunterscheidung nach Motornummer
{ //
case 1: //
Mrechtsaus (); // mot
break;
case 4: //
Mlinksaus (); // mot
break;
default: //
break;
} // Ende switch ( motNR )
uputs0 ("\r\tSprungantwort steht\r");
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
} // Ende void sprung ( void )
// ============================================================================= =
Lesezeichen