Forum: Mikrocontroller und Digitale Elektronik PWM Modul von Stellaris Cortex M3 - LM3S8971 BLDC Kit


von Felix (Gast)


Angehängte Dateien:

Lesenswert?

Hallo an alle und einen herzlichen Dank an dieses Forum,

(es hat meinen Kollegen und mir schon vielfach gute Dienste geleistet - 
vielen Dank)

wie die Suche gezeigt hat, sind zumindeste einige (Wenige) hier auch mit 
einem Stellarisboard unterwegs. Z. Zt. beginne ich gerade damit zu 
arbeiten und habe noch ein Problem(chen):

Vorweg: Es geht um einen permanent erregten Synchronmotor, der als 
bürstenlose Gleichstrommaschine betrieben wird: BLCD

Was das Programm machen soll: Blocksteuerung der drei Phasen A, B und C, 
basierend auf 3 Halbbrücken. (Schaltungsausschnitt, Phase C, als Bild im 
Anhang)

Meines Erachtens habe ich die PWM-Module richtig konfiguriert, sodass 
eine Blocksteuerung entstehen sollte. Im Debugmodus sehe ich auch die 
Register des MCs "klappern" (Die eingestellten Parameter werden, soweit 
man das erkennen kann, in die Register übernommen). Habe ich da 
irgendein Enable oder ähnliches vergessen? Ich bin dabei nach Beispiel 
aus dem Handbuch vorgegangen.
(Quelletext am Ende)

