www.mikrocontroller.net

Forum: Compiler & IDEs led automatisch dimmen in c und atmega8


Autor: roadrunner2008 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich möchte eine LED an meinem Atmega8 automatisch dimmen lassen. ich 
krieg das aber nicht so ganz hin. ich möchts ganz einfach mit delay 
programmieren, das sich bei jeder ms einfach erhöht.
zeiten passen noch nicht so ganz. das ganze startet wenn ich an pc6 den 
schalter betätige. die leds hängen auf PortD.

danke

#define F_CPU 1000000UL
#include <avr/io.h>
#include <delay.h>

uint16_t dimmzeit (void)// ich möcht das sich x mit jeder millisekunde 
um 10 erhöht bis es 1000 erreicht hat
{
unsigned char wert;
unsigned char x;
while (PINC&(1<<PINC5));
wert = x;

for (x=1;x<=1000;x+10)
_delay_ms(1);
if (x=1000){x=1};

return wert;
}


int main(void)
{
Init();

DDRD = 0xFF;
DDRC = 0x00;

unsigned int x;
while(1){
if (PINC&(1<<PINC5)){
PORTD= 0xFF;
_delay_ms (1000);
PORTD= 0x00;
_delay_ms (x);}


else {
PORTD= 0x00;}}

return 0;
}

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> das ganze startet wenn ich an pc6 den
> schalter betätige. die leds hängen auf PortD.

pc6 passt nicht zu dem Code unten. Dort wird pc5 verwendet.

Originalcode etwas formatiert und kommentiert:

#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>  // <===

// ich möcht das sich x mit jeder millisekunde
// um 10 erhöht bis es 1000 erreicht hat

uint16_t dimmzeit (void)
{
  unsigned char wert;
  unsigned char x;

  while (PINC&(1<<PINC5));
  
  wert = x;
  for (x=1;x<=1000;x+10)
    _delay_ms(1);

  if (x=1000)  // <=== ist wohl == gemeint
    x = 1;

  return wert;
}


int main(void)
{
  unsigned int x;

  Init();

  DDRD = 0xFF;
  DDRC = 0x00;

  while(1){
    if (PINC&(1<<PINC5)){
      PORTD = 0xFF;
      _delay_ms (1000); // so grosses Argument (1000 ms = 
                        // 1 Sekunde) funktioniert 
                        // nur bei avr-libc >= 1.6
      PORTD = 0x00;
      _delay_ms (x);    // zur Compilezeit undefiniertes Argument
                        // ist ein no-no!

    } else {
      PORTD = 0x00;
    }
  }

  return 0;
}


Für exakte Änderungen sind zuwenig Infos in der Frage. Wann sind die 
LEDS AN und wann AUS?. Soll das Dimmen nur bei gedrückter Taste laufen? 
Sind die LEDs vor dem Dimmen AN oder AUS? Hier wie man vielleicht 
vorgehen könnte:

#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>

void dimmzeit(unsigned int x)
{
  while(x--)
    _delay_ms(1);
}

int main(void)
{
  unsigned int x = 0;

  DDRD = 0xFF; // Alle PORTD Ausgang
  DDRC = 0x00; // Alle PINC Eingang

  while(1)
  {
    if ((PINC & (1<<PINC5)))
    {
      PORTD = 0xFF;
      _delay_ms (1000);
      PORTD = 0x00;
      x += 10;
      dimmzeit(x);
      if (x >= 1000) x = 0;
    } else
      PORTD = 0x00;
  }

  return 0;
}


Autor: roadrunner2008 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi,
danke für die hilfe.
kann ich den code auch irgendwie ändern, so dass ich die leds dimmen 
kann bis sie aus sind. also von ganz hell bis dunkel.
probier nämlich schon seit drei stunden und den code von led-fadding 
kappier ich noch nicht so ganz. bin noch nicht so fit in c.
danke
mfg

Autor: bastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
öhm,
nur kurz nen hinweis.
der wertebereich von nem unsigned char ist 0-255 wenn ich nicht irre, 
wenn ihr jetzt eine schleife von 1 bis 100 laufen lasst, sollte das 
eigentlich nicht so richtig funktionieren....

hm

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde das mal so angehen.

Dimmen bedeutet, dass es erst mal möglich sein muss
eine Led auf eine (fast) beliebige Helligkeitsstufe
zu setzen.

