1 | #include <avr/io.h>
|
2 |
|
3 | // Variablen
|
4 | uint8_t I = 53; // Strom bei 47 Ohm in mA Wertebereich 1..75,5
|
5 | uint8_t Duty_Cycle = 50; // Duty_Cycle in Prozent Wertebereich 1..100
|
6 | uint16_t U; // aktuelle Spannung am NTC in mV Wertebereich 1..5000
|
7 | uint8_t R; // NTC_Widerstandswert Wertebereich 1..128
|
8 |
|
9 | // AD-Wandler-Prozedur +++ AD-Wandler-Prozedur +++ AD-Wandler-Prozedur +++ AD-Wandler-Prozedur
|
10 |
|
11 | uint16_t ReadChannel()
|
12 | {
|
13 | uint8_t i; // Zähler Wertebereich 1..5
|
14 | uint16_t result; // Spannung am NTC Wertebereich 1..1024
|
15 |
|
16 | ADMUX = 0b00000010; // externe Referenzspannung nutzen und Kanal PB4 auswählen
|
17 |
|
18 | ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler setzen auf 8 (1) und ADC aktivieren
|
19 |
|
20 | /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
|
21 |
|
22 | ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
|
23 | while ( ADCSRA & (1<<ADSC) ) {
|
24 | ; // auf Abschluss der Konvertierung warten
|
25 | }
|
26 | result = ADCW; // ADCW muss einmal gelesen werden,
|
27 | // sonst wird Ergebnis der nächsten Wandlung
|
28 | // nicht übernommen.
|
29 |
|
30 | /* Messung - Mittelwert aus 5 aufeinanderfolgenden Wandlungen */
|
31 | result = 0;
|
32 | for( i=0; i<5; i++ )
|
33 | {
|
34 | ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
|
35 | while ( ADCSRA & (1<<ADSC) ) {
|
36 | ; // auf Abschluss der Konvertierung warten
|
37 | }
|
38 | result += ADCW; // Wandlungsergebnisse aufaddieren
|
39 | }
|
40 | ADCSRA &= ~(1<<ADEN); // ADC deaktivieren
|
41 |
|
42 | result /= 5; // Summe durch 5 teilen = arithm. Mittelwert
|
43 |
|
44 | result = result * 5000/1024; // Umwandeln in den Spannungswert
|
45 |
|
46 | return result;
|
47 | }
|
48 |
|
49 |
|
50 | // PWM-Prozedur +++ PWM-Prozedur +++ PWM-Prozedur +++ PWM-Prozedur +++ PWM-Prozedur +++
|
51 |
|
52 | void PWM(uint8_t duty_cycle)
|
53 | {
|
54 | OCR0A = (duty_cycle*255/100);
|
55 | }
|
56 |
|
57 |
|
58 |
|
59 |
|
60 | // Hauptprogramm +++ Hauptprogramm +++ Hauptprogramm +++ Hauptprogramm +++ Hauptprogramm +++ Hauptprogramm +++
|
61 |
|
62 | int main (void)
|
63 |
|
64 | {
|
65 | // Initial I/O
|
66 |
|
67 | ACSR = 0b10000000; // Analog-Komparator abschalten, spart Strom. ACD-Bit im ACSR auf 1. Außerdem müssen wir sicherstellen, dass die Intern Voltage Reference nicht auf den Analog Comparator geschaltet ist. Dazu muss ACBG in ACSR auf 0 gesetzt werden.
|
68 | DDRB = 0b00000001; // PB0 ist PWM-Ausgang; Rest Eingang
|
69 |
|
70 | PORTB = 0b00000001; // interne Pull-Ups an Port-Pins 1 bis 7 deaktiviert
|
71 |
|
72 | TCCR0A = 0b11000011; // COM0A1 - COM0A0 (Set OC0A on Compare Match, clear OC0A at TOP) WGM01 - WGM00 (set fast PWM)
|
73 | TCCR0B = 0b00000001; // Prescaler = 1 => 37,647 kHz PWM-Frequenz
|
74 | OCR0A = 0; // clear OC0A at TOP, initialize Output Compare Register A to 0
|
75 |
|
76 | while(1) // Endlosschleife
|
77 |
|
78 | {
|
79 | // Analogwert U von PB4 (MUX10) einlesen mit ADC-Noise-Reduzierung wusste ich nicht wie
|
80 |
|
81 | U = ReadChannel();
|
82 |
|
83 | // Spannungswert in NTC_Widerstandswert umwandeln
|
84 |
|
85 | R = U/I;
|
86 |
|
87 | // Duty_Cycle berechnen:
|
88 |
|
89 | Duty_Cycle = (2.8236*R - 84.199);
|
90 |
|
91 |
|
92 | PWM(Duty_Cycle); // PWM-Duty-Cycle an Ausgang PB0
|
93 | // }
|
94 |
|
95 |
|
96 |
|
97 | return 0;
|
98 | }
|