Forum: Mikrocontroller und Digitale Elektronik ADC problem mit delay


von Wilfried (wil_w)


Lesenswert?

hallo Leute
der klatschalter macht eigentlich was er machen soll. Bei einem Geräusch
schaltet er die LED ein und nach drei sek. wieder aus. Was mir nicht 
klar ist
das ich eine delay von 20000 wählen muss um auf drei Sekunden zu kommen.
Eigentlich müsste eine delay von 3000 richtig sein. Kann mir jemand 
sagen
warum? es so ist.
1
 //CPU 1200000
2
 //ATTINY 13a                                                       
3
 //Klatsch Schalter
4
#include<avr/io.h>
5
#include<util/delay.h>
6
int main (void)
7
{
8
DDRB = 0b00000001;
9
PORTB = 0b00011000;
10
ADMUX = 2;
11
ADCSRA = (1<<ADEN)+(1<<ADSC)+(1<<ADATE)+(1<<ADPS2);
12
13
_delay_ms(1000);
14
15
while(1)
16
{
17
while ((ADCSRA & (1<<ADIF))==0);
18
if (ADC<1014)
19
20
{
21
PORTB |= 0b00000001;
22
_delay_ms(20000);
23
PORTB &=~ 0b00000001;
24
//_delay_ms(1000);
25
}
26
ADCSRA |= (1<<ADIF);
27
}
28
}

[Mod: bitte künftig selber die [c] Tags setzen wie in der 
Bedienungsanleitung über jeder Texteingabebox beschrieben]

: Bearbeitet durch Moderator
von N. M. (mani)


Lesenswert?

Mit Meeresfehler könnte das ein Faktor von 8 sein.
Erster Verdacht: schau Mal die ClkDiv8 Fuse an. Ein Klassiker 😉

von Wastl (hartundweichware)



Lesenswert?

Wilfried schrieb:
> hallo Leute

Hallo Wilfried,

guck doch mal das Bildchen oben an.

von Rolf M. (rmagnus)


Lesenswert?

Wilfried schrieb:
> Kann mir jemand
> sagen
> warum? es so ist.

Auf was ist den F_CPU eingestellt, wie sind die Fuses eingestellt, und 
das ist deine Taktquelle? Das muss alles zusammenpassen, damit die 
Delays stimmen.
Wenn du 20000 statt 3000 einstellen musst, deutet das darauf hin, dass 
dein µC mit einem höheren Takt läuft als du per F_CPU angibst.

: Bearbeitet durch User
von Klaus H. (hildek)


Lesenswert?

Wilfried schrieb:
> _delay_ms(20000);
Durch den Datentyp des Parameters (double) kannst du eine maximale 
Verzögerung von 6,5535 Sekunden erreichen.

Nix mit 20000!

von Rolf M. (rmagnus)


Lesenswert?

Klaus H. schrieb:
> Wilfried schrieb:
>> _delay_ms(20000);
> Durch den Datentyp des Parameters (double) kannst du eine maximale
> Verzögerung von 6,5535 Sekunden erreichen.

Das hat nichts mit double zu tun. Mit dem Datentyp kannst du auch Delays 
angeben, die dem mehrfachen der Lebensdauer des Universums entsprechen. 
Die Begrenzung des Delays kommt dadurch, dass intern für die 
Warteschleife ein Zähler mit begrenzter Größe verwendet wird und liegt 
auch bei ganz anderen Werten. Siehe 
https://avrdudes.github.io/avr-libc/avr-libc-user-manual-2.2.0/group__util__delay.html#gad22e7a36b80e2f917324dc43a425e9d3

> Nix mit 20000!

Bei sehr veralteten avr-Toolchains kann es tatsächlich sein, dass das zu 
lang ist, hängt aber vom Takt ab.

von Axel R. (axlr)


Lesenswert?

Klaus H. schrieb:
> Wilfried schrieb:
>> _delay_ms(20000);
> Durch den Datentyp des Parameters (double) kannst du eine maximale
> Verzögerung von 6,5535 Sekunden erreichen.
>
> Nix mit 20000!

