Zaloguj się, aby zobaczyć kod
#define F_CPU 8000000UL //ustawienie oscylatora na 8MHz
#include <avr/io.h> //dołączenie podstawowej biblioteki
#include <avr/interrupt.h> //dołączenie biblioteki z przerwaniami
#define LED PORTC //zdefiniowanie stałych
volatile uint16_t a1, a2, a3;
int volatile licznik1 = 0; //zmienna dla licznika programowego
int volatile licznik2 = 0;
int volatile licznik3 = 0;
//inicjalizacja adc
void init_ADC(void)
{
ADMUX = (ADMUX & ~(1<<REFS1)) | (1<<REFS0);//00 AREF, 01 AVCC, 11 int 2,5V
ADMUX |= (1<<ADLAR);// 8 bit=1, 10 bit=0
ADCSRA = (1<<ADPS2) | (1<<ADPS1); // select the ADC clock frequency
ADCSRA = ADCSRA | (1<<ADEN); // enable the ADC
}
void ADC_0(void)
{
ADMUX = ADMUX& ~(1<<MUX0)& ~(1<<MUX1)& ~(1<<MUX2)& ~(1<<MUX3);
}
void ADC_1(void)
{
ADMUX = ADMUX | ((1<<MUX0)& ~(1<<MUX1)& ~(1<<MUX2)& ~(1<<MUX3));
}
void ADC_2(void)
{
ADMUX = (ADMUX& ~(1<<MUX0)) | ((1<<MUX1)& ~(1<<MUX2)& ~(1<<MUX3));
}
uint16_t read_ADC(void)
{
ADCSRA = ADCSRA | (1<<ADSC); // start a conversion
while( (ADCSRA & (1<<ADIF)) == 0 ); // wait for conversion to be completed
ADCSRA = ADCSRA | (1<<ADIF); // clear the flag
return ADCH;
}
void init_PWM(void)
{
TCCR0 = 0b01101001;
TCCR1A = 0b10100010; // ustawienie pinów i trybu fast PWM
TCCR1B = 0b00011010; // ustawienia z brakiem preskalera
ICR1=20000;// ustawinie okresu 20ms
}
int PWM(int a
{
OCR1A = 800+a1*55/10;// sterowanie szerokością impulsu od 0,8ms do ok. 2ms
OCR1B = 800+a1*55/10;// sterowanie szerokością impulsu od 0,8ms do ok. 2ms
}
ISR(TIMER0_OVF_vect) //początek funkcji obsługi przerwania
{
licznik1++; //zwiększenie o 1
licznik2++; //zwiększenie o 1
licznik3++; //zwiększenie o 1
TCNT0 = 176;//początkowa wartość timera 0, daje nam przerwanie co 0,00001s
if(licznik1 > 2000) //sprawdzamy, czy nie minęło już 2000 przepełnień, czyli 0,00001s*2000=0,02s=20ms - okres sygnału
{
PORTC ^= 128; //zmiana stanu na porcie c
if(PORTC & 128)
licznik1 = 1930-(a1-140);//ustawienie szerokości impulsu z potencjometru 1
if(!(PORTC & 128))
licznik1 = 200;//ustawinie okresu
}
if(licznik2 > 2000) //sprawdzamy, czy nie minęło już 2000 przepełnień, czyli 0,00001s*2000=0,02s=20ms - okres sygnału
{
PORTC ^= 64; //zmiana stanu na porcie c
if(PORTC & 64)
licznik2 = 1930-(a1-140)-(a2-140);//ustawienie szerokości impulsu z potencjometru 1 i 2
if(!(PORTC & 64))
licznik2 = 200;//ustawinie okresu
}
if(licznik3 > 2000) //sprawdzamy, czy nie minęło już 2000 przepełnień, czyli 0,00001s*2000=0,02s=20ms - okres sygnału
{
PORTC ^= 32; //zmiana stanu na porcie c
if(PORTC & 32)
licznik3 = 1930-(a1-140)-(a2-140)-(a3-140);//ustawienie szerokości impulsu z potencjometru 1, 2 i 3
if(!(PORTC & 32))
licznik3 = 200;//ustawinie okresu
}
}
int main(void)
{
init_ADC();
init_PWM();
DDRC = 224; //konfiguracja portu jako wyjścia
DDRB=255;// PORTY B ustawione jako wyjscia
DDRD=255;//PORTY D ustawione jako wyjscia
DDRA=0;
TCCR0 |= (1<<CS00); //bez preskalera
TIMSK = 0b00000001; //włączenie przerwania od przepełnienia licznika
TCNT0 = 176; //początkowa wartość timera 0, daje nam przerwanie co 0,00001s
sei(); //globalne włączenie przerwań
while(1) //sczytywanie ADC
{
ADC_0();
a1=read_ADC();
ADC_1();
a2=read_ADC();
ADC_2();
a3=read_ADC();
PWM(a1);
}
}
Zaloguj się, aby zobaczyć kod
Dodano po 4 [minuty]:
Cały program z komentarzami
Dzięki wielkie za kalkulator, nie muszę już na piechotę liczyć
Dodano po 8 [minuty]:
Jeszcze zapomniałem zmienić w tym miejscu
TCCR1B = 0b00011010; // ustawienia preskalera na 8
Mam jeszcze jedno pytanie, dlaczego jak mnoże dany odczyt z ADC to zakres serwa sie nie zwiększa tylko serwo nie wie co ma robić i zachowuje sie nie przewidywalnie, podaje fragment kodu:
Dodano po 1 [minuty]:
Zaloguj się, aby zobaczyć kod
if(licznik1 > 2000) //sprawdzamy, czy nie minęło już 2000 przepełnień, czyli 0,00001s*2000=0,02s=20ms - okres sygnału
{
PORTC ^= 128; //zmiana stanu na porcie c
if(PORTC & 128)
licznik1 = 1930-(a1-140)*15/10;//serwo zaczyna świrować
if(!(PORTC & 128))
licznik1 = 200;//ustawinie okresu
}
Zaloguj się, aby zobaczyć kod