der Motor scheint ein BLDC motor zu sein, die Halsenoren dienen der Positionserkennung des Rotors, damit der Motorcontroller die Spulen präzise ansteuern kann. ist besonders hilfreich beim Anfahren/Beschleunigen des Motors.
Im RC-Modellbau nutzen wir sowohl sensored BLDC (besonders im RC-Car Bereich) als auch unsensored. Bei den unsensored wird das Motortiming über die gegen EMK der Spulen berechnet und über fixe Timings, das funktioniert aber bei sehr kleinen Drehzahlen schlecht bis gar nicht, diese Motoren laufen erst ab einer gewissen Drehzahl sauber ohne zu stottern, sind damit im unteren Drehzalbereich nicht feinfühlig zu regeln. Da sind die Sensored, also mit Hallsensoren ausgestatteten viel besser, da aüsserst feinfühlig zu Regeln.
Im oberen Drehzahlbereich bedeutet dies aber wiederum sehr viel mehr Rechenleistung (Rechenzeit) für den Controler, was diesen etwas träge macht. aus diesem Grund aben wir im Modellbau dann sensored-Regler, die beide betriebsarten gemischt verwenden. wenn also ein Sensored Motor dranhängt, wird dieser im unteren Drehzahlbereich und (zum Teil) während dem Hochlaufen das timing über die Hallsensoren gesteuert, und danach schaltet der Regler um und benutzt vorwiegend user definierbare timings. Die erlauben dann auch , den Motor auf die strecke abzustimmen und so möglichst viel aus dem Motor rauszuholen.
Jo. BrushLessDC ![]()
Ich hatte oben schon das Musterblatt in #12.
Wenn ihr sowas extern besteuert, was nehmt ihr als Controller?
Ne neue Platine zu machen und den da auszulöten ist ja nu nicht soo schlimm.
Im Modellbau haben wir natürlich da unsere Regler.
Aber: Es gibt einen ATTiny der darauf spezialisiert ist, BLDCs zu steuern, da er die entsprechenden, an Timer gekoppelten 3 Gegenläufige Ausgangs-Paare beinhaltet, Moment, ich muss nachschauen, welcher es ist. evt der 861, aber ich muss erst in meinen Unterlagen nachschauen, um sicher zu sein.
OK habs gefunden. es sind die Attiny's 261, 461, 861 die dazu besonders geeignet sind, da sie 3 synchronisierbare PWM Ausgangspaare besitzen.
OC1A, OC1B, OC1D
Datenblatt
Die Sensoren sind separat verbaut, siehe Bild 2, die Sensoren haben genau genommen mit dem Motoraufbau auch nichts zu tun, die sollen dessen Drehzahl und Drehrichtung detektieren, die könnten auch an einem nachgeschaltetem Getriebe sitzen. Hier noch ein Hinweis: der Stator hat 9 Wicklungen.
Auf den ICs ist nicht wirklich etwas zu erkennen (auch nicht nach der Lackentfernung) und auf den Hallis befindet sich eine 221.
https://www.micronas.tdk.com/en/products/hall-switches/hal-2xy
![]()
Dann ist guter Rat gefragt - @Deltaflyer ist da besser drauf als ich....
NEIN! Dazu würden nicht 3 Sensoren benötigt, für Drehzahl und Drehrichtung würden auch 2 sensoren ausreichen. Diese Sensoren sind für das Motortiming zuständig. natürlich kann der Controller daraus auch Dreh-Richtung und Dreh-Zahl bestimmen / errechnen, was er vlt. hier auch tut, falls der Motor gleichzeitig zum erkennen der von aussen zugeführten mechanischen Energie dient. Aber wie gesagt, dazu reichen 2 Sensoren. Im Betrieb als Motor werden die Sensoren eindeutig für das Motortiming benötigt, darum sind diese auch direkt um den Rotor angebracht. Denn gerade hier ist es wichtig, dass eine feinfühlige Regelung des Motors im unteren Drehzahlbereich möglich ist, und dazu benötigt der BLDC-Motor die Sensoren, und zwar direkt am Rotor, nicht erst hinter einem Untersetzungs-Getriebe.
Ja, verstanden, aber die Funktionsweise war hier auch nicht wirklich gemeint, gemeint war, dass die Sensorausgänge nicht aus dem Stator kommen, weil der dem Grunde nach nicht viel damit zu tun hat.
Wie schätzt Du die Ausgangslage ein, könnte es Sinn machen den Motor mal auszulöten, auf eine neue PCB zu setzen und versuchen, diesen über einen externen Controller anzusteuern?
UUPS, jetzt hast Du mich kalt erwischt.
Es ist so: ich bin über den 861 vor etwa 3-1/2 Jahren gestossen, als ich für den Umbau eines Spektrum DX3C Sender von 3Kanal auf 2Kanal + 7xSchaltkanal (5 Rastend, 2 Tastend) einen Controler mit mehr IO-Pins als den ATtiny84 benötigte, den ich auch schnell zur verfügung hatte, um damit zu experimentieren, also bei meinem bevorzugten Elektronikversender (in der Schweiz gibt es da nicht viele) auf Lager ist. Bei den Recherchen über den 861 bin ich dann über diese Eigenschaft gestossen, dass der eben speziell für BrushlessMotoren geeignet (entwickelt) ist.
Ich habe jedoch bisher noch nie einen Brushlessregler selber aufgebaut oder gar die Firmware dafür Programmiert.
Deshalb kann ich leider dahingehend nicht wirklich effektiv helfen. Man findet jedoch über google, wenn man nach 'ATtiny 861 BLDC' und ähnlich, durchaus recht detailierte infos, wie man das zum laufen bringt.
Mir selber fehlt leider die Zeit, mich da hinein zu knien, einerseits, weil ich noch mitten in einem Projekt stecke, dass unbedingt in nächster Zeit fertig werden muss, damit meine Katze bei meinem nächsten , erwarteten aber doch plötzlichen , Krankenhausaufenthalt sicher versorgt ist. bis die Externe Versorgung anspringt. Und anderseits möchte ich mich, nach Abschluss dieses Projects etwas aus den Hobbys zurückziehen, also nicht mehr so intensiv an Projekten arbeiten, und mich wieder etwas mehr dem Zwischenmenschlichen zuwenden, solange mir das noch möglich ist.
Ja, das sehe ich, andererseits stellst Du die Frage, warum der Motor sechs Anschlüsse hat.
In 5.2 BLDC Motor Control Implementation sehe ich "Zero Crossing Detection", mit drei Leitungen am Motor angeschlossen. In BLDC Treiber MIT AVR sehe ich das auch. Die drei zusätzlichen Anschlüsse könnten damit zusammenhängen.
Mehr Lesestoff: Bürstenlose DC-Motoren und Animation Bürstenlose DC-Motoren
Da hast Du Dir aber was vorgenommen ![]()
Vielen Dank für die Links und Hinweise.
Ja, da brauche ich vermutlich einen neuen Plan.
Paßt das zu Deinem Motor?
Da bin ich mir zwar nicht ganz sicher, aber sehr wahrscheinlich ist, dass der 2. Schritt, die Ansteuerung über den Arduino, lösbar wird, wenn ich herausfinde, wie die 6 Eingänge zu verschalten sind.
Hallo Leute,
so, hier ein kurzes Feedback und die erneute Bitte um Hilfe.
Nachdem die chinesischen Volksgenossen mir mitteilten, dass die 3 zusätzlichen Pins nur der Befestigung dienen, habe ich den Treiber wie von „agmue“ vorgeschlagen und 3 zusätzliche Hall-Sensoren eingebaut. Der Motor funktioniert perfekt und ist auch für andere Anwendungen nur zu empfehlen.
Zum Problem:
Die Ansteuerung soll über eine Wägezelle erfolgen. Einzeln aufgebaut ist auch alles gut, aber wenn ich beide Systeme verheiraten will, kommt es zu einem Konflikt. Das liegt sicher daran, dass in der Bibliothek auch ein Interrupt verwendet wird oder delays verwendet werden. Da die Art des Rückgabewertes der Wägezelle für die Ansteuerung völlig egal ist, benötige ich die einfachste Lösung den HX711 auszulesen oder anzusteuern, ohne dass mein jetziger Sketch kapituliert.
Sicher hat jemand von Euch damit Erfahrung.
const int SensorPin = 2; //Interrupt Pin (nur 2 oder 3 @ Arduino Uno)
const byte Brake = 8;//Pinausgang Bremse, HIGH = Vollbremsung
const byte PWM = 9;// Pinausgang für Drehzahl
byte power = 30;// Motor-Drehzahl
const byte Drehrichtung = 10;// Pin Drehrichtungswechsel LOW/HIGH Drehrichtung
const int Pause[] = {100, 500, 1000, 2000};
unsigned long FlagMillis;
unsigned int Counter;
bool setupStep = LOW;
bool Normalbetrieb = LOW;
void motor(bool Stop, bool Richtung, int pwmSignal) {
digitalWrite (Brake, Stop);
digitalWrite (Drehrichtung, Richtung);
analogWrite (PWM, pwmSignal);
}
void M_Stop() {
motor(HIGH, LOW, 0);
}
void M_Hoch() {
motor(LOW, HIGH, power);
}
void M_Runter() {
motor(LOW, LOW, power);
}
void count () {
Counter++;
}
void setup() {
Serial.begin(9600);
pinMode(SensorPin, INPUT); //definiertes Potenzial (HIGH/LOW) von einem Hall-Sensor
pinMode(Brake , OUTPUT);
pinMode(PWM , OUTPUT);
pinMode(Drehrichtung , OUTPUT);//Drehrichung
}
void loop() {
motorSetup();
motorMatik();
Serial.print("\t Counts: ");
Serial.print(Counter);
Serial.print("\t setupStep: ");
Serial.println(setupStep);
}
void motorSetup() {
if (!setupStep) { //Variable um den Setupvorgang vom Normalbetrieb zu trennen
Counter = 0;
attachInterrupt(digitalPinToInterrupt(SensorPin), count, CHANGE);
delay(500);
detachInterrupt(digitalPinToInterrupt(SensorPin));//Stop zur Ermittlung der Drehzahl über 500ms
motor(LOW, LOW, 30); //Kriechgang (30) zum Anfahren der Endposition (Anschlag)
}
static unsigned long SetupMillis = 0;
if ((Counter < 10) && ((millis() - SetupMillis >= 1000))) {// 1s um den Anlaufprozess zu überbrücken
M_Stop (); // Drehzahl sinkt am Anschlag unter (10) , der Motor stopt
setupStep = HIGH;
Counter = 1000;// Counter wir af 1000 gesetzt um ein "Überfahren" in den negativen Bereich zu verhindern
}
// Der Zähler wird auf Positionsmods umgestellt, absolute Werte werden gespeichert
if (setupStep && !Normalbetrieb) {
attachInterrupt(digitalPinToInterrupt(SensorPin), count, CHANGE);
motor (LOW, HIGH, 120); //Richtungswechsel nach Anschlag
}
if (Counter >= 1100) {//Fahrt auf Ausgangsposition (z.B X + 100)
M_Stop ();//Setup-Phase ist beendet, Motor steht in Ausgangsposition
Normalbetrieb = HIGH;//Umschalten auf Normalbetrieb
}
}
void motorMatik () {
if (Normalbetrieb) {
attachInterrupt(digitalPinToInterrupt(SensorPin), count, CHANGE);
// /* Wägezelle (WZ) erreicht max. Wert -> runter schalten um x Counts
// Pause
// WZ erreicht min. Wert -> hoch schalten um x Counts
// */
//
//
//
//
//
}
}
In deinem Code in #35 sehe ich keine Bibliothek...
Hallo michael_x,
ja, das ist der Sketch ohne Wägezelle.
Die Bibliothek war: HX711_ADC.
Chapeau für Dein Durchhaltevermögen!
Ich würde das Pferd andersherum aufzäumen: Erst den Motorsketch vernünftig programmieren, dann HX711 ergänzen. Kernproblem scheint mir die Messung der Impulse während delay(500); zu sein. Damit verträgt sich keine andere Aktivität.
Erster Schritt zur Lösung ist also die Zeitmessung mit millis(). Der Herzschlag soll die scheinbare Gleichzeitigkeit verdeutlichen:
const int SensorPin = 2; //Interrupt Pin (nur 2 oder 3 @ Arduino Uno)
const uint32_t MESSINTERVALL = 500;
volatile unsigned int counter;
bool neuerwert = false;
bool Normalbetrieb = LOW;
void setup() {
Serial.begin(9600);
Serial.println("\nStart");
pinMode(SensorPin, INPUT); //definiertes Potenzial (HIGH/LOW) von einem Hall-Sensor
attachInterrupt(digitalPinToInterrupt(SensorPin), count_isr, CHANGE);
Normalbetrieb = HIGH;
}
void loop() {
motorMatik();
herzschlag();
}
void count_isr () {
counter++;
}
void motorMatik () {
uint32_t jetzt = millis();
static uint32_t vorhin = 0;
static unsigned int zaehler = 0;
if (Normalbetrieb) {
if (jetzt - vorhin >= MESSINTERVALL) {
vorhin = jetzt;
zaehler = counter;
counter = 0;
Serial.print("\t Zaehlerstand: ");
Serial.println(zaehler);
}
}
}
void herzschlag() {
pinMode(LED_BUILTIN, OUTPUT); // interne LED für Testzweke aktiviert
uint32_t jetzt = millis();
static uint32_t vorhin = 0;
const uint32_t BLINKZEIT = 111; // Primzahl
if (jetzt - vorhin >= BLINKZEIT) {
vorhin = jetzt;
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
}
Wäre das eine Grundlage für weitere Überlegungen?
Bist Du sicher, es handelt sich um die Drehzahl? Mit analogWrite wird eine feste Frequenz von 490 Hz ausgegeben, die 30 gibt das Puls-Pausenverhältnis an. Brushlessmotoren werden mit einem Signal wie Servos angesteuert, Takt und Richtung erinnern mich doch stark an Schrittmotoren, was ich für ein Getriebe auch sinnvoll fände.
Hallo agmue,
vielen Dank für die Unterstützung,
ja, das klingt gut, obwohl es auf eine zeitgenaue Kraftmessung nicht ankommt,
hätte man damit aber vermutlich auch für künftige Probleme schon mal vorgesorgt.
Allerdings sind die 500 millis aus dem delay nicht kritisch, da dies sozusagen noch ein Setup ist, welches nach dessen Durchlauf und dann mit: (setupStep = 1) nicht wieder angesprochen wird.
In dieser Phase des Programms wird noch keine Kraftmessung benötigt. Hier findet der Motor nur seine Ausgangsposition. (Video) und Bild (Ausschnitt1 sM).
In Bild (Ausschnitt2 sM) ist der Verlauf mir Bibliothek HX711 dargestellt, HX711.h scheint "motorSetup()" komplett zu unterdrücken. Ich hänge beide Sketch-Versionen unten an.
Noch etwas anders:
Du hast für die Blinkzeit eine Primzahl verwendet, warum macht man das so?
die ersten Positionen 13, 15, 14, 15 usw. sind quasi die Geschwindigkeitsanzeige,
sinkt die unter 10, wird gestoppt und in Ausgangsposition gefahren
mit HX711 Motor überspringt das Setup
const int SensorPin = 2; //Interrupt Pin (nur 2 oder 3 @ Arduino Uno)
const byte Brake = 8;//Pinausgang Bremse, HIGH = Vollbremsung
const byte PWM = 9;// Pinausgang für Drehzahl
byte power = 150;// Motor-Drehzahl-Normalbetrieb
const byte Drehrichtung = 10;// Pin Drehrichtungswechsel LOW/HIGH Drehrichtung
unsigned long FlagMillis;
unsigned int Counter;
bool setupStep = LOW;
bool Normalbetrieb = LOW;
void motor(bool Stop, bool Richtung, int pwmSignal) {
digitalWrite (Brake, Stop);
digitalWrite (Drehrichtung, Richtung);
analogWrite (PWM, pwmSignal);
}
void M_Stop() {
motor(HIGH, LOW, 0);
}
void M_Hoch() {
motor(LOW, HIGH, power);
}
void M_Runter() {
motor(LOW, LOW, power);
}
void count () {
Counter++;
}
void setup() {
Serial.begin(9600);
pinMode(SensorPin, INPUT); //definiertes Potenzial (HIGH/LOW) von einem Hall-Sensor
pinMode(Brake , OUTPUT);
pinMode(PWM , OUTPUT);
pinMode(Drehrichtung , OUTPUT);//Drehrichung
}
void loop() {
motorSetup();
motorMatik();
Serial.print("\t Counts: ");
Serial.print(Counter);
Serial.print("\t setupStep: ");
Serial.println(setupStep);
}
void motorSetup() {
if (!setupStep) { //Variable um den Setupvorgang vom Normalbetrieb zu trennen
Counter = 0;
attachInterrupt(digitalPinToInterrupt(SensorPin), count, CHANGE);
delay(500);
detachInterrupt(digitalPinToInterrupt(SensorPin));//Stop zur Ermittlung der Drehzahl über 500ms
motor(LOW, LOW, 30); //Kriechgang (30) zum Anfahren der Endposition (Anschlag)
}
static unsigned long SetupMillis = 0;
if ((Counter < 10) && ((millis() - SetupMillis >= 1000))) {// 1s um den Anlaufprozess zu überbrücken
M_Stop (); // Drehzahl sinkt am Anschlag unter (10) , der Motor stopt
setupStep = HIGH;
Counter = 1000;// Counter wir af 1000 gesetzt um ein "Überfahren" in den negativen Bereich zu verhindern
}
// Der Zähler wird auf Positionsmods umgestellt, absolute Werte werden gespeichert
if (setupStep && !Normalbetrieb) {
attachInterrupt(digitalPinToInterrupt(SensorPin), count, CHANGE);
motor (LOW, HIGH, 120); //Richtungswechsel nach Anschlag
if (Counter >= 1100) {//Fahrt auf Ausgangsposition (z.B X + 100)
M_Stop ();//Setup-Phase ist beendet, Motor steht in Ausgangsposition
Normalbetrieb = HIGH;//Umschalten auf Normalbetrieb
}
}
}
void motorMatik () {
if (Normalbetrieb) {
attachInterrupt(digitalPinToInterrupt(SensorPin), count, CHANGE);
}
}