Daher würde ich damit mal anfangen: Eine Led auf eine
bestimmte Helligkeitsstufe zu setzen.

Da das ganze mit _delay_ms gemacht werden soll, ist als
erstes mal eine Funktion notwendig, die eine bestimmte
Zeit in ms abwarten kann.
void Delay( uint8_t ms )
{
  while( ms > 0 ) {
    _delay_ms( 1 );
    --ms;
  }
}

Soweit so gut. Wie wird eine LED gedimmt?
Sie wird dadurch gedimmt, dass das Verhältnis von Einschalt
zu Ausschaltzeit variiert wird. Ist die Led lange ein aber
nur kurz aus, dann leuchtet sie heller als wie wenn sie nur
kurz ein aber lange aus ist.
Das heist, in einer bestimmten Zeiteinheit x ist die Led
y Zeiteinheiten ein und x-y Zeiteinheiten aus.
Als Basiszeit nehme ich mal 50ms. D.h. die LED durchläuft
so einen ein/aus Zyklus 20 mal in der Sekunde. Das wird zwar
noch zu einem gewissen Flackern führen, ist aber fürs Testen
erst mal gar nicht so schlecht und mit Millisekunden erst mal
auch nicht anders machbar. Wir wollen ja auch genügend Helligkeits-
stufen für die LED haben.
void LedZyklus( uint8_t OnTime )
{
  if( OnTime > 0 ) {
    // Led ein
    PORTD = 0x00;
    // OnTime abwarten
    Delay( OnTime );
  }

  if( OnTime < 50 ) {
    // Led aus
    PORTD = 0xFF;
    // Aus-Zeit abwarten
    Delay( 50 - OnTime );
  }
}

Ein Aufruf der Funktion LedZyklus dauert 50 Millisekunden (und
ein paar Zerquetschte) und zwar unabhängig davon, wie 'hell'
die Led leuchten soll.

Das ist es mir schon mal wert, dafür ein Testprogramm zu schreiben
um zu sehen, ob das auch funktioniert.
int main()
{
  DDRD = 0xFF;    // auf Ausgang

  while( 1 )
    LedZyklus( 10 );   // Led soll nur schwach leuchten
}

Wenn ich jetzt keinen Tippfehler gemacht habe, dann sollte die
Led am Port D dunkel leuchten (flackern).

Durch Variation der 10 beim Aufruf von LedZyklus sollten sich
verschiedene Werte einstellen lassen. Ausprobieren!
Bei einem Aufruf
   LedZyklus( 0 );
dürfte die Led überhaupt nicht leuchten, während sie bei
   LedZyklus( 50 );
mit voller Kraft leuchten sollte. Werte dazwischen führen
zu verschiedenen Helligkeitsstufen.

Das ist ja schon mal ein Anfang. Um die Led zu dimmen, genügt
es daher, diesen Wert laufend zu ändern. Zb. indem man ihn in
der Schleife variiert:
int main()
{
  uint8_t UpDown;
  uint8_t Level;

  DDRD = 0xFF;   // alles auf Ausgang

  Level = 0;
  UpDown = 0;

  while( 1 ) {
    LedZyklus( Level );

    if( UpDown == 0 ) {   // Led soll heller werden
      if( Level >= 50 )   // Obere Grenze erreicht ?
        UpDown = 1;         // Ja: Auf dunkler werden umschalten
      else
        Level += 1;         // Nein: Na dann mach sie heller
    }

    else {                // Led soll dunkler werden
      if( Level == 0 )    // Untere Grenze erreicht ?
        UpDown = 0;          // Ja: Auf heller werden umschalten
      else
        Level -= 1;          // Nein: Na dann mach sie dunkler
    }
  }
}

Damit sollte die Led dann eigentlich laufend dunkler/heller
werden.

Von da weg, ist es nur noch ein kleiner Schritt einen Taster
mit einzubauen.

Ich denke das Hauptproblem des OP ist dasselbe, dass viele
Einsteiger haben: Ihr versucht immer zuviel in main() hinein-
zupacken. Schreibt euch Funktionen für Teilaufgaben! Dadurch
wird die Entwicklung sehr viel einfacher und auch wesentlich
überschaubarer. In diesem konkreten Fall besteht der Trick
darin, die effektive Helligkeitseinstellung von der Dimmerei
zu trennen.

