Problem z programem do silnika krokowego

To forum jest dla wszystkich pasjonatów mikrokontrolerów AVR Atmela. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
ODPOWIEDZ
Awatar użytkownika
vcd_a
-
Posty: 17
Rejestracja: 11 sie 2006, 21:23
Lokalizacja: Olsztyn
Kontakt:

Problem z programem do silnika krokowego

Post autor: vcd_a » 13 sie 2006, 22:43

Witam, właśnie z pomocą Marcinq, napisałem taki oto program (znaczy się ten program więc więcej jego niż mój, ale mniejsza z tym ;])

Kod: Zaznacz cały

Config Porta = &B11111111
Porta = &B00000000

Config Portb = &B11111111
Portb = &B11110110

Config Portd = &B11000000
Portd = &B11000000

Dim A1 As Byte
Dim A2 As Byte
Dim B1 As Byte
Dim B2 As Byte

A1 = 0
A2 = 0

Do
   If Pind.0 = 1 Then
   Portb.0 = 1
   If A1 < 4 Then
   B1 = Lookup(a1 , Tablica1)
   B1 = B1 And &B00001111
   Porta = B1
   A1 = A1 + 1
   Waitms 10
   Else
   A1 = 0
   End If
   Else
   Portb.0 = 0
   Porta.0 = 0
   Porta.1 = 0
   Porta.2 = 0
   Porta.3 = 0
   End If

   If Pind.1 = 1 Then
   Portb.3 = 1
   If A2 < 4 Then
   B2 = Lookup(a2 , Tablica1)
   Swap B2
   B2 = B2 And &B00001111
   Porta = B2
   A2 = A2 + 1
   Else
   A2 = 0
   Waitms 10
   End If
   Else
   Portb.3 = 0
   Porta.4 = 0
   Porta.5 = 0
   Porta.6 = 0
   Porta.7 = 0
   End If


  Loop
End

Tablica1:
Data 1010 , 0110 , 0101 , 1001
I problem polega na tym, że instrukcja:

Kod: Zaznacz cały

If Pind.1 = 1 Then
   Portb.3 = 1
   If A2 < 4 Then
   B2 = Lookup(a2 , Tablica1)
   Swap B2
   B2 = B2 And &B00001111
   Porta = B2
   A2 = A2 + 1
   Else
   A2 = 0
   Waitms 10
   End If
   Else
   Portb.3 = 0
   Porta.4 = 0
   Porta.5 = 0
   Porta.6 = 0
   Porta.7 = 0
   End If
Wogóle nie jest realizowana, nie wiem dlaczego tak się dzieje, wydaję mi się, że gdzieś musi być jakiś błąd. Bo w tej instrukcji chodzi o to, żeby pobrała dane z tablicy, zamieniła w bajcie bity najmłodsze z najstarszymi, "obcięła" pól bitu (to znaczy, żeby część bitu dla 1 silnika była wszędzie 0) i wysłała do portu. Niestety męczę się już z tym błędem pare godzin i nie wiem w czym tkwi problem, pozdrawiam Krzysiek

ZbeeGin

Post autor: ZbeeGin » 14 sie 2006, 8:54

Jakiego używasz procesora? Co i do jakich portów jest podłączone? Bez tych informacji to będziemy szukać igły w stogu siana. No, ale spróbuję bez tego... :wink:

Na końcówkach PD.1 i PD.0 zwykle "siedzi" UART. Dla bezpieczeństwa możesz dopisać przed Do instrukcje:

Kod: Zaznacz cały

Reset UCR.3
Reset UCR.4


Czy przypadkiem tutaj nie pomyliłeś się nieco:

Kod: Zaznacz cały

Config Portd = &B11000000 
Portd = &B11000000
Bity 7 i 6 są wyjściami, domyślnie w stanie wysokim; bity 5-0 są wejściami, bez wewnętrznego podciągania (pull-up high). Takie miałeś założenia?


Drugi Moim zdaniem błąd. Tablica poisada elementy Integer pomieszane z Byte - tak to kompilator potraktuje. Zatem prawidłowa postać to:

Kod: Zaznacz cały

Tablica1: 
  Data &B1010 , &B0110 , &B0101 , &B1001

