Hallo, ich habe folgendes Problem und bin schon echt am verzweifeln mit dem PIC. Vorgeschichte: Ich habe für ein elektrisches Einziehfahrwerk für einen Modelljet (11kg schwer) eine Steuerungselektronik gebaut. Die Motoren der Fahrwerke verfügen über magnetische Encoder um die Lage der Fahrwerksbeine zu bestimmen. Die Impulse der Encoder werden über die Timer 0, 3 und 5 gezählt. Beim Referenzieren fahren die Beine auf Anschlag und schalten mittels Überstrom ab. Die dabei gezählten Impulse werden gespeichert. Über das ECCP1 wird das Fernsteuerungssignal ausgewertet und das Fahrwerk fährt entweder ein oder aus. Zur Ansteuerung der 3 Motoren verwende ich drei VNH5180 Motortreiber. Diese besitzen einen PWM-Eingang der jeweils mit einem CCP-Modul (CCP 7, 8, 9) verbunden ist. Die Geschwindigkeit (Einschaltdauer des PWM-Signals) kann in einem Menü für jedes Fahrwerksbein separat eingestellt werden. Problem: Die Abschaltung der Fahrwerksbeine mit den gezählten Impulsen funktioniert nur korrekt, wenn die Einschaltzeit 100% beträgt. Sobald für den Ausgang 2 und einen anderen Ausgang die Einschaltzeit des PWM geringer ist schaltet der Timer 3 (zählt die Impulse des Motor2) zu früh ab. Je geringer die Einschaltdauer ist, desto früher kommt es beim Timer 3 zu einem Interrupt, der die Motoren stoppt. Wenn ich nur bei einem Fahrwerksbein ein PWM-Signal einstelle so funktioniert auch alles. Der Fehler tritt nur beim Ausgang 2 auf, wenn auch bei einem zweiten Ausgang die Einschaltdauer geringer ist. Ich habe leider keine Ahnung, woher der Fehler kommt. Ich hoffe, dass mir jemand eine Tipp geben kann, um das Problem zu lösen. Zur Programmierung des PICs verwende ich MPLAB X mit dem XC8 Compiler in der 60 Tage Pro Version. Anbei ein Foto des Fahrwerks mit dem Teststand und der betroffene Teil des Quellcodes. Vielen Dank für eure Hilfe. High Interrupt
1 | #include "Definition.h" |
2 | |
3 | |
4 | void interrupt high_isr(void) |
5 | {
|
6 | if(TMR0IE == 1 && TMR0IF == 1) |
7 | {
|
8 | TMR0IF = 0; //Flag lösche |
9 | INA1 = 0; //Motor stoppen |
10 | INB1 = 0; |
11 | motor1 = 0; //Variable für Motor = 0 => Motor ausgeschaltn |
12 | CCPR7L = 200; //PWM auf 100% für die Bremsung |
13 | if(Richt == 1) //Wenn die Richtung = 1 = Ausfahren => Enpostion = 0 = Ausgefahren |
14 | F1pos = 0; |
15 | if(Richt == 0) //Wenn die Richtung = 0 = Einfahren => Enpostion = 2 = Eingefahren |
16 | F1pos = 2; |
17 | CuError1 = 0; //Überttromfehler keiner |
18 | savep++; //Endpostion im main speichern, wenn alle Fahrwerk in Endpostion |
19 | return; |
20 | }
|
21 | |
22 | if(TMR3IE == 1 && TMR3IF == 1) |
23 | {
|
24 | TMR3IF = 0; |
25 | INA2 = 0; |
26 | INB2 = 0; |
27 | motor2 = 0; |
28 | CCPR8L = 200; |
29 | if(Richt == 1) |
30 | F2pos = 0; |
31 | if(Richt == 0) |
32 | F2pos = 2; |
33 | T3CONbits.TMR3ON = 0; |
34 | CuError2 = 0; |
35 | savep++; |
36 | return; |
37 | }
|
38 | |
39 | if(TMR5IE == 1 && TMR5IF == 1) |
40 | {
|
41 | TMR5IF = 0; |
42 | INA3 = 0; |
43 | INB3 = 0; |
44 | motor3 = 0; |
45 | CCPR9L = 200; |
46 | if(Richt == 1) |
47 | F3pos = 0; |
48 | if(Richt == 0) |
49 | F3pos = 2; |
50 | T5CONbits.TMR5ON = 0; |
51 | CuError3 = 0; |
52 | savep++; |
53 | return; |
54 | }
|
55 | }
|
Timer- und CCP-Einstellungen
1 | //Interrupt-Einstellungen
|
2 | INTCON = 0b11100000; //TMR0-Interrupt eingeschalten |
3 | INTCON2 = 0b10000100; //TMR0-Interrupt High priority |
4 | INTCON3 = 0b00000000; //External Interrupts = 0 => unwichtig |
5 | PIR1 = 0; //Flag bits = 0 |
6 | PIR2 = 0; //Flag bits = 0 |
7 | PIR3 = 0; //Flag bits = 0 |
8 | PIR4 = 0; //Flag bits = 0 |
9 | PIR5 = 0; //Flag bits = 0 |
10 | PIR6 = 0; //Flag bits = 0 |
11 | PIE1 = 0b01000000; //ADC-Interrupt |
12 | PIE2 = 0b00000010; //TMR3-Interrupt eingeschalten |
13 | PIE3 = 0b00000110; //Interrupt für ECCP1 und ECCP2 eingeschalten |
14 | PIE4 = 0b00000001; //Interrupt Enable bits = 0 |
15 | PIE5 = 0b00000011; //TMR5- & TMR4-Interrupt eingeschalten |
16 | PIE6 = 0; //Interrupt Enable bits = 0 |
17 | IPR1 = 0; //Alle diese Interrupts haben Low priority |
18 | IPR2 = 0b00000010; //TMR3-Interrupt High priority |
19 | IPR3 = 0; //Alle diese Interrupts (ECCP1 und ECCP2) haben Low priority |
20 | IPR4 = 0; //Alle diese Interrupts haben Low priority |
21 | IPR5 = 0b00000010; //TMR5-Interrupt High priority |
22 | IPR6 = 0; //Alle diese Interrupts haben Low priority |
23 | RCONbits.IPEN = 1; //Priority levels sind aktiviert |
24 | |
25 | |
26 | //ADC
|
27 | ANCON1bits.ANSEL9 = 1; //RF4 als analoger Eingang |
28 | ANCON2bits.ANSEL18 = 1; //RG2 als analoger Eingang (ISENSE3) |
29 | ANCON2bits.ANSEL20 = 1; //RH3 als analoger Eingang (ISENSE2) |
30 | ANCON2bits.ANSEL23 = 1; //RH0 als analoger Eingang (ISENSE1) |
31 | ADCON1 = 0b01110000; //Special trigger: CTMU; VREF+: 4,096V; VREF-: Masse; Neg. Chanel: Masse; |
32 | ADCON2 = 0b10001101; //Right; ACQU: 2xTAD; FOSC/16 |
33 | |
34 | |
35 | //Counter-Einstellungen
|
36 | T0CON = 0b00101000; //TMR0: Stop, 16-Bit, T0CKI, kein Prescaler |
37 | T3GCON = 0b00000000; //TMR3: Gate-Funktionen ausgeschalten |
38 | T3CON = 0b10000110; //TMR3: Stop, 16-Bit-Mode, nicht synchronisieren, T3CKl, Prescaler 1:1, Signale von T3CKl |
39 | T5GCON = 0b00000000; //TMR5: Gate-Funktionen ausgeschalten |
40 | T5CON = 0b10000110; //TMR5: Stop, 16-Bit-Mode, nicht synchronisieren, T5CKl, Prescaler 1:1, Signale von T5CKl |
41 | |
42 | |
43 | //Timer-Einstellungen
|
44 | T1CON = 0b00000011; //TMR1: Instruction Clock, Prescaler 1:1, 16Bit-Mode |
45 | T1GCON = 0; //Gate Control ausgeschalten |
46 | T2CON = 0b00000100; //TMR2 eingeschalten, Prescaler 1:1 |
47 | PR2 = 199; //TMR2 auf 20kHz eingestellt |
48 | |
49 | T4CON = 0b01111111; //TMR4: Postscaler: 1:16; Prescaler: 1:16, TMR4: ON |
50 | PR4 = 156; //=> 0,25ns*16*16*156=9984ns => ~10ms gibt es einen Interrupt |
51 | |
52 | |
53 | //Capture-Einstellungen
|
54 | CCPTMRS0 = 0; //Alle ECCP Timer 1 |
55 | CCP1CON = 0b00000100; //Capture eingestellt, steigende Flanke |
56 | |
57 | |
58 | //PWM-Einstellungen
|
59 | CCPTMRS1 = 0b00000000; //CCP4-7: TMR1/TMR2 |
60 | CCPTMRS2 = 0b00010000; //CCP8-9: TMR1/TMR2; CCP10: TMR7/TMR2 |
Impulse in Register schreiben und Motoren starten
1 | //Ausfahren des Fahrwerks
|
2 | if((1000 <= imp1alt && imp1alt <= 1495 && 1000 <= imp1neu && imp1neu <= 1495 && VBATlow == 0) || VBATlow == 1) //Nur ausfahren, wenn der neu under alte Impuls im selben Bereich liegen |
3 | { //Fahrwerk ausfahren, wenn die Akkuspannung zu gering ist |
4 | if(F1pos == 2 && F2pos == 2 && F3pos == 2) //Vorgang nur starten, wenn das Fahrwerk in der Enposition "Eingefahren" ist |
5 | {
|
6 | TMR0H = F1impH; //Impulse in die Timer schreiben |
7 | TMR0L = F1impL; |
8 | TMR3H = F2impH; |
9 | TMR3L = F2impL; |
10 | TMR5H = F3impH; |
11 | TMR5L = F3impL; |
12 | |
13 | eeprom_write(0x00, 1); //Fahrwerk befindet sich in keiner Endpostion |
14 | F3pos = F2pos = F1pos = 1; |
15 | Richt = 1; //Richt => Ausfahren |
16 | |
17 | CCPR7L = 100 + 10 * runos1; //Einschaltdeur der PWMs festlegen |
18 | CCPR8L = 100 + 10 * runos2; |
19 | CCPR9L = 100 + 10 * runos3; |
20 | |
21 | CCP7CON = 0b00001100; //PWM7 eingeschalten (Motor 1) |
22 | CCP8CON = 0b00001100; //PWM8 eingeschalten (Motor 2) |
23 | CCP9CON = 0b00001100; //PWM9 eingeschalten (Motor 3) |
24 | |
25 | T0CONbits.TMR0ON = 1; //Timer0 einschalten |
26 | motorausf(1); |
27 | |
28 | T3CONbits.TMR3ON = 1; //Timer3 einschalten |
29 | motorausf(2); |
30 | |
31 | T5CONbits.TMR5ON = 1; //Timer5 einschalten |
32 | motorausf(3); |
33 | |
34 | Anlauf = 1; |
35 | PWM = 1; |
36 | |
37 | WriteIns(0x80); |
38 | WriteBuch('R'); //R |
39 | WriteBuch('u'); //u |
40 | WriteBuch('n'); //n |
41 | WriteBuch('-'); //Space |
42 | WriteBuch('O'); //O |
43 | WriteBuch('u'); //u |
44 | WriteBuch('t'); //t |
45 | WriteBuch(' '); //Space |
46 | }
|
47 | }
|
48 | |
49 | |
50 | //----------------------------------------------------------------------------------------------------
|
51 | //----------------------------------------------------------------------------------------------------
|
52 | |
53 | //Einfahren des Fahrwerks
|
54 | if(1505 <= imp1alt && imp1alt <= 2000 && 1505 <= imp1neu && imp1neu <= 2000 && VBATlow == 0) |
55 | {
|
56 | if(F1pos == 0 && F2pos == 0 && F3pos == 0) //Vorgang nur starten, wenn das Fahrwerk in der Enposition "Ausgefahren" ist |
57 | {
|
58 | TMR0H = F1impH; |
59 | TMR0L = F1impL; |
60 | TMR3H = F2impH; |
61 | TMR3L = F2impL; |
62 | TMR5H = F3impH; |
63 | TMR5L = F3impL; |
64 | |
65 | eeprom_write(0x00, 1); |
66 | F3pos = F2pos = F1pos = 1; |
67 | Richt = 0; |
68 | |
69 | CCPR7L = 100 + 10 * runis1; |
70 | CCPR8L = 100 + 10 * runis2; |
71 | CCPR9L = 100 + 10 * runis3; |
72 | |
73 | CCP7CON = 0b00001100; //PWM1 eingeschalten |
74 | CCP8CON = 0b00001100; //PWM2 eingeschalten |
75 | CCP9CON = 0b00001100; //PWM3 eingeschalten |
76 | |
77 | T0CONbits.TMR0ON = 1; //Timer0 einschalten |
78 | motoreinf(1); |
79 | |
80 | T3CONbits.TMR3ON = 1; //Timer3 einschalten |
81 | motoreinf(2); |
82 | |
83 | T5CONbits.TMR5ON = 1; //Timer5 einschalten |
84 | motoreinf(3); |
85 | |
86 | Anlauf = 1; |
87 | PWM = 1; |
88 | |
89 | WriteIns(0x80); |
90 | WriteBuch('R'); //R |
91 | WriteBuch('u'); //u |
92 | WriteBuch('n'); //n |
93 | WriteBuch('-'); //Space |
94 | WriteBuch('I'); //I |
95 | WriteBuch('n'); //n |
96 | WriteBuch(' '); //Space |
97 | WriteBuch(' '); //Space |
98 | }
|
99 | }
|
100 | |
101 | |
102 | //------------------------------------------------------------------------------------------------------------
|
103 | //------------------------------------------------------------------------------------------------------------
|
104 | |
105 | Ueberstromabschaltung(); |
106 | |
107 | if(motor1 == 0 && motor2 == 0 && motor3 == 0 && PWM == 1) |
108 | {
|
109 | PWM = 0; |
110 | __delay_ms(40); |
111 | CCP7CON = 0; |
112 | CCP8CON = 0; |
113 | CCP9CON = 0; |
114 | }
|

