Skocz do zawartości

Sterowanie SERWEM przez TIMER w BASCOMIE


Tomy89

Pomocna odpowiedź

Witam,
przeglądałem Wasze forum oraz inne, całe google.pl i nie mogłem znaleźć dokładnej odpowiedzi na moje pytanie...

Chciałbym sterować położeniem serwa w BASCOMIE poprzez TIMER, a nie przez polecenie "Config Servos = 1".Chodzi tylko o jeden serwomechanizm. Zależy mi na tym, ponieważ korzystając z wyżej wymienionej opcji, serwo nie było stabilne i nie mogło się ustawić w jednej konkretnej pozycji...Jeżeli ktoś wie jak to zrobić to proszę o kawałek kodu, który to mi przybliży.... Korzystam z Atmegi32-8PU ustawionej na standardowe 1MHz.

Dodam, że chodzi mi o sterowanie czasem impulsu w standardowych serwach, tak jak na tej stronie:

http://www.henryk.mbapp.com/servo/servo.html

Bardzo proszę o pomoc, mimo, że pewnie jest to trywialne zadanie...

Link do komentarza
Share on other sites

Polecenie Config Servos = 1 nie steruje serwem

serwem steruje polecenie serwo(.. ) = ...

Ustaw oscylator na 8Mhz i zacznie ci ono działać prawidłowo

Jeżeli chcesz na przerwanie timera to tez oczywiście można to bez problemu zrobić.

Link do komentarza
Share on other sites

Jeżeli chcesz na przerwanie timera to tez oczywiście można to bez problemu zrobić.

Tak, dokładnie chciałbym to zrobić korzystając z timera...tyle tylko, że nie wiem jak to zrealizować w algorytmie.

Link do komentarza
Share on other sites

Oto program , który sam napisałem (dla warcu 16mhz i attiny2313) w Bascomie:

Dim Pomoc As Bit

Dim usatwaienie As Word

Config Portb = 256

Portb = 0

Config Portd = &B1111111

Portd = &B0000000

Config Timer1 = Timer , Prescale = 8

Enable Interrupts

Enable Timer1

ustawienie = 1000

Pomoc = 0

On Timer1 podprogram

Stop Timer1

Timer1 = 63536 - ustawienie

Do

Portb.7 = 1

Start Timer1

Timer1 = 63536 - ustawienie

If Pomoc = 1 Then

Pomoc = 0

Stop Timer1

waitms 25

End If

Loop

End

Podprogram:

Timer1 = 63536 - ustawienie

Pomoc = 1

Return

W zmienną ustawienie wpisujesz liczbę w zakresie od 0 do 2000

A tak nawiasem to funkcja config servos też Ci będzie pewnie działać tylko musisz dać większy kwarc.

Zgodnie z twoim artykułem ,który podałeś w linku to należałoby usatawić waitms 20 , ale ja myślę ,że z waitms 25 będzie lepiej (większy margines błędu).

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Proszę jedno z możliwych rozwiązań. Da się nawet 5 serwami za jego pomocą sterować. Ale wykorzystuje 2 Timery.


'*****************************************************************************
'*                HTSC -HyperThreading Servomotor Controler                  *
'* CPU - ATMEGA 168                                                          *
'* FCPU - 1MHz internal RC                                                   *
'*****************************************************************************
$sim
$regfile = "m168def.dat"
$crystal = 1000000
Config Portc.0 = Output
Config Portc.1 = Output
Config Portc.2 = Input
Config Portc.3 = Input
Config Portc.4 = Input
Config Portc.5 = Input
Config Portb.0 = Output

Config Portd.3 = Output
Config Portd.4 = Output
Config Portd.5 = Output
Config Portd.6 = Output
Config Portd.7 = Output
Config Timer0 = Timer , Prescale = 64
Stop Timer0
Config Timer1 = Timer , Prescale = 1       'bo cykl uC trwa dokładnie 1us
Stop Timer1
Enable Interrupts
Enable Timer0
Enable Timer1
'declare
On Timer0 Sterowanie
On Timer1 Off_serwo
'const , dim
Dim S_time(5) As Word
Dim Pomocnicza As Word
Dim Wsk_serwa As Byte
Dim I As Byte
Dim S As Bit
Const 2_5ms = 40             '2560us
Const 1_5ms = 23             '1472us
'razem daje to pełen cykl dla 5 serw co 20160us (20,16ms)
Const Neutral = 1500


Portd = &H0
'Inicjacja pozycji wyjściowej serw.
For I = 1 To 5
   S_time(i) = Neutral
Next
Wsk_serwa = 1
Reset S                      ' status na zero, czyli najpierw odczyt klawiatury
Load Timer0 , 1_5ms          ' ładujemy pierwszy między czas
Enable Timer0                ' odblokowujemy przerwania od T0
Start Timer0                 ' startujemy timer 0
Do
  ' i spokojnie czekamy na przerwania
Loop
End