Trzeci myślę, że błąd - podpierając się przypuszczeniem, iż każdy silnik ma swoją własną połówkę w PortA. Najpierw zamieniasz połówki bajtu, a potem użyteczną wartość sobie zerujesz. Ponadto Swap z założenia ma trochę inne działanie i dziwię się, że kompilator to "przełknął". Bezpieczniej użyć Rotate lub nawet Shift. Ten fragment mógłby wyglądać tak:

Kod: Zaznacz cały

   B2 = Lookup(a2 , Tablica1) 
   B2 = B2 And &B00001111 
   Rotate B2 , Left , 4
   Porta = B2 

A tak przy okazji - wcięcia please:

Kod: Zaznacz cały

  If Pind.1 = 1 Then 
    Portb.3 = 1 
    If A2 < 4 Then 
      B2 = Lookup(a2 , Tablica1) 
      B2 = B2 And &B00001111 
      Rotate B2 , Left , 4
      Porta = B2 
      A2 = A2 + 1 
    Else 
      A2 = 0 
      Waitms 10 
    End If 
  Else 
  ....
Ostatnio zmieniony 15 sie 2006, 9:53 przez ZbeeGin, łącznie zmieniany 2 razy.

Awatar użytkownika
marcing
Użytkownik
Posty: 868
Rejestracja: 14 lut 2006, 14:13
Lokalizacja: z pociągu...
Kontakt:

Post autor: marcing » 14 sie 2006, 10:53

ZbeeGin - dzięki ;) Wygląda na to, że moje okulary sa za słabe...

Kolega vcd_a próbuje zrzucić całą "winę" na mnie ;) Kod w większości pisał sam, ale parę rzeczy starałem się podpowiedzieć...

Ciężko pomóc korzystając z GG - mało to czytelne wychodzi...
Co do SWAP - "pomylnęło" mi się z asm

Co do kodu, proponowałem coś takiego

Kod: Zaznacz cały

  B = 0
  B = B2
  Swap B
  B = B Or B1
  Porta = B
A w programie wyżej widzę inną konstrukcję...

ZbeeGin

Post autor: ZbeeGin » 14 sie 2006, 11:40

Marcing, instrukcja Swap potrzebuje 2 parametrów:

Kod: Zaznacz cały

B1 = &HAA
B2 = &H55
Swap B1, B2
Print B1; "-"; B2
Wynik będzie: 85-170

Awatar użytkownika
vcd_a
-
Posty: 17
Rejestracja: 11 sie 2006, 21:23
Lokalizacja: Olsztyn
Kontakt:

Post autor: vcd_a » 14 sie 2006, 23:22

Witam, właśnie z Marcinq i ZbeeGin dopradowaliśmy trochę kod teraz wygląda tak:

Kod: Zaznacz cały

$regfile "m8535.dat"
$crystal = 1000000

Config Porta = &B11111111
Porta = &B00000000

Config Portb = &B11111111
Portb = &B11110110

Config Portd = &B11000000
Portd = &B11000000

Dim A1 As Byte
Dim A2 As Byte
Dim B1 As Byte
Dim B2 As Byte
Dim B As Byte
A1 = 0
A2 = 0

Do

   If Pind.0 = 1 Then
   Portb.0 = 1
   If A1 < 4 Then
   B1 = Lookup(a1 , Tablica1)
   B1 = B1 And &B00001111
   Porta = B1
   A1 = A1 + 1
   Waitms 10
   Else
   A1 = 0
   End If
   Else
   Portb.0 = 0
   Porta.0 = 0
   Porta.1 = 0
   Porta.2 = 0
   Porta.3 = 0
   End If

   If Pind.1 = 1 Then
   Portb.3 = 1
   If A2 < 4 Then
   B2 = Lookup(a2 , Tablica2)
   A2 = A2 + 1
   Porta = B2
   Waitms 10
   Else
   A2 = 0
   End If
   Else
   Portb.3 = 0
   Porta.4 = 0
   Porta.5 = 0
   Porta.6 = 0
   Porta.7 = 0
   End If

  Loop
End

Tablica1:
Data &B1010 , &B0110 , &B0101 , &B1001

Tablica2:
  Data &B10100000 , &B01100000 , &B01010000 , &B10010000
