Witam! Mam spory problem z ADC, który nie pozwala mi zasnąć:
Konfiguracja sprzętowa:
- Wybrane wewnętrzne źródło napięcia 2.56V
- Kondensator na AREF-GND (zgodnie z instrukcją)
- AVCC wolne (niepodpięte)
- Źródło napięcia na PC0 (ADC0)
- Wyjście na wyświetlacz LCD
Konfiguracja software:
- Pomiar na przerwaniu
- Uśrednienie z 10 wyników dla lepszej stabilności
Problem:
- Po pierwsze ADC działa (manipulacja napięciem na ADC0 zmienia wyświetlaną wartość) - daje wyniki, ale absurdalne (patrz niżej)
- Gdy ADC0 jest niepodłączone, uC mierzy wartość 1024 (a powinna być 0, prawda?)
- Gdy zewrę ADC0 do masy jest 0
- Gdy podłączę pod ADC0 źródło napięcia (np. bateria AA, bo zakres jest 0-2.56 - nie używam dzielnika napięcia), pojawiają się wyniki z kosmosu, które nijak nie dają się przeliczyć na rzeczywiste napięcie (sprawdzane multimetrem)
Załączam poniżej kod źródłowy i bardzo proszę o pomoc. W czym tkwi problem?
Konfiguracja sprzętowa:
- Wybrane wewnętrzne źródło napięcia 2.56V
- Kondensator na AREF-GND (zgodnie z instrukcją)
- AVCC wolne (niepodpięte)
- Źródło napięcia na PC0 (ADC0)
- Wyjście na wyświetlacz LCD
Konfiguracja software:
- Pomiar na przerwaniu
- Uśrednienie z 10 wyników dla lepszej stabilności
Problem:
- Po pierwsze ADC działa (manipulacja napięciem na ADC0 zmienia wyświetlaną wartość) - daje wyniki, ale absurdalne (patrz niżej)
- Gdy ADC0 jest niepodłączone, uC mierzy wartość 1024 (a powinna być 0, prawda?)
- Gdy zewrę ADC0 do masy jest 0
- Gdy podłączę pod ADC0 źródło napięcia (np. bateria AA, bo zakres jest 0-2.56 - nie używam dzielnika napięcia), pojawiają się wyniki z kosmosu, które nijak nie dają się przeliczyć na rzeczywiste napięcie (sprawdzane multimetrem)
Załączam poniżej kod źródłowy i bardzo proszę o pomoc. W czym tkwi problem?
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include "HD44780.h"
volatile float result = 0;
volatile float values[10] = {0,0,0,0,0,0,0,0,0,0};
volatile unsigned int current = 0;
char text[12];
void init_adc() {
sei();
PORTC = 0x00;
DDRC = 0x00;
ADMUX |= _BV(REFS0) | _BV(REFS1); //internal reference 2.56V
//ADMUX |= _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // calibration test
ADCSRA |= _BV(ADEN) | _BV(ADFR) | _BV(ADPS0) | _BV(ADPS1);
}
void adc_start_conversion()
{
ADCSRA |= _BV(ADSC) | _BV(ADIE);
}
ISR(ADC_vect)
{
result = (float)(ADCL | (ADCH << 8));
values[current] = result;
current+=1;
if(current==10)
current = 0;
//stop ADC
ADCSRA &= ~(1<<ADIE);
}
void calculateAvg() {
float avg = (values[0] + values[1] + values[2] + values[3] + values[4] + values[5]
+ values[6] + values[7] + values[8] + values[9])/10;
dtostrf(avg,6,2,text);
//text[6]='V';
}
int main()
{
_delay_ms(200);
LCD_Initalize();
LCD_Clear();
LCD_Write1x16Text("Waiting...");
// blink LED
DDRD |= _BV(PD7);
PORTD |= _BV(PD7);
init_adc();
adc_start_conversion();
while(1){
_delay_ms(100);
// blink LED
PORTD ^= _BV(PD7);
adc_start_conversion();
calculateAvg();
LCD_Clear();
LCD_Write1x16Text(text);
set_sleep_mode(SLEEP_MODE_ADC);
}
return 0;
}