Guten Abend!
Ich habe folgendes Programm welches nicht so läuft wie ich es mir
wünsche:
Ein ATtiny45 soll über einen seiner ADC-Kanäle eine Spannung einlesen
(Sensorspannung). Anschließend wird der Kanal umgeschaltet und es wird
eine weitere Spannung eingelesen (Referenzspannung). Nur soll verglichen
werden, ob die eingelesene Referenzspannung größer ist, als die
eingelesene Sensorspannung. Trifft das zu, so sollen zwei LEDs
eingeschaltet werden, sonst aus.
Leider bleiben die LEDs dunkel und ein Test mit einer Debug-LED hat
ergeben, dass er immer in den zweig springt "Referenzspannung kleiner
als Sensorspannung".
Hier das Programm:
Die Main:
1 | /*
|
2 | * Tank_Heater.c
|
3 | *
|
4 | * Created: 06.01.2015 19:52:30
|
5 | * Author: *****
|
6 | */
|
7 |
|
8 | #define F_CPU 800000UL
|
9 |
|
10 | #include <avr/io.h>
|
11 | #include <avr/interrupt.h>
|
12 | #include <util/delay.h>
|
13 | #include "ADC.h"
|
14 |
|
15 | #define HEATER PB1
|
16 | #define LED PB3
|
17 | #define DEBUG_LED PB0
|
18 |
|
19 | void init_ports(void);
|
20 | void checkTemperature(void);
|
21 | void debug(void);
|
22 |
|
23 | int main(void)
|
24 | {
|
25 | uint8_t i;
|
26 |
|
27 | init_ADC();
|
28 | init_ports();
|
29 |
|
30 | // Toggle LED again, to show -> initialisation done
|
31 | for(i = 0; i < 2; i++ )
|
32 | {
|
33 | PORTB = (1<<LED);
|
34 | _delay_ms(1000);
|
35 | PORTB &= ~(1<<LED);
|
36 | _delay_ms(1000);
|
37 | }
|
38 |
|
39 | // Toggle heater, so the user can see if it is all right
|
40 | PORTB = (1<<HEATER);
|
41 | _delay_ms(2000);
|
42 | PORTB &= ~(1<<HEATER);
|
43 |
|
44 | while(1)
|
45 | {
|
46 | checkTemperature();
|
47 |
|
48 | _delay_ms(500);
|
49 | }
|
50 |
|
51 | return 0;
|
52 | }
|
53 |
|
54 | // Initialize the port-pins
|
55 | void init_ports(void)
|
56 | {
|
57 | // LED-Port (output), Relay-Port (for heater) (output)
|
58 | DDRB |= (1<<LED) | (1<<HEATER) | (1<<DEBUG_LED);
|
59 |
|
60 | PORTB &= ~(1<<LED);
|
61 | PORTB &= ~(1<<HEATER);
|
62 | PORTB &= ~(1<<DEBUG_LED);
|
63 | }
|
64 |
|
65 | // Function which compares the actual temperature value with the user-set value. Depending on the result, the heater is controlled
|
66 | void checkTemperature(void)
|
67 | {
|
68 | uint16_t tempValue, refTemp;
|
69 |
|
70 | // Get the actual temperature value from sensor
|
71 | tempValue = getNewSensorValue();
|
72 |
|
73 | // Get the actual reference temperature
|
74 | refTemp = setNewTempValue();
|
75 |
|
76 | // Control the heater depending on the measure
|
77 | if(tempValue < refTemp)
|
78 | {
|
79 | // Heater on
|
80 | PORTB |= (1<<HEATER);
|
81 | PORTB |= (1<<LED);
|
82 | }
|
83 | else
|
84 | {
|
85 | // Heater off
|
86 | PORTB &= ~(1<<HEATER);
|
87 | PORTB &= ~(1<<LED);
|
88 | }
|
89 | }
|
90 |
|
91 | void debug(void)
|
92 | {
|
93 | PORTB = (1<<DEBUG_LED);
|
94 | _delay_ms(500);
|
95 | PORTB &= ~(1<<DEBUG_LED);
|
96 | _delay_ms(500);
|
97 | }
|
Der Header:
1 | /*
|
2 | * ADC.h
|
3 | *
|
4 | * Created: 26.08.2014 13:44:10
|
5 | * Author: ******
|
6 | */
|
7 |
|
8 |
|
9 | #ifndef ADC_H_
|
10 | #define ADC_H_
|
11 |
|
12 | #include <avr/io.h>
|
13 |
|
14 | extern void init_ADC(void);
|
15 | extern uint16_t setNewTempValue(void);
|
16 | extern uint16_t getNewSensorValue(void);
|
17 | extern void debug(void);
|
18 |
|
19 | #endif /* ADC_H_ */
|
Und die ADC-Datei:
1 | /*
|
2 | * ADC.c
|
3 | *
|
4 | * Created: 26.08.2014 13:44:00
|
5 | * Author: ******
|
6 | *
|
7 | * This file includes initialization and access function for the use of the build in ADC of an ATtiny45
|
8 | */
|
9 |
|
10 | #include <avr/io.h>
|
11 | #include "ADC.h"
|
12 |
|
13 | // Function to initialize the ADC
|
14 | void init_ADC(void)
|
15 | {
|
16 | // Select the reference voltage source (VCC)
|
17 | ADMUX &= ~(1<<REFS0) | ~(1<<REFS1);
|
18 |
|
19 | // Select prescaler to clk/32
|
20 | ADCSRA |= (1<<ADPS2) | (1<<ADPS0);
|
21 | ADCSRA &= ~(1<<ADPS1);
|
22 |
|
23 | // Enable the ADC
|
24 | ADCSRA = (1<<ADEN);
|
25 |
|
26 | // Do one conversion, for start-up of the ADC
|
27 | ADCSRA |= (1<<ADSC);
|
28 | // Wait for conversion complete
|
29 | while(ADCSRA & (1<<ADSC)){}
|
30 |
|
31 | // The value has to be read, because otherwise it could cause a false value next time converting
|
32 | (void) ADCW;
|
33 | }
|
34 |
|
35 | // Function to get a new set-temperature
|
36 | uint16_t setNewTempValue(void)
|
37 | {
|
38 | // Select temperature-set-channel
|
39 | ADMUX &= ~(1<<MUX1);
|
40 | ADMUX = (1<<MUX2);
|
41 |
|
42 | // Get a new value
|
43 | ADCSRA |= (1<<ADSC);
|
44 | // Wait for conversion complete
|
45 | while(ADCSRA & (1<<ADSC)){}
|
46 |
|
47 | // Return new value
|
48 | return ADCW;
|
49 | }
|
50 |
|
51 | // Function to read the actual temperature from sensor
|
52 | uint16_t getNewSensorValue(void)
|
53 | {
|
54 | // Select sensor-measuring-channel
|
55 | ADMUX &= ~(1<<MUX2);
|
56 | ADMUX = (1<<MUX1);
|
57 |
|
58 | // Get a new value
|
59 | ADCSRA |= (1<<ADSC);
|
60 | // Wait for conversion complete
|
61 | while(ADCSRA & (1<<ADSC)){}
|
62 |
|
63 | // Return value
|
64 | return ADCW;
|
65 | }
|
Achja, hardwaremäßig sieht das ganze so aus, da ich am
Referenzspannungseingang fest 2,5V habe und am Sensorspannungseingang
ein Poti mit dem ich zwischen 1V und 5V regeln kann. Die Spannungen an
den Eingängen habe ich gemessen, dass passt soweit.
Ich hoffe ihr habt ein paar Ideen ;-)