Histereza aTtiny13
Wiec zmienielem troche program i dziła jak chciałem:) aczkolwiem musiałem zastosować delay
Film
http://www.youtube.com/watch?v=punKRmF2 ... e=youtu.be
Jakim rejestrze???
Film
http://www.youtube.com/watch?v=punKRmF2 ... e=youtu.be
Kod: Zaznacz cały
#define F_CPU 4800000UL
#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>
#define LED1 PB1
#define LED2 PB2
#define ADCIN PB4
int main(void)
{
while(1)
{
DDRB |= (1<<LED1)|(1<<LED2);
DDRB &=~ (1<<ADCIN);
ADCSRA |= (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1) ;
ADMUX |= (1<<MUX1)|(1<<REFS0);
int tab[5];
int wynik = 0;
int i;
for(i=0;i<5;i++)
{
ADCSRA |= (1<<ADSC);
while(ADCSRA & (1<<ADSC));
tab[i] = ADC;
_delay_ms(50);
}
wynik = (tab[0] + tab[1] + tab[2] + tab[3] + tab[4]) / 5 ;
if(wynik<700)
{
PORTB &=~ (1<<LED1);
PORTB &=~ (1<<LED2);
}
else if(wynik<750)
{
PORTB &=~ (1<<LED1);
PORTB |= (1<<LED2);
}
else
{
PORTB |= (1<<LED1);
PORTB |= (1<<LED2);
}
}
}Myśle że tak i tak byłoby ok skoro ładnie działa. Idąc dalej chciałbym uzyskać ciągły pomiar. Za właczenie tej opcji odpowiada bit ADATE w rejestrze ADSRA w Tiny13 oraz trzeba usunąć linijke:
Tak kod nie działa, co należałoby jeszcze zrobić? Też chciałbym mieć to z uśrednieniem wyniku.
edit:
Właściwie kiedy warto stosować ciągły pomiar a kiedy pojedyńczy jak wyżej w kodzie??
Kod: Zaznacz cały
ADCSRA |= (1<<ADSC);
while(ADCSRA & (1<<ADSC)); edit:
Właściwie kiedy warto stosować ciągły pomiar a kiedy pojedyńczy jak wyżej w kodzie??
OK nie mam pojęcie o tym ale jak wyczytałem, funkcja ta powoduje zatrzymanie wew. układów i wej/wyj które powodują zakłócenia pomiaru na ADC, aby włączyć tryb o którym mowa nalezy w rejestrze MCUCR włączyć bit SM0, bit ten odpowiada za włączenie wg tabeli ADC Noise Reduction. Nalęzy to zrobic gdzies po włączeniu ADC z tego co wyczytałem.. a jak wzbudzić potem uC do dalszego dzialania aby wykonaf funkcje if itd?
Możesz to zrobić prościej dołączając nagłówek sleep.h.
Tutaj opis: http://www.nongnu.org/avr-libc/user-manual/modules.html
A procedura wygląda na przykład tak (fragment artykułu, który ukaże się dzisiaj dla ATmega8):
Wystarczy wywołać funkcję dd_swiatlo_adc_pomiar_start() i następnie pomiar masz już w zmiennej swiatlo_pomiar. Możesz także nie odczytywać ADC w przerwaniu pozostawiając funkcję pustą (ale musi być), a odczytać tam gdzie wywołałeś wtedy zmienna nie będzie potrzebna.
Datasheet ATmega8:
Tutaj opis: http://www.nongnu.org/avr-libc/user-manual/modules.html
A procedura wygląda na przykład tak (fragment artykułu, który ukaże się dzisiaj dla ATmega8):
Kod: Zaznacz cały
#include <avr/sleep.h>
volatile unsigned int swiatlo_pomiar;
void dd_swiatlo_adc_ini(void){
//Funkcja inicjuje przetwornik ADC
DDRC &= ~(1<<PC5); //wejście
ADMUX = (1<<REFS0) //VCC jako napięcie referencyjne
|(1<<MUX2) | (1<<MUX0); //kanał ADC5
ADCSRA = (1<<ADEN) //włącz ADC
|(1<<ADIE) //włącz przerwania
|(1<<ADPS0) //preskaler 128
|(1<<ADPS1)
|(1<<ADPS2);
sei(); //włącz przerwania globalne
}
//------------------------------------------------------------
void dd_swiatlo_adc_pomiar_start(void){
//ustaw tryb snu ADC Noise Reduction
set_sleep_mode(SLEEP_MODE_ADC);
sleep_enable();
//rozpocznij pomiar światła poprzez uśpienie mikrokontrolera
sleep_cpu();
}
//------------------------------------------------------------
ISR(ADC_vect){
//Przerwanie ADC - pomiar zakończony
swiatlo_pomiar = ADC;
}
Datasheet ATmega8:
The ADC features a noise canceler that enables conversion during sleep mode to reduce noise
induced from the CPU core and other I/O peripherals. The noise canceler can be used with ADC
Noise Reduction and Idle mode. To make use of this feature, the following procedure should be
used:
1. Make sure that the ADC is enabled and is not busy converting. Single Conversion
mode must be selected and the ADC conversion complete interrupt must be
enabled.
2. Enter ADC Noise Reduction mode (or Idle mode). The ADC will start a conversion
once the CPU has been halted.
3. If no other interrupts occur before the ADC conversion completes, the ADC interrupt
will wake up the CPU and execute the ADC Conversion Complete interrupt routine. If
another interrupt wakes up the CPU before the ADC conversion is complete, that
interrupt will be executed, and an ADC Conversion Complete interrupt request will be
generated when the ADC conversion completes. The CPU will remain in Active mode
until a new sleep command is executed.
Note that the ADC will not be automatically turned off when entering other sleep modes than Idle
mode and ADC Noise Reduction mode. The user is advised to write zero to ADEN before entering
such sleep modes to avoid excessive power consumption.
Dondu można w moim przypadku wszystko zrealizować w jednym kodzie bez wywoływania kolejnej funkcji? Troche się gubię, bo troche tego tam jest.
Próbuję się wzorować na 'pipdręczycielu' ale to wydaje sie byc inną bajką.Najwiekszy problem sprawia w którym miejscu wstawić;
set_sleep_mode(SLEEP_MODE_ADC);
sleep_enable();
sleep_cpu();
Próbuję się wzorować na 'pipdręczycielu' ale to wydaje sie byc inną bajką.Najwiekszy problem sprawia w którym miejscu wstawić;
set_sleep_mode(SLEEP_MODE_ADC);
sleep_enable();
sleep_cpu();
Ten program to porażka;/, ale pokaże ja kombinowałem...
Wydawało mi się że podstawie kilka linijek kodu związanego z sleep do mojego poprzedniego kodu i będzie ok, szczerze nie ogarniam.
-jak wybudza się procek z trybu Noise reduction, automatycznie?
-w którym momenvie go uspać
-jak podstawic wartość pomierzonego ADC do zmiennej o ile to potrzebne..
duzo pytań się nasuwa..
Wydawało mi się że podstawie kilka linijek kodu związanego z sleep do mojego poprzedniego kodu i będzie ok, szczerze nie ogarniam.
-jak wybudza się procek z trybu Noise reduction, automatycznie?
-w którym momenvie go uspać
-jak podstawic wartość pomierzonego ADC do zmiennej o ile to potrzebne..
duzo pytań się nasuwa..
Kod: Zaznacz cały
#define F_CPU 4800000UL
#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#define LED1 PB1
#define LED2 PB2
#define ADCIN PB4
int main(void)
{
DDRB |= (1<<LED1)|(1<<LED2);
DDRB &=~ (1<<ADCIN);
ADCSRA |= (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1) ;
ADMUX |= (1<<MUX1)|(1<<REFS0);
sei();
for(;;)
{
if(ADC<700)
{
PORTB &=~ (1<<LED1);
PORTB &=~ (1<<LED2);
}
else if(ADC<750)
{
PORTB &=~ (1<<LED1);
PORTB |= (1<<LED2);
}
else
{
PORTB |= (1<<LED1);
PORTB |= (1<<LED2);
}
set_sleep_mode(SLEEP_MODE_ADC);
sleep_enable();
sleep_cpu();
}
}
ISR(ADC_vect){
}