Forum: Mikrocontroller und Digitale Elektronik atmega8 led dimmen ohne PB1, PB2 (OC1A, OC1B)


von Rafael S. (rafi)


Lesenswert?

Hallo miteinander,
ich bin dabei für mein Aquarium eine LED Beleuchtung zu Steuern. Dabei 
sollen die LEDs ( eine LED- Beleuchtung, die in 5 LED- Stränge 
aufgeteilt ist) bzw die LED- Stränge einzeln und oder auch zusammen 
dimmbar sein.
Dabei soll per Tasterdruck ( für jeden Strang 1 Taster) ein- und 
ausgeschatet werden. Beim Ein- und Ausschalten soll hoch und runter 
gedimmt werden.

Zur Technik: ich nutze den Atmega8, AVR- Studio6. Der Atmega8 steckt 
noch zum programmieren auf der MyAvr Programmierumgebung.
Und ich versuche mich gerade in C !!
Die LED- Stränge meist 3-7 LEDs pro Strang werden über einen MeanWell 
LDD 350/700 gespeist.
Die LDDs haben einen PWM- Eingang mit dem das Dimmen möglich ist.

Ich habe etwas in C Programmiert und eine Lösung über die beiden PWM- 
Ausgänge OC1A und OC1B realisiert. Aber ich brauche noch mehr PWM- 
Ausgänge bzw. OC1X.
Desweiteren habe ich das Problem, dass sich die beiden PWM- Ausgänge nur 
nach einander ein bzw. auschalten lassen. Woran es liegt weiß ich, aber 
ich weiß nicht welche Möglichkeiten ich noch habe, da ich ein ziemlicher 
neuling im programmieren bin. Das ist quasi mein erstes Projekt.

Hier nun meine Frage:
Kann ich auch einen normlen Ausgang (PORT C oder D als Ausgang 
konfiguriert) dazu bringen mir einen PWM auszugeben??
Das müsste doch iwie gehen in dem ich den Ausgang mit einer bestimmten 
Frequenz ein und ausschalte.
Ich habe hier im Forum viel über PWM gelesen.. aber alles war mit OCR1a 
und OCR1b realisiert.

Zum bisherigen Code:
1
#define F_CPU 3686400
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <stdbool.h>
5
#include <avr/interrupt.h>
6
7
8
9
void  wait(int i)
10
{  int n = 0;
11
  while (n<i)  { _delay_us(10); n++;}
12
}
13
14
int main(void)
15
{
16
//PWM-init
17
TCCR1A=(1<<WGM11) | (1<<WGM10) | (1<<COM1A1) | (1<<COM1B1); // 0xA3; 
18
TCCR1B= (1<<CS11);  // 0x02;
19
OCR1A=0;    // inizialisieren mit 0
20
OCR1B=0;    // inizialisieren mit 0
21
  
22
// Aus und Eingänge konfigurieren
23
24
DDRB |=0xff;    // Ausgänge
25
DDRD &= ~ 0xff;    // Eingänge
26
PORTD |= 0xff;    // Pullup Widerstände
27
  
28
// deklarieren und inizialisieren von Variablen
29
  
30
bool freigabe1=0; 
31
bool freigabe2 =0;
32
33
int a = 10;
34
int b = 10;
35
int max = 1024;
36
int min = 0;
37
  
38
  
39
while (1)
40
{  
41
// Zustand LED ist AN und Taster ist nicht mehr betätigt
42
// Freigabe fürs Ausschalten
43
  
44
if  ((PIND & (1<<PD2)) && (PINB & (1<<PB1)))
45
{      
46
  freigabe1 = true;
47
}
48
49
// Zustand LED ist AUS und Taster nicht mehr betätigt
50
// Freigabe fürs Einschalten
51
// Wenn Taater nicht gedrückt und LED OFF
52
    
53
if ((PIND & (1<<PD2) ) && (!(PINB & (1<<PB1)))) 
54
{          
55
  freigabe1 = false;
56
}
57
58
// LED ON  
59
// Wenn Taster gedrückt und LED OFF und Verriegelung
60
      
61
if (!(PIND & (1<<PD2) ) && (freigabe1 == false) ) 
62
{
63
  while (a<max)   {OCR1A=a; wait(50); a++; }                    
64
}
65
    
66
// LED OFF
67
// Wenn Taster gedrückt und LED ON 
68
  else
69
  {
70
  if (!(PIND & (1<<PIND2) ) && (freigabe1 == true)) 
71
  {          
72
  while (a>=min)   {OCR1A=a; wait(50); a--; }          
73
  }
74
  }
75
      
76
// Taster 2 wird abgefragt und wenn betätigt LED ON / OFF
77
// Wenn Taater nicht gedrückt und LED ON
78
    
79
if  ((PIND & (1<<PD3)) && (PINB & (1<<PB2))) 
80
{
81
  freigabe2 = true;
82
}
83
  
84
// Wenn Taater nicht gedrückt und LED OFF
85
    
86
if ((PIND & (1<<PD3) ) && (!(PINB & (1<<PB2)))) 
87
{
88
  freigabe2 = false;
89
}
90
      
91
// LED ON
92
// Wenn Taster gedrückt und LED OFF und Verriegelung
93
if (!(PIND & (1<<PD3) ) && (freigabe2 == false) )
94
{
95
  while (b<max)   {OCR1B=b; wait(50); b++; }        
96
}
97
// LED OFF
98
else
99
{
100
// Wenn Taster gedrückt und LED ON
101
  if (!(PIND & (1<<PIND3) ) && (freigabe2 == true)) 
102
  {          
103
  while (b>=min)   {OCR1B=b; wait(50); b--; }          
104
  }
105
}
106
      
107
}
108
109
  return 0;
110
}

