Forum: Mikrocontroller und Digitale Elektronik Variable in _delay_ms() einfügen


von Michael H. (h_m)


Lesenswert?

Guten Abend,

ich habe nachfolgenden Code geschrieben. In dem ich einen Analogenwert 
einlesen will, und den Wert des ADCH Registers dann praktisch in 
delay_ms() einfügen damit sich dann je nach Stellung des potis die Zeit 
ändert. Es kommt immer eine Fehlermeldung, was mache ich hier falsch. 
könnte mir das BITTE jemand zeigen ?
1
/*
2
 * ATTINY_85.c
3
 *
4
 * Created: 03.03.2018 15:59:47
5
 * Author : USER
6
 */ 
7
#define F_CPU 1000000UL
8
#include <avr/io.h>
9
#include <util/delay.h>
10
11
uint8_t WERT = 0;
12
uint8_t t = 0;
13
14
15
int main(void)
16
{
17
    DDRB &= ~ (1<<PB2); // auf Eingang Bewegungsmelder
18
  DDRB =    (1<<PB3); // auf Ausgang Magnetventil
19
  
20
  // ADC INIT
21
  ADMUX = (1<<REFS0); // Referenzspannung Vcc wählen +5V
22
  ADMUX = (1<<MUX1);  // Kanal 1 PB1 wählen
23
  ADCSRA = (1<<ADEN); // ADC freigeben / aktivieren
24
  ADCSRA = (1<<ADSC); // ADC starten
25
  ADCSRA = (1<<ADPS2);// Prescaler /16 
26
  ADMUX = (1<<ADLAR); // Ausgabe linksbündig ADCH Register
27
  
28
  
29
    while (1) 
30
    {
31
    WERT = ADCH;
32
    t = WERT*3;
33
    
34
    if (PINB & (1<<PB2))
35
    {
36
      PORTB |= (1<<PB3);
37
      _delay_ms(t);
38
    } 
39
    else
40
    {
41
      PORTB &= ~(1<<PB3);
42
    }
43
    }
44
}

und hier wäre die Fehlermeldung.:
1
Severity  Code  Description  Project  File  Line
2
Error    recipe for target 'main.o' failed  Attiny85  C:\Users\USER\Documents\Atmel Studio\7.0\Attiny85\Attiny85\Debug\Makefile  79

1
Severity  Code  Description  Project  File  Line
2
Error    __builtin_avr_delay_cycles expects a compile time integer constant  Attiny85  c:\program files (x86)\atmel\studio\7.0\toolchain\avr8\avr8-gnu-toolchain\avr\include\util\delay.h  187

von Uhrmacher (Gast)


Lesenswert?

Hier steht er doch, der Fehler:

Michael H. schrieb:
> Error    __builtin_avr_delay_cycles expects a compile time integer
> constant

Will heissen du dafst _delay_ms(..) keine Variable übergeben
sondern nur eine Konstatnte.

von sumo (Gast)


Lesenswert?

Der Compiler will eine Integer-Konstante als Argument für delay() haben. 
Du bietest ihm eine Variable an.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Steht doch da, _delay_ms() erwartet eben keine Variable, sondern eine 
Konstante.

Kannst du durch sowas lösen:
1
void MyDelay(uint16_t t) {
2
 while(t > 0) {
3
   _delay_ms(1);
4
    t--;
5
 }
6
return;
7
}
oder ähnlich.

: Bearbeitet durch User
von Michael H. (h_m)


Lesenswert?

kann ich das dann gar nicht so bewerkstelligen, das ich mit dem Poti die 
verzögerungszeit einstelle. Das heißt ich kann nur eine ganze 
unveränderliche Zahl eingeben.

von sumo (Gast)


Lesenswert?

Michael H. schrieb:
> kann ich das dann gar nicht so bewerkstelligen, das ich mit dem
> Poti die
> verzögerungszeit einstelle. Das heißt ich kann nur eine ganze
> unveränderliche Zahl eingeben.

Doch, so wie Matthias es vorgeschlagen hat.
Da rufst du delay(1) so oft auf, wie du Millisekunden brauchst.

von Dominik (Gast)


Lesenswert?

Michael H. schrieb:
> kann ich das dann gar nicht so bewerkstelligen, das ich mit dem
> Poti die verzögerungszeit einstelle. Das heißt ich kann nur eine ganze
> unveränderliche Zahl eingeben.

Doch, indem Du wie Matthias schrieb ein fixes Delay von z.B. einer ms 
öfter abarbeitest.

Matthias S. schrieb:
> Steht doch da, _delay_ms() erwartet eben keine Variable, sondern
> eine Konstante.
>
> Kannst du durch sowas lösen:void MyDelay(uint16_t t) {
>  while(t > 0) {
>    _delay_ms(1);
>     t--;
>  }
> return;
> }
>
> oder ähnlich.

Braucht tatsächlich etwas länger als die x mal 1 ms, kann hier aber 
sicher vernachlässigt werden.
Der Königsweg wäre ein Hardwaretimer.

Gruß Dominik

von Einer K. (Gast)


Lesenswert?

Dominik schrieb:
> Der Königsweg wäre ein Hardwaretimer.

Denn irgendwann wird die Anforderung kommen:
"Ich möchte die Wartezeit für andere sinnvolle Aufgaben nutzen!"
Spätestens dann gehts nicht mehr ohne.

von Curby23523 N. (Gast)


Lesenswert?

Grundlagen, Grundlagen, Grundlagen.

_delay_ms(x); ist gut zum testen, wenn man schnell eine fixe Delayzeit 
braucht. Ansonsten IMMER einen Hardware-Timer verwenden. Wie schon 
gesagt, funktioniert diese Funktion nur mit Konstanten.

Z.B. ein Hardware-Timer macht einen Interrupt von 1ms und zählt eine 
uint32_t  Variable hoch. Dann ist das dein Software-Zeitstempel.

Datenblatt runterladen und Kapitel über Timer durchlesen und 
ausprobieren!

von Gordonk (Gast)


Lesenswert?

Letztlich kann ein Mikrocontroller ja nur zwei Dinge: etwas berechnen 
und sich an etwas erinnern. Nur kann er das irre schnell. Diesen Vorteil 
der Geschwindigkeit nimmst du ihm mit solchen Warte-Funktionen.

Darum empfehle ich dass du dir Artikel zum Thema Multitasking 
durchliesst. Es gibt sowohl hier auf mikrocontroller.net aber auch auf 
embeddedrelated.com sehr gute Artikel dazu. Timer bringen auch mehr 
Verständnis zu anderen Applikationen.

von Walter S. (avatar)


Lesenswert?

Michael H. schrieb:
> DDRB &= ~ (1<<PB2); // auf Eingang Bewegungsmelder
>   DDRB =    (1<<PB3); // auf Ausgang Magnetventil

da könntest du die erste Zeile streichen, es sei denn du wolltest 
eigentlich schreiben
DDRB |=    (1<<PB3); // auf Ausgang Magnetventil

desweiteren musst du nach dem Start der AD-Wandlung warten bis die 
Wandlung erfolgt ist, das machst du nicht!

von Walter S. (avatar)


Lesenswert?

da ist noch viel mehr seltsam:

die Reihenfolge Intialisierung/Starten der Wandlung
Überlauf bei der Multiplikation mit 3

Ansonsten sind die Vorschläge mit Multitasking prinzipiell zwar richtig,
aber vergiss sie erst Mal für einige Zeit bis du etwas mehr Überblick 
hast

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.