Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Silnik krokowy - zadawanie liczby kroków z terminala Realterm

Jakub17 25 Lut 2017 21:38 684 19
  • #1 25 Lut 2017 21:38
    Jakub17
    Poziom 6  

    Witam.

    Program ma działać w ten sposób, że w terminalu Realterm na komputerze wpisują sobie zadaną liczbę kroków i silnik wykonuje dokładnie to liczbę kroków. Problem mam z transmisją danych liczby kroków.


    Kod: c
    Zaloguj się, aby zobaczyć kod

    Problem jest jedynie z transmisją bo jak ustawie na sztywno parametr m np. m=5 to wszystko jest ok. Coś musi byc nie halo z tą tablicą str1 tak mi się zdaje ale nie mam pomysłu jak to inaczej zrobić. Jakieś sugestie?
    Dzięki z pomoc.

    0 19
  • #2 26 Lut 2017 13:30
    Mad Bekon
    Poziom 23  

    A nie powinno zamiast:
    str1[j++] = UDR;
    być:
    str1[j++] = odb;

    ?

    0
  • #3 26 Lut 2017 13:33
    BlueDraco
    Specjalista - Mikrokontrolery

    Skąd wiesz, że odebrałeś znak, który wstawiasz do łańcucha?

    Napis zupełnie od nowa odbiór danych - tu nawet nie ma czego poprawiać.

    0
  • #4 26 Lut 2017 13:44
    2675900
    Użytkownik usunął konto  
  • #5 26 Lut 2017 13:44
    Mad Bekon
    Poziom 23  

    BlueGraco ma rację. Powinieneś dodawać odebrany znak do ciągu tylko wtedy gdy pojawi się coś nowego, a Ty robisz to za każdym obkręceniem pętli.
    Powinieneś, w przerwaniu odebrać znak, przypisać do zmiennej, oraz ustawić drugą zmienną jako flagę odebrania nowego znaku.
    W pętli głównej, jeśli pojawił się nowy znak, wyzerować tą zmienną flagę, dodać do ciągu, i sprawdzić czy nie była znakiem końcowym, jeśli tak, to przeliczyć i wykonać kod obrotu.

    @Piotrus_999

    Piotrus_999 napisał:

    Mad Bekon napisał:
    str1[j++] = odb;
    A co to zmieni?

    Za szybko przeleciałem przez kod, a to pierwsza rzecz która wpadła mi w oko, aczkolwiek wg mojej wiedzy jest różnica między
    Code:
    odb = UDR; 
    
    str1[j++] = odb;
    a
    Code:
    str1[j++] = UDR;

    0
  • #6 26 Lut 2017 13:58
    BlueDraco
    Specjalista - Mikrokontrolery

    Mad Bekon napisał:
    Powinieneś, w przerwaniu odebrać znak, przypisać do zmiennej, oraz ustawić drugą zmienną jako flagę odebrania nowego znaku.


    A po co tu przerwanie? żeby przepisać rejestr do zmiennej i ustawić własny znacznik? Przecież znacznik już jest - w rejestrze stanu UART, a odebrany znak w rejestrze UDR. Z kopiowania danych i znaczników pożytku nie będzie.

    0
  • #7 26 Lut 2017 14:08
    2675900
    Użytkownik usunął konto  
  • Pomocny post
    #8 26 Lut 2017 14:36
    Mad Bekon
    Poziom 23  

    Nie ma jeśli wywołamy go raz,
    ale jak tu w kodzie, kolega w przerwaniu zrobił

    Code:
    odb = UDR;
    a potem w kodzie głównym
    Code:
    str1[j++] = UDR;
    to nie zadziała, a
    Code:
    str1[j++] = odb;
    już tak.
    Cytat:
    However, the receive buffering has two improvements that will affect the compatibility in some
    special cases:
    • A second Buffer Register has been added. The two Buffer Registers operate as a circular
    FIFO buffer. Therefore the UDR must only be read once for each incoming data!


    Jednak wszyscy zgodnie możemy stwierdzić, że w kodzie jest wiele nieprawidłowości, nie tylko to.

    @Jakub17
    Na kolanie, bez sprawdzania, ale może być to jakoś tak:
    Zmienne:
    Code:
    volatile unsigned char bytesReceivedCounter = 0 , bytesProcessed = 0, startTurning = 0;

    W pętli głównej:
    Code:

    while(1) {

          while(!startTurning);
          startTurning = 0;
          obrot_tab();
          stop();
       }

    Przerwanie:
    Code:

    ISR(USART_RXC_vect)
    {
       bytesReceivedCounter ++;

    while(bytesReceivedCounter > bytesProcessed) {
           bytesProcessed++;
             uint8_t tmp = UDR;
             if(tmp == 0x2D || (tmp>=0x30 && tmp<= 0x39))
             {
                str1[bytesProcessed-1] = tmp;
             }
             else
             {
                str1[bytesProcessed-1] = 0;
                m = atoi(str1);
                bytesProcessed = bytesReceivedCounter = 0;
                startTurning = 1;
             }
          }
    }

    0
  • #9 26 Lut 2017 14:40
    2675900
    Użytkownik usunął konto  
  • #10 26 Lut 2017 14:46
    Mad Bekon
    Poziom 23  

    Co najwyżej wskazuje na jeden z błędów w kodzie. Ale myślę, że warto przytoczyć tą kwestię, bo nie każdy pamięta o tym, że z UDR czyta się raz.

    0
  • #11 26 Lut 2017 14:55
    BlueDraco
    Specjalista - Mikrokontrolery

    To już mamy dwa przykłady dydaktyczne pt. "jak nie należy używać przerwań". ;)

    0
  • #12 26 Lut 2017 15:00
    Mad Bekon
    Poziom 23  

    A jak to jest dydaktycznie?

    0
  • Pomocny post
    #13 26 Lut 2017 15:03
    BlueDraco
    Specjalista - Mikrokontrolery

    Np. coś takiego - są tu 3 błędy, ale na początek ujdzie:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #14 26 Lut 2017 15:07
    Mad Bekon
    Poziom 23  

    Też zauważyłem błędy w swoim kodzie.
    Inna sprawa, że zależy jak do tematu podejść. I kwestia priorytetów. Przerwanie można wykorzystać na różne sposoby.
    W tym przypadku parsowanie nie jest bardzo skomplikowane, natomiast nie jestem pewien czy bardziej skomplikowane należałoby całkowicie wykonywać w czasie przerwania.
    Mnie tłuczono do głowy, że długi kod wykonywany w przerwaniu jest beeee...

    0
  • #15 26 Lut 2017 15:23
    2675900
    Użytkownik usunął konto  
  • #16 26 Lut 2017 15:29
    BlueDraco
    Specjalista - Mikrokontrolery

    Mad Bekon napisał:
    Mnie tłuczono do głowy, że długi kod wykonywany w przerwaniu jest beeee...

    Przesądy.

    0
  • #17 26 Lut 2017 17:36
    Jakub17
    Poziom 6  

    Dzięki za tak aktywny udział w dyskusji.
    A wracając do tematu...
    Czyli powinienem wstrzymać pętlę główną do tego czasu aż wszystkie bajty informacji znajdą się w tablicy, a o końcu ciągu oznajmi mi znak '\0' który będę musiał wykryć. String reprezentowany przez tą tablice mogę wtedy przekształcić przez atoi na int i gotowe. Tylko zastanawiam się jak uzupełniać tą tablice każdą kolejną ramką danych. Kolega Mad Bekon zamieścił kod ale nie do końca go rozumiem...

    0
  • #18 26 Lut 2017 17:57
    2675900
    Użytkownik usunął konto  
  • #19 26 Lut 2017 18:33
    BlueDraco
    Specjalista - Mikrokontrolery

    Nie wiem, czemu upierasz się na robienie czegokolwiek w pętli głównej. Pokazałem rozwiązanie krótkie i działające, z pustą pętlą główną i dwoma przerwaniami. Przerwanie timera i tak musisz mieć - do odmierzania czasu kroków.

    0
  • #20 26 Lut 2017 19:21
    2675900
    Użytkownik usunął konto