Na doch. Das geht schon. Allerdings mit verringerter Auflösung von nur 
noch ner Zehntel MilliSekunde.
Steht im Manual
1
When the user request delay which exceed the maximum possible one, _delay_ms() provides a decreased resolution functionality. In this mode _delay_ms() will work with a resolution of 1/10 ms, providing delays up to 6.5535 seconds (independent from CPU frequency). The user will not be informed about decreased resolution.
Oder interpretiere ich das falsch?
Ebenso steht dort, wenn man F_CPU nicht angibt, er als „fallback“  1Mhz 
zur Berechnung verwendet.

https://www.nongnu.org/avr-libc/user-manual/group__util__delay.html

von Falk B. (falk)


Lesenswert?

Axel R. schrieb:
> Oder interpretiere ich das falsch?

Nein, das siehst du korrekt, aber die fehlende Warnung bei zu großen 
Parametern ist doof. Mit 0,1ms Auflösung kann man problemlos leben.

von Klaus H. (hildek)


Lesenswert?

Ich habe das von 
https://de.wikibooks.org/wiki/C-Programmierung_mit_AVR-GCC/_Warteschleifen

Kann sein, dass es veraltet ist.
Ich meine aber auch, dass bei mir schon aufgetaucht ist, wobei mein 
Compiler auch alt ist (WinAVR-20100110).

von Axel R. (axlr)


Lesenswert?

In muss man aber doch fairerweise eingestehen, dass (20000), also 
20Sekunden schon weit weg von den möglichen 6komma5 Sekunden sind, die 
dort als Maximum angegeben wurden. Auflösung hin oder her.
Muss man direkt mal ausprobieren (geht jetzt hier am Handy schlecht)

von Mario M. (thelonging)


Lesenswert?

Aktuelle Compiler machen aus der delay-Funktion einen Zähler mit 
mehreren Bytes. Da sind problemlos mehrminütige Delays möglich.

von Rahul D. (rahul)


Lesenswert?

Mario M. schrieb:
> Aktuelle Compiler machen aus der delay-Funktion einen Zähler mit
> mehreren Bytes. Da sind problemlos mehrminütige Delays möglich.

Die maximale Delaytime sollte doch irgendwo dokumentiert sein.

von Mario M. (thelonging)


Lesenswert?

Das wurde oben mehrfach verlinkt. Zusammenfassung: Mit einer aktuellen 
AVR-GCC-Toolchain und konstantem Delay-Wert sind es rund 4295 Sekunden 
geteilt durch die CPU-Frequenz in MHz.

von Rahul D. (rahul)


Lesenswert?

Mario M. schrieb:
> Das wurde oben mehrfach verlinkt. Zusammenfassung: Mit einer aktuellen
> AVR-GCC-Toolchain und konstantem Delay-Wert sind es rund 4295 Sekunden
> geteilt durch die CPU-Frequenz in MHz.

Dann ist ja alles klar.

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


Lesenswert?

Hi hi hi....
Eine lustige Diskussion!

Da lobe ich mir doch die Arduino delay() Funktion.
Die ist (fast) gut Dokumentiert.
Man kann während dessen noch (kooperativ, dank yield()) anderen Kram 
erledigen.
Auch verlängern ISR Läufe nicht die delay() Zeit.

----------

Meinen Dank, für die Gelegenheit, diesen Einwurf machen zu dürfen.

: Bearbeitet durch User
von Axel R. (axlr)


Lesenswert?

Arduino F. schrieb:
> Hi hi hi....
> Eine lustige Diskussion!
>
> Da lobe ich mir doch die Arduino delay() Funktion.
> Die ist (fast) gut Dokumentiert.
> Man kann während dessen noch (kooperativ, dank yield()) anderen Kram
> erledigen.
> Auch verlängern ISR Läufe nicht die delay() Zeit.
>
> ----------
>
> Meinen Dank, für die Gelegenheit, diesen Einwurf machen zu dürfen.

