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.
:
Bearbeitet durch User
Holger S. schrieb: > Ich weiß aber, was bremst. Es sind analogRead(), pulseIn() und > Servo.write. delay (1000) bremst auch.
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:
1 | void loop() |
2 | {
|
3 | if (zaehler_sensoren==0) |
4 | {
|
5 | |
6 | if (digitalRead(pin_sensor1)==LOW) sensordurchgang1=millis(); |
7 | if (digitalRead(pin_sensor2)==LOW) sensordurchgang2=millis(); |
8 | if (sensordurchgang1>sensordurchgang2)vorlauf=sensordurchgang1-sensordurchgang2; else vorlauf=0; |
9 | zsensor++; //zaehlt anzahl Zugriffe |
10 | zaehler_sensoren=TAKT_SENSOREN; |
11 | }
|
12 | else zaehler_sensoren --; |
13 | |
14 | if (zaehler_sender==0) |
15 | {
|
16 | kanal1=pulseIn(pin_kanal1,HIGH); |
17 | kanal2=pulseIn(pin_kanal2,HIGH); |
18 | zkanal++; |
19 | zaehler_sender=TAKT_SENDER; |
20 | }
|
21 | else zaehler_sender --; |
22 | if (zaehler_steuerung==0) |
23 | {
|
24 | |
25 | regler_1.write(90); |
26 | regler_2.write(90); |
27 | zsteuerung++; |
28 | |
29 | |
30 | zaehler_steuerung=TAKT_STEUERUNG; |
31 | }
|
32 | else zaehler_steuerung --; |
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.
:
Bearbeitet durch User
Ich hab mal den Code etwas formatiert (fuer den geneigten Leser), das aber nur nebenbei:
1 | void loop() |
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...
Kaj schrieb: > Wenn du also den Quarz > austauscht... ... wird sein Bootloader nicht mehr funktionieren !
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.
:
Bearbeitet durch User
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.
:
Bearbeitet durch User
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: > Mach mal digitalRead weg. Das bremst dich aus. Hier (m)eine Arduino Lib für schnelle Portzugriffe: Beitrag "Welche AVR besitzen die PIN Toggle Fähigkeit?"
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?
Das PulseIn dauert auch mit einem 40 EUR Quark-Mikrocontroller worst case 20+x ms https://www.mikrocontroller.net/articles/Modellbauservo_Ansteuerung#Signalaufbau 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/
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
:
Bearbeitet durch User
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
:
Bearbeitet durch User
@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
:
Bearbeitet durch User
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 | void loop() |
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.
:
Bearbeitet durch User
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
:
Bearbeitet durch User
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
:
Bearbeitet durch User
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
:
Bearbeitet durch User
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 |
2 | {
|
3 | if(vorlauf>TOLERANZ&&vorlauf<(umlaufzeit-TOLERANZ)) |
4 | {
|
5 | if (vorlauf<halbe_umlaufzeit) |
6 | bremse_steuerbord((vorlauf)); |
7 | else bremse_backbord(((umlaufzeit-vorlauf)) ); |
8 | }
|
9 | }
|
10 | |
11 | }
|
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
:
Bearbeitet durch User
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 | volatile int sender_backbord=0; |
2 | volatile int sender_steuerbord=0; |
3 | volatile int prev_time1=0; |
4 | volatile int prev_time2=0; |
5 | |
6 | attachInterrupt(0,steigend1,RISING); |
7 | attachInterrupt(1,steigend2,RISING); |
8 | |
9 | void steigend1(){ |
10 | attachInterrupt(0,fallend1,FALLING); |
11 | prev_time1=micros(); |
12 | }
|
13 | void fallend1(){ |
14 | attachInterrupt(0,steigend1,RISING); |
15 | sender_backbord=micros()-prev_time1; |
16 | }
|
17 | void steigend2(){ |
18 | attachInterrupt(1,fallend2,FALLING); |
19 | prev_time2=micros(); |
20 | }
|
21 | void fallend2(){ |
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
:
Bearbeitet durch User
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:
1 | #define PIN_SENSOR_BACKBORD 7
|
2 | #define PIN_SENSOR_STEUERBORD 8
|
3 | |
4 | |
5 | volatile unsigned long durchgang_backbord=0; |
6 | volatile int sensor_backbord=0; |
7 | volatile unsigned long durchgang_steuerbord=0; |
8 | volatile int sensor_steuerbord=0; |
9 | |
10 | uint8_t latest_interrupted_pin; |
11 | |
12 | void setup() |
13 | {
|
14 | |
15 | // .............. Auszug:
|
16 | |
17 | |
18 | pinMode(PIN_SENSOR_BACKBORD,INPUT_PULLUP); |
19 | PCintPort::attachInterrupt(PIN_SENSOR_BACKBORD,&sensor_bb_fallend,FALLING); |
20 | pinMode(PIN_SENSOR_STEUERBORD,INPUT_PULLUP); |
21 | PCintPort::attachInterrupt(PIN_SENSOR_STEUERBORD,&sensor_stb_fallend,FALLING); |
22 | }
|
23 | |
24 | |
25 | void sensor_bb_fallend() { |
26 | latest_interrupted_pin=PCintPort::arduinoPin; |
27 | durchgang_backbord = micros(); |
28 | }
|
29 | void sensor_stb_fallend() { |
30 | latest_interrupted_pin=PCintPort::arduinoPin; |
31 | durchgang_steuerbord = micros(); |
32 | }
|
Gruß Xenophon
:
Bearbeitet durch User
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.
:
Bearbeitet durch User
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
:
Bearbeitet durch User
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
:
Bearbeitet durch User
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
:
Bearbeitet durch User
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.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.