Guten Tag,
Warum funktioniert delayMicroseconds() nicht mit einer variable? Ich
dachte delay() und delayMicroseconds() sind extra für variable geeignet.
delay() spuckt auch keine Fehler aus, aber das andere ja.
c:\users\reder\desktop\arduino-nightly\hardware\tools\avr\avr\include\util\delay.h: In function 'main':
4
5
c:\users\reder\desktop\arduino-nightly\hardware\tools\avr\avr\include\util\delay.h:276:28: error: __builtin_avr_delay_cycles expects a compile time integer constant
6
7
__builtin_avr_delay_cycles(__ticks_dc);
8
9
^
10
11
lto-wrapper.exe: fatal error: C:\Users\reder\Desktop\arduino-nightly\hardware\tools\avr/bin/avr-gcc returned 1 exit status
Erik H. schrieb:> Warum funktioniert delayMicroseconds() nicht mit einer variable? Ich> dachte delay() und delayMicroseconds() sind extra für variable geeignet.
Das ist bei den originalen Arduino Cores auch der Fall.
Warum der Ersteller deiner exotischen Boarddefinition davon abgewichen
ist, naja....
Vielleicht, wegen der Zwergigkeit des ATtiny13?
> void long_delay(uint16_t us)> {> for(; us>0; us--) delayMicroseconds(1);> }
Sorry, das war mal Unfug... beim herunterzählen der us wird durch die
verwendeten Prozessortakte Zeit unterschlagen, welches massive
Auswirkungen auf das Ergebniss hat.
Wenn dies bei Millisekunden angewandt wird ist es nicht so Dramatisch,
wenn auch unschön. Das es bei der delay() Funktion funktioniert, könnte
daran liegen das solch eine Funktion verwendet wird.
danke, auch die unschöne version ist ausreichend.
Dann liegt das also am Board, dass delayMicroseconds nicht funktioniert?
Evtl finde ich noch ein anderes Board.
Hallo,
übersehe ich etwas wichtiges? Laut Beschreibung nutzt er unter "der
Haube" von delayMicroseconds(us) das standardmäßige _delay_us(us).
Deswegen gehe ich davon das es funktioniert. Von der Sache her kann man
dann auch gleich _delay_us(us) verwenden.
Hallo,
bevor ich etwas übersehe habe ich mir eine Portable eingerichtet und den
Blink Sketch auf delayMicroseconds(1000) abgeändert. Es kompiliert auch
mit Variable. _delay_us(1000) kompiliert auch.
Falls man millis oder micros verwendet muss man in Boardmenü "Timing"
auf enable setzen.
Veit D. schrieb:> Es kompiliert auch mit Variable.
Teste mal dieses:
1
voidsetup()
2
{
3
volatiledoubletest=55.44;
4
_delay_us(test);
5
}
6
7
voidloop()
8
{
9
10
}
Aus der Doku:
Note
In order for these functions to work as intended, compiler optimizations
must be enabled, and the delay time must be an expression that is a
known constant at compile-time. If these requirements are not met, the
resulting delay will be much longer (and basically unpredictable), and
applications that otherwise do not use floating-point calculations will
experience severe code bloat by the floating-point library routines
linked into the application.
Hi
>aha okay, funktioniert nur mit Konstanten.
Man, das hat ja echt lange gedauert. Diese Einschränkung kenne ich schon
aus den Zeiten von KHB. Aber dafür seit ihr wohl noch zu jung in C.
MfG Spess
spess53 schrieb:> Man, das hat ja echt lange gedauert. Diese Einschränkung kenne ich schon> aus den Zeiten von KHB. Aber dafür seit ihr wohl noch zu jung in C.>> MfG Spess
Wenn man mal den Sourcecode anschaut, erkennt man setup() und loop()
Das ist zuerst einmal ziemlich Arduino typisch.
Schauen wir mal in die Dokumentation (hab' gerade 1.8.12 hier):
1
delayMicroseconds()
2
Description
3
Pauses the program for the amount of time (in microseconds) specified as parameter. There are a thousand microseconds in a millisecond, and a million microseconds in a second. Currently, the largest value that will produce an accurate delay is 16383. This could change in future Arduino releases. For delays longer than a few thousand microseconds, you should use delay() instead.
4
5
Syntax
6
delayMicroseconds(us)
7
8
Parameters
9
us: the number of microseconds to pause (unsigned int)
10
Returns
11
None
12
13
Caveats and Known Issues
14
This function works very accurately in the range 3 microseconds and up. We cannot assure that delayMicroseconds will perform precisely for smaller delay-times.
Also ich kann anhand der Dokumentation auf den ersten Blick NICHT
erkennen das man hier nur mit Konstanten arbeiten darf.
Wer sich schon lange mit Thema beschäftigt hat, also vor der Arduino
Zeit, weiß natürlich das die delay_us() Funktion so gestrickt sind.
Schauen wir mal in die Implementierung,
in hardware/arduino/avr/cores/arduino/wiring.c
Auch da wird nichts von Konstanten gesagt. Wir finden eine Reihe von
Anpassungen für versch. Taktfrequenzen und dann...
1
__asm__ __volatile__ (
2
"1: sbiw %0,1" "\n\t" // 2 cycles
3
"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
4
);
Es bietet sich also an auch mal den Ball flach zu halten und nicht
einfach Trumpartig Meinungen heraus zu blasen.
Norbert schrieb:> und dann...
Natürlich ist eine Zahlervariable variabel, aber jetzt ist da nur noch
die Frage, ob an die Stelle, an der subtrahiert wird, zur Laufzeit ein
variabler Wert geschrieben werden kann.
Und wie der ggfs. zur Laufzeit für eine Taktfrequenz von ż. B. 13, 792
MHz innerhalb von 3us ausgerechnet werden kann...
BTW ein Programm sollte sich nie auf Delays im us Bereich verlassen.
Denn immerhin war da noch die Sache mit den Interrupts, die da
reinfunken können.
delay() != delayMicroseconds()
Ersteres benötigt einen konstanten Parameter, weil der Wert per Formel
umgerechnet wird und darin der Parameter enthalten ist. Zur Laufzeit
durchgeführt kann diese Rechnung massiv beeinflussen.
Die Umrechnung von Letzterem wird bewusst so durchgeführt, dass die
Umrechnung sehr einfach wird und keinen konstanten Parameter erfordert.
Sie setzt jedoch eine Taktfrequenz von den im Quellcode gezeigten
1/8/16/... MHz voraus. Deutlich abweichende Werte führen zu falschen
Delays
Norbert schrieb:> Es bietet sich also an auch mal den Ball flach zu halten und nicht> einfach Trumpartig Meinungen heraus zu blasen.
Bist du denn sicher, dass das überhaupt die richtige Implementation ist?
Wo ist dort der Aufruf von __builtin_avr_delay_cycles, wo im
Ursprungsposting der Fehler gemeldet wird?
Rolf M. schrieb:> Bist du denn sicher, dass das überhaupt die richtige Implementation ist?
Das auch noch. Das vom TE genutzte delayMicroseconds ist jedenfalls
nicht das, was in wiring.c implementiert ist.
Lothar M. schrieb:> Natürlich ist eine Zahlervariable variabel, aber jetzt ist da nur noch> die Frage, ob an die Stelle, an der subtrahiert wird, zur Laufzeit ein> variabler Wert geschrieben werden kann.
Ja kann, laut source code in wiring.c
Dort sieht man auch das für verschiedene Arduino boards mit festen
Frequenzen gearbeitet wird. Muss mal eben den vi starten...
1
/* Delay for the given number of microseconds. Assumes a 1, 8, 12, 16, 20 or 24 MHz clock. */
Und da hat es dann versch. Korrekturwerte.
> Und wie der ggfs. zur Laufzeit für eine Taktfrequenz von ż. B. 13, 792> MHz innerhalb von 3us ausgerechnet werden kann...
Arduino boards mit festen Frequenzen lt. wiring.c
> BTW ein Programm sollte sich nie auf Delays im us Bereich verlassen.> Denn immerhin war da noch die Sache mit den Interrupts, die da> reinfunken können.
Selbstverständlich sollte man sich nie auf Delays im us Bereich
verlassen, es sei denn man hat sie selbst geschrieben oder den
Sourcecode verifiziert.
Der ist Arduino-typisch ziemlich schmutzig und macht einfach mal
Annahmen die wohl zur Sourcecode-Erstellungszeit empirisch ermittelt
(ausprobiert) wurden.
Wir reden hier aber eben vom Arduino Umfeld, also eher etwas für
BWL-Abbrecher. ;-)
Rolf M. schrieb:> Bist du denn sicher, dass das überhaupt die richtige Implementation ist?
Sicher? Nö.
Ich habe gesehen das der OP eine Arduino Version 1.8.14 benutzt, und
habe in meine Antwort geschrieben das ich hier nur eine 1.8.12 habe.
Norbert schrieb:> Der ist Arduino-typisch ziemlich schmutzig und macht einfach mal> Annahmen die wohl zur Sourcecode-Erstellungszeit empirisch ermittelt> (ausprobiert) wurden.>> Wir reden hier aber eben vom Arduino Umfeld, also eher etwas für> BWL-Abbrecher. ;-)
Dummschwätzer.
Brett vom Schädel.
Großes Maul aber Tomaten auf den Augen.
Und offensichtlich viel Luft zwischen den Ohren.
Wie genau die Arduino Implementierung ist, findet sich in der Arduino
Doku.
https://www.arduino.cc/reference/de/language/functions/time/delaymicroseconds/
Tut hier aber überhaupt nichts zur Sache.
Dass auf einem ATTiny13 nicht die komplette Arduino Framework
Implementierung nutzbar ist, sollte auch dir klar sein.
Ist es dir aber nicht.
Zu blöd, zu blind und zu doof zum hinschauen.
Von dieser, hier verwendeten, Boarddefinition wird statt dessen die AVR
LibC _delay_us() verwendet. Und aus der Ecke kommt auch die
Fehlermeldung.
Dein Dummschwätz betrifft also ALLEAVR-Gcc Nutzer.
Norbert schrieb:> Ich habe gesehen das der OP eine Arduino Version 1.8.14 benutzt, und> habe in meine Antwort geschrieben das ich hier nur eine 1.8.12 habe.
Hat damit überhaut nichts zu tun.
NICHTS.
Einfacher Grund:
Die Boarddefinition gehört nicht zu Arduino selber.
Norbert schrieb:> Ja kann, laut source code in wiring.c
Eine Lüge!
Eine dumm dreiste Lüge!
Ich habe eben/gestern schon die konkrete Stelle verlinkt.
Hier nochmal extra für dich, zum mitmeißeln:
https://github.com/MCUdude/MicroCore/blob/9199e45eb749d34c4f73b5112b62bad5698a1906/avr/cores/microcore/Arduino.h#L91
Du siehst: Nix wiring.c, sondern Arduino.h
A. K. schrieb:> Sie setzt jedoch eine Taktfrequenz von den im Quellcode gezeigten> 1/8/16/... MHz voraus. Deutlich abweichende Werte führen zu falschen> Delays
Kann bei der originalen Arduino Borddefinition nicht vor kommen, da die
Frequenzen der originalen Boards bekannt sind.
Abweichler benötigen eine Extrawurst.
Wie diese hier, in diesem Thread, für den Tiny13.
Christoph M. schrieb:> Erstaunlich, im Funktionsheader ist ein "double" als Parameter, stimmt> da die Doku?:> void _delay_us ( double __us )
Ja. Und genau deshalb muss man es mit einer Konstanten als Parameter
verwenden. Sonst müssen die floating-point-Berechnungen zur Laufzeit
durchgeführt werden, was ggf. länger dauert als das eigentliche Delay
und sehr viel Flash benötigt.