auf 'nem ATtiny13. jo nee - iss klar. Viel Spaß mit "yield()"
Das passt irgendwie nicht zusammen.

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


Lesenswert?

Axel R. schrieb:
> Das passt irgendwie nicht zusammen.
Einerseits hast du Wahr: Es gibt keinen t13 Arduino.
Es gibt nur derbe abgespeckte t13 Cores für die Arduino IDE

Andererseits, ist die _delay_ms() eine Beilage für alle AVR Arduinos
Nutzt dort nur kaum jemand.

Ausnahme:
Die/Der Ersteller des https://github.com/MCUdude/MicroCore
1
void delay(uint16_t ms)
2
{
3
  while(ms--)
4
    _delay_ms(1);
5
}

von Axel R. (axlr)


Lesenswert?

Arduino F. schrieb:
> Es gibt nur derbe abgespeckte t13 Cores für die Arduino IDE

Ja weiß ich. nehm ich auch ganz gern.
(hab da gerade einen Tiny2313 - kein t13! -  mit mini-mikro-Oled und 
Betriebsspannungsanzeige am Basteln, der statt der originalen 
Ladekontrollleuchte in die Bajonettfassung gesteckt wird. (Moped MZ 
TS175) Allerdngs mit VSCode und PlatformIO. Wenns absolut nicht 
draufgeht, nehm ich wieder WinAVR und ProgrammersNotepad ;)
bislang kann ich micht erinnern, jemals mit dem Problem konfrontiert 
worden zu sein. delay(20000) wartet jedenfalls brav 20 Sekunden. Vorhin 
probiert. Müsste man sich das LST ausgeben lassen, was die dort 
veranstalten. wahrscheinlich, we oben angegeben eine while mit 
_delay_ms(1) lt. Doku ginge das ja sonst garnicht.

: Bearbeitet durch User
von Axel R. (axlr)


Lesenswert?

nochmal zum eigentlichen Thema,
#define F_CPU 12E6
oder #define F_CPU 12000000
mit vor die #include(s) sollte das eigentliche Problem abstellen, denke 
ich.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Axel R. schrieb:
> lt. Doku ginge das ja sonst garnicht.
Nochmal der Verweis auf die Doku:
- https://www.nongnu.org/avr-libc/user-manual/group__util__delay.html

> wahrscheinlich we oben angegeben eine while mit _delay_ms(1)
Warhscheinlich mit einem _delay_ms(0,1) weil das ja die Auflösung ist 
und dann (2^32-1)*0,1s lange Delays möglich sind.

Man muss eben nur den Prescaler richtig einstellen. Wenn man den falsch 
einstellt, sind sogar noch deutlich längere Delays möglich.

Axel R. schrieb:
> #define F_CPU 12000000
Da fehlt ein UL hinten dran. Denn 12000000 passt nicht in einen 
16-Bit-Integer.

: Bearbeitet durch Moderator
von Wilfried (wil_w)


Lesenswert?

Hallo Leute
Vielen Dank für die zahlreichen Antworten. Habe den Fehler gefunden.
Es sieht so aus als wäre der Mikrochip das Problem. Ich habe einen neuen 
Chip genommen und siehe da es funktioniert auf Anhieb. Habe noch mit den 
"delay" verschiedene Zeiten probiert es klappt ohne Probleme.
Nochmals vielen Dank.
Wilfried

von Mario M. (thelonging)


Lesenswert?

Nicht der Chip ist das Problem, sondern die Einstellung der "Fuses". Die 
Einstellung der Taktfrequenz passt einfach nicht zum Wert von F_CPU in 
Deinem Programm.

von Wilfried (wil_w)


Lesenswert?

Hallo Mario
Die "Fuses" waren-sind h-0xFF und l-0x6A .
Gruß Wilfried

von Mario M. (thelonging)


Lesenswert?

Sehr interessant, da müsste ja der Prescaler kaputt sein.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.