Danke im Voraus!
Gruß
Rafael

: Bearbeitet durch User
von Thomas E. (thomase)


Lesenswert?

Rafael S. schrieb:
> Kann ich auch einen normlen Ausgang (PORT C oder D als Ausgang
> konfiguriert) dazu bringen mir einen PWM auszugeben??

Ja. Das nennt sich Software PWM. Dazu wirst du hier unzählige Artikel 
finden.

Der Atmega88 hat übrigens 6 PWM-Kanäle.

mfg.

von Karl H. (kbuchegg)


Lesenswert?

Rafael S. schrieb:

> Desweiteren habe ich das Problem, dass sich die beiden PWM- Ausgänge nur
> nach einander ein bzw. auschalten lassen. Woran es liegt weiß ich, aber
> ich weiß nicht welche Möglichkeiten ich noch habe, da ich ein ziemlicher
> neuling im programmieren bin.

Das liegt an deinem Programmaufbau bzw. daran das du noch zu sequentiell 
denkst und nicht in Ereignissen. Wenn du beim Kochen neben dem Herd 
stehen bleibst und darauf wartest, bis das Gulasch fertig ist ...
1
   while (a<max)   {OCR1A=a; wait(50); a++; }
... dann kannst du eben nicht nebenher staubsaugen.

Du musst dein Denkweise umstellen. Nicht: das Programm soll darauf 
warten, dass eine Endbedingung erreicht ist, sondern bei jedem Durchlauf 
durch die Hauptschleife "Ist die Endbedingung erreicht, dann mach 
nichts, andernfalls bewege dich einen Schritt auf die Endbedingung zu". 
Vergleichbar damit eben nicht neben dem Herd stehen zu bleiben sondern 
immer abwechselnd nach dem Gulasch schauen und staubsaugen bis eines 
davon erledigt ist.
1
int main()
2
{
3
  uint16_t Licht1Vorgabe ;
4
  uint8_t Taste1Jetzt, Taste1Vorher;
5
6
  .....
7
8
  Licht1Vorgabe = 0;
9
  OCR1A = 0;
10
11
  Taste1Vorher = PIND & ( 1 << PD2 );
12
 
13
  while( 1 ) {
14
15
    // Taste1 auswerten
16
    // wird die Taste gedrückt, dann soll die Vorgabe für die Beleuchtung 1
17
    // in die jeweils andere Position springen. Aus Maximum wird Minimum
18
    // und umgekehrt
19
20
    Taste1Jetzt = PIND & ( 1 << PD2 );
21
22
    if( Taste1Jetzt != Taste1Vorher ) {  // Die Taste hat sich veraendert?
23
      Taste1Vorher = Taste1Jetzt;
24
      if( !Taste1Jetzt ) {               // interessant ist nur: sie wurde
25
                                         // niedergedrueckt,
26
                                         // d.h. die Frage "Wie steht sie jetzt?"
27
28
                                         // Die Taste wurde also niedergedrückt
29
        if( Licht1Vorgabe == 0 )         // -> Die Vorgabe für LED 1 von Minimum
30
          Licht1Vorgabe = 1023;          // auf Maximum umstellen und umgekehrt
31
        else
32
          Licht1Vorgabe = 0;
33
      }
34
    }
35
36
    ... selbiges fuer die andere Taste bzw. die Vorgabe fuer Licht 2
37
38
    // Auswertung der Vorgaben für die Beleuchtung
39
    // Ist die tatsächliche Einstellung kleiner als die Vorgabe dann
40
    // das Licht etwas heller machen. Ist sie grösser dann eben etwas dunkler
41
42
    if( OCR1A < Licht1Vorgabe )
43
      OCR1A++;
44
    else if( OCR1A > Licht1Vorgabe )
45
      OCR1A--;
46
47
    .... selbiges fuer das andere Licht und OCR1B
48
49
    _delay_ms( 50 );  // und etwas warten. Das beeinflusst dann wie schnell
50
                      // das Licht auf die jeweilige Vorgabe dimmt, bzw. ist
51
                      // notwendig, damit Tastenprellen nicht durchschlägt.
52
  }
53
}

