Hallo geehrte Experten, für mein nächstes Hobby-Projekt bin ich auf das o. g. Board umgestiegen und habe zur Einarbeitung mein letztes Projekt angepasst. Nachdem mir Nemopuk zielsicher die Lösung eines Problem der Datenübertragung genannt hat, stellten sich nach und nach weitere Besonderheiten des Uno R4 heraus, über welche zum Großteil auch andere Benutzer im Netz berichten: 1. Speicherbedarf: Ein Programm welches auf dem Mega 52kB gross ist, benötigt auf dem R4 mehr als den doppelten Speicher. Abhilfe: keine bekannt 2. Compilier-Dauer: Das Compilieren dauert beim R4 mit ca. 30s deutlich länger als beim Mega mit ca. 11s. Abhilfe: keine bekannt 3. random(): Diese Funktion arbeitet beim R4 extrem langsam, da die Routine bei jedem Aufruf den True Random Number Generator (TRNG) neu initialisiert. Abhilfe: Wert einmal pro Sekunde abfragen und in einem Ringpuffer speichern. Den Wert aus dem Ringpuffer abfragen. 4. tone: Diese Funktion scheint beim R4 nicht zum Abspielen von Melodien geeignet zu sein - es treten diverse störende Effekte auf. Abhilfe: Verwendung einer alternativen Bibliothek (z. B. TimerFreeTone) 5. EEPROM: um exakt zu sein, gibt es beim R4 kein EEPROM, dieses wird im Flash simuliert - bei jedem Schreiben muss die gesamte Page gelöscht werden. Abhilfe: Verwendung eines externen EEPROM 6. Datenübertragung: Einbrechen der Übertragungsgeschwindigkeit bei längeren Übertragungen. Abhilfe: keine bekannt Sind euch Abhilfen zu den genannten Besonderheiten bekannt? Viele Grüße Kai
:
Bearbeitet durch User
Kai schrieb: > Speicherbedarf: Ein Programm welches auf dem Mega 52kB gross ist, > benötigt auf dem R4 mehr als den doppelten Speicher. > Abhilfe: keine bekannt Das ist allerdings kein Fehler, sondern der 32 Bit ARM Architektur geschuldet.
Hallo Nemompuk vielen Dank für deine Antwort, hatte ich bereits vermutet - deshalb habe ich auch Besonderheit geschrieben. Wenn aber jemand mit einem grösseren Projekt vom Mega auf den Uno R4 umziehen möchte, wird er Schiffbruch erleiden... Weitere Besonderheiten: 6. LED-Matrix: recht dunkel, wird diese mit matrix.play(true) gestartet kommt es zu zyklischer Laufzeiterhöhung (was zu erwarten war) Abhilfe: für Helligkeit keine bekannt, Matrix.next an geeigneter Stelle einsetzen. 7. Interrupts: einige Funktionen werden vermutlich durch unerwartete Interrupts beeinflusst. Abhilfe: keine bekannt Viele Grüße Kai
:
Bearbeitet durch User
Meiner Meinung nach hätte dieses neue Board nicht "Uno" heissen sollen.
Nemopuk schrieb: > Meiner Meinung nach hätte dieses neue Board nicht "Uno" heissen > sollen. Offensichtlich scheint deine Meinung da nicht sonderlich relevant zu sein. So wie auch Nano nur die Bauform beschreibt und nicht den montierten µC, ist es auch mittlerweile auch beim UNO.
Kai schrieb: > Ein Programm welches auf dem Mega 52kB gross ist, > benötigt auf dem R4 mehr als den doppelten Speicher. Ist egal, du bekommst kein Geld zurück für ungenutzten Speicher. Passt das Programm rein? Dann ist alles gut. Kai schrieb: > Das Compilieren dauert beim R4 mit ca. 30s deutlich > länger als beim Mega mit ca. 11s. Da ist eine wesentlich fettere Architektur dahinter, von 8 auf 32 bit und natürlich ist ARM auch unheimlich aufgeblasen, so stark, das es nur mit C zu ertragen ist. In Assembler ein kurzes einfaches Blinkprogramm zum testen geht nicht, weil das nicht oder nur sehr umständlich dokumentiert ist wie man den Chip anspricht. Kai schrieb: > Diese Funktion arbeitet beim R4 extrem langsam, da die > Routine bei jedem Aufruf den True Random Number Generator (TRNG) neu > initialisiert. Dafür isses echter Zufall und kein PRNG. Eins willste, eins kriegste. Kai schrieb: > Diese Funktion scheint beim R4 nicht zum Abspielen von > Melodien geeignet zu sein - es treten diverse störende Effekte auf. Vollkommen andere Architektur der CPU, die solcherlei Hardwarenahen Krempel halt nicht erlaubt. Daher kann man C-Programme ja auch nie auf eine andere Hardware übertragen, obwohl das ja eins der Hauptargumente für C ist. Aber irgendwann nutzt man eben doch Hardwareeigenheiten, und dann kommt das dabei raus. Kai schrieb: > um exakt zu sein, gibt es beim R4 kein EEPROM, dieses wird > im Flash simuliert - bei jedem Schreiben muss die gesamte Page gelöscht > werden. Auch hier: Hardwarenaher Kram, der emuliert werden muss, das geht halt oder eben nicht. Kai schrieb: > Einbrechen der Übertragungsgeschwindigkeit bei > längeren Übertragungen. Das liegt nicht an der Firmware, niemals nicht... Kai schrieb: > Wenn aber jemand mit einem grösseren Projekt vom Mega auf den Uno R4 > umziehen möchte, wird er Schiffbruch erleiden... Wenn ein doppelt so großes Programm von 32kB auf 256kB nicht passt, stimmt was mit deinem Taschenrechner nicht. Kai schrieb: > recht dunkel Falsche Hardware für sowas. Du meckerst auch, weil deine Ape nur noch kriechen kann wenn da 7,5 Tonnen dranhängen. Kai schrieb: > einige Funktionen werden vermutlich durch > unerwartete Interrupts beeinflusst. Nochmal: Falsche Hardware. Du erwartest ernsthaft, das ein nicht mal im entferntesten ähnlicher Controller hardwarenah identisch funktioniert? Wie läuft den C64 mit Windows 11? Wo hast du das Userport-TPM und den USB3.2-1541-Adapter gekauft, und wie kann man im C64-Bios Secureboot aktivieren?
Jens M. schrieb: > von 32kB auf 256kB nicht passt, Der Arduino Mega hat 256k Flash.
:
Bearbeitet durch User
Oh stimmt ich hatte nach dem Uno R3 gekuckt. Das ist ja auch der "Vorvater" des Uno R4, nicht der Mega. Vielleicht muss man vom Mega (mit ATmega2560) auf einen ESP gehen, der hat 4MByte Flash. Und WLAN. Aber halt wenig RAM. Irgendwas ist ja immer.
Arduino F. schrieb: > Der Arduino Mega hat 256k Flash. Die nicht mal 1% der Anwender jemals ausgenutzt haben!
Kai schrieb: > Das Compilieren dauert beim R4 mit ca. 30s deutlich > länger als beim Mega mit ca. 11s. Damit nicht Äpfel mit Birnen verglichen werden: Für die gleiche GCC Version und die gleichen Optimierungseinstellungen? C++ Programme mit DWARF-3 Debug-Info sind teilweise riesig, und das kann Linken spürbar langsamer machen. Ändert sich was wenn mit -g0 übersetzt wird?
Kai schrieb: > Nachdem mir Nemopuk zielsicher die Lösung eines Problem der > Datenübertragung genannt hat, Wenn die Person hinter Nepomuk die ist, welche ich vermute, denn würde ich das Wort "zielsicher" nicht verwenden wollen ;-) > 1. Speicherbedarf: Ein Programm welches auf dem Mega 52kB gross ist, > benötigt auf dem R4 mehr als den doppelten Speicher. > Abhilfe: keine bekannt Ignorieren. Denn der R4 hat genügend Flash-Speicher (256k). Wie es scheint, beherrscht die CPU auch keinen Thumb Mode, welcher weniger Speicher braucht. > 2. Compilier-Dauer: Das Compilieren dauert beim R4 mit ca. 30s deutlich > länger als beim Mega mit ca. 11s. > Abhilfe: keine bekannt Ist halt so. Damit kann und muss man leben. > 3. random(): Diese Funktion arbeitet beim R4 extrem langsam, da die > Routine bei jedem Aufruf den True Random Number Generator (TRNG) neu > initialisiert. Glaub ich nicht. Wie hast du das gemessen? Was ist "extrem langsam"? > 5. EEPROM: um exakt zu sein, gibt es beim R4 kein EEPROM, dieses wird > im Flash simuliert - bei jedem Schreiben muss die gesamte Page gelöscht > werden. > Abhilfe: Verwendung eines externen EEPROM Oder Schreibzugriffe minimieren. https://www.mikrocontroller.net/articles/Speicher#EEPROM-Schreibzugriffe_minimieren > 6. Datenübertragung: Einbrechen der Übertragungsgeschwindigkeit bei > längeren Übertragungen. > Abhilfe: keine bekannt Unsinn! Ohne genauere Beschreibung der Übertragung und des Quellcodes kann man da rein GAR NICHTS sagen!
Jens M. schrieb: > auf einen ESP gehen, der > hat 4MByte Flash. Und WLAN. Aber halt wenig RAM. "Der" ESP kann auch mehr Flash-ROM haben, aber wie kommst Du auf "wenig" RAM? Welchen "ESP" meinst Du überhaupt? Es gibt viele Varianten, die alle unterschiedlich ausgestattet sind. Und obendrein kann da PSRAM angeschlossen werden, und ist es auf den besseren Modulen auch standardmäßig.
Johann L. schrieb: > Kai schrieb: >> Das Compilieren dauert beim R4 mit ca. 30s deutlich >> länger als beim Mega mit ca. 11s. > > Damit nicht Äpfel mit Birnen verglichen werden: Für die gleiche GCC > Version und die gleichen Optimierungseinstellungen? > > C++ Programme mit DWARF-3 Debug-Info sind teilweise riesig, und das kann > Linken spürbar langsamer machen. Ändert sich was wenn mit -g0 übersetzt > wird? Hallo Johann, klingt logisch aber wo kann ich diese Option in der Arduino-Ide einstellen? Vielen Dank und viele Grüße Kai
Falk B. schrieb: >> 3. random(): Diese Funktion arbeitet beim R4 extrem langsam, da die >> Routine bei jedem Aufruf den True Random Number Generator (TRNG) neu >> initialisiert. > > Glaub ich nicht. Wie hast du das gemessen? Was ist "extrem langsam"? Hallo Falk, ich habe die Zeit nicht exakt bestimmt - wahrscheinlich um 100ms pro Aufruf, jedoch ist dieses Problem bekannt: https://forum.arduino.cc/t/random-function-on-r4-terribly-slow/1342877 Wird random() einer Routine intensiv verwendet, scheint der Controller stehen zu bleiben. Viele Grüße Kai
Kai schrieb: > klingt logisch aber wo kann ich diese Option in der Arduino-Ide > einstellen? Du legst neben der vorhandenen, genutzten, platform.txt eine platform.local.txt. In dieser bringst du deine Änderungen unter.
Hallo Arduino F, vielen Dank für deine Antwort - versuche ich morgen. Viele Grüße Kai
Kai schrieb: > ich habe die Zeit nicht exakt bestimmt - wahrscheinlich um 100ms pro > Aufruf, jedoch ist dieses Problem bekannt: > https://forum.arduino.cc/t/random-function-on-r4-terribly-slow/1342877 > Wird random() einer Routine intensiv verwendet, scheint der Controller > stehen zu bleiben. Hier gibt es die Lösung. Lesen bildet. https://forum.arduino.cc/t/random-function-on-r4-terribly-slow/1342877/12?_gl=1*1mw7hsl*_up*MQ..*_ga*OTYxMTM3NzcxLjE3NTg3Mzg2MzM.*_ga_NEXN8H46L5*czE3NTg3Mzg2MjckbzEkZzEkdDE3NTg3Mzg5NjMkajYwJGwwJGg3MTk0MjU5MjM.
Falk B. schrieb: > Hier gibt es die Lösung. Lesen bildet. > > https://forum.arduino.cc/t/random-function-on-r4-terribly-slow/1342877/12?_gl=1*1mw7hsl*_up*MQ..*_ga*OTYxMTM3NzcxLjE3NTg3Mzg2MzM.*_ga_NEXN8H46L5*czE3NTg3Mzg2MjckbzEkZzEkdDE3NTg3Mzg5NjMkajYwJGwwJGg3MTk0MjU5MjM. Hallo Falk, Vielen Dank - super - funktioniert! Jens M. schrieb: > Vollkommen andere Architektur der CPU, die solcherlei Hardwarenahen > Krempel halt nicht erlaubt. Daher kann man C-Programme ja auch nie auf > eine andere Hardware übertragen, obwohl das ja eins der Hauptargumente > für C ist. Aber irgendwann nutzt man eben doch Hardwareeigenheiten, und > dann kommt das dabei raus. Hallo Jens, es geht um die Funktion tone(), welche kein hardwarenaher Krempel ist. Jens M. schrieb: > Du erwartest ernsthaft, das ein nicht mal im entferntesten ähnlicher > Controller hardwarenah identisch funktioniert? > Wie läuft den C64 mit Windows 11? Wo hast du das Userport-TPM und den > USB3.2-1541-Adapter gekauft, und wie kann man im C64-Bios Secureboot > aktivieren? Nein das erwarte ich gar nicht sondern frage hier, ob ihr Abhilfen zu den aufgetretenen Besonderheiten kennt. Jens M. schrieb: > Das liegt nicht an der Firmware, niemals nicht... Falk B. schrieb: >> 6. Datenübertragung: Einbrechen der Übertragungsgeschwindigkeit bei >> längeren Übertragungen. >> Abhilfe: keine bekannt > Unsinn! Ohne genauere Beschreibung der Übertragung und des Quellcodes > kann man da rein GAR NICHTS sagen! Hallo Jens und Falk, die Ursache dieses Problemes muss ich noch genauer analysieren - zurzeit ist es so, dass die Übertragung längerer Dateien an Mega und Uno R3 störungsfrei funktioniert und bei R4 nicht. Jetzt suche ich erstmal den richtigen Ordner für: Arduino F. schrieb: >> klingt logisch aber wo kann ich diese Option in der Arduino-Ide >> einstellen? > Du legst neben der vorhandenen, genutzten, platform.txt eine > platform.local.txt. > In dieser bringst du deine Änderungen unter. Vielen Dank für alle Antworten bisher! Viele Grüße Kai
Kai schrieb: > Jetzt suche ich erstmal den richtigen Ordner für: Zeigt Arduino dir wenn du die ausführlichen Ausgaben aktivierst.
Nemopuk schrieb: > Meiner Meinung nach hätte dieses neue Board nicht "Uno" heissen sollen. Geht es dir auch so dass sich quasi niemand für deine Meinung interessiert? Das ist bei mir sehr oft der Fall. Eigentlich durchgehend.
:
Bearbeitet durch User
Cyblord -. schrieb: > ... Du hast mein volles Mitgefühl! (hihi) Schaut euch einfach mal den VW Golf Revision 1 und Revision 7 an. Was haben die gemeinsam? Nicht viel! OK, die Räder sind weiterhin unten, und das Dach meist oben, aber sonst? Kein relevantes Teil passt. Nichts, außer vielleicht die ein oder andere M6er Schraube.
Arduino F. schrieb: > Kai schrieb: >> Jetzt suche ich erstmal den richtigen Ordner für: > > Zeigt Arduino dir wenn du die ausführlichen Ausgaben aktivierst. Hallo Arduino F, vielen Dank - das war dank deiner Hilfe sehr einfach - aber welche ist die richtige Stelle? Viele Grüße Kai
Kai schrieb: > aber welche ist > die richtige Stelle? Wofür? Wolltest du nicht -g3 in -g0 ändern? Dann nimmst du alle Zeilen, aus der platform.txt welche -g3 beinhalten und kopierst diese in die platform.local.txt. Dann darin alle -g3 in -g0 ändern Denn: Die platform.txt wird nur einmal geladen. Die platform.local.txt bei jedem Compilerlauf. Einträge in der platform.local.txt überdecken Einträge aus der platform.txt
Hallo Arduino F, ich habe an 2 Stellen -G3 gefunden und diese auf -G0 geändert: compiler.c.flags=-c {compiler.warning_flags} {compiler.optimization_flags} -g0 -nostdlib {build.defines} -MMD -std=gnu11 -mcpu={build.mcu} {build.float-abi} {build.fpu} -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fmessage- compiler.cpp.flags=-c {compiler.warning_flags} {compiler.optimization_flags} -g0 -fno-use-cxa-atexit -fno-rtti -fno-exceptions -MMD -nostdlib {build.defines} -MMD -std=gnu++17 -mcpu={build.mcu} {build.float-abi} {build.fpu} -fsigned-char -ffunction-sections -fdata-sections -fmessage-length=0 -fno-builtin Als Ergebnis kein großer Unterschied - immer noch ca. 30 s mit Upload. Gibt es eine Möglichkeit, das Erzeugen der Dateien für den Debugger abzuschalten? Viele Grüße Kai
Kai schrieb: > ich habe an 2 Stellen -G3 gefunden und diese auf -G0 geändert: Nicht -G0 sondern -g0. Das mag für dich keinen Unterschied machen..... Nach 1 Minute suchen: Lesestoff: https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html
Kai schrieb: > es geht um die Funktion tone(), welche kein hardwarenaher Krempel ist. Falsch gedacht. Tone frickelt an einem Timer rum, um eine Frequenz zu erzeugen. Dazu sind Timer nicht da, d.h. das ist eine sehr hardwarenahe Funktion. Wenn die Timer des anderen Prozessors anders funktionieren, gibt's halt Stress. Kai schrieb: > Nein das erwarte ich gar nicht sondern frage hier, ob ihr Abhilfen zu > den aufgetretenen Besonderheiten kennt. Es gibt zwei Abhilfen: Einen Chip nehmen, der die gewünschten Funktionen nativ unterstützt, oder auf die nicht möglichen Funktionen verzichten. Eine Emulation kann niemals zu 100% identisch funktionieren.
Entschuldigung: ich habe natürlich von -g3 auf -g0 geändert
Arduino F. schrieb: > Nach 1 Minute suchen: > Lesestoff: https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html super - vielen Dank - wird etwas dauern, bis ich das alles verstanden habe....
Jens M. schrieb: > Kai schrieb: >> es geht um die Funktion tone(), welche kein hardwarenaher Krempel ist. > > Falsch gedacht. > Tone frickelt an einem Timer rum, um eine Frequenz zu erzeugen. Dazu > sind Timer nicht da, d.h. das ist eine sehr hardwarenahe Funktion. > Wenn die Timer des anderen Prozessors anders funktionieren, gibt's halt > Stress. Hallo Jens, danke für deine Antwort - wahrscheinlich habe ich es falsch formuliert: die Funktion tone() ist klar definiert und sollte daher auf allen Plattformen das selbe Ergebnis produzieren: tone(pin, frequency) tone(pin, frequency, duration) Viele Grüße Kai
Kai schrieb: > Als Ergebnis kein großer Unterschied - immer noch ca. 30 s mit Upload. Ähmm, mit -g0 dreht es sich nicht so sehr um die Compilezeit, sondern eher um die Codegröße.
:
Bearbeitet durch User
Kai schrieb: > die Funktion tone() ist klar definiert und sollte daher auf allen > Plattformen das selbe Ergebnis produzieren Reparieren und die Verbesserung der Gemeinschaft melden.
Kai schrieb: > die Funktion tone() ist klar definiert und sollte daher auf allen > Plattformen das selbe Ergebnis produzieren: Das kann sie nicht. Sie funktioniert, weil Arduino nunmal dazu da ist simpel und kurz zu einem Ergebnis zu kommen. Was völlig unüblich ist. Also ist es gerade so ein "geht so", identisch kann es gar nicht sein. Wenn du da tatsächlich von ausgehst bist du seeehr blauäugig.
Jens M. schrieb: > identisch Die Implementierungen von tone() sowohl AVR, als auch R4 liegen auf Github offen aus. Da ist nichts identisch! Bis auf die Funktionsdeklarationen. Sonst: Komplett unterschiedlich. Was auch kein Wunder ist.
Ersetze Mundharmonika durch Clarinette und spiele den gleichen Ton. Es sind sogar beides Blasinstrumente.
Hallo, nach einigen Experimenten bezüglich tone() kann ich folgendes berichten: 1. Die Originalversion aller Melodien (https://github.com/robsoncouto/arduino-songs) funktioniert sowohl auf dem Uno R4 als auch R3 störungsfrei. Der Sketch-Datei beinhaltet sowohl die Defines der Tonhöhen (pitches) als auch die Noten in Form eines Integer-Arrays für jeweils ein Lied. 2. Zusammen mit anderen Programmteilen wird bei der Verwendung von tone() anstelle bestimmter Noten (= Frequenzen) ein merkwürdiger Ton ausgegeben - könnte man als Tschilpen beschreiben. (Der Sketch beinhaltet nur die Abspielroutine. Tonhöhen und Noten sind in Header ausgelagert. Die Noten befinden sich im PROGMEM int melody[]. 3. Wird tone() durch TimerFreeTone() ersetzt, so werden fast alle Melodien korrekt abgespielt. Bei 2 von 25 Melodien gibt es Probleme, diese sind durcheinander und zwar sowohl beim Lesen aus dem PROGMEM als auch aus dem EEPROM. 4. Werden die Melodien vom Uno R4 EEPROM als Datei ausgelesen und in das EEPROM des Uno R3 eingelesen, so ist die Wiedergabe aller Melodien korrekt. In beiden Controllern befinden sich identische Programmteile. Ich habe das Programm, als auch die Noten schon mehrfach verglichen bzw. kontrolliert, komme aber nicht auf die Fehlerursache. Daher werde ich jetzt eine Pause einlegen.... Viele Grüße Kai
Hallo Arduino F, vielen Dank für deine Antwort - was bedeutet es exakt, dass ich PROGMEM auf dem ARM vergessen kann? Die meisten Verwendungen des PROGMEM funktionieren ohne erkennbare Fehler, die Fehler treten in Zusammenhang mit den Melodien auf. Eventuell habe ich in der Adressberechnung auch einen Fehler? Aber weshalb dann nur für Uno R4 bzw. ARM? Anbei ein minimierter Sketch, welcher auf dem Uno R3 fehlerfrei funktioniert und auf dem R4 die Melodien mehr oder weniger stark verfremdet. Am stärksten durcheinander sind Melodie 8. Heilige Nacht und 9. Happy Birthday. Vielen Dank für jede Hilfe im Voraus. Ein schönes Wochenende und viele Grüße Kai
Nachtrag: das weiter oben beschriebene Störgeräusch (Zwitschern bzw. Tschilpen) tritt in diesem Minimal-Sketch nicht auf - hier muss ich noch finden, welche Funktion oder Bibliothek ursächlich ist.
Kai schrieb: > Aber weshalb dann nur für Uno R4 bzw. ARM? Die alten AVR haben getrennte Adressbusse für RAM+Register und Flash. Bei diesen ist das Progmem Gedönse notwendig. Bei dem ARM ist das Flash und Ram im gleichen Adressraum. Also nix Progmem nötig. Kai schrieb: > Die meisten Verwendungen des PROGMEM funktionieren ohne erkennbare > Fehler, Das sind alles mehr oder weniger leere Stummel. Beispiel, die Definition von PROGMEM auf dem R4 ist: #define PROGMEM Also leer. Nur aus Kompatibilitätsgründen da.
Kai schrieb: > was bedeutet es exakt, dass ich PROGMEM auf dem ARM vergessen kann? Bei 8 Bit AVR wird der Programmspeicher mit anderen Befehlen angesprochen, als RAM. Adresse 1234 ist nicht eideutig. Damit kann RAM oder Flash gemeint sein. Bei 32 Bit ARM Controllern ist das anders. Dort werden beide Speicher durch die selben Befehle angesprochen. Die Unterscheidung wird durch eindeutige Adress-Bereiche gemacht. Deswegen hat PROGMEM dort keinen Sinn. Beim STM32 Core ist Progmem einfach als gar nichts definiert, PGM_P ist ein normaler const char* und PSTR(von x) ist auch ein dummy, nämlich x.
Kai schrieb: > was bedeutet es exakt, dass ich PROGMEM > auf dem ARM vergessen kann? Vor allem bedeutet es, dass du das ganze pgm_read_xxx Geraffel nicht brauchst. Anstatt
1 | tempo = pgm_read_word_near(tempis+(snd-1)); |
kannst also einfach:
1 | tempo = tempis[snd - 1]; |
Und warum nimmst du eigentlich globale Variablen, zum Beispiel für tempo??? Der Code sollte eigentlich eher so aussehen:
1 | void setup() // put your setup |
2 | code here, to run once: |
3 | {
|
4 | Serial.begin(19200); // opens serial |
5 | |
6 | ...
|
7 | |
8 | for (byte snd = 1; snd < 28; ++snd) // Play melody 1 - 27 |
9 | {
|
10 | int tempo = tempis[snd - 1]; // Melody tempo |
11 | Serial.print("Title: "); |
12 | Serial.print(snd); |
13 | Serial.print(" "); // Blank |
14 | for (uint8_t byte x = 0; x < 14; ++x) |
15 | {
|
16 | ...
|
Und was sind eigentlich diese magischen Zahlen 14 und 28? Arraylängen? Und warum wird das alles in setup() gemacht?
Kai schrieb: > was bedeutet es exakt, dass ich PROGMEM > auf dem ARM vergessen kann? * Harvard Architektur gegenüber * Von-Neumann Architektur
Hallo Arduino F, Nemopuk, Johann und Norbert, vielen Dank für eure Antworten. Arduino F. schrieb: > Die alten AVR haben getrennte Adressbusse für RAM+Register und Flash. > Bei diesen ist das Progmem Gedönse notwendig. Arduino F. schrieb: > Bei dem ARM ist das Flash und Ram im gleichen Adressraum. Also nix > Progmem nötig. OK - verstanden - vielen Dank Nemopuk schrieb: > Bei 8 Bit AVR wird der Programmspeicher mit anderen Befehlen > angesprochen, als RAM. Adresse 1234 ist nicht eideutig. Damit kann RAM > oder Flash gemeint sein. > > Bei 32 Bit ARM Controllern ist das anders. Dort werden beide Speicher > durch die selben Befehle angesprochen. ebenfalls verstanden Johann L. schrieb: > Vor allem bedeutet es, dass du das ganze pgm_read_xxx Geraffel nicht > brauchst. Anstatttempo = pgm_read_word_near(tempis+(snd-1)); > kannst also einfach:tempo = tempis[snd - 1]; Super - das verkürzt diese Zeilen deutlich Johann L. schrieb: > Und warum nimmst du eigentlich globale Variablen, zum Beispiel für > tempo??? Weil tempo und snd in meinem Sketch auf dem LCD angezeigt werden. Johann L. schrieb: > Und warum wird das alles in setup() gemacht? Weil es im Original (https://github.com/robsoncouto/arduino-songs) genauso ist und ich sicher gehen wollte, das dies nicht die Ursache ist. Johann L. schrieb: > Und was sind eigentlich diese magischen Zahlen 14 und 28? Arraylängen? 14 ist die Länge der Titel und 28 die Anzahl der vorhandenen Melodien. Mal sehen, ob sich das Verhalten nach Änderung verbessert..... Viele Grüße Kai
:
Bearbeitet durch User
Hallo, nach Anpassung des oben angehangenen Minimal-Sketches werden alle Melodien auch auf dem Uno R4 richtig wiedergegeben. Somit war hier die Verwendung von PROGMEM die Ursache. Was ich aber noch nicht verstehe ist, dass auch die Wiedergabe aus dem externen EEPROM in meinem Gesamt-Sketch an identischen Stellen wie bei Verwendung von PROGMEM fehlerhaft ist. Klar ist, dass wenn ich das EEPROM mit dem Uno R4 beschreibe die Daten deshalb durcheinander sind, weil die Routine die Melodien mittels PROGMEM ausliest und ins EEPROM schreibt. Der Fehler tritt aber ebenfalls auf, wenn ich ein mit dem Arduino Mega beschriebenes EEPROM einsetze, welches auf Uno R3 und Mega fehlerfreie Melodien ausgibt. Viele Grüße Kai
:
Bearbeitet durch User
Arduino F. schrieb: > Jens M. schrieb: >> von 32kB auf 256kB nicht passt, > > Der Arduino Mega hat 256k Flash. und der ATmega1284p hat 128k Flash Gibt es nicht mehr die Compilerinfo wo man unterschiedliche Compileroptionen setzen kann? sollte sich auch anpassen lassen auf Arm Architektur.
1 | #if defined(__AVR__)
|
2 | const uint8_t PROGMEM pwmtable_11C[] = {255, 253, 251, 248, 244, 236, 223, 201, 165, 103, 0}; |
3 | #elif defined(ESP32)
|
4 | const uint8_t PROGMEM pwmtable_11C[] = {0, 2, 4, 7, 11, 19, 32, 54, 90, 152, 255}; |
5 | const int freq = 5000; |
6 | const int resolution = 8; |
7 | #endif
|
oder
1 | #if defined(__AVR_ATmega1284P__)
|
2 | Serial.println(F(", auf migthy ATmega1284p")); |
3 | #elif defined(__AVR_ATmega328P__)
|
4 | Serial.println(F(", auf ATmega328p")); |
5 | #elif defined(ESP32)
|
6 | Serial.println(F(", auf ESP32 WEMOS LOLIN32")); |
7 | #endif
|
Beitrag #7943116 wurde vom Autor gelöscht.
Kai schrieb: > 1. Speicherbedarf: Ein Programm welches auf dem Mega 52kB gross ist, > benötigt auf dem R4 mehr als den doppelten Speicher. Wahrscheinlich sind die Arduino-Libraries für den Peripheriezugriff beim ARM einfach komplexer, eben weil die Peripherie komplexer ist. Dafür kann sie auch mehr. Der eigene Code der Anwendung könnte sogar durchaus kleiner sein, hängt vom Einzelfall ab. Kai schrieb: > ich habe an 2 Stellen -G3 gefunden und diese auf -G0 geändert: Das bringt gar nichts. Die Debug-Informationen landen nur in der ELF-Datei, welche sich ausschließlich auf dem PC befindet. Der eigentliche Maschinencode der auf dem Controller landet ist durch die -g Option vollkommen unverändert. Wenn also die Festplatte im PC fast voll ist und du auf dem PC jedes einzelne KB sparen musst, kannst du auf -g0 gehen, sonst würde ich Mikrocontroler-Projekte grundsätzlich immer mit -g3 kompilieren, denn für den Controller macht es keinen Unterschied (auch nicht bei der Übertragungszeit). Dies vereinfacht die Fehlersuche dramatisch - wobei die Arduino-Hardware alleine ja sowieso nicht in-circuit debuggen kann, aber für Crash-Dumps oder Disassembly o.ä. kann es trotzdem nützlich sein. Um den Programmspeicher zu reduzieren musst du i.W. die Arduino-Libraries modifizieren und "entschlacken". Das ist viel Arbeit. Arduino kompiliert anscheinend standardmäßig schon mit "-Os", man kann noch mit LTO und ein paar anderen Optionen experimentieren. Das ist aber was für Leute die sich damit auskennen. Kai schrieb: > 2. Compilier-Dauer: Das Compilieren dauert beim R4 mit ca. 30s deutlich > länger als beim Mega mit ca. 11s. > Abhilfe: keine bekannt Die Arduino-IDE ist da nicht besonders clever, und kompiliert immer alles/vieles neu. Wenn du auf eine andere IDE (z.B. VS Code) umsteigst und ninja als Build-Tool nutzt, geht es viel schneller. Aber auch hier gilt dass die komplexere Library eben etwas Zeit braucht, auch beim Linken. Kai schrieb: > 6. Datenübertragung: Einbrechen der Übertragungsgeschwindigkeit bei > längeren Übertragungen. > Abhilfe: keine bekannt Was für eine Übertragungskanal? Benutze DMA, dann geht's noch viel schneller als beim AVR. Jens M. schrieb: > so stark, das es nur > mit C zu ertragen ist. In Assembler ein kurzes einfaches Blinkprogramm > zum testen geht nicht, weil das nicht oder nur sehr umständlich > dokumentiert ist wie man den Chip anspricht. Die Dokumentation von ARM ist exzellent, wenn Renesas die Peripherie nicht gut dokumentiert liegt das nicht an ARM. Und selbstverständlich kann man problemlos in Assembler für ARM Cortex-M ein einfaches Blinkprogramm hinschreiben, das macht nur normalerweise keiner. Tatsächlich programmiert es sich im ARM-Assembler ziemlich angenehm, dank Offset-Adressierung (gerade auch auf dem Stack), der vielen als Pointer nutzbaren Register, vielfältigen Arithmetik-Instructions inkl. Multiplikation, Barrel-Shifting und FPU, effizienten Load/Store-Multi-Instructions, integrierten Shifts bei diversen Instructions (bei Speicherzugriffen und auch Arithmetik), automatischer Kontext-Sicherung bei Interrupts, und natürlich linearem Adressraums. Etwas nervig ist dass auf Peripherieregister immer als Read-Modify-Write zugegriffen werden muss, aber das ist erträglich (kann man z.B. auch in ein Makro stecken). Jens M. schrieb: > Daher kann man C-Programme ja auch nie auf > eine andere Hardware übertragen Komisch dass eine Unmenge an C-Software super auf ARM-Smartphones/Laptops/Servern, x86- und x86_64 -PCs, MIPS-Routern läuft, sogar ohne Massen an "#ifdef __arm__" etc.
Niklas G. schrieb: > wobei die Arduino-Hardware alleine ja sowieso nicht > in-circuit debuggen kann, Das ist nicht mehr richtig! Die Arduino IDE 2.X kann das, zumindest für einige µC z.B. STM32
Arduino F. schrieb: > Das ist nicht mehr richtig! > Die Arduino IDE 2.X kann das, zumindest für einige µC > z.B. STM32 m.W. hat aber keines der Original-Arduino-Boards einen Debugger integriert, und ich schrieb ja auch "Arduino-Hardware _alleine_".
Hallo Joachim und Niklas, Vielen Dank auch für eure Antworten. Joachim B. schrieb: > Gibt es nicht mehr die Compilerinfo wo man unterschiedliche > Compileroptionen setzen kann? Damit bin ich überfragt.... Niklas G. schrieb: > Die Arduino-IDE ist da nicht besonders clever, und kompiliert immer > alles/vieles neu. Wenn du auf eine andere IDE (z.B. VS Code) umsteigst > und ninja als Build-Tool nutzt, geht es viel schneller. Aber auch hier > gilt dass die komplexere Library eben etwas Zeit braucht, auch beim > Linken. Mir ging es nicht um das Sparen von Arbeitsspeicher, sonden um das Verkürzen der Compilierdauer. Viele Grüße Kai
Niklas G. schrieb: > Kai schrieb: >> 6. Datenübertragung: Einbrechen der Übertragungsgeschwindigkeit bei >> längeren Übertragungen. >> Abhilfe: keine bekannt > > Was für eine Übertragungskanal? Benutze DMA, dann geht's noch viel > schneller als beim AVR. Hallo Niklas, es geht um die serielle Schnittstelle. Viele Grüße Kai
Niklas G. schrieb: > m.W. hat aber keines der Original-Arduino-Boards einen Debugger > integriert Dieses hat einen: https://store.arduino.cc/products/arduino-zero
Kai schrieb: > Mir ging es nicht um das Sparen von Arbeitsspeicher, sonden um das > Verkürzen der Compilierdauer. Das hatte ich verstanden. Du kannst wie gesagt die Compilierdauer drastisch reduzieren indem du nicht mit der Arduino-IDE kompilierst, sondern über ein Tool das immer nur genau das neu baut, das auch wirklich geändert wurde. Wie eben über Ninja. Beispielsweise hat ST für die STM32 jetzt Plugins für VS Code welche Ninja nutzen, und damit geht's dann sehr flott. z.B. 1-2 Sekunden wenn nur eine nicht allzu komplexe Datei geändert wurde. Das ist die gleiche Architektur und gleicher Compiler wie für den RA4M1. i.A. geht kompilieren übrigens unter Linux schneller als unter Windows. Kai schrieb: > es geht um die serielle Schnittstelle. Angeblich kann der RA4M1 bis zu 6.6 MHz auf der seriellen Schnittstelle, die lässt sich mit dem ARM-Prozessorkern auf jeden Fall kontinuierlich bedienen, gerade auch wenn man DMA nutzt. Die Verbindung zum PC wird über USB hergestellt, mit einer theoretischen maximalen Datenrate von 12 Mbps, auch die sollte erzielbar sein. Also wieder eine Frage der Software. Kann natürlich sein dass das Arduino-Framework das nicht schafft, da muss man dann ggf. von Hand ran. Nemopuk schrieb: > Dieses hat einen: Cool, na dafür sollte man dann definitiv immer mit -g3 kompilieren.
Hallo Niklas, die Übertragung kürzerer Dateien (aktuell 605 Zeichen) funktioniert auch beim Arduino R4 ohne Probleme. Meine erste Analyse zeigt, dass bei grösseren Dateien die Übertragung zwischendurch stockt (ich lasse mir das Erreichen einer bestimmten Anzahl von Daten über die serielle Schnittstelle ausgeben). Der serielle Puffer verschluckt dann scheinbar Zeichen. Am Ende der Übertragung wurden deutlich weniger Zeichen übertragen, als in der Datei vorhanden sind. Viele Grüße Kai
Kai schrieb: > Der serielle > Puffer verschluckt dann scheinbar Zeichen. Am Ende der Übertragung > wurden deutlich weniger Zeichen übertragen, als in der Datei vorhanden > sind. Was ist das Zielgerät? Hast du mal per Oszilloskop oder Logic-Analyzer geprüft was gesendet wird? Sendest du immer nur einzelne Bytes? Mal per USB-Serial-Adapter den Datenstrom mitgeschnitten? Wie ist die Baudrate? Klingt doch stark nach Software-Problem.
Da das Flashen der Firmware (die ja deutlich über 605 Bytes hat) ebenfalls über exakt die selbe Schnittstelle geht und problemlos klappt (sonst würde das Programm nicht laufen) ist das 100% ein Problem des Codes.
Jens M. schrieb: > Da das Flashen der Firmware (die ja deutlich über 605 Bytes hat) > ebenfalls über exakt die selbe Schnittstelle geht Das Flashen geht über natives USB, keine serielle Schnittstelle. Das Board hat keinen USB-Serial-Adapter. Kai nutzt vermutlich die "sekundäre" serielle Schnittstelle zur Kommunikation mit einem anderen Gerät.
Niklas G. schrieb: > Das Flashen geht über natives USB, keine serielle Schnittstelle. Das > Board hat keinen USB-Serial-Adapter. Kai nutzt vermutlich die > "sekundäre" serielle Schnittstelle zur Kommunikation mit einem anderen > Gerät. Hallo Niklas, richtig - die Datenübertragung zwischen PC und Arduino erfolgt über die "sekundäre" serielle Schnittstelle (19200 Baud). Viele Grüße Kai
:
Bearbeitet durch User
Kai schrieb: > richtig - die Datenübertragung zwischen PC und Arduino erfolgt über die > "sekundäre" serielle Schnittstelle (19200 Baud). Warum nicht über USB? Wie hast du die sekundäre Schnittstelle am PC angebunden? Mit was für einer Software empfängst du die Daten? 19200 Baud sind jedenfalls so gut wie nix, das kann jeder Controller unter der Sonne zu 100% abhandeln.
:
Bearbeitet durch User
Hallo Niklas, entschuldige - da habe ich nicht aufgepasst - die Übertragung erfolgt über USB - im Falle Uno R4 über COM7 und im Falle Uno R3 COM4. Das Senden von beiden Controllern an den PC ist weiterhin problemlos, jedoch tritt beim Empfangen mit Uno R4 das o. g. Problem auf. Evtl. liegt das Problem an der höheren Arbeitsfrequenz des Uno R4? Zurzeit übertrage ich die Daten mittels des seriellen Monitors, habe aber auch eine Visual Studio App dafür geschrieben. Muss ich beim R4 evtl. Serial1 nutzen? Ich habe schon überlegt, wie ich das Problem mittels Scope darstellen kann, bin aber bisher auf keine Lösung gekommen. Viele Grüße Kai
:
Bearbeitet durch User
Kai schrieb: > jedoch tritt beim Empfangen mit Uno R4 das o. g. Problem auf. Theoretisch könnte es ein Fehler in der Arduino Library für den R4 sein, aber ich kann mir nicht vorstellen dass so ein elementarer Fall nicht korrekt abgedeckt wird. Das USB Protokoll enthält eine Prüfung und Flusskontrolle für die Nutzdaten, somit kann auf dem Controller kein Puffer überlaufen und Daten verloren gehen. Daher ist es höchst wahrscheinlich ein Problem in deinem Code. Kai schrieb: > Evtl. liegt das Problem an der höheren Arbeitsfrequenz des Uno R4? Nein. Kai schrieb: > Zurzeit übertrage ich die Daten mittels des seriellen Monitors, Und damit tritt das Problem auch auf? Kai schrieb: > Muss ich beim R4 evtl. Serial1 nutzen? Nein. Kai schrieb: > Ich habe schon überlegt, wie ich das Problem mittels Scope darstellen > kann, bin aber bisher auf keine Lösung gekommen. Bei USB geht das nicht wirklich und ist auch kaum sinnvoll. Die Baudrate spielt übrigens bei reiner USB-Übertragung keine Rolle, weil nirgendwo eine physische serielle Schnittstelle im Spiel ist.
:
Bearbeitet durch User
Niklas G. schrieb: >> Zurzeit übertrage ich die Daten mittels des seriellen Monitors, > Und damit tritt das Problem auch auf? ja - beim Uno R4 und nein - beim Uno R3
Kai schrieb: > ja - beim Uno R4 und Dann liegt es so gut wie sicher an deinem Sketch. Insbesondere weil du schreibst: > Der serielle Puffer verschluckt dann scheinbar Zeichen. Am Ende der Übertragung wurden deutlich weniger Zeichen übertragen Bei USB-Serial kann eigentlich nichts verschluckt werden.
Dieses Thema hatten wir schon mal, da lag es 100% an schlechtem Code. Nur wolltest du das bis zum Schluss nicht einsehen. Beitrag "Arduino: page-write in I2C eeprom verliert sporadisch ein Byte"
:
Bearbeitet durch User
Hallo Nemopuk, naja - der schlechte Code läuft aber auf Mega und Uno R3 seit gut 2 Monaten problemlos.... Viele Grüße Kai
Kai schrieb: > naja - der schlechte Code läuft aber auf Mega und Uno R3 seit gut 2 > Monaten problemlos.... Dann bleibe halt beim Uno R3 und akzeptiere die Schuld, anstatt über den Uno R4 zu schimpfen. Wenn du die Ratschläge damals angenommen hättest, dann hättest du jetzt kein Problem. Oder nutze dies als zweite Gelegenheit und Grund, es richtig zu machen. Neue Ratschläge braucht es dazu nicht.
:
Bearbeitet durch User
Hallo Nemopuk, ich habe nicht über den Uno R4 geschimpft, sondern Besonderheiten geschildert und nach Abhilfe gefragt. Aus meiner Sicht können alle Punkte auch für andere Uno R4 Umsteiger hilfreich sein - sei es, um eine Entscheidung für oder gegen Arduino Uno R4 zu treffen oder um nicht mit den selben Besonderheiten kämpfen zu müssen. 1. Übertragung PC an seriellen Monitor funktioniert nicht - Ursache dank deines Tipps gefunden Abhilfe: DTR + RTS müssen gesetzt werden 2. Doppelter Speicherbedarf - Ursache dank deines Tipps: ARM-Architektur Abhilfe: keine 3. random() sehr langsam - Ursache Routine initialisiert TRNG bei jedem Aufruf neu initialisiert (100ms) - Abhilfe dank eines Tipps von Falk gefunden 4. tone() Melodien fehlerhaft - Ursache PROGMEM Abhilfe: dank Tipps von Arduino F, Johann und dir ist PROGMEM nicht nötig. *) 5. EEPROM: ggf. schnell verschlissen - Ursache: wird im Flash simuliert Abhilfe: wahrscheinlich besser externes EEPROM verwenden 6. Datenübertragung: Einbrechen der Übertragungsgeschwindigkeit - Ursache: ggf. mein schlechter Code Abhilfe bisher unklar 7. LED-Matrix: recht dunkel - Ursache: Charlieplexing Abhilfe: keine bekannt - ist aber auch nicht so wichtig. 8. Interrupts: unerwartete Interrupts - Ursache: ggf. weitere von mir eingebundene Bibliotheken bzw. Funktionen Abhilfe: keine bekannt. Nur bei Punkt 6. ist eventuell mein Code ursächlich - die Ursache muss ich noch finden - evtl. schlägt ein Timeout zu, da das Programm ja schneller abgearbeitet wird. Als weitere Besonderheiten wäre noch zu nennen: 9. Bluetooth: nur BLE Viele Grüße Kai *) Offen ist noch herauszufinden, welche Bibliotheken oder Funktionen den Ton selber stören.
Hallo, anbei ein Minimal-Sketch bei dem die oben beschriebenen Störungen auftreten. Dieser schreibt die Daten in ein externes 32k-EEPROM und liest diese anschliessend wieder aus. Bei allen Melodien treten mehr oder weniger starke Störungen auf. Die meisten sind aber noch erkennbar. Nur 8 und 9 sind vollkommen durcheinander. Ohne das Einbinden des LCD werden keine I2C-Adressen gefunden. Was könnte dafür die Ursache sein? Viele Grüße Kai
Kai schrieb: > Ohne das Einbinden des LCD werden keine I2C-Adressen gefunden. Was > könnte dafür die Ursache sein? Fehlende Pull-Up Widerstände an SCL und SDA.
Kai schrieb: > Ohne das Einbinden des LCD werden keine I2C-Adressen gefunden. Was > könnte dafür die Ursache sein? fehlende Pullup
Die Pull-Up Widerstände auf den gängigen Display Boards sind außerdem recht hochohmig. Das könnte deine Kommunikation zum EEPROM beeinträchtigen. Ich würde sie immer auf 1-3 mA auslegen, wenn die Leitungen kurz sind.
:
Bearbeitet durch User
Hallo Arduino F und Nemopuk, vielen Dank für Eure Antworten. ich messe 1k6. LCD und RTC sind auch ohne Einbinden montiert und somit deren Pull-Up aktiv. Jedoch bekomme ich erst nach dem Einbinden des LCD Adressen angezeigt. Viele Grüße Kai
Kai schrieb: > Jedoch bekomme ich erst nach dem Einbinden des LCD Adressen angezeigt. Was genau meinst du mit "einbinden"?
Die includes einfügen: #include <LiquidCrystal_I2C.h> // I2C-Display LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display und das LCD initialisieren: lcd.init(); // Initialize the lcd
Hmm, darauf kann ich mir keinen Reim machen. Das Display sollte auch ohne Initialisierung nicht den Bus blockieren. Hast du eventuell noch andere Stellen im Code, die auf das nicht initialisierte Display zuzugreifen versuchen? Wahrscheinlich nicht, das würde wohl nicht compilieren.
:
Bearbeitet durch User
Nein - ich habe alle Befehle für das Display erst eingefügt, als ich keine Adressen fand. Zuerst habe ich mit dem LCD angefangen. Sobald ich nur diese 3 Zeilen einfüge: #include <LiquidCrystal_I2C.h> // I2C-Display LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 lcd.init(); finde ich die Adressen (siehe Screenshot).
:
Bearbeitet durch User
Nemopuk schrieb: > Bei 32 Bit ARM Controllern ist das anders. Dort werden beide Speicher > durch die selben Befehle angesprochen. Die Unterscheidung wird durch > eindeutige Adress-Bereiche gemacht. Deswegen hat PROGMEM dort keinen > Sinn. Beim STM32 Core ist Progmem einfach als gar nichts definiert, > PGM_P ist ein normaler const char* und PSTR(von x) ist auch ein dummy, > nämlich x. Hallo Nemopuk, wie bekomme ich die Daten in den Flash bzw. wie und welche eindeutigen Adress-Bereiche muss ich angeben um beispielsweise: const int melody[] PROGMEM = { in den Flash zu bekommen? Viele Grüße Kai
Kai schrieb: > Hallo Nemopuk, > > wie bekomme ich die Daten in den Flash bzw. wie und welche eindeutigen > Adress-Bereiche muss ich angeben um beispielsweise: > > const int melody[] PROGMEM = { > > in den Flash zu bekommen? Einfach hinschreiben, um den Rest kümmert sich der Compiler.
Kai schrieb: > wie bekomme ich die Daten in den Flash Im einfachsten Fall als statisches Array in den Quelltext schreiben. > welche eindeutigen Adress-Bereiche muss ich angeben Schau doch einfach ins Datenblatt von deinem Mikrocontroller. Ich habe mit dem keine Erfahrung.
Falk B. schrieb: > Einfach hinschreiben, um den Rest kümmert sich der Compiler. Hallo Falk, vielen Dank für deine Antwort - der Compiler ignoriert es - die Daten landen im RAM: Globale Variablen verwenden 9020 Bytes (27%) des dynamischen Speichers, 23748 Bytes für lokale Variablen verbleiben. Das Maximum sind 32768 Bytes. Es geht um einen Arduino R4 mit ARM-Controller (Renesas RA4M1 Cortex M4). Hallo Nemopuk, ebenfalls vielen Dank - schaue ich gleich mal rein. Viele Grüße Kai
:
Bearbeitet durch User
Kai schrieb: > vielen Dank für deine Antwort - der Compiler ignoriert es - die Daten > landen im RAM Vielleicht hast du "const" vergessen oder an die falsche Stelle gesetzt. Wobei du die 27% vielleicht falsch interpretierst. Lasse dir lieber ein map File erzeugen und da rein.
:
Bearbeitet durch User
Wenn ich mich recht erinnere ist Arduino so intelligent, alle Strings ins RAM zu kopieren, damit man die da benutzen kann. Auch wenn da nur ein "print 'hello world'" drinsteht und sich der String nicht ändert wird er beim Start in's RAM kopiert. Mag aber sein das es sich da um eine ATmega328-Spezialität handelt die vom Compiler abgefrühstückt wird. Bei Arduino und C wundert mich nix mehr.
Jens M. schrieb: > Wenn ich mich recht erinnere ist Arduino so intelligent, alle Strings > ins RAM zu kopieren, Das ist keine spezielle Eigenschaft von Arduino, sondern von C/C++. Um dem entgegen zu wirken, benutzt man auf AVR PROGMEM, PSTR und was sonst noch daran hängt. Arduino fügt noch due F-Strings hinzu. Das ist alles gut verständlich dokumentiert: - https://www.nongnu.org/avr-libc/user-manual/pgmspace.html - https://docs.arduino.cc/language-reference/de/en/variables/utilities/PROGMEM/ Auf ARM benutzt man hingegen const. Wenn dem Compiler klar ist, dass der String nicht änderbar ist, dann wird er nicht ins RAM kopiert. Direkte nur lesende Zugriffe auf den Programmspeicher brauchen bei ARM wie gesagt keiner besonderen Befehle.
:
Bearbeitet durch User
Jens M. schrieb: > Bei Arduino und C wundert mich nix mehr. C++! Nicht C. Oder nur wenig C. Nein das ist keine Arduino Besonderheit. Sondern der Harvard Architektur der alten AVR geschuldet. Jens M. schrieb: > Mag aber sein das es sich da um eine ATmega328-Spezialität handelt die > vom Compiler abgefrühstückt wird. Genau! Dein Arduino Bashing ist völlig fehl am platze. Einfach mal kundig machen, würde dir diese Peinlichkeit erspart haben können. Denn so siehst du aus, wie der Verrückte, der wildfremde Leute auf der Straße, ohne jeden erkennbaren Grund anschreit.
Nemopuk schrieb: > Um > dem entgegen zu wirken, benutzt man auf AVR PROGMEM und PSTR. Auf ARM > benutzt man hingegen const. Oh, also eine vollkommen hirnrissige Vorgehensweise, und Hardwareabhängig dazu? Muss man die dann alle kennen und in #ifdef einpacken, damit man in 10 Jahren wenn man die Architektur wechselt noch weiß wo man hardwarespezifisch war? Oder schreibt man dann einfach ein ganzes Programm neu? Ist wahrscheinlich einfacher.... Warum kann ein ach so schlauer Compiler nicht im Quellcode nachsehen, ob es irgendwo eine Zuweisung gibt, und wenn nicht ist das im Flash und wird auch kurz daraus gelesen anstatt dafür RAM zu verblasen?
Jens M. schrieb: > Oh, also eine vollkommen hirnrissige Vorgehensweise, und > Hardwareabhängig dazu? Hast du eine bessere Idee? Funktionen, die RAM lesen können auf AVR halt nicht den Programmspeicher lesen. Ich bin auf deine zauberhaft bessere Lösung gedpannt.
Jens M. schrieb: > Warum kann ein ach so schlauer Compiler nicht im Quellcode nachsehen, ob > es irgendwo eine Zuweisung gibt, und wenn nicht ist das im Flash und > wird auch kurz daraus gelesen anstatt dafür RAM zu verblasen? Jetzt schreit der Verrückte auch noch die GCC Entwickler an....
Das ist ein allgemeines C-Problem (und das schließt c# und c++ ein), denke ich. Aber speziell bei Arduino bzw. AVR ist mir aufgefallen, das alle Nase lang Zeug auf den Stack und wieder runter geholt wird, und dabei hat der Controller nicht mal einen, der wird simuliert. Und diese ganze hin und her schieberei kostet Speicher, Zeit und sorgt dafür das es nicht so einfach geht, den Kram auf einer anderen Architektur zu benutzen. Nemopuk schrieb: > Ich bin auf deine zauberhaft bessere > Lösung gedpannt. Anstatt den String beim Start in den Ram zu kopieren, und dann wenn er benutzt wird das Ram auf den Stack zu kopieren um dann die Funktion aufzurufen die den Stack abruft könnte eine kleine Funktion den String direkt auf den Stack schreiben, oder besser noch: direkt in den entsprechenden Puffer kopieren, das spart den Stack (oder dessen Benutzung) komplett ein. Noch ne Alternative (da wir ja eh hardwarespezifisch sind) wäre auch direktes Lesen des Flash-Arrays. Kann der Bootloader ja auch, geht also. Arduino F. schrieb: > Jetzt schreit der Verrückte auch noch die GCC Entwickler an.... Das ist kein Ding des GCC, das ist allgemein C, oder?
:
Bearbeitet durch User
Jens M. schrieb: > Aber speziell bei Arduino bzw. AVR ist mir aufgefallen, das alle Nase > lang Zeug auf den Stack und wieder runter geholt wird, und dabei hat > der Controller nicht mal einen, der wird simuliert. Natürlich haben (fast alle) AVR Stack! Und der wird auch nur so viel genutzt, wie nötig. Ich bezweifle stark, dass du einen vom Compiler optimierten Code noch weiter verbessern kannst. > Anstatt den String beim Start in den Ram zu kopieren, und dann wenn er > benutzt wird das Ram auf den Stack zu kopieren um dann die Funktion > aufzurufen die den Stack abruft ... Wie man sieht, hast du keine Ahnung, wie C funktioniert. Der Zugriff auf Strings erfolgt immer mittels Zeiger. > puts(welcome) Kopiert den String nicht auf den Stack, sondern legt höchstens dessen Adresse auf den Stack. Bei so wenigen Argumenten bevorzugt der Compiler allerdings die Nutzung von CPU Registern zur Übergabe. Also keine indirekte Übergabe mittels Stack. Der andere Punkt ist, dass die Funktion puts() eine Zeiger auf Daten im RAM erwartet. Der Zeiger ist technisch eine Integer Zahl, die Adresse der Zeichenkette im RAM. Der Zeiger enthält keine Information, auf welchen Adressraum er sich bezieht. Wenn du einen String aus dem Programmspeicher ausgeben willst, musst du daher eine andere Funktion aufrufen: > puts_P(welcome) Die puts_P() Funktion erwartete ebenfalls einen Zeiger als Argument, also die Adresse im Speicher. Sie liest jedoch nicht aus dem RAM, sondern aus dem Programmspeicher. Dafür enthält sie andere CPU Instruktionen (siehe https://ww1.microchip.com/downloads/en/DeviceDoc/AVR-InstructionSet-Manual-DS40002198.pdf Kapitel 3, besonders 3.9 und 3.10). Eine C-Funktion, die beides kann, müsste einen weiteren Parameters haben: > puts(welcome,RAM) > puts(welcome,FLASH) Damit wäre man aber noch weiter von C Standard weg, als die aktuelle Lösung. Arduino überlädt C++ Methoden, so dass dort scheinbar eine Methode beides kann. In Wirklichkeit sind es aber mindestens zwei Methoden. Der Compiler wählt die zum Zeiger-Typ passende Methode aus. C++ kann das. Jens M. schrieb: > Muss man die dann alle kennen und in #ifdef einpacken Kann man. Oder man legt für jede Hardware eigene Dateien an, und lässt den Build-Prozessor entscheiden, welche Implementierung eingebunden wird. So wie Arduino das mit den "Cores" macht. Jens M. schrieb: > könnte eine kleine Funktion den String ... besser noch: > direkt in den entsprechenden Puffer kopieren Das wird ja oft so gemacht. Dann übergibst du einen Zeiger auf den vorbereiteten Puffer. Die ganze Standard C Bibliothek ist darauf ausgelegt. > Noch ne Alternative (da wir ja eh hardwarespezifisch sind) wäre auch > direktes Lesen des Flash-Arrays. Das macht puts_P() ja. Es macht wenig Sinn, die Programmiersprache C zu kritisieren. Sie wurde 1972 für die damals aktuellen Computer entworfen. Natürlich hatten viele Menschen inzwischen andere (teils bessere) Ideen. Aber dann wäre es kein C mehr, sondern vielleicht Basic, oder Pascal, oder ... Bei C hast du die Garantie, dass sich solche Sachen nicht ändern. Wenn du es ändern willst: gerne, aber unter einem anderen Namen. Du darfst dich gerne in die endlos lange Reihe der Erfinder stellen, die einen "besseren" Nachfolger von C entworfen haben.
:
Bearbeitet durch User
Jens M. schrieb: > das ist allgemein C, oder? Nein! Gcc C kann __flash (mache dich kundig, was __flash tut) Gcc C++ kann das nicht. Jens M. schrieb: > Aber speziell bei Arduino Nochmal: Das hat mit Arduino nichts zu tun.
:
Bearbeitet durch User
Nemopuk schrieb: > Wobei du die 27% vielleicht falsch interpretierst. Lasse dir lieber ein > map File erzeugen und da rein. Hallo Nemopuk, das map-File macht mich nicht viel schlauer..... Kannst du da etwas herauslesen? Viele Grüße Kai
Wahrscheinlich ist diese Stelle richtig: .rodata._ZL5title 0x00011a2b 0x2a1 C:\Users\kai-s\AppData\Local\arduino\sketches\E60D65F7750953D07710A2F09E A6D18F\sketch\Melody_ARM_aus_EEPROM_all.ino.cpp.o .rodata._ZL6melody 0x00011ccc 0x4e20 C:\Users\kai-s\AppData\Local\arduino\sketches\E60D65F7750953D07710A2F09E A6D18F\sketch\Melody_ARM_aus_EEPROM_all.ino.cpp.o .rodata._ZL6tempis 0x00016aec 0xc8 C:\Users\kai-s\AppData\Local\arduino\sketches\E60D65F7750953D07710A2F09E A6D18F\sketch\Melody_ARM_aus_EEPROM_all.ino.cpp.o und diese: Memory Configuration Name Origin Length Attributes FLASH 0x00004000 0x0003c000 xr RAM 0x20000000 0x00008000 xrw DATA_FLASH 0x40100000 0x00002000 xr OPTION_SETTING 0x00000000 0x00000000 r OPTION_SETTING_S 0x00000000 0x00000000 r ID_CODE 0x01010018 0x00000020 xr default 0x00000000 0xffffffff Das würde bedeuten, dass titel, melody und tempi im Flash sind. Aber was verbraucht dann so viel RAM? Der Sketch verwendet 81312 Bytes (31%) des Programmspeicherplatzes. Das Maximum sind 262144 Bytes. Globale Variablen verwenden 9020 Bytes (27%) des dynamischen Speichers, 23748 Bytes für lokale Variablen verbleiben. Das Maximum sind 32768 Bytes.
Kai schrieb: > Kannst du da etwas herauslesen? Der größte Verbraucher sind die Arduino Libraries - "Wire" und die Puffer für die seriellen Schnittstellen etc. Sieht ansonsten auf den ersten Blick unauffällig aus. Nemopuk schrieb: > Vielleicht hast du "const" vergessen oder an die falsche Stelle gesetzt. Da es C++ ist sollte man besser constexpr nutzen um ganz sicher zu gehen:
1 | constexpr int melody[] = { 1, 2, 3 }; |
Ist es sinnvoll den Datentyp "int" zu nutzen? Der ist auf ARM 32bit groß. Wenn deine Zahlen einen kleineren Wertebereich haben, nutze int16_t, int8_t, uint16_t oder uint8_t. Kai schrieb: > Das würde bedeuten, dass titel, melody und tempi im Flash sind. Korrekt.
:
Bearbeitet durch User
Kai schrieb: > der Compiler ignoriert es - die Daten > landen im RAM Das ist falsch! Im Beispiel verwende ich 3 Arten ein Array zu definieren. Den Ram Verbrauch habe als Kommentar angeführt.
Niklas G. schrieb: > Der ist auf ARM 32bit > groß. Wenn deine Zahlen einen kleineren Wertebereich haben, nutze > int16_t, int8_t, uint16_t oder uint8_t. Das kann sich kontraproduktiv auswirken. (?) 32Bit ist halt der der native Datentype für ARM Wobei mir hier unsigned sinnvoller erscheint, als signed
Arduino F. schrieb: > Das kann sich kontraproduktiv auswirken. (?) Cortex-M4 (und nicht nur der) hat Maschinenbefehle um gefahrlos und ohne Zeitstrafe auf Bytes (LDRB/STRB), Halfwords (LDRH/STRH) und natürlich volle Words (LDR/STR) zuzugreifen. Anständig aligned müssen sie aber sein, sonst gibt's Saures.
Hallo Niklas und Arduino F, vielen Dank für eure Antworten. Niklas G. schrieb: > Da es C++ ist sollte man besser constexpr nutzen um ganz sicher zu > gehen: > constexpr int melody[] = { 1, 2, 3 }; Arduino F. schrieb: > Das ist falsch! ich habe immer noch nicht verstanden, weshalb angezeigt wird, dass so viel RAM verbraucht wird obwohl nur wenige Variablen im Sketch verwendet werden. Viele Grüße Kai
Beitrag #7943533 wurde vom Autor gelöscht.
Arduino F. schrieb: > Kai schrieb: >> der Compiler ignoriert es - die Daten >> landen im RAM > > Das ist falsch! > > Im Beispiel verwende ich 3 Arten ein Array zu definieren. > Den Ram Verbrauch habe als Kommentar angeführt. Hallo Arduino F, vielen Dank - aber was genau kann ich mit deinem Sketch erreichen? Viele Grüße Kai
Die Interrupt-Vektor Tabelle, Puffer für USB, Puffer für printf/puts sind bei Cortex-M viel größer als bei 8 Bit AVR.
:
Bearbeitet durch User
Kai schrieb: > ich habe immer noch nicht verstanden, weshalb angezeigt wird, dass so > viel RAM verbraucht wird obwohl nur wenige Variablen im Sketch verwendet > werden. Das mag sein, dass du das nicht verstehst. Ich weiß das auch nicht exakt. Aber das ist alles kein Grund sich irgendwelche Fantasien aus den Fingern zu saugen. Oder mit Nebelkerzen um sich zu werfen.
:
Bearbeitet durch User
Beitrag "Re: Arduino Uno R4: Besonderheiten und Abhilfen" Mit PROGMEM auf Arduino Uno R3 ergibt sich folgender Speicherverbrauch: Der Sketch verwendet 15472 Bytes (47%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes. Globale Variablen verwenden 226 Bytes (11%) des dynamischen Speichers, 1822 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes. Das ist deutlich weniger RAM - allerdings für die paar Variablen auch recht viel
:
Bearbeitet durch User
Arduino F. schrieb: >> ich habe immer noch nicht verstanden, weshalb angezeigt wird, dass so >> viel RAM verbraucht wird obwohl nur wenige Variablen im Sketch verwendet >> werden. > > Das mag sein, dass du das nicht verstehst. > Ich weiß das auch nicht exakt. > > Aber das ist alles kein Grund sich irgendwelche Fantasien aus den > Fingern zu saugen. Oder mit Nebelkerzen um sich zu werfen. Hallo Arduino F, danke für deine ehrliche Antwort - aber wo fantasiere ich und werfe Nebelkerzen? Viele Grüße Kai
:
Bearbeitet durch User
Kai schrieb: > Mit PROGMEM auf Arduino Uno R3 ergibt sich folgender Speicherverbrauch Das ist wieder eine solche Nebelkerze! Kai schrieb: > Hallo Arduino F, > > vielen Dank - aber was genau kann ich mit deinem Sketch erreichen? Du kannst damit nachvollziehen, dass const(expr) Daten eben nicht im Ram landen. Nicht mehr, und nicht weniger. Es wird Zeit für dich, dass du akzeptierst, dass die Flash Geschichte sich grundsätzlich zwischen ARM und AVR unterscheidet. Dein ganzes mit dem Füßen auf dem Boden rumstampfen hilft dir nichts. Es setzt keine Fakten außer Kraft.
:
Bearbeitet durch User
Kai schrieb: > Hm - im Ordner für Uno R3 finde ich keins.... Du kannst die Arduino IDE, bzw. den Builder überreden ein map File zu bauen Für AVR habe ich das bei mir eingebaut. Für ARM habe ich das noch nicht probiert. Die Doku dazu: https://docs.arduino.cc/arduino-cli/platform-specification/ Beachte besonders: > Pre and post build hooks (since Arduino IDE 1.6.5) Da ist es unterzubringen
Kai schrieb: > Hm - im Ordner für Uno R3 finde ich keins.... Ein bisschen mehr Eigeninitiative bitte. Du musst in der platform.txt etwas einfügen: > -Wl,-Map,dateiname.map Konkrete Beispiele findest du mit Google. Zum Beispiel http://jheyman.github.io/blog/pages/ArduinoTipsAndTricks/#checking-the-linkers-memory-map Und lies das: https://docs.arduino.cc/learn/programming/memory-guide/
:
Bearbeitet durch User
Nemopuk schrieb: > Du musst in der platform.txt > etwas einfügen: Für Anpassungen ist es wirklich empfehlenswert diese in der platform.local.txt vorzunehmen. Die ist dafür vorgesehen.
:
Bearbeitet durch User
Arduino F. schrieb: > Für Anpassungen ist es wirklich empfehlenswert diese in der > platform.local.txt vorzunehmen. > Die ist dafür vorgesehen. Ja. Doch ich wollte ihn nicht mit optionalen Details überfordern.
Hallo Arduino F und Nemopuk, vielen Dank für eure Antworten. Arduino F. schrieb: > Du kannst die Arduino IDE, bzw. den Builder überreden ein map File zu > bauen Danke Nemopuk schrieb: > Ein bisschen mehr Eigeninitiative bitte. Du musst in der platform.txt > etwas einfügen: >> -Wl,-Map,dateiname.map > Konkrete Beispiele findest du mit Google. Zum Beispiel > http://jheyman.github.io/blog/pages/ArduinoTipsAndTricks/#checking-the-linkers-memory-map Ebenfalls Danke Nemopuk schrieb: > Ja. Doch ich wollte ihn nicht mit optionalen Details überfordern. platform.local.txt kennt er schon :) Viele Grüße Kai
Arduino F. schrieb: > Das kann sich kontraproduktiv auswirken. (?) Tendentiell eher nur bei lokalen/temporären Variablen, aber auch i.W. nur weil die Compiler noch nicht gut genug sind das entsprechend zu optimieren. Bei globalen unsignierten Variablen hat es keinen Nachteil kleinere Datentypen zu nutzen, denn der ARM kann über die LDRB/LDRH -Instruktionen beim Laden die Variable automatisch auf 32bit "ausdehnen" (zero-extend). Bei Signed-Werten muss je ein ganzer Takt für die Sign-Extension aufgewendet werden (SXTH/SXTB). Das dürfe in den allermeisten Fällen ein guter Trade-Off sein. Kai schrieb: > ich habe immer noch nicht verstanden, weshalb angezeigt wird, dass so > viel RAM verbraucht wird obwohl nur wenige Variablen im Sketch verwendet > werden. Die Arduino-Library verwendet eben auch noch Variablen, und zwar eben große (Arrays). Arduino ist halt nicht auf Effizienz getrimmt.
Nemopuk schrieb: > Doch ich wollte ihn nicht mit optionalen Details überfordern. Das ist nicht optional, sondern eine Empfehlung/Ansage Zudem macht es keinen Sinn Nutzer mit falschen Informationen zu füttern, oder sie für zu dumm für die Wahrheit zu erklären.
Hallo, es ist mir gelungen, auch die .map-Datei für den Uno R3 zu erzeugen, aber das bringt uns ja nicht weiter. Ich habe jetzt verstanden, dass die Arduino Uno R4-Welt eine ganz andere ist. Dauert bei mir manchmal etwas länger - hängt wohl mit dem Alter zusammen - auch wenn mich vom allseits beliebten alten Knacker noch ein Jahrzehnt trennt. Viele Grüße Kai
Hallo, bezüglich der Melodien habe ich festgestellt, dass die Art des Zugriffs auf die Daten nicht dafür ursächlich ist, dass Melodie 8 und 9 völlig falsch wiedergegeben werden. Verschiebe ich beispielsweise Melodie 8 an die erste Stelle, so wird diese immer noch falsch wiedergegeben. Auch habe ich die Noten nochmal aus dem Original kopiert. Auch hiermit ändert sich das Verhalten nicht. Viele Grüße Kai
Kai schrieb: > ... Du trittst auf der Stelle, kommst mit deinen "Diagnosen" keinen Millimeter weiter. Was würde ich tun, wenn mein Arduino falsche Töne ausgibt? Ich würde testen, ob wirklich die richtigen Werte in die tone Funktion rein kommen. Würde prüfen ob in dem Tone Gedönse die Berechnungen korrekt sind. Ist das alles korrekt, dann: Mir die Doku/Quellcode zu dem verwendetem Timer zur Gemühte führen. Test Cases bauen um dessen Funktion ausgiebig zu stressen. Grundsätzlich: Irgendwann macht es keinen Sinn mehr an der Oberfläche rum zu prokeln, dann muss man in die Tiefe gehen.
Arduino F. schrieb: > Irgendwann macht es keinen Sinn mehr an der Oberfläche rum zu prokeln, In dem Fall ist die "Oberfläche" ein Brei aus Schlüsselworten, Variablennamen und Sonderzeichen, mit einem Zuckerguss aus Kommentarspalte. Keine Erkennbaren Coding-Rules, und Leerzeichen und Zeilenumbruch werden gemieden wie der Teufel das Weihwasser. Sorry für die harsche Kritik, aber so kann man keinen Überblick über den Code und seine Struktur bekommen. Was im (nicht-vorhandenen) Coding-Style anfängt, setzt sich in den Datenstrukturen — oder vielmehr Nicht-Strukturen fort. Das Array mit den Noten sind einfach nur aneinandergeklatschte Zahlen, statt Strukturierung in einzelne Melodien, die aus Noten und Pausen bestehen. Dementsprechend umständlich wird der Code, da helfen auch keine Kommentare. Dann noch der Zoo von globalen Variablen...
:
Bearbeitet durch User
Hallo Arduino F und Johann, vielen Dank für die aufbauenden Worte - ich betreibe das nur als Hobby und der Minimal-Sketch war zugegeben auch mit der heißen Nadel gestrickt... Nun habe ich mir den Tipp von Arduino F zu Herzen genommen und die Parametrierung von note() kontrolliert. Da war alles in Ordnung - aber der Divider hatte anstelle negativer Werte riesige Zahlen (z. B. 65531). Damit war klar, dass die negativen Werte nicht passen. Fehlerursache war, dass die negativen Werte vom ARM falsch interpretiert werden. Die Lösung war. dass ich das mit read_integer aus dem EEPROM gelesene int16_t für den ARM in ein int32_t wandeln musste. Deshalb funktionierte es auch auf dem Uno R3.... Viele Grüße Kai
:
Bearbeitet durch User
Kai schrieb: > Die Lösung war. dass ich das mit read_integer aus dem EEPROM gelesene > int16_t für den ARM in ein int32_t wandeln musste. Für mich klingt das nach einem nur halb verstandenem Problem. Denn ARM Controller können durchaus auch 16 Bit Integer korrekt benutzen.
Kai schrieb: > naja - der schlechte Code läuft aber auf Mega und Uno R3 seit gut 2 > Monaten problemlos.... nutze doch die bedingte Compilierung und berücksichtige die beiden Zeigergrößen 16bit zu 32bit dann ist der doppelt so große Code kein Problem
Kai schrieb: > dass die negativen Werte vom ARM > falsch interpretiert werden. Diese Sicht auf die Dinge, ist wenig auf Ziel führend. Um es unverblümt zu sagen: Irgendwer ist schlampig mit Datentypen umgegangen. Sowas führt gerne in ein "Undefined Behavior" oder Kurz: UB Und in ein solches UB bist du gestolpert. Bei dir waren es nur schiefe Töne. Aber nächstes mal kann es dir den Rasen mähen, oder ein Regenschauer im Kongo auslösen. Kai schrieb: > ich betreibe das nur als Hobby Spielt keine Rolle. Ob Hobby oder Beruf... Wir(Ich) wollen, dass unsere Programme fehlerfrei laufen. Dazu braucht man etwas Wissen, viel Übung und auch Sorgfalt. Alles keine unerreichbaren Dinge für Leute mit mehr als 2,5 Gehirnwindungen.
Kai schrieb: > das map-File macht mich nicht viel schlauer..... > Kannst du da etwas herauslesen? Ich bin jetzt wieder zu hause, so dass ich es mir anschauen konnte. Am interessantesten ist die .bss Sektion. Dein eigener Code belegt nur wenig RAM, siehe Screenshot. Dort kannst du sehen, dass der Compiler die meisten globalen Variablen weg optimiert hat. Für sie wird kein RAM belegt, sondern CPU Register.
1 | 1 kB für Wire |
2 | 1 kB für Wire1 |
3 | 1.2 kB für _UART1_ |
4 | 1.2 kB für _UART2_ |
5 | 1.2 kB für _UART3_ |
6 | 1.3 kB für USB |
7 | 258 Bytes für ADC |
8 | 104 Bytes für PWM |
Das sind schon 7 kB. Wenn du Programme mit der STM32 Cube IDE generierst sieht es ähnlich aus. Gewöhne dich dran, oder bleibe bei 8 Bit. Beim Arduino Uno (ATmega328) entfällt viel davon, weil: - Nur eine Instanz von Wire existiert - Nur eine serielle Schnittstelle existiert - Die Puffer viel kleiner sind - Die USB Schnittstelle in einem separaten Chip implementiert ist Der ursprüngliche AVR Core ist zwangsläufig stärker auf geringen Speicherbedarf ausgelegt, weil er auf Mikrocontrollern mit nur 1 kB RAM laufen musste.
:
Bearbeitet durch User
Nemopuk schrieb: > Ich bin jetzt wieder zu hause, so dass ich es mir anschauen konnte Was ist das für ein Tool?
Niklas G. schrieb: > Was ist das für ein Tool? Das ist das "amap" Tool, dass auf http://jheyman.github.io/blog/pages/ArduinoTipsAndTricks/#checking-the-linkers-memory-map empfohlen wird. > A very helpful viewer tool for windows and linux is available here > https://www.sikorskiy.net/info/prj/amap/
:
Bearbeitet durch User
Das so viel Speicher für unbenutzte Hardware verschwendet wird, stört euch nicht? Oder werden in dem Dudelding tatsächlich zwei I²C, 3 UARTS, USV und ADC bneutzt?
:
Bearbeitet durch User
Jens M. schrieb: > Oder werden in dem Dudelding tatsächlich zwei I²C, 3 UARTS, USV und ADC > bneutzt? Zumindest, offensichtlich, für die Benutzung vorbereitet. Solange genug Speicher da ist wird das wohl kein Problem sein. Bei Speichermangel kann man sicher eingreifen. Gar, mit Eintrag/Auswahl im Boards Menü der Arduino IDE, wenn man sich etwas Mühe gibt.
:
Bearbeitet durch User
Jens M. schrieb: > Das so viel Speicher für unbenutzte Hardware verschwendet wird, stört > euch nicht? Man muss es wohl hinnehmen, wenn es einfach bleiben soll.
Ein Serial geht übers native USB Die zweite Serielle an den ESP32 Und ja es werden 2 I2C herausgeführt.
Nemopuk schrieb: > Das ist das "amap" Tool, dass auf Cool, danke. Jens M. schrieb: > Das so viel Speicher für unbenutzte Hardware verschwendet wird, stört > euch nicht? Tja, das Arduino-Framework könnte es so umsetzen dass der Speicher nur dann reserviert wird wenn im Code irgendwo die entsprechende "SerialX" -Instanz genutzt wird, auch dann wenn eine ISR im Spiel ist die vom Interrupt-Vektor referenziert wird und die dann die jeweilige Serial-Instanz referenziert. Wird aber offenbar nicht gemacht...
Niklas G. schrieb: > Tja, das Arduino-Framework könnte es so umsetzen dass der Speicher nur > dann reserviert wird wenn im Code irgendwo die entsprechende "SerialX" > -Instanz genutzt wird, auch dann wenn eine ISR im Spiel ist die vom > Interrupt-Vektor referenziert wird und die dann die jeweilige > Serial-Instanz referenziert. Wird aber offenbar nicht gemacht... Der Weg dahin ist quasi nur einen Pullrequest entfernt. https://github.com/arduino/ArduinoCore-renesas Also keine Hemmungen.
Arduino F. schrieb: > Der Weg dahin ist quasi nur einen Pullrequest entfernt. Hab wenig Motivation auf OpenSource-Arbeit weil ich keine Muße für das Hoch-Arbeiten und sich-einen-Namen-Verdienen habe. Als unbekannter Contributor braucht man bei vielen Open-Source-Projekten nicht mit komplexeren Refactorings um die Ecke kommen. Die meisten meiner PRs werden abgelehnt bzw. ignoriert, außer die beim ESP-IDF, die Leute da arbeiten zielorientiert. Keine Lust auszuprobieren wie die Arduino-Leute so drauf sind.
Arduino F. schrieb: > Und ja es werden 2 I2C herausgeführt. Ich meinte nicht "kann man benutzen", sondern "werden benutzt". Ich hätte gedacht, das der Compiler nur die Komponenten einbindet, die auch z.B. durch ein serial.init() benutzt werden. Somit sollte für die nicht benutzten I²C und UARTs z.B. einfach ein "Nulltreiber" benutzt werden sofern erforderlich, der die entsprechenden Register auf "aus" mit minimalem Stromverbrauch und ohne Beeinflussung der anderen Resourcen setzt. Arduino F. schrieb: > Bei Speichermangel kann man sicher eingreifen. Ja ich weiß, nicht benutzter Flash wird wieder vergütet.
Jens M. schrieb: > z.B. durch ein serial.init() Es gibt kein serial.init() sondern ein Serial.begin() und dafür muss Serial vorhanden sein, sonst kein begin(). Und nein, auf keinem Arduino Board muss Serial extra eingebunden werden. Es ist immer vorhanden, wenn das Board die nötige Hardware mitbringt. Ansonsten: Schön, dass du was zum nörgeln gefunden hast. Leider bin ich die falsche Adresse. Auch du darfst hier https://github.com/arduino/ArduinoCore-renesas gerne deine Verbesserungen unterbringen.
Falk B. schrieb: > Arduino F. schrieb: >> Der Arduino Mega hat 256k Flash. > > Die nicht mal 1% der Anwender jemals ausgenutzt haben! Wie sollen Arduino-Nutzer das auch jemals nutzen? Die können nur 2-3 libs einbinden und dann jeweils mit 5 Befehlen, die sie per copy&paste ausm Netz haben, ansprechen. Kein Arduino-Opfer kann kilobyteweise Code selbst schreiben der danach auch irgendwie läuft.
Norbert schrieb: > Anständig aligned müssen sie aber sein, sonst gibt's Saures. Darauf wollte ich gerade anspielen, als ich ein wenig hier im Thread rümgestöbert habe.
Hallo Nemopuk, Arduino F, Niklas, Norbert, Joachim B und Jens M, Nemopuk: > Für mich klingt das nach einem nur halb verstandenem Problem. Denn ARM > Controller können durchaus auch 16 Bit Integer korrekt benutzen. du hast vollkommen recht: mit Zuweisung zu einem int16_t funktioniert es ebenfalls - nur nicht mit einem int. Joachim B: >> naja - der schlechte Code läuft aber auf Mega und Uno R3 seit gut 2 >> Monaten problemlos.... > nutze doch die bedingte Compilierung und berücksichtige die beiden > Zeigergrößen 16bit zu 32bit dann ist der doppelt so große Code kein > Problem entschuldige - verstehe ich leider nicht - kannst du es bitte genauer erläutern? Nemopuk: > Ich bin jetzt wieder zu hause, so dass ich es mir anschauen konnte. Am > interessantesten ist die .bss Sektion. > Dein eigener Code belegt nur wenig RAM, siehe Screenshot. Dort kannst du > sehen, dass der Compiler die meisten globalen Variablen weg optimiert > hat. Für sie wird kein RAM belegt, sondern CPU Register. vielen Dank für deine Analyse - das hilft mir beim Verständnis weiter - ich hatte fälschlicherweise angenommen, dass dies meine Daten sind - hätte ich als erstes ein einfaches Blinkprogramm hochgeladen, wäre mir der erhöhte Speicherbedarf aufgefallen. Arduino F: >> dass die negativen Werte vom ARM >> falsch interpretiert werden. > Diese Sicht auf die Dinge, ist wenig auf Ziel führend. > Um es unverblümt zu sagen: > Irgendwer ist schlampig mit Datentypen umgegangen. korrekt: die Zuweisung zu einem int funktioniert nur auf AVR - für den ARM muss einem int16_t zugewiesen werden. > Sowas führt gerne in ein "Undefined Behavior" oder Kurz: UB > Und in ein solches UB bist du gestolpert. > Bei dir waren es nur schiefe Töne. Aber nächstes mal kann es dir den > Rasen mähen, oder ein Regenschauer im Kongo auslösen. richtig - aber ein gründlicher Software-Test ist mindestens ebenso wichtig und dabei ist das Problem (UB) aufgefallen.... >> ich betreibe das nur als Hobby > Spielt keine Rolle. > Ob Hobby oder Beruf... > Wir(Ich) wollen, dass unsere Programme fehlerfrei laufen. > Dazu braucht man etwas Wissen, viel Übung und auch Sorgfalt. > Alles keine unerreichbaren Dinge für Leute mit mehr als 2,5 > Gehirnwindungen. hast ja recht - aber ich habe nicht absichtlich falsch codiert, sondern mangels vollständigen Verständnisses. Viele Grüße Kai
:
Bearbeitet durch User
Kai schrieb: > entschuldige - verstehe ich leider nicht - kannst du es bitte genauer > erläutern? Ich übersetze es dir mal: Ihm hat den Präprozessor halbwegs verstanden, und meint, diesen Hammer auf alles anzuwenden, was ihm an C++ noch nicht verstanden hat. Völlig unbelastet, von der Tatsache, dass gerade die Vermeidung von Präprozessor Statements eins der Entwicklungsziele in modernerem C++ ist.
Hallo Arduino F, danke für deine Antwort - dann ist das kein möglicher Weg? Eine Frage zu Bluetooth auf dem Arduino Uno R4: ist es wirklich damit nicht möglich, grössere Datenmengen wie z. B. mit dem HC05 an den Controller zu übertragen? Zurzeit verwende ich ein HC05-Modul am 328P bzw. Uno R3, um die Daten mit dem Gerät im Wohnzimer auszutauschen, ohne es aus dem Gehäuse befreien und in meine Bastelecke transportieren zu müssen, was auch fehlerfrei funktioniert. Viele Grüße Kai
Kai schrieb: > dann ist das kein möglicher Weg? Doch, möglich! So wie man auch mit dem Kopf durch die Wand gehen kann, selbst wenn der Mauerer 2m weiter ein Loch gelassen hat. Die Frage ist nicht, ob möglich, sondern ob nötig. Kai schrieb: > ist es wirklich damit > nicht möglich, grössere Datenmengen Der ESP32 kann sehr wohl große Datenmengen übertragen. (soweit mir bekannt) Also ist auch hier die Suche nach dem Engpass und seine Behebung sinnvoll.
:
Bearbeitet durch User
Hallo Arduino F, danke für deine Antwort. Zurzeit habe ich 3 Varianten des Sketches: 1. Uno R3 (bzw. 328P) 2. Mega: 3. Uno R4 und hatte schon mal überlegt, ob ich diese mit konditionierter Programmierung zu einem zusammenfassen könnte, befürchte aber, dass dieser aufgrund des Overheads nicht mehr lesbar ist. Eine weitere Frage zum Datentyp long: ich glaube festgestellt zu haben, dass sich dieser zwischen Uno R3 und Uno R4 unterschiedlich verhält. Hast du hierzu Informationen? Viele Grüße Kai
Kai schrieb: > ich glaube festgestellt zu haben, > dass sich dieser zwischen Uno R3 und Uno R4 unterschiedlich verhält. > Hast du hierzu Informationen? Ich kann, möchte, nicht auf unspezifische Ängste/Vermutungen eingehen. Zeige einen Test, der das belegt, dann schaue ich mir das gerne mal an. Ansonsten, die grundlegenden Datentypen und ihre Verwendung sollte in jedem guten C++ Einsteiger Buch zu finden sein. https://en.cppreference.com/w/cpp/language/types.html
:
Bearbeitet durch User
Hallo Arduino, danke für den Link - ist es somit richtig, dass ein long sowohl auf AVR als ARM 32 bit hat? Ein unsigned long müsste somit den Wertebereich bis 4.294.967.295 haben. Ich habe den Verdacht, dass meine CRC-Berechnung ein Problem verursacht. Diese ermittelt die benötigte Anzahl führenden Nullen und hängt daran die Summe aller Daten als CRC an, so dass sich immer die selbe Anzahl an Ziffern am Ende der Datei befindet:
1 | void add_crc(unsigned long crc){ |
2 | unsigned long check = 0x10; // Mask |
3 | for (byte i = 0; i < 7; i++){ // Check all nibbles |
4 | if(crc < check){Serial.print(F("0"));} // Add leading 0 |
5 | check = check << 4;} // Next nibble |
6 | Serial.print(crc,HEX);} // Add crc |
7 | } |
Viele Grüße Kai
Kai schrieb: > Serial.print(F("0")); Überzogen. Ausreichend: Serial.print('0'); Kai schrieb: > Ich habe den Verdacht, Leider so nicht testbar Kai schrieb: > Diese ermittelt die benötigte Anzahl führenden Nullen und hängt daran > die Summe aller Daten als CRC an, so dass sich immer die selbe Anzahl an > Ziffern am Ende der Datei befindet Viel Prosa, aber keine Fakten Wie wäre es mit Beispieldaten. Was soll raus kommen, wie sieht das Ergebnis stattdessen aus? Kai schrieb: > ist es somit richtig, dass ein long sowohl auf AVR > als ARM 32 bit hat? Wenn du der Referenz nicht vertrauen möchtest, könntest du auch sizeof() befragen, oder die limits.h oder limits nutzen sprintf und seine Brüder schmecken dir ncht?
:
Bearbeitet durch User
Kai schrieb: > mit Zuweisung zu einem int16_t funktioniert es > ebenfalls - nur nicht mit einem int. Liegt vermutlich daran dass die EEPROM Leseroutine sowas ist wie
1 | uint16_t eeprom_read_word (const uint16_t*); |
Wenn der Rückgabewert einem int zugeweisen wird, dann wird zuerst eine unsigned Erweiterung auf die Bitbreite von int gemacht, und erst dann dem int zugewiesen.
1 | int val = (int16_t) eeprom_read_word (addr); |
hingegen wird der 16-Bit Wert sign-extended (wobei man da formal u.U. ein signed Overflow hat). Zu long: Seit über 25 jahren gibt es uint32_t. Warum nicht das verwenden? Außerdem hat dein CRC Code mehr } als {.
:
Bearbeitet durch User
Hallo Arduino F, Arduino F. schrieb: > Leider so nicht testbar > Viel Prosa, aber keine Fakten > Wie wäre es mit Beispieldaten. > Was soll raus kommen, wie sieht das Ergebnis stattdessen aus? du hast vollkommen recht - ich überlege noch, wie ich einen Test-Sketch baue..... Hallo Johann, Johann L. schrieb: > Außerdem hat dein CRC Code mehr } als {. richtig - ich hatte den Schnipsel nach dem Kopieren noch editiert und dabei nicht aufgepasst. Viel Grüße Kai
Hallo Zusammen, ich habe die Datenübertragung nun mit einem Uno R4 Minima getestet und dabei festgestellt, dass sie hier fehlerfrei funktioniert. Der Sketch ist der selbe, wie für den Uno R4 WiFi, jedoch ohne die LED-Matrix. Die Daten kommen kontinuierlich und ohne Stocken herein und anschließend ist die CRC in Ordnung und die erwartete Anzahl von Bytes eingetroffen:
1 | CRC 523E8 OK data-type: melody all 0 end: 8605 bytes: 8605 |
Die angezeigte CRC 523E8 ist also richtig berechnet, da diese mit der von der Übertragung berechneten übereinstimmt. Anschliessend habe ich diesen Sketch wieder in den Uno R4 WiFi übertragen. Hier stockt die Datenübertragung mehrfach. Die kritische Datenlänge beträgt etwa 5200 Bytes. Bis zu dem Erreichen dieser Anzahl funktioniert die Übertragung. Darüber bricht sie ab.
1 | CRC error Checksum file 523E8 Checksum receive 3CAB2 data-type: melody all 0 end: 5693 bytes: 5693 |
Die CRC der Übertragung ist hier deutlich niedriger, da um 3kB Daten fehlen. Viele Grüße Kai
:
Bearbeitet durch User
Arduino UNO R4, als jemand der erfolgreich einen Pull-Request für ArduinoCore-renesas gemacht hat, kann ich Dir sagen, warum der Arduino UNO R4 an manchen Stellen langsam ist. Da sitzt noch eine Software-Schicht dazwischen, die Arduino Klassen rufen Funktionen der Renesas Flexible Software Package (FSP) auf. Diese Library liegt im Arduino Core Repository auch nicht als Source-Code vor, sondern als .lib, sonst würde das Compilieren noch viel länger dauern. Bei meinen ersten Versuchen vor zwei Jahren hat mein Test-Programm für eine SPI Übertragung von 231 Bytes auf dem UNO R4 fünf Mal so lange gebraucht wie das gleiche Programm mit dem gleichen SPI Takt auf einem UNO R3. Das Problem war dann, das die SPI Klasse für ein SPI.transfer(data); nur eine einzige FSP Funktion aufrufen kann, es gibt keine Alternative dazu. Und diese FSP Funktion hat jedesmal die SPI Einstellungen geprüft, die SPI Einheit aktiviert, die SPI Einheit konfiguriert, das Byte verschickt und die SPI Einheit wieder deaktiviert. Darauf habe ich dann die SPI Klasse auf Register-Zugriffe umgeschrieben. Inklusive so Spaß dabei das es ein notwendiges Register gibt das im User-Manual vom Controller nicht dokumentiert ist (oder war), zwar in den Includes enthalten und von FSP verwendet, aber nicht dokumentiert. Ach ja, irgendwo in diesem Thread kam ein Spruch DMA zu benutzen. Wenn es nach mir ginge, dann könnte die UNU R4 SPI Klasse jetzt auch DMA, der Pull-Request wäre damit aber nicht angenommen worden, da die offizielle Arduino API kein DMA unterstützt. Das gleiche oder ein ähnliches Problem werden die anderen Arduino Klassen auch haben, sofern sich da noch niemand erbarmt hat die zu Überarbeiten. Das wurde implementiert und auf Funktion geprüft, da hat sich bei Arduino offenbar vor Veröffentlichung niemand die Mühe gemacht einen Logic-Analyzer zu benutzen und Renesas kümmert das offensichtlich auch nicht. Compilier-Zeit. Da kann ich mich nur der Empfehlung anschließen Platform-IO zu verwenden. Das hat dann auch gleich den Vorteil, dass man Build-Flags setzen kann. Ein Build von meinem Test-Projekt hat hier gerade 2.47s für den UNO R3 und 5.53s für den UNO R4 gebraucht - und das war nur so lange, weil ich vorher ein "Full Clean" gemacht habe. Größe des Builds. UNO R3 -Os RAM: [ ] 3.6% (used 73 bytes from 2048 bytes) Flash: [=== ] 30.7% (used 9890 bytes from 32256 bytes) UNO R3 -O2 RAM: [ ] 3.6% (used 73 bytes from 2048 bytes) Flash: [==== ] 39.1% (used 12598 bytes from 32256 bytes) UNO R4 Minima -Os RAM: [== ] 21.1% (used 6912 bytes from 32768 bytes) Flash: [== ] 18.1% (used 47492 bytes from 262144 bytes) UNO R4 Minima -O2 RAM: [== ] 21.1% (used 6924 bytes from 32768 bytes) Flash: [== ] 20.1% (used 52736 bytes from 262144 bytes) Mega2560 -Os RAM: [ ] 0.9% (used 73 bytes from 8192 bytes) Flash: [ ] 4.1% (used 10518 bytes from 253952 bytes) Mega2560 -O2 RAM: [ ] 0.9% (used 73 bytes from 8192 bytes) Flash: [= ] 5.2% (used 13296 bytes from 253952 bytes) Ja, ist erstmal so, der UNO R4 braucht mehr Speicher. Das liegt aber auch daran, was da noch so an Software mit rein gespült wird. SAMD21 -O2 RAM: [= ] 9.3% (used 3060 bytes from 32768 bytes) Flash: [= ] 9.9% (used 25956 bytes from 262144 bytes) Adafruit Metro M4 -O2 RAM: [ ] 3.7% (used 7192 bytes from 196608 bytes) Flash: [ ] 5.0% (used 26120 bytes from 524288 bytes) ESP32-C3 -O2 RAM: [= ] 5.5% (used 17904 bytes from 327680 bytes) Flash: [== ] 19.5% (used 255964 bytes from 1310720 bytes) STM32 F446 -O2 RAM: [ ] 4.2% (used 5528 bytes from 131072 bytes) Flash: [= ] 5.4% (used 28300 bytes from 524288 bytes) Von weit weg betrachtet immer das gleiche Programm, das läuft auch so mit diesen und noch mehr Controllern. Im Detail macht jeder Arduino Core seine eigenen Faxen und das sind diverse verschiedene Compiler. Solange das Programm in den Controller passt macht das ja auch nichts. Darum nutze ich normalerweise auch -O2 und nicht -Os. RP2040 -O2 RAM: [== ] 16.7% (used 45108 bytes from 270336 bytes) Flash: [ ] 0.2% (used 4182 bytes from 2097152 bytes) Äh ja, da klappt wohl was nicht so ganz. :-)
Hallo Rudolph R, vielen Dank für deinen ausführlichen Beitrag, welchen ich zum Großteil noch verdauen muss. > Compilier-Zeit. > Da kann ich mich nur der Empfehlung anschließen Platform-IO zu > verwenden. Da werde ich mich wohl tiefer einlesen müssen oder kennst du eine einfache Beschreibung, wie man dieses für Arduino einsetzt? Viele Grüße Kai
:
Bearbeitet durch User
Arduino F. schrieb: > Und nein, auf keinem Arduino Board muss Serial extra eingebunden werden. > Es ist immer vorhanden, wenn das Board die nötige Hardware mitbringt. Beim STM32 Core kann man die Serial Instanz konfigurieren: - Vorhanden als UART - Vorhanden als USB-CDC - Nicht vorhanden Außerdem muss man jede weitere UART "manuell" instanziieren. Ich finde das besser. Andererseits hat das viele Leute irritiert. Cyblord -. schrieb: > Kein Arduino-Opfer kann kilobyteweise Code selbst schreiben der danach > auch irgendwie läuft. Eine Menge RAM zu verplempern ist hingegen einfach - vor allem für Leute, die aus der PC Welt kommen.
:
Bearbeitet durch User
Kai schrieb: > ist es wirklich damit nicht möglich, grössere > Datenmengen ... zu übertragen? Wer sagt das, du? Es ist mit Sicherheit möglich, beliebig große Datenmengen zu übertragen. Der Mikrocontroller schränkt dich dabei nicht ein. Kai schrieb:
1 | void add_crc(unsigned long crc){ |
2 | unsigned long check = 0x10; // Mask |
3 | for (byte i = 0; i < 7; i++){ // Check all nibbles |
4 | if(crc < check){Serial.print(F("0"));} // Add leading 0 |
5 | check = check << 4;} // Next nibble |
6 | Serial.print(crc,HEX);} // Add crc |
7 | }
|
Deine Code-Formatierung ist unter aller Sau. kein Wunder, dass du stellenweise selbst nicht durchblickst. Benutze doch bitte wenigstens die Auto-Formatierung deiner IDE, wenn du schon so faul bist. Die macht daraus folgendes:
1 | void add_crc(unsigned long crc) { |
2 | unsigned long check = 0x10; // Mask |
3 | for (byte i = 0; i < 7; i++) { // Check all nibbles |
4 | if (crc < check) { Serial.print(F("0")); } // Add leading 0 |
5 | check = check << 4; |
6 | } // Next nibble |
7 | Serial.print(crc, HEX); |
8 | } // Add crc |
9 | }
|
Und schon wird (in der letzten Zeile) offensichtlich, dass da eine Klammer zu viel drin ist. Wo wird da jetzt etwas addiert?
:
Bearbeitet durch User
Kai schrieb: > Da werde ich mich wohl tiefer einlesen müssen oder kennst du eine > einfache Beschreibung, wie man dieses für Arduino einsetzt? Ich versuchs mal, ich habe schon ewig kein Projekt komplett neu angelegt. Ich benutze das als Extension in VSCode. Nach der Installation hat man erstmal PlatformIO auf der Linken Seite in der Leiste. Und wenn das "PIO Home" nicht direkt aufgeht, dann kann man das über "Open" aus dem "Quick Access" Menü öffnen. Und auf der "PIO Home" Seite gibt es "New Projekt", "Import Arduino Project" und "Project Example". Kann sehr gut sein, dass man da per Default direkt nach der Installation noch nicht weit kommt, genau wie die Arduino IDE nach der Installation auch noch nicht alles kennt. Dann muss man im "Quick Access" Menü oder auf dem "PIO Home" auf "Platforms" drücken und da auf den Reiter "Embedded" wechseln. Da werden die ganzen Platforms für Controller gelistet und es wird auch jeweils angezeigt welche Frameworks die unterstützen. Wenn man eine Platform anklickt bekommt man einen "Install" Button. Wenn man eine Platform im "Installed" Reiter anschaut, dann kann sich dort auch die "Examples" anschauen.
Kai schrieb: > Eine weitere Frage zum Datentyp long: ich glaube festgestellt zu haben, > dass sich dieser zwischen Uno R3 und Uno R4 unterschiedlich verhält. Um solche Unklarheiten zu vermeiden, kannst du die "Exact-width integer types" aus der Datei stdint.h verwenden. Die sind in C standardisiert. https://www.nongnu.org/avr-libc/user-manual/group__avr__stdint.html
Hallo Nemopuk, Nemopuk schrieb: >> ist es wirklich damit nicht möglich, grössere >> Datenmengen ... zu übertragen? > > Wer sagt das, du? > > Es ist mit Sicherheit möglich, beliebig große Datenmengen zu übertragen. > Der Mikrocontroller schränkt dich dabei nicht ein. es ging hier um Bluetooth BLE, von welchem ich las, dass dieser nur für das Übertragen kleiner Datenmengen - wie z. B. Sensordaten - geeignet sei. Grössere Mengen müssten in Chunks aufgeteilt werden. Bisher habe ich noch keine Beschreibung gefunden, wie man dieses ähnlich eines HC05 verwenden kann. Nemopuk schrieb: > Deine Code-Formatierung ist unter aller Sau. kein Wunder, dass du > stellenweise selbst nicht durchblickst. Benutze doch bitte wenigstens > die Auto-Formatierung deiner IDE, wenn du schon so faul bist. ich glaube, dass ich erst recht nicht mehr durchblicke, wenn ich 297kB Quellcode autoformatieren lasse..... Nemopuk schrieb: > Und schon wird (in der letzten Zeile) offensichtlich, dass da eine > Klammer zu viel drin ist. ich hatte bereits oben geschrieben, dass ich beim manuellen editieren im Beitrag nicht aufgepasst hatte. Nemopuk schrieb: > Wo wird da jetzt etwas addiert? in der Senderoutine werden alle gesendeten Bytes aufsummiert. Hier vermutete ich keinen Fehler. Hallo Rudolph, Rudolph R. schrieb: > Ich versuchs mal, ich habe schon ewig kein Projekt komplett neu > angelegt. > Ich benutze das als Extension in VSCode. Vielen Dank für deine Beschreibung - versuche ich in einer ruhigen Minute. Viele Grüße Kai
Kai schrieb: > Grössere Mengen müssten in Chunks aufgeteilt werden Größere Datenübertragungen teilt man sinnvollerweise immer in Chunks auf, sonst muss man im Fehlerfall immer wieder von Vorne beginnen. > Bisher habe ich noch keine Beschreibung gefunden, wie man dieses > ähnlich eines HC05 verwenden kann. Du meinst die UART Emulation (SPP)? Die gibt es bei BLE nicht. Manche Module bieten etwas ähnliches an, das ist dann aber Proprietär und zu anderen Module inkompatibel.
:
Bearbeitet durch User
Hallo Nemopuk Nemopuk schrieb: > Du meinst die UART Emulation (SPP)? Die gibt es bei BLE nicht. schade - ich hatte gehofft, beim Uno R4 WiFi auf das HC05 verzichten zu können. Viele Grüße Kai
Hallo Zusammen, es sieht so aus, als wenn der Uno R4 Minima egal mit welcher Einstellung des seriellen Monitors immer mit 115200 Baud kommuniziert und der serielle Puffer mindestens 254 Bytes groß ist. Die Übertragung von 8605 Zeichen funktioniert problemlos. Im Gegensatz dazu arbeitet der Uno R4 WiFi mit der eingestellten Baudrate des seriellen Monitors. Auch hier scheint der Puffer mindestens 255 Bytes groß zu sein. Nach Änderung von Serial.begin auf 115200 Baud ist das Stocken deutlich kürzer, leider wird die Übertragung immer noch abgebrochen - und zwar bereits nach 4500 Zeichen.. Viele Grüße Kai
Kai schrieb: > Im Gegensatz dazu arbeitet der Uno R4 WiFi mit der eingestellten > Baudrate des seriellen Monitors. Soweit mir bekannt arbeiten beide mit Serial über natives USB, also CDC. Da ist die eingestellte Baudrate völlig egal. Einzig die 1200 Baud haben eine Sonderrolle in der Arduino Welt.
:
Bearbeitet durch User
Hallo Arduino F, bei meinem Uno R4 Wifi ist es nicht so..... wähle ich eine andere Baudrate, gibt es Kauderwelsch. Viele Grüße Kai
Kai schrieb: > bei meinem Uno R4 Wifi ist es nicht so... Das ist bei beiden so! Beide nutzen natives USB. Einzig der Umschalter, den gibts nur beim Wifi https://docs.arduino.cc/resources/schematics/ABX00080-schematics.pdf https://docs.arduino.cc/resources/schematics/ABX00087-schematics.pdf
Hallo Arduino F, Arduino F. schrieb: >> SJ1? > > Nein, U2 und U6. > Aber der hat keinen Einfluss auf die Baudrate. SJ1 ist der Löt-Jumper mit welchem du U2 und U6 umschalten kannst. Ist dieser offen, so ist der USB mit dem ESP verbunden - dieser arbeitet dann als Bridge zum ARM. Viele Grüße Kai
Kai schrieb: > SJ1 ist der Löt-Jumper mit welchem du U2 und U6 umschalten kannst. Ja, ein bisschen kann ich auch Schaltpläne lesen. Wenn Serial über den ESP an USB geht, dann ist der zwischengeschaltete ESP evtl. das Problem bei deiner versagenden Daten Übertragung. Vielleicht solltest du die Brücke mal schließen und dann die Übertragung testen. So wird dann wohl der Wifi genauso stabil wie der Minima laufen.
Hallo Zusammen, @Arduino F: ich möchte den SJ1 des Uno R4 WiFi noch nicht umlöten, da damit vermutlich auch die WiFi-Funktionalität wegfällt und ggf. auch das unschöne Verhalten des Uno R4 Minima hinzukommt, beim Flashen jedes Mal den USB zu trennen und danach neu zu verbinden. um das Problem eingrenzen zu können, habe ich einen Minimal-Sketch erstellt und damit das Verhalten der verschiedenen Boards genauer analysiert - geprüft jeweils mit der selben Test-Datei mit einer Länge von 17210 Bytes. Der Sketch sendet alle 20 Zeichen ein + über den Seriellen Monitor (Damit man das Stocken des Arduino Uno R4 WiFi besser nachvollziehen kann) und am Ende der Übertragung eine Zusammenfassung: 1. Arduino Mega: Kontinuierliche Datenübertragung, der Puffer läuft auf max. 9 Bytes hoch, wird zwischendurch leer, alle gesendeten 17210 Bytes werden empfangen. 2. Arduino Uno R4 Minima: Kontinuierliche Datenübertragung, der Puffer läuft auf max. 255 Bytes hoch, wird zwischendurch nicht leer, alle gesendeten 17210 Bytes werden empfangen. 3. Arduino Uno R4 WiFi: Die Datenübertragung stockt zum ersten Mal nach 255 Bytes, anschließend nach einer größeren Anzahl von Bytes, der Puffer läuft auf max. 9 Bytes hoch, wird zwischendurch leer, es werden max. 11398 Bytes empfangen. Hat einer von euch eine Erklärung für das abweichende Verhalten des Uno R4 WiFi? Viele Grüße Kai PS: die Testdatei habe ich in den Seriellen Monitor kopiert und damit gesendet
:
Bearbeitet durch User
Serial geht beim Uno R4 über USB und hat effektiv keine Baudrate. Die Übertragung findet beliebig schnell statt. Beim Arduino Mega ist es hingegen eine UART Schnittstelle mit Baudrate, die via USB-UART Adapter durch USB getunnelt wird.
:
Bearbeitet durch User
Hallo Nemopuk, vielen Dank für deine Antwort. Ich stellte für den Uno R4 Minima fest, dass es exakt so ist, wie du beschreibst - eine Änderung der Einstellung des seriellen Monitors hat keinerlei Auswirkungen - die Daten werden mit einer festen (hohen) Baudrate gesendet und empfangen. Beim Uno R4 WiFi werden die Empfangs-Daten nicht mehr korrekt angezeigt, wenn ich eine von der Definition des Serial.begin(19200) abweichende Baudrate einstelle. Wie schnell die Sende-Daten ausgegeben werden, konnte ich noch nicht eindeutig ermitteln. Aus der Feststellung, dass der Puffer auf maximal 9 Bytes anwächst, schliesse ich aber, dass die Baudrate ebenso hoch ist, wie beim Mega - nämlich 19200 Baud - da hier der Puffer ebenfalls auf maximal 9 Bytes anwächst. Viele Grüße Kai
:
Bearbeitet durch User
Kai schrieb: > Beim Uno R4 WiFi ist der USB Swich standardmäßig auf den ESP eingestellt. Dieser ist wiederum über UART mit dem Renesas Controller verbunden. Deswegen gibt es eine wirksame Baudrate. Der ESP spielt hier die Rolle des USB-UART Adapters. Dein Hauptproblem ist immer noch, dass du kein vernünftiges Übertragungsprotokoll hast. Du ballerst den Mikrocontroller einfach rücksichtslos mit Daten zu, in der Hoffnung, dass er schnell genug mit kommt. Im vorherigen Thread wurde dir bereits dringend davon abgeraten. Gerade bei USB gibt es kein verlässliches Timing mehr. Deswegen taugt Timing alleine nicht als Übertragungsprotoll.
:
Bearbeitet durch User
Hallo Nemopuk, Nemopuk schrieb: > ist der USB Swich standardmäßig auf den ESP eingestellt. Dieser ist > wiederum über UART mit dem Renesas Controller verbunden. Deswegen gibt > es eine wirksame Baudrate. Der ESP spielt hier die Rolle des USB-UART > Adapters. exakt so ist es beim Uno R4 WiFi Nemopuk schrieb: > Dein Hauptproblem ist immer noch, dass du kein vernünftiges > Übertragungsprotokoll hast. Du ballerst den Mikrocontroller einfach > rücksichtslos mit Daten zu, in der Hoffnung, dass er schnell genug mit > kommt. Im vorherigen Thread wurde dir bereits dringend davon abgeraten. ich verstehe dein Argument vollkommen. Aber welche Abhilfe gibt es? Da es kein Anzeichen dafür gibt, dass der Controller nicht schnell genug ist, kann ich auch keine Maßnahme dagegen treffen. Natürlich wäre es möglich, immer nur ein kleines Paket zu senden. Aber wie groß soll es sein? Meine Feststellung ist, dass beim Arduino R4 WiFi oberhalb einer bestimmten Grenze keine Daten von der UART mehr kommen. Bis dahin hat der Controller immer brav alle Daten abgeholt und dies so schnell geschafft, dass der Puffer nur auf 9 Bytes angewachsen ist. Also hat sich die Hoffnung erfüllt, dass er schnell genug ist.... oder sehe ich das falsch? Viele Grüße Kai
Kai schrieb: > Aber welche Abhilfe gibt es? Die Diskussion hattest du bereits, und schon damals nur ablehnend reagiert. Ich habe besseres zu tun. Du kannst dir ja ein Buch zu Übertragungsprotokollen kaufen. Papier ist geduldiger. Vielleicht findest du die Dokumentation von ZMODEM von Chuck Forsberg. Es ist alt, hat aber seinen Zweck erfüllt.
:
Bearbeitet durch User
Hallo Nemopuk, danke für deine Antwort und den Hinweis auf ZMODEM, welches ich mir jetzt genauer ansehen werde. Ich habe mir die damalige Diskussion noch einmal komplett durchgelesen. Die Quintessenz ist: a) Benutze ein gesichtertes Protokoll oder b) Puffere die Daten im RAM und schreibe dann ins EEPROM. Damals hatte ich nicht genug RAM, weshalb ich hier ablehnend reagierte. Jetzt hätte ich genug RAM, wird aber nichts am Verhalten ändern, da es identisch zu meinem zuletzt geposteten Minimal-Sketch funktioniert. Viele Grüße Kai
:
Bearbeitet durch User
Nemopuk schrieb: > Serial geht beim Uno R4 über USB und hat effektiv keine Baudrate. Ja, nein! Du musst unterscheiden zwischen Minima und Wifi. Die Schaltplane habe ich oben verlinkt.
:
Bearbeitet durch User
Hallo, auch mit dem Sketch von Veit werden max. 11386 Bytes ins RAM geschrieben. Viele Grüße Kai
Wozu hat der RS232-Gott eigentlich RTS und CTS erfunden? Und wenn man die 4 Cent für die Stecker gespart hat (USB-UARTS können das eigentlich alle!) kann man ja auch mit XON/XOFF arbeiten. Das dürfte einfacher sein als ZModem. Oder man reduziert die Sache einfach auf "ey, hörst du?" "Jau" "gut dann haste hier 16 Bytes" "ok, danke. kommt da noch was?", ähnlich wie es viele Bootloader machen. Klappt auch 100%.
Arduino F. schrieb: > Du musst unterscheiden zwischen Minima und Wifi. Du hast Recht. Ich meine den einfachen Uno R4 (Minima). Kai hat das schon richtig erkannt. Beim Wifi Modell hängt es wie gesagt vom Switch ab: 1) Per Default spielt der ESP die Rolle des USB-UART. Da RxD und TxD verwendet werden, gibt es eine Baudrate. 2) Wenn man ihn umschaltet, hängt der Renesas Chip direkt am USB (wie beim Uno R4 Minima). Hier gibt es keine wirksame Baudrate.
:
Bearbeitet durch User
Hallo Zusammen, das Aufteilen der 17212 Bytes großen Datei in 3 Pakete und eine Pause von über 2 Sekunden zwischen dem Senden derselben bringt eine Änderung des Verhaltens: Das Ergebnis der Datenübertragung ist dann fehlerfrei. Daraus folgere ich, dass beim Uno R4 die Übertragung bei Überschreitung eines bestimmten Wertes des Sendepuffers gesperrt und erst bei Unterschreitung eines deutlich niedrigeren Wertes wieder freigegeben wird. Viele Grüße Kai
:
Bearbeitet durch User
Das ist alles Open Source, was sagt denn die Analyse der Arduino Klasse dazu?
:
Bearbeitet durch User
Hallo Rudolph, Rudolph R. schrieb: > Das ist alles Open Source, was sagt denn die Analyse der Arduino Klasse > dazu? wo findet man diese genau? Hat einer von euch bitte einen Link dazu? Wahrscheinlich ist das Verhalten wie folgt: Behauptung: Es gibt für die USB-Interfaces aller Boards eine Beschränkung des Sendepuffers auf ca. 12kB. Der Unterschied, ob diese zu tragen kommt, ist die Baudrate für das Senden und das Abholen vom USB-Interface. Arduino Uno R3 und Mega: Der serielle Monitor sendet und empfängt die Daten an / vom USB-Interface mit der eingestellten Baudrate. Die Daten werden vom Controller genauso schnell abgeholt, wie sie gesendet werden. Der Sendepuffer erreicht seine Grenze nicht. Arduino Uno R4 Minima: Der serielle Monitor sendet die Daten mit hoher Baudrate an das USB-Interface, diese werden vom Controller ebenfalls mit identisch hoher Baudrate abgeholt. Der Sendepuffer erreicht seine Grenze nicht. Arduino Uno R4 Wifi: Der serielle Monitor sendet die Daten mit hoher Baudrate an das USB-Interface, diese werden vom Controller aber nur mit der im seriellen Monitor eingestellten (deutlich niedrigeren) Baudrate abgeholt. Der Sendepuffer erreicht seine Grenze und sperrt die Übertragung. Werden die Daten durch die App in Pakete unterhalb der Grenze aufgeteilt und im Abstand von ca. 2s gesendet:
1 | if (delayCounter > 0) |
2 | { |
3 | string gesamt = textBox1.Text; |
4 | int Ende = dateiLänge - 12000 -1; |
5 | string teil1 = gesamt.Substring( 0 , 6000); |
6 | string teil2 = gesamt.Substring( 6000 , 6000); |
7 | string teil3 = gesamt.Substring( 12000 , Ende); |
8 | |
9 | if (delayCounter == 45) { serialPort1.Write(teil1); } |
10 | if (delayCounter == 22) { serialPort1.Write(teil2); } |
11 | if (delayCounter == 1) { serialPort1.Write(teil3); } |
12 | } |
erreicht der Sendepuffer seine Begrenzung nicht, da der Sendepuffer immer wieder geleert wird. Viele Grüße Kai
Kai schrieb: > wo findet man diese genau? Hat einer von euch bitte einen Link dazu? Auf deinem Rechner! Und hier: https://github.com/arduino/ArduinoCore-renesas Gleiches gilt für quasi alle Arduino, kompatiblen Boards und Libraries.
Hallo Arduino F, vielen Dank für den Hinweis und den Link. Viele Grüße Kai
Kai schrieb: > Arduino Uno R4 Minima: > Der serielle Monitor sendet die Daten mit hoher Baudrate an das > USB-Interface, diese werden vom Controller ebenfalls mit identisch hoher > Baudrate abgeholt. Der Sendepuffer erreicht seine Grenze nicht. Nochmal: Mit nativem USB, klarer CDC, ist es eine virtuelle Serielle. Die interessiert sich nicht für die Baudrate. Da kannst du fantasieren wie du willst Ausnahme: 1200Baud (Arduino Besonderheit) Kai schrieb: > Arduino Uno R4 Wifi: > Der serielle Monitor sendet die Daten mit hoher Baudrate an das > USB-Interface, Auch wieder natives USB, also keine Baudrate auf dieser Seite des "USB-Interface". Wobei das "USB-Interface", in dem Fall, vom ESP32 gestellt wird. > diese werden vom Controller aber nur mit der im seriellen > Monitor eingestellten (deutlich niedrigeren) Baudrate abgeholt. Der > Sendepuffer erreicht seine Grenze und sperrt die Übertragung. Erst bei der UART Verbindung zwischen ESP32 und RA4 spielt dir deine Baudrate rein. Und sie kann nicht "niedriger" sein, weil es vorher keine gibt. Der ESP32 übernimmt die Baudrate aus dem Serial-Monitor. Der RA4 aus dem Serial.begin(); Sind beiden gleich, dann können sie miteinander quatschen. So sollte es sein!
Der ESP32 kann Daten schneller vom PC empfangen, als per UART an den Renesas Chip weiter zu leiten. Wenn der Puffer des ESP32 voll ist, sollte er dies dem PC signalisieren und die Übertragung passend ausbremsen. Vielleicht tut er das nicht, sondern verwirft einen Teil der Daten. Das könnte man gezielt austesten.
:
Bearbeitet durch User
Hallo Arduino F, vielen Dank für deine Antwort. Arduino F. schrieb: > Da kannst du fantasieren wie du willst ich fantasiere nicht, sondern habe mich etwas unglücklich ausgedrückt. Arduino F. schrieb: >> Arduino Uno R4 Wifi: >> Der serielle Monitor sendet die Daten mit hoher Baudrate an das >> USB-Interface, > Auch wieder natives USB, also keine Baudrate auf dieser Seite des > "USB-Interface". > Wobei das "USB-Interface", in dem Fall, vom ESP32 gestellt wird. ich korrigiere meine Aussage in: mit sehr hoher Übertragungsrate. Arduino F. schrieb: > Erst bei der UART Verbindung zwischen ESP32 und RA4 spielt dir deine > Baudrate rein. > Und sie kann nicht "niedriger" sein, weil es vorher keine gibt. ich korrigiere meine Aussage in: mit deutlich niedrigerer Übertragungsrate. Hallo Nemopuk, vielen Dank für deine Antwort. Nemopuk schrieb: > Der ESP32 kann Daten schneller vom PC empfangen, als per UART an den > Renesas Chip weiter zu leiten. Wenn der Puffer des ESP32 voll ist, > sollte er dies dem PC signalisieren und die Übertragung passend > ausbremsen. er bremst den PC leider nicht > Vielleicht tut er das nicht, sondern verwirft einen Teil der Daten. Das > könnte man gezielt austesten. habe ich ja - er läuft an seinen Anschlag und ignoriert die folgenden Daten. Nur wenn man die Daten vor dem Erreichen desselben abholt, hat man eine Chance. Viele Grüße Kai
Ich bin mir sehr sicher, das die USB-Verbindung zum ESP keine Puffer überschreibt. Das wird erst auf der UART-Seite zum Controller passieren, denn die hat kein Handshaking.
Hallo Jens, vielen Dank für deine Antwort. Jens M. schrieb: > Wozu hat der RS232-Gott eigentlich RTS und CTS erfunden? > Und wenn man die 4 Cent für die Stecker gespart hat (USB-UARTS können > das eigentlich alle!) kann man ja auch mit XON/XOFF arbeiten. > Das dürfte einfacher sein als ZModem. > Oder man reduziert die Sache einfach auf "ey, hörst du?" "Jau" "gut dann > haste hier 16 Bytes" "ok, danke. kommt da noch was?", ähnlich wie es > viele Bootloader machen. Klappt auch 100%. XON/XOFF hatte ich bereits probiert - brachte keine Verbesserung. Hallo Rudolph, vielen Dank für deine Antwort. Rudolph R. schrieb: > Das ist alles Open Source, was sagt denn die Analyse der Arduino > Klasse dazu? Ich habe versucht die Quelldateien zu analysieren. Zum Einen die vom Uno R4 Renesas, welche Arduino F freundlicherweise verlinkt hatte und zum anderen die der uno-r4-wifi-usb-bridge und bin teilweise auch fündig geworden. Der Puffer scheint bei allen 512 Bytes gross zu sein, was sich mit meinen Beobachtungen deckt.
1 | ArduinoCore-renesas/cores/Arduino/Serial.h: SERIAL_BUFFER_SIZE 512 |
Jedoch habe ich nur für die USB-Bridge des Uno R4 Wifi weitere Angaben gefunden:
1 | uno-r4-wifi-usb-bridge/UNOR4USBBridge/UNOR4USBBridge.ino: |
2 | SERIAL_USER.begin(115200); |
3 | SERIAL_USER.setRxBufferSize(0); |
4 | SERIAL_USER.setRxBufferSize(2048); |
5 | SERIAL_USER_INTERNAL.setRxBufferSize(8192); |
6 | SERIAL_USER_INTERNAL.setTxBufferSize(8192); |
7 | SERIAL_USER_INTERNAL.begin(115200, SERIAL_8N1, 44, 43); |
8 | SERIAL_AT.setRxBufferSize(8192); |
9 | SERIAL_AT.setTxBufferSize(8192); |
10 | SERIAL_AT.begin(115200, SERIAL_8N1, 6, 5); |
Angenommen die hier angegebenen 8192 Bytes wären die Beschränkung des Schreibpuffers, so deckt sich dies erst einmal nicht mit der Beobachtung, dass ich maximal ca. 12.000 Bytes ohne Pause fehlerfrei empfange. Berücksichtigt man jedoch, dass wärend der Zeit des Schreibens in den Sendepuffer auch Daten abgeholt werden, so würde es doch passen (beim Uno R4 WiFi hole ich die die Daten mit 19200 BAUD ab - somit wird der Puffer in 1s um 4000 Bytes geleert). So richtig kann ich mir noch keinen Reim darauf machen.... Viele Grüße Kai
Hallo Zusammen, 10. Geschwindigkeit dabei fällt mit noch die Frage ein, weshalb der Uno R4 mit 48 MHz Taktfrequenz nicht wesentlich schneller ist, als der Mega oder Uno R3 mit 16MHz? Meine Beobachtung ist, dass die Zykluszeit bei beiden Uno R4 Varianten (mit 10ms) nur ca. 40% niedriger ist, als bei Mega und Uno R3 (16ms). Hat dafür jemand eine Erklärung? Vielen Dank im Voraus und viele Grüße Kai
Kai schrieb: > 10. Geschwindigkeit > > dabei fällt mit noch die Frage ein, weshalb der Uno R4 mit 48 MHz > Taktfrequenz nicht wesentlich schneller ist, als der Mega oder Uno R3 > mit 16MHz? > > Meine Beobachtung ist, dass die Zykluszeit bei beiden Uno R4 Varianten > (mit 10ms) nur ca. 40% niedriger ist, als bei Mega und Uno R3 (16ms). > > Hat dafür jemand eine Erklärung? Bei welcher Software?
Hallo Falk, vielen Dank für deine Antwort - es ist die Zykluszeit meines aktuellen Projektes - ist jetzt auch erst einmal eine Hausnummer zur Abschätzung. Viele Grüße Kai
Kai schrieb: > vielen Dank für deine Antwort - es ist die Zykluszeit meines aktuellen > Projektes - ist jetzt auch erst einmal eine Hausnummer zur Abschätzung. Willst du mich verarschen? Wenn man deine Frage ERNSTHAFT beantworten will, braucht man den Quelltext!
Kai schrieb: > XON/XOFF hatte ich bereits probiert - brachte keine Verbesserung. Die XonXoff kommen aber dann vom Zielprozessor, und dessen Puffer läuft nie in den Xoff, oder? Weil dein Problem die ESP-USB/UART-Bridge ist, die nur wenig RAM hat und dadurch nicht puffern kann. Die könnte den Datenstrom USB-Seitig bremsen, bekommt aber von dem Problem des Ziels nichts mit. Also solltest du probieren, eine erprobte Größe X zu transferieren und dann immer eine Quittung vom Ziel ganz am Ende der Kette zu bekommen, und evtl. auch X anpassen, quasi adaptives Buffer probing. Kai schrieb: > Hat dafür jemand eine Erklärung? Weil Software schneller langsam wird als Hardware schneller wird. Das sind zwei abartig unterschiedliche Architekturen, da nur die MHz zu vergleichen ist sinnlos. Mein Lamborghini hat 247kW, kann aber nur 60km/h. Ist halt nen Traktor, ne? ;)
Hallo Falk, vielen Dank für deine Antwort - nein wollte ich nicht. Meine Frage zielte eher in die Richtung, dass aus einem bestimmten Grund nicht mit einer deutlichen Geschwindigkeitszunahme zu rechnen ist. Viele Grüße Kai PS: du willst nicht wirklich 298 kB Quelltext analysieren?
:
Bearbeitet durch User
Kai schrieb: > vielen Dank für deine Antwort - nein wollte ich nicht. > > Meine Frage zielte eher in die Richtung, dass aus einem bestimmten Grund > nicht mit einer deutlichen Geschwindigkeitszunahme zu rechnen ist. Das kann viele Gründe haben. - Schlechte Software, welche die CPU ausbremst (delays) - der R4 ist mit seinem ARM ineffizienter als ein R3 mit AVR Kern, d.h. die 48 MHz bedeuten nicht automatisch doppelte Rechenleistung - IO Komponenten und Bibliotheken sind lahm (z.B. die SPI-Implementierung beim RP2040 ist grottig!) > > Viele Grüße > Kai > > PS: du willst nicht wirklich 298 kB Quelltext analysieren? Man kann sie aber überfliegen, um möglicherweise grobe Fehler zu erkennen. Wenn deine Software mit delays vollgestopft ist, nützt die schnellste CPU nichts. Wie immer gilt. https://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung#Prinzipien_der_Optimierung
Hallo Jens, vielen Dank für deine Antwort. Jens M. schrieb: > Die XonXoff kommen aber dann vom Zielprozessor, und dessen Puffer läuft > nie in den Xoff, oder? korrekt (schon länger nicht mehr - hatte ich anfangs mal probiert) > Weil dein Problem die ESP-USB/UART-Bridge ist, die nur wenig RAM hat und > dadurch nicht puffern kann. Die könnte den Datenstrom USB-Seitig > bremsen, bekommt aber von dem Problem des Ziels nichts mit. > Also solltest du probieren, eine erprobte Größe X zu transferieren und > dann immer eine Quittung vom Ziel ganz am Ende der Kette zu bekommen, > und evtl. auch X anpassen, quasi adaptives Buffer probing. exakt so stellt es sich dar - ich glaube in den Sourcen gefunden zu haben, dass der Puffer 8192 Bytes groß ist. Teile ich die Datei in 6kB große Teile und warte zwischendurch mit der Übertragung, so funktioniert es. > Kai schrieb: >> Hat dafür jemand eine Erklärung? > Weil Software schneller langsam wird als Hardware schneller wird. > Das sind zwei abartig unterschiedliche Architekturen, da nur die MHz zu > vergleichen ist sinnlos. > Mein Lamborghini hat 247kW, kann aber nur 60km/h. Ist halt nen Traktor, > ne? ;) ok - gute Antwort - es wird in diversen Artikeln davon geschrieben, dass der Uno R4 aufgrund seiner 48 MHz deutlich mehr Rechenleistung zur Verfügung stellt. Viele Grüße Kai
Hallo Falk, vielen Dank für deine freundliche Antwort. Falk B. schrieb: > - der R4 ist mit seinem ARM ineffizienter als ein R3 mit AVR Kern, d.h. > die 48 MHz bedeuten nicht automatisch doppelte Rechenleistung > - IO Komponenten und Bibliotheken sind lahm (z.B. die > SPI-Implementierung beim RP2040 ist grottig!) ok - klingt einleuchtend > Man kann sie aber überfliegen, um möglicherweise grobe Fehler zu > erkennen. Wenn deine Software mit delays vollgestopft ist, nützt die > schnellste CPU nichts. nein - ist sie nicht > > Wie immer gilt. > > https://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung#Prinzipien_der_Optimierung Vielen Dank für den Link, lese ich ersteinmal. Viele Grüße Kai
Kai schrieb: > dass > der Uno R4 aufgrund seiner 48 MHz deutlich mehr Rechenleistung zur > Verfügung stellt. Ja das ist ja auch so. Aber die Software ist halt aufgeblasener und schluckt das wieder weg. Erst Recht wenn sie auf beiden Systemen läuft und keine Rücksicht auf systemspezifische Krankheiten nimmt. Mit einem anderen Aufbau deines Programms lässt sich evtl. noch was machen, und mit besseren Drittprogrammen auch noch. Aber du bindest irgendwelche Libraries ein und bist denen ausgeliefert, und wenn die schlecht gebaut sind oder prozessorspezifisches Zeug enthalten das simuliert werden muss knallt's halt.
Falk B. schrieb: > der R4 ist mit seinem ARM ineffizienter als ein R3 mit AVR Kern, d.h. > die 48 MHz bedeuten nicht automatisch doppelte Rechenleistung Mit Sicherheit nicht, der ARM Cortex-M ist selbst bei gleicher Taktfrequenz im Durchschnitt deutlich schneller. Es handelt sich mit Sicherheit um ein Software -Problem. Man könnte jetzt natürlich noch ewig mit den Arduino Frameworks rum basteln, oder doch mal direkt die Low-Level Treiber des Herstellers nutzen oder direkt auf die Peripherie zugreifen. Damit hat man das Problem wahrscheinlich ziemlich fix umgangen und kann Daten per Serial beliebig schnell empfangen.
Niklas G. schrieb: > Mit Sicherheit nicht, der ARM Cortex-M ist selbst bei gleicher > Taktfrequenz im Durchschnitt deutlich schneller. Sicher? Wo kann man einen Test dazu sehen? Das ist ein echter 32 Bit ARM mit 32 Bit Code, nix Thumb(2). D.h. auch, der Flash muss doppelt mindestens soviel Daten wie der AVR schaufeln. Kann er das? Es gib genügend CPUs, die einen Flaschenhals beim Flash haben (z.B. der PICCOLO) und das nur bedingt durch Cache kompensieren können, vor allem wenn keiner da ist, nur die normale Pipeline. > Es handelt sich mit Sicherheit um ein Software -Problem. Mit sehr hoher Wahrscheinlichkeit.
Niklas G. schrieb: > Man könnte > jetzt natürlich noch ewig mit den Arduino Frameworks rum basteln, oder > doch mal direkt die Low-Level Treiber des Herstellers nutzen oder direkt > auf die Peripherie zugreifen. Damit hat man das Problem wahrscheinlich > ziemlich fix umgangen und kann Daten per Serial beliebig schnell > empfangen. Man könnte auch einfach den Lötjumper durch einen richtigen (oder Micro Schalter) ersetzen.
Falk B. schrieb: > Das ist ein echter 32 Bit ARM > mit 32 Bit Code, nix Thumb(2) Hä? Bin ich im falschen Film? Wir reden immer noch vom Arduino R4, ja? Der basiert auf dem Renesas RA4M1, das ist ein ARM Cortex-M4 und der implementiert die ARMv7M-Variante "T32" von Thumb2, also 16/32bit Code gemischt - aber nicht den reinen 32bit-Code "A32", wie man ihn von Cortex-A oder ARM11 kennt. Aber es ist dennoch ein vollwertiger 32bit-Prozessor (es gibt überhaupt keine 8/16bit ARMs). Die meisten "T32"-Instruktionen (vom Cortex-M4) sind 16bit breit, d.h. genau so breit wie die vom AVR. Die Handvoll 32bit-Instruktionen brauchen i.A. auch nur einen Takt zum Berechnen; das Laden aus dem Flash kann langsamer sein daher implementieren typische Cortex-M4-Mikrocontroller einen Prefetch/Cache. Dafür können die typischen 32bit-Instruktionen halt auch etwas, für das der AVR noch viel mehr Takte brauchen würde. Die großen ARMs mit "A32" Instruction Set, bei denen alle Instruktionen 32bit groß sind, haben sowieso keinen Flash, sondern führen alles aus dem (externen) SDRAM aus, der vom L1-L3 -Cache gepuffert ist... Falk B. schrieb: > Sicher? Wo kann man einen Test dazu sehen? Da findet sich sicher einiges im Netz. Aus meinem eigenen Wissen kann ich sagen, dass die Cortex-M (insbesondere M3/4/7) einen ganzen Haufen Instruktionen haben (viele davon 16bit breit), die viele Dinge in 1 Takt machen, die man auf dem AVR in Software mit vielen einzelnen Instruktionen implementieren muss. Ganz offensichtlich insbesondere 32bit-Berechnungen; der AVR braucht für jede Pointer-Berechnung 2 Takte, das kann der ARM in einem. Sobald es um richtiges "Numbercrunching" geht, schlägt der ARM mit der FPU und den DSP-Erweiterungen den AVR um viele Größenordnungen. Wenn der Flash wirklich der Flaschenhals sein sollte, kann man den Code auch einfach aus dem internen SRAM ausführen. Aber für eine popelige UART-Ansteuerung ist das absolut nicht notwendig. Der Core könnte auch locker mehrere Serialports bei maximaler Datenrate abhandeln.
Kai schrieb: > dabei fällt mit noch die Frage ein, weshalb der Uno R4 mit 48 MHz > Taktfrequenz nicht wesentlich schneller ist, als der Mega oder Uno R3 > mit 16MHz? Ich schrieb ja schon: >Da sitzt noch eine Software-Schicht dazwischen, die Arduino Klassen >rufen Funktionen der Renesas Flexible Software Package (FSP) auf. Ob Dein Programm davon wirklich betroffen ist kann ich natürlich nicht sagen, kommt eben darauf, was es wirklich macht. Aber wie sich das auf den SPI ausgewirkt hat, das habe ich dokumentiert. Die Bilder sind Ausschnitte aus den auch angehängten Logic-Analyzer Mitschnitten. Das ist der gleiche 5 Byte lange SPI Frame, einmal mit dem UNO R3 gesendet, einmal mit dem UNO R4 gesendet mit der SPI Klasse die Juli 2023 zur Verfügung stand. Der SPI Takt war für beide 8MHz. UNO R3: 16.06µs von SPI-Enable auf Low bis SPI-Enable wieder auf High. UNO R4: 60.4µs von SPI-Enable auf Low bis SPI-Enable wieder auf High. Faktor 3,7 für den UNO R4 bei dreifachem CPU-Takt. Der Grund? uint8_t ArduinoSPI::transfer(uint8_t data) hat im wesentlichen das hier gemacht: _write_then_read(&_spi_ctrl, &data, &rxbuf, 1, SPI_BIT_WIDTH_8_BITS); Und diese FSP Funktion prüft die Parameter, schaltet den SPI ein, konfiguriert den SPI, sendet das Byte, wartet auf die Antwort, schaltet den SPI wieder aus und liefert das Ergebnis. Also das meiste was die Funktion macht ist komplett überflüssig. Und so kommt man auf 10,9µs zwischen zwei Bytes für den R4, während der UNO R3 nur 1µs braucht. In Taktzyklen sind das 16 mit dem AVR und 523 mit dem RA4M1. Der Controller ist zwar viel schneller, musste durch die Implementierung ein Vielfaches vom Code für die gleiche Aufgabe ausführen. Die aktuelle R4 SPI Klasse ist meine ich schneller als der R3, aber weder finde ich gerade die Traces dazu, noch den UNO R4 um das noch mal nachzumessen. Und arduino/Serial.cpp? Da war noch keiner wirklich dran, das nutzt immer noch R_SCI_UART_Write(&uart_ctrl, &c, 1); aus der ursprünglichen Implementierung. Suchen wir das doch mal: https://github.com/renesas/fsp/blob/master/ra/fsp/src/r_sci_uart/r_sci_uart.c Das sind 100 Zeilen für R_SCI_UART_Write() um 1 Byte zu schreiben. So Handbremsen sind da bestimmt noch haufenweise in der Software drin. Beim reinen Rechnen ist der RA4M1 ganz sicher viel schneller als der AVR, erst recht mit 32 Bit Werten, aber in den Klassen Richtung Peripherie verpufft das alles, wenn sich da noch niemand drum gekümmert hat.
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.