Forum: Mikrocontroller und Digitale Elektronik Denkfehler BLDC Motor Steuerung o_o


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Peter H. (borntopizza)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi zusammen,

ich bin seit längerem dabei eine BLDC Motor Steuerung zu bauen. Jetzt 
wollte ich den ganzen Spaß mal Probeweise mit einem "kleinen" 500 W BLDC 
Motor testen. Nur leider springt die Strombegrenzung meiner Netzteile 
immer ein (sind beide auf 3A hochgedreht).
Jetzt habe ich ein bisschen Angst, nicht dass ich doch einen größeren 
Denkfehler hier drin habe.
Ich habe für jeden FET in den 3 Halbbrücken einen eigenen DC/DC Wandler 
(Ausgang + Eingang von einander Isoliert) macht also insgesamt 6 DC/DC 
Wandler für den "Leistungsteil" und noch einen 5V DC/DC Wandler für den 
Mikrocontroller etc. Die FET Treiber werden über Optokoppler vom 
Mikrocontroller angesteuert.
Fet´s sind: 
https://www.tme.eu/de/details/ixfn360n10t/mosfet-transistormodule/ixys/

Vielleicht könnt Ihr mir sagen ob das theorethisch überhaupt 
funktionieren würde. Ich bin nur kleiner Azubi und habe nicht so das 
riesen Wissen wie vielleicht andere.

Danke und viele Grüße
Peter



Anbei noch mein Code. Ist noch nicht fertig und muss dazu sagen, dass 
ich noch nie das Programmieren so richtig gelernt habe.
int Hall01;    
int Hall02;
int Hall03;
int PWM1 = PB9;
int PWM2 = PB8;
int PWM3 = PB1;
int PWM4 = PB0;
int PWM5 = PB7;
int PWM6 = PB6;
int ledPin =  PC13;

void setup()
 {pinMode(ledPin, OUTPUT);}

void loop() {
  Hall01 = digitalRead(PA4);
  Hall02 = digitalRead(PA3);
  Hall03 = digitalRead(PA2);
  if (Hall01 == 0 && Hall02 == 1 && Hall03 == 1)
  {analogWrite(PWM3, 5000);
   analogWrite(PWM6, 5000);
   Hall01 = digitalRead(PA4);
   Hall02 = digitalRead(PA3);
   Hall03 = digitalRead(PA2);}
  if (Hall01 == 0 && Hall02 == 1 && Hall03 == 1)
  {analogWrite(PWM3, 5000);
   analogWrite(PWM2, 5000);
   Hall01 = digitalRead(PA4);
   Hall02 = digitalRead(PA3);
   Hall03 = digitalRead(PA2);}
  if (Hall01 == 1 && Hall02 == 0 && Hall03 == 1)
  {analogWrite(PWM2, 5000);
   analogWrite(PWM5, 5000);
   Hall01=digitalRead(PA4);
   Hall02=digitalRead(PA3);
   Hall03=digitalRead(PA2);}
  if (Hall01 == 1 && Hall02 == 0 && Hall03 == 0)
  {analogWrite(PWM4, 5000);
   analogWrite(PWM5, 5000);
   Hall01=digitalRead(PA4);
   Hall02=digitalRead(PA3);
   Hall03=digitalRead(PA2);}
  if (Hall01 == 1 && Hall02 == 1 && Hall03 == 0)
  {analogWrite(PWM1, 5000);
   analogWrite(PWM4, 5000);
   Hall01=digitalRead(PA4);
   Hall02=digitalRead(PA3);
   Hall03=digitalRead(PA2);}
  if (Hall01 == 0 && Hall02 == 1 && Hall03 == 0)
  {analogWrite(PWM1, 5000);
   analogWrite(PWM6, 5000);
   Hall01=digitalRead(PA4);
   Hall02=digitalRead(PA3);
   Hall03=digitalRead(PA2);}
  else
  {digitalWrite(ledPin, HIGH);
   Hall01=digitalRead(PA4);
   Hall02=digitalRead(PA3);
   Hall03=digitalRead(PA2);}
}

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Bewertung
0 lesenswert
nicht lesenswert
Peter H. schrieb:
> Hall01 = digitalRead(PA4);
>   Hall02 = digitalRead(PA3);
>   Hall03 = digitalRead(PA2);
>   if (Hall01 == 0 && Hall02 == 1 && Hall03 == 1)
>   {analogWrite(PWM3, 5000);
>    analogWrite(PWM6, 5000);
>    Hall01 = digitalRead(PA4);
>    Hall02 = digitalRead(PA3);
>    Hall03 = digitalRead(PA2);}

