Hallo,
es gibt ja die neuen Prozessoren von Intel, sollen kompatibel sein mit
dem Arduino/Genuino Uno.
Nur sehr viel schneller. 10xgrößerer Speicher, 32 Mhz Taktrate und so
weiter.
Mein Blick ist drauf gefallen, weil mein Arduino Uno mit einer Steuerung
so an seiner Leistungsgrenze herumeiert, er ist einfach nicht sehr
schnell.
Kann jemand aus eigener ERfahrung zu diesem Bord etwas sagen?
Insbesondere was Kompatiblität und SPeed angeht?
Würde ja andere Mitleser vielleicht auch interessieren.
Xenophon
Hmm. Den ich habe hat meine ich 400MHz und riesig viel Ram und Flash.
Ich nutze ihn aber aktuell als Linux System.
Als Arduino hatte ich ihn nur kurz mal getestet und wie kompatibel er
wirklich ist..?
Muesste man ggf. mal ausprobieren..
Letzlich laeuft hier ein Linux System, das den Arduino Code ablaufen
laesst..
Peter
Holger S. schrieb:> es gibt ja die neuen Prozessoren von Intel, sollen kompatibel sein mit> dem Arduino/Genuino Uno.>> Nur sehr viel schneller. 10xgrößerer Speicher, 32 Mhz Taktrate und so> weiter.
Da gibt es noch viele Zwischenstufen, siehe Arduino MEGA2560, Arduino
Due, STM32-Arduino o. ä.
Holger S. schrieb:> Mein Blick ist drauf gefallen, weil mein Arduino Uno mit einer Steuerung> so an seiner Leistungsgrenze herumeiert, er ist einfach nicht sehr> schnell.
Hier sollte man sich fragen, ob das Programm/Sketch nicht noch durch
wenige gezielte Eingriffe laufzeitoptimiert werden kann. Dazu muss man
aber wissen, was bremst. Deine Aussage erweckt den Eindruck, als ob Du
das nicht wüßtest, was wiederum darauf schließen läßt, dass da
erhebliche Defizite bestehen und Optimierungspotential besteht.
Zeig doch mal Deinen Sketch.
Zweifler schrieb:> Hier sollte man sich fragen, ob das Programm/Sketch nicht noch durch> wenige gezielte Eingriffe laufzeitoptimiert werden kann. Dazu muss man> aber wissen, was bremst. Deine Aussage erweckt den Eindruck, als ob Du> das nicht wüßtest, was wiederum darauf schließen läßt, dass da> erhebliche Defizite bestehen und Optimierungspotential besteht.>> Zeig doch mal Deinen Sketch.
Kann ich heute abend nachreichen.
Ich weiß aber, was bremst. Es sind analogRead(), pulseIn() und
Servo.write.
Holger S. schrieb:> Es sind analogRead(),
Der ADC kann nebenläufig arbeiten.
Martin K. schrieb:> pulseIn()
Kann evtl. mit Hilfe eines Timers auch nebenläufig gemacht werden.
Bedenke, dass so ein AVR Mikrocontroller wesentlich mehr leistet, als
ein C64 oder ein Gameboy, und die hatten ganze Videospiele ausgeführt!
Nutze die Gelegenheit, zu lernen, wie man performante Programme
schreibt. Das Gelernte wird auch auf größeren Systemen hilfreich sein.
Oder muss das Projekt schnell fertig werden?
101:
Ein PIN-doggeln braucht auch ohne delay() eine Milisekunde. Das
läuft offensichtlich über Linux.
Mich würde interessieren, wie man ein Programm direkt am 101 ausführt.
Himmelherrgottsakra, ich stell da doch kein delay() rein! ;)
Wenn es das gäbe, würde ich eher das Gegenteil reinsetzen! ;)
Ich stell hier mal den Kern der Loop-Schleife rein. Darin ist alles
enthalten, was Problem machen kann:
Erklärung:
Die Sensoren müssen häufig gemessen werden, ca. 400-500/sec. Für die
Fahrtregler reichen 5-6/Sec.
Daher sind die I/O Funktionen in Schleifen gepackt. Die Frequenz für die
Funktionen entspricht dem Kehrwert der Schleifen.
TAKT_SENSOREN=3000
TAKT_SENDER = 30000
TAKT_STEUERUNG=30000
Die Sensoren werden damit 10mal so oft abgefragt wie die Sendersignale.
Der ARduino macht mit diesem Grundgerüst ca. 140.000
Programmdurchläufe/sec, die Sensoren werden ca. 400/sec abgefragt
(Untergrenze), Sender 4-5 mal/sec.
Das Programm ist noch nicht fertig, daher wird die Frequenz von 140 kHz
wohl noch abfallen. Bzgl. der Sensoren ist es an der Grenze.
Was würde das schnell machen?
Assembler für die Input-Abfragen
oder maschinennahe C-Befehle (z. B. PORT).
Dazu habe ich aber keinen Code gefunden, den man annähernd verwenden
könnte, und mit Assembler und PORT muß man sich in der
Prozessor-Architektur auskennen, was bei mir nicht der Fall ist.
Wäre die Hardware insgesamt ca. 10x schneller, gäbe es keine Probleme.
Ich hab mal den Code etwas formatiert (fuer den geneigten Leser), das
aber nur nebenbei:
1
voidloop()
2
{
3
if(zaehler_sensoren==0)
4
{
5
if(digitalRead(pin_sensor1)==LOW)
6
{
7
sensordurchgang1=millis();
8
}
9
10
if(digitalRead(pin_sensor2)==LOW)
11
{
12
sensordurchgang2=millis();
13
}
14
15
if(sensordurchgang1>sensordurchgang2)
16
{
17
vorlauf=sensordurchgang1-sensordurchgang2;
18
}
19
else
20
{
21
vorlauf=0;
22
}
23
24
zsensor++;//zaehlt anzahl Zugriffe
25
zaehler_sensoren=TAKT_SENSOREN;
26
}
27
else
28
{
29
zaehler_sensoren--;
30
}
31
32
if(zaehler_sender==0)
33
{
34
kanal1=pulseIn(pin_kanal1,HIGH);
35
kanal2=pulseIn(pin_kanal2,HIGH);
36
zkanal++;
37
zaehler_sender=TAKT_SENDER;
38
}
39
else
40
{
41
zaehler_sender--;
42
}
43
44
if(zaehler_steuerung==0)
45
{
46
regler_1.write(90);
47
regler_2.write(90);
48
zsteuerung++;
49
zaehler_steuerung=TAKT_STEUERUNG;
50
}
51
else
52
{
53
zaehler_steuerung--;
54
}
55
}
Holger S. schrieb:> Die Sensoren müssen häufig gemessen werden, ca. 400-500/sec.
Dann nimm einen Timerinterrupt der alle 2ms ausloest.
Holger S. schrieb:> Dazu habe ich aber keinen Code gefunden
Einfach mal ins Datenblatt von dem uC schauen:
http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf
In Kapitel 18 "I/O-Ports" findest du alles, was du brauchst, inkl.
Codebeispiele fuer C und ASM, um I/O Pins anzusprechen.
Die Kapitel 16, 19, 20, 21, 22 und 28 koennten ebenfalls von interesse
fuer dich sein.
Holger S. schrieb:> Wäre die Hardware insgesamt ca. 10x schneller, gäbe es keine Probleme.
Der ATmega328P kann mit bis zu 20MHz laufen. Auf den Arduinoboards ist
standardmaessig ein 16MHz Quarz verbaut. Wenn du also den Quarz
austauscht...
Ralph S. schrieb:> ... wird sein Bootloader nicht mehr funktionieren !
... und abgesehen davon wird dann der eigentliche Engpass auch nicht
schneller durchlaufen:
pulseIn() waits for the pin to go HIGH, starts timing, then waits for
the pin to go LOW and stops timing.
Wie lang dauert denn ein pulseIn? Kommen da Servo-Signale mit 20ms?
Arduino F. schrieb:>> pulseIn()> Kann evtl. mit Hilfe eines Timers auch nebenläufig gemacht werden.
Helmut H. schrieb:> Ralph S. schrieb:>> ... wird sein Bootloader nicht mehr funktionieren !>> ... und abgesehen davon wird dann der eigentliche Engpass auch nicht> schneller durchlaufen:> pulseIn() waits for the pin to go HIGH, starts timing, then waits for> the pin to go LOW and stops timing.>> Wie lang dauert denn ein pulseIn? Kommen da Servo-Signale mit 20ms?>> Arduino F. schrieb:>>> pulseIn()>> Kann evtl. mit Hilfe eines Timers auch nebenläufig gemacht werden.
PulseIn() liest den Sender aus. Die Signale werden gemessen am
Empfängereingang.
Die Messdauer ist 20 ms + x (ca. 21.2 ms).
Würde man pulseIn() einfach in die Loop-Schleife packen, würde er nichts
anderes tun als diese Funktion auszuführen, wobei die Performance des
Programms um 98 Prozent auf 2 Prozent absackt.
Wie gezeigt, reduziere ich die Zugriffe im Programm aber auf 5
Zugriffe/Sec., so daß die Killerwirkung von pulseIn() damit praktisch
aufgehoben ist.
Die Sensoren wurden getauscht von PNP auf NPN. Wie sich das zeitlich
auswirkt, muß ich noch messen.
Insgesamt aber ist der Uno mit 500 Messungen am Sensor und 5 am Sender
bereits an der OBergrenze dessen, was er leisten kann, und das Programm
ist noch nicht komplett.
Eine schnellere Hardware wäre hier schon wünschenswert.
Ich hab den Genuino 101 mal bestellt, aus Neugier. Wg. Kompotibilität,
Treiberproblemen etc. bzw. wenn man mal eine wirklich schnelle Schaltung
baut.
Diese Schaltung kommt, wenn sie fertig ist, aus Platzgründen auf einen
Arduino Nano. Es sei denn, es würde so nicht funktionieren.
Das hier ist widerum ein super Beispiel contra Arduino Jünger. Man kommt
mit der Workframe ans Limit und anstatt es mithilfe Interrupts und
Baremetal es zu lösen wird ein größerer µC geholt. Hust hust.
Mach mal digitalRead weg. Das bremst dich aus.
Weitere Tipps wurden dir schon gegeben.
aSma>> schrieb:> Das hier ist widerum ein super Beispiel contra Arduino Jünger. Man kommt> mit der Workframe ans Limit und anstatt es mithilfe Interrupts und> Baremetal es zu lösen wird ein größerer µC geholt. Hust hust.>> Mach mal digitalRead weg. Das bremst dich aus.>
Mit digitalRead werden die Sensoren ausgelesen. Meßzugriffe mindestens
500/sek.
Den Tipp, das wegzumachen, kann ich irgendwie nicht ernst nehmen.
Machst du Scherze?
Woher bekomme ich dann die Sensor-Signale?
Holger S. schrieb:> kanal1=pulseIn(pin_kanal1,HIGH);> kanal2=pulseIn(pin_kanal2,HIGH);Holger S. schrieb:> Wäre die Hardware insgesamt ca. 10x schneller, gäbe es keine Probleme.
Du irrst, die Hardware ist völlig unschuldig, es liegt allein an der
Programmierung.
pulseIn ist nämlich blockierend, wie es in der Beschreibung steht:
"For example, if value is HIGH, pulseIn() waits for the pin to go
HIGH, starts timing, then waits for the pin to go LOW and stops
timing."
Schreib das um als Interrupt und schon rennt Dein Programm wie blöde.
Entweder ganz profan mit externen Interrupts oder mit Input-Capture des
Timers.
Beim ATmega328 kann man das Input-Capture über den ADC-MUX und analog
Komparator auf bis zu 8 Inputs umschalten, d.h. 8 Signale ganz ohne
Warten messen (PC0..5, PB0, PD7) bzw. 10 beim SMD-Gehäuse (+ ADC6,
ADC7).
Holger S. schrieb:> Machst du Scherze?
Du sollst die Sensoren schon einlesen, aber nicht mit digitalRead(). Das
ist zwar sehr praktisch für den Anfang, aber nicht besonders schnell.
Wobei ich glaube, dass Dein Bottleneck nicht dort liegt, siehe den Post
von Helmut.
Insgesamt sollte diese Aufgabenstellung einen ATmega zu höchstens 10%
auslasten. Sogar mit Arduino.
Gruß, Stefan
aSma>> schrieb:> Mach mal digitalRead weg. Das bremst dich aus.
Ich konnte keine Angaben dazu finden, wie lange das dauert.
Aber selbst, wenn ich 20 Takte ansetzte, wären das immer noch 800.000
digitalRead/s. Das sollte daher auch nicht der Flaschenhals sein.
Was machen und wie lange dauern die beiden regler_X.write?
Und mehr ist doch in dem kleinen Progrämmchen nicht drin.
Nimm einfach die von Helmut vorgeschlagene Lib:
Helmut H. schrieb:> Dabei ist es mit Pin Change Interrupt im Arduino Framework so einfach zu> vermeiden:> http://www.benripley.com/diy/arduino/three-ways-to-read-a-pwm-signal-with-arduino/
für alle Deine 4 Eingänge und schon ist Deine loop() praktisch leer. Und
da die pin-change-Interrupts nur wirklich dann aufgerufen werden, wenn
tatsächlich Pin Changes erfolgen, ist sogar digitalRead() nicht mehr
notwendig und Dein Uno wird fast arbeitslos.
Gruß, Stefan
@stefan @helmut u. a.
Vielen Dank für die guten Tipps!
Die Interrupts scheinen es wirklich zu bringen!
Das kannte ich bisher nicht.
WErde das heute abend ausprobieren und berichte dann wieder.
Xenophon
Gewöhne Dir an, keine blockierenden Funktionen zu benutzen (dazu gehört
auch delay()).
Das ist der kardinalfehler Nummer 1 in der Mikrocontroller
Programmierung - ganz besonders im Arduino Umfeld weil dieses blöde
Framework an allen Ecken und Kanten blockierende Funktionen
bereitstsellt.
So sind z.B. beinahe alle Webserver im Arduino Umfeld nicht dazu fähig,
mehrere HTTP Requests parallel abzuarbeiten, insbesondere wenn der
HTTP-GET Request auf mehrere TXP Segmente aufgeteilt ist.
Aber auch viele Android Programme scheitern an solchen Konstrukten. Sie
reagieren dann nicht auf Eingaben, wo sie es sollten und ziehen außerden
noch den Akku unnötig schnell leer. Manche Android Apps stürzen ab, wenn
die Netzwerk-Kommunikation länger als gewöhnlich dauert, und dadurhc zu
lange in einer Warteschleife hängen.
Auch in Linux und Windows gelten blockierende Funktionen längst als
No-Go.
Lerne, wie man ereignisgesteuerte Programme schreibt. Solche Programme
warte niemals auf irgend etwas, sondern sie bearbeiten Ereignisse. Etwa
so:
1
voidloop()
2
{
3
if(taste_gedrueckt()
4
{
5
reagiere_auf_Tastendruck();
6
}
7
if(signal_empfangen())
8
{
9
verarbeite_signal();
10
}
11
if(millis()>=mittagsPause)
12
{
13
pausenklingel_aktivieren();
14
// Nächste Mittagspause is morgen
15
mittagsPause=millis()+24*60*60*1000;
16
}
17
}
Bei Geräten mit Betriebsystem (wie dem ESP8266, Linux, Windows) stellst
du auf diese Weise sicher, dass das System und andere Programme
möglichst viel Rechenzeit ab bekommen und dass du selbst keine
Rechenzeit in Warteschleifen verschwendest.
Im falle deiner Singale und Interrupts bedeutet dies, dass du bei jedem
Interrupt lediglich den zeitpunkt efasst und dann in der Hauptschleife
mit den Messwerten arbeitest. Etwa so:
Bei Steigender-Flanke:
start=millis();
Bei fallender-Flanke:
ende=millis();
habeSignalGemessen=true;
und in der Hauptschleife:
if (habeSignalGemessen)
{
unsigned long signalDauer=ende-start;
// mach was draus
habeSignalGemessen=false;
}
Und falls Dir der Millisekunden-Time rdazu nicht fein genug ist, dann
verwendet einen anderen Timer, der z.B. in 1/10 Millisekunden hochzählt.
Das kann der Chip ganz von alleine, man muss den Timer dazu nur
initialisieren.
Wenn du auf einem AVR 20ms wartest, verplemperst du 400.000 Befehle.
Wenn du auf einem PC 29ms wartest, verplemperst du 160.000.000
Befehle(oder so ähnlich).
So oder so, hast du aber 20ms verplempert. Eine schnellere CPU ändert
nichts an der Zeit, und löst somit dein Problem nicht.
Siegerehrung beim BOTTLENECK-Wettbewerb.
Abgeschlagen und völlig chancenlos auf dem letzten Rang:
digitalRead() mit 0 ms bei 100 Aufrufen
Zweiter und dennoch auch völlig chancenlos abgeschlagen:
Servo.write() mit 4 ms bei 100 Aufrufen.
Der absolute Champ, der die Konkurrenz in Grund und Boden gestampft hat:
pulseIn()
MIT SAGE UND SCHREIBE 69280 ms bei 100 Aufrufen.
Messanordnung: Alle Pins waren physisch belegt, das ist keine Messung an
leeren Pins. Für den Sensor war ein NPN Sensor angeschlossen und aktiv,
für den Sender eine Fernsteuerung mit Empfänger und für den Regler ein
echter Fahrtregler.
Jetzt sagt Sherlock Holmes zu Dr. Watson:
Wir haben es hier nur mit einem üblen Kerl zu tun, die beiden anderen
sind harmlos.
Aus dem, was ich jetzt durch die guten Tipps gelernt zu haben glaube,
schließe ich, alles kann so bleiben, nur die beiden Aufrufe von
pulseIn() müssen über Interrupt gesteuert werden.
Dafür würde sich die (programmiertechnisch) etwas einfachere Methode der
attached Interrupts auf Pin 2 und 3 anbieten, bzw. würde die reichen, da
die anderen Verdächtigen eben harmlos sind.
Jetzt müßte man nur noch außer dem Ereignis den PWM Wert des Signals
auslesen. Wenn man dafür millis() braucht mit start und stop, kann ich
nur sagen, der Aufruf der Funktion millis() ist auch zeitkritisch. Aber
wenn man es nur aufruft, wenn es wirklich Sache ist, natürlich sehr viel
weniger.
Das wär jetzt so der Plan.
Xenophon
Nachtrag:
Ich hab mir die PWM mal auf dem Oszi angeschaut. Signalwert ist die
Flankenbreite.
Bild1: Frequenz des Gesamtsignals
Bild2: Sender Knüppel auf Anschlag
Bild2: Sender Knüppel Gegenseite
Flankenbreite zwischen 1000 und 2000 Mikrosekunden, plus/minus
Überschüsse je nach Trimmhebel-Stellung. Beschriftung mit ms ist falsch,
es muß heißen Mikrosekungen.
Ich weiss nicht, wie genau du das Signal abtasten willst. Für normale
Modellbau Servos genügen meiner Erfahrung nach 100 Werte für den ganzen
Bereich (links bis rechts, feiner lassen sie sich ohnehin nicht
ansteuern).
Also reicht ein 8bit Timer. Den auszulesen kostet beinahe gar nichts -
nur einen Takt.
Holger S. schrieb:>> Mach mal digitalRead weg. Das bremst dich aus.>> Den Tipp, das wegzumachen, kann ich irgendwie nicht ernst nehmen.
Solltest du aber, wenn bei dir Prozessorleistung knapp ist.
> Machst du Scherze?
Hast du den Post Arduino Fanboy [1] nicht gelesen?
> Woher bekomme ich dann die Sensor-Signale?
Von den Ports natürlich. Hast du dir mal angesehen, was die
Digitalread()-Funktion vom Arduino alles veranstaltet und wieviel Zeit
das in Relation zu einem normalen Lesen vom Port dauert?
[1] Arduino F. schrieb:> Hier (m)eine Arduino Lib für schnelle Portzugriffe:
Stefan U. schrieb:> Ich weiss nicht, wie genau du das Signal abtasten willst. Für normale> Modellbau Servos genügen meiner Erfahrung nach 100 Werte für den ganzen> Bereich (links bis rechts, feiner lassen sie sich ohnehin nicht> ansteuern).>> Also reicht ein 8bit Timer. Den auszulesen kostet beinahe gar nichts -> nur einen Takt.
100 Werte wären mehr als ausreichend.
Ganz glücklich wäre ich, wenn du als erfahrener mP Progger mir nur mal
ein paar Beispielzeilen reinwerfen würdest, wie man den PWM-Wert des
Signals am besten abcheckt.
Wie ich das jetzt sehe, spricht der Interrupt wahlweise an auf HIGH oder
LOW, steigt dann bei Erreichen der Gegenflanke LOW bzw. bei HIGH wieder
aus und man müßte dafür eine Zeitmessung selbst machen, weil der
Interrupt das nicht zurückliefert.
Gruß Xenophon
Holger S. schrieb:> sender_periode.png> 1,99 MB>> sender_voll_rechts.png> 2,4 MB>> sender_voll_links.png> 2,21 MB
Hast du dich schon mal gefragt, was man wohl mit der USB-Buchse vorne
links am Oszi anfangen kann?
Ich möchte fast wetten, dass dem dem Gerät darüber rattenscharfe und
dazu auch noch handlich kleine PNG-Dateien zu entlocken sind und man
nicht gezwungen ist, unter Mißachtung sämtlicher Hinweise beim Upload,
Photos im dafür denkbar ungeeigneten PNG-Format zu posten.
Forist schrieb:> Holger S. schrieb:>> sender_periode.png>> 1,99 MB>>>> sender_voll_rechts.png>> 2,4 MB>>>> sender_voll_links.png>> 2,21 MB>> Hast du dich schon mal gefragt, was man wohl mit der USB-Buchse vorne> links am Oszi anfangen kann?>> Ich möchte fast wetten, dass dem dem Gerät darüber rattenscharfe und> dazu auch noch handlich kleine PNG-Dateien zu entlocken sind und man> nicht gezwungen ist, unter Mißachtung sämtlicher Hinweise beim Upload,> Photos im dafür denkbar ungeeigneten PNG-Format zu posten.
Mit den 2.x MB ist was falsch gelaufen. Das hab ich nicht gesehen.
Klar, daß man das auch kleiner liefern kann.
Ich werde mich bessern! ;)
Xenophon
Die AVR COntroller, die ich verwende können sowohl bei der steigenden
als auch bei der fallenden Flanke einen Interrupt auslösen.
Zum Erfassen der Pulsbreiten gibt es reichlich konkreten Anleitungen im
Netz
Ich brauchte 5 Sekunden, um diese Seite mit Google zu finden:
http://www.camelsoftware.com/2015/12/25/reading-pwm-signals-from-an-rc-receiver-with-arduino/
Lies das und probiere es aus.
was würde die Sache schneller machen ?
A: ein besseres Programm
B: unter Einbeziehung der Möglichkeiten der Hardware
C: die Wahl der passenden Hardware.
Hierzu hilft es einen Plan zu machen was wann wie aufgerufen werden
soll. Vom Timing schwierige Sachen lagert man auf die Hardware aus oder
sorgt dafür das sie eingehalten werden. Dazu braucht das Programm eine
Struktur und keinen zusammen gewurstelten Code.
Mit der Arduino Umgebung bist du schon mal schlecht beraten, da du kaum
Kenntnis davon hast was da im Hintergrund passiert.
Marco H. schrieb:> Mit der Arduino Umgebung bist du schon mal schlecht beraten, da du kaum> Kenntnis davon hast was da im Hintergrund passiert.
.....aber dafür ist es doch so schön einfach und schnell für die "Maker"
zusammenkloppbar. ;-)
Nach vielen gerede habe ich mir die Arduino IDE vor zwei Wochen mal
angeschaut, mit dem ehrlichen Willen, damit ein echtes kleines
Testprogramm zu schreiben.
Einen Tag später war ich wieder bei Netbeans.
Das Einzige, was mir an der Arduino IDE gefällt, ist der schnelle
Einstieg, vor allem beim ESP8266. Ansonsten sehe ich nur Nachteile.
Marco H. schrieb:> was würde die Sache schneller machen ?>> A: ein besseres Programm> B: unter Einbeziehung der Möglichkeiten der Hardware> C: die Wahl der passenden Hardware.>>> Hierzu hilft es einen Plan zu machen was wann wie aufgerufen werden> soll. Vom Timing schwierige Sachen lagert man auf die Hardware aus oder> sorgt dafür das sie eingehalten werden. Dazu braucht das Programm eine> Struktur und keinen zusammen gewurstelten Code.>> Mit der Arduino Umgebung bist du schon mal schlecht beraten, da du kaum> Kenntnis davon hast was da im Hintergrund passiert.
Hallo Marco,
ich besitze seit dem 11.4.2017 einen Arduino, gekauft bei ama__z0n
Zuvor hab ich noch niemals einen mC in der Hand gehabt oder mich damit
beschäftigt oder wußte überhaupt, daß man sowas selbst programmieren
kann.
Wir haben heute den 26.4.
Ich brauche nur eine Motorsteuerung für mein Modellboot und wollte nicht
professioneller mC Programmierer werden.
Xenophon
Marco H. schrieb:> Mit der Arduino Umgebung bist du schon mal schlecht beraten
Kann man so nicht sagen, zum Einstieg ist es schon brauchbar.
Allerdings muß man berücksichtigen, daß die Arduino-Community eben kein
professioneller Programmieranbieter ist, sondern viele Libs als Hobby
entstehen. Daher kann man daran keine hohen Anforderungen stellen und
sie können auch leicht viele Ressourcen verbrauchen.
Aber man kann es als Grundgerüst benutzen und kritische Funktionen
anhand des Datenblattes besser implementieren. Oft findet man in der
Community auch schon Beispiele dafür.
Auch muß man trotzdem erstmal das strukturierte Programmieren lernen,
das nimmt einem auch kein anderes Tool ab. Ich hab auch mit den
schlimmsten Spaghetticodemonstern angefangen, die ich nach einem Monat
selber nicht mehr verstanden habe.
Ich hab die Steuerung jetzt fertig. Die Motoren treiben auf jeder Seite
3 Riemen an, mit denen sich das Schiff fortbewegt. Wenn die nicht
synchron sind, schaukelt es elend hin und her. Mit dem Sender kann man
das nicht koordinieren, daher mußte eine elektronische Regelung her.
Wahl auf Arduino fiel, weil bei Ama__?zon "Bestseller". Millionen
Fliegen können sich nicht irren. Oder?
https://www.youtube.com/watch?v=pRCdyDwQ8kY
Die pulseIn() Funktion hab ich in eine 30000er Zählschleife gepackt, die
greift ca. 5x/Sekunde zu, kann keinen Schaden anrichten. Damit werden
die Signale des Fernsteuerungs-Senders ausgelesen.
Die induktiven Näherungssensoren (NPN) werden mit einer Zählschleife von
500 ausgelesen, macht ca. einige hundert Zugriffe /sec., reicht auch.
Das Programm überschlägt keinen Durchlauf.
Der Arduino läuft mit einer einfachen Zählschleife mit 360 kHz
(=Programmdurchläufe/Sek.).
Mit dem Programm bringt er ca. 100 kHz.
Also mein Projekt wäre soweit in Version 1.0 eigentlich fertig.
Trotzdem danke ich für die vielen Anregungen, man wird sich fortbilden
müssen, um das Phänomen mP besser zu verstehen.
Xenophon
Mal ehrlich das kann nie funktionieren. Wenn du keine Ahnung hast vom µP
warum löst du das nicht Analog ? Hierzu sollte es auch fertige Regler
geben.
Du musst nicht nur den µP verstehen sondern auch wie Reglungen arbeiten.
Des weiteren auch wie man sie Digital realisiert.
Die Aufgabe einen DC Motor synchron unter Belastung zu steuern ist für
einen Anfänger schon recht hoch gegriffen. Da sollte man auf fertige
Lösungen zurückgreifen.
Marco H. schrieb:> Mal ehrlich das kann nie funktionieren.
Ich will nicht bestreiten, je mehr man von der Sache versteht, umso
besser. Meine mC Laufbahn hat aber erst vor 3 Wochen begonnen.
Und daher ist die Frage nicht, wie man ein perfektes Programm schreibt,
sondern ob das Programm die gestellte Aufgabe lösen kann.
Und das kann es definitiv.
Die Steuerung wurde heute nochmal überarbeitet und funktioniert 1a. Im
Prinzip sind die Motoren schon aus dem Stand synchron.
Hier ist ein neues Video dazu von heute:
https://youtu.be/2Kb80-H4CDM
Wie ist das programmiert? Ohne Interrupts. Die wären wohl noch besser,
muß ich mich aber erst einarbeiten. Programmstruktur:
Zählschleife Sensoren
liest Sensoren aus digitalread()
Zählschleife Sender
liest Sendersignal pulseIn()
Zählschleife Regler
gibt Signal an den Fahrtregler Servo.write()
Die Zählschleifen machen bei 0 für einen einzigen Zugriff auf, dann wird
der Zähler hochgesetzt und muß neu runtergezählt werden. Dadurch kann
man die Zugriffe takten.
Werte bei ca. 110 kHz:
Sensoren 500/sec
Sender 5/sec
Regler 5/sec
Die Sensoren überprüfen nicht die Motoren, sondern die Antriebe. Daher
wäre es auch egal, wieviel Last auf die Mots kommt, oder ob der Antrieb
Schlupf hat. Oder ob man eine Seite mit einer längeren Kette fahren
will. Bleibt sich alles gleich.
Die gesamte Regelung findet mit 3 Programmzeilen statt, die hinter die
Abfrage des linken Sensors gelegt wurden. Es sind die drei Zeilen, die
hinter der Bedingung beide_voraus() stehen. Denn wenn nicht beide voraus
stehen, bleibt die Regelung inaktiv.
if (sensor_backbord==LOW) // NPN Sensor schaltet auf Masse
{
durchgang_backbord=millis(); // höchster Zeitwert
vorlauf=durchgang_backbord-durchgang_steuerbord;
if (vorlauf>umlaufzeit)vorlauf=umlaufzeit;
// Falls eine Messung durchrutscht
1
if(beide_voraus()==TRUE)// Sendersignal beide voraus
Halbe Umlaufzeit: der andere Antrieb läuft die halbe Umlaufzeit weg,
danach kommt er ja aber wieder zurück. In der ersten Hälfte muß er
stoppen, läuft er zurück, muß der andere Motor stoppen.
Also, es funktioniert prima. Was mich nicht daran hindern wird, mich
weiter mit der mC Programmierung zu beschäftigen. Als nächstes wären mal
die Interrupts dran.
Xenophon
Jeder noch so kleine Arduino reicht auf jeden Fall aus, um mehrere
Motoren zu regeln. Jetzt kristallisiert sich deutlich heraus, dass dein
Problem defintiv nicht zu schwache Hardware ist, sondern an der Software
liegt.
> Millionen Fliegen können sich nicht irren. Oder?
Genau. Schau Dir mal an, was Leute mit einem Asuro so alles anstellen.
Der wird gerne verwendet, um genau das, was du brauchst, zu erlernen.
Das funktioniert trotzdem nicht. Da du die Belastung der Motoren nie mit
so geringen feedback regeln kannst. In der Praxis ist die Belastung
unkalkulierbar. Dein Gefährt fährt sonst wo hin, nur nicht da hin wo es
soll.
Selbst wenn die Motoren wirklich synchron sind, funktioniert das auch
nicht ohne die Position des Bootes mit in die Reglung einzubeziehen.
Das Steuern ist auch viel zu grob um Abweichungen zu korrigieren, das
gelingt auch nicht aus der Ferne.
Verstehe der Impuls für einen Umlauf ist viel zu grob im Verhältnis des
Fehlers der sich aus den Schleifen ergibt. So das eine Reglung auf diese
Art nicht möglich ist. Immer dann wenn sich in deine Schleife eine
Bedingung ändert, ändert sich auch das Zeitverhalten.
Vergleich das Problem mit einen quadcopter dessen Reglung ist ähnlich
komplex. Das erfordert eine ganze Menge wissen damit dieses Ding so
fliegt.
Holger S. schrieb:> Also, es funktioniert prima. Was mich nicht daran hindern wird, mich> weiter mit der mC Programmierung zu beschäftigen.
Finde ich gut dass du dich da durchgebissen hast und es so läuft wie du
es dir vorstellst.
Helmut H. schrieb:> Holger S. schrieb:>> Also, es funktioniert prima. Was mich nicht daran hindern wird, mich>> weiter mit der mC Programmierung zu beschäftigen.>> Finde ich gut dass du dich da durchgebissen hast und es so läuft wie du> es dir vorstellst.
Vielen Dank Helmut! Ich bin hier so niedergeknüppelt worden, da zählt
das doppelt! ;)
Aaaaaaaaaaaaaaaaaaaaaaaaaber:
Ich merk mir natürlich auch Kritik und arbeite dran. Daher habe ich
jetzt das Programm modifiziert.
Die pulseIn() sind raus, statt dessen attachedInterrupt
Es geht ja darum, die Flankenbreite von 2 PWM SIgnalen zu bestimmen. Das
sieht jetzt so aus:
1
volatileintsender_backbord=0;
2
volatileintsender_steuerbord=0;
3
volatileintprev_time1=0;
4
volatileintprev_time2=0;
5
6
attachInterrupt(0,steigend1,RISING);
7
attachInterrupt(1,steigend2,RISING);
8
9
voidsteigend1(){
10
attachInterrupt(0,fallend1,FALLING);
11
prev_time1=micros();
12
}
13
voidfallend1(){
14
attachInterrupt(0,steigend1,RISING);
15
sender_backbord=micros()-prev_time1;
16
}
17
voidsteigend2(){
18
attachInterrupt(1,fallend2,FALLING);
19
prev_time2=micros();
20
}
21
voidfallend2(){
22
attachInterrupt(1,steigend2,RISING);
23
sender_steuerbord=micros()-prev_time2;
24
}
Was ist nun der Effekt von der Sache?
Gemessen mit pulseIn() macht das Programm 110000 Programmdurchläufe/sec,
ich sage dazu 110 kHz
pulseIn gegen die Interrupts ausgetauscht, beträgt die Frequenz 146 kHz.
Das ist ungefähr 40% schneller. NIcht sehr viel schneller.
Das zeigt, daß die ursprüngliche Programmierung, das pulseIn() in eine
Zählschleife einzusperren, nicht soooooooo schlecht war.
Wir haben mit den Interrupts zwar jetzt das Signal alle 20 ms neu, und
wenn man eine zeitkritische Steuerung hätte, wäre das prima.
Allerdings um die Bootsmotoren zu steuern, reichen mir 5
Aktualisierungen pro sec. locker aus. Viel mehr kann man am Sender auch
gar nicht anstellen. Wenn man allerdings einen Heli steuern müßte, wären
die Interrupts Pflicht.
Was weitere Interrupt maximal bringen könnten, kann man messen.
Man klammert die fraglichen Funktionen einfach aus.
Dann läuft das Programm um soviel schneller, als dem Zeitaufwand durch
diese Funktionen entspricht.
So kann ich also sagen, wenn ich die Sensoren (digitalread())auch noch
mit Interrupts auslesen würde, daß dann die Performance von 146 auf 207
kHz steigen würde. Das wär fast doppelt so schnell wie ganz ohne
Interrupts, und man wüßte genau, daß keine Messung "durchflutscht".
Problem jetzt aber: attachedInterrupt() hat nur die Pins 2+3, und die
sind bereits vergeben.
Also weiter zu PinChangeInterrupts. Die sollen aber nicht so schnell
sein wie Attached.
Kann man beide Methoden parallel verwenden?
Xenophon
Holger S. schrieb:> Gemessen mit pulseIn() macht das Programm 110000 Programmdurchläufe/sec,
Das sagt nicht viel, da das Ausmessen eines Pulse wie oben gezeigt über
20 ms dauern kann.
Bei der Interrupt Lösung kostet das praktisch nichts. in sender_backbord
oder _steuerbord steht immer der zuletzt gemessene Wert.
Wenn ich es richtig verstehe werden die Sensoren für die Lage der Riemen
nur etwa alle zwei Sekunden angesprochen, Es bringt also nichts jetzt
noch Digital-in zu beschleunigen. Eine ms-genaue Messung ist bei der
relativ langsamen Mechanik sowieso nicht erforderlich.
Würde mal einen Ablauf skizzieren
* die Regelung greift nur bei Voller Fahrt Voraus und wird sofort
abgeschaltet wenn dies nicht mehr der Fall ist.
* der Stellwert für die Motoren wird für einen Pull eingestellt.
Dazwischen bringt eine Änderung nichts, da der aktuelle Wert der
Riemenstellung nicht bekannt ist.
* Also Synchronisieren, d.h. die vorlaufende Seite wird angehalten bis
das Signal der anderen Seite erkannt wurde
Beide Motore volle Fahrt voraus
Wenn ein Sensor anspricht, den entsprechenden Motor anhalten
Wenn dann der andere Sensor anspricht, beide Motoren volle Fahrt voraus
stellen
* Jetzt etwas Zeit totschlagen, damit die Sensoren sich wieder beruhigen
Das kann man via State-Machine oder mit Zustandsvariablen lösen.
Regelung
Motoren links(backbord) und rechts(steuerbord) auf volle Fahrt.
links_erkannt=FALSE
rechts_erkannt=FALSE
starte_pull=FALSE
Schleife:
Prüfe sender_*, ggf Regelung beenden
// Beginn Sync
Wenn starte_pull==FALSE:
Wenn linker Sensor LOW:
Wenn rechts_erkannt==TRUE:
starte_pull=TRUE
Sonst:
links_erkannt=TRUE
Motor links Halt
Wenn rechter Sensor LOW:
Wenn links_erkannt==TRUE:
starte_pull=TRUE
Sonst:
rechts_erkannt=TRUE
Motor rechts Halt
Wenn starte_pull==TRUE: // hier wird ein Pull gestartet
Endezeit = aktuelle Zeit + z.B. 0.5 sec
beide Motoren volle Fahrt voraus
// Ende Sync
// Zeit nach Sync
Wenn starte_pull==TRUE
Wenn aktuelle Zeit > Endezeit:
starte_pull=FALSE
links_erkannt=FALSE
rechts_erkannt=FALSE
Helmut H. schrieb:> Wenn ich es richtig verstehe werden die Sensoren für die Lage der Riemen> nur etwa alle zwei Sekunden angesprochen, Es bringt also nichts jetzt> noch Digital-in zu beschleunigen.
Wie wahr, wie wahr.
Zunächst: um den Durchgang innerhalb dieser 2 Sekunden zu erwischen, muß
man ca. 500mal/sec. die Sensoren an der Kette abfragen, weil die Kette
mit ca. 250 mm/sec durchläuft.
Ich habe neben dem attachtedInterrupt() zur Messung der PWM-Signale des
Senders nun noch einen PinModeChangeInterrupt für 2 Pins dazugenommen,
um die Sensoren an der Kette einzulesen.
Darf man beide Interrupt-Methoden nebeneinander verwenden? Weiß ich
nicht. Jedenfalls, es funktioniert, die Werte stimmen. Für den Durchgang
der Sensoren liefert er Mikrosekunden zurück.
Für die Performance bringt das aber gar nichts. Mit digitalRead alle
1/500 sec. macht das PRogramm 146 kHz, mit den zusätzlichen Interrupts
für die Sensoren sind 152 KHz.
Wenn die Interrupts nichts kosten, müßte er (= der Chip) eigentlich ca.
50 kHz schneller sein. Das ist die Differenz, wenn man im alten Programm
die Sensoren komplett rausnimmt. Ist er aber nicht.
Während die ersten beiden Interrupts als Ersatz für pulseIn() ca. 45 kHz
gebracht haben.
Jedenfalls, so bringt es nichts. Entweder hab ich falsch programmiert,
oder die beiden Interrupt-Methoden nebeneinander behindern sich
irgendwie, oder es bringt eben nichts (werde es wohl wieder
herausnehmen). Hier ist der Code für die beiden zusätzlichen Interrupts:
Holger S. schrieb:> Zunächst: um den Durchgang innerhalb dieser 2 Sekunden zu erwischen, muß> man ca. 500mal/sec. die Sensoren an der Kette abfragen, weil die Kette> mit ca. 250 mm/sec durchläuft.
Ist ja kein Problem, das schafft die oben skizzierte Regelung mit
digitalRead() locker.
Die Sensoren sind wahrscheinlich auch länger als 2 ms LOW wenn die Kette
vorbeiläuft. Vielleicht kannst du das Signal mal auf dem Scope
anschauen, ich befürchte es prellt, dann würden die Interrupts mehrfach
aufgerufen.
NB: Wenn Du den Zeitpunkt eines Durchlaufs speichern willst, merke dir
oben die micros();, z.B.
Wenn linker Sensor LOW:
...
Sonst:
links_erkannt=TRUE
durchgang_backbord = aktuelle Zeit
Motor links Halt
Natürlich kostet die Interruptverarbeitung auch Zeit, aber imho deutlich
weniger als 1 ms und das hängt nicht von der Länge und Lage des zu
messenden Signals ab. Zudem werden während des PulseIns() eventuell
einkommende Sensorsignale nicht erkannt.
Holger S. schrieb:> Darf man beide Interrupt-Methoden nebeneinander verwenden?
Natürlich. Nur für den selben Pin wäre es quatsch.
Beim Pin-Change muß man aber selber die Flanke ermitteln mit einer
Schattenvariable für den vorherigen Wert bzw. bei mehreren Pins je
Interrupt auch noch den Pin.
Ich benutze keine Arduinos, kann also nicht einschätzen, was genau Dein
Code macht.
Als ich 1997 mit AVRs angefangen habe, gabs lange noch keine Arduinos.
Die alten Hasen kennen daher die Arduino-Libs nicht, sie machen alles
bare-metal direkt nach Datenblatt. In der Registerbeschreibung steht ja
kurz und knackig zusammengefaßt die Bedeutung jedes Bits.
Ich bin mir auch nicht sicher, ob die Doku zu den Arduino-Libs umfassend
genug ist, bzw. ob man sie überhaupt versteht, ohne im Datenblatt
gelesen zu haben.
Die Doku von Arduino ist .... knapp. Viele Details erfährt man nur durch
Ausprobieren oder Quelltext+Datenblatt lesen.
Deswegen halte ich auch nicht viel von ihnen.
Aber was die Arduino Jungs richtig gut hinbekommen haben, ist der
schnelle Einstieg - vor allem beim ESP8266 war es für mich hilfreich.
Klasse Projekt!!! Nach den Videos der Mechanik bin ich auf das Video
der Jungfernfahrt gespannt.
Ich hab mir auch mal ein "Böötchen" gebastelt und dort nahezu alles mit
nem Atiny2313 gesteuert. Dein Ruderboot wurde es aber vermutlich
stehenlassen. Ich hab da bei der Motorisierung wohl ein wenig
übertrieben :D das gute Stück ist knapp 1m lang und mit 2mal 1.8kW
(BLDC)bestückt. Wenn ich den Hebel schlagartig aufn Tisch leg, springt
es komplett aus dem Wasser. Der Rumpf ist mir auch nicht wirklich gut
als Gleiter gelungen. Aber beeindruckend ist das schon und die Motörchen
brüllen ein infernalisches Duett. Evtl auch die Schrauben ich bin da
nich vom Fach.
So genuch gefaselt, sorry fürs OT, und immer ne Handbreit Wasser untern
Kiel
Helmut H. schrieb:> Die Sensoren sind wahrscheinlich auch länger als 2 ms LOW wenn die Kette> vorbeiläuft. Vielleicht kannst du das Signal mal auf dem Scope> anschauen, ich befürchte es prellt, dann würden die Interrupts mehrfach> aufgerufen.
Das Prellen würde erklären, warum da kein Zugewinn in der Performance
stattfindet.
Da werde ich mal nachschauen.
Andererseits sind die Interrupts mit PinModeChange ja softwaremäßig mit
Library, plus daß der Port intern nochmal feststellen muß, welcher Pin
ausgelöst hat,
zusammengefaßt wahrscheinlich um Längen langsamer als die hardwaremäßig
fest eingebauten AtttachInterrupts.
Xenophon
J. T. schrieb:> Klasse Projekt!!! Nach den Videos der Mechanik bin ich auf das Video> der Jungfernfahrt gespannt.>
Sie war schon im Wasser, aber ohne Synchronsteuerung.
Deshalb eiert sie mehr rum als daß sie rudert.
Mit der Fernsteuerung kriegt man es nicht hin.
So sieht es bis jetzt aus (ohne Synchro):
Video ---------------------------------------------------
https://www.youtube.com/watch?v=F4RVWzIqqHU&t=3s
/Video -----------------------------------------------------
Xenophon
Danke für den Link, hab es auch grad so entdeckt :D.
Hab auch noch ein 2tes gefunden wo es im Wasser ist. Da stand ein Text
von wegen "jetzt 2,5kg leichter".
Rein intuitiv hät ich gedacht, um so schwerer, um so weniger anfällig
müsste es für das "rumgeeiere" sein. Was war da dein Gefühl? War es nach
der Diät schlimmer oder besser?
Nebenbei bemerkt eiert es viieeel weniger als ich gedacht hätte. Ich
hatte als lütter Steppke mal son Plastikboot mit Aufziehmotor, das hatte
einen starren von Haus aus also synchronisierten "2-Ruder-Antrieb". Das
war nur am Eiern. Da hat es gelangt wenn die Paddel aufgrund minimaler
Wellen in der Badewanne nicht exakt gleichtief eingestochen haben, um
das Ding gefühlt auf der Stelle drehen zu lassen.
Hast du den Rumpf auch selbst gebaut oder ist das was fertiges? Wenn da
noch ein genauso schöner Aufbau draufkommt, echt top. Oder wolltest du
deine schöne Rudermechanik offenlaufen lassen, so dass man sie auch im
Betrieb bewundern kann? :D
MfG Chaos
P.S.
Lässt sich an der Mechanik eigentlich einstellen, wie weit die Ruder
auschlagen? Also dass die "Endrollen" quasi verschiebbar sind? Oder wär
dass ganze dann zu aufwändig geworden? (Kettenspanner usw?)
@chaoskind
Womit wir hier jetzt ganz vom Thema ab wären, aber was soll´s, ist ja
Hobby.
Die nackte Rumpfschale ist aus ABS, den hab ich als Ersatzteil gekauft.
Alles andere ist Eigenbau.
Selbstverständlich, wenn das Schiff fertig ist, ist von der
Rudermechanik nichts mehr zu sehen. Da kommen geschlossene Decks drauf.
Außerdem soll es ja ein Segelschiff werden, es kommt auch noch ein Rigg
drauf. Das wär auch alles schon erledigt, wenn ich nicht so lange bei
den Ruderantrieben hängen geblieben wäre.
Rudermechanik: Der innere Hebel ist begrenzt durch den Abstand
Antrieb->Bordwand. Den kann man nicht vergrößern.
Die Bahn, welche die Ruder beschreiben, entspricht in Länge und Umfang
dem Kettentrieb. Man kann die Kette in der Länge ändern (Abstand der
Zahnräder) oder den Radius des Mitnehmers bezogen auf die Mitte der
Zahnräder. Im Video ist die Höhe zu knapp, der Mitnehmer wurde daher im
Radius vergrößert, also mehr nach außen gesetzt. Er sitzt jetzt Höhe
Kette.
Zum Gewicht:
Alles Gewicht muß so weit wie möglich Mitte und Unten sitzen. Da braucht
es Ballast. Daher hat es einen 2 kg schweren Kiel aus VA-Stahl. Das
Gewicht oberhalb und seitlich verschlechtert die Stabilität. Mit den 11
kg vorher war das Schiff überladen und träge. Es wäre, mit Segel drauf,
bei der ersten Böe direkt abgesoffen. ;)
Daher wurden die (schweren) Zahriemenantriebe getauscht gegen
Kettenantriebe, die ca. 1,5 kg leichter sind, sowie sonstwie noch 1 kg
eingespart. Das kennt man vom Modellfliegen, Kampf um jedes Gramm, aber
beim Schiff gilt das dann irgendwann auch.
Insgesamt bin ich kein Freund von ABS oder GFK. Wenn das alles so fertig
ist, daß es läuft, werd ich das Ganze nochmal komplett mit einem
Holzrumpf aufbauen.
Der ABS Rumpf dient jetzt nur als Arbeitsplattform.
-------------------------------------------------------------
Nun zu der Synchronsteuerung:
Nach der Hereinnahme der Interrupts lief die Regelung instabil. Das
Programm machte sogar öfter mal den Totalabsturz, und das bei laufenden
Motoren. Man stelle sich das mal im realen Betrieb vor!
Ich hab das jetzt alles nochmal neu programmiert und ganz ohne
Interrupts. Die brauche ich nicht, weil:
Sendersignal abfragen alle 0,2 Sekunden = nicht zeitkritisch
Reglersignal geben alle 0,2 Sekunden = nicht zeitkritisch
Sensor abfragen 500x pro Sek. = nicht zeitkritisch
Ich brauch keine Signale, die alle 20 ms oder jede ms aktualisiert
werden, wenn ich nur alle 200 ms drauf zugreife.
Dazu kommt, daß der Sensor prellt. Der Durchgang des Mitnehmers am
Sensor dauert ca. 32 ms. In der Zeit greift das Programm mit Interrupts
einen Haufen Prellsignale ab. Die müßte man dann softwaremäßig praktisch
in eine Warteschleife packen oder sonderbehandeln, ich will jetzt nicht
sagen delay(), aber z. B. Filtern, um den unerwünschten Speed wieder
herauszukriegen. ALso man muß die schnellen Signale wieder langsam
machen, das macht nicht wirklich Sinn.
Natürlich ist es ohne Interrupts möglich, daß mal ein Sensordurchgang
nicht erfaßt wird. Das bemerkt man, wenn der Vorlauf der Antriebe größer
wird als die Umlaufzeit. Ist aber kein Problem:
if (vorlauf<=umlaufzeit&&vorlauf>0) // bei Meßfehler nichts machen
{
dann mach was, nämlich regeln
}
Ob die Instabilität letztlich von den Interrupts kam, weiß ich nicht.
Ich weiß nur, jetzt ist sie weg.
Das Programm macht jetzt 100 kHZ mit den Parametern:
500 Zugriffe/sec. auf die Sensoren
5 Zugriffe/sec. auf Sender und Reglersignale.
Die Steuerung der Zugriffe erfolgt mit Zählschleifen, die einmal
aufmachen und dann wieder neu herunterzählen.
Man könnte die Schleifen natürlich auch mit millis() takten, der Aufruf
von millis() ist aber keine gute Idee, weil der die Performance nach
unten drückt, aber kräftig. Es fast so schlimm wie pulseIn().
Das Programm funktioniert jetzt absolut fehlerfrei, keine
Programmabstürze mehr.
Auf dem Arduino Nano. Der ist ja kein Rennpferd.
Mehr braucht es jetzt nicht, um das Problem zu lösen.
Xenophon
Wenn man bedenkt, dass Du am Anfang einen Arduino 101 mit 32Mhz nehmen
wolltest und jetzt das Ganze doch mit einem 16Mhz Arduino läuft ...
Meiner Erfahrung nach braucht man für mechanische Regelungen sowieso
keine hohen Abtastraten. Meistens reicht eine Zykluszeit von 10ms aus.
Holger S. schrieb:> Das> Programm machte sogar öfter mal den Totalabsturz, und das bei laufenden> Motoren. Man stelle sich das mal im realen Betrieb vor!
Da kann ich auch ne kleine Anekdote erzählen. Bei meinem ersten Boot, da
hatte ich versucht, nen Fahrtregler selbst zu bauen, lief im trockenen
alles wunderbar. Also ab aufn See. Langsam losgetuckert, dann knapp in
der Mitte mal Vollgas gegeben. Abgestürzt. Zum Glück lag der See luv von
mir :D. Nach ca ner halben Stunde kam es dann wieder angetrieben... Naja
letzendlich hab ich eingesehen, dass ich es scheinbar nicht hinbekomme,
den Motor so zu entstören, dass er bei Volllast nicht alles zudreckt,
oder meinen Fahrtregler unempfindlicher zu bekommen, als das gute Stück
mit Vollgas ins Ufer raste, auf nix reagierte, und der Motor dann in
Flammen stand, als ich letzendlich am Boot ankam. :D Da hab ich dann
doch auf nen fertigen Fahrtregler zurückgegriffen, muss ich eingestehen.
Holger S. schrieb:> Das Programm funktioniert jetzt absolut fehlerfrei, keine> Programmabstürze mehr.
Ja dann herzlichen Glückwunsch zu deinen rasanten
Programmierfortschritten!!
Und wo is nun läuft, ist ja wirklich nicht so dramatisch, wenn wir ein
wenig OT geworden sind ;)
Und ein Holzrumpf wäre definitiv Stilechter, da haste meine volle
Unterstützung und Fürsprache :D ich bin auch kein Freund von ABS und Co.
Meine sind alle aus Blech handgeformt. Schweinearbeit, und irgendwie
auch gar nicht so einfach, das hinzubekommen, was man sich vorgestellt
hat.
Ich würd mich freuen, wenn du hier weiter über den Verlauf von dem
Projekt berichtest! Und dank dir, für die Zusammenfassung.
Frohes Basteln,
Chaos
Ist meinem Vater schonmal mit einem Nitro R/C Auto passiert. Das knallte
mit Vollgas am Ende von zwei Feldern gegen einen Bauernhof und brannte
dort aus. Leider war das Spektakel so weit weg, dass niemand zuschauen
konnte - außer der Bauer.