Forum: Mikrocontroller und Digitale Elektronik Arduino Uno R4: Besonderheiten und Abhilfen


von Kai (ksb)


Lesenswert?

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
von Nemopuk (nemopuk)


Lesenswert?

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.

von Kai (ksb)


Lesenswert?

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
von Nemopuk (nemopuk)


Lesenswert?

Meiner Meinung nach hätte dieses neue Board nicht "Uno" heissen sollen.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

von Jens M. (schuchkleisser)


Lesenswert?

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?

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Jens M. schrieb:
> von 32kB auf 256kB nicht passt,

Der Arduino Mega hat 256k Flash.

: Bearbeitet durch User
von Jens M. (schuchkleisser)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

Arduino F. schrieb:
> Der Arduino Mega hat 256k Flash.

Die nicht mal 1% der Anwender jemals ausgenutzt haben!

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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?

von Falk B. (falk)


Lesenswert?

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!

von Harald K. (kirnbichler)


Lesenswert?

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.

von Kai (ksb)


Lesenswert?

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

von Kai (ksb)


Lesenswert?

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

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

von Kai (ksb)


Lesenswert?

Hallo Arduino F,

vielen Dank für deine Antwort - versuche ich morgen.

Viele Grüße
Kai

von Falk B. (falk)


Lesenswert?

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.

von Kai (ksb)


Lesenswert?

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

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Kai schrieb:
> Jetzt suche ich erstmal den richtigen Ordner für:

Zeigt Arduino dir wenn du die ausführlichen Ausgaben aktivierst.

von Cyblord -. (cyblord)


Lesenswert?

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
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

von Kai (ksb)


Lesenswert?

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

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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

von Kai (ksb)


Lesenswert?

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

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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

von Jens M. (schuchkleisser)


Lesenswert?

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.

von Kai (ksb)


Lesenswert?

Entschuldigung: ich habe natürlich von -g3 auf -g0 geändert

von Kai (ksb)


Lesenswert?

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....

von Kai (ksb)


Lesenswert?

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

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

von Jens M. (schuchkleisser)


Lesenswert?

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.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

von Nemopuk (nemopuk)


Lesenswert?

Ersetze Mundharmonika durch Clarinette und spiele den gleichen Ton. Es 
sind sogar beides Blasinstrumente.

von Kai (ksb)


Lesenswert?

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

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Kai schrieb:
> PROGMEM

Das ganze PROGMEM Gedönse kannste auf ARM vergessen

von Kai (ksb)


Angehängte Dateien:

Lesenswert?

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

von Kai (ksb)


Lesenswert?

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.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

von Nemopuk (nemopuk)


Lesenswert?

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.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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?

von Norbert (der_norbert)


Lesenswert?

Kai schrieb:
> was bedeutet es exakt, dass ich PROGMEM
> auf dem ARM vergessen kann?

* Harvard Architektur
gegenüber
* Von-Neumann Architektur

von Kai (ksb)


Lesenswert?

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
von Kai (ksb)



Lesenswert?

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
von Joachim B. (jar)


Lesenswert?

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.
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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_".

von Kai (ksb)


Lesenswert?

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

von Kai (ksb)


Lesenswert?

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

von Nemopuk (nemopuk)


Lesenswert?

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

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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.

von Kai (ksb)


Lesenswert?

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

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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.

von Jens M. (schuchkleisser)


Lesenswert?

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.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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.

von Kai (ksb)


Lesenswert?

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
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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
von Kai (ksb)


Lesenswert?

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
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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
von Kai (ksb)


Lesenswert?

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

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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.

von Nemopuk (nemopuk)


Lesenswert?

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
von Kai (ksb)


Lesenswert?

Hallo Nemopuk,

naja - der schlechte Code läuft aber auf Mega und Uno R3 seit gut 2 
Monaten problemlos....

Viele Grüße
Kai

von Nemopuk (nemopuk)


Lesenswert?

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
von Kai (ksb)


Lesenswert?

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.

von Kai (ksb)


Angehängte Dateien:

Lesenswert?

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

von Nemopuk (nemopuk)


Lesenswert?

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.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Kai schrieb:
> Ohne das Einbinden des LCD werden keine I2C-Adressen gefunden. Was
> könnte dafür die Ursache sein?

fehlende Pullup

von Nemopuk (nemopuk)


Lesenswert?

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
von Kai (ksb)


Angehängte Dateien:

Lesenswert?

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

von Nemopuk (nemopuk)


Lesenswert?

Kai schrieb:
> Jedoch bekomme ich erst nach dem Einbinden des LCD Adressen angezeigt.

Was genau meinst du mit "einbinden"?

von Kai (ksb)


Lesenswert?

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

von Nemopuk (nemopuk)


Lesenswert?

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
von Kai (ksb)


Lesenswert?

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
von Kai (ksb)


Lesenswert?

Ah - mein Fehler: Wire.begin(); fehlte

von Kai (ksb)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

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.

von Nemopuk (nemopuk)


Lesenswert?

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.

von Kai (ksb)


Lesenswert?

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
von Nemopuk (nemopuk)


Lesenswert?

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
von Jens M. (schuchkleisser)


Lesenswert?

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.

von Nemopuk (nemopuk)


Lesenswert?

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
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

von Jens M. (schuchkleisser)


Lesenswert?

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?

von Nemopuk (nemopuk)


Lesenswert?

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.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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....

von Jens M. (schuchkleisser)