: Bearbeitet durch User
von Rafael S. (rafi)


Lesenswert?

hi,
ohhh... das wusste ich nicht.
Welche sind das??
Sie sind aber nicht wie die OC1A und OC1B direk nach aussen geführt. 
ODER übersehe ich etwas ??
Die Geschichte mit der Software PWM war mir auch NEU. Danke für den 
Tipp!!!!

Ich habe direkt gesucht und einen Link gefunden:

Beitrag "Software PWM mit Atmega8 funktioniert nicht"

Hat jemand von euch schon diesen Code aus dem letzten Beitrag 
ausprobiert.

Es will bei mir nicht laufen.

@ Karl Heinz:

danke auch für deine Tipps. Ich glaube ich habe da wirklich bissl in die 
falsche Richtung geschaut! Ich werde es mal so ausprobieren!!!
Besonders gut ist das Beispiel mit dem Saugen und Gulaschkochen ! :-)

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Rafael S. schrieb:
> hi,
> ohhh... das wusste ich nicht.
> Welche sind das??
> Sie sind aber nicht wie die OC1A und OC1B direk nach aussen geführt.
> ODER übersehe ich etwas ??

Er sagte Mega 88 (achtundachzig). Du hast aber einen Mega 8

von Karl H. (kbuchegg)


Lesenswert?

Rafael S. schrieb:

> Beitrag "Software PWM mit Atmega8 funktioniert nicht"
>
> Hat jemand von euch schon diesen Code aus dem letzten Beitrag
> ausprobiert.
>
> Es will bei mir nicht laufen.
Was heisst 'will nicht'.

Nach schnellem Drüberschauen sollte der anstandslos eine LED an Port C / 
1 durch dimmen.

Du tauscht natürlich ganz oben das F_CPU gegen die Taktfreqquenz deines 
Prozessors aus
1
#define F_CPU 3686400

und wenn deine LED an einem anderen Pin hängt, dann änderst du das eben 
im Code entsprechend. So schwer ist das ja nicht zu finden, wo der Port 
C angesprochen wird (auf das DDR Register nicht vergessen!)

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

>Du hast aber einen Mega 8

Da ist OC2 noch verfügbar.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

spess53 schrieb:
> Hi
>
>>Du hast aber einen Mega 8
>
> Da ist OC2 noch verfügbar.
>

Ja. Aber er hat keine 6 PWM Stufen. Der TO braucht 5, somit sind ihm 3 
zu wenig.

von Rafael S. (rafi)


Lesenswert?

Karl H. schrieb:

> Was heisst 'will nicht'.
>
> Nach schnellem Drüberschauen sollte der anstandslos eine LED an Port C /
> 1 durch dimmen.

Tut mir leid... war ein Fehlalarm. Ich hatte eine kleinen Fehler 
gemacht. Meine Schuld.
Die LED dimmt hoch, geht aus und dimmt dann wieder hoch... und das in 
Schleife.


Karl H. schrieb:

>
> Er sagte Mega 88 (achtundachzig). Du hast aber einen Mega 8

Richtig.. ich habe den Atmega8. Habe in der Antwort auch jetzt erst 
gemerkt das da 88 und nicht 8 steht. Sorry!

Gruß

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


Lesenswert?

Rafael S. schrieb:
> Richtig.. ich habe den Atmega8. Habe in der Antwort auch jetzt erst
> gemerkt das da 88 und nicht 8 steht. Sorry!

Den kannst du dir trotzdem beim nächsten Mal mitbestellen und anstelle 
des Mega8 in die Platine stecken, er ist pinkompatibel. Das gleiche gilt 
auch für den Mega48 und Mega 168/328. Dies sind die modernen Nachfolger 
deines Mega8 Urgesteins :-P

von Rafael S. (rafi)


Lesenswert?

Matthias S. schrieb:


> deines Mega8 Urgesteins :-P

hi hi ... :-)

Ja da hast du definitiv recht. Das sollte ich mir durch den Kopf gehen 
lassen!
Danke für die Tipps!!!

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.