Hallo,
ich versuch 2 Brushless Motoren mit STM32F1 zu steuern. Ich weiss nicht
wie man 3, 120° Phasen versetzte PWMs mittels Timer1 erzeugt.
Hat jemand einen Beispiel Code für mich? Ich habe viel danach im
Internet gesucht, bin am verzweifeln.
Danke!
offene Fragen:
1. Wofür sind die NVIC_Configuration und SysTick_Configuration im
Beispiel?
2. Ein Pin wird als floating Eingang definiert. Was wird hier gemessen?
Braucht man das überhaupt für die Steuerung der BLDCs?
3. ist Channel1N negierte Channel1 oder hat damit nix zu tun?
4. Wie gebe ich die PWM vor?
5. Wie ändere ich die Drehrichtung?
Danke ;)
Kristoffer Ullsten schrieb:> 1. Wofür sind die NVIC_Configuration und SysTick_Configuration im> Beispiel?
Steht im Quelltext. Der Systick erzeugt ein COM Event, um den Motor
weiterzuschalten. Ohne die Konfiguration des NVIC wird kein Interrupt
ausgelöst.
> 3. ist Channel1N negierte Channel1 oder hat damit nix zu tun?
Das ist der zu Channel 1 komplementäre Ausgang - lies im Reference
Manual die Konfiguration der Advanced Timer und der CC Register.
> 4. Wie gebe ich die PWM vor?
Durch Schreiben der 3 CC Register. Wird im Beispiel nur in der Init
benutzt, kann man aber mit im COM Interrupt erledigen.
> 5. Wie ändere ich die Drehrichtung?
Indem du in der COM ISR eine zweite Schiene einbaust, die die Steps
enthält, aber bei der zwei Phasen vertauscht sind.
> 2. Ein Pin wird als floating Eingang definiert. Was wird hier gemessen?
Gemessen wird gar nichts. Ich denke, STM will den Eingang als Stop
Eingang benutzen. Scheint aber noch nicht geschehen zu sein.
Alles in allem ist die Software nur ein Behelf. Die COM ISR würde
sinnvoller mit einer kleinen Tabelle laufen, dann wäre auch die
Drehrichtung vil leichter umkehrbar. Die zwanghafte Benutzung der Std.
Peri. Lib ist hier nicht besonders hilfreich.
Matthias S. schrieb:> Kristoffer Ullsten schrieb:>> 1. Wofür sind die NVIC_Configuration und SysTick_Configuration im>> Beispiel?> Steht im Quelltext. Der Systick erzeugt ein COM Event, um den Motor> weiterzuschalten. Ohne die Konfiguration des NVIC wird kein Interrupt> ausgelöst.
Vielen Dank! ich verstehe langsam einiges. Das heißt ohne COM Event oder
Info über Motor Drehlage ist es unmöglich, den Motor weiterzudrehen bzw.
wieder ab Step1 zu betreiben?
>> 4. Wie gebe ich die PWM vor?> Durch Schreiben der 3 CC Register. Wird im Beispiel nur in der Init> benutzt, kann man aber mit im COM Interrupt erledigen.
Das heißt, müssen die 3 CC Register den gleichen Wert bzw. Pulsweite
haben? Warum sind die CCR Werte verschieden im Beispiel.
1
uint16_tCCR1_Val=32767;
2
uint16_tCCR2_Val=24575;
3
uint16_tCCR3_Val=16383;
4
uint16_tCCR4_Val=8191;
Meine BLDC Motoren haben eingebaute 3 Hallsensoren und Shunts für
Strommessung.
Ich habe überhaupt keine Erfahrung mit BLDC Motoren, daher muss ich
folgende Noob Fragen stellen.
Was ist ein Com Event?
Welche Methoden gibts für die Steuerung von BLDC Motoren in Konbination
mit Encoder.
Viele Dank.
Kristoffer Ullsten schrieb:> Welche Methoden gibts für die Steuerung von BLDC Motoren in Konbination> mit Encoder.
Wenn du Hallsensoren hast, wird die Sache viel einfacher als mit dem
zwangsgeführten Motor aus dem Beispiel. Du konfigurierst 3 Pins als
Interrupt Quelle und liest den Sektor bei Pegelwechsel aus dem Zustand
der Sensoren. Damit schaltest du die Sektoren (Step1 - Step6 im
Beispiel).
Wenn du die Sektornummer als Zeiger in eine Tabelle benutzt, ist die
Kommutierung in nullkommanichts erledigt. Das kann z.B. so aussehen -
von meinem alten Projekt für den VL Discovery
1
// from PMSMTables.h
2
// PHASES to position in TIM1_CCER register
3
4
#define UH 0x0004
5
#define UL 0x0001
6
7
#define VH 0x0040
8
#define VL 0x0010
9
10
#define WH 0x0400
11
#define WL 0x0100
12
13
#define LOSIDEMASK (UL | VL | WL)
14
#define HISIDEMASK (UH | VH | WH)
15
#define PHASEMASK (LOSIDEMASK | HISIDEMASK)
16
// tables organized for enabling bits in TIMx_CCER
17
constuint16_tblockCommutationTableForward[8]=
18
{
19
0,// illegal value
20
WH|UL,// UL, WH
21
UH|VL,// VL, UH
22
WH|VL,// VL, WH
23
VH|WL,// WL, VH
24
VH|UL,// UL, VH
25
UH|WL,// WL, UH
26
0// illegal value
27
};
28
constuint16_tblockCommutationTableReverse[8]=
29
{
30
0,
31
UH|VL,
32
VH|WL,
33
UH|WL,
34
WH|UL,
35
WH|VL,
36
VH|UL,
37
0
38
};
39
40
// from main.c
41
// set power to all of the CC Registers for block commutation
42
voidBlockCommutationSetDuty(constuint16_tduty)
43
{
44
// Set all compare registers to new duty cycle value.
45
TIM_SetCompare1(TIM1,duty);
46
TIM_SetCompare2(TIM1,duty);
47
TIM_SetCompare3(TIM1,duty);
48
}
49
/* Block Commutate does the activation of OC outputs according to the
Du arbeitest mit blockkommutierung...da werden die phasen nacheinander!
angesteuert. Lies dir mal hier den Artikel zu BLDC Steuerungen durch!
Für hohe drehzahlen geht das problemlos...erst wenn der motor langsam
drehen soll brauchst du eine feldorientierte Regelung..hierfür kannst du
das Beispiel aber vergessen...das wird wesentlich komplexer
Kristoffer Ullsten schrieb:> ich habe die PWMs mit komplementären generiert, die PWMs schauen nicht> phasenverschoben aus.>> Wie verschiebe ich die denn um 120 grad. Danke!
Dafür sind doch die 6 Sektoren da. 360/6 = 60° und für jeweils 2
Sektoren ist doch jede Wickung bestromt. Deswegen habe ich doch mal
meinen Code für einfache Blockkommutierung gepostet. Der ist nicht
vollständig, zeigt aber das Prinzip der Bestromung in Abhängigkeit von
den Hallsensoren.
Kristoffer Ullsten schrieb:> ist der Anfangszustand von 6 Steps unabhängig von Motordrehlage?
Nein. Der Sektor, in dem der Motor steht, wird ja durch deine
Hallsensoren an den Controller gemeldet. Es ist also einer von 6
möglichen Zuständen. Die Wicklungen werden dann so bestromt, das der
Motor in den nächsten Sektor (vorwärts) oder in den vorigen Sektor
(rückwärts) 'gezogen' wird.
Beim zwangsgeführten Beispiel von STM wird einfach mit einem Sektor
angefangen, da eine Rückmeldung hier nicht erfolgt. Die Chancen sind
also 1:5, das zufällig der Motor ohne Ruckeln anläuft.
Das PDF zur Atmel Application Note AVR447 erklärt dazu recht viel, unter
anderem auch, wie aus einfacher Blockkommutierung dann Sinusmodulation
wird, die den Motor laufruhiger macht und auch sehr gleichmässige
Bewegung bei langsamen Drehzahlen ermöglicht:
http://www.atmel.com/images/doc8010.pdf
Ich lasse so mit u.a. dem VLDiscovery STM32F100RB sehr laufruhig und
langsam einen Pioneer Direct Drive Plattenspieler Motor laufen - eine
meiner Versuchsanordnungen für BLDC Antrieb.
Danke,
ich versuche grad folgende Zeile zu verstehen
1
TIM1->CCER=blockCommutationTableReverse[hall]
.
Wie wird der Wert hall aus den Encoder Werten abgebildet. Mich würde
interessieren, welchen Wert der hall bekommt, wenn Encoder Zustand 101
ist, oder 100, 001.
Danke!
Kristoffer Ullsten schrieb:> Mich würde> interessieren, welchen Wert der hall bekommt, wenn Encoder Zustand 101> ist, oder 100, 001.
Das ist genau die binäre Abbildung. Also '101' ist hall = 5, 001
entspricht hall = 1 und 100 wäre hall = 4.
Ich habe die Hallsensor Eingänge auf PA0 bis PA2 gelegt und triggere
beim Wechsel auf einem dieser Pins einen EXTI:
* values of 0 or 7 mean an error and should set the ERR_HALLSENSOR bit in 'error'
4
* this happens if more than 3 hallsensor errors have occured
5
*/
6
uint16_tGetHall(void){
7
volatileuint8_tn=0;
8
volatileuint16_thall;
9
hall=HALL_GPIO_PORT->IDR&HALLMASK;
10
while(n<6){
11
if(hall==(HALL_GPIO_PORT->IDR&HALLMASK)){
12
n++;
13
}
14
else{
15
n=0;
16
hall=(HALL_GPIO_PORT->IDR&HALLMASK);
17
}
18
}
19
if((hall<1)|(hall>6))hallerrcount++;
20
if(hallerrcount>3)error|=ERR_HALLSENSORS;
21
returnhall;
22
}
23
24
voidHallIRQ(void){
25
EXTI_ClearFlag(EXTI_Line0|EXTI_Line1|EXTI_Line2);
26
volatileuint16_thall=GetHall();
27
// spurious trap - this routine should only be fired if we have a
28
// valid sensor change
29
if(lastHall!=hall){
30
LED_GPIO_PORT->BSRR=BLUE_LED_PIN;
31
// rpms = TCD0.CNT; // read measure
32
// TCD0.CNT = 0 ; // reset measure
33
BlockCommutate(hall);
34
}
35
}
36
/*
37
* Hall Sensor 1 IRQ
38
*/
39
voidEXTI0_IRQHandler(void)
40
{
41
if(EXTI_GetITStatus(HALL1_EXTI_LINE)!=RESET)
42
{
43
/* Clear the EXTI line pending bit */
44
EXTI_ClearITPendingBit(HALL1_EXTI_LINE);
45
HallIRQ();
46
}
47
}
48
/*
49
* Hall Sensor 2 IRQ
50
*/
51
voidEXTI1_IRQHandler(void)
52
{
53
if(EXTI_GetITStatus(HALL2_EXTI_LINE)!=RESET)
54
{
55
/* Clear the EXTI line pending bit */
56
EXTI_ClearITPendingBit(HALL2_EXTI_LINE);
57
HallIRQ();
58
}
59
}
60
/*
61
* Hall Sensor 3 IRQ
62
*/
63
voidEXTI2_IRQHandler(void)
64
{
65
if(EXTI_GetITStatus(HALL3_EXTI_LINE)!=RESET)
66
{
67
/* Clear the EXTI line pending bit */
68
EXTI_ClearITPendingBit(HALL3_EXTI_LINE);
69
HallIRQ();
70
}
71
}
das ist alles abstrahiert, da ich die eigentliche Port Deklaration wie
GPIOA usw. z.B. HALL_GPIO_PORT nenne, um schneller auf andere Ports
umzutippen, falls das mal nötig sein sollte. Ich habe auch eine Menge
hier weggelassen, wie z.B. lastHall und so, damit es nicht zu verwirrend
wird. Ausserdem sind da ein paar Plausibilitätschecks drin, weil es
hier um etwas kritische Anwendungen geht.
Vielen Dank. Ich habe den Code etwas geändert.
Hall Inputs bei mir PC10 bis PC12:
1
uint16_tHALLMASK=7<<9;// PC10 PC11 PC12
später nach Rechts um 9 Bits verschoben.
Beim Kompilieren gibts keine Fehlermeldung, nur der Motor dreht nicht.
Können Sie bitte den kompletten Code kurz schauen, ob es in Ordnung
ausschaut.
Danke!
Matthias S. schrieb:> Hier ist doppelt PinSource10 konfiguriert:
Danke,
> Ich würde mal eine serielle Ausgabe einbauen und mir Werte ausschreiben,> wie z.B. hall oder das CCER Register.
Danke!! Ich mach das gleich.. Der Encoder funktioniert jetzt ordentlich.
:)
ich bekomme über GetHall() folgende Werte
Rechts: 264513264513264513264513264513264513264513264513264513
Links: 231546231546231546231546231546231546231546231546231546
Es funktioniert immer nicht :(
Kristoffer Ullsten schrieb:> 264513
Das sieht doch gut aus. Wo ist denn jetzt das Problem?
Die Spulenbestromungsreihenfolge (hehehe) ist von Motor zu Motor
unterschiedlich, wenn du jetzt also die Tabellen auf deine Maschine
anpasst, klappt das.
Dazu bestromst du den Motor ganz wenig und prüfst ob der Motor immer in
den nächsten Sektor ziehen will. Fehler in der Tabelle kriegst du über
die Hallnummer ja sofort raus.
Matthias S. schrieb:> azu bestromst du den Motor ganz wenig und prüfst ob der Motor immer in> den näcMatthias S. schrieb:> Kristoffer Ullsten schrieb:>> 264513>> Das sieht doch gut aus. Wo ist denn jetzt das Problem?>> Die Spulenbestromungsreihenfolge (hehehe) ist von Motor zu Motor> unterschiedlich, wenn du jetzt also die Tabellen auf deine Maschine> anpasst, klappt das.> Dazu bestromst du den Motor ganz wenig und prüfst ob der Motor immer in> den nächsten Sektor ziehen will. Fehler in der Tabelle kriegst du über> die Hallnummer ja sofort raus.
wie denn?
na sag schon ;)
Kristoffer Ullsten schrieb:> wie denn?> na sag schon ;)
Du bist wohl ein Witzbold. Ich habe keine Ahnung von deinem Aufbau und
von der derzeitigen Software. Hast du z.B. die Ports und die PWM
initialisiert und eine Regelung der PWM Power eingebaut?
Ich kann dir nicht meinen kompletten Sourcecode posten - erstens ist der
schweinelang und zweitens kommen dann noch mehr Fragen, weil dir
anscheinend ein paar Grundlagen fehlen. Also lies in Ruhe mal AVR447 und
evtl. auch AVR444. Auch Freescale hat interessante Artikel...
bin beinah am verzweifeln. Es funktioniert immer nicht. Jedesmal beim
Einschalten bricht die Quellspannung von 30V auf 18V zusammen und zieht
dabei 2A. Ich weiss nicht wo der Fehler liegt.
Kristoffer Ullsten schrieb:> Jedesmal beim> Einschalten bricht die Quellspannung von 30V auf 18V zusammen
Wie, du testest mit angeschlossenen Endstufen? Das solltest du vorerst
lassen, sondern stattdessen erstmal nur die Hallsensoren anschliessen
und schauen, was an den PWM Ausgängen passiert, wenn du den Motor
langsam händisch drehst.
Ausserdem ist es sinnvoll, sich ein paar Debug Pins als Ausgang zu
konfigurieren, um den Programmablauf zu untersuchen.
In der commutate() Routine hast du den Weg über switch case gewählt,
statt über eine Tabelle, das macht das Konfigurieren unnötig
unübersichtlich und langsam, aber gut, gehen sollte es auch.
Bei meinen ersten Versuchen (mit dem guten alten Mega) hatte ich mir auf
ein Blatt Papier die Sensoren und die Spulen aufgemalt und dann
untersucht, wie der Motor bestromt werden muss, damit er bei Zustand 1
der Sensoren in den nächsten Sektor zieht, und das gleiche für alle 6
Sektoren wiederholt. Als ich das so dann in die Tabelle eintrug, lief
der kleine Kerl sofort wie gewünscht. Das gleiche habe ich dann für den
Rückwärtslauf auch gemacht.
Gib dir über UART zu den Hallsensoren auch mal den Zustand des CCER
Registers von Timer 1 aus (TIM1->CCER), dann siehst du, ob das
Ansteuermuster auch funktioniert.
Hier ein paar ganz primitive Routinen zur Ausgabe von Bytes, Words und
Longs auf UART:
Matthias S. schrieb:
Danke für die Antwort. Ich hab den Motor zum Drehen gebracht einfach
ohne PWM. Die untere 3 Eingänge PB13, PB14, PB15 vom Gate-Treiber sind
invertiert worden.
1
voidcommutate(uint16_tstep){
2
3
switch(step){
4
case5:
5
// 1
6
GPIO_SetBits(GPIOA,GPIO_Pin_8);
7
GPIO_SetBits(GPIOB,GPIO_Pin_13);
8
9
GPIO_ResetBits(GPIOA,GPIO_Pin_9);
10
GPIO_ResetBits(GPIOB,GPIO_Pin_14);
11
12
GPIO_ResetBits(GPIOA,GPIO_Pin_10);
13
GPIO_SetBits(GPIOB,GPIO_Pin_15);
14
break;
15
case4:
16
// 2
17
GPIO_ResetBits(GPIOA,GPIO_Pin_8);
18
GPIO_SetBits(GPIOB,GPIO_Pin_13);
19
20
GPIO_ResetBits(GPIOA,GPIO_Pin_9);
21
GPIO_ResetBits(GPIOB,GPIO_Pin_14);
22
23
GPIO_SetBits(GPIOA,GPIO_Pin_10);
24
GPIO_SetBits(GPIOB,GPIO_Pin_15);
25
break;
26
case6:
27
// 3
28
GPIO_ResetBits(GPIOA,GPIO_Pin_8);
29
GPIO_ResetBits(GPIOB,GPIO_Pin_13);
30
31
GPIO_ResetBits(GPIOA,GPIO_Pin_9);
32
GPIO_SetBits(GPIOB,GPIO_Pin_14);
33
34
GPIO_SetBits(GPIOA,GPIO_Pin_10);
35
GPIO_SetBits(GPIOB,GPIO_Pin_15);
36
break;
37
case2:
38
// 4
39
GPIO_ResetBits(GPIOA,GPIO_Pin_8);
40
GPIO_ResetBits(GPIOB,GPIO_Pin_13);
41
42
GPIO_SetBits(GPIOA,GPIO_Pin_9);
43
GPIO_SetBits(GPIOB,GPIO_Pin_14);
44
45
GPIO_ResetBits(GPIOA,GPIO_Pin_10);
46
GPIO_SetBits(GPIOB,GPIO_Pin_15);
47
break;
48
case3:
49
// 5
50
GPIO_ResetBits(GPIOA,GPIO_Pin_8);
51
GPIO_SetBits(GPIOB,GPIO_Pin_13);
52
53
GPIO_SetBits(GPIOA,GPIO_Pin_9);
54
GPIO_SetBits(GPIOB,GPIO_Pin_14);
55
56
GPIO_ResetBits(GPIOA,GPIO_Pin_10);
57
GPIO_ResetBits(GPIOB,GPIO_Pin_15);
58
break;
59
case1:
60
// 6
61
GPIO_SetBits(GPIOA,GPIO_Pin_8);
62
GPIO_SetBits(GPIOB,GPIO_Pin_13);
63
64
GPIO_ResetBits(GPIOA,GPIO_Pin_9);
65
GPIO_SetBits(GPIOB,GPIO_Pin_14);
66
67
GPIO_ResetBits(GPIOA,GPIO_Pin_10);
68
GPIO_ResetBits(GPIOB,GPIO_Pin_15);
69
break;
70
default:
71
break;
72
}
73
}
ich frag mich wie ich das jetzt mit PWM mache.
1
/* Channel 1, 2 and 3 Configuration in PWM mode */
Kristoffer Ullsten schrieb:> ich frag mich wie ich das jetzt mit PWM mache.> /* Channel 1, 2 and 3 Configuration in PWM mode */> TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;> TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;> TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;> TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;> TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;> TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;> TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;
Sieht doch gar nicht falsch aus. Allerdings musst du die Struktur nun
auch benutzen:
1
TIM_OC1Init(TIM1,&TIM_OCInitStructure);
2
TIM_OC2Init(TIM1,&TIM_OCInitStructure);
3
TIM_OC3Init(TIM1,&TIM_OCInitStructure);
Und nicht vergessen, die CC Register dann auch mit PWM Werten zu
beschreiben. Timer 1 muss natürlich initialisiert sein, und die Pins auf
AF konfiguriert werden. Siehe z.B. die Beispiele im STM32 VLDicovery
Package.
Matthias S. schrieb:> TIM_OutputNStateMatthias S. schrieb:> Kristoffer Ullsten schrieb:>> ich frag mich wie ich das jetzt mit PWM mache.>> /* Channel 1, 2 and 3 Configuration in PWM mode */>> TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;>> TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;>> TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;>> TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;>> TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;>> TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;>> TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;>> Sieht doch gar nicht falsch aus. Allerdings musst du die Struktur nun> auch benutzen:TIM_OC1Init(TIM1, &TIM_OCInitStructure);> TIM_OC2Init(TIM1, &TIM_OCInitStructure);> TIM_OC3Init(TIM1, &TIM_OCInitStructure);> Und nicht vergessen, die CC Register dann auch mit PWM Werten zu> beschreiben. Timer 1 muss natürlich initialisiert sein, und die Pins auf> AF konfiguriert werden. Siehe z.B. die Beispiele im STM32 VLDicovery> Package.
Wie macht man dass die OCN Ausgänge nicht invertiert sind
ich habe den Motor mit PWM 15% Tastverhältnis zum Drehen gebracht. Und
zwar vibriert er zu heftig und macht laute Geräusche. Ich denke, dass
ich immer noch die Kommutierungsschritte nicht richtig hingekriegt habe.
PWM Frequenz liegt auf 20kHz.
Ohne PWM direkt beispielsweise mit
1
voidcommutate(uint16_tstep){
2
switch(step){
3
case5:
4
GPIO_SetBits(GPIOA,GPIO_Pin_8);
5
GPIO_SetBits(GPIOB,GPIO_Pin_13);
6
7
GPIO_ResetBits(GPIOA,GPIO_Pin_9);
8
GPIO_ResetBits(GPIOB,GPIO_Pin_14);
9
10
GPIO_ResetBits(GPIOA,GPIO_Pin_10);
11
GPIO_SetBits(GPIOB,GPIO_Pin_15);
12
break;
hat der Motor schön sauber gedreht. Ich weiss nicht wo der Fehler genau
liegt.
Ich werde jetzt nicht die völlig bekloppte Methode mit deinen
TIMCCxCMD() switch-case durchklappern. Da wirst du dich irgendwo
vertippt haben.
Ich habe dir vor ein paar -zig Beiträgen die Sache mit den Tabellen
vorgeschlagen, die recht idiotensicher und schnell an andere Motoren
anpassbar ist.
Matthias S. schrieb:> Ich werde jetzt nicht die völlig bekloppte Methode mit deinen> TIMCCxCMD() switch-case durchklappern. Da wirst du dich irgendwo> vertippt haben.>> Ich habe dir vor ein paar -zig Beiträgen die Sache mit den Tabellen> vorgeschlagen, die recht idiotensicher und schnell an andere Motoren> anpassbar ist.
Die Tabelle würde ich gern später verwenden. Mein Problem ist , wie
setze ich einen bestimmten PWM Pin Pegel auf High ohne
TIM_ForcedAction_Active zu benutzen.
Zwischen TIM1->CCER = 0x0002 und 0x0000 sehe ich keinen Unterschied am
Oszi. Der Pin Level liegt immer auf Low.