Forum: Mikrocontroller und Digitale Elektronik LEDs blinken mit einstellbarer Frequenz/Leuchtdauer


von Stefan S. (derprogrammierer2)


Lesenswert?

Hey!

Das eine LED blinkt ist kein Problem. Ich habe jetzt aber versucht in 
meiner _delay_ms() Funktion eine Variable zu setzen statt einer Zahl: 
_delay_ms(x)  -> das geht nicht. mit google fand ich die erklärung wieso 
das nicht funktioniert. Doch jetzt stellt sich mir die Frage, wie sonst 
geht das ?? Ich will das mit einem Poti sozusagen einstellen (den Wert 
-- zB 200 -> 200ms --> in _delay_ms(200);))

von Oliver R. (orb)


Lesenswert?

Nimm _delay_ms(1), pack den in eine Schleife und lass die 200mal 
durchlaufen.

von Wolfgang A. (Gast)


Lesenswert?

Stefan S. schrieb:
> Doch jetzt stellt sich mir die Frage, wie sonst geht das ??
Wenn dein µC auch noch andere Aufgaben übernehmen soll, vergiss die 
Funktion _delay_ms() ganz schnell wieder. Damit legst du den µC lahm, 
weil er die ganze Zeit mit Zeittotschlagen beschäftigt ist.

Besser ist es, einen Timer so zu programmieren, dass er von sich aus 
läuft und entweder direkt (wenn du ihn anderweitig nicht brauchst) oder 
über regelmäßige Interrupts, in denen du Zählerstände auswertest (z.B. 
LED 200 Takte an, 50 Takte aus), die LED steuert.

von Draco (Gast)


Lesenswert?

Grundsätzlich stimme ich Patryk zu, nimm einen Timer und versuche es 
"Thread-ähnlich" aufzubauen. Solltest du dennoch, für einfache Aufgaben, 
den Delay nutzen wollen, mach es einfach so:
1
void delayMS(uint16_t delay)
2
{
3
   for(uint16_t i = 0;i<delay;i++)
4
   {
5
      _delay_ms(1);
6
   }
7
}


Aufrufen tust du das ganze dann halt einfach so:

1
 
2
delayMS(1000);
3
 
4
//oder eben mit Variable:
5
 
6
uint16_t Warte = 2300;
7
delayMS(Warte);

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


Lesenswert?

Draco schrieb:
> Solltest du dennoch, für einfache Aufgaben, den Delay nutzen wollen
Ich sehe das so:
ein Delay zur bewussten Rechenzeitverschwendung hat in einer 
Hauptschleife nichts zu suchen und ist als Programmierfehler (oder 
besser Konzeptfehler) zu sehen...
Gerade an einer simplen blinkenden LED kann man ideal z.B. mal einen 
Timer mit Interrupt ausprobieren und das Ganze mit einem 
Zustandsautomaten abhandeln. Damit wäre das ein Ansatz:
http://www.lothar-miller.de/s9y/categories/22-Zeiten

Wenn man keine ganz so langen Zeiten braucht (ein long reicht für einen 
ms-Takt von Montag früh bis Donnerstag Mittag), dann reicht auch eine 16 
Bit Zählvariable.

von Stefan S. (derprogrammierer2)


Lesenswert?

das mit der for-schleife in einem unterprogramm, das habe ich mir auch 
schon überlegt. ich werde mich etwas mit den timern spielen. mal sehen 
ob sich da was gscheit's ergibt. falls ich was interessantes hab poste 
ich es

von spess53 (Gast)


Lesenswert?

Hi

>gibt es eigentlich eine Beschreibung zu dem Blockschaltbild von der ADU
>(eine gute?) Also was zB ADMUX; ADCSRA,SFIOR, also die ganzen Register
>machen bzw wozu sie dienen.

Aktuelles Datenblatt?

MfG Spess

von Stefan S. (derprogrammierer2)


Lesenswert?

1
else if (counter == 3)
2
      {
3
        ADC_Wert = ADC_Umsetzung(1);
4
        itoa(ADC_Wert,Text,10);
5
        lcd_print(1,0,Text);
6
        lcd_write("           ");
7
        
8
        if(!(PIND & (1<<PD3))) break;
9
      }
1
uint16_t ADC_Umsetzung(uint8_t AD_Channel)
2
{
3
  // Kanal auswählen
4
  ADMUX |= AD_Channel;
5
  // Umsetzung starten
6
  ADCSRA |= (1<<ADSC);
7
  // warten bis Umsetzung beendet
8
  while (ADCSRA & (1<<ADSC));
9
  
10
  return(ADC);
11
}
Das AD_Init ist richtig eingestellt.

Mein Programm: Drücke ich das dritte mal den blauen Taster komme ich in 
diese If Bedingung die oben abgebildet ist.
Gestern war der Wert am LCD immer aktuell, sobald ich am Poti gedreht 
habe. Solang der counter==3 war. Ich hab immer den richtigen Wert 
gehabt.

Doch heute muss ich feststellen, (habe ein bisschen mit MUX0 gespielt, 
jedoch wieder den Bit gelöscht dann!) dass der immer nur einen Wert (den 
ersten anzeigt). War mein Poti ganz am Ende als ich in den counter==3 If 
reingekommen bin, hat er nur 1023 angezeigt, egal ob ich drehe oder 
nicht,.. woran kann das liegen?

(gestern gings noch ohne eine while...........)

von Dietrich L. (dietrichl)


Lesenswert?

Zumindest das ist falsch:

Stefan S. schrieb:
> ADMUX |= AD_Channel;

Das setzt nur zusätzliche "1"-Bits (ODER-Verknüpfung!).
Du musst vorher alle Channel-Bits löschen (mit UND-Verknüpfung) bevor Du 
den neuen Channel-Wert hinein-ODER-st.

Ob das jetzt Dein beschriebenes Problem löst habe ich nicht geschaut.

Gruß Dietrich

von Stefan S. (derprogrammierer2)


Lesenswert?

Tut es leider nicht :(

von Stefan S. (derprogrammierer2)


Lesenswert?

habs geschafft. falsche { am falschen Ort

von c-hater (Gast)


Lesenswert?

Draco schrieb:

> Grundsätzlich stimme ich Patryk zu, nimm einen Timer und versuche es
> "Thread-ähnlich" aufzubauen.

Sowas nennt sich "ereignisorientierte Programmierung".

Hat mit Threads nur sehr bedingt etwas zu tun, eigentlich garnix. Eine 
gewisse Analogie entsteht nur daraus, das Ereignisse (im abstrakten 
Sinn) bei µC-Applikationen oft sehr direkt aus Interrupts stammen statt 
dass diese Tatsache durch Unmassen zeitfressender Schichten nutzlosen 
Glue-Codes vor dem Anwendungsprogrammierer verborgen wird, wie das bei 
"richtigen OS" gewöhnlich der Fall ist.

von Dieter F. (Gast)


Lesenswert?

Na, das hättest Du doch dort

Beitrag "Atmega32, Poti, ADC, Poti-am LCD ausgeben"

gleich dranhängen können ...



Stefan S. schrieb:
> if(!(PIND & (1<<PD3))) break;

Hast Du da nur die MAIN-(WHILE-) Schleife drum? Falls ja, solltest Du 
mal nachlesen, was so ein BREAK-Statement macht :-)
Wenn der Prozessor nicht mehr arbeitet wird auch das LCD nicht mehr 
aktualisiert ...

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.