* Du musst nur einmal pro Durchlauf die Sensoren lesen und danach die 
Endstufen setzen. Es hat keinen Sinn, das bei jedem Schritt wieder zu 
tun.
Ich würde den Hallsektor vermutlich in eine Zahl verwandeln, und die als 
Zeiger in eine kleine Tabelle tun, in der die Bestromung der Spulen 
festgelegt wird.

* Wo schaltest du denn die PWM für die im Moment nicht bestromten Spulen 
ab? Ich bin nicht so ein Arduinist, aber wenn der MC wirklich 6 PWMs am 
Stück kann, die sich auch nicht überlappen, dann laufen die so lange 
weiter, bis man sie wieder auf 0 setzt.

Ich empfehle dir, mal die Application Note AVR447 (heute Microchip 
AN_8010) zu studieren. Da wird beschrieben, wie man mit 3 Timern eines 
Mega168 6 sich nicht überlappende, komplementäre Signale für 3 Phasen 
(aka Halbbrücken) erzeugt.
https://www.microchip.com/wwwAppNotes/AppNotes.aspx?appnote=en591447

Können deine Optokoppler genügend Gatespannung erzeugen? Die dicken 
MOSFet werden sicher mehr als 5V Ugs benötigen, um sauber 
durchzusteuern. Schaltungsauszug kann also nicht schaden, zumal du nicht 
schreibst, wieviel Spannung die 6 DC/DC Wandler nun erzeugen.

von Peter H. (borntopizza)


Bewertung
0 lesenswert
nicht lesenswert
Hmm weiss gerade selber nicht wie man das am besten macht. Ich habe beim 
Programmieren selber nicht so den Durchblick.
Also anscheinend geht das so wie ich das gedacht habe nicht.
Dann muss ich das ganze wohl doch versuchen anders zu lösen. Puh :-/

Den Link von Dir kuck ich mir mal an, Danke!

Die Optokoppler werden am Eingang vom Mikrocontroller angesteuert und 
steuern am Ausgang die Gate Treiber an. Die wiederum schalten die FET´s.
Die 6 DC/DC Wandler liefern 12V und 470 mA.

Würde das Ganze den "Hardware-technisch" überhaupt funktionieren?

Danke und viele Grüße
Peter

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Bewertung
0 lesenswert
nicht lesenswert
Peter H. schrieb:
> Würde das Ganze den "Hardware-technisch" überhaupt funktionieren?

Zeig doch bitte mal den Schaltplan für (mindestens) eine Halbbrücke vom 
MC bis zu den MOSFet.