Lesenswert?

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
von Nemopuk (nemopuk)


Lesenswert?

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
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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
von Kai (ksb)


Angehängte Dateien:

Lesenswert?

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

von Kai (ksb)


Lesenswert?

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.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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
von Arduino F. (Firma: Gast) (arduinof)


Angehängte Dateien:

Lesenswert?

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.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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

von Norbert (der_norbert)


Lesenswert?

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.

von Kai (ksb)


Lesenswert?

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.
von Kai (ksb)


Lesenswert?

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

von Nemopuk (nemopuk)


Lesenswert?

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
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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
von Kai (ksb)


Lesenswert?

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
von Nemopuk (nemopuk)


Lesenswert?

Zeige uns dein map File.

von Kai (ksb)


Lesenswert?

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
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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
von Kai (ksb)


Angehängte Dateien:

Lesenswert?

Nemopuk schrieb:
> Zeige uns dein map File.

Hm - im Ordner für Uno R3 finde ich keins....

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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

von Nemopuk (nemopuk)


Lesenswert?

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
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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
von Nemopuk (nemopuk)


Lesenswert?

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.

von Kai (ksb)


Lesenswert?

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

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

von Kai (ksb)


Lesenswert?

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

von Kai (ksb)


Lesenswert?

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

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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
von Kai (ksb)


Lesenswert?

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
von Nemopuk (nemopuk)


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

von Nemopuk (nemopuk)


Angehängte Dateien:

Lesenswert?

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
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Nemopuk schrieb:
> Ich bin jetzt wieder zu hause, so dass ich es mir anschauen konnte

Was ist das für ein Tool?

von Nemopuk (nemopuk)


Lesenswert?

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
von Jens M. (schuchkleisser)


Lesenswert?

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
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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
von Nemopuk (nemopuk)


Lesenswert?

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.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Ein Serial geht übers native USB
Die zweite Serielle an den ESP32
Und ja es werden 2 I2C herausgeführt.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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...

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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.

von Jens M. (schuchkleisser)


Lesenswert?

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.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

von Cyblord -. (cyblord)


Lesenswert?

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.

von Axel R. (axlr)


Lesenswert?

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.

von Kai (ksb)


Lesenswert?

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
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

von Kai (ksb)


Lesenswert?

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

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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
von Kai (ksb)


Lesenswert?

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

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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
von Kai (ksb)


Lesenswert?

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

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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
von Kai (ksb)


Lesenswert?

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

von Kai (ksb)


Lesenswert?

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
von Rudolph R. (rudolph)


Lesenswert?

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. :-)

von Kai (ksb)


Lesenswert?

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
von Nemopuk (nemopuk)


Lesenswert?

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
von Nemopuk (nemopuk)


Lesenswert?

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
von Rudolph R. (rudolph)


Lesenswert?

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.

von Nemopuk (nemopuk)


Lesenswert?

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

von Kai (ksb)


Lesenswert?

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

von Nemopuk (nemopuk)


Lesenswert?

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
von Kai (ksb)


Lesenswert?

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

von Kai (ksb)


Lesenswert?

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

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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
von Kai (ksb)



Lesenswert?

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

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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

von Kai (ksb)


Lesenswert?

Arduino F. schrieb:
> Einzig der Umschalter, den gibts nur beim Wifi

du meinst SJ1?

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Kai schrieb:
> SJ1?

Nein, U2 und U6.
Aber der hat keinen Einfluss auf die Baudrate.

von Kai (ksb)


Lesenswert?

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

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

von Kai (ksb)


Angehängte Dateien:

Lesenswert?

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
von Nemopuk (nemopuk)


Lesenswert?

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
von Kai (ksb)


Lesenswert?

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
von Nemopuk (nemopuk)


Lesenswert?

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
von Kai (ksb)


Lesenswert?

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

von Nemopuk (nemopuk)


Lesenswert?

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
von Kai (ksb)


Lesenswert?

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
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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
von Kai (ksb)


Angehängte Dateien:

Lesenswert?

Hallo,

auch mit dem Sketch von Veit werden max. 11386 Bytes ins RAM 
geschrieben.

Viele Grüße
Kai

von Jens M. (schuchkleisser)


Lesenswert?

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%.

von Nemopuk (nemopuk)


Lesenswert?

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
von Kai (ksb)


Lesenswert?

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
von Rudolph R. (rudolph)


Lesenswert?

Das ist alles Open Source, was sagt denn die Analyse der Arduino Klasse 
dazu?

: Bearbeitet durch User
von Kai (ksb)


Lesenswert?

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

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

von Kai (ksb)


Lesenswert?

Hallo Arduino F,

vielen Dank für den Hinweis und den Link.

Viele Grüße
Kai

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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!

von Nemopuk (nemopuk)


Lesenswert?

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
von Kai (ksb)


Lesenswert?

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

von Jens M. (schuchkleisser)


Lesenswert?

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.

von Kai (ksb)


Lesenswert?

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

von Kai (ksb)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

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?

von Kai (ksb)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

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!

von Jens M. (schuchkleisser)


Lesenswert?

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? ;)

von Kai (ksb)


Lesenswert?

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
von Falk B. (falk)


Lesenswert?

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

von Kai (ksb)


Lesenswert?

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

von Kai (ksb)


Lesenswert?

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

von Jens M. (schuchkleisser)


Lesenswert?

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.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

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.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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.

von Rudolph R. (rudolph)



Lesenswert?

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
Noch kein Account? Hier anmelden.