Spannungskomperator mit ADC

#3969842
Lesenswert?

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 ;-)
#3969873
Lesenswert?

Das ist ein weiteres Problem, hatte ich vergessen zu erwähnen, sorry:

Normalerweise setze ich F_CPU auf 8000000UL bei einem 8MHz Quarz und 
alles läuft wie es soll. Nun habe ich den interen Oszillator mit 8 MHz 
(laut AVR Studio) eingeschaltet und wie gewohnt 8000000UL definiert. 
Dann dauert ein _delay_ms(1000) allerdings auf einmal 10 Sekunden? bei 
800000UL läuft alles perfekt?!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren