Witam
Zbiornik wyremontowany i uruchomiony. Pozostało jeszcze zliczanie
impulsów na kole. Dziś się tym zajmę.
A wczoraj ... :
Tym razem trochę o sterowaniu serwami modelarskimi (analogowymi).
Sterowanie odbywa się za pomocą PWM (Pulse Width Modulation).
Tłumacząc to na ludzki : zmienna szerokość impulsu.
Okres wynosi 20 milisekund (20 * 1/1000) czyli 50Hz. Standardowo serwo wychyla się około 90
stopni gdy długość impulsu napięcia zmienia się od 1 do 2 milisekund.
Mikrokontroler ATmega32 ma fantastyczne możliwości generowania takich przebiegów.
Tą razą jednak, okazało się, że przy kwarcu 16Mhz nie można dobrać żadnych danych tak,
aby timer2 generował przebieg nadający się do sterowania serwem ciągającym
stery głębokości na kiosku. Ciągle wychodziło 61 Hz. Po różnych rozpaczliwych próbach polegających
między innymi na dzieleniu liczby 16 000 000 przez 256 lub 510, postanowiłem
zrealizować to, czego się nie da automatycznie, za pomocą programu.
I tak, założyłem, że stery na kiosku będą rozróżniać po 6 położeń w każdym kierunku.
45stopni/6 = 7,5 stopna. Przy przełożeniu mniejszym od 1 wyjdzie cóś ze trzy stopnie.
Na razie wydaje się to wystarczające. W końcu i tak tego widać nie będzie, bo stery na kiosku
będą się ruszać wyłącznie w stanie zanurzony. Musiałem użyć Timera2, bo wszystko inne jest
już zajęte.
Umyśliłem generowanie przerwań od timera co 0,1 ms. Gdy się okaże, że stanowią zbyt duże obciążenie dla procesora, to w okresie od 0 do 2ms będą generowane co 0,1ms a od 2ms do 20ms co 1ms albo jeszcze rzadziej.
Serwo zachowuje się ok. A teraz stosowny kawałek programu :
Inicjalizacja timerów i dopuszczenie przerwań od nich :
[code:1]
// Inicjalizacja Timera2 do generowania PWM
// przerwania co 0,1ms preskaler 64
TCCR2 = 0b00000100;
TCNT2 = 256 - 25;
TIMSK |= _BV( TOIE0 ) | _BV( TOIE1 ) | _BV( TOIE2 );
[/code:1]
Funkcja obsługująca przerwania od timera2 :
[code:1]
unsigned char intT2period = 0; //liczy do 200
volatile unsigned char intT2Pulselength = 15;
volatile unsigned char inT2Counter = 0;
SIGNAL(SIG_OVERFLOW2)
{
// TCNT2 musi być przeladowywany
// Timer tyka zgodnie z zaprogramowanymi wartosciami
// Przy kazdym tyknieciu zwieksza TCNT2.
// Przy osiagnieciu 0xFF generowane jest to przerwanie
TCNT2 = 256 - 25;
if ( ++intT2period <= 23 )
{
if ( ++inT2Counter <= intT2Pulselength )
{
PORTD |= _BV( Servo_SterK );
}
else
{
PORTD &= ~_BV( Servo_SterK );
}
}
else if ( intT2period > 199 )
{
intT2period = 0;
inT2Counter = 0;
}
}
[/code:1]
Funkcja ta odpowiedzialna jest za generowanie owego krótkiego impulsu
o regulowanej długości od 0,9 ms do 2,1 ms.
I wreszcie funkcja zmieniająca położenie serwa :
[code:1]
// Ustawia dlugosc wystawianego impulsu na 9 do 21
// Uzywane do sterowania sterow poziomych
void SetPulseIntT2Length( unsigned char length )
{
if ( ( length > 8 ) && ( length < 22 ) )
{
intT2Pulselength = length;
}
}
[/code:1]
Na razie nie dostosowane do faktycznego wychylenia sterów, ale to już drobiazg.
Pozostał timer1, który ma dawać dwa przebiegi PWM : do sterowania silnikiem głównym i
sterami głębokości na rufie.
Z ukłonami
Andrzej Korycki