Forum: Mikrocontroller und Digitale Elektronik ATmega48 - Timer0: PWM mit Poti zum LED dimmen in C


von Squat *. (squat)


Lesenswert?

Langsam weiß ich nicht mehr weiter.

Ich möchte, wie in der Überschrift beschrieben eine bzw. zwei LED dimmen 
(später sollen die LEDs mit 2 Pumpen und Fet getauscht werden).

Dazu möchte ich ein Poti verwenden. Die Funktion des ADC sollte 
funktionieren, da ich mit einer Abfrage 4 LEDs leuchten lasse (je 
nachdem, welcher Wert ansteht).

Der Timer1 wird für einen andere Aufgabe benötigt und wird daher auch 
verwendet.
1
//ICC-AVR application builder : 13.04.2010 16:15:44
2
// Target : m48
3
// Crystal: 8.0000Mhz
4
5
#include <iom48v.h>
6
#include <macros.h>
7
8
unsigned char i = 0;
9
unsigned int result;
10
11
void port_init(void)
12
{
13
 PORTB = 0xF1;
14
 DDRB  = 0x0E;
15
 PORTC = 0x43; 
16
 DDRC  = 0xBC;
17
 PORTD = 0x00;
18
 DDRD  = 0xFF;
19
}
20
21
void timer0_init(void)
22
{
23
    OCR0A = 0x80;
24
  OCR0B = 0x80;
25
  TCCR0A |= (1 << WGM01) | (1 << WGM00);    // Fast PWM
26
  TCCR0A |= (1 << COM0A1);                  // Fast PWM, non-inverting mode
27
  TCCR0A &= ~(1 << COM0A0);
28
  TCCR0A |= (1 << CS02);                    // Prescaler: 1/256
29
  
30
//  TCCR0B |= (1 << WGM01) | (1 << WGM00);  // Fast PWM
31
//  TCCR0B |= (1 << COM0B1);                // Fast PWM, non-inverting mode
32
//  TCCR0B &= ~(1 << COM0B0); 
33
//  TCCR0B |= (1 << CS02);                  // Prescaler: 1/256
34
35
        
36
}
37
38
//TIMER1 initialize - prescale:64
39
// WGM: 0) Normal, TOP=0xFFFF
40
// desired value: 100mSec
41
// actual value: 100,000mSec (0,0%)
42
void timer1_init(void)
43
{
44
 TCCR1B = 0x00; //stop
45
 TCNT1H = 0xCF; //setup
46
 TCNT1L = 0x2C;
47
 OCR1AH = 0x30;
48
 OCR1AL = 0xD4;
49
 OCR1BH = 0x30;
50
 OCR1BL = 0xD4;
51
 ICR1H  = 0x30;
52
 ICR1L  = 0xD4;
53
 TCCR1A = 0x00;
54
 TCCR1B = 0x03; //start Timer
55
}
56
57
//ADC initialize
58
// Conversion time: 6uS
59
void adc_init(void)
60
{
61
 ADCSRA = 0x00; //disable adc
62
 ADMUX = 0x00;  //select adc input 0
63
 ACSR  = 0x80;
64
 ADCSRB = 0x00;
65
 ADCSRA = 0x01;
66
 
67
}
68
69
#pragma interrupt_handler timer1_ovf_isr:iv_TIM1_OVF
70
void timer1_ovf_isr(void)
71
{
72
 //TIMER1 has overflowed
73
 TCNT1H = 0xCF; //reload counter high value
74
 TCNT1L = 0x2C; //reload counter low value
75
76
77
 
78
//----------------------------------------------------------------------------//
79
       //         AD-Wandlung
80
//----------------------------------------------------------------------------//
81
       // Dummy-Readout
82
       ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);  // ADC aktivieren, Frequenzvorteiler: setzen auf 64 (8 MHz / 64 = 125 kHz) und ADC aktivieren
83
       ADMUX = 0x00;                                  // Kanal waehlen (ADC0)
84
       ADMUX |= (1<<REFS0) | (1<<REFS1);              // interne Referenzspannung nutzen 
85
       ADCSRA |= (1<<ADSC);                           // eine ADC-Wandlung
86
       while(!(ADCSRA & (1<<ADIF)));                  // auf Abschluss der Konvertierung warten (ADIF-bit)
87
       result = ADC;                                  // ADC muss einmal gelesen werden,
88
                                                      // sonst wird Ergebnis der nächsten Wandlung
89
                                                      // nicht übernommen.
90
       
91
       //ADC-Messung mit arithmetischen Mittel aus 4 Messungen
92
       result = 0;
93
       for (i=0;i<4;i++)
94
            {
95
          ADCSRA |= (1<<ADSC);                        // Messung ausfuehren
96
        while ( ADCSRA & (1<<ADSC) );                 // Konvertierung abwarten
97
        result += ADC;                                // aufaddieren zur Mittelwertbildung (ADC auslesen der zwei Bits
98
        }
99
        ADCSRA &= ~(1<<ADEN);                         // ADC ausschalten
100
        
101
        result /= 16;                                 // Mittelwert aus 4 und 8Bit für PWM (1024 / 4 = 256)
102
        
103
        OCR0A = result;                               // OC0A (PD6) = Poti-wert
104
        OCR0B = result;                               // OC0B (PD5) = Poti-wert
105
106
107
//----------------------------------------------------------------------------//
108
       //         AD-Abfrage zur Prüfung auf Funktion - Komentare sind für ein anders Projekt
109
//----------------------------------------------------------------------------//
110
       if (result < 63)  //410 = 5,4V
111
               {
112
          PORTD &= ~0x15; // PD4, PD2 &PD0 low
113
          PORTD |= 0x08; // PD3 high => LED an
114
          }
115
       if ((result < 127) & (result >= 63)) //430 = 5,7V
116
             {
117
          PORTD &= ~0x0D; // PD3, PD2 & PD0 low
118
          PORTD |= 0x10; // PD4 high => LED an
119
          }
120
       if ((result < 191) & (result >= 127)) //915 = 10,8V, 975 = 11,5V bei 100K und 330R
121
             {
122
          PORTD &= ~0x1c; // PD4, PD3 & PD2 low
123
          PORTD |= 0x01; // PD0 high => LED an
124
          } 
125
       if  (result >= 191)
126
          {
127
          PORTD &= ~0x19; // PD4, PD3 & PD0 low
128
          PORTD |= 0x04; // PD2 high => LED an
129
          }
130
                   
131
}  
132
////////////////////////////////////////////////////////////////////////////////
133
// Hauptprogramm
134
////////////////////////////////////////////////////////////////////////////////
135
void main(void)
136
{
137
 //stop errant interrupts until set up
138
 CLI(); //disable all interrupts
139
 port_init();
140
 timer0_init();
141
 timer1_init();
142
 adc_init();
143
 
144
145
 MCUCR = 0x00;
146
 EICRA = 0x00; //extended ext ints
147
 EIMSK = 0x00;
148
 
149
 TIMSK0 = 0x01; //timer 0 interrupt sources
150
 TIMSK1 = 0x01; //timer 1 interrupt sources
151
 TIMSK2 = 0x00; //timer 2 interrupt sources
152
 
153
 PCMSK0 = 0x00; //pin change mask 0 
154
 PCMSK1 = 0x00; //pin change mask 1 
155
 PCMSK2 = 0x00; //pin change mask 2
156
 PCICR = 0x00; //pin change enable 
157
 PRR = 0x00; //power controller
158
 SEI(); //re-enable interrupts
159
 //all peripherals are now initialized
160
   
161
 while(1);
162
  // Endlosschleife, blinken läuft im 100ms Interrupt
163
 
164
  
165
}

Vielen Dank für euche Hilfe.

von MWS (Gast)


Lesenswert?

1
TIMSK0 = 0x01; //timer 0 interrupt sources
Timer0n Ovfl Int erlaubt ohne Interrupt Handler = Nirvana

von Squat *. (squat)


Lesenswert?

Also verstanden habe ich deine Antwort, da ich bisher mir den Quelltext 
immer zusammengesucht habe und so langsam mir die Fakten anlese, weiß 
ich jedoch nicht wirklich, wie ich dem abhilfe schaffen kann.
1
TIMSK0 = 0x00; //timer 0 interrupt sources
Timer auf Null setzen oder
1
#pragma interrupt_handler timer0_ovf_isr:iv_TIM0_OVF
2
void timer0_ovf_isr(void)
3
{
4
 //TIMER0 has overflowed
5
}
diesen Teil einsetzen?

Hat jedoch beides nicht geholfen.

von Frederik K. (n0ll4k)


Lesenswert?

Denke eher er meint das du den Timer interrupt einfügen solltest.

Was mir noch auffällt das ganze AD Wandler auslesen solltest du im 
Hauptprogramm machen und im Interrupt von Timer 1 dann nur den Wert 
nutzen, falls du das zyklisch mit diesem machen willst.

von Squat *. (squat)


Lesenswert?

Aber wenn ich die AD-Wandlung im Hauptprogramm ablaufen lasse, dann wird 
diese doch nur einmal ausgeführt, oder wie kann ich diese Funktion in 
die While-Schleife einbauen?

Ich wollte sowie so gerne aus ein paar Abschnitte Teilprogramme 
erstellen, da ich die AD-Wandlung z.B. für 3 Ports benötige. Ich bin 
damit jedoch etwas überfragt. Gerne würde ich Quelltexte und nicht nur 
Ratschläge von euch bekommen, da es mir schwer fällt, z.B.
> das du den Timer interrupt einfügen solltest.
zu deuten.

von Karl H. (kbuchegg)


Lesenswert?

Squat *** schrieb:
> Aber wenn ich die AD-Wandlung im Hauptprogramm ablaufen lasse, dann wird
> diese doch nur einmal ausgeführt, oder wie kann ich diese Funktion in
> die While-Schleife einbauen?

Das ist jetzt aber nicht dein Ernst, oder?

Ich empfehle das Zusammenstoppeln von geklautem Code zu unterlassen und 
erst mal mit einem guten Buch die ersten Gehversuche in richtigem 
Programmieren auf einem PC zu machen.

von Frederik K. (n0ll4k)


Lesenswert?

Les dir mal das AVR-GCC Tutorial hier auf der Seite durch und arbeite 
das mal ab. Da hast du mehr von als blind den Quelltext 
zusammenzusuchen. Vor allem vereinfacht das die Fehlerfindung und 
Behebung um einiges.

von Squat *. (squat)


Lesenswert?

Ich wollte an dieser Stelle von niemandem Tipps, wie ich grundsätzlich 
hier was lernen kann.

Vielleicht habe ich mich falsch ausgedrückt.

Entschuldigt Bitte.

Natürlich habe ich mich belesen. Neben den "AVR-GCC Tutorial" und den 
Grundlagen aus dem "AVR-Tutorial" habe ich noch "AVR - Hardware und 
C-Programmierung in der Praxis", sowie PROGRAMMIEREN IN C oder 
C-Programmierung unter Linux/UNIX/Windows durch gearbeitet. Daher habe 
ich neben dem Datenblatt auch das grundsätzliche Gerüst.

Ich weiß ja nicht wie Ihr lernt, aber ich lerne ganz viel durch 
ausprobieren. Und so bin ich auch soweit gekommen, habe den ADC ans 
laufen bekommen und kann diesen über 4 LEDs signalisieren, ein 
Rundumlicht aus 4 Lämpchen,  eine Jumper-Abfrage sowie das Ansteuern 
eines Servos.

Was mir jetzt noch fehlt sind ein paar C-Grundlagen, die nach und nach 
erarbeitet werden sowie weitere Hardwarefunktionen.

Und darum geht es hier. Benötige Hilfe bei der obengenannten 
Aufgabenstellung und wäre für jeden aufschlußreichen Hinweis dankbar.

Und danke an  MWS und  Frederik Krämer für die ersten Hilfestellungen.

von MWS (Gast)


Lesenswert?

Hier ist Dein Fehler:
1
TCCR0A |= (1 << CS02);
Schau Dir das DB an, dann weist Du warum.

Wobei auch ich sagen muss, Dein Code ist schwer zu lesen, und dann fällt 
erfahrungsgemäß die Hilfe geringer aus, wenn sich da erst jemand 
umständlich durchpflügen muss.

von Squat *. (squat)


Lesenswert?

Vielen Dank.

Und schon wieder konnte ich was lernen. War mir garnicht bewusst, dass 
die Parametisierung über zwei Register geht. Aber dank eurer Hilfe und 
dem Datenblatt habe ich es nun verstanden.

Mich würde noch interessieren, was zu schwer zu lesen ist. Ist das zu 
viel Quelltext oder schlecht kommentiert oder liegt es an dem 
Programmaufbau.

Eine Frage hätte ich jedoch noch. Die LED geht nicht ganz aus. Das wäre 
mit der Pumpe dann genauso. Woran liegt das?

Der vollständigkeitshalber hänge ich hier nochmal den funktionstüchtigen 
Quelltest an.
1
//ICC-AVR application builder : 13.04.2010 16:15:44
2
// Target : m48
3
// Crystal: 8.0000Mhz
4
5
#include <iom48v.h>
6
#include <macros.h>
7
8
unsigned char i = 0;
9
unsigned int result;
10
11
void port_init(void)
12
{
13
 PORTB = 0xF1;
14
 DDRB  = 0x0E;
15
 PORTC = 0x43; 
16
 DDRC  = 0xBC;
17
 PORTD = 0x00;
18
 DDRD  = 0xFF;
19
}
20
21
//TIMER0 initialize - prescale:256
22
// WGM: PWM Fast
23
// desired value: ...mSec
24
// actual value:  ...mSec ()
25
void timer0_init(void)
26
{
27
 //OCR0A = 0x20;
28
 //OCR0B = 0x40;
29
 TCCR0B = 0x00; //stop
30
 TCNT0 = 0x01; //set count
31
 TCCR0A = 0xA3; 
32
 TCCR0B = 0x04; //start timer
33
}
34
35
//Ist gleich zu setzen mit
36
//void timer0_init(void)
37
//{
38
//    OCR0A = 0x80;
39
//  OCR0B = 0x80;
40
//  TCCR0A |= (1 << WGM01) | (1 << WGM00);    // Fast PWM
41
//  TCCR0A |= (1 << COM0A1);                  // Fast PWM, non-inverting mode
42
//  TCCR0A &= ~(1 << COM0A0);
43
//  TCCR0B |= (1 << CS02);                    // Prescaler: 1/256
44
45
46
47
//TIMER1 initialize - prescale:64
48
// WGM: 0) Normal, TOP=0xFFFF
49
// desired value: 100mSec
50
// actual value: 100,000mSec (0,0%)
51
void timer1_init(void)
52
{
53
 TCCR1B = 0x00; //stop
54
 TCNT1H = 0xCF; //setup
55
 TCNT1L = 0x2C;
56
 OCR1AH = 0x30;
57
 OCR1AL = 0xD4;
58
 OCR1BH = 0x30;
59
 OCR1BL = 0xD4;
60
 ICR1H  = 0x30;
61
 ICR1L  = 0xD4;
62
 TCCR1A = 0x00;
63
 TCCR1B = 0x03; //start Timer
64
}
65
66
//ADC initialize
67
// Conversion time: 6uS
68
void adc_init(void)
69
{
70
 ADCSRA = 0x00; //disable adc
71
 ADMUX = 0x00;  //select adc input 0
72
 ACSR  = 0x80;
73
 ADCSRB = 0x00;
74
 ADCSRA = 0x01;
75
 
76
}
77
78
#pragma interrupt_handler timer1_ovf_isr:iv_TIM1_OVF
79
void timer1_ovf_isr(void)
80
{
81
 //TIMER1 has overflowed
82
 TCNT1H = 0xCF; //reload counter high value
83
 TCNT1L = 0x2C; //reload counter low value
84
 
85
86
//----------------------------------------------------------------------------//
87
       //         AD-Wandlung
88
//----------------------------------------------------------------------------//
89
       // Dummy-Readout
90
       ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);  // ADC aktivieren, Frequenzvorteiler: setzen auf 64 (8 MHz / 64 = 125 kHz) und ADC aktivieren
91
       ADMUX = 0x00;                      // Kanal waehlen (ADC0)
92
       ADMUX |= (1<<REFS0) | (1<<REFS1);        // interne Referenzspannung nutzen 
93
       ADCSRA |= (1<<ADSC);               // eine ADC-Wandlung
94
       while(!(ADCSRA & (1<<ADIF)));          // auf Abschluss der Konvertierung warten (ADIF-bit)
95
       result = ADC;                    // ADC muss einmal gelesen werden,
96
                                        // sonst wird Ergebnis der nächsten Wandlung
97
                                        // nicht übernommen.
98
       
99
       //ADC-Messung mit arithmetischen Mittel aus 4 Messungen
100
       result = 0;
101
       for (i=0;i<4;i++)
102
            {
103
          ADCSRA |= (1<<ADSC);             // Messung ausfuehren
104
        while ( ADCSRA & (1<<ADSC) );        // Konvertierung abwarten
105
        result += ADC;                     // aufaddieren zur Mittelwertbildung (ADC auslesen der zwei Bits
106
        }
107
        ADCSRA &= ~(1<<ADEN);               // ADC ausschalten
108
        
109
        result /= 16; // 
110
        
111
        OCR0A = result;
112
        OCR0B = result;
113
        
114
        if (blink_state = 0)
115
        {}
116
        if (blink_state = 1)
117
        {}
118
        if (blink_state = 2)
119
        {}
120
121
122
       
123
       if (result < 63)  //410 = 5,4V
124
               {
125
          PORTD &= ~0x15; // PD4, PD2 &PD0 low
126
             PORTD |= 0x08; // PD3 high => LED an
127
          }
128
       if ((result < 127) & (result >= 63)) //430 = 5,7V
129
             {
130
          PORTD &= ~0x0D; // PD3, PD2 & PD0 low
131
             PORTD |= 0x10; // PD4 high => LED an
132
          }
133
           if ((result < 191) & (result >= 127)) //915 = 10,8V, 975 = 11,5V bei 100K und 330R
134
             {
135
          PORTD &= ~0x1c; // PD4, PD3 & PD2 low
136
             PORTD |= 0x01; // PD0 high => LED an
137
          } 
138
           if  (result >= 191)
139
          {
140
          PORTD &= ~0x19; // PD4, PD3 & PD0 low
141
                 PORTD |= 0x04; // PD2 high => LED an
142
          }
143
144
      
145
}
146
147
////////////////////////////////////////////////////////////////////////////////
148
// Hauptprogramm
149
////////////////////////////////////////////////////////////////////////////////
150
void main(void)
151
{
152
 //stop errant interrupts until set up
153
 CLI(); //disable all interrupts
154
 port_init();
155
 timer0_init();
156
 timer1_init();
157
 adc_init();
158
 
159
160
 MCUCR = 0x00;
161
 EICRA = 0x00; //extended ext ints
162
 EIMSK = 0x00;
163
 
164
 TIMSK0 = 0x00; //timer 0 interrupt sources
165
 TIMSK1 = 0x01; //timer 1 interrupt sources
166
 TIMSK2 = 0x00; //timer 2 interrupt sources
167
 
168
 PCMSK0 = 0x00; //pin change mask 0 
169
 PCMSK1 = 0x00; //pin change mask 1 
170
 PCMSK2 = 0x00; //pin change mask 2
171
 PCICR = 0x00; //pin change enable 
172
 PRR = 0x00; //power controller
173
 SEI(); //re-enable interrupts
174
 //all peripherals are now initialized
175
   
176
 while(1);
177
  // Endlosschleife, blinken läuft im 100ms Interrupt
178
 
179
  
180
}

