jawohl, bitte weiter verfolgen , da bin ich auch dran interessiert. Mein Arduino PWM ist noch nicht
abgeschlossen, bzw weiter gediehen. Wurde durch einen Festplatten Crash ausgebremst.
Was braucht man zusätzlich zu den PWM Teilen für die Drehzahlregelung an Hardware?
Es gab hier schon vor einigen Jahren einen Faden, in dem eine analoge PWM (Pulsbreitensteuerung) beschrieben wurde (https://www.h0slot.eu/showthread.php?tid...nsteuerung); die Details sind aber leider nicht mehr erhältlich, da der erwähnte Download-Bereich nicht mehr zu existieren scheint - zumindest kann ich ihn nicht finden. ...
robi
Hallo zusammen,
Ja, das war wirklich schon etwas lang her. Zischenzeitlich gab es diverse Sofware und Server-Wechsel des Forums, Mit einigen Datenverlusten. Die Schaltung existiert moch, und mein Bruder (Heiko) sucht auch wo, er die Schaltplan-Datei geparkt haben könnte. Ist aber halt ei bissel her ... . Und mittlerweile hat auch er andere Baustellen am laufen.
06-09-2020, 21:01 (Dieser Beitrag wurde zuletzt bearbeitet: 06-09-2020, 21:28 von finbar.)
Hallo AMSler,
ja, es handelt sich um eine Regelung, da ich mit PWM-Steuerungen bisher nicht das gewünschte Resultat erzielen konnte. Für den Leistungsschalter bin ich beim L293 geblieben, der zwar an der Leistungsgrenze arbeitet, er bietet aber den Vorteil, dass die Ausgänge nicht nur die Zustände 0 und 1 beherrschen, sondern durch den enable Eingang auch hochohmig geschaltet werden können. Dies ist erforderlich zur Messung der Generatorspannung, entsprechende H-Brücken sind rar. Ich schalte also einen Motoranschluss gegen die Betriebsspannung, den anderen Anschluss hochohmig. Dann kann die Betriebsspannung minus die Generatorspannung gemessen werden. Pro Fahrzeug sind eine Diode, zwei Zenerdioden, zwei, drei Widerstände und ein Kondensator für die Messschaltung erforderlich. Ausserdem ein 4051 Multiplexer, um die 6 A/D Eingänge des Arduino auf 8 zu erweitern. Ich benötige Eingänge für 4x Sollwert und 4x Istwert. Und es benötigt ein stabilisiertes Netzteil, ich arbeite z.Zt. mit einem Faller-Trafo 4016? mit anschliessender Stabilisierung, welche auf 20 Volt eingestellt ist. Ich werde den Schaltplan die nächsten Tage hier einstellen.
Ciao, Finbar.
Hallo Holger,
Vielen Dank für deine Mühe. Ich glaube ich kenne die analoge Impulssteuerung von Heiko (Herrlich?, wenn ich mich richtig erinnere) hab mich damals auch lange damit befasst. Die war ohne Rückmeldung des Motors, richtig? Was ich vorhabe ist folgendes: ich sage dem Motor er soll z.B. mit 10% Drehzahl drehen. Sehr kurz danach messe ich, ob der Motor mit 10% Drehzahl dreht. Dreht er langsamer, erhöht der Arduino automatisch die Spannung, wenn der Motor schneller dreht, verringert der Arduino die Motorspannung. Und das ganze vielleicht 100 mal pro Sekunde. Damit erreiche ich letztendlich eine konstante Drehzahl.
Finbar
Ein paar Fragen drängen sich mir auf:
Werden Sie die Schaltung zwar mit Lastregelung aber ohne PWM realisieren? Oder planen Sie eine lastgeregelte PWM-Ansteuerung?
Bisher war ich davon ausgegangen, dass die Messung der Generatorspannung immer direkt am Motor erfolgen muss, um wirksam zu sein. Haben Sie das Problem in anderer Weise gelöst? Oder ist das Regelverhalten auch bei fernem Verbraucher noch zufriedenstellend?
Unsere (Verkehrs-)Autochens ziehen um die 100 mA. Welche Grenzwerte für den L293 meinen Sie?
ciao michaelo ... und wer zuletzt aufgibt gewinnt.
Hallo Michaelo,
die Schaltung misst die Generatorspannung des Motors, welche proportional ist zur Drehzahl. Als Regler habe ich verschiedene Versionen ausprobiert, der Zweipunktregler funktioniert am besten. Also, fällt der Istwert unter den Sollwert, so wird für die komplette Halbwelle der Motor eingeschaltet, ist der Istwert höher als der Sollwert, bleibt der Motor ausgeschaltet. Die Pulsbreite bleibt gleich und ist somit keine PWM. Versuche die Pulsbreite mittels PID Regler zu regeln haben bei mir nicht befriedigend funktioniert.
Ich habe die Motorspannung auf 20Volt hochgesetzt, die Schleifer der Autos optimiert und die Schienen gereinigt. Natürlich ist der Kontakt zum Auto doppelt wichtig, da nicht nur die Steuerspannung zum Auto übertragen, sondern auch der Messwert zurückübertragen wird. Bei Fehlmessungen hilft mir aber die Software und ich messe jeden Wert 20 mal und arbeite mit der Summe der Messwerte.
Es geht um die Leistung, am L293 haben wir einen Spannungsabfall von ca. 3 V bei (ich rechne)150mA ergibt 0,45 Watt pro Fahrzeug.
Ciao, Finbar
Wie versprochen stelle ich hier zunächst einen Schaltplan für die Drehzahlregelung vor.
Den Arduino Sketch dazu lade ich in den nächsten Tagen hoch. Ich möchte noch ein paar Justierschrauben einbauen.
interessante Schaltung, insbesondere der De/Multiplexer .
Klar nutzt du die Generatorspannung. Ich vermute allerdings, dass mit der Entfernung des Autos von der Schaltung signifikante Unterschiede auftreten. Das wird m.E. aber nicht so schlimm sein, da es ja "nur" die Lastregelung betrifft.
Die Versorgung der Fahrzeuge mit 20 V halte ich für zu hoch, selbst wenn da noch Spannungsabfall durch die Schaltung hinzu kommt - die armen 12V-Autochens. Gibt es einen Grund dafür, weil der von dir verwendete Baustein 4051 ja auch niedrigere Spannungen zulässt?
Eine Idee : Wir verwenden ja standardmäßig je nach Motortyp Regler zwischen 40 und 120 Ohm. Den könnte man über eine Grätzbrücke an einen 4:1/2-channel Multiplexer (z.B. CD4052B) anschließen und die dann zwei Ausgänge im Arduino auswerten. Insbesondere die Faller-Reglerpulte (100 Ω ) wären dafür interessant. Wäre das eine Option für dich?
ciao michaelo ... und wer zuletzt aufgibt gewinnt.
Also die Idee den 4051 zu verwenden stammt nicht von mir, die verdanke ich dem Arduino Kochbuch. Im Übrigen wird der Multiplexer natürlich mit 5V vom Arduino betrieben. Sorry, die Versorgungsspannung habe ich im Schaltplan glatt vergessen. Wird korrigiert.
Richtig, die 20V Betriebsspannung sind hoch angesetzt. Nun, ich wollte als Netzteil den Faller Trafo 4016 verwenden, Gleichrichterbrücke dahinter und einen Elko, dann hats schnell 27 Volt. Die überschüssigen 7 Volt muß ein zur Stabilisierung benutzter LM317 verbraten. Die Verlustleistung ist nicht gering bei 4 Autos aber ich brauche die Stabilisierung unbedingt, da letztendlich die Betriebsspannung minus die Generatorspannung gemessen wird.
Dir ist klar, dass zur Messung z.B. der Ausgang 1Y des L293 auf High geschaltet wird, während der Ausgang 4Y hochohmig geschaltet wird (deshalb 1Y und 4Y, nicht 1Y und 2Y). Dann messe ich die Ausgangsspannung (bei stehendem Motor) von 1Y (18,5V) über den Motor und dessen Diode (17,8V), dann über D9(17,1V), Zenerdiode D11(5,1V), Spannungsteiler R2 und R6(4,6Volt). Damit liege ich knapp unter der als Schutzdiode für den Arduino dienende Zenerdiode D16, und ich habe fast den gesamten Arduino A/D Eingangsspannungsbereich abgedeckt. Das ergibt die bestmögliche Auflösung. Also, wenn die Betriebsspannung geändert werden soll, muss entsprechend auch die Zenerdiode D11 geändert werden zur Beibehaltung der bestmöglichen Auflösung.
Ich denke, bei einer idealen Leitung wäre es eigentlich egal, wo man misst. Jetzt kommen aber die Fallerschienen und Schleifer ins Spiel! Meine Versuche haben gezeigt, dass durch die 20V einfach eine zuverlässigere Messung stattfindet als bei 12V Betriebsspannung. (Ich gebe zu, ich habe reichlich alte Schienen).
Zu den Reglern: Ich mache hier nur einen Vorschlag wie man die Schaltung aufbauen kann. Die Regler kann man natürlich ändern, ich glaube es gab da auch schon entsprechende Vorschläge. Aber: ich verwende die volle Auflösung des Arduino A/D Eingangs 10-bit, 0...1023, die gleiche Auflösung verwende ich auch bei meinen Sollwert-Potis. Und es gelingt mir nicht die Potis stufenweise einzustellen, sodaß ich über die Verwendung von 10-Gang Potis nachdenke. Je langsamer die Autos werden, und dies ist der interessante Bereich, desto geringer ist die Generatorspannung und da kommt selbst die Auflösung des Arduino an ihre Grenzen.
Ich habe auf Anregung von mos im Schaltplan die Betriebsspannung auf 12 Volt reduziert, dazu die Zenerdioden D10, D11, D14 und D15 von 12V auf 4,7 Volt abgeändert und ein paar Kleinigkeiten ergänzt. Und hier ist ein vorläufiger Code.
Ciao Finbar
Code:
/* AMS controller 2 State using PWM outputs V0.8.2.ino
//
// Before starting:
//
// - double check direction of Zenerdiodes and measurement circuit to avoid 12V on Arduino input!
// - use stabilized power supply 12 Volt!
// - add heatsink to L293!
// - check each car is using diode
//
// - checked with and optimized for zinc motors
//
// controls 2 x 2 Faller AMS cars by measuring motor rpm via Back EMF and
// using L293N dual H bridge module, a CD4051 multiplexer and 4 potmeters
//
// *** Version 0.8.2 preliminary ***
// (c) Rainer Woerthmann
//
//
// -> No warranty
// -> Have fun
//
//
// ================================= [global variables ] ==========================================
*/
// input pin definition
const byte bemf1pin = A0; // Back-EMF input car 1 track A
const byte bemf2pin = A1; // Back-EMF input car 2 track A
const byte bemf3pin = A2; // Back-EMF input car 3 track B
const byte bemf4pin = A3; // Back-EMF input car 4 track B
const byte mx0 = 2; // to multiplexer 4051 pin 11, LSB
const byte mx1 = 3; // to multiplexer 4051 pin 10, HSB
const int analogPin =A5; // setpoint readings via multiplexer 4051, cars 1...4
// output pin definition H-bridge 1, track A (L293 V1 und V4)
const byte L293V1pin = 11; // track A, car 1, L293 pin 2, PWM
const byte L293V4pin = 6; // track A, car 2, L293 Pin 15, PWM
// output pin definition H-bridge, high state
const byte L293V12ena = 7; // car 1+2 enable, L293 Pin 1
const byte L293V34ena = 8; // car 3+4 enable, L293 Pin 9
// constant value to equalize speed of different motors // increase value => car faster, decrease value => car slower
const byte carfactor1 = 3; // f.e. zinc, 5 or 6
const byte carfactor2 = 3; // Truck Flachanker = 1
const byte carfactor3 = 3;
const byte carfactor4 = 3; //
int Setpoint1, Setpoint2, Setpoint3, Setpoint4; // setpoints cars 1...4
int bemf1,bemf2,bemf3,bemf4; // back-emf cars 1...4
int ref1,ref2,ref3,ref4; // reference values cars 1...4, standstill
int data1,data2;
byte pwm1,pwm2,pwm3,pwm4; // output cars 1...4
word i; // counter
const int pulsetime =5000; // frequency (around (2*(5ms+4ms measurement))
// increase if motor does not start, decrease for running smooth
// =========================== [ set up ]=========================================================================
pinMode(bemf1pin,INPUT); // back-emf car 1
pinMode(bemf2pin,INPUT); // back-emf car 2
pinMode(bemf3pin,INPUT); // back-emf car 3
pinMode(bemf4pin,INPUT); // back-emf car 4
pinMode(L293V12ena,OUTPUT); // H-bridge V 1,2 high state
pinMode(L293V34ena,OUTPUT); // H-bridge V 3,4 high state
digitalWrite(L293V12ena,LOW);
digitalWrite(L293V34ena,LOW);
pinMode(L293V1pin,OUTPUT); // H bridge input, cars 1..4
pinMode(L293V2pin,OUTPUT);
pinMode(L293V3pin,OUTPUT);
pinMode(L293V4pin,OUTPUT);
// read reference values
digitalWrite(L293V34ena,LOW); // cars 1 + 3 high state
digitalWrite(L293V1pin,HIGH); // car 1 to plus
digitalWrite(L293V2pin,HIGH); // car 3 to plus
digitalWrite(L293V12ena,HIGH); // cars 1 + 3 enable
delay(1000);
ref1 = analogRead(bemf1pin); // read reference (standstill) value car 1
ref1 = constrain(ref1,300,950);
ref3 = analogRead(bemf3pin); // read reference (standstill) value car 3
ref3 = constrain(ref3,300,950);
digitalWrite(L293V12ena,LOW); // cars 2 + 4 high state
digitalWrite(L293V3pin,HIGH); // car2 to plus
digitalWrite(L293V4pin,HIGH); // car 4 to plus
digitalWrite(L293V34ena,HIGH); // cars 2+4 enable
delay(1000);
ref2 = analogRead(bemf2pin); // read reference (standstill) value car 2
ref2 = constrain(ref2,300,950);
ref4 = analogRead(bemf4pin); // read reference (standstill) value car 4
ref4 = constrain(ref4,300,950);
} // end of setup
// =========================== [ main ] ==========================================================================
void loop() {
// 1. halfwave
// setup L293 for bemf measurement car 1 + 3
digitalWrite(L293V34ena,LOW); // L293 cars 1 + 3 high state
digitalWrite(L293V1pin,HIGH); // car 1 to plus
digitalWrite(L293V2pin,HIGH); // car 3 to plus
digitalWrite(L293V12ena,HIGH);
delayMicroseconds(500); // allow settings (0,5ms)
// measure bemf car 1 + 3
bemf1 = 0;
bemf3 = 0;
for (i = 0; i < 20; i++) { // do 20 readings
data1 = analogRead(bemf1pin); // read supply voltage minus bemf car 1
if (data1 < 100){ // poor contact?
data1 = ref1;
}
bemf1 += ref1-min(data1,ref1); // calculate rpm car1
data2 = analogRead(bemf3pin); // read supply voltage minus bemf car 3
if (data2 < 100) { // poor contact??
data2 = ref3;
}
bemf3 += ref3-min(data2,ref3); // calculate rpm car1
}
// return to pwm
analogWrite(L293V1pin,pwm1);
digitalWrite(L293V4pin,LOW);
analogWrite(L293V2pin,pwm3);
digitalWrite(L293V3pin,LOW);
digitalWrite(L293V34ena,HIGH); // end of measurement
// calculate new PWM value car 1
if (Setpoint1 < 1) {
analogWrite(L293V1pin,0); // standstill
}
else {
if (bemf1 <1) { // f.e. poor contact
analogWrite(L293V1pin,255); // add power car 1
}
else {
bemf1 = constrain(bemf1/carfactor1,0,1023);// include carfactor
if (Setpoint1>bemf1) { // power calculation car 1
pwm1 = 255; // value may be reduced for smooth drive car1 (0...255)
}
else {
pwm1 = 0; // PWM off
}
analogWrite(L293V1pin,pwm1); } // write new PWM value car 1
}
// calculate new PWM value car 3
if (Setpoint3 <1) {
analogWrite(L293V2pin,0); // standstill
}
else {
if (bemf3 <1) { // f.e. poor contact
analogWrite(L293V2pin,255); // add power car 3
}
else {
bemf3 = constrain(bemf3/carfactor3,0,1023);// include carfactor
if (Setpoint3>bemf3) { // power calculation car3
pwm3 = 255; // value may be reduced for smooth drive car3 (0...255)
}
else {
pwm3 = 0; // PWM off
} }
analogWrite(L293V2pin,pwm3); // write new PWM value car 3
}
delayMicroseconds(pulsetime); // hold signal until end of halfwave
// end 1. halfwave
// 2. halfwave
// setup L293 for bemf measurement car 2 + 4
digitalWrite(L293V12ena,LOW); // L293 cars 2 + 4 high state
digitalWrite(L293V3pin,HIGH); // car 2 to plus
digitalWrite(L293V4pin,HIGH); // car 4 to plus
digitalWrite(L293V34ena,HIGH);
delayMicroseconds(500); // allow settings (0,5ms)
// measure bemf car 2 + 4
bemf2 = 0;
bemf4 = 0;
for ( i = 0; i < 20; i++) { // do 20 readings
data1 = analogRead(bemf2pin); // read supply voltage minus bemf car 2
if (data1 < 100){ // poor contact?
data1 = ref2;
}
bemf2 += ref2-min(data1,ref2); // calculate rpm car 2
data2 = analogRead(bemf4pin); // read supply voltage minus bemf car4
if (data2 < 100) { // poor contact?
data2= ref4;
}
bemf4 +=ref4-min(data2,ref4); // calculate rpm car 4
}
// return to pwm
analogWrite(L293V4pin,pwm2);
digitalWrite(L293V1pin,LOW);
analogWrite(L293V3pin,pwm4);
digitalWrite(L293V2pin,LOW);
digitalWrite(L293V12ena,HIGH); // end of measurement
// calculate new PWM value car 2
if (Setpoint2 < 1) {
analogWrite(L293V4pin,0); // standstill
}
else {
if (bemf2 < 1) { // f.e. poor contact
analogWrite(L293V4pin,1); // add power car 2
}
else {
bemf2 = constrain(bemf2/carfactor2,0,1023); // include carfactor
if (Setpoint2>bemf2) {
pwm2 = 255; // value may be reduced for smooth drive car2 (0...255)
}
else {
pwm2 = 0; // PWM off
}
analogWrite(L293V4pin,pwm2); // write new PWM value car 2
}
}
// calculate new PWM value car 4
if (Setpoint4 < 1) {
digitalWrite(L293V3pin,0); // standstill
}
else {
if (bemf4<1) { // f.e. poor contact
analogWrite(L293V3pin,255); // add power car 4
}
else {
bemf4 = constrain(bemf4/carfactor4,0,1023); // include carfactor
if (Setpoint4>bemf4) { // power calculation car 4
pwm4 = 255; // value may be reduced for smooth drive car 4 (0...255)
}
else {
pwm4 = 0; // PWM off
}
digitalWrite(L293V3pin,pwm4); // write new PWM value car 4
}
}
11-09-2020, 19:58 (Dieser Beitrag wurde zuletzt bearbeitet: 11-09-2020, 20:00 von 72Sonett.)
Ich habe noch mal über dein Schaltplan nachgedacht... Die eine 4051 Multiplexer wird nur 50% benutzt, mit zwei multiplexer, 8 Potis und 2 H-brücken ist es auch möglich 8 Autos mit PWM und feedback zu fahren. Dein Arduino Programm bleibt im Grunde gleich, nur 4 regler zufugen:
Coole Idee, 8 Fahrzeug mit einem Arduino zu regeln. Dann benötigt man die Digitalausgänge des Arduino. In dieser Software-Version werden die Analogausgänge benutzt, also eine PWM mit festem Tastverhältnis ausgegeben. Ich habe das gemacht, da ich einmal die Pulsbreite in der Software variieren kann und ich zweitens auch eine Software-Version untersuche, die wirklich die Pulsbreite regelt. Also, wenn du die Software mit Digitalausgängen benötigst, die könnte ich dir geben.
Noch ein allgemeiner Hinweis zu Software: während der Initialisierung des Arduino werden die Referenzwerte der Motoren gemessen. Das oder die zu regelnde(n) Fahrzeug(e) müssen also auf der Bahn stehen, sonst wird es nicht korrekt geregelt. Der gemessene Wert wird auf dem Bildschirm angezeigt (falls angeschlossen) und sollte zwischen 800 und 900 liegen. Danach werden die Sollwerte angezeigt.
Mit 'Analogausgänge' meinst du hier 'PWM Ausgänge' ? Ja dann reicht ein Arduino Uno oder Nano nicht aus, die haben nur 6 PWM Ausgänge (3, 5, 6, 9, 10, 11) und mann brauche dan 8.
Mit ein Arduino Mega wurde das aber gehen, die hat 15 PWM ausgänge (2 - 13, 44 - 46).
Das kann mit dem Uno schon funktionieren. Du musst in der Software nur alle analogWrite..,255 ersetzen durch digitalWrite...,HIGH. Für das Fahrzeug funktioniert das ebenso.
Die Messung für zwei Fahrzeuge (Fahrzeug1 Track 1 und Fahrzeug3, Track 2) dauert etwa 4ms, beide Autos werden in jeder Halbwelle 20 mal gelesen. Danach bleiben 5ms Pause pro Halbwelle. In dieser Zeit könnten zwei weitere Fahrzeuge gelesen werden. Zeitlich müsste es also auch funktionieren.
Übrigens, ich habe die Betriebsspannung von 20 Volt auf 12 Volt reduziert, siehe Version 1.4.
12-09-2020, 23:53 (Dieser Beitrag wurde zuletzt bearbeitet: 11-12-2021, 22:09 von 72Sonett.)
(12-09-2020, 00:30)finbar schrieb: Das kann mit dem Uno schon funktionieren. ... in der Software nur alle analogWrite(..,255) ersetzen durch digitalWrite(...,HIGH) ...
Das habe ich gemacht, das Programm für 4 Autos sieht dann so aus:
Code:
// AMS controller 2 State using PWM outputs V0.8.2
//
// Before starting:
//
// - double check direction of Zenerdiodes and measurement circuit to avoid 12 V on Arduino input!
// - use stabilized power supply 12 Volt!
// - add heatsink to L293!
// - check each car is using diode
//
// - checked with and optimized for zinc motors
//
// controls 2 x 2 Faller AMS cars by measuring motor rpm via back EMF and
// using L293N dual H bridge module, a CD4051 multiplexer and 4 potmeters
// --------------------------------------------------------------
// *** Version 0.8.2 preliminary ***
// (c) Rainer Woerthmann
// -> No warranty
// -> Have fun
//
// ---------------------------------------------------------------
// *** Version 0.8.3 preliminary ***
// analogWrite() replaced with digitalWrite()
// pwm1,pwm2,pwm3,pwm4 variables eliminated
//
// ================================= [global variables ] ==========================================
//
// input pin definitions feedback voltage
const byte bemf1pin = A0; // Back-EMF input car 1 track A
const byte bemf2pin = A1; // Back-EMF input car 2 track A
const byte bemf3pin = A2; // Back-EMF input car 3 track B
const byte bemf4pin = A3; // Back-EMF input car 4 track B
const byte mx0 = 2; // to multiplexer 4051 pin 11, LSB
const byte mx1 = 3; // to multiplexer 4051 pin 10, HSB
const int setpointspin =A5; // setpoint potmeter readings via multiplexer 4051, cars 1...4
// output pin definition H-bridge 1, track A (L293 V1 und V4)
const byte L293V1pin = 11; // track A, car 1, L293 pin 2, PWM out
const byte L293V4pin = 6; // track A, car 2, L293 Pin 15, PWM out
// output pin definition H-bridge 2, track B, (L293 V2 and V3)
const byte L293V2pin = 10; // track B, car 3, L293 pin 7, PWM out
const byte L293V3pin = 9; // track B, car 4, L293 pin 10, PWM out
// output pin definition H-bridge, high state
const byte L293V12ENpin = 7; // car 1+2 enable, L293 Pin 1, dig out
const byte L293V34ENpin = 8; // car 3+4 enable, L293 Pin 9, dig out
// constant value to equalize speed of different motors // increase value => car faster, decrease value => car slower
const byte carfactor1 = 3; // f.e. zinc, 5 or 6
const byte carfactor2 = 3; // Truck Flachanker = 1
const byte carfactor3 = 3;
const byte carfactor4 = 3; //
int setpoint1, setpoint2, setpoint3, setpoint4; // setpoints cars 1...4
int bemf1,bemf2,bemf3,bemf4; // back-emf cars 1...4
int ref1,ref2,ref3,ref4; // reference values cars 1...4, standstill
int data1,data2;
//byte pwm1,pwm2,pwm3,pwm4; // output cars 1...4
word i; // counter
const int pulsetime =5000; // frequency (around (2*(5ms+4ms measurement))
// increase if motor does not start, decrease for running smooth
// =========================== [ set up ]=========================================================================
pinMode(bemf1pin,INPUT); // back-emf car 1
pinMode(bemf2pin,INPUT); // back-emf car 2
pinMode(bemf3pin,INPUT); // back-emf car 3
pinMode(bemf4pin,INPUT); // back-emf car 4
pinMode(L293V12ENpin,OUTPUT); // enable H-bridge V 1,2 high state
pinMode(L293V34ENpin,OUTPUT); // enable H-bridge V 3,4 high state
digitalWrite(L293V12ENpin,LOW);
digitalWrite(L293V34ENpin,LOW);
pinMode(L293V1pin,OUTPUT); // H bridge input, cars 1..4
pinMode(L293V2pin,OUTPUT);
pinMode(L293V3pin,OUTPUT);
pinMode(L293V4pin,OUTPUT);
// reference values
digitalWrite(L293V34ENpin,LOW); // cars 1 + 3 high state
digitalWrite(L293V1pin,HIGH); // car 1 to plus
digitalWrite(L293V2pin,HIGH); // car 3 to plus
digitalWrite(L293V12ENpin,HIGH); // cars 1 + 3 enable
delay(1000);
ref1 = constrain(analogRead(bemf1pin),300,950); // read reference (standstill) value car 1
ref3 = constrain(analogRead(bemf3pin),300,950); // read reference (standstill) value car 3
digitalWrite(L293V12ENpin,LOW); // cars 2 + 4 high state
digitalWrite(L293V3pin,HIGH); // car2 to plus
digitalWrite(L293V4pin,HIGH); // car 4 to plus
digitalWrite(L293V34ENpin,HIGH); // cars 2+4 enable
delay(1000);
ref2 = constrain(analogRead(bemf2pin),300,950); // read reference (standstill) value car 2
ref4 = constrain(analogRead(bemf4pin),300,950); // read reference (standstill) value car 4
Serial.print(ref1,DEC); // Show reference values
Serial.print(" ");
Serial.print(ref2,DEC);
Serial.print(" ");
Serial.print(ref3,DEC);
Serial.print(" ");
Serial.println(ref4,DEC);
} // end of setup
// =========================== [ main ] ==========================================================================
void loop() {
// 1. halfwave
// setup L293 for bemf measurement car 1 + 3
digitalWrite(L293V34ENpin,LOW); // L293 cars 1 + 3 high state
digitalWrite(L293V1pin,HIGH); // car 1 to plus
digitalWrite(L293V2pin,HIGH); // car 3 to plus
digitalWrite(L293V12ENpin,HIGH);
delayMicroseconds(500); // allow settings (0,5ms)
// measure bemf car 1 + 3
bemf1 = 0;
bemf3 = 0;
for (i = 0; i < 20; i++) { // do 20 readings
data1 = analogRead(bemf1pin); // read supply voltage minus bemf car 1
if (data1 < 100){ // poor contact?
data1 = ref1;
}
bemf1 += ref1-min(data1,ref1); // calculate rpm car1
data2 = analogRead(bemf3pin); // read supply voltage minus bemf car 3
if (data2 < 100) { // poor contact??
data2 = ref3;
}
bemf3 += ref3-min(data2,ref3); // calculate rpm car3
}
// return to pwm
//analogWrite(L293V1pin,pwm1); // pwm1 VALUE IS NOT INITIALISED !
digitalWrite(L293V4pin,LOW);
//analogWrite(L293V2pin,pwm3); // pwm3 VALUE IS NOT INITIALISED !
digitalWrite(L293V3pin,LOW);
digitalWrite(L293V34ENpin,HIGH); // end of measurement
// calculate new PWM value car 1
if (setpoint1 < 1) {
//analogWrite(L293V1pin,0);
digitalWrite(L293V1pin,LOW); // standstill
}
else {
if (bemf1 <1) { // f.e. poor contact
//analogWrite(L293V1pin,255); // add power car 1
digitalWrite(L293V1pin,HIGH); // add power car 1
}
else {
bemf1 = constrain(bemf1/carfactor1,0,1023);// include carfactor
if (setpoint1>bemf1) { // power calculation car 1
//pwm1 = 255; // xxxxxxxxxxx
digitalWrite(L293V1pin,HIGH); // write new PWM value car 1
}
else {
//pwm1 = 0; // PWM off
digitalWrite(L293V1pin,LOW); // write new PWM value car 1
}
//analogWrite(L293V1pin,pwm1); // write new PWM value car 1
}
}
// calculate new PWM value car 3
if (setpoint3 <1) {
//analogWrite(L293V2pin,0);
digitalWrite(L293V2pin,LOW); // standstill
}
else {
if (bemf3 <1) { // f.e. poor contact
//analogWrite(L293V2pin,255); // xxxxxxxxxxx
digitalWrite(L293V2pin,HIGH); // add power car 3
}
else {
bemf3 = constrain(bemf3/carfactor3,0,1023); // include carfactor
if (setpoint3>bemf3) { // power calculation car3
//pwm3 = 255; // xxxxxxxxx
digitalWrite(L293V2pin,HIGH); // write new PWM value car 3
}
else {
//pwm3 = 0; // PWM off
digitalWrite(L293V2pin,LOW); // write new PWM value car 3
}
//analogWrite(L293V2pin,pwm3); // xxxxxxxxxxxxxxxx
}
}
delayMicroseconds(pulsetime); // hold signal until end of halfwave
// end 1. halfwave
// --------------------------
// 2. halfwave
// setup L293 for bemf measurement car 2 + 4
digitalWrite(L293V12ENpin,LOW); // L293 cars 2 + 4 high state
digitalWrite(L293V3pin,HIGH); // car 2 to plus
digitalWrite(L293V4pin,HIGH); // car 4 to plus
digitalWrite(L293V34ENpin,HIGH);
delayMicroseconds(500); // allow settings (0,5ms)
// measure bemf car 2 + 4
bemf2 = 0;
bemf4 = 0;
for ( i = 0; i < 20; i++) { // do 20 readings
data1 = analogRead(bemf2pin); // read supply voltage minus bemf car 2
if (data1 < 100){ // poor contact?
data1 = ref2;
}
bemf2 += ref2-min(data1,ref2); // calculate rpm car 2
data2 = analogRead(bemf4pin); // read supply voltage minus bemf car4
if (data2 < 100) { // poor contact?
data2= ref4;
}
bemf4 +=ref4-min(data2,ref4); // calculate rpm car 4
}
// return to pwm
//analogWrite(L293V4pin,pwm2); // pwm2 VALUE IS NOT INITIALISED !
digitalWrite(L293V1pin,LOW);
//analogWrite(L293V3pin,pwm4); // pwm4 VALUE IS NOT INITIALISED !
digitalWrite(L293V2pin,LOW);
digitalWrite(L293V12ENpin,HIGH); // end of measurement
// calculate new PWM value car 2
if (setpoint2 < 1) {
//analogWrite(L293V4pin,0); // standstill
digitalWrite(L293V4pin,LOW); // standstill
}
else {
if (bemf2 < 1) { // f.e. poor contact
//analogWrite(L293V4pin,255); // add power car 2 (255, not 1)
digitalWrite(L293V4pin,HIGH); // add power car 2
}
else {
bemf2 = constrain(bemf2/carfactor2,0,1023); // include carfactor
if (setpoint2>bemf2) {
//pwm2 = 255; // xxxxxxxxxxxx
digitalWrite(L293V4pin,HIGH); // write new PWM value car 2
}
else {
//pwm2 = 0; // PWM off
digitalWrite(L293V4pin,LOW); // standstill
}
//analogWrite(L293V4pin,pwm2); // write new PWM value car 2
}
}
// calculate new PWM value car 4
if (setpoint4 < 1) {
//analogWrite(L293V3pin,0); // standstill
digitalWrite(L293V3pin,LOW); // standstill
}
else {
if (bemf4<1) { // f.e. poor contact
//analogWrite(L293V3pin,255); // add power car 4
digitalWrite(L293V3pin,HIGH); // add power car 4
}
else {
bemf4 = constrain(bemf4/carfactor4,0,1023); // include carfactor
if (setpoint4>bemf4) { // power calculation car 4
//pwm4 = 255; // xxxxxxxxxxxxx)
digitalWrite(L293V3pin,HIGH); // write new PWM value car 4
}
else {
//pwm4 = 0; // PWM off
digitalWrite(L293V3pin,LOW); // write new PWM value car 4
}
//analogWrite(L293V3pin,pwm4); // write new PWM value car 4
}
}
Serial.print(setpoint3,DEC); // need for diagnose purposes only
Serial.print(" ");
// Serial.print(bemf4,DEC); // helpful for diagnose
// Serial.print(" ");
Serial.print(setpoint4,DEC);
// Serial.print(" "); // helpful for diagnose
// Serial.print(bemf4,DEC);
Serial.println(" ");
delayMicroseconds(pulsetime); // hold signal until end of halfwave
}
// repeat forever
// ==========================[ end main ] ========================================================================
Auch pwm1, pwm2, pwm3, pwm4 gibt es nicht mehr (wurden nie initialisiert). Ohne "analogWrite()" könnte das Arduino nano Programm einfach ausgebreitet werden für 8 Autos.
Ich habe die Drehzahlregelung für die Autos nochmal upgedated, V 1.5. Die Schaltung wird jetzt mit 15V betrieben, dazu habe ich die Zenerdioden D5,D6,D7,D8 durch 8,2 Volt Typen ersetzt. Außerdem wurden die Widerstände R2, R4, R5 und R8 durch 150 Ohm ersetzt.
Ich habe eine Funktionsbeschreibung beigefügt und einen Sketch geschrieben, bei dem ein PID Regler die PWM regelt.
Have fun!
Code:
/* AMS controller myPID Control V0.8.7.ino
This sketch controls rpm of 2 x 2 Faller AMS cars by measuring motor rpm via back EMF using circuit diagram AMS control with feedback V 1.5.
Before starting:
- double check direction of zenerdiodes and measurement circuit to avoid supply voltage on Arduino input!
- use stabilized power supply!
- add heatsink to L293!
- check each car is using diode
- checked with and optimized for Faller zinc, LKW-Flachanker and PKW-Flachanker
*** Version 0.8.7 preliminary ***
(c) Rainer Woerthmann
-> No warranty
-> Have fun
================================= [include libraries ] ==========================================*/
#include <PID_v1.h>
/*
================================= [global variables ] ===========================================*/
// input pin definition
const byte bemf1pin = A0; // Back-EMF input car 1 track A
const byte bemf2pin = A1; // Back-EMF input car 2 track A
const byte bemf3pin = A2; // Back-EMF input car 3 track B
const byte bemf4pin = A3; // Back-EMF input car 4 track B
pinMode(bemf1pin,INPUT); // back-emf car 1
pinMode(bemf2pin,INPUT); // back-emf car 2
pinMode(bemf3pin,INPUT); // back-emf car 3
pinMode(bemf4pin,INPUT); // back-emf car 4
pinMode(L293V12ena,OUTPUT); // H-bridge V 1,2 high state
pinMode(L293V34ena,OUTPUT); // H-bridge V 3,4 high state
digitalWrite(L293V12ena,LOW);
digitalWrite(L293V34ena,LOW);
pinMode(L293V1pin,OUTPUT); // H bridge input, cars 1..4
pinMode(L293V2pin,OUTPUT);
pinMode(L293V3pin,OUTPUT);
pinMode(L293V4pin,OUTPUT);
// read and show reference values
digitalWrite(L293V34ena,LOW); // cars 1 + 3 high state
digitalWrite(L293V1pin,HIGH); // car 1 to plus
digitalWrite(L293V2pin,HIGH); // car 3 to plus
digitalWrite(L293V12ena,HIGH); // cars 1 + 3 enable
delay(1000);
ref[0] = analogRead(bemf1pin); // read reference (standstill) value car 1
ref[2] = analogRead(bemf3pin); // read reference (standstill) value car 3
digitalWrite(L293V12ena,LOW); // cars 2 + 4 high state
digitalWrite(L293V3pin,HIGH); // car2 to plus
digitalWrite(L293V4pin,HIGH); // car 4 to plus
digitalWrite(L293V34ena,HIGH); // cars 2 + 4 enable
delay(500);
ref[1] = analogRead(bemf2pin); // read reference (standstill) value car 2
ref[3] = analogRead(bemf4pin); // read reference (standstill) value car 4
for (i = 0;i<4;i++) { // show reference value information
Serial.print ("Car ");
Serial.print (i+1);
if (ref[i] < 800 || ref[i] > 950) {
Serial.print(" error: ");
}
else {
Serial.print (" ok: ");
carenable[i] =1;
}
Serial.println(ref[i],DEC);
}
delay(3000);
}
/* =========================== end of setup ======================================================================
=========================== [ main ] ========================================================================== */
void loop() {
// 1. halfwave
// setup L293 for bemf measurement car 1 + 3
digitalWrite(L293V34ena,LOW); // L293 cars 1 + 3 high state
digitalWrite(L293V1pin,HIGH); // car 1 to plus
digitalWrite(L293V2pin,HIGH); // car 3 to plus
digitalWrite(L293V12ena,HIGH);
delayMicroseconds(500); // allow settings (0,5ms)
// measure rpm car 1 + 3
rpm[0] = 0;
rpm[2] = 0;
for (i = 0; i < samples; i++) { // do 20 or so readings
data1 = analogRead(bemf1pin); // read supply voltage minus bemf car 1
if (data1 < ref[0]/4) { // poor contact?
data1 = ref[0];
}
rpm[0] += ref[0]-min(data1,ref[0]); // calculate rpm car1 and limit
data2 = analogRead(bemf3pin); // read supply voltage minus bemf car 3
if (data2 < ref[2]/4) { // poor contact??
data2 = ref[2];
}
rpm[2] += ref[2]-min(data2,ref[2]); // calculate rpm car3 and limit
}
rpm[0] = constrain(rpm[0]*carspeed[0],0,1023); // include motor mapping and limit
rpm[2] = constrain(rpm[2]*carspeed[2],0,1023); // include motor mapping and limit
// setup L293 for pwm
analogWrite(L293V1pin,pwm[0]);
digitalWrite(L293V4pin,LOW);
analogWrite(L293V2pin,pwm[2]);
digitalWrite(L293V3pin,LOW);
digitalWrite(L293V34ena,HIGH); // end of measurement
// calculate new PWM value car 1
if (setpoint[0] <1 || carenable[0]==0) { // standstill
analogWrite(L293V1pin,0);
}
else {
myPID1.Compute(); // calculate new PWM value
analogWrite(L293V1pin,pwm[0]); // write new PWM value car 1
}
// calculate new PWM value car 3
if (setpoint[2] <1 || carenable[2]==0) { // standstill
analogWrite(L293V2pin,0);
}
else {
myPID3.Compute(); // calculate new PWM value
analogWrite(L293V2pin,pwm[2]); // write new PWM value car 3
}
// show parameters
Serial.print(setpoint[0],0); // useful for diagnosis and adjustment but affects timing
Serial.print(" "); // shows car 1 and car 2 parameters
Serial.print(rpm[0],0);
Serial.print(" ");
Serial.print(pwm[0],0);
Serial.print(" ");
Serial.print(setpoint[1],0);
Serial.print(" ");
Serial.print(rpm[1],0);
Serial.print(" ");
Serial.print(pwm[1],0);
Serial.print(" ");
delay(pulsetime); // hold signal until end of halfwave
// end 1. halfwave
// 2. halfwave
// setup L293 for bemf measurement car 2 + 4
digitalWrite(L293V12ena,LOW); // L293 cars 2 + 4 high state
digitalWrite(L293V3pin,HIGH); // car 2 to plus
digitalWrite(L293V4pin,HIGH); // car 4 to plus
digitalWrite(L293V34ena,HIGH);
delayMicroseconds(500); // allow settings (0,5ms)
// measure bemf car 2 + 4
rpm[1] = 0;
rpm[3] = 0;
for ( i = 0; i < samples; i++) { // do 20 or so readings
data1 = analogRead(bemf2pin); // read supply voltage minus bemf car 2
if (data1 < ref[1]/5){ // poor contact?
data1 = ref[1];
}
rpm[1] += ref[1]-min(data1,ref[1]); // calculate rpm car 2
data2 = analogRead(bemf4pin); // read supply voltage minus bemf car4
if (data2 < ref[3]/5) { // poor contact?
data2 = ref[3];
}
rpm[3] +=ref[3]-min(data2,ref[3]); // calculate rpm car 4
}
// setup L293 for PWM
analogWrite(L293V4pin,pwm[1]);
digitalWrite(L293V1pin,LOW);
analogWrite(L293V3pin,pwm[3]);
digitalWrite(L293V2pin,LOW);
digitalWrite(L293V12ena,HIGH); // end of measurement
// calculate new PWM value car 2
if (setpoint[1] <1 || carenable[1] ==0) { // standstill
analogWrite(L293V4pin,0);
}
else {
myPID2.Compute(); // calculate new PWM value
analogWrite(L293V4pin,pwm[1]); // write new PWM value car 2
}
// calculate new PWM value car 4
if (setpoint[3] <1 || carenable[3] ==0) { // standstill
analogWrite(L293V3pin,0);
}
else {
myPID4.Compute(); // calculate new PWM value
analogWrite(L293V3pin,pwm[3]); // write new PWM value car 4
}
(23-11-2020, 14:43)finbar schrieb: ... Ich habe eine Funktionsbeschreibung beigefügt und einen Sketch geschrieben, bei dem ein PID Regler die PWM regelt.
klasse, vorbildlich .
ciao michaelo ... und wer zuletzt aufgibt gewinnt.