logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[MEGA8][ASM] - Problem z sterowaniem silnikiem krokowym

paavo91 19 Lis 2013 20:53 1998 15
REKLAMA
  • #1 12970993
    paavo91
    Poziom 19  
    Witam.

    Napisałem prosty kod z pomocą artykułów w z internetu który steruje silnikiem krokowym bipolarnym. Jeden przycisk powoduje obrót w lewo, drugi zaś w prawo.

    Problem polega na tym, że gdy wykonam krok do przodu i następnie po nim krok do tyłu, to silnik robi dodatkowy jeszcze jeden krok do przodu, po czym dopiero rusza do tyłu. Równolegle mam podłączone 4 LEDy na których widzę zmieniającą się sekwencje i na diodach tego problemu nie widać. Również symulator w AVR Studio 4 którego używam do uruchomienia w trybie pracy krokowej nie pokazuje tego problemu.

    Nigdy nie pisałem w ASM, nie przychodzi mi tak łatwo jak np. C/BASCOM.

    Proszę o pomoc , ewentualnie sugestie.

    Kod: text
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • Pomocny post
    #2 12971033
    excray
    Poziom 41  
    Tam na samym końcu zgubiłeś jeszcze jeden skok czy go wcale nie masz? Pod jakie wejścia masz podpięty ten silnik?
  • REKLAMA
  • Pomocny post
    #3 12971093
    BlueDraco
    Specjalista - Mikrokontrolery
    Po co piszesz to w asemblerze? Nie obskakuj skoków bezwarunkowych skokami warunkowymi - odwróć warunek takiego skoku warunkowego.
  • #4 12971119
    paavo91
    Poziom 19  
    Przepraszam, nie skopiowałem całości, już poprawiłem ten skok na końcu.

    Silnik podpięty od PB1 do PB4. Przyciski na PD6 i PD7.

    BlueDraco, takie jest założenie projektu na uczelni. Wcale mi się to nie uśmiecha, ale musiałem chociaż wstęp napisać w ASM, rozbuduję projekt już w innym języku.

    Mógłbyś sprecyzować o co Ci chodzi z tymi skokami?
  • Pomocny post
    #5 12971129
    BlueDraco
    Specjalista - Mikrokontrolery
    O to, że sekwencja:

    brne l1
    rjmp l2
    l1:

    jest równoważna instrukcji breq l2
  • REKLAMA
  • #6 12971156
    paavo91
    Poziom 19  
    Masz rację, to się nazywa brak doświadczenia z mojej strony.

    Kod teraz wygląda tak(mam nadzieję, że o to Ci chodziło):

      
        .include "m8def.inc"
         
         
         
        ;---------------------------------------------------------------------------------------------
        .def    acc     =  r16  ; r16 teraz ma nazwę acc
        .def    acc2    =  r17  ; r17 teraz ma nazwę acc2
        .cseg
        .org $000
         
         
                rjmp reset
         
         
        RESET:
         
               
                ldi r30,low(RAMEND)
                out SPL,r30
                ldi r30,high(RAMEND)
                out SPH,r30
         
         
                cbi DDRD,7      ; pd7 jakowe wejscie
                sbi PORTD,7     ;pullup
                cbi ddrd,6
                sbi portd,6
         
         
                ldi     r18,0xFF
                ldi r19,0x00    ;
                out     DDRB,r18        ; cały port B jako wyjściowy
                out     PORTB,r19
                ldi r24,0b00000010
                out portb,r24   ;wystaw na portB
         
                rjmp sprawdz_przycisk
         
        ;--------------------------------------------------
         
        Delay   :               ; realizacji opóźnienia
                ldi     acc2,0  ; zawartość acc2 = 0
                ldi     acc,0   ; zawartość acc = 0
        Del_0   :               ;
                inc     acc     ; zwiększ zawartość acc
                brne    Del_0   ; skocz gdy acc różne od 0
                inc     acc2    ; zwiększ zawartość acc2
                brne    Del_0
                ret             ; powrót z podprogramu
        ;----------------------------------------------  
         
         
         
               
                               
        Sprawdz_przycisk:        
         
               
    		     	out portb,r24   ;wystaw na portB      
    
                in r23,pind
                andi r23,0b11000000
         
                cpi r23,0b10000000
                breq doPrzodu
         
                cpi r23,0b01000000
                breq doTylu
                ;PWM = 120
         
                rjmp Sprawdz_przycisk
         
         
         
         
         
         
        doPrzodu:
         
    	 	
                rcall delay ; opóźnienie kroków
                ;PWM = 255
                       
                lsl r24 
    			                 
                mov r25,r24             ;kopia rejestru do maski
                andi r25,0b00100000     ;maska
                
    			breq sprawdz_przycisk              ;jesli pinb.5=1 to skocz i od nowa
         
              
         
         
         
         
         
         
        Z5Na1:
         
                ldi r24,0b00000010
         
                rjmp sprawdz_przycisk
         
           
         
        doTylu:
         
         		
                rcall delay ; opóźnienie kroków
                ;PWM = 255
                       
                lsr r24
    			                       
                mov r25,r24             ;kopia rejestru do maski
                andi r25,0b00000001     ;maska
                breq sprawdz_przycisk              ;jesli pinb.5=1 to skocz i od nowa
         
               
         
         
        Z0Na4:
         
                ldi r24,0b00010000
         
                rjmp sprawdz_przycisk
    
    


    Niestety działa tak samo. To chyba niemożliwe, żebym źle coś podpiął skoro kręci się jak należy?
  • Pomocny post
    #7 12971190
    excray
    Poziom 41  
    Poza tym funkcję główną wykonaj inaczej - prościej:
    Kod: text
    Zaloguj się, aby zobaczyć kod
  • Pomocny post
    #8 12971215
    BlueDraco
    Specjalista - Mikrokontrolery
    Pomyliłeś warunki skoków. Powinno być np.:

    lsl r24
    mov r25,r24 ;kopia rejestru do maski
    andi r25,0b00100000 ;maska

    brne sprawdz_przycisk
    ldi r24,0b00000010
    rjmp sprawdz_przycisk

    I analogicznie dla drugiego kierunku
  • #9 12971241
    excray
    Poziom 41  
    Albo nawet:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    co po wkomponowaniu w poprzednio podesłany kod daje całkiem ładny kod:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    Wywal jeszcze tego delaya na sam koniec dzięki czemu usuniesz jeden "rjmp Sprawdz_przycisk"
  • REKLAMA
  • #10 12971377
    paavo91
    Poziom 19  
    Ok, przerobiłem kod na taki:

    (Zamiast SBIS dałem SBIC)

       .include "m8def.inc"
         
         
         
        ;---------------------------------------------------------------------------------------------
        .def    acc     =  r16  ; r16 teraz ma nazwę acc
        .def    acc2    =  r17  ; r17 teraz ma nazwę acc2
        .cseg
        .org $000
         
         
                rjmp reset
         
         
        RESET:
         
               
                ldi r30,low(RAMEND)
                out SPL,r30
                ldi r30,high(RAMEND)
                out SPH,r30
         
         
                cbi DDRD,7      ; pd7 jakowe wejscie
                sbi PORTD,7     ;pullup
                cbi ddrd,6
                sbi portd,6
         
         
                ldi     r18,0xFF
                ldi r19,0x00    ;
                out     DDRB,r18        ; cały port B jako wyjściowy
                out     PORTB,r19
                ldi r24,0b00000010
                out portb,r24   ;wystaw na portB
         
                rjmp sprawdz_przycisk
         
        ;--------------------------------------------------
         
        Delay   :               ; realizacji opóźnienia
                ldi     acc2,0  ; zawartość acc2 = 0
                ldi     acc,0   ; zawartość acc = 0
        Del_0   :               ;
                inc     acc     ; zwiększ zawartość acc
                brne    Del_0   ; skocz gdy acc różne od 0
                inc     acc2    ; zwiększ zawartość acc2
                brne    Del_0
                ret             ; powrót z podprogramu
        ;----------------------------------------------  
         
         
         
    Sprawdz_przycisk:       
                sbic PIND,7
                rjmp war_1
                //do przodu
                lsl r24
                sbrs r24,5
                rjmp war_1
                ldi r24,0b00000010
     
    war_1:      sbic PIND,6
                rjmp war_2
                //do tyłu
                lsr r24
                sbrs r24,0
                rjmp war_2
                ldi r24,0b00010000
     
    war_2:
                rcall delay 			
                out portb,r24   ;wystaw na portB 
                rjmp Sprawdz_przycisk 
    
    
    
         
     
    



    Moje uwagi:

    Teraz działa poprawnie. Dlaczego wcześniej był problem? Dlaczego na LEDach było ok? Czy był to tak krótki impuls, że nie zdołałem go zauważyć a jednak krokowiec zadziałał?

    Zauważyłem, że teraz reakcja na przycisk nie jest natychmiastowa. Trzeba dłużej kliknąć co jest wg. mnie wadą. Czy chodzi o to przesunięcie rcall delay na sam koniec pętli PRZED rjmp sprawdz_przycisk? To pomoże?
  • #11 12971425
    excray
    Poziom 41  
    Teraz będzie natychmiastowa:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    A co do pytania dlaczego było źle to odpowiedział Ci już BlueDraco.
  • #12 12971471
    paavo91
    Poziom 19  
    Hmm rozumiem. Najpierw BlueDraco napisał, że moja sekwencja nie ma sensu bo równoważy się krótkiemu breq. Zmieniłem więc na breq, po czym powiedział, że pomyliłem instrukcję, zaproponował brne zamiast breq. Bo breq nie mogło działać.
    Zamotałem się po prostu, ale wciąż to nie jest dla mnie odpowiedź czemu następowała ta "cofka" w kodzie który przedstawiłem jako pierwszy.

    Dodano po 2 [minuty]:

    excray, niestety po tej zmianie delay nie działa prawidłowo.
  • #13 12971492
    excray
    Poziom 41  
    Racja. Zagapiłem się.
    Kod: text
    Zaloguj się, aby zobaczyć kod

    W kodzie miałeś dużo błędów bądź udziwnień. Zresztą dalej masz. Czemu nie przeniosłeś delaya na koniec jak pisałem? Po co robisz skok do RESET skoro RESET to następna instrukcja? Czemu nie zostawiłeś miejsca na wektory przerwań tak jak zaleca datasheet? Albo na przykład po co zmieniasz nazwę r16 na acc? Tak więc nie dziw się że BlueDraco sukcesywnie Ci o tym pisał. A przynajmniej o tych najbardziej kuriozalnych.
  • #14 12972314
    paavo91
    Poziom 19  
    Wzorowałem się na tym artykule: http://elportal.pl/ea/asm_prog001.html
    Przeczytałem, że miejsce na wektory przerwań to dobry nawyk ale na razie chciałem to sobie darować. Na pewno później bym to poprawił. Stąd skok do resetu który jest zbędny, oczywiście to rozumiem. Chciałem się skupić na działaniu kodu a później poprawić takie błędy.

    Nie napisałem, że się dziwie odnośnie odpowiedzi kolegi BlueDraco, dziękuję mu za wsparcie tak jak i Tobie ;)

    Nie kumam tylko po co ten delay na końcu i w którym dokładnie miejscu? W tej chwili delay'e mam umieszczone jak w Twoim kodzie powyżej.
  • Pomocny post
    #15 12972340
    excray
    Poziom 41  
    Chodzi mi o funkcję Delay. Patrz komentarz w kodzie:
    Kod: text
    Zaloguj się, aby zobaczyć kod
  • #16 12972398
    paavo91
    Poziom 19  
    Po prostu źle zrozumiałem. Myślałem, że chodzi o jakieś polecenie delay a nie o cały podprogram ;) Dzięki
REKLAMA