von Karl H. (kbuchegg)


Lesenswert?

Squat *** schrieb:

> Mich würde noch interessieren, was zu schwer zu lesen ist.

Vieles.

zb
welche Bits werden hier gesetzt?
1
 TCCR0A = 0xA3; 
2
 TCCR0B = 0x04; //start timer
Was bedeuten sie? Warum werden sie gesetzt?

1
void timer1_ovf_isr(void)
2
{
3
 //TIMER1 has overflowed
4
 TCNT1H = 0xCF; //reload counter high value
5
 TCNT1L = 0x2C; //reload counter low value
Kann dein Compiler die beiden TCNT1 Register zu einem logischen 16 Bit 
Regsiter zusammenfassen? Im gcc geht zb das
1
  TCNT1 = 0xCF2C;
damit erhebt isch aber sofort die Frage: Huch 0xCF2C. Was'n das?
1
  TCNT1 = 53036;
Damit aber sofort die nächste Frage: Warum ausgerechnet dieser Wert, 
warum kein anderer? Wo kommt der Wert her? Wenn ich meine Taktfrequenz 
ändere, muss ich den anpassen? Wie muss ich den anpassen? Kann ich das 
nicht am besten so fomulieren, dass der Compiler mir den Wert 
ausrechnet, wenn ich ihm Taktfrequenz und gewünschte Zeit angebe?

Die Kommentare
1
void timer1_ovf_isr(void)
2
{
3
 //TIMER1 has overflowed
4
 TCNT1H = 0xCF; //reload counter high value
5
 TCNT1L = 0x2C; //reload counter low value
sind zwar ein netter Versuch, mehr aber auch nicht. Das da das High Byte 
vom Counter beschrieben wird, sehe ich auch im Code. Dazu brauch ich 
keinen Kommentar. Viel interessanter: Warum ausgerechnet mit diesem 
Wert?


Das hier
1
       for (i=0;i<4;i++)
2
            {
3
          ADCSRA |= (1<<ADSC);             // Messung ausfuehren
4
        while ( ADCSRA & (1<<ADSC) );        // Konvertierung abwarten
5
        result += ADC;                     // aufaddieren zur Mittelwertbildung (ADC auslesen der zwei Bits
6
        }
7
        ADCSRA &= ~(1<<ADEN);               // ADC ausschalten
8
        
9
        result /= 16; //
ist nicht unmittelbar logisch. Du machst 4 Messungen, dividierst die 
Summe der Messungen aber durch 16. Programmfehler? (Ich weiss schon, das 
du auf einen Wertebereich 0..255 runterkommen willst. Aber dazu muss ich 
den Rest der Funktion lesen, bis mir das dämmert)

Was soll das sein?
1
        if (blink_state = 0)
2
        {}
3
        if (blink_state = 1)
4
        {}
5
        if (blink_state = 2)
6
        {}

1
        PORTD &= ~0x15; // PD4, PD2 &PD0 low
2
             PORTD |= 0x08; // PD3 high => LED an

Super. Das PD4, PD2, PD0 auf low geschaltet werden, seh ich auch im 
Code. Aber warum?

Deine Konstanten für 'Welche LED hängt wo' sind quer über den ganzen 
Programmtext verstreut.

Denkst du nicht, dass
1
        Led_off( VOLTAGE_LOW_LED | VOLTAGE_MEDIUM_LED | FAILURE_LED );
2
        Led_on( VOLATGE_GOOD_LED );
sehr viel einfacher zu lesen und zu verstehen wäre? Von der wesentlich 
einfacheren Adaptierbarkeit an einer Stelle bei Hardwareänderungen
1
#define LED_PORT            PORTD
2
#define LED_DDR             DDRD
3
4
#define VOLTAGE_LOW_LED     (1<<PD4)
5
#define VOLTAGE_MEDIUM_LED  (1<<PD2)
6
#define VOLTAGE_GOOD_LED    (1<<PD3)
7
#define FAILURE_LED         (1<<PD0)
mal ganz abgesehen.

Sieh dir deinen Code an, wie gepostet. Sind die Einrückungen konsistent?

etc. etc.

von Djin Qiujote del manche (Gast)


Lesenswert?

>Ist das zu viel Quelltext oder schlecht kommentiert oder liegt es an dem
>Programmaufbau.
Genau. Später dann frag' nochmal. Da kommt noch mehr dazu.

>Ich wollte an dieser Stelle von niemandem Tipps, wie ich grundsätzlich
>hier was lernen kann.
Schon, aber wir sind sowas von kommunikativ hier... Du hast's nötig. Und 
wie willst Du das verhindern? Ätsch.

>Natürlich habe ich mich belesen. Neben den "AVR-GCC Tutorial" und den
>Grundlagen aus dem "AVR-Tutorial" habe ich noch "AVR - Hardware und
>C-Programmierung in der Praxis", sowie PROGRAMMIEREN IN C oder
>C-Programmierung unter Linux/UNIX/Windows durch gearbeitet.

---> 6. 3.

-----------------------------------------------


1. Manche Posts sollte man nicht beantworten.
2. Manche Antworten sollte man ignorieren.
3. Manche Texte sollte man zweimal lesen.
4. Manche Programme sollte man zweimal schreiben.
6. Ach! (Loriot)
7. Ich bin doch klüger, besser, länger, schöner als Du, egal was Du 
sagst.
8. Google

von spess53 (Gast)


Lesenswert?

Hi

>Was mir jetzt noch fehlt sind ein paar C-Grundlagen, die nach und nach
>erarbeitet werden sowie weitere Hardwarefunktionen.

Da fehlt auch noch etwas Verständnis für den Controller.

>void adc_init(void)
>{
> ADCSRA = 0x00; //disable adc
> ADMUX = 0x00;  //select adc input 0
> ACSR  = 0x80;
> ADCSRB = 0x00;
> ADCSRA = 0x01;
>}

Das ist keine Init. Bis auf zwei irrelevante Bit sind das die Zustände 
nach einem Reset. Hier solltest du die Einstellungen machen, die sich 
im Programm nicht mehr ändern. Also Referenzspannungsquelle, 
Prescaler... .
Dann kannst du die die ständige Neuinitialisierung und den Dummyread im 
Timerinterrupt sparen.

>Eine Frage hätte ich jedoch noch. Die LED geht nicht ganz aus. Das wäre
>mit der Pumpe dann genauso. Woran liegt das?

Am Non-Inverting-Mode. Wenn du wirklich auf Null herunter willst nimm 
den Inverting Mode

MfG Spess

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

spess53 schrieb:

> Am Non-Inverting-Mode. Wenn du wirklich auf Null herunter willst nimm
> den Inverting Mode

Oder man schaltet im Fall "Null" einfach die PWM ab.

Gruß,

Frank

von spess53 (Gast)


Lesenswert?

Hi

>Oder man schaltet im Fall "Null" einfach die PWM ab.

Inverting Mode ist aber einfacher. Kostet einen zusätzlichen 
Assemblerbefehl.

MfG Spess

von Squat *. (squat)


Lesenswert?

Wunderbar.

Vielen Dank an alle, die diesen Threat gefüllt haben.

Neben der Lösung konnte ich so noch weitere Denkanstöße erhalten.

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.