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

Chiński enkoder po modbusie RDE42BS6 i zerowanie

07 Wrz 2019 09:49 132 6
  • Poziom 17  
    Witam
    Posiadam chiński enkoder który jest w pewnej maszynie i niestety innego nie można zastosować.
    http://www.roundssencoder.com/news_images/20150728230105530.pdf

    Komunikacja z nim odbywa się po modbusie rtu (rs485).
    Ogólnie ten enkoder działa z maszyną ale nie działa komenda zerowania (strona 8 w w/w pdfie).

    Według dokumentacji trzeba wysłać komendę 0x1 0xCC 0x00 z CRC którą trzeba wyliczyć ale nie wiem w jaki sposób.
    Próbowałem kalkulatorem na tych stronach
    https://www.lammertbies.nl/comm/info/crc-calculation.html
    http://www.zorc.breitbandkatze.de/crc.html
    ale zawsze po wpisaniu komendy wyskakiwał bajt zwrotny 00 i nic więcej.

    Kontaktowałem się z dostawcą enkodera ale żadnej konkretnej odpowiedzi nie dostałem poza tą.

    If you send 0x01 0xCC 0x00 XX XX(CRC checksum code, LSB first.
    0x00 means "Set the current position to zero"
    trying this command from computer first then connect to the application.
    Chiński enkoder po modbusie RDE42BS6 i zerowanie

    Pomoże ktoś z tym kodem crc ?

    Edit: Poszukałem trochę na elektrodzie i znalazłem taki post z funkcją która według opisu z dokumentacji pasuje do algorytmu.
    https://www.elektroda.pl/rtvforum/viewtopic.php?p=16721760#16721760

    Code:

    #include <stdio.h>
    #include <stdlib.h>

    const unsigned char cmd[] =
    {
      {0x01, 0xCC, 0x00}
    };

    unsigned int CRC;

    unsigned int addCRC(unsigned char val[] ,unsigned char len)
    {
    unsigned int crc=0xffff;
    unsigned char i,k;


       for(k=0;k<len;k++)
          {
          crc=crc^val[k];
           i=8;
           while(i)
              {
             if (crc&1)
                {
                crc=crc>>1;
                crc=crc^0xA001;
                }
                else
                {
                crc=crc>>1;
                }
             i--;
             }
          }

       return crc;
    }



    int main()
    {

        printf("Hello world!\n");
        CRC=addCRC(cmd,3);

        printf("%04x",CRC);
        return 0;
    }

    Wynik wychodzi mi 0x0020. Czy jest on poprawny ? Nie mam teraz dostępu do tego enkodera a muszę mieć pewność przy następnym podejściu że ramkę którą będę wysyłał będzie ok.
  • Poziom 22  
    Czesc,

    Jakiego narzędzia używasz do komunikacji z tym enkoderem? PC z konwerterem?

    Jeśli tak i masz gotowy program typu Modbus Master to nie wyliczasz zadnego CRC program robi to za Ciebie.
    posługujesz sie tylko adresam modbus enkodera i kodem funkcji wg manuala. i Program reszte robi za Ciebie. Proponuje wybrać tą drogę. Modbus mastery znajdziesz na sieci.

    Jesli natomiast nie masz programu typu modbus master lecz wysylasz na port RS dane to musisz wyliczyc CRC na piechote i dodac do paczki wysylanej. Tutaj proponuje zaczac od wyslania takiego ciągu w formacie HEX
    01 03 00 00 00 01 84 0A i zobaczyc co przyjdzie z Enkodera.
    Powinno
    01 03 02 XX XX
    oraz CRC XXXX wyliczone przez enkoder to dana pozycja z enkodera
    Acha pierwsza cyfra 01 zaklada ze twoj enkoder ma adres 01.
    Po tym poznasz ze masz wszystko dobrze skomunikowane i czas zabrac sie za CRC. Ale moze to w pozniejszym poscie:)
  • Poziom 17  
    Witaj Zgoodie
    Dzięki za szybką odpowiedź.
    Tą ramkę znam 01 03 00 00 00 01 84 0A i wiem że to jest zapytanie o 1 rejestr Holding Register, 01 - to id slave'a a 03 to kod funkcji czyli odczyt holding rejestru a 00 00 00 01 to adres 0 i długość 1, później jest kod crc.
    Ramka 01 03 00 00 00 01 84 0A działa jak również inne typu
    FF A0 40 38 odpowiadające za sprawdzenie adresu urządzenia (Check Device Address - strona 8 w pdf).

    Jednak do uruchomienia zerowania dostawca enkodera sugeruje użycie funkcji 01 CC 00 XX XX a wydaje mi się że CC to nie jest w standardzie modbusa.
    Używam realterma. Generalnie wystarczy obojętnie jaki który obsługuje nasłuch po serialu i możliwość wysyłania danych w hex.

    Edit: Popatrzyłem jeszcze raz w dokumentację i wydaje mi się że na 99% funkcję którą poniżej zamieszczam dokładnie robi to co jest napisane w chińskiej instrukcji. Tylko po wpisaniu 0x01 0xCC 0x00 0x00 0x75 enkoder odpowiada 0x00. Jeśli wpisze się inny kod CRC to też odpowie 0x00 czyli nie przyjmuje komendy.


    Chiński opis wyliczania kodu CRC

    The steps of calculating the CRC code is:

    ① Preset 16 bits slave is hexadecimal coding FFFF(that is 1 for all).We call this kind of slave as CRC slave;

    ② Exclusive OR the first 8-bit data with 16-bit CRC slave low-XOR, put the result into CRC slave;

    ③ Move one bit of the slave into right direction(towards low), filling the highest position with 0, checking the lowest position;

    ④ If the lowest bit (the moved out one) is 0: then repeat Step 3 (shifted again) If the lowest bit (the moved out one) is 1: Exclusive OR CRC slave with polynomial A001(1010 0000 0000 0001);

    ⑤ Repeat step 3 for and 4 until the right eight times, so that the whole 8-bit data are fully processed;

    ⑥ Repeat from the steps 2 to step 5, and carrying next 8-bit data processing;

    ⑦ The resulting of CRC slave is the CRC code。

    ⑧ Put CRC results into information frames, exchange the low bit with high bit, LSB first。


    I ta funkcja którą znalazłem dokładnie to robi

    unsigned int addCRC(unsigned char val[] ,unsigned char len)
    {
    unsigned int crc=0xffff;
    unsigned char i,k;


    for(k=0;k<len;k++)
    {
    crc=crc^val[k];
    i=8;
    while(i)
    {
    if (crc&1)
    {
    crc=crc>>1;
    crc=crc^0xA001;
    }
    else
    {
    crc=crc>>1;
    }
    i--;
    }
    }

    return crc;
    }
  • Poziom 22  
    W realterm zawsze bedzie kolega musila to liczyc. A jakby jednak sprobowac jakiegos mastera z ModB
  • Poziom 38  
    Czy zauważyłeś że w niektórych ramkach producent zamienia bajty crc ?
    np dla check device address - MSB first ale dla innych LSB first
    teraz pytanie czy jest to błąd w dokumentacji czy tak robią i czy przypadkiem nie trzeba tak zrobić dla zero position.
  • Poziom 17  
    @Tos18 Czyli zamiast ramki 0x01 0xCC 0x00 0x00 0x75 powinna być ramka
    0x01 0xCC 0x00 0x75 0x00 ?