Okay, Ihr könnt meine folgende Frage gleich mit "Ja, du bist zu dämlich"
beantworten.
Frage: Bin ich zu dämlich mit Arduino und CH32V003 irgendetwas anderes
zu bewerkstelligen als bloß Logikpegel auf einem Pin wackeln zu lassen?
Hintergrund:
Ich möchte mein serielles Bootloader-Board, welches ich jetzt
überarbeitet habe und dessen Vorgängerschaltung und Firmware ich hier
gepostet habe, tatsächlich Arduinotauglich machen (ich arbeite im
Normalfall nicht mit Arduino).
Grundsätzlich kann Arduino Codes compilieren und auch ein Upload in mein
Board durch patchen von platform.txt und boards.txt funktioniert
einwandfrei.
Aber jede etwas erweiterte Funktion scheint nicht zu funktionieren. Ist
der Core von hier:
https://github.com/openwch/arduino_core_ch32
wirklich so fehlerhaft und unvollständig wie es sich mir darstellt oder
mache ich grundlegend etwas falsch.
Für mich stellt es sich so dar:
- class Serial kann nur schreiben, lesen funktioniert nicht
- Interrupthandler funktioniert nicht
- Wire.h bedient i2c nicht korrekt
- SPI.h ebensowenig
Gerade versuche ich so etwas einfaches wie analogRead und das
funktioniert natürlich genausowenig wie analogWrite.
Für die obigen "Probleme" habe ich jetzt eigenständigen Ersatz
geschrieben, der Funktionen bereitstellt, der die Funktionaltät der
Hardware herstellt, aber es ist eben etwas ausserhalb der
Standardklassen und ich weiß nicht ob das Sinn und Zweck der Übung ist,
denn: für jedes SPI-Device, für jedes I2C-Device muß dann eine eigene
"Library" geschrieben werden, weil alle Beispiele aus dem Netz dann
darauf aufbauen (und eben nicht funktionieren).
Momentan habe ich für CH32V003 dann geschrieben SPI-TFT Display,
OLED-Display, TM16xx 7-Segmenttreiber, DS18B20, DHT11, LM75 ... etc.
Irgendwie fühlt sich das an, als ob ich das gesamte Ökosystem neu
aufsetze.
Bin ich zu dämlich?
:-) natürlich dürft ihr das mit "ja" beantworten
Ralph S. schrieb:> Gerade versuche ich so etwas einfaches wie analogRead und das> funktioniert natürlich genausowenig wie analogWrite.
analogRead scheint zumindest implementiert zu sein:
https://github.com/openwch/arduino_core_ch32/blob/main/cores/arduino/ch32/analog.cpp
Vielleicht geht es ja trotzdem nicht, weil es auf einem anderen
Prozessor probiert wurde.
Ich werfe jetzt einfach mal eine Vermutung den Raum: Wahrscheinlich ist
eines der #defines nicht aktiv
Christoph M. schrieb:> Vielleicht geht es ja trotzdem nicht, weil es auf einem anderen> Prozessor probiert wurde.>> Ich werfe jetzt einfach mal eine Vermutung den Raum: Wahrscheinlich ist> eines der #defines nicht aktiv> #if (defined(CH32V20x) || defined(CH32V30x) || defined(CH32V30x_C) ||> defined(CH32V10x) || defined(CH32L10x) || defined(CH32VM00X) )
... sagen wir es einmal so: Der Core ist grundsätzlich irgendwie höchst
unvollständig und höchst buggy. Aus diesem Grund, allerdings erst am
Entstehen: siehe Anhang.
Daraus werde ich dann am We eine weitere, rein spezielle Library für den
CH32V003 machen!
Mittlerweile nutzt man für neue Kontrollerimplementierungen die
Arduino-API:
https://github.com/arduino/ArduinoCore-API
Im Repository gibt es auch eine Kurzanleitung dazu.
Um das Ganze in Griff zu kriegen, muss man aber vermutlich Informatiker
sein.
>> Das ist vollkommen korrekt.
Bitte genau hinschauen. Ein CH32V003 ist kein CH32V20X. Der Ordnername
steht für CH32V003 und drin der Header für CH32V20X. Das kann nicht
richtig sein. Passt für mich nicht. Den Ordner für CH32V20X gibt es ja
extra noch.
Das praktische ist ja, daß vor lauter Platz, den die enthaltene Lizenz
wegnimmt, keinerlei Kommentar in so einer Datei drinstehen darf, wofür
sie genau da ist und welche Einschränkungen sie hat.
Und niemand wundert sich, daß da "Copyright (c) 2017,
STMicroelectronics" drinsteht, obwohl die Datei doch für einen µC von
WCH ist ...
Es ist jedenfalls nicht komplett auszuschließen, daß derjenige, der sie
geschrieben hat, sie aus einer Portierung für CH32V20x kopiert und
einfach vergessen hat, sie nach dem umbenennen anzupassen.
Ob das, was da in den beiden Funktionen pinV32_DisconnectDebug und
pin_SetV32AFPin geschieht, irgendwas macht, was spezifisch für CH32V20x,
aber nicht für CH32V00x ist, müsste sich jemand ansehen, der die
Reference Manuals vorliegen hat und weiß, was der ganze Kram überhaupt
soll.
Ich hab' mit Arduino und dem zugehörigen Schichtkuchen weniger zu tun,
aber ich beschäftige mich unter anderem schon mehrere Jahrzehnte damit,
C-Code von verschiedenen Leuten anzugucken. Es gibt wirkklich viele
Schlampen. Nach der Phase "zurechtgedengelt, bis es fehlerfrei
compiliert und bei einfachen Tests funktionier" entfällt meistens die
Phase "aufräumen", denn das ist ja mühsam ...
Harald K. schrieb:> Ich hab' mit Arduino und dem zugehörigen Schichtkuchen weniger zu tun,> aber ich beschäftige mich unter anderem schon mehrere Jahrzehnte damit,> C-Code von verschiedenen Leuten anzugucken. Es gibt wirkklich viele> Schlampen. Nach der Phase "zurechtgedengelt, bis es fehlerfrei> compiliert und bei einfachen Tests funktionier" entfällt meistens die> Phase "aufräumen", denn das ist ja mühsam ...
Ja, das passiert öfters. Im obigen Fall
Beitrag "Re: CH32V003 und Arduino"
wäre es vielleicht eine gute Übung, die gezeigte ADC-Funktion einfach
mal unterhalb des Komaptibilitätslayers anzuhängen.
Noch eine kleine Randbemerkung: In den ursprünglichen Arduino-API
Funktionen ist analogRead nicht in einer Klasse implementiert.
Christoph M. schrieb:> Noch eine kleine Randbemerkung: In den ursprünglichen Arduino-API> Funktionen ist analogRead nicht in einer Klasse implementiert.
tja, dann habe ich das jetzt anderst gemacht und das analoge Einlesen in
eine Klasse verpackt. Das ganze schön in Arduino-Häppchen, für jeden xyz
eine eigene "Lib".
Hier dann meine im Anhang.
Klasse ADC, aus der für jeden analogen Eingang ein Objekt instanziiert
wird. Es gibt dann nur 2 öffentliche Methoden: read() und
calc_spg(advalue, refwert).
Ich sollte irgendwann mal "in die Pötte" kommen und alle Dinge die für
Arduino und CH32V003 von mir gemacht worden sind, in einer Doku
zusammenschreiben. Hier also "meine Methode", analoges in Arduino mit
CH32V003 einzulesen.
Nächstes wird sein, "analog zu schreiben" (um das in Arduino-Sprech) zu
formulieren, in Wirklichkeit ist das ja eine PWM.
Hallo Ralph,
gehe bitte mit einem besseren Beispiel voran. Zeiger zerfallen als
Parameter, die Länge ist weg. Hier klappt das zufällig, weil print() bis
zum Nullpointer liest. Ansonsten ist sowas gefährlich. Lieber Referenzen
statt Zeiger.
So wäre das besser.
Christoph M. schrieb:> Ralph S. schrieb:>> tja, dann habe ich das jetzt anderst gemacht und das analoge Einlesen in>> eine Klasse verpackt. Das ganze schön in Arduino-Häppchen, für jeden xyz>> eine eigene "Lib".>> Wo wäre es laut Standard-API:> https://docs.arduino.cc/language-reference/en/functions/analog-io/analogRead/
Nur mal so am Rande:
Ich mache zwar im Normalfall so gar nichts mit Arduino und vor ein paar
Monaten hatte ich mich genau wegen DIR damit einmal auseinandergesetzt,
meinen Bootloader und mein passendes Board dazu, unter Arduino gangbar
zu machen.
Allerdings muß man mir, und so dämlich und blöd bin ich dann doch nicht,
nicht aufzeigen, wie ein analogRead in Arduino definiert ist.
Man muß nicht 1000 Klimmzüge machen, um ums Verrecken genau den gleichen
Mist zu haben, dann Arduino standardmäßig vorgibt. Man muß / sollte hier
nicht am Core herumfrickeln, wenn da 1000 Köche den Brei verderben.
Hier setze ich lieber auf das, was garantiert funktioniert und
garantieren funktioniert erst mal nur eines wirklich: Linkerscript,
Compiler und Linker (und so wie es aussieht digitalRead / write und
Serial (hier aber nur schreibend).
Also alles andere was man haben will selbst aufsetzen (was so gar nicht
wirklich Arduino-Style ist, weil: dann kann man es gleich anderst
machen).
Von daher schreibe ich jetzt erstmal alles auf was ich so habe und werde
dann alles "veröffentlichen": Allerdings wird dann zwar die Handhabung
Arduino-Style sein, aber mit vorhandenen Programmen nicht kompatibel
sein.
Vorhanden sind:
- adc (eigene Klasse, hier im Anhang)
- serial als eigene Klasse v003_serial (schreibend und lesend, erbt
Stream von daher funktioniert print und println)
- i2c (eigene Klasse als Ersatz für wire)
- my_printf (abgespecktes sehr kleines, printf, keine klasse)
- colpos farbige Textausgaben und Cursorpositionierung bei
Terminalausgaben
- v003_oled (Klasse für i2c-OLED mit SSD1306 / SSD1315 Controller)
- hx1838 (Infrarotempfänger, keine eigene Klasse, weil Benutzung Timer2
- und auch Timerinterruptbehandlung ist im Core unvollständig)
usgaben und textcursorpositionierung
- ds18b20 (Klasse fürs auslesen eines einzelnen Temperatursensors, evtl.
werd ich das für mehrere Sensoren erweitern)
- BMP280 (eigene Klasse, ein bereits initialisierter i2c wird
vorrausgesetzt)
- charlie20 (Library für 20 charliegeplexte LED's, keine eigene Klasse,
weil wieder Timerinterrupt)
- dht11 (eigene Klasse für diesen -schlechten- Sensor)
- Schieberegister 74HC595 (eigene Klasse)
- HD44780 (unglaublich: nicht einmal das originale Demo funktioniert,
weil das Timing scheinbar komlett daneben ist. Deshalb auch hier eigene
Library mit eigener Klasse. Erbt Stream und von daher funktioniert auch
print und println)
- rtc (für ds3231 / ds1305, eigene Klasse, ein bereits initialisierter
I2C Bus wird vorrausgesetzt).
- SPI-tftdisplay mit st7735 oder st7789 grafikcontroller, Displays von
160x80 bis 320x240 Pixel (eigene Klasse)
- tm16xx (7-Segment Anzeigetreiber, eigene Klasse)
- ws2812 (eigene Klasse)
Demos für LM75 I2C-Temperatursensor, I2C-EEprom, interruptgesteuertem
Blinken, Timernutzung generell.
------------------------
Das nächste ist PWM und Servos.
------------------------
Für den Fall, dass irgendjemand vorab von dem oben genannten "Zeugs"
etwas brauchen kann, sagt bescheid, ich werde das hier posten.
Aber bitte verschont mich damit, welche Syntax Arduino im Originalen
macht. Es nutzt hier nix, etwas kompatibel zu machen, das eher schlecht
als recht funktioniert, nur damit auf jeder Plattform einheitlich die
selbe Syntax herscht, nur um dann festzustellen: Funktioniert nur auf
einer Plattform fehlerfrei: Arduino Uno / Nano mit ATmega328.... bei
allen anderen Dingen zickt es immer irgendwo rum.
Egal was man ausprobiert, sogar mit originalen Uno r4 Platinen.
Aus diesem Grunde gleich eigene Klassen, Methoden und Funktionen...
allerdings dokumentieren muß man es auch (und damit tu ich mich dann
schwer).
----------------------------
Wie gesagt, wenn jemand etwas von obiger Liste benötigt: schreiben, ich
poste das hier dann.
Wochenendlicher Gruß,
Ralph
Ralph S. schrieb:> Allerdings muß man mir, und so dämlich und blöd bin ich dann doch nicht,> nicht aufzeigen, wie ein analogRead in Arduino definiert ist.
Ich finde es ja gut, dass du etwas arduinoartiges machst. Vor langer
Zeit habe ich einmal ähnlich angefangen, eine vereinfachte API
arduinoähnlich für eine MCU zu machen. Mit der Zeit habe ich aber
gemerkt, dass der Sinn eines "Kompatibilitätslayers" die Kompatibilität
ist. Bei analogRead ist das noch relativ überschaubar, aber sobald man
die I2C Funktionen implementiert, wird das schon schwieriger.
Veit D. schrieb:> So wäre das besser.>> Stream &cout {Serial};> void textnvalue(Stream &out, const char (&s1)[], const int16_t value,> const char (&s2)[], const bool mode)> {> out.print(s1);> out.print(' ');> if (mode)> {> out.print(value / 100);> out.print(".");> out.print(value % 100);> }> else> {> out.print(value);> }> out.print(' ');> out.println(s2);> }> textnvalue(cout, …> odervoid textnvalue(Stream &out, const char (&s1)[], const int16_t> value, const char (&s2)[], const bool mode)> {> char buffer[32]; // anpassen> if (mode) {> snprintf(buffer, sizeof(buffer), "%s %d.%02d %s", s1, (value/100),> (value%100), s2);> }> else {> snprintf(buffer, sizeof(buffer), "%s %d %s", s1, value, s2);> }> out.println(buffer);> }
Okay, die erste Variante kann ich einsehen (und finde ich auch recht
"elegant"), die zweite Variante ist genau das, was ich auf einem
ch32v003 vermeiden möchte: snprintf schluckt für die Verhältnisse eines
ch32v003 (nur 16384 Byte Flash insgesamt) ungehörige Mengen Flash. Zu
diesem Zweck habe ich ja auch extra ein abgespecktes printf, in den
Demos vollte ich mein eigenes printf vermeiden und deshalb die Krücke
mit textnvalue.
Die Frage ist, ob ein "üblicher" Arduino Nerd das hier:
1
Stream &cout {Serial};
versteht.
Aber im Grunde gehts ja um den ADC .... und nicht um die Ausgabe!
Ralph S. schrieb:> Die Frage ist, ob ein "üblicher" Arduino Nerd das hier:> Stream &cout {Serial};>> versteht.
Nicht am ersten Tag...
Aber das Streaming ist schon recht verbreitet.
Wichtiger ist eigentlich, dass Serial von (über Stream) Print erbt.
Ralph S. schrieb:> Die Frage ist, ob ein "üblicher" Arduino Nerd das hier:Stream &cout> {Serial};
Das Ziel des Arduino-Frameworks ist maximale Verständlichkeit und
einfachste Benutzbarkeit. Der gezeigte Code erfüllt diese Bedingungen
nicht und ist deshalb ungeeignet.
Hier hat sich auch jemand mit der Arduino Lösung rumgeärgert und
es doch noch irgendwie zum "laufen" gebracht.
Nur mal so und nebenbei für die mitlesenden Arduino Nerds:
https://www.elektronik-labor.de/Projekte/CH32V2.html
Christoph M. schrieb:> Ralph S. schrieb:>> Die Frage ist, ob ein "üblicher" Arduino Nerd das hier:Stream &cout>> {Serial};>> Das Ziel des Arduino-Frameworks ist maximale Verständlichkeit und> einfachste Benutzbarkeit. Der gezeigte Code erfüllt diese Bedingungen> nicht und ist deshalb ungeeignet.
Was ist das denn für eine schwachsinnige Aussage? Sowas bringt mich von
0 auf 100 auf die Palme. Überlege einmal was du da schreibst. Das passt
vorn und hinten nicht zusammen. Frage dich einmal was der normale
Arduino User davon sieht. Der guckt nicht einmal den Header an. Und das
soll dann laut deiner Meinung Grund genug sein schlechten bzw.
problematischen Code von einem selbst zu schreiben? Ich bitte dich. Das
kann nur Unsinn werden. Ich hoffe du regst dich nie über Arduino im
allgemeinen auf, sonst schmiere ich dir das jeden Tag aufs Brot.
Im Gegenteil, man könnte noch ein Funktion-Template daraus machen um die
Länge für irgendwas verarbeiten zu können. Zum Bsp. falls man snprintf
verwendet die optimale lokale Buffergröße anzulegen. Auch das würde der
normale Arduino User der diese Funktion einfach nur verwendet nicht
bemerken, aber dem Programmierer der Funktion schreibt, gibt es alle
Möglichkeiten in die Hand. Letzteres hat immer Vorrang. Immer!
Und wenn es dann interessierte Arduino User gibt, die mehr machen wollen
wie nur das Framework benutzen, die sehen dann wie es andere richtig
bzw. richtiger (bin auch nicht perfekt) geschrieben haben und können
dann selbst nachforschen oder Bücher lesen oder was auch immer um in die
Programmierung einzusteigen.
Es jedenfalls kein einziger Grund dabei diesen Leuten guten Code
vorzuenthalten bzw. umgekehrt schlechten Code zu servieren. Kein
Einziger!
Falls du der Christian bist mit dem ich schon im Biergarten saß, dann
müssten wir dieses Jahr darüber reden. :-)
Das war mein Sonntag-Plädoyer.
Ralph S. schrieb:> ... die zweite Variante ist genau das, was ich auf einem> ch32v003 vermeiden möchte: snprintf schluckt für die Verhältnisse eines> ch32v003 (nur 16384 Byte Flash insgesamt) ungehörige Mengen Flash.
Kann ich nachvollziehen. Das Problem kenne ich mit dem ATtiny412. Für
das Programm ist Platz genug. Zum bequemen Debuggen ist alles zu wenig.
Veit D. schrieb:> Ralph S. schrieb:>> ... die zweite Variante ist genau das, was ich auf einem>> ch32v003 vermeiden möchte: snprintf schluckt für die Verhältnisse eines>> ch32v003 (nur 16384 Byte Flash insgesamt) ungehörige Mengen Flash.>> Kann ich nachvollziehen. Das Problem kenne ich mit dem ATtiny412. Für> das Programm ist Platz genug. Zum bequemen Debuggen ist alles zu wenig.
:-) jetzt bin ich etwas "abgelenkt" von den eigentlichen Dingen, die ich
machen möchte.
Dein Vorschlag mittels stream etwas auszugeben ist natürlich absolut
berechtigt, andererseits liest print nun halt wirklich bis zum Zerobyte.
Mir war/ist die Ausgabe mittels print / println viel zu "dämlich" und zu
"Zeilenintensiv", vor allem geht da Übersicht verloren von dem, was man
eigentlich zeigen möchte.
Abgesehen davon dass ich Arduino immer nur für andere verwende, habe ich
deshalb ma mein eigenes, sehr abgepecktes printf, innerhalb Arduino
(sehr sehr kleiner Flashbedarf).
Da ich das nun aber in einem Demo zu bspw. ADC nicht verwenden möchte -
es erfordert dann eben das Einbinden meiner printf-Library (ich tu mich
immer noch schwer mit dem Begriff "Library" hinsichtlich den
Arduino-Libraries), was ich vermeiden möchte.
Hm, jetzt bin ich am überlegen, ob man so etwas wie textnvalues dann, um
das instanziieren eines Streams zu vermeiden, vllt. besser in ein Makro
packt (und den originalen Aufruf von mir dan beibehält) ?!?
Aber.... :-) ich werde mir das mit dem Stream zu Herzen nehmen und für
meine zu erstellende Dokumentation zu dem ganzen Sermon (den ich
hoffentlich wirklich mache) mit aufnehmen. Zumindest ist das mal auf
meiner ToDo Liste
ich hätte vermutet es bleibt gleich, weil der Parameter out nur
durchgereicht wird. Stream ist hierbei der Datentyp.
Die vielen print Zeilen nerven manchmal nicht nur dich. Deswegen gibt es
eine gern verwendete Streaming Klasse.
https://github.com/janelia-arduino/Streaming
Wegen deiner Print Klasse. Du kannst gern deine Printklasse verwenden,
ist kein Problem, du solltest nur, ich nenne es einmal
"Funktionskompatibel" bleiben mit dem Interface. Wenn es nicht alles
"drucken" kann was möglich wäre, geht das laut meiner Meinung nach auch,
muss dann eben in der Doku erwähnt werden, dass auf Grund von zu wenig
Flash nicht alles möglich ist. Wenn du eine Möglichkeit siehst Flash
einzusparen und musst deswegen die "Funktionskompatibilität" verlassen,
dann ist das eben so.
Thema Makros. Die sparen bestimmt durch Präprozessor Ersetzung Flash
ein. Nur wird man an einen Punkt kommen ab dem man nicht mehr
durchblickt und Fehler nicht mehr sieht. Man hat auch in C++ viele
Möglichkeiten allein schon mit constexpr. Für eine Funktion verwendet
kann alles zur Compile-Time ausgewertet werden, muss es jedoch nicht.
Man muss zusehen das alle Parameter Compile Time konstant sind. Ähnlich
wie mit Makros, nur das bei Makros weniger Prüfungen durchlaufen werden.
Das sind alles so viele Grundsatzentscheidungen, da sollte man sich Zeit
nehmen. :-)
Nochwas, weil ich das gerade sehen.
1
void loop()
2
{
3
uint16_t count = 0;
4
uint16_t temp;
5
while(1)
6
{
7
temp= ntc_gettemp(ntc1.read());
8
textnvalue("\rCounter: ", count, " | ", 0);
9
textnvalue("Temp.: ", temp, " oC", 1);
10
count++;
11
delay(1000);
12
}
13
}
loop() ist in Arduino die while() Schleife.
setup() ist das in der main() bis zur while().
count und temp entweder lokal static machen oder noch besser global.
temp ist in deinem Fall in der loop lokal und nicht initialisiert.
Vermutlich nur vergessen. ;-)
Hallo Ralph,
ich möchte dir nicht auf den Keks gehen oder klugsch. oder so. Habe
nochmal genauer hingeschaut und mir gehts wirklich darum mit besseren
Bsp. voranzugehen, weil in den Arduino IDE Bsp. schlummern mir nicht
gefallende zu viele #defines etc. rum und wir sagen das auch im Arduino
Forum fast wöchentlich jeden Neuling der zu uns findet. :-)
Nochmal zu deinem Bsp.
count global machen (ohne = 0;)
uint16_t count;
und dann
1
void loop()
2
{
3
const uint16_t temp = ntc_gettemp(ntc1.read());
4
textnvalue("\rCounter: ", count, " | ", 0);
5
textnvalue("Temp.: ", temp, " oC", 1);
6
count++;
7
delay(1000);
8
}
und wenn man so richtig gut sein möchte, schreibt man die erste Zeile
1
const uint16_t temp {ntc_gettemp(ntc1.read())};
Dann finden noch Datentyp- und Bereichsüberlaufprüfungen statt.
Ist wirklich nur gut gemeint. Ist dein Code, kannst schreiben wie du
möchtest. Falls temp noch weiter Verwendung finden soll, dann natürlich
global.
Grüß dich Veit,
nein, du gehst mir nicht auf den Keks. Grundsätzlich bin ich dankbar für
die Arduino-Sichtweise (und ich überdenke meine Ansätze, auch wenn ich
deine Meinung oder Sichtweise nur teilweise teile).
Man merkt mir auch an, dass ich bisweilen sehr "oldschool" unterwegs bin
und mich manchen Dingen (leider) hartnäckig verschließe, auch wenn sie
ihre Gründe haben und bisweilen besser sind.
Globale Variable lassen sich nicht immer vermeiden, aber dennoch
versuche ich sie so wenig wie möglich zu verwenden.
Was ich im Moment mit Arduino mache, mache ich für mich (sorry, wenn ich
das so sage, aber ich würde für mich oder auch dienstlich Arduino nicht
einsetzen). Auch wenn viele jetzt die Nase rümpfen werden, bei Arduino
(mit ATmega8, später ATmega328) hat mir vor allem der Bootloader und die
günstige Hardware gefallen, die aber auch nativ mit AVR-GCC, AVRDUDE und
Makefiles zu bedienen war / ist. Mehr aber ehrlich gesagt nicht.
Also habe ich für den CH32V003 eben auch einen seriellen Bootloader
geschrieben. Die Hardware siehst du im Bild im Anhang. Das ganze ist
vorrangig für meine Lehrlinge gedacht, die in der Schule mit Arduino
(und ganz schlimm mit Blockly) umgehen müssen und dafür zu je 5 Personen
sich eine SenseBox teilen müssen. Als Ausbildungsprojekt lernen sie hier
dann auch das SMD löten und "basteln" sich ein Nano-Board mit CH32V003
zusammen, für die ich jetzt die Libraries schreibe.
Natürlich verstehe ich das Anlegen lokaler Variable innerhalb des Codes,
bspw.
1
for (int i = 0; i< 10; i++)
Weil hier der Compiler selbst entscheiden kann, ob er die Variable im
Ram anlegt oder ob ein Register frei ist, die er als Laufvariable nutzen
kann.
Dennoch mag ich das nicht (warum auch immer) und habe in einer Funktion
/ Methode lieber ein für die gesamte Funktion gültige Variable i.
Im Falle von Arduino finde ich (sorry) void loop() fürchterlich, wird
diese doch in einer function main eben in der Schleife aufgerufen.
Inhalte lokaler Variablen gehen hier logischerweise verloren und sie
müssen alle static gemacht werden oder sind global.
Aus diesem Grund, wenn du dir das erste Demo genau ansiehst, mache in in
void loop genau das, was ich mit .c oder .cpp Sourcen auch mache, meine
"loop" ist in eine Endlosschleife while(1) { code } eingebunden so dass
die void loop niemals verlassen wird. Genau so, wie ich das im
Embedded-Bereich eben mache, wenn ich das ausserhalb von Arduino mache.
Deine Einwände habe ich "in mich aufgenommen" und werde das so
überdenken. Ein
1
const uint16_t temp = ntc_gettemp(ntc1.read());
funktioniert in deiner void loop() nur deshalb, weil diese Funktion vom
Arduino-Framework permanent neu aufgerufen wird und in die loop immer
wieder neu eingetreten wird.
Ich werde das so, den Auszubildenden auch mitteilen. Dieses Vorgehen ist
aber AUCH eines der Gründe, weshalb mir Arduino nicht soooo sonderlich
gut gefällt und ich verwende dann Dinge, wie ich sie auch in reinem C
oder C++ verwende.
Im Falle des textnvalues habe ich mich entschlossen das ganz fallen zu
lassen und in den Beispielprogrammen zu den Libraries, an denen Ausgaben
gemacht werden, egal ob auf Displays oder auf UART, mein abgespecktes
printf .... namentlich my_printf einzusetzen. Die Demos müssen demnach
einen Zugriff auf diese Library my_printf haben (auch wenn ich weiß,
dass man unter C++ - Arduino ist ja nichts anderes - eigentlich cout
verwendet).
Grundsätzlich bin ich der Meinung, dass C++ auf Leistungsschwachen
Mikrocontrollern wie bspw. AVR oder in meinem Falle jetzt CH32V003 ein
C++ zu viel Overhead hat und deshalb diese Chips doch besser mit C
bedient sind. C++ setze ich auf PC (in Verbindung mit QT5 ein) oder auf
leistungsstarken Mikrocontrollern ab STM32F4 oder auch H7.... ein-
zweimal auch auf einem STM32F030CCt (hat aber wenig RAM) und einem
STM32F103CCT (schon eher, aber alt). Die haben dann wenigstens 256 kByte
Flash und der Overhead von C++ ist hier zu verkraften.
Wahrscheinlich treffe ich Deine Meinung nicht, aber ich denke, man darf
auch unterschiedlicher Meinung sein. 2 hochinteressierten Lehrlingen
(aber noch nicht weit fortgeschritten) habe ich die unterschiedlichen
Realisierungsweisen gezeigt und deine - zugegeben sehr profesionellen -
Äußerungen haben sie nicht auf Anhieb verstanden.
Zur Schaltung, weil hier auch manche (nicht in diesem Forum) angemerkt
haben, dass die Resetschaltung hierfür "befremdlich" aussieht:
Der CH32V003 hat eine eigene Bootloader-Section, die NICHT in den
Firmwareflashbereich hereinragt. Somit sind die vollen 16384 Byte Flash
für die Firmware verfügbar. Die Bootloader-Section ist 1920 Byte groß
und wird, wenn die Optionbytes gesetzt sind, bei einem PowerOn
angesprungen. Und nur bei einem PowerOn. Für meine Schaltung ist das
"dämlich", weil ein Resetimpuls an nrst zwar das Userprogramm neu
startet, aber NICHT in den Bootloader springt. Aus diesem Grund habe ich
ein einfaches PushPull-Register gebaut, das dem V003 kurzfristig die
Spannung wegnimmt und somit den gesamten Chip neu startet und in den
Bootloader springt (wenn ein Impuls auf rts des CH340 Chips kommt).
Ursprünglich hatte ich hierfür einen einzelnen PNP vorgesehen gehabt.
Dieses hatte den Nachteil, sollte die Betriebsspannung hierüber
abgeschaltet werdeb, aber eine Peripherieelektronik an den Chip
angeschlossen sein, es vorkommen kann, dass der V003 über einen GPIO mit
Spannung fremdversorgt wird und der gesamte Chip nicht neu gestartet
wird.
Im Anhang auch mein (sehr) abgespecktes printf, das ich hier auch mit
dem Arduino verwende und mir die (unsägliche) Sache mit langen Reihen
von Serial.print erspart
Hallo Ralph,
sehr schön das du sowas mit Lehrlingen machst. :-)
Eine kurze Nachfrage bevor ich darauf antworten möchte.
> 2 hochinteressierten Lehrlingen (aber noch nicht weit fortgeschritten)> habe ich die unterschiedlichen Realisierungsweisen gezeigt und deine -> zugegeben sehr professionellen - Äußerungen haben sie nicht auf Anhieb> verstanden.
Ging es dabei um die Funktionsparameter oder wegen der loop() /
while(1)?
die Funktionsparameter haben sie nicht verstanden, die loop nach
Erklärung, dass diese Funktion in einer nicht sichtbaren funktion main
in einer endlosschleife aufgerufen wird:
1
int main(void)
2
{
3
loop();
4
}
und dass hier loop nur eine normale Funktion aus Sicht von C++ ist, die
eben lokale Variable wieder "vergißt" wenn sie nicht static sind.
:-) hier war dann "Erklärungsbedarf", dass es außerhalb von Arduino ohne
eigenes zutun keine Funktion loop gibt und dass die Funktion, die in
einem Programm beim Start des Programms "main" heißt.
Auch wenn dich das vielleicht ärgert, einer meinte in der Art: "wozu
braucht man dann noch Arduino" (ich habe meine Toolchain gezeigt).
Meine Antwort war, dass es für Arduino eine Unmenge an fertigen
Beispielen gibt und der Einstieg sehr schnell ist und ein installieren
einer Toolchain nicht notwendig ist. Einstecken und geht!
Für Funktionsparameter:
Ich bin erst einmal froh, dass, zumindest einige, den Unterschied
zwischen call by reference und call by value verstehen!
aus lauter Jux und Dollerei habe ich jetzt mein my_printf und v003colpos
auf avr losgelassen und prompt funktioniert es nicht, weil ich type int
verwende (und die auch als 32-bit behandle), die aber auf avr nur 16 bit
lang sind. eine explizite angabe von int32_t für alle bisher int angaben
macht my_printf und v003colpos auch mit avr kompatibel.
Ralph S. schrieb:> Grundsätzlich bin ich dankbar für> die Arduino-Sichtweise (und ich überdenke meine Ansätze, auch wenn ich> deine Meinung oder Sichtweise nur teilweise teile).>> Man merkt mir auch an, dass ich bisweilen sehr "oldschool" unterwegs bin> und mich manchen Dingen (leider) hartnäckig verschließe, auch wenn sie> ihre Gründe haben und bisweilen besser sind.>> Globale Variable lassen sich nicht immer vermeiden, aber dennoch> versuche ich sie so wenig wie möglich zu verwenden.
Übrigens: Ein paar der syntaktischen Eigenheiten der Arduino-API sind
der Kompatibilität mit Processing geschuldet. Mit Processing kann man
z.B. Daten vom Arduino Visuallisieren oder eine einfache GUI erzeugen,
mit der man die Arduinos steuern kann.
Processing ist eigentlich Java und nur bedingt kompatibel mit der C++
Seite von Arduino. Aber man hat eine gewisse Kompatibilität wie z.B.
Hallo Ralph,
Lokale vs. globale Variablen. Ja man sollte wenn immer möglich lokale
vorziehen. Nur in der Mainloop macht das für mich keinen Sinn, wenn sie
static sein müssen. Dann kann man sie auch gleich global machen.
> Natürlich verstehe ich das Anlegen lokaler Variable innerhalb des Codes, bspw.>
1
> for (int i = 0; i< 10; i++)
2
>
> Weil hier der Compiler selbst entscheiden kann, ob er die Variable im> Ram anlegt oder ob ein Register frei ist, die er als Laufvariable nutzen> kann.
Hier verstehe ich dann wiederum nicht, warum du i nicht immer lokal für
for() machst. Das ist sehr fehlerträchtig.
Gut, die Marotte wirst du wohl nicht mehr rausbekommen. :-) :-)
Kommen wir zur Arduino loop. Ich denke hier liegt ein großes
Missverständnis vor.
Die Bedeutung von setup() und loop() ist eigentlich, für mich, mehr
eindeutig wie der klassische Aufbau mit main und while. Aber gut, ist
Ansichtssache. Geschenkt. Kommen wir zum Kern.
In deiner demo.ino gehört alles zwischen
loop() {
und
while(1)
in setup().
Dann ist die überflüssige while(1) in der loop weg. Ansonsten ist deine
loop-while Programmierweise kurz gesagt wirklich etwas eigenartig und
würde ich Lehrlingen auch so nicht zeigen, weil es nirgends so steht und
ehrlich gesagt auch keinen Sinn macht.
Lehrlinge:
> und dass hier loop nur eine normale Funktion aus Sicht von C++ ist, die> eben lokale Variable wieder "vergißt" wenn sie nicht static sind.
Eine non static lokale Variable in while(1) wird von der Wirkungsweise
genauso vergessen wie in loop. Entweder wird sie immer neu initialisiert
oder bekommt einen Zufallswert zugewiesen. Das heißt auch in while(1)
muss man static verwenden, wenn der Wert erhalten bleiben soll.
Wenn sie call by reference vs. call by value verstanden haben, dann sind
sie doch schon einen großen Schritt weiter.
Wenn dich setup() und loop() stören, dann musst du diese nicht
verwenden. Du kannst in der Arduino IDE genauso gut
1
intmain(){
2
...
3
while(1)
4
{
5
...
6
}
7
}
verwenden. Und wenn du sowieso eigene Libs schreibst, dann fällt damit
auch der gesamte Basis Overhead vom Framework weg. Du bist damit auf
dich mit allen allein gestellt und nutzt die IDE nur noch zum
einfacheren flashen des Controllers.
> Auch wenn dich das vielleicht ärgert, einer meinte in der Art: "wozu> braucht man dann noch Arduino" (ich habe meine Toolchain gezeigt).
Keine Sorge, dass ärgert mich nicht. Ich kann mit und ohne Arduino IDE
programmieren.
Genau das meinte ich mit #defines
1
// Farbzuordnungen der EGA-Farben zu den Farbnummern
2
#define black 0
3
#define blue 1
4
#define green 2
5
#define cyan 3
Das ist in C++ alles Datentyp sicher zur Compile Time mit
constexpr uint8_t farbe {1};
Oder du hast dich noch nicht entschieden ob du C oder C++ programmierst.
:-)
Deine #define Konstanten cnt_speed bis yofs wären bei mir auch constexpr
… Compile Time Konstanten mit Datentyp.
Irgendwo hatte ich noch gesehen das du bool selbst definierst. Muss du
nicht, bringt die Toolchain schon mit.
Damit höre ich auch auf an der Stelle. Sonst schreiben wir Ellenlange
Seiten über jedes Detail und hilft niemanden weiter. Ich wünsche dir auf
jeden Fall jederzeit interessierte Lehrlinge, weil das ist etwas schönes
wenn jemand zuhören möchte und auch mit Fragen bohrt wo man erstmal
überlegen muss. In diesem Sinne, bleib so nett.
Grüß Dich Veit,
erstmal Danke für den Kommentar. Nur um evtl. Mißverständnisse
auszuräumen, ich mache mit Arduino eigentlich (und nicht nur eigentlich)
nichts.
Ich bin - gebe ich zu - schon ein Verfechter von klassisch C oder C++.
Mit Arduino bin ich derzeit nur deshalb beschäftigt, um zum einen
aufzuzeigen, dass mit meinem Bootloaderboard Arduino genauso gut umgehen
kann, wie mir "normalem" C oder auch C++.
Von daher bin ich "nur" damit beschäftigt, die Dinge, die in meiner
Toolchain funktionieren nach Arduino zu portieren, weil der Core für den
V003 aus meiner Hinsicht unzureichend ist.
Hier ist es dann etwas mühselig, die hardwarenahen Dinge mittels Arduino
zu realisieren. Was "state of the art" in und unter Arduino ist, weiß
ich zugegebenermaßen nicht.
Ich weiß nicht mehr wer es war (könntest sogar Du gewesen sein), müßte
ich nachlesen im Thread, der anmerkte, dass bei einer eigenen seriellen
Klasse ein Arduinoanwender erwarten würde, dass diese Klasse den Stream
von Arduino erbt (und somit auch print, println, write etc.).
Also habe ich den Stream in dieser Klasse geerbt. Mache ich dann auch
mit den Displays dann so.
Deine Anmerkungen zu setup und loop ... und wie das in Arduino gewollt
ist werde ich dann tatsächlich so auch dann in den Demos übernehmen:
Veit D. schrieb:> In deiner demo.ino gehört alles zwischen> loop() {> und> while(1)> in setup().> Dann ist die überflüssige while(1) in der loop weg. Ansonsten ist deine> loop-while Programmierweise kurz gesagt wirklich etwas eigenartig und> würde ich Lehrlingen auch so nicht zeigen, weil es nirgends so steht und> ehrlich gesagt auch keinen Sinn macht.
Die loop also für das verwenden, für das sie gedacht ist, alles vor
"meiner" while ins setup setzen und ein while in der loop nicht
verwenden. Variable dann eben static oder tatsächlich global.
Das reißt mir kein Arm (und auch kein Bein aus).
Veit D. schrieb:> Und wenn du sowieso eigene Libs schreibst, dann fällt damit> auch der gesamte Basis Overhead vom Framework weg.
dass die eigenen Libs geschrieben werden ist leider eine Notwendigkeit,
weil ansonsten bestimmt Dinge mit V003 und Arduino sonst nicht
funktionieren, leider!
Hier dann einfach mal die Frage: Hast du mit V003 unter Arduino schon
gewerkelt? Wenn ja :-) hätte ich ja glatt einen Ansprechpartner, wie man
etwas zum Laufen bekommt OHNE etwas neu schreiben zu müssen, das Rad muß
ja nicht immer wieder neue erfunden werden.
Veit D. schrieb:> Genau das meinte ich mit #defines// Farbzuordnungen der EGA-Farben zu> den Farbnummern> #define black 0> #define blue 1> #define green 2> #define cyan 3> Das ist in C++ alles Datentyp sicher zur Compile Time mit> constexpr uint8_t farbe {1};
Das hier ist natürlich eine gute Anmerkung. Im Sinne der Farbzuordnung
hatte ich mir tatsächlich ein constexpr überlegt, auch wegen der wie du
absolut richtig anmerkst, der Datentypsicherheit wegen. Hier sieht man
auch sehr deutlich an, dass das Original tatächlich ein C-code (und kein
C++) ist. Ich habe noch nicht evaluiert, ob ein constexpr uint8_t farbe
zusätzlichen Speicherplatz wegnimmt oder nicht und werde das einfach
einmal testen. Für den Fall dieser Farbzuordnungen schätze ich jedoch
die Gefahr eines falschen Datentyps eher als gering ein, testen werde
ich des dennoch.
Veit D. schrieb:> Oder du hast dich noch nicht entschieden ob du C oder C++ programmierst.> :-)Veit D. schrieb:> Oder du hast dich noch nicht entschieden ob du C oder C++ programmierst.> :-)Veit D. schrieb:> Oder du hast dich noch nicht entschieden ob du C oder C++ programmierst.> :-)
Na ja, ich habe mich schon entschieden und die Antwort ist: beides. Ich
mache das vom Target abhängig, normalerweise würde ich jedoch für einen
so kleinen Controller wie den V003 eben C bevorzugt nehmen (genauso wie
für AVR) und für die größeren dann eben C++ oder vorzugsweise für
PC-Anwendungsprogramme.
Ich tu mich immer noch schwer damit, das die vor Jahrzehnten schmerzhaft
gelernten C++ (damals unter Borland C++) Dinge auch auf Mikrocontroller
anzuwenden (mit meinem ersten Controller MCS-48 wäre das undenkbar
gewesen), einfach des größeren Resourcenbedarfs wegen.
Bei größeren Controllern, STM32F4 aufwärts habe ich dann dieses Problem
nicht mehr, weil da dann genug von allem da ist.
Man möge mir meine Ansichten verzeihen.
Aber dennoch ein großes Dankeschön für die Anmerkungen - und wie du
hoffentlich gelesen hast - werde ich dann eben ein paar Dinge doch so
machen wie du da gesagt hast, einfach weil ich in der "Arduino-Welt"
nicht wirklich zu Hause bin (die Demos zu den Hardware-Libraries werden
es dir danken).
Veit D. schrieb:> In diesem Sinne, bleib so nett.
Schmunzeln muß, du weißt doch: "Nett ist die kleine Schwester von
sch****" , nein ich gehe mal davon aus, das das so gemeint war, wie du
das geschrieben hast.
Einen Gruß an Dich,
Ralph
Hallo Ralph,
alles gut und schön das es keine Missverständnisse gibt. :-)
Wegen deiner Frage ob ich einen CH32V003 habe, da muss ich leider
passen. Bestimmt ein interessantes Teil, würde dann aber zu viel für
mich mit allen anderen Dingen. Ich bewundere daran, an so einem völlig
anderen fremden Controller, dein Durchhaltevermögen. Ehrlich. Bei allen
anderen bspw. neuen AVRs gibt es immer hier und da jemanden der helfen
könnte. Mit kleinen STM32 wollte ich einmal anfangen, dazu kam es aber
nie.
Eine constexpr Variable wird auf jeden Fall zur Compile Time "ersetzt"
und belegt keine zusätzlichen Ressourcen. Kann auch ein Rückgabewert
einer constexpr Funktion sein, allerdings nur, wenn dabei auch alles zur
Compile Time konstant ist und nicht nur "gefühlt" konstant. Zur Laufzeit
berechnet und mit const deklariert zählt nicht dazu. Die constexpr
Funktion funktioniert dennoch, man spart damit jedoch keine Ressourcen,
wenn nicht alles richtig konstant ist. Das findet man durch testen
heraus. Ich möchte dich jedoch nicht in die C++ Ecke drängen. Das
entscheidest du. Es sollte einem nur bewusst sein, dass Arduino C++ ist.
Ob man das alles nutzt steht auf einem anderen Blatt. Mach das worin du
dich wohl fühlst, dann profitieren auch deine Lehrlinge davon.
Auf eines kannste dich bei mir verlassen. Ich meine alles so wie
schreibe. Auch wenn manchmal hier und da meine Leidenschaft der
Überzeugungsarbeit mit mir durch gehen sollte. :-) Gute nachvollziehbare
begründete Gegenargumente können mich allerdings stoppen.
In diesem Sinne Grüße zurück,
Veit
> https://copilot.microsoft.com/shares/m3DxodnxxTu8k9eSLDAcL
Da hat die Microsoft KI was unterschlagen. "serialEventRun" in der loop
kann schon wichtig sein.
Auf meiner Platte findet sich in
.arduino15/packages/arduino/hardware/avr/1.8.6/cores/arduino
1
#include<Arduino.h>
2
3
// Declared weak in Arduino.h to allow user redefinitions.
4
intatexit(void(*/*func*/)()){return0;}
5
6
// Weak empty variant initialization function.
7
// May be redefined by variant files.
8
voidinitVariant()__attribute__((weak));
9
voidinitVariant(){}
10
11
voidsetupUSB()__attribute__((weak));
12
voidsetupUSB(){}
13
14
intmain(void)
15
{
16
init();
17
18
initVariant();
19
20
#if defined(USBCON)
21
USBDevice.attach();
22
#endif
23
24
setup();
25
26
for(;;){
27
loop();
28
if(serialEventRun)serialEventRun();
29
}
30
31
return0;
32
}
Bei den "Cören" für den ESP32 oder dem RP2040 wird das dann noch
aufwändiger. Dort ist oft noch die Funktion "yield" eingebaut, die von
manchen Treibern als zyklischer Aufruf benötigt wird.
Veit D. schrieb:> Eine constexpr Variable wird auf jeden Fall zur Compile Time "ersetzt"> und belegt keine zusätzlichen Ressourcen. Kann auch ein Rückgabewert> einer constexpr Funktion sein, allerdings nur, wenn dabei auch alles zur> Compile Time konstant ist und nicht nur "gefühlt" konstant. Zur Laufzeit> berechnet und mit const deklariert zählt nicht dazu. Die constexpr> Funktion funktioniert dennoch, man spart damit jedoch keine Ressourcen,> wenn nicht alles richtig konstant ist. Das findet man durch testen> heraus. Ich möchte dich jedoch nicht in die C++ Ecke drängen.
:-) du drängst mich nicht in die Ecke... da bin ich schon (zumindest
immer wieder). Allerdings lernt man nie aus, dass gcc constexpr
"wegoptiomiert" wenn alles tatsächlich konstant ist, wußte ich, dass das
unter Arduino mit avr-g++ auch so ist wußte ich nicht zu 100% ... Ich
habe es ausprobiert und es ist tatsächlich wie du sagst (unter riscv-gcc
auch), ergo, werde ich versuchen, bei Portierungen von C nach C++ etwas
"sorgfältiger" zu sein, was solche Dinge angeht.
Veit D. schrieb:> Auch wenn manchmal hier und da meine Leidenschaft der> Überzeugungsarbeit mit mir durch gehen sollte. :-)
lachen muß (sorry), dann überzeuge mich einmal, anstelle von C oder C++
bei Microcontrollern Arduino zu verwenden anstelle einer Toolchain (wie
bspw. eine eigen eingerichtete oder auch einfach nur avr-gcc, libopencm3
bei stm32 oder das ch32fun framework).
Mein Gegenargument für bspw. ch32v003 (weil ich das hier gerade belegen
kann) ist, dass ein Programm, welches im Code identisch ist (einfach
C-Code ins Arduino Sketch kopiert) mit dem Framework 3192 Byte belegt,
mit Arduino 9178 Byte!
Die Codegröße schreckt mich häufig ab (Verarbeitungsgeschwindigkeit
manchmal auch).
Okay, ich habe mittlerweile - auch durch Azubis - gelernt, dass die
Einstiegshürde niedrig ist, dass es etwas braucht, was schnell
funktioniert. Es kein Setup benötigt. Spricht dafür.
Aber wenn man auch anderst kann?
Hallo Ralph,
ich denke ich muss nochmal darauf eingehen. Auch auf die Gefahr das du
es doch schon weißt. :-) Oder für andere Mitleser. "Arduino" ist keine
eigene Sprache oder sowas wie man mancher Ortens traurigerweise lesen
muss. Das Framework ist ganz normales C/C++ und stellt viele Funktionen
bereit, damit die Nutzbarkeit und damit die Einstiegshürde niedrig wird.
Das haben deine Lehrlinge schon richtig erkannt. Arduino nutzt auch
keine eigens geschriebene Toolchain, sie nutzen einen ganz normalen
avr-gcc 7.3.0 mit eingestellten Sprachstandard C++11. Den kann man
locker auf C++14 und auch auf C++17 einstellen. Man darf nur keine
komplette C++17 Unterstützung erwarten. Den 'auto' Datentyp in
Range-based for loop verwenden zu können ist nett. Mit C++11 ist das
noch nicht möglich.
https://www.gnu.org/software/gcc/projects/cxx-status.html
Worin sich die Gimmicks eines avr-gcc von anderen xyz-gcc unterscheiden
ist die avr-LibC. Da hat man Dinge wie Range für switch-case, was man in
anderen Toolchains nicht hat. Das sind dann allgemeine Unterschiede der
Toolchains, die nichts mit Arduino zu tun haben, was auch gut so ist.
;-)
> lachen muß (sorry), dann überzeuge mich einmal, anstelle von C oder C++> bei Microcontrollern Arduino zu verwenden anstelle einer Toolchain (wie> bspw. eine eigen eingerichtete oder auch einfach nur avr-gcc, libopencm3> bei stm32 oder das ch32fun framework).
:-) Ich muss und möchte dich nicht überzeugen. Mir ging es vorwiegend
darum, wenn man Arduino verwendet, dass man es richtig verwendet. Also
nicht die loop() verschandelt und setup() ungenutzt lässt. :-)
> Mein Gegenargument für bspw. ch32v003 (weil ich das hier gerade belegen> kann) ist, dass ein Programm, welches im Code identisch ist (einfach> C-Code ins Arduino Sketch kopiert) mit dem Framework 3192 Byte belegt,> mit Arduino 9178 Byte!
Das ist ein berechtigtes Argument. Das ist vermutlich dem Framework
geschuldet. Also der Anpassung an alle Cores ohne Code Kompatibilität zu
verlieren. Was ja auch der Sinn von Arduino ist. Ein nacktes setup +
loop belegt schon Speicher, kommt noch Serial dazu, steigt es schon
stark an. Das rührt daher das unter der Haube schon viel Code ausgeführt
wird um Grundeinstellungen der Hardware vorzunehmen. Bsp. werden Timer
voreingestellt für millis, delay und analogWrite, damit dann zur
Laufzeit nichts/wenig umkonfiguriert werden muss. Der Komfort kostet
dann Speicher. Jetzt kann man das speziell für seine Hardware natürlich
auf ein Minimum reduzieren. Muss dann aber bspw. zusätzliche init/begin
Funktionen zur Verfügung stellen. Bei Serial kommt noch die Vererbung
dazu, die da scheinbar nicht so optimal ist. Allerdings hat wohl damals
von Arduino.cc niemand geahnt, dass Arduino für
Controller-Speicher-Miniaturen verwendet wird. :-) Arduino fing zwar
laut meines Wissens mit einem ATmega168P an, der Durchbruch begann
jedoch mit dem ATmega328P auf dem bekannten UNO R3.
> Aber wenn man auch anders kann?
Wenn man anders kann, dann kann man es anders machen. Ich sage einmal
so. Was du unter Haube wie in deinem Core programmierst ist deine Sache.
Für den Arduino User ist nur wichtig, wenn man den Anspruch hat
kompatibel zu bleiben, dass das Interface deiner Funktionen/Methoden dem
entspricht, was in der Arduino Doku steht. Was anderes interessiert den
gemeinen Arduino User nicht. :-) Alle anderen schauen ggf. unter die
Haube die mehr wissen wollen.
Betrachten wir es einmal anders. Auf der Welt schreiben bestimmt
Millionen Programmierer immer wieder fast den gleichen Code für USART
zum Bsp.. Ist das nicht vergeudete Zeit? Jetzt kann man bestimmt Arduino
in einem anderen Licht betrachten, die es geschafft haben vieles, trotz
unterschiedlichster Hardware, auf einen gemeinsamen Nenner
zusammenzuführen, damit eben nicht jeder bei Null anfangen muss. Dabei
bleiben fast unweigerlich Ressourcen liegen. Tja, ist eben so. Ich
meine, wenn man die Entwicklung von Arduino sieht, wieviele Leute ihren
eigenen Core beitragen usw., dann ist das schon eine Nummer. Wenn man
aus heutiger Sicht das Framework programmieren würde, würde es bestimmt
anders aussehen, weil paar Aspekte anders einfließen würden, wie zum
Bsp. Speicher sparen. Ich muss Arduino.cc nicht schön reden, da läuft
auch nicht alles rund, möchte jedoch einen Grund erkennen warum das so
ist wie es ist.
Was du noch machen könntest, SpenceKonde
(https://github.com/SpenceKonde) unterstützt mit seinen Cores ATtinys
die wenig Speicher haben. Hier könntest du einmal reinschauen wie er das
gemacht hat um Ressourcen zu sparen. Er arbeitet viel mit Makros und C
und Assembler und lehnt C++ regelrecht ab, was Schade ist.
Habe ich schon wieder zu viel getippt. ;-)
Ruhiges Wochenende wünsche ich …
Veit D. schrieb:> Controller-Speicher-Miniaturen verwendet wird. :-) Arduino fing zwar> laut meines Wissens mit einem ATmega168P an
Atmega8
1
In 2005, Massimo Banzi, along with David Mellis (an IDII student at the time) and David Cuartielles, added support for the cheaper ATmega8 microcontroller to Wiring. Then they forked (or copied) the Wiring source code and started running it as a separate project, called Arduino.
Veit D. schrieb:> ch denke ich muss nochmal darauf eingehen. Auch auf die Gefahr das du> es doch schon weißt. :-) Oder für andere Mitleser. "Arduino" ist keine> eigene Sprache oder sowas wie man mancher Ortens traurigerweise lesen> muss. Das Framework ist ganz normales C/C++
Das wußte ich natürlich schon, wie in vergangenen Threads bereits
geschrieben, bin ich ja gerade dabei, Arduino-Libraries für CH32V003 zu
schreiben und dann sieht man in den .c und .cpp Dateien schon deutlich,
was das ist ( :-) und ganz Blinde könnten das schon ander Dateiextension
.cpp erkennen). In den Libraries dich speziell für den V003 mache bin
ich permanent am überlegen, ob ich daraus eine Klasse mache oder nicht
und ob das eine eigenständige Library wird oder nicht.
Bsp. Auszubildende sollen / müssen Textdisplay in Betrieb nehmen
(HD44780) und stellen fest: Originaldemo funktioniert leider (wegen
Timingsachen am Clock) nicht. Also schreibe ich eine extra Library mit
denen die auch sofort umgehen konnten.
Gehen wir einen Schritt weiter, weil in einem anderen Thread scheinbar
schon der Unterschied zwischen einem OLED (Grafik) Display und einem
Textdisplay nicht sofort klar war, dass es Displayadapter für HD44780
mit I2C Anschluß gibt. Also bin ich momentan dabei, einen I2C
Displayadapter für Arduino CH32V003 zu machen. Ehrlichkeitshalber muß
ich sagen, dass ich die Funktionalität erst einmal in reinem C gemacht
habe und jetzt portiere ich das nach C++ / Arduino. Hier stellt sich
dann schon die triviale Frage: Packe ich das in eine kompakte Library
mit evtl. unterschiedlichen Klassen, die zum einen ein Display parallel
anfährt und die andere Klasse das mit I2C macht. Packe ich das in eine
Klasse, bei der über den Konstruktor entschieden wird, welche
Schnittstelle das Display hat? Prinzipiel: Nutze ich meine bereits
erstellte I2C auf Hardware-Basis (weil der Core von V003 fehlerhaft ist)
oder verwende ich lieber ein Software - Bitbanging um das an anderen
Pins als den I2C Hardwarepins zu legen ... oder mache ich beides und
untescheide wieder mit dem Konstruktor? Ganz "schräg" könnte ich noch
sagen: Hey, ich mache das als Demo für den I2C-Bus.
Hier habe ich so überhaupt keine Ahnung davon, was ein Arduino User
gerne hätte. Meine eigene "Strategie" ist, für jedes "Problem" seine
eigene Source zu haben (zumindest mal im Embeddedbereich). Auf PC oder
großen System packt man das in eine Datei, vllt. sogar in eine sehr
mächtige Klasse, weil man eh genügend Resourcen hat.
Veit D. schrieb:> was in der Arduino Doku steht.
Es ist nicht nur wichtig was in der Arduino Doku steht, sondern
grundsätzlich (und da muß ich mich daran machen) muß man seine
Funktionen dokumentieren, damit andere und man selbst später damit
umgehen kann.
Veit D. schrieb:> Jetzt kann man bestimmt Arduino> in einem anderen Licht betrachten, die es geschafft haben vieles, trotz> unterschiedlichster Hardware, auf einen gemeinsamen Nenner> zusammenzuführen, damit eben nicht jeder bei Null anfangen muss.
Das größere Problem ist doch eher, dass man versucht, alles irgendwie
"Arduino-kompatibel" zu machen, auf biegen und brechen. Für jede neue
Plattform oder für jede neue Controllerfamilie wird ein neuer Core
erstellt.... und dieser ist erst einmal unvollständig und häufig auch
noch buggy (leider). Aber das Produkt muß ja schnell auf den Markt.
Im Falle von AVR ist das im Laufe der Jahre gewachsen, aber man sieht
diesem Teil deutlich an, dass es ursprünglich eben für ATmega gemacht
war.
Für mich als Elektroniker sieht Arduino in manchen Dingen "befremdlich"
aus, ein "digitalWrite" ... herjeh... und dann auch noch eine Angabe von
"HIGH" und "LOW"... anstelle von 1 und 0 (ich weiß, dass ich auch 1 und
0 angeben kann).
Aber das ist eben der Lauf der Dinge, wie heute Sachen verstanden werden
(das ist jetzt keine Wertung von positiv oder negativ). Tatsache ist
aber auch, dass mit Arduino grundsätzlich fast kein Hardwareverständnis
gefördert wird (leider)
Herjeh, :-) ich wollte mich nicht darüber auslassen über ein für und
wider von Arduino... (und hab hier schon zu viel geschrieben).
Veit D. schrieb:> Arduino fing zwar> laut meines Wissens mit einem ATmega168P an, der Durchbruch begann> jedoch mit dem ATmega328P auf dem bekannten UNO R3.
Arduino fing mit einem Board namens "Arduino Board Serial" an, das noch
mit einer RS232 (anstelle von USB) ausgestattet war und einen ATmega8
als Controller hatte (das war im Jahr 2005). Diesem folgen Diecimila
2007 mit ATmega168 und USB... und dann gab es einige Platinen im r3
Format.
Veit D. schrieb:> Was du noch machen könntest, SpenceKonde> (https://github.com/SpenceKonde) unterstützt mit seinen Cores ATtinys> die wenig Speicher haben. Hier könntest du einmal reinschauen wie er das> gemacht hat um Ressourcen zu sparen.
Da habe ich vor Jahren schon reingesehen gehabt. Ehrlich erschließt es
sich mir nicht, auf solch kleinen Controllern Arduino machen zu wollen.
Für die neueren ATtiny 0/1/2 series gilt das nicht, die sind ja oft min.
so leistungsstark wie ein Mega... :-) den ATtiny1612 finde ich bspw. gar
nicht so schlecht.
Veit D. schrieb:> Habe ich schon wieder zu viel getippt. ;-)
Ich habe auch zu viel geschrieben... und wünsche dir ebenfalls ein
schönes Wocheende
PS: und ich ... bastel jetzt an einer anderen Baustelle die mir am
Herzen liegt und die lange brach lag: meine Webseite ... und damit ich
es nicht ganz verlerne, Seite mit JavaScript: NTC - LookUp Table
Generator entsteht ... ähnlich wie es vor einiger Zeit sebulli gemacht
hat ... er online und ich als konsolenprogramm ... :-) beim generierten
Code der Tabelle kommen wir zur gleichen Tabelle, was nicht wundert,
weil die benutzten Mechanismen sind dieselben. Bei der Interpolation
habe ich dort etwas "gespickelt", gebe ich zu ... und habe diese
Interpolation übernommen, weil sie effizienter ist als meine. Jetzt...
habe ich mich entschlossen, meine Webseite um eben auch einen
NTC-LookUp-Table Generator zu erweitern, die erste Version siehst man
hier ... und wenn man sich den JavaScript Code anschaut, sieht man bei
mir dann sehr deutlich, dass das einmal C war :
https://www.jjflash.de/ntc_table_v2.html
Veit D. schrieb:> Du kannst in der Arduino IDE genauso gut ... verwenden.
Nein, kann er nicht. Weil damit die unsichtbare Initialisierung des
Frameworks verloren geht.
Dir ist das klar, aber anderen womöglich nicht. Außeredem wir sind ja
gerade dabei, den ordentlichen Weg zu lehren. Wenn schon Arduino, dann
richtig.
Christoph M. schrieb:> Veit D. schrieb:>> Geschenkt. :-)>> Übrigens, die Arduino-API hieß ursprünglich "Wiring".> Es lohnt sich, hier mal die ersten zwei Seiten zu lesen.
Mir fiel dann ein, ich hatte das vor Jahren schon gelesen, die
Geschichte um Wiring und den Streit darum.
Alexander schrieb:> Arduino Nutzer wollen nichts, Arduino Nutzer nehmen (was immer man> ihnen vorsetzt)>> Ein> Arduino Nutzer
Du sprichst ganz klar für dich. Nicht alle sind wie du.
Veit D. schrieb:> Du sprichst ganz klar für dich. Nicht alle sind wie du.
Dito. Du bist bist extrem drin. Und ich kann ruhigen Gewissens behaupten
ich bin schon überdurchschnittlich tief ins Framework eingetaucht,
verglichen mit dem gemeinen Arduino Nutzer.
Nemopuk schrieb:> Veit D. schrieb:>> Du kannst in der Arduino IDE genauso gut ... verwenden.
Kannst du ordentlich zitieren? Wir sind schon viele Antworten weiter.
Worauf beziehst du dich?
Alexander schrieb:> Veit D. schrieb:>> Du sprichst ganz klar für dich. Nicht alle sind wie du.>> Dito. Du bist bist extrem drin. Und ich kann ruhigen Gewissens behaupten> ich bin schon überdurchschnittlich tief ins Framework eingetaucht,> verglichen mit dem gemeinen Arduino Nutzer.
Dann schreib nicht laufend solchen Unsinn, welche absolut unnötige
Gegenreaktion hervorrufen. Mir macht das keinen Spass.
Nemopuk schrieb:> Veit D. schrieb:>> Du kannst in der Arduino IDE genauso gut ... verwenden.>> Nein, kann er nicht. Weil damit die unsichtbare Initialisierung des> Frameworks verloren geht.>> Dir ist das klar, aber anderen womöglich nicht. Außeredem wir sind ja> gerade dabei, den ordentlichen Weg zu lehren. Wenn schon Arduino, dann> richtig.
Ich habe es rausgesucht. Du meinst
> Du kannst in der Arduino IDE genauso gut
1
intmain(){
2
...
3
while(1)
4
{
5
...
6
}
7
}
Dazu musst du den gesamten Kontext der Unterhaltung zwischen Ralph und
mir betrachten.
Hallo Nemupuk,
kleine Ergänzung. Das alleine für sich aus dem gesamten Kontext zu
ziehen macht wirklich keinen Sinn. In der Unterhaltung ging es an dem
Punkt darum, ob man sich generell entscheidet konform für Arduino zu
programmieren oder die IDE nur als Programmierwerkzeug verwendet und
ohne Framework sein eigenes Ding macht.
Hallo Ralph,
wegen Display Lib. Ja so eine Grundsatzentscheidung ist schwierig.
Meistens wird das mittels Konstruktor Überladung gelöst. Dafür muss man
die Parameterreihenfolge gut überlegt wählen und man kann mit
Defaultwerten arbeiten. Die Vorliebe muss man gedanklich durchspielen.
Eine beliebte Lib für grafische Displays ist die von Oli Kraus.
https://github.com/olikraus/u8g2https://github.com/olikraus/u8g2/wiki
Dich wird es erschlagen wenn du die anschaust. Er erschlägt alles mit
Konstruktor überladen.
Ist bestimmt einen Blick wert. Nur ein Bsp. wegen Konstruktor.
Man kann auch eine gemeinsame Basisklasse schreiben die dann an die
verwendete spezifische Interface Klasse vererbt wird. Dann hätte man
unterschiedliche Konstruktoren und mehr Parameterfreiheiten. Da gibt es
keine Vorgabe. Beim Standard HD44780 Display vielleicht nur, dass wie
erwähnt, sowas wie lcd.print() nutzbar ist.
Wenn man zwischendurch die "Baustelle" wechselt, deine Webseite, wird
das helfen aus dem Gedankenwald herauszukommen. Danach kommen meistens
bessere Ideen. Glaub mir. :-)
Bisher,bin ja ebenfalls Arduino nutzer, kam ich nach kurzer Einarbeitung
auch mit fremden "Codeschnipseln" ganz gut zurecht und habe diese
entsprechend "Arduino gerecht" für meine PY32 zurechtgebastelt.
Drehgeber zb.
https://www.mikrocontroller.net/articles/Drehgeber#Solide_L%C3%B6sung:_Beispielcode_in_C
War am Ende nicht wirklich schwer das umzustricken, weil Arduino eben
für die Interrupts/Timer ect. definierte Funktionen hat.
Es ist leichter als die Einstellungen in die entsprechenden Register zu
Schreiben, was das verstehen das Code angeht.
Was fehlt ist der Bezug zum Hintergrund, das kommt aber mit den ersten
Problemen die sich nicht mit Hilfe eines Tutorial lösen lassen. Wenn der
core beim Einstellen des Takt fehlerhaft ist, bleibt das schnellste
workaround es selbst zu lernen und was eigenes dafür zu schreiben. Man
bleibt halt leichter am Ball wenn wenigstens zwischendurch mal was ohne
basteln läuft.
Codegröße ist echt ein Faktor, schon die Optimierungsoptionen ergeben
teils einige KB Unterschied.
Moin Veit,
die u8g2 Library und auch die Displaytreiber von Adafruit (egal ob
monochrome oder farbig) habe ich mir natürlich schon vor längerer Zeit
angesehen und genau diese Librarys schrecken mich ab.
Der größte Vorteil dieser Treiber ist aus meiner Sicht der Dinge auch
ihr größter Nachteil. Sie sind derart umfangreich, dass dich die
Libraries schier erschlagen und ohne das Wiki kann man intuitiv zum
Einstieg erst einmal gar nichts machen leider.
Natürlich ist es sehr super, wenn man ultra viele Displays unterstützt,
aber das Inbetriebnehmen wird dadurch nicht so wirklich leichter.
Beispielsweise habe ich versucht, allerdings in C, mehrere Displays
(farbige TFT's) in einer Source unterzubringen, was ich auch getan habe.
Die Source ist in ihrern Einstellmöglichkeiten mittlerweile hart an der
Grenze, was ich mir antun möchte (und ich habe das selbst geschrieben).
Unterschiede in Farbreihenfolgen, Adressräumen (sogar bei Displays mit
dem gleichen Displaycontroller, Serien, die eine Verdrahtung wie ein
160x128 haben, aber ein nur ein Glas 128x128 montiert haben),
Initialisierungssequenzen und dann möchte man das ganze ja universell
haben in den Anschlussmöglichkeiten. Zu guter letzt dann noch SPI oder
paralleles Interface war / ist nicht so richtig übersichtlich und zu
guter letzt (im Falle von STM32) das ganze noch mittels DMA betreibbar
bewegt mich dann, das ganze (auch eine meiner Baustellen) auf C++
umzustellen und ich erhoffe mir davon eine einfachere Handhabung.
Aber wie gesagt ist das auch eine weitere Baustelle, :-) mit dem
CH32V003 dachte ich eigentlich, ich mache etwas mit einem schönen Anfang
und einem schönen Ende und bin da dran kleben geblieben (egal ob Arduino
oder Plain-C) und werkel daran schon länger als ich es mir so gedacht
hatte.
Im Falle eines Textdisplays mit I2C Adapter denke ich, ich mache eine
extra Lib dafür.
Veit D. schrieb:> Wenn man zwischendurch die "Baustelle" wechselt, deine Webseite, wird> das helfen aus dem Gedankenwald herauszukommen. Danach kommen meistens> bessere Ideen. Glaub mir. :-)
:-), ich weiß !
Ralph S. schrieb:> Aber wie gesagt ist das auch eine weitere Baustelle, :-) mit dem> CH32V003 dachte ich eigentlich, ich mache etwas mit einem schönen Anfang> und einem schönen Ende und bin da dran kleben geblieben (egal ob Arduino> oder Plain-C) und werkel daran schon länger als ich es mir so gedacht> hatte.
Das dürfte jedem bei jedem Projekt so gehen. Selbst in Firmen mit Geld
und viel Druck ist das so.
Behalte immer im Hinterkopf, daß die Chinesen erheblich weniger
Hemmungen haben, unausgereifte Sachen in den Massenmarkt zu bringen. Da
könnte man erwägen, für ordentliche Doku und vollständige Software aus
Europa 30 Cent mehr aus zu geben. Der CH32V003 war mal ein extremes
Schnäppchen, aber andere haben inzwischen nach gezogen.
> Arduino> Arduino> Arduino> Arduino
Erstens, es gibt dedizierte Arduino-Foren.
Zweitens, Mikrocontroller sind sehr unterschiedlich, weil ihre
Komponenten sehr unterschiedlich sind. Und weder C, noch C++, noch C+++,
noch Python, noch Kobra, noch Anakonda beschreiben die konkreten
Komponenten konkreter Mikrocontroller. Und auch Arduino hilft nicht.
Z.B., der kleine ATtiny412 enthält
• 16-bit Timer/Counter type A (TCA)
• 16-bit Timer/Counter type B (TCB)
• 12-bit Timer/Counter type D (TCD)
• 16-bit Real-Time Counter (RTC)
Alle Zähler sind für unterschiedliche Aufgaben konzipiert, nicht für
Arduino.
Hallo Georg,
hast du dich im Thread vertan?
Hat irgendjemand etwas anderes behauptet?
Deine Antwort, weil als Gegenargument formuliert, passt irgendwie nicht
zu den geschriebenen Antworten. Ich weiß nicht worauf deine Antwort eine
Antwort ist. Manual Screenshots ohne Bezug. Ich finde das komisch.
... jetzt muß ich schmunzeln zwecks des Posts von Georg M. der mich doch
am Anfang verwirrt hat, ob ich hier richtig bin.
Okay.... ich war zwar auf einer anderen Baustelle unterwegs (meine
Webseite), aber da funktioniert etwas zumindest funktional und ich muß
"nur" noch einen Beschreibungstext da einstellen. Dann läßt mich das
Thema hier nicht so wirklich los und das, obwohl ich ja "eigentlich"
kein Arduino mache (aber wie es jetzt ausschaut eben doch ein bisschen).
Zudem ist da (negative Charaktereigenschaft) mein Ego (aber nur ein
kleines bisschen) angekratzt, weil es dann irgendwie so ausschaut, als
ob ich ein blutiger Anfänger bin (hmm, unter Arduino stimmt das vllt.
sogar, Arduino ist unter der Motorhaube dann doch so ziemlich
vielschichtig).
Also habe ich mich noch einmal hingesetzt und mich der "Problematik"
gewidmet, wie man diesem für mich unsäglichen "Serial.print" Herr werden
kann und - zu Veit schiel - das dann mal so überlegt, wie denn das unter
C++ aussehen sollte / würde und für mich erst einmal etwas "hingebogen".
Und ich bin wirklich sehr gespannt, was Veit und andere dazu sagen (und
Veit, du siehst, ich habe die loop nicht kastriert und die counter
variable brav static gemacht).
Die nächste Frage hier ist dann, ob ein typischer Arduino-User oder auch
Anfänger damit etwas anfangen kann.... und ob das legitim ist, das für
Demonstration anderer Arduino-Libraries zu verwenden (bspw. Auswertung
NTC-Sensor).
Weil es so kurz ist, der Demo-Sketch ausnahmsweise auch hier zu lesen:
Ich fand schon vor 30 Jahren, dass dieses
> cout << irgendwas
syntaktisch nicht zum Rest der Sprache passt. Da hat man meiner Meinung
nach gleich zu Anfang demonstriert, wie man die Sprache nicht
missbrauchen sollte.
Seit dem habe ich viele andere Programmiersprachen gelernt. Trotz der
damit einhergehenden Toleranz für Vielfalt ist das Unbehagen gegen cout
bis heute geblieben. Cout fügt sich wie ein Krebsgeschwür ins Projekt
ein.
Also so als Anfänger, ja, anfangen könnte man was damit.
Allerdings cout gibt's unter Arduino eigentlich nicht standardmäßig, der
gemeine Arduino nutzer wird damit erst mal nicht viel anfangen können,
verbreiteter ist Streaming.
Das muss zwar auch erst hinzugefügt werden, ist aber scheinbar beliebter
als CinCout.
Hallo,
ich sage einmal so für mich redend. Sobald der gemeine Arduino
Nutzer/Programmierer :-) irgendwann ein C/C++ Buch aufschlägt, kommt er
mit cin und cout in Berührung. Von daher finde ich es legitim. Wer eine
Streaming Lib nutzt muss sowieso umdenken und ohne print klar kommen.
Und das geht. ;-) Ansonsten, irgendwas ist doch immer. ;-)
Zum Ralph seinen Code. Ja ja, dass #define sticht mir ins Auge. :-)
using funktioniert leider nicht. Dafür kann man C++ like eine Referenz
verwenden.
Entweder:
1
constexprauto&cout{cout_serial};
oder
1
constinitauto&cout{cout_serial};
oder
1
cout_light<HardwareSerial>&cout{cout_serial};
Man kann das auch weglassen und gleich die Objektinstanz so benennen.
Lach, Hallo Veit,
irgendwie finde ich das grundsätzlich witzig, dieses "hin und her" der
Postings.
Und immerhin, die "Anmerkungen" von dir werden kleiner, grundsätzlich
wußte ich, dass du das #define monieren würdest, aber die cout -
Umsetzung ist doch schon mal so halbwegs C++, oder etwa nicht (und das
cout auch).
Allerdings muß ich Nemopuk rechtgeben, so wirklich warm geworden bin ich
mit dem cout und cin nicht wirklich und für den Output "liebe" ich das
printf, das so viele hassen. Für mich ist der Aufbau von printf alles in
allem eher logisch und auch relativ schnell zu sehen, was ausgegeben
werden soll und es ist weniger Schreibarbeit (empfinde ich zumindest).
Aber, es ging hier um C++ und deshalb auch dieses cout hier.
Grundsätzlich gefällt mir das immer noch besser, als die einzelnen
Streamfunktionen print, println, write etc. im Sketch aufzurufen.
Und:
Veit D. schrieb:> Hier bitte kein '\r' sondern ein '\n'.cout << F("\n Counter: ") << Dec> << counter;
By the way: Sollte dich - wider erwarten - der CH32V003 interessieren,
klebe (okay löte) ich dir gerne einen kleinen Programmer hierfür
zusammen und einen Controller auf eine Adapterplatine und schick dir
das. Allerdings funktioniert der Programmer zumindest von mir getestet
nur unter Linux (würde ich doch sogar glatt unentgeldlich machen,
einfach so just for fun). Beim Core des Arduino muß man dann boards.txt
plattform.txt und system_ch32v00x.c patchen (aber wem erzähl ich das,
das weißt du alles selbst)
Natürlich soll das ein '\r' sein: Mein Terminalprogramm ist so
eingestellt, dass \r und \n eben als Carriage return und Newline
getrennt interpretiert werden. Damit erreiche ich, dass meine Ausgabe
immer in derselben Zeile erfolgt (ohne Zeilensprung) und das ist auch
gewollt so.
Hallo Ralph,
kein Problem, ich habe gegen cout nichts einzuwenden.
Wenn \r Absicht ist, wusste ich nicht, dann ist das okay,
Danke für das Angebot, freut mich, ggf. kommen wir darauf zurück. ;-)
Das ist auch lustig, hatte vor kurzem im Arduino Forum jemanden auch ein
kleines Geschenk machen wollen. :-)
Ralph S. schrieb:> Zudem ist da (negative Charaktereigenschaft) mein Ego (aber nur ein> kleines bisschen) angekratzt, weil es dann irgendwie so ausschaut, als> ob ich ein blutiger Anfänger bin (hmm, unter Arduino stimmt das vllt.> sogar, Arduino ist unter der Motorhaube dann doch so ziemlich> vielschichtig).
So ist es:
Arduino nutzen ist nicht schwer,
Arduino machen hingegen sehr.
Ich erwähne es noch mal: Es gibt da gewisse Coding-Guidlines, die man
natürlich einfach brechen kann, wenn es einem Spaß macht. Nur sollte man
es dann vielleicht nicht mehr "Arduino" nennen.
Ralph S. schrieb:> Mein Terminalprogramm ist so eingestellt, dass \r und \n eben als> Carriage return und Newline getrennt interpretiert werden.
Und warum schreibst Du es dann nicht konsequent durchgängig auch so da
wo neue Zeilen gewünscht sind F("\r\nHallo Welt,\r\n"); das muss doch
auch am Ego kratzen?
Alexander schrieb:> Und warum schreibst Du es dann nicht konsequent durchgängig auch so da> wo neue Zeilen gewünscht sind F("\r\nHallo Welt,\r\n"); das muss doch> auch am Ego kratzen?
??????
Irgendwie verstehst du wohl das einfachste nicht, um das es geht, oder ?
Wenn ich nach "Hallo Welt" eine neue Zeile haben möchte (und die möche
ich haben), dann folgt dem eben ein "\n\r".
Und ob ich jetzt (wie von dir vorgeschlagen) \r\n schreibe, oder \n\r
ist Jacke wie Hose. Ob ich erst einen Carriage return mache und dann
einen Zeilensprung oder umgekehrt macht auf der Ausgabe keinen
Unterschied.
Ralph S. schrieb:> cout << F("\n\r Hallo Welt,\n\r ein cout-Demo mit Arduino,hier> Zaehlerausgabe auf Serial\n\n\r");
Natürlich hätte ich auch schreiben können:
1
cout << F("\n\r Hallo Welt,");
2
cout << F("\n\r ein cout-Demo mit Arduino, hier Zaehlerausgabe auf Serial");
3
cout << F("\n\n\r);
Hrmpf, ich hätte ja noch als Kommentar hinzufügen können, dass ich hier
"Hallo Welt" ausgebe (das.... würde dann wirklich am Ego kratzen)
Alexander schrieb:>> dann folgt dem eben ein "\n\r".> aber nur bei Dir, sonst nirgends auf der Welt
Das ist halt ein altes Relikt aus der Zeit, als man Schreibmaschinen zur
Ausgabe nutzte. Heute bringt fast jedes Terminal den Cursor automatisch
an den Anfang der neuen Zeile - außer bei Microsoft.
Üblicherweise ist die Reihenfolge \r\n.
Wenn man wie eine Schreibmaschine denkt passieren eben solche Fehler.
LFCR ist nicht nur unüblich sondern falsch. Mag auf der
"Schreibmaschine" nicht stören, aber spätestens bei utils wie dos2unix
wird das spannend (wer's braucht)
Ich wusste übrigens bis gestern nicht dass Arduino gar kein
Serial.printf() hat. Auf dem ESP32 funktioniert das. Würde IMHO Sinn
machen das aus arduino-esp32/cores/esp32/Print.h zu klauen.
https://forum.arduino.cc/t/serial-print-and-printf/146256
Alexander schrieb:> Ich wusste übrigens bis gestern nicht dass Arduino gar kein> Serial.printf() hat.
Hat es nicht!
printf selber kann man nachrüsten.
printf ist allerdings auch arg fett für kleine µC
streaming.h bietet einiges an Formartiermöglichkeiten welche ungewohnt
aber meist ausreichend sind.
Alexander schrieb:> aber nur bei Dir, sonst nirgends auf der Welt
wie schräg bist du denn drauf? Erstens, auch wenn ich das nicht wirklich
mag, macht das Microsoft so... zweitens darf man seine Console so
einstellen wie es funktional ist. Wenn man also wie ich, es gerne hat,
dass die Ausgabe in ein und derselben Zeile erfolgen soll, stellt man
das Terminal für getrennte \n \r ein. Einzig mittels ESC-Sequenzen kann
man das auch bewerkstelligen, allerdings aufwändiger. Grundsätzlich: was
machst du für ein Fass auf, für so etwas triviales wie Steuerzeichen in
einem AsciiZ String???
Ich finde dich ganz toll, echt.
Aber immerhin, das meine ich ernst, könnte ich meiner HardwareSerial
mein abgespecktes printf vermachen. Grundsätzlich werd ich hier dieses
abgespeckte printf mit den entstehenden Bibliotheken hier einstellen.
Das kann dann zwar kein float und auch keine Längenangaben, dafür trägt
es im Falle von AVR nur mit 350 Byte auf, bei CH32V003 419 Byte... aber
du darfst dann gerne auch wegsehen, weil in den Demos dann wieder \n\r
zu sehen ist.
Auch würde ich gerne von dir lernen, zeig mal, was du da an
Arduino-Klassen schon produziert hast (anstelle dich über den Stil
anderer zu echaufieren)
Ralph S. schrieb:> könnte ich meiner HardwareSerial> mein abgespecktes printf vermachen.
Es ist üblich solche Erweiterungen in Print.h unter zu bringen.
Alexander schrieb:> Auf dem ESP32 funktioniert das. Würde IMHO Sinn> machen das aus arduino-esp32/cores/esp32/Print.h zu klauen.
printf braucht aber auf einem kleine Prozessor sehr viel Speicher. Das
könnte auch der Grund für das Fehlen von printf in der Atmega328 Version
gewesen sein.
Hallo,
> In der Arduinowelt kann man vieles mit der Stringklasse machen:
Kann man, man sollte jedoch auch die Probleme damit kennen. Gerade eben
mit dem + Operator.
Ralph S. schrieb:> Und ob ich jetzt (wie von dir vorgeschlagen) \r\n schreibe, oder \n\r> ist Jacke wie Hose.
Ist es nicht. Wenn ich meine Jacke als Hose anziehe fällt da was raus.
Ralph S. schrieb:> Erstens, auch wenn ich das nicht wirklich mag, macht das Microsoft so...
Nein macht es nicht. Du meinst:
Nemopuk schrieb:> Üblicherweise ist die Reihenfolge \r\n.Ralph S. schrieb:> Grundsätzlich: was machst du für ein Fass auf
Mach ich nicht. Ich hab Dich nur auf den (trivialen) Typo hingewiesen,
der sich bei Dir durchzog (und zu solchen Mißverständnissen wie mit Veit
führen kann). Sieht halt schlampig aus so, wäre schade wenn das so ins
Repo wandert.
Ralph S. schrieb:> zeig mal, was du da an Arduino-Klassen schon produziert hast
Da gibt es nichts. Ich nutze was da ist und erfinde nicht das Rad neu.
Das ist ja das schöne an Arduino. Ich muss gar nichts können.
Moin,
Ich bin eigentlich der Meinung, wenn etwas mehr Komfort gewünscht ist,
daß man dann besser eine etwas üppiger ausgestatteten uC wählen sollte.
Beim ATMEGA1284 mit 16K z.B., spielt die Unterstützung von printf eine
geringere Rolle als beim 328P oder noch kleiner. Beim STM32L496 denke
ich überhaupt nicht daran. Ausser Sportlichkeit lohnt es sich nicht mehr
frugal den uC zu wählen. 32-bit uC kosten heutzutage weniger als die
älteren 8-Bitter und braucht nicht abgespeckte Bibliotheken. Beim STM
habe ich auch noch einen schnell und gut funktionierenden Debugger. Da
ist das Arduino Konzept klar im Nachteil. Andrerseits kann man bei
Erfahrung auch gut ohne Debugger auskommen und mit cleverer Ausnützung
von printf und Oszi Unterstützung Probleme verfolgen. Aber manchmal hat
natürlich der Debugger schon den Tag gerettet.
Trotzdem arbeite ich noch gerne mit den kleineren Exemplaren, weil es
einfach erzieherisch ist, mit geringen uC Ressourcen Probleme effizient
in funktionierende HW umzusetzen und diszipliniert zu planen and
programmieren. Viele Realwelt Steuer Anwendungen agieren mit ihrer
Umwelt in ms oder s Skala. Und wenn es wirklich nicht langt, skaliert
man aufwärts. Für "moderne" kommunizierenden Anwendungen nimmt man
ohnehin oft ESP32 oder Vergleichbares.
Gerhard
Gerhard O. schrieb:> 32-bit uC kosten heutzutage weniger als die> älteren 8-Bitter und braucht nicht abgespeckte Bibliotheken.
Der CH32V003 ist ein 32-Bit-µC, nur halt einer am unteren Ende der
Ausstattung.
Ihm hat sich übrigens ein etwas besser ausgestatteter Nachfolger
hinzugesellt, der CH32V002 mit doppelt so viel RAM.
Und wenn man damit leben kann, daß es kein SO-8 bzw. SO-16 als Gehäuse
gibt, ist der CH32V006 ein nochmal deutlich besser ausgetatteter
Kandidat - 8 kiB RAM und in den meisten Fällen* 62 kiB Flash-ROM. Geben
tuts ihn ab TSSOP20/QFN20 bis zu QFN32 (mit dann den meisten I/Os).
Dennoch ist der auch für 5V-Betrieb geeignet, was für viele Bastler den
einen oder anderen Pegelkonverterkrampf vermeiden hilft.
*) der CH32V006F4U6 hat aus irgendwelchen Gründen nur 16 kiB Flash und
auch nur 4 kiB RAM,
Harald K. schrieb:> Dennoch ist der auch für 5V-Betrieb geeignet, was für viele Bastler den> einen oder anderen Pegelkonverterkrampf vermeiden hilft.
Was läuft denn heute noch mit 5V, außer uralter Arduino Kram?
Anscheinend genug, daß es manchen "Makern" oder Bastlern Probleme
bereitet und sie mit Pegelwandlern herummachen müssen, weil sie mit
5V-Peripherie zu tun bekommen.
Die verschiedenen CH32V00x-Modelle laufen aber auch mit weniger als 3 V,
die neueren bereits ab 2 V (2.4, wenn ein ADC genutzt werden soll).
Beschränkungen bei der Taktfrequenz gibt es wohl nicht.
Insofern ist der 5-V-Betrieb ein Kann, kein Muss.
Alexander schrieb:> Da gibt es nichts. Ich nutze was da ist und erfinde nicht das Rad neu.> Das ist ja das schöne an Arduino. Ich muss gar nichts können.
Ich würde an deiner Stelle den Ball flacher halten. Dir muss bewusst
sein, wenn du nichts kannst, dann müssen andere etwas können, damit du
vorhandenes Nutzen darfst. Das heißt, du bist abhängig von Entwicklern
wie Ralph die einen Core schreiben, den du später nutzen kannst. In der
Sache hast du Recht, nur kann man es auch netter formulieren.
Es gibt zwischen den Betriebssystemen paar kleine Unterschiede in der
Interpretation der Steuerzeichen.
Das betrifft jedoch weniger Serial -> Terminalausgabe, sondern Programme
welche in eine Textdatei schreiben.
Jetzt weiß ich nicht was Ralph für ein Terminal verwendet.
Ich hatte es mit dem Seriellen Monitor der Arduino IDE 1.8.19 und 2.3.8
probiert.
Eine Einstellung auf CR hilft da nicht. Es wird fortlaufend die Zeile
weitergeschrieben, bis es aus den Sichtfeld ist bzw. man den
Scrollbalken bewegen muss.
hterm kommt mit CR allein zurecht und macht einen Zeilenumbruch. hterm
weiß offenbar, dass am COM Port (USB) im Jahre 2026 keine
Schreibmaschine angeschlossen ist. :-)
Der Serielle Monitor weiß das nicht bzw. gibt es da ein Problem was man
adressieren sollte oder es verhält sich Windows konform, was auch nicht
sein kann, denn ein Wagenrücklauf erfolgt auch nicht. Könnte man separat
besprechen.
Ausreichend für einen Zeilenumbruch im Terminal im Jahre 2026 wäre '\n',
macht das was die Beschreibung dazu sagt.
Mit welchen Terminal '\r' sauber funktioniert weiß ich nicht. Ich kenne
keines was an den Anfang der Zeile springt und alles überschreibt.
Unter Windows mit Dateioperationen ist dagegen '\r\n' Standard für EOL.
Hiermit gibt es dann wohl die bekannten Problem mit Textdateien bei
Austausch zwischen Betriebssystemen.
Jedes Detail habe ich nun nicht studiert, es gibt jedoch
Interpretationsunterschiede im OS.
https://www.loginradius.com/blog/engineering/eol-end-of-line-or-newline-charactersNemopuk schrieb:> Was läuft denn heute noch mit 5V, außer uralter Arduino Kram?
Entwicklungen verpasst?
Hier geht es übrigens immer noch um CH32V003. Kein STM oder sonstwas.
Veit D. schrieb:> Das heißt, du bist abhängig von Entwicklern> wie Ralph die einen Core schreiben, den du später nutzen kannst. In der> Sache hast du Recht, nur kann man es auch netter formulieren.
Den Satz ich lasse programmieren habe ich mir verkniffen.
Veit D. schrieb:> Ausreichend für einen Zeilenumbruch im Terminal im Jahre 2026 wäre '\n',> macht das was die Beschreibung dazu sagt.> Mit welchen Terminal '\r' sauber funktioniert weiß ich nicht. Ich kenne> keines was an den Anfang der Zeile springt und alles überschreibt.
Alles was sich VT52,VT100,VT220, … nennt.
Und wahrscheinlich ein ganzer Sack voller korrekt implementierter
Terminal Emulationen. Selbst minicom, rudimentär in Python programmiert,
macht das.
Als newline/neue Zeile:
0x0d CR wird/wurde vom alten Apple genutzt.
0x0d,0x0a CRLF wird von Windows genutzt.
0x0a LF wird von allem Unixodiden genutzt.
0x15 NL wird/wurde von IBM im EBCDIC genutzt.
Christoph M. schrieb:> Gerhard O. schrieb:>> Beim STM>> habe ich auch noch einen schnell und gut funktionierenden Debugger. Da>> ist das Arduino Konzept klar im Nachteil.>> Wie das?>> https://github.com/stm32duino
Danke für den Hinweis. Habe ich bisher ignoriert, weil ich beim STM32
lieber mit ST Werkzeugen und Debugger arbeite. Und bei den 8-bittern
stimmt es ja, dass Debugging in der Regel nicht vorgesehen ist.
Wer effizienten Debug mit minimal IO Verlust möchte, ist wahrscheinlich
z.B. bei MSP430 und Z!Encore besser aufgehoben. Der MSP430 ist da im
Umgang mit CubeMX IDE ohnehin sehr ähnlich. Auch Siliconlabs 8051
Derivate haben ähnlichen Komfort. Über die CH32 Familie kann ich nicht
kommentieren, weil ich noch keinen Grund hatte, mich damit zu befassen -
stehe da eher neutral dazu. Vermutlich sind die Dokumentationen unserer
Hersteller zugänglicher, aber das ist Geschmacksache.
Die einzige chinesische uC Famile die mich peripherell interessiert,
sind STCs 8051 uC Flash programmierbare Derivate, die sich über UART
Flashen lassen. Und auch nur, weil mir einige zugelaufen sind und der
Keil MC51 kompatibel ist. Ob es sich lohnt viel Zeit zu investieren - da
bin ich eher skeptisch. Aber es wäre eine Gelegenheit die Tochter einer
anderen Mutter näher kennenzulernen.
Seid froh, dass es für die uC eures Herzen, vielfach freie mächtige
Entwicklungswerkzeuge gibt, die den Einstieg leicht machen. Arduino ist
für viele Sachen auch sehr zweckmässig, wobei dort, wenn man nicht uC
übergreifend arbeiten muß, auch dort wie sonst gewohnt, bare Metal
Zugang hat. Keiner ist gezwungen immer nur mit Libraries arbeiten zu
müssen. Arduino, dank GCC, wo kompatible, lässt da keine Wünsche offen.
Übergreifende uC Kompatibilität im Quellcode für Portabilität ist nicht
immer unbedingt für alle notwendig noch wichtig.
Gerhard
Gerhard O. schrieb:> Und bei den 8-bittern> stimmt es ja, dass Debugging in der Regel nicht vorgesehen ist.
Hätten sie bestimmt gerne implementiert, wenn der Hersteller (Atmel) das
nicht als geheimes Premium Feature für seine eigenen schweineteuren
Debugger reserviert hätte. Die Hardware ist inzwischen bezahlbar
geworden, aber das Protokoll immer noch geheim.
Gerhard O. schrieb:> Vermutlich sind die Dokumentationen unserer> Hersteller zugänglicher, aber das ist Geschmacksache.
Finde ich nicht. Ordentliche Dokumentation ist Grundvoraussetzung für
vernünftiges Arbeiten.
Norbert schrieb:> Alles was sich VT52,VT100,VT220, … nennt.> Und wahrscheinlich ein ganzer Sack voller korrekt implementierter> Terminal Emulationen. Selbst minicom, rudimentär in Python programmiert,> macht das.>> Als newline/neue Zeile:> 0x0d CR wird/wurde vom alten Apple genutzt.> 0x0d,0x0a CRLF wird von Windows genutzt.> 0x0a LF wird von allem Unixodiden genutzt.> 0x15 NL wird/wurde von IBM im EBCDIC genutzt.
Hallo Norbert,
Danke für den Hinweis. Von VT100 hatte ich schon gehört, da nie benötigt
fiel das immer hinten runter. ;-)
Norbert schrieb:> Alles was sich VT52,VT100,VT220, … nennt.
Nö. Die interpretieren CR als "springe an den Anfang der aktuellen
Zeile".
Erst in Kombination mit LF gibt es eine neue Zeile.
LF alleine positioniert den Cursor eine Zeile unter seiner bisherigen
Position, ändert aber nichts an seiner horizontalen Ausrichtung.
Allerdings nutzen die meisten Terminalemulatoren eine Einstellung, daß
sie auch einzelne CR bzw. LF wie eine Kombination aus CR+LF
interpretieren.
Harald K. schrieb:> Norbert schrieb:>> Alles was sich VT52,VT100,VT220, … nennt.>> Nö. Die interpretieren CR als "springe an den Anfang der aktuellen> Zeile".> Erst in Kombination mit LF gibt es eine neue Zeile.
Tja Harald, die korrekte Abfolge des Zitats lautet allerdings wie folgt:
Veit D. schrieb:
> Mit welchen Terminal '\r' sauber funktioniert weiß ich nicht. Ich kenne> keines was an den Anfang der Zeile springt und alles überschreibt.
Worauf ich antwortete:
Norbert schrieb:> Alles was sich VT52,VT100,VT220, … nennt.
Hallo Norbert,
richtig. Tera Term habe ich ausprobiert und es führt CR korrekt aus. Für
einen Zählerwert den Ralph in seinem Demoprogramm zeigt, ist das okay.
Funktioniert nur leider nicht mit dem Seriellen Monitor der Arduino IDE
und auch nicht mit hterm, welches ich auch sehr gern verwende. Da kann
man wie gesagt eine Anfrage stellen. Werde ich machen.
Veit D. schrieb:> Funktioniert nur leider nicht mit dem Seriellen Monitor der Arduino IDE> und auch nicht mit hterm
Da stören die Zeitstempel / time logs.
Veit D. schrieb:> Jetzt weiß ich nicht was Ralph für ein Terminal verwendet.> Ich hatte es mit dem Seriellen Monitor der Arduino IDE 1.8.19 und 2.3.8> probiert.
Ich verwende 2 Terminals, zum einen PuTTY, das so ziemlich alles kann,
was Datenübertragung angeht (auch SSH und Telnet), aber häufiger ein
(nur optisch) modifiziertes picocom
https://github.com/npat-efault/picocom in der Konsole!
Den seriellen Monitor der Arduino IDE verwende ich gerade wegen der
vielen Einschränkungen überhaupt nicht.
Veit D. schrieb:> Das heißt, du bist abhängig von Entwicklern> wie Ralph die einen Core schreiben, den du später nutzen kannst.
:-) um Mißverständnissen vorzubeugen, ich entwickle keinen Core, dafür
bin ich ein viel zu großer Arduino-Anfänger und werde das wohl auch
bleiben. Ich weiß, wie schon erwähnt nicht, was ein typischer
Arduino-User sich wünscht.
Ich schreibe nur Funktionalitäten für einen meiner Ansicht nach
unvollständigen Core, damit eben ein CH32V003 auch unter Arduino gut
verwendbar ist. Hier vordergründig SPI, I2C, ADC und UART (uart
funktioniert mit dem Core, allerdings nur schreibend, nicht lesend). Und
ich schreibe Demosketche, wie bspw. Timer2 verwendet werden kann. Die
Interruptbehandlung des CH32V003 Core ist ebenfalls unvollständig und
hier muß ich ein ebenfalls ein Workaround machen, damit man dieses
Nutzen kann. Ohne die Arduinofunktionen habe ich es bspw. noch nicht
erreicht, einen Interruptvektor aus einer Klasse heraus anszuspringen.
Aber ich lasse mich von Nörglern wie alecxs nicht abschrecken: er muß ja
einen CH32V003 nicht nutzen.
Meine "Versuchskanninchen" kommen mit den Funktionen die ich bereits
habe sehr gut zurecht, allerdings - geb ich zu - muß ich die Verwendung
erklären und es wartet eine Menge Doku auf mich.
Im Moment geht mir durch den Kopf, für den CH32V003 das Streaming um
eine Methode printf zu erweitern.
PS:
wenn ich gerade so über Unzulänglichkeiten nachdenke, erinnere ich mich
noch sehr genau, wie ich mich gewundert habe, wie ein einfaches
Arduino-Programm, welches eine 7-Segmentanzeige über einen TM1650
angesteuert hat, unverhältnismäßig groß geworden ist, und mich deshalb
in die Tiefen des Cores hinabbegeben habe. Als Übeltäter habe ich dann
delayMicroseconds() ausgemacht, welches soviele Dinge mit einbindet,
dass der Speicherbedarf bei Verwendung dieser delayMicroseconds um mehr
als 5600 Byte angestiegen ist (was bei einem gesamten Flashspeicher von
16 kByte enorm ist).
Also gibt es bei mir, wenn es genauer sein soll, hier eine Verzögerung,
die mittels Timer2 realisiert wird und wenn es ungenauer sein darf
schlicht über eine for schleife, in der __asm volatile(" nop ");
ausgeführt wird (und sicherlich schreien jetzt Arduino-User auf, weil
(eine einzige) Assembleranweisung in Arduino auftaucht. Grundsätzlich
glaube ich hier jedoch, dass die Speichereinsparung enorm ist und ein
Kommentar reicht, was man der Funktion zu übergeben hat. Wie die
Funktion dann die Mikrosekunden verzögert sollte dem Anwender dann egal
sein.
Ralph S. schrieb:> und ein Kommentar reicht, was man der Funktion zu übergeben hat. Wie die> Funktion dann die Mikrosekunden verzögert sollte dem Anwender dann egal> sein.
Die interna jucken meistens null, jedenfalls dann nicht wenn die
Funktion das macht was man braucht.
Erst wenn's nicht klappt, gehen die meisten erst mal library für library
durch bis eine funktionierende gefunden ist, gibt's da nichts, geht's
weiter:
KI, Foren, Aufgeben..
Ralph S. schrieb:> Ich weiß, wie schon erwähnt nicht, was ein typischer Arduino-User sich> wünscht.
Das muss im Prinzip wie PHP sein, der normale "Arduino Nutzer"
instbesondere diese die sich an diesen comfort gewohnt haben, will ein
analogWrite(Pin, Val) usw.
Hochsprache ohne mit Registern, Magic Numbers, bitoperation usw.
konfrontiert zu werden.
Wenn du das Benennungsschema nach dem richtest was es bereits gibt,
Funktionsnamen, übergabeparameter usw. fragt nicht mal jemand was im
Hintergrund abgeht, ob da nun "nop" oder "sackreisumgefallen" in der
Funktion steht, nach dem Motto analogWrite ist immer das gleiche
analogWrite weil es heißt ja analogWrite.
Es guckt keiner genau hin, aber dafür wurde es ja auch so konstruiert,
einstiegsfreundlich.
Das war auch mein Anfang. Ein Nano, LCD anstöpseln, library laden und
Loslegen. Erst mit dem PY32 kam so richtig Interesse auch "besser"
programmieren zu lernen. Gibt wenig librarys, wobei häufig die vom STM32
kompatibel sind. Und wie beim CH32 ein paar unschöne Mankos im core für
PY32, also sehr viel weniger, trotzdem doof. (Takt, GPIO usw..)
Das muss gestaltet sein das ein Kind das lernen kann, dann ist es
Arduino Nutzer tauglich. ;-)
Ralph S. schrieb:> Aber ich lasse mich von Nörglern wie alecxs nicht abschrecken
Sowas nennt man Übertragung. Ich habe kein Wort zu Deinem Core
gewechselt. Den hab ich mir noch nicht mal angeschaut, das war Veit. Bin
dann jetzt auch mal wieder still.
Kilo S. schrieb:> library laden und Loslegen.
Das ist genau das Entscheidende: Das Framework muss es ermöglichen, dass
Libraries ohne Anpassung einfach laufen.
Außerdem sollten die grundsätzlichen, in der Arduino IDE vorhandenen
Beispiel laufen:
blink ( setzt die Definition von LED_BUILTIN voraus )
analogReadSerial ( setzt voraus das analogRead und Serial funktioniert )
Serial.available muss unbedingt für die serielle Steuerung und
Datenübertragung funktionieren:
https://docs.arduino.cc/language-reference/de/funktionen/communication/serial/available/
Der I2C-Scanner sollte funktionieren
https://wolles-elektronikkiste.de/en/i2c-scanner
Kilo S. schrieb:> Das muss im Prinzip wie PHP sein, der normale "Arduino Nutzer"> instbesondere diese die sich an diesen comfort gewohnt haben, will ein> analogWrite(Pin, Val) usw.
Jetzt habe ich natürlich ein Problem: Ich weiß wie man den Core dazu
bringt, dass bspw. analogWrite(Pin, Val); so funktioniert, wie das auch
mit einem AVR-Board funktioniert und habe das auch schon gemacht. Es
erfordert dann einen Patch des Cores.
Das Problem ist jetzt: Gibt es ein Update des Core's und installiert
dieses, ist der Patch dann weg!
Am Beispiel des ADC (analogRead) die Frage, ist folgendes "noch in
Ordnung" für einen Arduino-User (die Klasse hat 2 öffentliche Methoden,
"read" und "calc_spg") oder sollte tatsächlich der Core gepatcht werden,
so dass man nur die analogRead Funktion hat:
1
#include "v003_adc.h"
2
3
// Objekte erzeugen, Konstruktor erwartet GPIO-Pin, auf dem
4
// ein analoger Wert eingelesen wird. Erlaubte Pins sind:
5
6
// PA2, PA1, PC4, PD2 .. PD6
7
ADC analog1(PD4);
8
ADC analog2(PA1);
9
10
// zum Einlesen einer Spannung (4990 ist die Betriebsspannung in mV als Referenz)dann:
Ralph S. schrieb:> Am Beispiel des ADC (analogRead) die Frage, ist folgendes "noch in> Ordnung" für einen Arduino-User (die Klasse hat 2 öffentliche Methoden,> "read" und "calc_spg") oder sollte tatsächlich der Core gepatcht werden,> so dass man nur die analogRead Funktion hat:
1
// PA2, PA1, PC4, PD2 .. PD6
2
ADCanalog1(PD4);
3
ADCanalog2(PA1);
Hier liegt ein ganz grundlegendes Verständnisproblem vor. Hernando
Barragán schreibt auf der zweiten Seite in
https://arduinohistory.github.io
1
Abstracting the microcontroller pins as numbers was, without a doubt, a major decision, possible because the syntax was defined prior to implementation in any hardware platform. All the language command naming and syntax were the result of an exhaustive design process I conducted, which included user testing with students, observation, analysis, adjustment and iteration.
Die Abstrahierten analogen Eingänge heißen bei den Arduino-Boards A0, A1
..
Christoph M. schrieb:> blink ( setzt die Definition von LED_BUILTIN voraus )> analogReadSerial ( setzt voraus das analogRead und Serial funktioniert )>> Serial.available muss unbedingt für die serielle Steuerung und> Datenübertragung funktionieren:> https://docs.arduino.cc/language-reference/de/funktionen/communication/serial/available/>> Der I2C-Scanner sollte funktionieren> https://wolles-elektronikkiste.de/en/i2c-scanner
Genau das alles macht der "offizielle Core" für den CH32V003 nicht, und
für LED_BUILTIN muß man wissen, dass Arduino in diesem Core "2"
verwendet und dieser als PC0 interpretiert wird. Noch nicht einmal ein
Textdisplay unter Verwendung von #include <LiquidCrystal.h> funktioniert
(Timingfehler)
Christoph M. schrieb:> Die Abstrahierten analogen Eingänge heißen bei den Arduino-Boards A0, A1> ..
ich glaube ich werde mich nie daran gewöhnen, bei Arduino die
Boardbezeichnungen anstelle der wahren Bezeichnung des Chips zu
verwenden. Will man wirklich so weit von der Hardware weg, dass das Teil
ein absolut abstraktes Stück Elektronik ist?
Hm, überlege ich, ob meine Library ADC auch um die Arduino-Namen für die
GPIO-Pins erweitert wird
Ralph S. schrieb:> Das Problem ist jetzt: Gibt es ein Update des Core's und installiert> dieses, ist der Patch dann weg!
Übermittel die Patches doch per GitHub an WCH bzw. an einen der anderen
auf GitHub die einen Core für CH32 bereitstellen.
Ich weiß nicht wie weit die den Code pflegen, ob die vorhaben selbst
noch was zu machen, so unvollständig kann der aber eigentlich kaum
bleiben.
Aber letzte Version von WCH direkt ist auch drei Jahre alt. (2023)
Ralph S. schrieb:> Will man wirklich so weit von der Hardware weg, dass das Teil> ein absolut abstraktes Stück Elektronik ist?
Man will:
1
Abstracting the microcontroller pins as numbers was, without a doubt, a major decision, possible because the syntax was defined prior to implementation in any hardware platform.
Ralph S. schrieb:> Das Problem ist jetzt: Gibt es ein Update des Core's und installiert> dieses, ist der Patch dann weg!
Solange Du keinen Pullrequest erstellt und dieser nicht angenommen und
gemerged wurde.
Christoph M. schrieb:> Man will:
Man will weniger denken. Mikrocontroller sind sehr unterschiedlich
(Warum?), und durchs Arduinieren werden sie alle gleich gemacht.
Alexander schrieb:> Veit D. schrieb:>> Funktioniert nur leider nicht mit dem Seriellen Monitor der Arduino IDE>> und auch nicht mit hterm>> Da stören die Zeitstempel / time logs.
Das kann man in beiden einstellen.
Christoph M. schrieb:> Ja, wer schlau ist, will das.
Schade wenn es halt nicht so wirklich klappt.
Ich muss dank Arduino sogar "mehr denken". Das gleiche Problem
(Benennung, Parameter, Rückgabewerte) hab ich auch wenn ich Code
produzieren möchte der anderen helfen kann.
Beispiel Beitrag "Re: Fumot Tornado 25000 mit LCD -Teardown"
Setzte das dem blutigen Anfänger vor der die IDE vielleicht seit einem
Monat benutzt, der wird erst mal Fragezeichen in den Augen haben.
Ohne Erklärung kommt der damit vermutlich nicht direkt weiter, schon der
Unterschied zwischen der Schreibweise LCD_ (Uppercase!) Zu lcd.
(Lowercase) der Standard library. (Hab's getestet! Mein Nachbar,
wandelndes Klischee der Arduino Welt. Tutorial kopieren, scheitern,
nächstes Tutorial. Das ist ein Loop bis irgendwann der Frust so groß ist
das er hin wirft oder zufällig mal ein Versuch klappt.)
Das bringt Manche Leute völlig aus dem Konzept.
Lustigerweise, lcd.print, lcd.prinln usw.. kennt der alles!
Er war nicht in der Lage aus diesem "Quasistandard" auszubrechen.
Erst als ich ihm erklärt habe das LCD_DrawString theoretisch lcd.println
entspricht hat er es halbwegs kapiert.
Klar, ist eines der extremen Beispiele, es gibt in der Arduino Fraktion
so viele Facetten, auch Leute die (Guck ich mir ja auch zum Teil so ab)
die IDE auch nur als IDE mit kompilerfunktion nutzen. Da wird dann bare
Metal oder mit HAL gearbeitet, klappt erstaunlich gut.
Einerseits geiler scheiß, niedriger Einstieg, günstige Hardware,
schneller Erfolg.
Andererseits Beihilfe zur aktiven Verdummung!
Alles hat halt gute und schlechte Seiten.
Veit D. schrieb:> ... Da kann man wie gesagt eine Anfrage stellen. Werde ich machen.
Zum Thema Nachfrage wegen der CR Fehlinterpretation der Arduino IDE hat
sich ganz schnell geklärt. Dazu gibt es schon "Hunderte" Anfragen, wird
alles abgelehnt. Bsp. https://github.com/arduino/arduino-ide/issues/406
Da wird nichts passieren, man muss ein anderes Terminal verwenden.
Tera Term und putty funktionieren bspw..