von BornToPizza (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hi,
ist doch oben als PDF dabei oder ?
Oder kannst Du die nicht öffnen ?
Wenn nicht poste ich nachher das KiCad File

Danke und Viele Grüße
Peter

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Bewertung
0 lesenswert
nicht lesenswert
Oh, sorry, habe ich glatt übersehen :-O
Das sieht alles recht hochohmig um den Optokoppler aus. Was für eine PWM 
Frequenz benutzt der MC? Bei den insgesamt etwa 16k als Arbeitwiderstand 
ist da recht wenig Strom und niedrige Grenzfrequenz zu erwarten - zumal 
der PC817 kein Geschwindigkeitswunder ist.

Wenn du Optokoppler benutzen willst, schau dir mal die Endstufen in 
meinem FU an:
https://www.mikrocontroller.net/articles/3-Phasen_Frequenzumrichter_mit_AVR

Vorsicht - bei deiner Schaltung gibt es keine Verriegelung gegen einen 
'Shoot-Through', also das gleichzeitige Leiten des oberen und des 
unteren MOSFet der Halbbrücke. Dein Programm darf also keinesfalls die 
Halbbrücke beidseitig anschalten, sonst knallts.

: Bearbeitet durch User
von Andre (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Kann mir jemand die Theorie zu den ganzen DC/DC Wandlern erklären? 
Versorgst du eine Motorphase jeweils aus zwei Wandlern? Benötigst du 
keine Stromregelung?
Schau dir mal an wie das in Appnotes gelöst wurde, oder z.B. beim 
Odrive.

von Uwe (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hi,
Waren die Abfragen wirklich so gedacht?
>  if (Hall01 == 0 && Hall02 == 1 && Hall03 == 1)
>  {analogWrite(PWM3, 5000);
>   analogWrite(PWM6, 5000);
>   Hall01 = digitalRead(PA4);
>   Hall02 = digitalRead(PA3);
>   Hall03 = digitalRead(PA2);}
>  if (Hall01 == 0 && Hall02 == 1 && Hall03 == 1)
>  {analogWrite(PWM3, 5000);
>   analogWrite(PWM2, 5000);
bestimmt ein Schreibfehler.
Mit was wolltst du denn die Drehzahl festlegen?
Die PWMs können maximal die Bestromung einer Wicklung festlegen.
Die vorgesehenen OK sind dafür aber komplett ungeeignet weil zu langsam.
470mA für 1 Fet. Naja da sind verschiedene Typen unterwegs.
Für einen fetten ist es sehr knapp. Für die 3 Treiber auf der GND-Seite 
brauchst du keine separate Stromversorgung, die kannste alle auf eine 
hängen.
(Schaden tut es aber auch nicht direkt)
Wie schon von anderen geschrieben, ein gesetzte PWM bleibt gesetzt wenn 
sie nicht abgeschaltet wird.
Ich sehe im Hintergrund ein Oszi, du hast also gute Möglichkeiten das zu 
testen was du erreichen möchtest.
Viel erfolg, Uwe

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Bewertung
0 lesenswert
nicht lesenswert
Andre schrieb:
> Kann mir jemand die Theorie zu den ganzen DC/DC Wandlern erklären?
> Versorgst du eine Motorphase jeweils aus zwei Wandlern?

Wenn man sich auf DC/DC Wandler statt Ladungspumpen festlegt, dann ist 
es schon richtig, das die Highside für jede Halbbrücke einen eigenen 
DC/DC Wandler benötigt. Wie Uwe schon schrieb, kann die Lowside aus 
einem einzigen gespeist werden oder ganz ohne auskommen.
Es ist schon ein wenig schade, das die Platine super aussieht, aber 
vorher kein Rat eingeholt wurde.

von BornToPizza (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Okay danke euch.
Den Code schmeiss ich dann erstmal in den Muell und denk mir was neues 
aus.

Die Spannungsteiler am Ausgang von den OPV's werde ich dann noch etwas 
anpassen.
Reichen die 470mA echt nicht? Ich hab ja noch einen dicken 1000uF Elko 
am Ausgang(sorry ist im Schaltplan falsch beschriftet)


Danke und viele Grüße
Peter

von Guest (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich kenne die Arduino Funktion jetzt nicht genau aber ich bezweifle dass 
die ein komplementäres PWM mit Dead Time erzeugt demnach schließt du 
vermutlich einfach deine Versorgungsleitung kurz.

von Peter H. (borntopizza)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So also Motor dreht sich :-)

Leider noch nicht so richtig.
Beim anlaufen muss man ihm kurz helfen, denke das liegt aber an meinen 
Netzteilen.

Das größte Problem jetzt ist, dass der Motor extrem Langsam läuft.

Ich weiss nicht zu 100% an was das liegt, aber ich vermute, dass die PWM 
Frequenz, die der Mikrocontroller ausgibt mit 500Hz noch deutlich zu 
niedrig ist.
Wenn ich das noch hinbekommen würde, dann wäre das optimal.

Anbei noch mein Code, ich musste in den if-conditions die anderen PWM 
Ausgänge nur wieder auf 0 Schalten, das war denke ich der Fehler.
int Hall01;    
int Hall02;
int Hall03;
int PWM1 = PB9;
int PWM2 = PB8;
int PWM3 = PB1;
int PWM4 = PB0;
int PWM5 = PB7;
int PWM6 = PB6;
int ledPin =  PC13;

int drehzahl = 40;

void setup() 
 {pinMode(ledPin, OUTPUT);
 Serial.begin(115200);}

void loop() {
  Hall01 = digitalRead(PA4);
  Hall02 = digitalRead(PA3);
  Hall03 = digitalRead(PA2);
  Serial.println(Hall01);
  Serial.println(Hall02);
  Serial.println(Hall03);
  Serial.println();
  if (Hall01 == 0 && Hall02 == 1 && Hall03 == 1)
  {analogWrite(PWM1, 0);
   analogWrite(PWM2, 0);
   analogWrite(PWM4, 0);
   analogWrite(PWM5, 0);
   analogWrite(PWM3, drehzahl);
   analogWrite(PWM6, drehzahl);}
  else if (Hall01 == 0 && Hall02 == 0 && Hall03 == 1)
  {analogWrite(PWM1, 0);
   analogWrite(PWM4, 0);
   analogWrite(PWM5, 0);
   analogWrite(PWM6, 0);
   analogWrite(PWM3, drehzahl);
   analogWrite(PWM2, drehzahl);}
  else if (Hall01 == 1 && Hall02 == 0 && Hall03 == 1)
  {analogWrite(PWM1, 0);
   analogWrite(PWM3, 0);
   analogWrite(PWM4, 0);
   analogWrite(PWM6, 0);
   analogWrite(PWM2, drehzahl);
   analogWrite(PWM5, drehzahl);}
  else if (Hall01 == 1 && Hall02 == 0 && Hall03 == 0)
  {analogWrite(PWM1, 0);
   analogWrite(PWM2, 0);
   analogWrite(PWM3, 0);
   analogWrite(PWM6, 0);
   analogWrite(PWM4, drehzahl);
   analogWrite(PWM5, drehzahl);}
  else if (Hall01 == 1 && Hall02 == 1 && Hall03 == 0)
  {analogWrite(PWM2, 0);
   analogWrite(PWM3, 0);
   analogWrite(PWM5, 0);
   analogWrite(PWM6, 0);
   analogWrite(PWM1, drehzahl);
   analogWrite(PWM4, drehzahl);}
  else if (Hall01 == 0 && Hall02 == 1 && Hall03 == 0)
  {analogWrite(PWM2, 0);
   analogWrite(PWM3, 0);
   analogWrite(PWM4, 0);
   analogWrite(PWM5, 0);
   analogWrite(PWM1, drehzahl);
   analogWrite(PWM6, drehzahl);}
  else
  {digitalWrite(ledPin, HIGH);}
}

Und hier noch ein Beweisvideo :D

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Bewertung
0 lesenswert
nicht lesenswert
Peter H. schrieb:
> Serial.println(Hall01);
>   Serial.println(Hall02);
>   Serial.println(Hall03);
>   Serial.println();

Das schluckt den Löwenanteil deiner Schleifenzeit und deshalb dreht der 
Motor auch so langsam. Die serielle Ausgabe ist hier fehlplaziert, denn 
es handelt sich um eine blockierende Routine, die so lange wartet, bis 
auch das letzte Zeichen auf dem Weg ist.
Mit der PWM Frequenz hat das nur ganz am Rande zu tun, z.B., wenn die 
Periode der PWM länger ist als das Durchlaufen eines Sektors.
Sinnvoll wäre es, die Hallsensoren einen Interrupt auslösen zulassen, 
der die Bestromung der Endstufen einstellt.

: Bearbeitet durch User
von Peter H. (borntopizza)


Bewertung
-1 lesenswert
nicht lesenswert
Super, Danke hat schonmal was gebracht :-) !

Meinst du external interrupts ?

Danke und viele Grüsse
Peter

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Bewertung
0 lesenswert
nicht lesenswert
Peter H. schrieb:
> Meinst du external interrupts ?

Ja. Du benutzt da STM32, der für sowas prima geeignet ist, wo es aber 
sein kann, das du dich vom Arduino Zeug zumindest teilweise lösen 
solltest.
Mein altes BLDC Projekt mit STM32F100RB (VLDiscovery Board) und SPL 
initialisiert das z.B. folgendermassen:
/* Setup Hall inputs */
RCC_APB2PeriphClockCmd(HALL_GPIO_CLK | RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitStructure.GPIO_Pin = H1_GPIO_PIN | H2_GPIO_PIN | H3_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(HALL_GPIO_PORT, &GPIO_InitStructure);
/* Setup Hall Interrupt */
/* Connect EXTI0 Line to Hall1 GPIO Pin */

GPIO_EXTILineConfig(HALL_EXTI_PORT_SOURCE, HALL1_EXTI_PIN_SOURCE);
GPIO_EXTILineConfig(HALL_EXTI_PORT_SOURCE, HALL2_EXTI_PIN_SOURCE);
GPIO_EXTILineConfig(HALL_EXTI_PORT_SOURCE, HALL3_EXTI_PIN_SOURCE);

/* Configure Hall EXTI line */

EXTI_InitStructure.EXTI_Line = (HALL1_EXTI_LINE | HALL2_EXTI_LINE | HALL3_EXTI_LINE);
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
EXTI_ClearITPendingBit(HALL1_EXTI_LINE | HALL2_EXTI_LINE | HALL3_EXTI_LINE);
/* Enable and set EXTI0 Interrupt to the lowest priority */
NVIC_InitStructure.NVIC_IRQChannel = HALL1_EXTI_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = HALL2_EXTI_IRQn;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = HALL3_EXTI_IRQn;
NVIC_Init(&NVIC_InitStructure);
Damit ist der EXTI Interrupt so konfiguriert, das jeder Flankenwechsel 
an einem der Hallsensoren die ISR auslöst.
In dieser wird der Sektor gelesen und dann die neue Bestromung 
festgelegt. Die Sache ist etwas komplizierter, weil ich Sinusmodulation 
benutze, aber das Prinzip bleibt das gleiche.

: Bearbeitet durch User
von Peter H. (borntopizza)


Angehängte Dateien:

Bewertung
-1 lesenswert
nicht lesenswert
Hi, ich habs jetzt einigermaßen, dass der µ-Controller höhere Frequenzen 
ausspuckt, jetzt aber das Problem wie das schon erwartet wurde, dass die 
Signale ziemlich stark verzerrt sind.

Bild 1 ist direkt am Mikrocontroller, Bild 2 am Ausgang des Optokopplers 
und Bild 3 am Gate des Fets.

Reicht es einfach den Spannungsteiler auszutauschen oder brauche ich 
auch einen anderen Optokoppler?

Auf welche Werte soll ich den Spannungsteiler anpassen, momentan sind es 
ja noch 16.8k?

Danke und viele Grüße
Peter

von Peter H. (borntopizza)


Bewertung
0 lesenswert
nicht lesenswert
Habe jetzt mal bisschen die Widerstände ausgetauscht.

Am Eingang 220 Ohm + IR-Diode vom Optokoppler.
Auf der anderen Seite den Kollektor des Optokopplers an 12V und am 
Emitter 1k und 2k in Reihe.
Das Signal bleibt aber immer noch ziemlich stark verzerrt.
Das Ganze geht nur bis 3-4 kHz gut, danach ist so ziemlich Schluss.

Kennt jemand evlt. einen "schnelleren" Optokoppler, am besten auch 
DIP-4, wenn es sowas überhaupt gibt.

Viele Grüße
Peter

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Bewertung
0 lesenswert
nicht lesenswert
Peter H. schrieb:
> Kennt jemand evlt. einen "schnelleren" Optokoppler, am besten auch
> DIP-4, wenn es sowas überhaupt gibt.

6N137 (DIP8) ist schon nicht schlecht, auch HCPL2630, der hat 2 OK in 
einem DIP-8 Gehäuse.

von Paul S. (paul360)


Bewertung
0 lesenswert
nicht lesenswert
ich hatte mich auch zuerst mit den Hall Sensoren bei "meinem" Motor 
rumgequaelt, und dann einfach mal die Zero Crossing Back EMF Schaltung 
aus
https://simple-circuit.com/arduino-sensorless-bldc-motor-controller-esc/
nachgebaut.
Ich kann zumindest sagen, dass sowohl Software als auch Schaltung besser 
laufen als der Kram, den ich vorher ausprobiert hatte :)
Vielleicht hilft es dir ja auch...

von Peter H. (borntopizza)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich habe mir jetzt mal Optokoppler mit Schmitt Trigger gekauft und 
getestet.

https://www.tme.eu/de/details/tlp2355-e-t/optokoppler-digitalausgang/toshiba/tlp2355-e-t/
Ich glaube soetwas ist auch der HCPL3120 in dem weiter oben verlinkten 
FU.

Ein klein wenig verzerrt ist das PWM Signal am Ausgang leider immer 
noch. Und das schon bei ~16 kHz. Ist aber auch denke ich gut möglich, 
dass das an meinem momentanen Steckbrett - Aufbau liegt. Oder dass mein 
super 12€ Oszi Mist baut.

Beschalten ist der Optokoppler wie im Datenblatt angegeben mit dem 100nF 
Kondensator zwischen VCC und GND und ca. 4 mA If an der Diode.

Oder ist das Signal schon gut genug?

Danke und viele Grüße
Peter

: Bearbeitet durch User
von Eric B. (beric)


Bewertung
2 lesenswert
nicht lesenswert
Peter H. schrieb:
> Anbei noch mein Code, ich musste in den if-conditions die anderen PWM
> Ausgänge nur wieder auf 0 Schalten, das war denke ich der Fehler.

Solche lange if/else-Kaskaden mit sich immer wiederholenden Statements 
schreien förmlich danach optimiert zu werden. z.B. so:
static const uint8 pwm_pins[] = [
  PWM1, PWM2, PWM3, PWM4, PWM5, PWM6 ];
  
static const uint8 values[][] = [
  [ 0, 0, 0, 0, 0, 0 ],
  [ 0, 1, 1, 0, 0, 0 ],
  [ 1, 0, 0, 0, 0, 1 ],
  [ 0, 0, 1, 0, 0, 1 ],
  [ 0, 0, 0, 1, 1, 0 ],
  [ 0, 1, 0, 0, 1, 0 ],
  [ 1, 0, 0, 1, 0, 0 ],
  [ 0, 0, 0, 0, 0, 0 ]];
  
void loop() {
  Hall01 = digitalRead(PA4);
  Hall02 = digitalRead(PA3);
  Hall03 = digitalRead(PA2);
  
  Serial.println(Hall01);
  Serial.println(Hall02);
  Serial.println(Hall03);
  Serial.println();

  // idx ist Zeile-nr in der values[]-Tabelle
  uint8 idx = ((Hall01 << 2) | (Hall02 << 1) | (Hall03 << 0)) & 0x07;
  
  // Generiere Output für jede PWM pin
  for (p = 0; p < 6; p++) {
    analogWrite(pwm_pins[p], (values[idx][p] == 1)? drehzahl: 0);
  }
  
  // idx 0 oder 7 soll nicht sein --> LED an!
  digitalWrite(ledPin, (idx == 0 || idx == 7));
}

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Bewertung
0 lesenswert
nicht lesenswert
Peter H. schrieb:
> Oder ist das Signal schon gut genug?

Dein kleines DSO wird eine niedrige Grenzfrequenz haben, deswegen kann 
man die Steilheit der Flanken nur schlecht beurteilen. Aber gegenüber 
den alten Screenies sieht das schon deutlich besser aus.
Eric zeigt dir auch sehr gut, wie man mit einfachen Tabellenkonstrukten 
und Definitionen die Software deutlich vereinfachen kann. Mach das.
Wobei die SerialPrints hier so nicht funktionieren, da sie die Schleife 
wieder ausbremsen. Besser ist es, die ganze Kommutiererei in Interrupts 
zu verlegen.

: Bearbeitet durch User
von Pat P. (tsag)


Bewertung
0 lesenswert
nicht lesenswert
Ich habe für meinen BLDC/3 Phasen Motor damals diesen Code genutzt und 
er funktionierte sehr gut. Vielleicht kannst Du ja daraus etwas 
gebrauchen:
https://github.com/cmasenas/3-Phase-Sine-Arduino

Habe dafür damals den DRV8313 genutzt.

von Peter H. (borntopizza)


Bewertung
0 lesenswert
nicht lesenswert
Danke Euch schonmal!

Ich werde den Code dann noch mal anpassen, wenn ich neue Platinen da 
habe.

Ich hatte heute schon versucht nach dem Optokoppler mit integriertem 
Schmitt Trigger versucht noch einen Komparator hinten anzuhängen, der 
das Signal noch mehr verzerrt hat. Ich weiss nicht an was das gelegen 
hat, evtl. war hier der OPV den ich verwendet hatte (LM358) auch wieder 
zu langsam.

Ich denke ich bleibe jetzt nur bei den Optokopplern mit Schmitt Trigger, 
16kHz müssten ja eigentlich reichen.

Danke und viele Grüße
Peter

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Bewertung
0 lesenswert
nicht lesenswert
Peter H. schrieb:
> war hier der OPV den ich verwendet hatte (LM358) auch wieder
> zu langsam.

Der LM358 mag ja für einige Leute immer noch das Nonplusultra bei OpAmps 
sein, aber für den Zweck ist er einfach nicht geeignet. Generell hat ein 
OpAmp da hinten nichts zu schaffen.

Peter H. schrieb:
> ich bleibe jetzt nur bei den Optokopplern mit Schmitt Trigger

Jo, besser is' das.

von Peter H. (borntopizza)


Bewertung
0 lesenswert
nicht lesenswert
Hi, also ich habe mal ein wenig versucht den Code anzupassen mit den 
External Interrupts. Ich weiss nicht ob der Code jetzt überhaupt Sinn 
macht oder einen Vorteil bringt. Das von Eric habe ich leider nicht so 
ganz verstanden :-/.

Was mich auch noch ein bisschen wundert ist, dass der 500W China Motor 
noch nicht von alleine anläuft, auch wenn meine Netzteile nur 50V / 3A 
können.  Also die gehen am Anfang nur den Bruchteil von einer Sekunde in 
den Constant Current Modus, dann fließen nur 30 mA, erst wenn ich 
anschubse fängt alles an und der Strom fließt je nach PWM verhältnis. 
Bei einem Verhältnis von 50/50 sind es dann ungefähr 1.5A.

Vielleicht wisst Ihr ja was man noch besser machen kann.

Danke und viele Grüße
Peter
HardwareTimer pwmtimer3(3);
HardwareTimer pwmtimer4(4);
const byte interruptHall01 = PA4;
const byte interruptHall02 = PA3;
const byte interruptHall03 = PA2;
int Hall01;    
int Hall02;
int Hall03;
int PWM1 = PB9;
int PWM2 = PB8;
int PWM3 = PB1;
int PWM4 = PB0;
int PWM5 = PB7;
int PWM6 = PB6;
int drehzahl = 16000;
int stepstate;

void setup() {
pinMode(PWM1, PWM);
pinMode(PWM2, PWM);
pinMode(PWM3, PWM);
pinMode(PWM4, PWM);
pinMode(PWM5, PWM);
pinMode(PWM6, PWM);
pwmtimer3.pause();
pwmtimer3.setPrescaleFactor(1);
pwmtimer3.setOverflow(32000);
pwmtimer3.refresh();
pwmtimer3.resume();
pwmtimer4.pause();
pwmtimer4.setPrescaleFactor(1);
pwmtimer4.setOverflow(32000);
pwmtimer4.refresh();
pwmtimer4.resume();
Hall01 = digitalRead(PA4);
Hall02 = digitalRead(PA3);
Hall03 = digitalRead(PA2);
attachInterrupt(digitalPinToInterrupt(interruptHall01), INTHall01, CHANGE);
attachInterrupt(digitalPinToInterrupt(interruptHall02), INTHall02, CHANGE);
attachInterrupt(digitalPinToInterrupt(interruptHall03), INTHall03, CHANGE);}

void INTHall01() {
  Hall01 = digitalRead(PA4);
  NextStep();}

void INTHall02() {
  Hall02 = digitalRead(PA3);
  NextStep();}

void INTHall03() {
  Hall03 = digitalRead(PA2);
  NextStep();}

void NextStep() {
  if (Hall01 == 0 && Hall02 == 1 && Hall03 == 1)
  {stepstate = 1;}
  else if (Hall01 == 0 && Hall02 == 0 && Hall03 == 1)
  {stepstate = 2;}
  else if (Hall01 == 1 && Hall02 == 0 && Hall03 == 1)
  {stepstate = 3;}
  else if (Hall01 == 1 && Hall02 == 0 && Hall03 == 0)
  {stepstate = 4;}
  if (Hall01 == 1 && Hall02 == 1 && Hall03 == 0)
  {stepstate = 5;}
  else if (Hall01 == 0 && Hall02 == 1 && Hall03 == 0)
  {stepstate = 6;}
  switch (stepstate) {
  case 1:
  pwmWrite(PWM1, 0);
  pwmWrite(PWM2, 0);
  pwmWrite(PWM4, 0);
  pwmWrite(PWM5, 0);
  pwmWrite(PWM3, drehzahl);
  pwmWrite(PWM6, drehzahl);
  break;
  case 2:
  pwmWrite(PWM1, 0);
  pwmWrite(PWM4, 0);
  pwmWrite(PWM5, 0);
  pwmWrite(PWM6, 0);
  pwmWrite(PWM3, drehzahl);
  pwmWrite(PWM2, drehzahl);
  break;
  case 3:
  pwmWrite(PWM1, 0);
  pwmWrite(PWM3, 0);
  pwmWrite(PWM4, 0);
  pwmWrite(PWM6, 0);
  pwmWrite(PWM2, drehzahl);
  pwmWrite(PWM5, drehzahl);
  break;
  case 4:
  pwmWrite(PWM1, 0);
  pwmWrite(PWM2, 0);
  pwmWrite(PWM3, 0);
  pwmWrite(PWM6, 0);
  pwmWrite(PWM4, drehzahl);
  pwmWrite(PWM5, drehzahl);
  break;
  case 5:
  pwmWrite(PWM2, 0);
  pwmWrite(PWM3, 0);
  pwmWrite(PWM5, 0);
  pwmWrite(PWM6, 0);
  pwmWrite(PWM1, drehzahl);
  pwmWrite(PWM4, drehzahl);
  break;
  case 6:
  pwmWrite(PWM2, 0);
  pwmWrite(PWM3, 0);
  pwmWrite(PWM4, 0);
  pwmWrite(PWM5, 0);
  pwmWrite(PWM1, drehzahl);
  pwmWrite(PWM6, drehzahl);
  break;
  }
}

void loop() {}

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Bewertung
0 lesenswert
nicht lesenswert
Peter H. schrieb:
> lso die gehen am Anfang nur den Bruchteil von einer Sekunde in
> den Constant Current Modus, dann fließen nur 30 mA, erst wenn ich
> anschubse fängt alles an und der Strom fließt je nach PWM verhältnis.

Dein Bestromungsschema scheint nicht zu stimmen. Die Sektornummer der 
drei Sensoren muss so ausgewertet werden, das die Spulen den Motor in 
den nächsten Sektor ziehen. Gibst du also nur ganz wenig PWM, solltest 
du beim Drehen merken, wie der Motor immer weiter ziehen will. Gibt es 
da Aussetzer, stimmt das Spulenschema nicht.
Mach es dir einfacher, indem du aus den drei Sensoren direkt eine Zahl 
formst, die als Zeiger in eine Tabelle zeigt. Das spart dir den ganzen 
if-then-switch Kram. In der Tabelle steht das Spulenschema.
Das kann aus 0 und 1 bestehen. Für die PWM multiplizierst du dann diese 
Zahl mit 0 bis 255 und schickst sie aufs Register.

von Peter H. (borntopizza)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Also ich habe jetzt noch andere Bestromungen durchprobiert, leider 
scheinen die auch nicht so ganz zu passen.

Eigentlich sollten doch von der Bestromung her alle BLDC Motoren gleich 
funktionieren oder nicht? Oder unterscheiden die sich in der Anordnung 
der Hall Sensoren etc.?

Anbei noch 2 von den Bestromungstabellen, die ich probiert habe.

Die beiden lassen z.B. den Motor drehen, man kann ihn aber leicht 
anhalten und er läuft nicht wieder von alleine an (Beide lassen den 
Motor im Uhrzeigersinn drehen).


Im Internet finde ich gefühlt 100 verschiedene Tabellen.
Muss ich die alle durchprobieren oder gibt es eine "richtige" Tabelle?

Danke und viele Grüße
Peter

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Bewertung
0 lesenswert
nicht lesenswert
Peter H. schrieb:
> Oder unterscheiden die sich in der Anordnung
> der Hall Sensoren etc.?

Aber klar. Da es keinerlei Standard gibt (und das betrifft sowohl 
Sensoranschluss als auch Motorwicklungen), muss das bei jedem Motor 
angepasst werden.
Wir hatten sogar schon E-Antriebe fürs Schiff komplett mit Controller, 
bei denen uns der Hersteller nicht sagen konnte, welche Leitung des 
Motors auf welchen Phasenausgang gehört. Der Typ schlug mir genau die 
Testmethode vor, die ich oben gepostet hatte:

> Gibst du also nur ganz wenig PWM, solltest
> du beim Drehen merken, wie der Motor immer weiter ziehen will.

von Peter H. (borntopizza)


Bewertung
0 lesenswert
nicht lesenswert
Hmm okay das ist jetzt blöd :D

Dann probiere ich mal wie Du es vorgeschlagen hast.

Danke für die Hilfe!

von Peter H. (borntopizza)


Bewertung
0 lesenswert
nicht lesenswert
Mir ist gerade noch eingefallen, dass ich ja den A200S aus dem VESC 
Projekt hier rumliegen habe.

Der Controller stellt über seine Software ein, welchen Phase bei welchem 
Hall Sensor am besten passt.
Kann man das irgendwie ausnutzen und das irgendwie nach verfolgen?
Ich habe zur Zeit leider nur dieses 12€ Oszi vom Aliexpress, mein 
anderes Hameg mag zur Zeit nicht.
Oder braucht man da etwas anderes dafür?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.