Mám malý problém s ADC-čkem u ATtiny45. Napsal jsem si jednoduchý program, který má za úkol měřit napětí na dvou hall sondách ACS712.
Tyto sondy mají na výstupu napětí 2,5V a podle proudu potom buť zvyšují výstup, nebo snižují.
Takže dejme tomu, že defaultně mám na vstupu hodnotu 2,5V. Referenci mám externí 3V. Potom hodnota ADC bude 853. Jakmile připojím zátěž, tak na výstupu budu mít třeba 2,6V, což odpovídá ADC = 887.
Pokud dojde k tomu, že hodnota výchozí je menší než aktuálně naměřená, dojde k překlopení výstupu.
Program takhle funguje, ale mám problém s tím, že místo toho, aby byl výstup trvale seplý (pokud teče proud), tak mi výstup pulzuje. Proto se obracím sem, jestli někdo v těch mých pár řádcích neuvidí nějakou chybu. Díky moc
Init ADC.
Kód: Vybrať všetko
void init_adc()
{
/* Nastaveni externi reference na pinu PB0 */
ADMUX |= (1 << REFS0);
ADMUX &= ~(1 << REFS1);
/* povoli ADC */
ADCSRA |= (1 << ADEN);
/* preruseni od ADC */
ADCSRA |= (1 << ADIF);
/* nastavi delicku na 64 (125kHz) */
ADCSRA |= (1 << ADPS2);
ADCSRA |= (1 << ADPS1);
ADCSRA &=~(1 << ADPS0);
}
Kód: Vybrať všetko
unsigned int Read_ADC(unsigned char channel){
// vloz cislo kanala, vymaskuj nepouzite bity
ADMUX &= 0xF0;
ADMUX |= channel & 0x0F;
// Start prevodu
ADCSRA |= (1 << ADSC);
// ceka, dokud se neskonci konverze
while(!(ADCSRA & (1<<ADIF)));
// navratova hodnota - vysledok ad prevodu
return ADC;
}
Kód: Vybrať všetko
/*
* DEKM.c
*
* Created: 25.9.2016 10:55:13
* Author : Jirka
*/
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdio.h>
#include <avr/wdt.h>
#define OUT1 PB1
#define OUT2 PB3
unsigned int Read_ADC(unsigned char channel){
// vloz cislo kanala, vymaskuj nepouzite bity
ADMUX &= 0xF0;
ADMUX |= channel & 0x0F;
// Start prevodu
ADCSRA |= (1 << ADSC);
// ceka, dokud se neskonci konverze
while(!(ADCSRA & (1<<ADIF)));
// navratova hodnota - vysledok ad prevodu
return ADC;
}
void init_adc()
{
/* Nastaveni externi reference na pinu PB0 */
ADMUX |= (1 << REFS0);
ADMUX &= ~(1 << REFS1);
/* povoli ADC */
ADCSRA |= (1 << ADEN);
/* preruseni od ADC */
ADCSRA |= (1 << ADIF);
/* nastavi delicku na 64 (125kHz) */
ADCSRA |= (1 << ADPS2);
ADCSRA |= (1 << ADPS1);
ADCSRA &=~(1 << ADPS0);
}
void init_output()
{
DDRB |= (1 << OUT1); //tento piny jako vystupni
DDRB |= (1 << OUT2); //tento piny jako vystupni
PORTB |= (1 << OUT1) | (1 << OUT2); //nastavi pullup odpory
}
int main(void)
{
/* inicializace ADC */
init_adc();
/* inicializace vystupu */
init_output();
/* povoleni preruseni */
sei();
uint16_t adc1 = 0, adc2 = 0, initADC1 = 0, initADC2 = 0, pomocna1 = 0, pomocna2 = 0;
pomocna1 = Read_ADC(1);
pomocna2 = Read_ADC(2);
pomocna1 = 0; pomocna2 = 0;
for (int i = 0; i < 5; i++)
{
pomocna1 += Read_ADC(1); //po zapnuti vyctu hodnotu z ADC pro lepsi stabilitu
_delay_ms(1);
pomocna2 += Read_ADC(2); //po zapnuti vyctu hodnotu z ADC pro lepsi stabilitu
_delay_ms(1);
}
initADC1 = pomocna1 / 5;
initADC2 = pomocna2 / 5;
/* Replace with your application code */
while (1)
{
/* prumer z 5 hodnot */
pomocna1 = 0; pomocna2 = 0;
for (int i = 0; i < 5; i++)
{
pomocna1 += Read_ADC(1);
_delay_ms(2);
pomocna2 += Read_ADC(2);
_delay_ms(2);
}
adc1 = pomocna1 / 5;
adc2 = pomocna2 / 5;
if (adc1 > (initADC1+10 ) ) //hodnota 850 prevedeno na napeti (850*3)/2^10 = 2,49V (kde 10 odpovida zmene napeti o 0,03V)
PORTB &= ~(1 << OUT1);
else
PORTB |= (1 << OUT1);
if (adc2 > (initADC2+10) )
PORTB &= ~(1 << OUT2);
else
PORTB |= (1 << OUT2);
}
}