Nur am eigentlichen Ausgang (Phase A, B oder C) kann ich nichts messen. 
Vom Verständiss her: Im Debugmodus (Schrittweise Programmabarbeitung) 
müsste ich doch die "Highspannung" am Ausgang (beispielw. Phase C) 
messen können, wenn das korrespondierende PWM-Modul eben den Schalter 
"Highspannung" öffnen lässt.
Alternative Methode zum Messen der Phasenspannung: Es handelt sich um 
ein Entwicklerboard, da könnte man ja auch an elektronischen Schaltern 
messen, ob diese durchschalten?! (Spannungsmessung über dem Ventil Q5, 
an Pin2 gegen Masse: unangesteuert -> "Sternpunktspannung", 
angesteuertes Ventil -> Highspannung")

Laut Datenblatt sind das  N-Kanal Mosfets. Ich habe die oben 
beschriebene Messung bei abgetrenntem Motor durchgeführt (also kein 
Stromfluss). Da ich keine Leuchte in elektronischen Bauelementen bin 
folgende Frage: Kann es sein, dass ich bei dieser Messung erst zu einem 
vernünftigen Ergebnis komme, wenn da ein Strom durch die Ventile 
durchfließt oder hat das damit rein gar nichts zu tun?

Wäre für hilfreiche Antworten sehr dankbar, ich sitze da schon leider 
eine gute Woche dran und es will mir nicht gelingen :-/

Felix

Programmtext: ein Funktion PWMBeispielBlocksteuerung, die im 
nachfolgenden Main aufgerufen wird.
1
void PWMBeispielBlocksteuerung(unsigned long varPeriode)
2
{
3
  //
4
  //  Saftey First - erstmal sicherheitshalber Deaktivieren
5
  //
6
  
7
  PWMGenDisable(PWM_BASE, PWM_GEN_0);
8
  PWMGenDisable(PWM_BASE, PWM_GEN_1);
9
  PWMGenDisable(PWM_BASE, PWM_GEN_2);
10
  
11
  //
12
  // Configure the PWM generator for count down mode with immediate updates
13
  // to the parameters. 
14
  //Pulse Width Modulator (PWM)
15
  
16
  PWMGenConfigure(PWM_BASE, PWM_GEN_0,
17
  PWM_GEN_MODE_UP_DOWN);
18
  
19
  PWMGenConfigure(PWM_BASE, PWM_GEN_1,
20
  PWM_GEN_MODE_UP_DOWN);
21
  
22
  PWMGenConfigure(PWM_BASE, PWM_GEN_2,
23
  PWM_GEN_MODE_UP_DOWN);
24
25
  //PWMClock-Teiler setzen
26
  SYSCTL_RCC_R |= SYSCTL_RCC_USEPWMDIV + SYSCTL_RCC_PWMDIV_64;  
27
  
28
  // Set the period. For a 50 KHz frequency, the period = 1/50,000, or 20
29
  // microseconds. For a 20 MHz clock, this translates to 400 clock ticks.
30
  // Use this value to set the period.
31
  //3,125 MhZ / SYSCTL_RCC_PWMDIV_64/ 5Hz = 3,125x10^6 / 64 / 5 = 
32
  //  varPeriode = SystemFrequenz / Zieltaktfrequenz
33
  
34
  varPeriode = SysCtlClockGet() / 64 / varPeriode;
35
  
36
  PWMGenPeriodSet(PWM_BASE, PWM_GEN_0, varPeriode);
37
  PWMGenPeriodSet(PWM_BASE, PWM_GEN_1, varPeriode);
38
  PWMGenPeriodSet(PWM_BASE, PWM_GEN_2, varPeriode);
39
  
40
  
41
  // Setze Werte für Compare A Register
42
  PWM_0_CMPA_R = PWM_1_CMPA_R = PWM_2_CMPA_R = varPeriode/3;
43
44
  // Setze Werte für Compare B Register
45
  PWM_0_CMPB_R = PWM_1_CMPB_R =  PWM_2_CMPB_R = varPeriode*2/3;
46
47
  
48
//   PWM0 Generator A Control (PWM0GENA) - Aktionen für CMP_AU/D und CMP_BU/D 
49
    PWM_0_GENA_R = 0xE0;
50
    PWM_1_GENA_R = 0x230;
51
    PWM_2_GENA_R = 0x380;
52
  
53
//   PWM0 Generator B Control (PWM0GENB) - Aktionen für CMP_AU/D und CMP_BU/D
54
    PWM_0_GENB_R = 0xB00;
55
    PWM_1_GENB_R = 0xC02;
56
    PWM_2_GENB_R = 0x23;
57
  
58
  //
59
  // Start the timers in generator 0,1,2.
60
  //
61
  PWMGenEnable(PWM_BASE, PWM_GEN_0 );
62
  PWMGenEnable(PWM_BASE, PWM_GEN_1 );
63
  PWMGenEnable(PWM_BASE, PWM_GEN_2 );
64
  //
65
  // Enable the outputs.
66
  //
67
  PWMOutputState(PWM_BASE, (PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_2_BIT |
68
  PWM_OUT_3_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT), true);
69
70
}
71
72
73
int
74
main(void)
75
{
76
//*****************************************************************************
77
//
78
// ulPeriod     Dauer definieren
79
//
80
//*****************************************************************************
81
unsigned long ulPeriod = 0;
82
83
//*****************************************************************************
84
//
85
// ulDelay      Verzögerung definieren
86
//
87
//*****************************************************************************
88
unsigned long ulDelay=0;   
89
90
91
    //
92
    // If running on Rev A2 silicon, turn the LDO voltage up to 2.75V.  This is
93
    // a workaround to allow the PLL to operate reliably.
94
    //
95
    if(REVISION_IS_A2)
96
    {
97
        SysCtlLDOSet(SYSCTL_LDO_2_75V);
98
    }
99
100
    //
101
    // Configure the processor to run at 3,125 MHz.
102
    //
103
    SysCtlClockSet(SYSCTL_SYSDIV_64 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
104
                   SYSCTL_XTAL_8MHZ);
105
106
    //
107
    // Enable the peripherals used by the application.
108
    //
109
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
110
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
111
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
112
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
113
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
114
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
115
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
116
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM);
117
    SysCtlPeripheralEnable(SYSCTL_PERIPH_QEI0);
118
    //
119
    // Enable the peripherals that should continue to run when the processor
120
    // is sleeping.
121
    //
122
123
    SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOA);
124
    SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOB);
125
    SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOC);
126
    SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOD);
127
    SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOE);
128
    SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOF);
129
    SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOG);
130
    SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_PWM);
131
    SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_QEI0);
132
    //
133
    // Enable peripheral clock gating.  Note that this is required in order to
134
    // measure the the processor usage.
135
    //
136
    SysCtlPeripheralClockGating(true);
137
138
    //
139
    // Set the priorities of the interrupts used by the application.
140
    //
141
    IntPrioritySet(INT_GPIOB,       0x20);
142
    IntPrioritySet(INT_GPIOD,       0x20);
143
    IntPrioritySet(INT_PWM0,        0x80);
144
    IntPrioritySet(INT_PWM1,        0xa0);
145
    IntPrioritySet(INT_PWM2,        0xc0);
146
    IntPrioritySet(FAULT_SYSTICK,   0xc0);
147
148
    //************************************ HIER GEHTS LOS
149
    
150
    PWMBeispielBlocksteuerung(5);
151
    
152
      
153
    ulPeriod = SysCtlClockGet() / 10; 
154
    ulDelay = ((ulPeriod / 2) / 3) - 4 ;
155
156
    PWMBeispielBlocksteuerung(5);
157
158
    SysCtlDelay(ulDelay);
159
    
160
    PWMOutputState(PWM_BASE, (PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_2_BIT |
161
    PWM_OUT_3_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT), false );
162
  
163
// Berechnung Strom durch Ventile  R=U/I=> I= 12V / 2x300mOhm = 20Ampere 
164
// Dauerstromtragfähigkeit der Ventile ~50 Ampere -> SAFE
165
     
166
    while(1)
167
    {
168
        //
169
        // Put the processor to sleep.
170
        //
171
      
172
#ifndef DEBUG
173
        SysCtlSleep();
174
#endif
175
    }
176
}

von Felix (Gast)


Lesenswert?

In der Funktion
1
 void PWMBlockSteuerung(unsigned long varPeriode)

haben noch ein paar Zeilen zur Initialisierung der PWM-Module gefehlt 
(Ausgangsrichtung festlegen, Pins als PWM konfigueren etc.):
1
// Alternative Funktion des jeweiligen Pins wählen
2
  GPIO_PORTF_AFSEL_R |= GPIO_PIN_0 + GPIO_PIN_1;  
3
4
// Pin für PWM Konfigurieren  -  Unnötig da es sich um ein Fury-Class-Chip handelt       
5
/*  GPIOPinConfigure(GPIO_PF0_PWM0);
6
  GPIOPinConfigure(GPIO_PF1_PWM1);
7
*/
8
9
// GPIOS als PWM-Pin konfigurieren
10
  GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_0 + GPIO_PIN_1);
11
12
// GPIO als Ausgänge festlegen
13
  GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, (GPIO_PIN_0 + GPIO_PIN_1));
14
15
// Gleiche Befehle nur für die weiteren 2 Phasen
16
  GPIO_PORTE_AFSEL_R |= GPIO_PIN_0 + GPIO_PIN_1;  
17
  GPIOPinConfigure(GPIO_PE0_PWM4);
18
  GPIOPinConfigure(GPIO_PE1_PWM5);
19
  GPIOPinTypePWM(GPIO_PORTE_BASE, (GPIO_PIN_0 + GPIO_PIN_1));
20
  GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, (GPIO_PIN_0 + GPIO_PIN_1));
21
  
22
  GPIO_PORTD_AFSEL_R |= GPIO_PIN_2 + GPIO_PIN_3;
23
  GPIOPinConfigure(GPIO_PD2_PWM2);
24
  GPIOPinConfigure(GPIO_PD3_PWM3);
25
  GPIOPinTypePWM(GPIO_PORTD_BASE, GPIO_PIN_2 + GPIO_PIN_3);
26
  GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, (GPIO_PIN_2 + GPIO_PIN_3));

Allerdings ist Vorsicht geboten: Damit habe ich das Board lahm gelegt. 
Nimmt jetzt 200 bis 300 mA auf statt der üblichen 60 mA, die Spannung 
ist von rund 3,3 V auf 2,1 V gefallen. Die Spannung ist damit außerhalb 
des nötigen Bereiches um programmiert zu werden :-/

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.