Sterowanie:
   Stop Timer0
   If S = 0 Then
      Load Timer0 , 1_5ms
      Start Timer0
      'obsługa klawiatury, mamy na to 1,5ms czyli 1472 cykle zegara
      'zanim nadejdzie kolejne przerwanie od T0
      Set S
   Else
      Load Timer0 , 2_5ms
      Start Timer0
      Pomocnicza = S_time(wsk_serwa)
      Load Timer1 , Pomocnicza
      Select Case Wsk_serwa
      Case 1 : Set Portd.3
      Case 2 : Set Portd.4
      Case 3 : Set Portd.5
      Case 4 : Set Portd.6
      Case 5 : Set Portd.7
      End Select
      Start Timer1
      'generowanie czasu dla serwa
      Reset S
   End If
Return

Off_serwo:
   Stop Timer1
   Select Case Wsk_serwa
   Case 1 : Reset Portd.3
   Case 2 : Reset Portd.4
   Case 3 : Reset Portd.5
   Case 4 : Reset Portd.6
   Case 5 : Reset Portd.7
   End Select
   Incr Wsk_serwa
   If Wsk_serwa > 5 Then
      Wsk_serwa = 1
   End If
Return

A TUTAJ kolega ma cały temat poświęcony tej problematyce, w tym rozwiązanie mojego kolegi na tylko 1 Timerze.

  • Lubię! 1
Link do komentarza
Share on other sites

Niestety sytuacja zmusiła mnie do porzucenia na dłuższy czas problemu serwa i timera. Ostatnio zagłębiłem się jednak w ten problem i napisałem program który prawie działa. Serwo pracuje tylko w jednej pozycji i mimo zmiany wartości długości stanu wysokiego, nie zmienia swojego położenia. Bardzo bym prosił o wskazanie błędu w programie, jeżeli taki występuje... 😳

$regfile = "m32def.dat"
$crystal = 8000000



Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portb.2 , Db5 = Portb.3 , Db6 = Portb.4 , Db7 = Portb.5 , E = Portb.1 , Rs = Portb.0
Cls



Dim A As Byte
Dim Licz As Byte
Dim Stan As Byte
Licz = 0
Stan = 1
A = 250


Config Portd = Output
Config Portc = Input





S1 Alias Pinc.0
Set Portc.0

S2 Alias Pinc.1
Set Portc.1






Set Portd.1
Config Timer0 = Timer , Prescale = 64

On Timer0 Servo

Enable Interrupts
Enable Timer0




Do

Debounce S1 , 0 , Up_serwo , Sub
Debounce S2 , 0 , Down_serwo , Sub

Locate 2 , 1 : Lcd A

Loop
End

Up_serwo:

  A = A + 1

Return


Down_serwo:

  A = A - 1

Return





Servo:
 If Stan = 1 Then

     Load Timer0 = A
     Reset Portd.1
     Stan = 0
     Licz = 0

 Else

     Load Timer0 = 250
     Incr Licz

     If Licz = 10 Then

        Set Portd.1
        Stan = 1

     End If


 End If


Return
Link do komentarza
Share on other sites

Ten artykuł czytałem wiele razy już i na jego podstawie napisałem powyższy program.

Chodzi mi o to, że nie ma w nim funkcji zmiany wychylenia serwa i nie potrafię tego zrobić. Jak zmienić czas z 1,5ms na np 1,8ms ? Nawet na przykładzie swojego programu, gdybyś mi pokazał, poradziłbym sobie dalej 🙂

Jest to w ogóle możliwe? U siebie sterujesz 5 serwami - po odpaleniu programu serwa trzymają się jednej pozycji. Teraz jak zmienić tą pozycję?

Link do komentarza
Share on other sites

To bardzo proste, aczkolwiek trzeba uwzględniać jakim zegarem jest taktowane CPU. Ja robiłem eksperymenty na 1MHZ, wiec podstawą czasu u mnie była 1 us.

A ponieważ do sterowania trzeba odliczać czasy w granicy od ok. 1ms do ok 2ms, to wychodzi nam że musimy zliczać od 1000us do 2000us. Teraz używamy Timera 0, on potrafi liczyć tylko do 255 bo jest 8-bitowy, dla tego aby móc zliczać do 2000us. Trzeba to jakoś obejść więc użyłem preskalera = 8, aby zamiast 1us mieć 8us. Teraz aby obliczyć potrzebną wartość do wygenerowania odpowiedniego impulsu, trzeba podzielić potrzebny czas np. 1,6ms czyli 1600us / 8 = 200 i tą wartość wstawić do timera. Ponieważ ja mam 5 serw to stworzyłem tablice =>

Dim Serva(5) As Byte

Potrzebne ustawienia wpisuje się po prostu do tej tablicy, dla serwa nr1, na pozycję nr 1 w tablicy.

Link do komentarza
Share on other sites

Czyli jeżeli (dla ułatwienia) używam tego samego zegara, prescalera jak u Ciebie w programie, to wystarczy że zamienię pętlę:

For Wsk_serva = 1 To 5
  Serva(wsk_serva) = Wsk_serva * 4
  Serva(wsk_serva) = Serva(wsk_serva) + 123
Next Wsk_serva

na swoje ręcznie wpisane wartości (na przykład takie same jakby były w pętli):

Serva(1) = 127
Serva(2) = 131
Serva(3) = 135
Serva(4) = 139
Serva(5) = 143

i zmienię na przykład wartość pierwszego? Chyba będę musiał to jeszcze umieścić w pętli Do...Loop.

Jestem teraz w pracy i nie mogę tego sprawdzić, ale jak będę w domu, to na pewno się za to wezmę...

Link do komentarza
Share on other sites

Tak wystarczy do tej tabeli podstawiać wartości z zakresu od 125 (1ms) do 250 (2ms). Przy czym jak masz ATMege 32 to możesz skorzystać spokojnie sobie z trybu CTC Timera0, co uprości program i polepszy trochę stabilność generowanych impulsów. Ostatecznie jak masz tylko 1 serwo to można T0 skonfigurować w tryb PWM, ale trzeba tak dobrać zegar i ustawienia, aby mieć częstotliwość 50Hz, a to tam chyba wymaga nietypowego kwarcu podpiętego do CPU. (chyba 3.28MHz ?)

Link do komentarza
Share on other sites

Po wielu próbach i testach...nie udało mi się zmienić położenia serwa. Zmieniłem tylko wartość

Serva(1) = 240

i dalej nic. Próbowałem nawet z innymi portami. Serwo zawsze zachowuje jedną pozycję. Wydobywają się z niego również dziwne dźwięki, co może świadczyć o nie dokładności odmierzanych impulsów. Mam Atmegę32 i jeżeli ułatwiłoby to dużo sprawę chciałbym skorzystać z CTC Timera0, ale nigdzie w necie nie mogę znaleźć tematu dotyczącego serwomechanizmów. Jeżeli jest to takie proste, podaj mi jak możesz te czarodziejskie instrukcje...

Link do komentarza
Share on other sites

Ja jak robiłem próby z serwem, to miałem taki problem że mi zbyt mocno skakało napięcie. Co do tego CTC, w nocie jest, natomiast o serwach tam nic nie ma, do to trzeba by szukać noty aplikacyjnej.

Jak znajdę trochę czasu to spróbuję podrzucić kod pod M32, ale wątpię że zrobię to dzisiaj.

PS. Szczerze zaintrygowały mnie twoje problemy i aż z ciekawości wyciągnąłem mój muzealny polski oscyloskop ST-315A II, i zrobiłem pomiar na mojej płytce stykowej z programem z arta. Jeżeli dobrze pamiętam to co na 2 lekcjach nam o oscyloskopie powiedzieli, bo elektronikiem nie jestem, to wyszło mi coś takiego.

Na tym widać że impuls ma ok 1ms, odstęp jest co prawda tylko 9ms, ale jak pisałem w arcie tak miało być.

Link do komentarza
Share on other sites

Ha! Udało mi się dobrać takie wartości, żeby serwo działało tak jak należy. Pewnie ameryki nie odkryłem, ale doszedłem do tego sam - nie znalazłem tego w internecie. Poniżej zamieszczam kod dla potomności 🙂 Przyciskiem zmieniamy długość impulsu. Dzięki za pomoc BlackJack. Jeżeli miałbyś chwilę, to powiedz mi co to jest w tym moim kodzie:

Set Tccr0.wgm01
Set Tccr0.com01

Config Timer0 = Timer , Prescale = 8 , Clear Timer = 1

Ocr0 = 125

Odpowiada to za CTC? jak to interpretować?

Cały kod:

$regfile = "m32def.dat"

$crystal = 8000000


Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portb.2 , Db5 = Portb.3 , Db6 = Portb.4 , Db7 = Portb.5 , E = Portb.1 , Rs = Portb.0
Cls


Set Tccr0.wgm01
Set Tccr0.com01

Config Timer0 = Timer , Prescale = 8 , Clear Timer = 1

Ocr0 = 125

Config Portd = Output



Dim Licz As Byte
Dim A As Byte
Dim B As Single
Dim Stan As Byte

A = 12

Enable Interrupts
On Oc0 1_8ms
Enable Oc0

'klawiatura
S1 Alias Pinc.0
Set Portc.0


Do

  Debounce S1 , 0 , Dodaj , Sub
  Cls
  B = A \ 8
  Lcd B
  Lcd " ms"

Loop
End


Dodaj:

  Incr A
  If A = 17 Then A = 8

Return



1_8ms:

Incr Licz

  If Licz = 160 Then
     Licz = 0
     Stan = 1
     Set Portd.1
  End If

  If Licz = A And Stan = 1 Then
     Licz = 0
     Stan = 0
     Reset Portd.1
  End If

Return
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.