delayMicroseconds() Error. Keine Variable erlaubt.

OP #6349668
Lesenswert?

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.
1
unsigned int pwm = 2000;
2
int c = 0;
3

4
void setup() {
5
  // put your setup code here, to run once:
6
pinMode(1,OUTPUT);
7
}
8

9
void loop() {
10
  // put your main code here, to run repeatedly:
11
pwm = 100;
12
digitalWrite(1,HIGH);
13
delayMicroseconds(pwm);
14
digitalWrite(1,LOW);
15
delayMicroseconds(20000);
16
}

Fehlermeldung:
1
Arduino: 1.8.14 Hourly Build 2020/07/13 05:33 (Windows 10), Board: "ATtiny13, 9.6 MHz internal osc., BOD 2.7V, Micros disabled"
2

3
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
12

13
compilation terminated.
14

15
c:/users/reder/desktop/arduino-nightly/hardware/tools/avr/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld.exe: error: lto-wrapper failed
16

17
collect2.exe: error: ld returned 1 exit status
18

19
exit status 1
20

21
Fehler beim Kompilieren für das Board ATtiny13.
Gast #6349710
Lesenswert?

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?
#6349753
Lesenswert?

> 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.
Beitrag #6349793 wurde von einem Moderator gelöscht.
#6350001
Lesenswert?

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.
Gast #6350011
Lesenswert?

Veit D. schrieb:
> Es kompiliert auch mit Variable.

Teste mal dieses:
1
void setup() 
2
{
3
  volatile double test = 55.44;
4
  _delay_us(test) ;
5
}
6

7
void loop() 
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.
Gast #6350225
Lesenswert?

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
Gast #6350319
Lesenswert?

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.
Moderator (Firma: Titel) Persönliche Seite #6350351
Lesenswert?

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.
#6350355
Lesenswert?

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
Gast #6350365
Lesenswert?

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. ;-)
Gast #6350406
Lesenswert?

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 ALLE AVR-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
Beitrag #6350417 wurde von einem Moderator gelöscht.
Beitrag #6350419 wurde von einem Moderator gelöscht.
Gast #6350511
Lesenswert?

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.
Gast #6350524
Lesenswert?

Christoph M. schrieb:
> Der Link zur avr-libc fehlt hier vielleicht noch:
> https://www.nongnu.org/avr-libc/user-manual/group__util__delay.html
>
> Erstaunlich, im Funktionsheader ist ein "double" als Parameter, stimmt
> da die Doku?:
> void _delay_us   ( double __us )
Ja, das stimmt!
Beitrag "Re: delayMicroseconds() Error. Keine Variable erlaubt."

Da der Wert zur Kompilezeit bekannt ist, kann er auch zur Kompilezeit 
umgerechnet werden.
Steht auch in der verlinkten Doku so.
#6350529
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren