Hallo zusammen
Ich implementiere gerade eine Strommessung für einen
Brushless-Controller. Hierzu ist es von Nöten quasi die "Mitte" einer
PWM-Phase zu ermitteln.
Da zwar einen Overflow-Interrupt aber kein Top-Interrupt vorhanden ist,
benutze ich den Compare-Match-Interrupt A mit OCR2A = 255. Mein Problem
ist, dass dieser aus einem mir unerfindlichen Grund zwar ausgeführt
wird, sich aber kein Bisschen an OCR2A hält.
Die Initialisierung erfolgt folgendermassen:
1 | inline void PWM_init()
|
2 | {
|
3 | //MOSFET-Pins
|
4 | DDRD |= (1<<M_AP) | (1<<M_BP) | (1<<M_CP);
|
5 | DDRC |= (1<<M_AN) | (1<<M_BN) | (1<<M_CN);
|
6 |
|
7 | //Timer 1 (16Bit): PhaseCorrect-PWM, 8bit bis 255
|
8 | TCCR1A = (0<<WGM11) | (1<<WGM10) | (1<<COM1B1) | (1<<COM1A1);
|
9 | TCCR1B = PRESCALER_1;
|
10 |
|
11 | //Timer 2 (8Bit): PhaseCorrect-PWM bis 255
|
12 | TCCR2A = (0<<WGM21) | (1<<WGM20) | (1<<COM2B1);
|
13 | TCCR2B = PRESCALER_1_Timer2;
|
14 |
|
15 | //Compare-Match Interrupt der Strommessung
|
16 | OCR2A = 255;
|
17 | }
|
Der PWM-Wert (bei Timer2 wird hierzu einfach nur OCR2B benutzt) wird
live gesetzt. Sobald ein AC-Interrupt der sensorlosen Motor-Steuerung
erfolgt, läuft eine Phase-Erkennung durch. Jede Sekunde wird nun der
Compare-Match Interrupt (TOP_INT_ON) eingeschaltet:
1 | ISR(ANALOG_COMP_vect)
|
2 | {
|
3 | switch (Phase)
|
4 | {
|
5 | //... Teil entfernt
|
6 |
|
7 | case 2:
|
8 | SENSE_A;
|
9 | SENSE_RISING;
|
10 | COM_2;
|
11 | CommutationCounter++;
|
12 | if(compare_time(SenderWatchdog))
|
13 | {
|
14 | SenderWatchdog = calculate_time(625);
|
15 | sei();
|
16 | TOP_INT_ON;
|
17 | }
|
18 | Phase++;
|
19 | break;
|
20 |
|
21 | //... Teil entfernt
|
22 | }
|
23 | }
|
Ich verstehe somit nicht, warum folgende Interrupt-Routine ausgeführt
wird, der ausgelesene TCNT2-Wert sich aber unabhängig von OCR2A (schon
völlig verschiedene Werte getestet) meistens bei ca 230 befindet. Meiner
Meinung nach, sollte dieser ca. bei 254 liegen.
Was mir auch noch aufgefallen ist: der Interrupt erfolgt immer vor der
ersten PWM-Wave. Will heissen: der Interrupt wird bei Aktivierung
sofort ausgeführt und wartet anscheinend nicht einmal bis zum ersten
möglichen Compare-Match.
1 | ISR(TIMER2_COMPA_vect)
|
2 | {
|
3 | uint8_t data = TCNT2;
|
4 | u_transmit(data);
|
5 | PORTA ^= (1<<GREEN);
|
6 | TOP_INT_OFF;
|
7 | }
|
Zu Testzwecken wird lässt dieser Interrupt einfach ein LED togglen und
übermittelt den TCNT2-Wert per UART. Anschliessend schaltet er sich
selbst ab, da er nur ca jede Sekunde erfolgen soll.
Vielen Dank
Gruss, AP