Program już działa, ale czy na pewno?, ponieważ silnik 2 drga a nie kręci się, a stany w na tranzystorach sterownika zmieniają się prawidłowo, podejżewam, że mógł się spalić jeden z tranzystorów, ponieważ przez przypadek podłączyłem piny silnika odwrotnie (razem z napięciem), ale nie wiem będe musiał sprawdzić te tranzystory (Tip122), pozdrawiam Krzysiek

Jeżeli ktoś zauważy jakiś błąd niech piszę, pozdrawiam!

P.S. Wyjeżdżam teraz będę dopiero 23 sierpnia, ale jak tylko dorwę kompa to zobaczę jak się rozwija topic, pozdrawiam !

I jeszcze jedno czy w Bascomie jest jakaś opcja która robi wcięcia w kodzie? np. przy kolejnych if'ach albo coś takiego?

ZbeeGin

Post autor: ZbeeGin » 15 sie 2006, 8:09

vcd_a pisze:I jeszcze jedno czy w Bascomie jest jakaś opcja która robi wcięcia w kodzie? np. przy kolejnych if'ach albo coś takiego?
Pisząc program SAM musisz o to zadbać!

A propos wczorajszej dyskusji, to pierwotna wersja - z naniesionymi poprawkami - działa, sprawdziłem w symulatorze. Usunąłem instrukcje maskowania, bo okazują się zbędne, a wiadomo każdy bajt i czas wykonywania operacji w BASCOMie są cenne...

Kod: Zaznacz cały

'VCD_A - wersja pierwsza (poprawiona)
'
'sterownik silnikow krokowych
'

$regfile "m8535.dat"
$crystal = 1000000

Config Porta = &B11111111
Porta = &B00000000

Config Portb = &B11111111
Portb = &B11110110

Config Portd = &B11000000
Portd = &B11000000

Dim A1 As Byte
Dim A2 As Byte
Dim B1 As Byte
Dim B2 As Byte

A1 = 0
A2 = 0

Do

'1wszy silnik
  If Pind.0 = 1 Then
    Portb.0 = 1
    If A1 < 4 Then
      B1 = Lookup(a1 , Tablica1)
      Porta = B1
      Incr A1
      Waitms 10
    Else
      A1 = 0
    End If
  Else
    Portb.0 = 0
    Porta.0 = 0
    Porta.1 = 0
    Porta.2 = 0
    Porta.3 = 0
  End If

'2gi silnik
  If Pind.1 = 1 Then
    Portb.3 = 1
    If A2 < 4 Then
      B2 = Lookup(a2 , Tablica1)
      Rotate B2 , Left , 4
      Porta = B2
      Incr A2
      Waitms 10
    Else
      A2 = 0
    End If
  Else
    Portb.3 = 0
    Porta.4 = 0
    Porta.5 = 0
    Porta.6 = 0
    Porta.7 = 0
  End If
Loop

End

Tablica1:
  Data &B1010 , &B0110 , &B0101 , &B1001
Można by dokonać jeszce paru optymalizacji, ale obecnie chcę zachować pierwotny styl programu. Np. zauważ, że przy niespełnionych warunkach A2 < 4 lub A1 < 4, są "puste" przejścia pętli Do...Loop i zmiana położenia wału silników nie występuje! Zatem obroty tracą płynność w tym miejscu.

Awatar użytkownika
vcd_a
-
Posty: 17
Rejestracja: 11 sie 2006, 21:23
Lokalizacja: Olsztyn
Kontakt:

Post autor: vcd_a » 23 sie 2006, 14:47

Witam, właśnie wróciłem z wakacji i okazuje się coś tak dziwnego, że ja tego nigdy nie zrozumiem, program, który podałem w swoim poprzednim poście, przestał teraz działać... ;/
Silnik nie kręci się tylko robi raz krok w jedna strone, raz w drugą..., nie wiecie o co może chodzić ?, co się mogło zepsuć?, pozdrawiam Krzysiek


P.S.
@ZbeeGin
Jak możesz to odezwij się do mnie proszę, pozd

Daymian
-
Posty: 82
Rejestracja: 25 lip 2006, 21:23
Lokalizacja: Bochnia
Kontakt:

Post autor: Daymian » 23 sie 2006, 21:04

Nic takiego sie nie stało..poprostu pewnie zmieniłeś kolejność wyprowadzeń cewek silnika :mrgreen: Przynajmniej u mnie tak sie działo jak zmieniłem kolejność. :???:

ZbeeGin

Post autor: ZbeeGin » 23 sie 2006, 22:08

W kwestii wspomnianych optymalizacji:

Kod: Zaznacz cały

'VCD_A - wersja pierwsza (poprawiona)
'
'sterownik silnikow krokowych
'
$regfile "m8535.dat"
$crystal = 1000000

Config Porta = &B11111111                         'tutaj podlaczymy uzwojenia
Porta = &B00000000

Config Portb = &B11111111                         'tutaj sterujemy zasilaniem uzwojen
Portb = &B11110110

Config Portd = &B11000000                         'tu bedzie joystick
Portd = &B11000000

Dim A1 As Byte
Dim A2 As Byte
Dim B1 As Byte
Dim B2 As Byte

A1 = 0                                            'zeruj stany
A2 = 0

Do

'1wszy silnik
  If Pind.0 = 1 Then                              'sterowac 1 silnikiem?
    Set Portb.0                                   'tak, wlacz zasilanie
    B1 = Lookup(a1 , Tablica1)                    ' odczytaj bieżącą sekwencję
    Porta = B1                                    ' zasteruj uzwojeniami
    Incr A1                                       ' przesun wskaznik na nast. sekwencje
    If A1 > 3 Then A1 = 0                         ' ale nie za daleko...
    Waitms 10                                     ' niech wal się obróci i ustabilizuje
  Else
    Reset Portb.0                                 'nie, wylacz zasilanie
    Porta = Porta And &B11110000                  ' wylacz uzwojenia
  End If

'2gi silnik
  If Pind.1 = 1 Then                              'sterowac 2 silnikiem?
    Set Portb.3                                   ' tak, wlacz zasilanie
    B2 = Lookup(a2 , Tablica1)                    ' odczytaj bieżącą sekwencję
    Rotate B2 , Left , 4                          ' ustaw na odpowienim miejscu w porcie
    Porta = B2                                    ' zasteruj uzwojeniami
    Incr A2                                       ' przesun wskaznik na nast. sekwencje
    If A2 > 3 Then A2 = 0                         ' ale nie za daleko...
    Waitms 10                                     ' niech wal się obróci i ustabilizuje
  Else
    Reset Portb.3                                 'nie, wylacz zasilanie
    Porta = Porta And &B00001111                  ' wylacz uzwojenia
  End If
Loop

End

Tablica1:
  Data &B1010 , &B0110 , &B0101 , &B1001          'sekwencja sterująca - normalne kroki
vcd_a pisze:nie wiecie o co może chodzić ?, co się mogło zepsuć?
Wydaje Mi się, że to Ty jesteś projektantem układu... :???:

Awatar użytkownika
vcd_a
-
Posty: 17
Rejestracja: 11 sie 2006, 21:23
Lokalizacja: Olsztyn
Kontakt:

Post autor: vcd_a » 26 sie 2006, 2:00

Witam, sterowniki w końcu naprawiłem, trochę mi z tym zeszło czasu, aż 2 dni, dzięki wielkie ZbeeGin za poprawiony kod, najpierw muszę go teraz przestudiować, a potem wrzuce do uC. Narazie napisałem taki kod (przerobiłem ten co już był, aby silniki mogły się obracać w obydwie strony), programik działa i jest ok. Zastanawiam się tylko jeszcze jak wyciągnąć z silników więcej mocy, bo boję się, że teraz mają jej zbyt mało, pozd

Pokazuje kod, który teraz napisałem:

Kod: Zaznacz cały

'VCD_A - wersja pierwsza (poprawiona)
'
'Sterownik Suwnicy na ATmega 8535
'

$regfile "m8535.dat"
$crystal = 1000000

Config Porta = &B11111111
Porta = &B00000000

Config Portb = &B11111111
Portb = &B11110110

Config Portd = &B11000000
Portd = &B11000000

Dim A1 As Byte
Dim A2 As Byte
Dim A3 As Byte
Dim A4 As Byte
Dim B1 As Byte
Dim B2 As Byte
Dim B3 As Byte
Dim B4 As Byte

A1 = 0
A2 = 0
A3 = 0
A4 = 0

Do

'1wszy silnik
'góra
  If Pind.0 = 1 Then
    Portb.0 = 1
    If A1 < 4 Then
      B1 = Lookup(a1 , Tablica1)
      Porta = B1
      Incr A1
      Waitms 10
    Else
      A1 = 0
    End If
  Else
    Portb.0 = 0
    Porta.0 = 0
    Porta.1 = 0
    Porta.2 = 0
    Porta.3 = 0
  End If

'dół
 If Pind.1 = 1 Then
    Portb.0 = 1
    If A2 < 4 Then
      B2 = Lookup(a2 , Tablica2)
      Porta = B2
      Incr A2
      Waitms 10
    Else
      A2 = 0
    End If
  Else
    Portb.0 = 0
    Porta.0 = 0
    Porta.1 = 0
    Porta.2 = 0
    Porta.3 = 0
  End If



'2gi silnik
'lewo
  If Pind.2 = 1 Then
    Portb.3 = 1
    If A3 < 4 Then
      B3 = Lookup(a3 , Tablica1)
      Rotate B3 , Left , 4
      Porta = B3
      Incr A3
      Waitms 10
    Else
      A3 = 0
    End If
  Else
    Portb.3 = 0
    Porta.4 = 0
    Porta.5 = 0
    Porta.6 = 0
    Porta.7 = 0
  End If

'prawo
 If Pind.3 = 1 Then
    Portb.3 = 1
    If A4 < 4 Then
      B4 = Lookup(a4 , Tablica2)
      Rotate B4 , Left , 4
      Porta = B4
      Incr A4
      Waitms 10
    Else
      A4 = 0
    End If
  Else
    Portb.3 = 0
    Porta.4 = 0
    Porta.5 = 0
    Porta.6 = 0
    Porta.7 = 0
  End If

Loop

End

Tablica1:
  Data &B1010 , &B0110 , &B0101 , &B1001

Tablica2:
  Data &B1001 , &B0101 , &B0110 , &B1010
P.S. @ZbeeGin
Dzięki wielkie jeszcze raz za kod, właśnie go "przestudiowałem" i jutro przerobie swój stary program i wrzuce ten, pozd

[ Dodano: 2006-08-26, 19:02 ]
Witam, właśnie przerobiłem kod, ale mam jeszcze pytanko czy w Bascomie występuje zmienna BOOLEAN?, czyli True/False ?, bo właśnie będe dołączał do sterownika krańcówki i ta komenda mi będzie potrzebna, pozd Krzysiek

yakuza
-
Posty: 38
Rejestracja: 10 sty 2006, 12:59
Kontakt:

Post autor: yakuza » 26 sie 2006, 20:19

Nie, ale mozna skorzystac ze zmiennej typu Bit.

Pozdrawiam Yakuza

Awatar użytkownika
vcd_a
-
Posty: 17
Rejestracja: 11 sie 2006, 21:23
Lokalizacja: Olsztyn
Kontakt:

Post autor: vcd_a » 26 sie 2006, 21:30

A możesz mi podać jakiś przykład zastosowania tej zmiennej?, bo nie moge znaleźć w helpie, pozd

ZbeeGin

Post autor: ZbeeGin » 27 sie 2006, 6:56

Kod: Zaznacz cały

$crystal = 8000000
$baud = 19200

Config Portb = Input
Config Timer0 = Timer, Prescale = 8

Dim Flaga As Bit
Dim Stan As Byte

Flaga = 0

On Timer0 Timer0_Isr
Enable Timer0
Enable Interrupts
Start Timer0

Do
  If Flaga = 1 Then
    Reset Flaga
    Stan = Portb
    Shift Stan , Right , 1
    Print Hex(stan)
  End If
Loop

Timer0_Isr:
  Set Flaga
Return
Program wykorzystuje przerwania licznika TIMER0 do generowania cyklicznych odczytów stanu portu B i wysyłania jego zmodyfikowanego stanu na terminal znakowy. Stan portu jest pokazywany w postaci szesnastkowej. Ponieważ nie powinno się używać zaawansowanych poleceń w procedurze obsługi przerwania (Timer0_Isr) ustawia ona tylko flagę by pętla główna dokonała właściwego odcztu i przesłania danych.

Jest to tylko przykład, który do niczego konkretnego nie służy, poza zobrazowaniem do czego wykorzystać można zmienne typu Bit.

ODPOWIEDZ