Autor: roadrunner2008 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vielen Dank. Endlich hat mir das mal jemand verständlich erklärt.
super. funktioniert auch prima

Autor: roadrunner2008 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
eine Frage noch.
was bedeutet "--ms;".
was besagt das?
danke

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  roadrunner2008 (Gast)

>was bedeutet "--ms;".

Die Variable ms wird ums eins verringert.

Mfg
Falk

Autor: eels (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wie ist es dann möglich, dass ich zwei leds nacheinander heller bzw. 
dunkler werden.
LED1 heller - LED1 dunkler - LED2 heller - LED2 dunkler

hab bei LEDZyklus eine kopie gemacht für die zweite LED.
und dieses dann nacheinander laufen lassen.
doch bei mir laufen beide gleich los. hangt damit zusammen dass ich 
beides in eine while-schleife gepackt hab.
wie kann ich das lösen?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du mein Programm weiterverwenden willst,
dann kannst du das zb. so machen

* Anstelle von einem Level, gibt es deren 2. Für jede Led eine
  eigene. Level1 und Level2

* Die Variable UpDown wird in ihrer Bedeutung etwas umgedreht.
  Anstelle von 2 Zuständen, bekommt sie jetzt 4. Dabei bedeutet

  0 ... Led 1 soll heller werden
  1 ... Led 1 soll dunkler werden
  2 ... Led 2 soll heller werden
  3 ... Led 2 soll dunkler werden

Probleme wird es allerdings dadurch geben, dass du dann mit
der Zykluszeit nicht mehr vernünftig hin kommen wirst. Mit
Millieskunden wird das ohne heftiges Geblinke nichts mehr
werden.

Autor: eels (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gibt es denn noch eine andere möglichkeit das zu programmieren.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sicher.
Die PWM mit Hardwareunterstützung machen.

Entweder (wenns nur wenige Kanäle sind) einen Timer eine
PWM erledigen lassen, oder einen Timer mit einer ISR
zusammenspannen, die dann die einzelnen PWM Kanäle
bedient.

Das dimmen an sich geht dann wieder wie gehabt, zb durch delays
(wenn der Proz sonst nichts zu tun hat).

So wie es zb hier gemacht wurde
http://www.mikrocontroller.net/articles/AVR-Tutorial:_SRAM

Autor: eels (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab jetzt mal mein programm verändert aber es klappt nicht so ganz.
liegt es daran dass ich in der while schleife nur 1 oder 0 lesen kann?
Es leuchtet nur portD1

#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>

void Delay( uint8_t ms )
{
  while( ms > 0 ) {
    _delay_us( 200 );
    --ms;
  }
}

void LedZyklus1( uint8_t OnTime )
{
  if( OnTime > 0 ) {
    // Led ein
    PORTD = 0x00;
    // OnTime abwarten
    Delay( OnTime );
  }

  if( OnTime < 120 ) {
    // Led aus
    PORTD = 0x01;
    // Aus-Zeit abwarten
    Delay( 120 - OnTime );
  }
}

void LedZyklus2( uint8_t OnTime2 )
{
  if( OnTime2 > 0 ) {
    // Led ein
    PORTD = 0x00;
    // OnTime abwarten
    Delay( OnTime2 );
  }

  if( OnTime2 < 120 ) {
    // Led aus
    PORTD = 0x02;
    // Aus-Zeit abwarten
    Delay( 120 - OnTime2 );
  }
}

int main()
{
  uint8_t UpDown;
  uint8_t Level;
  uint8_t Level2;

  DDRD = 0xFF;   // alles auf Ausgang

  Level = 1; // da ich sonst probleme bekomm beim umschalten auf die 
zweite LED
  Level2 = 0;
  UpDown = 0;
while(1){

while(Level >1 ){

    LedZyklus1( Level );
{  if( Level < 120 )
    {Level += 1;}  // Led1 soll heller werden
    if( Level >= 120 )   // Obere Grenze erreicht ?
    {Level -=1;}         // Ja: Auf dunkler werden umschalten
}return (Level);

}

while(Level <= 1){
  LedZyklus2( Level2 );
{   if( Level2 < 120 )
    {Level2 += 1;} // Led2 soll heller werden

  if( Level2 >= 120 )   // Obere Grenze erreicht ?
    {Level2 -=1;}        // Ja: Auf dunkler werden umschalten
}
     return (Level);
    }

}
}

Autor: roadrunner2008 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bin selber noch anfänger. aber ich hab dieses Programm gerade 
ausprobiert.
Da ist zwar irgendwo noch ein Fehler drin, weil die LED's nicht langsam 
heller werden sondern gleich angehen. aber danach dimmen sie langsam und 
dies nacheinander.
vielleicht kann jemand hier den code mal durchschauen, wo der Fehler 
liegt
viel spass
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>

void Delay( uint8_t ms )
{
  while( ms > 0 ) {
    _delay_us( 200 );
    --ms;
  }
}

void LedZyklus1( uint8_t OnTime )
{
  if( OnTime > 0 ) {
    // Led ein
    PORTD = 0x00;
    // OnTime abwarten
    Delay( OnTime );
  }

  if( OnTime < 120 ) {
    // Led aus
    PORTD = 0x01;
    // Aus-Zeit abwarten
    Delay( 120 - OnTime );
  }
}

void LedZyklus2( uint8_t OnTime2 )
{
  if( OnTime2 > 0 ) {
    // Led ein
    PORTD = 0x00;
    // OnTime abwarten
    Delay( OnTime2 );
  }

  if( OnTime2 < 120 ) {
    // Led aus
    PORTD = 0x02;
    // Aus-Zeit abwarten
    Delay( 120 - OnTime2 );
  }
}

int main()
{
  uint8_t UpDown;
  uint8_t Level;
  uint8_t Level2;

  DDRD = 0xFF;   // alles auf Ausgang

  Level = 0; // da ich sonst probleme bekomm beim umschalten auf die zweite LED
  Level2 = 0;
  UpDown = 0;
while(1){

while(Level <=120 ){

    LedZyklus1( Level );
    Level += 1;}  // Led1 soll heller werden
    
while(Level =0 ){  
  LedZyklus1( Level );  // Obere Grenze erreicht ?
    Level -=1;}         // Ja: Auf dunkler werden umschalten

while(Level2 <= 120){
  LedZyklus2( Level2 );
    Level2 += 1;} // Led2 soll heller werden

while(Level2 = 0){
  LedZyklus2( Level2 );   // Obere Grenze erreicht ?
    Level2 -=1;}// Ja: Auf dunkler werden umschalten
 }   
}

Autor: roadrunner2008 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
okay habs,
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>

void Delay( uint8_t ms )
{
  while( ms > 0 ) {
    _delay_us( 200 );
    --ms;
  }
}

void LedZyklus1( uint8_t OnTime )
{
  if( OnTime > 0 ) {
    // Led ein
    PORTD = 0x00;
    // OnTime abwarten
    Delay( OnTime );
  }

  if( OnTime < 120 ) {
    // Led aus
    PORTD = 0x01;
    // Aus-Zeit abwarten
    Delay( 120 - OnTime );
  }
}

void LedZyklus2( uint8_t OnTime2 )
{
  if( OnTime2 > 0 ) {
    // Led ein
    PORTD = 0x00;
    // OnTime abwarten
    Delay( OnTime2 );
  }

  if( OnTime2 < 120 ) {
    // Led aus
    PORTD = 0x02;
    // Aus-Zeit abwarten
    Delay( 120 - OnTime2 );
  }
}

int main()
{
  
  uint8_t Level;
  uint8_t Level2;

  DDRD = 0xFF;   // alles auf Ausgang

  Level = 0; // da ich sonst probleme bekomm beim umschalten auf die zweite LED
  Level2 = 0;
 
while(1){

while(Level >0 ){  
  LedZyklus1( Level );  // Obere Grenze erreicht ?
    Level -=1;}         // Ja: Auf dunkler werden umschalten

while(Level <=120 ){

    LedZyklus1( Level );
    Level += 1;}  // Led1 soll heller werden

while(Level2 > 0){
  LedZyklus2( Level2 );   // Obere Grenze erreicht ?
    Level2 -=1;}// Ja: Auf dunkler werden umschalten
    

while(Level2 <= 120){
  LedZyklus2( Level2 );
    Level2 += 1;} // Led2 soll heller werden

 }   
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
roadrunner2008 wrote:

Standardfehler

Das hier

> while(Level =0 ){

ist kein Vergleich, sondern eine Zuweisung.
Du willst auch nicht auf gleich 0 vergleichen, sondern auf
ungleich 0

  while( Level != 0 )

Autor: kazoo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist das nur bei mir so, oder flackert die Led bei euch auch so?
mfg

Autor: Florian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo...

Ich habe den C-Code von oben erweitert auf 4 LEDs und das Flackern 
entfernen können. Das ganze schaut schon ganz schön aus, jedoch ist es 
ein wenig unschön, dass die LEDs nur der Reihe nach an und aus "faden".

Besserer wäre es, wenn man zwei LEDs hintereinander andimmen lassen kann 
und dass dann wenn die dritte angeht, die erste ausgeht... zeitgleich 
spielt keine rolle.

So ungefähr:

LED1 an, LED2 an, Led3 an, LED1 aus, LED4 an, LED2 aus, LED1 an.... etc.

Ich weiss, dass dieses Thema schon ein paar Jährchen auf dem Rücken 
hat... aber vielleicht kann ja trotzdem noch einer helfen :)

Hier noch mein C-Code:
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>

int ledzeit;

ledzeit = 19;

void Delay( uint8_t ms )
{
  while( ms > 0 ) {
    _delay_us( 400 );
    --ms;
  }
}

void LedZyklus1( uint8_t OnTime )
{
  if( OnTime > 0 ) {
    // Led ein
    PORTB = (0 << DDB4);
    Delay( OnTime );
  }

  if( OnTime < ledzeit ) {
    // Led aus
    PORTB = (1 << DDB4);
    Delay( ledzeit - OnTime );
  }
}

void LedZyklus2( uint8_t OnTime2 )
{
  if( OnTime2 > 0 ) {
    // Led ein
    PORTB = (0 << DDB3);
    Delay( OnTime2 );
  }

  if( OnTime2 < ledzeit ) {
    // Led aus
    PORTB = (1 << DDB3);
    Delay( ledzeit - OnTime2 );
  }
}

void LedZyklus3( uint8_t OnTime3 )
{
  if( OnTime3 > 0 ) {
    // Led ein
    PORTB = (0 << DDB2);
    Delay( OnTime3 );
  }

  if( OnTime3 < ledzeit ) {
    // Led aus
    PORTB = (1 << DDB2);
    Delay( ledzeit - OnTime3 );
  }
}

void LedZyklus4( uint8_t OnTime4 )
{
  if( OnTime4 > 0 ) {
    // Led ein
    PORTB = (0 << DDB1);
    Delay( OnTime4 );
  }

  if( OnTime4 < ledzeit ) {
    // Led aus
    PORTB = (1 << DDB1);
    Delay( ledzeit - OnTime4 );
  }
}

int main()
{
  
  uint8_t Level;
  uint8_t Level2;
  uint8_t Level3;
  uint8_t Level4;

  DDRB = 0b00011110;

  Level = 19;        // kein Flackern der LEDs bei 19
  Level2 = 19;
  Level3 = 19;
  Level4 = 19;
 
while(1){

while(Level >0 ){  
  LedZyklus1( Level );    // Obere Grenze erreicht ?
    Level -= 1;}      // Ja: Auf dunkler werden umschalten
  
while(Level <= ledzeit ){
    LedZyklus1( Level );
    Level += 1;}      // Led1 soll heller werden
  
while(Level2 > 0){
  LedZyklus2( Level2 );    // Obere Grenze erreicht ?
    Level2 -= 1;}      // Ja: Auf dunkler werden umschalten

while(Level2 <= ledzeit){
  LedZyklus2( Level2 );
    Level2 += 1;}      // Led2 soll heller werden

while(Level3 > 0){
  LedZyklus3( Level3 );    // Obere Grenze erreicht ?
    Level3 -= 1;}      // Ja: Auf dunkler werden umschalten

while(Level3 <= ledzeit){
  LedZyklus3( Level3 );
    Level3 += 1;}      // Led3 soll heller werden

while(Level4 > 0){
  LedZyklus4( Level4 );    // Obere Grenze erreicht ?
    Level4 -= 1;}      // Ja: Auf dunkler werden umschalten

while(Level4 <= ledzeit){
  LedZyklus4( Level4 );
    Level4 += 1;}      // Led4 soll heller werden

 }   
}

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.