Raspberry PI 3 + OpenCV + Arduino UNO + ......(поледнее решение и вопрос в последнем сообщении)

Тема в разделе "Флудилка", создана пользователем Igor68, 21 ноя 2016.

  1. Alex19

    Alex19 Гуру

    Наверно не правильно выразился, речь шла о адресах регистров.
    То есть нельзя было получить данные по адресу 300, у меня их уже 350, поэтому было принято такое решение.

    Они были оставлены на 255. Из моего опыта, такие запросы просто не нужны. Запросы более 120 слов делятся на несколько запросов. К тому же, сложно добиться, того, чтобы регистры во всех случаях запросов выбирали данные байт за байтом. Простой пример из реальной жизни
    Код (C++):
    #define RULER_P_VALUE_RAW               modbusData[38]
    ....
    #define RULER_PUSHER_VALUE              modbusData[57]
    ....
    #define RULER_P_LENGTH                  modbusData[204]
    ....
    #define RULER_PUSHER_END                modbusData[224]
     
    В самом частом из моих запросов, последовательность верная, но есть запросы, которые выбирают данные с 38 по 57 и с 204 по 224. Не вопрос сделаем до 65535.

    Он быстрее, проще.
     
    Igor68 нравится это.
  2. Igor68

    Igor68 Гуру

    Не обращайте внимания на несоответствие количества регистров и счётчик байтов - это косяк в протоколе. Количество регистров тоже могли бы одним байтом!
    И претензия у меня вовсе не к Вам, а к протоколу!

    Применяю частотник ПЧВ3 от ОВЕН... тоже не могу в одно обращение сделать доступ для записи всех параметров.
    Табличный метод непременно испытаю!!!!!!!!!
    Что-то не в себе сегодня... очередь в поликлинике на приём... более 4-х часов. с 8:00...12:27.
    Не ругайте за развязанность!
    Спасибо!
     
  3. Alex19

    Alex19 Гуру

    Да все верно, запутался.
    Starting Address Hi 00
    Starting Address Lo 01
    No. of Registers Hi 00
    No. of Registers Lo 02
    Byte Count 04
    Из того же описания - http://www.modbus.org/docs/PI_MBUS_300.pdf.
    Стр. 55 с описание команды запроса 16.

    Ну это не ограничение, можно делать несколько запросов.

    У самого, сейчас панель HMI в качестве Master, сама режет запросы и т.д. Но ни когда не требовалось выбирать или записывать все данные.

    Он рекомендован, более скоростные решения только если сохранять в память массивы или делать на ассемблере.

    Все нормально, хотя честно не какой развязанности не заметил.
    Сейчас такая погода, что каждый второй гриппует или простужен.
     
    Igor68 нравится это.
  4. Igor68

    Igor68 Гуру

    Доброго времени суток!
    Не все данные конечно... но запуск частоткика и передача ему направления вращения надо делать практически одновременно. А регистры данных параметров и управления в моём случае не последовательны, а с "разрывом". Да и чтение его статуса - текущая частота и состояние... которые тоже не последовательны надо читать одновременно. В роли мастера у меня MOXA IA240-LX с Linux на борту. Потому и пришлось сделать сервер работы с модбас.
    Не ругайте за ссылку (может этого нельзя делать):
    http://www.moxa.ru/forum/index.php?/topic/7110-ia240-lx-modbus-rtu-master/
    и вот пример применения (тоже ссылка). Всё гораздо на мой взгляд оригинальнее стандартного варианта:
    http://www.moxa.ru/forum/index.php?/topic/7860-ia-240lx-pomogite-chajniku-ochen-nuzhno/
    Простите за лишнее. Ну а если говорить про ИП320 то передача и приём множества параметров - то это просто необходимо.
    Простите за уж совсем лишний флуд.
     
  5. Igor68

    Igor68 Гуру

    Про ошибку в изображении:
    из документа:
    Код примера:
    Код (C++):
    Mat img = imread( "image01.jpg"); // Открытие файла
    // Отобразить на изображении белую пунктирную сетку
    for( int i = 0; i < img.rows; i++ )
    for( int j = 0; j < img.cols; j++ )
    if ( ( i % 20 == 10 && j % 2 == 1 ) ||
    ( j % 50 == 25 && i % 2 == 1 ) )
    {
    img.at<Vec3b>(i,j)[0]= 255;
    img.at<Vec3b>(i,j)[1]= 255;
    img.at<Vec3b>(i,j)[2]= 255;
    }
    imwrite( "image01_res.jpg", img );
    Цикл перебирает строки изображения (i) и столбцы (j). Условие вывода на изображения
    белого пикселя: если остаток от деления на 20 номера строки равен 10 и столбец нечетный,
    если остаток от деления на 50 номера столбца равен 25 и строка нечетная. Здесь видно, что
    для вывода белого пикселя закрашивается каждый компонент. Если бы изображение было 8
    битным 1 канальным, т.е. градации серого, тогда можно было бы ограничиться одной
    строкой:
    img.at<uchar>(i,j)= 255;


    как видно вторым параметром идёт не Y а X тоесть должно быть:
    Код (C++):
    //рабочий процесс камеры
    void* CamLoop(void * pr)
    {
        U32    cntx, cnty, cntbyte;
        cv::Mat src;
        cv::Mat gray;
        //
        printf("start camm loop...\n");
        //
        while(1)
        {
            src = cvQueryFrame(capture);
            cv::cvtColor(src, gray, CV_BGR2GRAY);
            cnty     = 0;
            cntbyte    = 0;
            pthread_mutex_lock(&ServerMutex);
            while(cnty < height)
            {
                cntx = 0;
                while(cntx < width)
                {
                    ocvbuf[cntbyte] = gray.at<char>(cnty,cntx);
                    cntx++;
                    cntbyte++;
                }
                cnty++;
            }
            pthread_mutex_unlock(&ServerMutex);
            usleep(_wait_cam);
        }
        //
        pthread_exit(0);
    }
     
    За одно переделал в тестовой программе :
    Код (C++):
    static void*  vclient_process(void * pr)
    {
        U8    txbuf[_vsize_buf];
        U8    rxbuf[_vsize_buf];
        U32    txsz = 0;
        U32 cntx, cnty, cntbyte;
        int    res;
        //
        while(vClientWork)
        {
            pthread_mutex_lock(&vClientMutex);
            //формирование запроса
            memset(&txbuf[0], 0, _vsize_buf);
            txbuf[_vtype]   = _vtype_scr8;
            txbuf[_vcop]    = _vcop_rd;
            txsz = 16;
            (*(U32*)(&txbuf[_vtcp_szl])) = txsz;
            //передача данных
            if(txsz > 0)
            {
                res = cvWriteSocket(vcclient.socket, &txbuf[0], txsz);
                switch(res)
                {
                    case -2:
                        vClientWork = 0;
                        break;
                    case 0:        //
                        break;
                    default:
                        break;
                }
            }
            //usleep(_vconn_sleep);
            res = cvReadSocket(vcclient.socket, &rxbuf[0]);
            //приём данных
            switch(res)
            {
                case 0:    //Ok
                    //countlive = setcntlive;
                    //mworkr(&rxbuf[0]);
                    break;
                case -1: //таймаут
                    #if(_deb == 1)
                        printf("TCP client recv. timeout..\r\n");
                    #endif
                    break;
                case -2: //какая-то ошибка сокета
                    #if(_deb == 1)
                        printf("TCP client resv. err?..\r\n");
                    #endif
                    goto mexit;
                case -3: //ошибка размера пакета
                    //передача сообщения о несоответствии
                    #if(_deb == 1)
                        printf("TCP client frame no correct..\r\n");
                    #endif
                    goto mexit; //отмена обработки запроса
                default: //нормально - данные приняты
                    //обработка ответа
                    szall   = res;
                    rcvsz   = (*(U32*)(&rxbuf[_vtcp_szl]));
                    szx     = (*(U16*)(&rxbuf[_vwidht]));
                    szy     = (*(U16*)(&rxbuf[_vheight]));
                    //memcpy(&vbuf[0], &rxbuf[_vdaddr], szx * szy);
                    cnty = 0;
                    cntbyte = 0;
                    while(cnty < szy)
                    {
                        cntx = 0;
                        while(cntx < szx)
                        {
                            vbuf[cntx][cnty] = rxbuf[_vheight + cntbyte];
                            cntbyte++;
                            cntx++;
                        }
                        cnty++;
                    }
                    break;
            }
            pthread_mutex_unlock(&vClientMutex);
            //
            usleep(_vconn_sleep);
        }
    mexit:    close(vcclient.socket);
        vClientWork = 0;
        pthread_mutex_unlock(&vClientMutex);
        #if(_deb == 1)
            printf("mb1 disconnect\r\n");
        #endif
        //
        pthread_exit(0);
    }
    После этого всё стало нормально... но что-то происходит постепенное увеличение размера занятого ОЗУ в процессе работы программы теста на стороне ноутбука.:( Где-то бардак... пока не пойму где.

    На картинке:
    snapshot9.png
    малина в корпусе (разумеется не та на которую снимаю) и коробка от вновь купленной (которая сейчас крутит приводы и производит покадровую передачу изображения). на заднем фоне красным сообщения от QtCreator:
    QPainter::begin: Paint device returned engine == 0, type: 2
    С этим сейчас ковыряюсь.

    Спасибо!
     
    Последнее редактирование: 7 дек 2016
    Alex19 нравится это.
  6. Igor68

    Igor68 Гуру

    Сейчас вернулся снова к Arduino - доработка.
    1 - согласно указанному документу http://www.modbus.org/docs/PI_MBUS_300.pdf. решил переделать подсчёт контрольной суммы табличным методом.
    Вначале переставил старший и младший байт CRC в порядке следования как на сервере, так и в прошивке. Старший байт первым, а младший вторым в передаче. Испытал! Затем переделал процедуру подсчёта только в прошивке... испытал и...:(. Вопрос - эти два метода совместимы? Либо надо одинаково делать на двух концах? Хотя может я туплю! Сейчас какой-нибудь простой код сваяю для проверки.
    Спасибо!
     
    Последнее редактирование: 7 дек 2016
  7. Alex19

    Alex19 Гуру

    День добрый.

    Вот и у меня, что-то странное, вчера они работали, сегодня ни в какую. Даже не знаю, что сказать, сейчас сам ковыряюсь. Временно перешел на обычный расчет, который был в библиотеке calcCRC с ним работает.

    И нашел ошибку у себя в библиотеке, в одном из методов поставил u8 вместо u16.
     

    Вложения:

    Igor68 нравится это.
  8. Igor68

    Igor68 Гуру

    Вот:
    Код (C++):
    //testcrc.c

    #include <stdio.h>
    #include "types.h"


    static unsigned char auchCRCHi[]=
        {
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
            0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
            0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
            0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
            0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
            0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
            0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
            0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
            0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
        };
    /*Table of CRC values for low–order byte*/
    static char auchCRCLo[]=
        {
            0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06,0x07,0xC7,0x05,0xC5,0xC4,0x04,
            0xCC,0x0C,0x0D,0xCD,0x0F,0xCF,0xCE,0x0E,0x0A,0xCA,0xCB,0x0B,0xC9,0x09,0x08,0xC8,
            0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA,0x1A,0x1E,0xDE,0xDF,0x1F,0xDD,0x1D,0x1C,0xDC,
            0x14,0xD4,0xD5,0x15,0xD7,0x17,0x16,0xD6,0xD2,0x12,0x13,0xD3,0x11,0xD1,0xD0,0x10,
            0xF0,0x30,0x31,0xF1,0x33,0xF3,0xF2,0x32,0x36,0xF6,0xF7,0x37,0xF5,0x35,0x34,0xF4,
            0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,0xFA,0x3A,0x3B,0xFB,0x39,0xF9,0xF8,0x38,
            0x28,0xE8,0xE9,0x29,0xEB,0x2B,0x2A,0xEA,0xEE,0x2E,0x2F,0xEF,0x2D,0xED,0xEC,0x2C,
            0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26,0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,
            0xA0,0x60,0x61,0xA1,0x63,0xA3,0xA2,0x62,0x66,0xA6,0xA7,0x67,0xA5,0x65,0x64,0xA4,
            0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,0x6E,0xAE,0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xA8,0x68,
            0x78,0xB8,0xB9,0x79,0xBB,0x7B,0x7A,0xBA,0xBE,0x7E,0x7F,0xBF,0x7D,0xBD,0xBC,0x7C,
            0xB4,0x74,0x75,0xB5,0x77,0xB7,0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71,0x70,0xB0,
            0x50,0x90,0x91,0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54,
            0x9C,0x5C,0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,0x5A,0x9A,0x9B,0x5B,0x99,0x59,0x58,0x98,
            0x88,0x48,0x49,0x89,0x4B,0x8B,0x8A,0x4A,0x4E,0x8E,0x8F,0x4F,0x8D,0x4D,0x4C,0x8C,
            0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,0x43,0x83,0x41,0x81,0x80,0x40,
        };

    U16 crc16(U8 *adr_buffer, U16 byte_cnt)
    {
    // переменные для расчета CRC16 -?*:?????
        U8 uchCRCHi = 0xFF;
        U8 uchCRCLo = 0xFF;
        U16 uIndex;
       
        /* CRC Generation Function */
        while( byte_cnt--) /* pass through message buffer */
        {
            uIndex = uchCRCHi ^ *adr_buffer++; /* calculate the CRC */
            uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
            uchCRCLo = auchCRCLo[uIndex];
        }
    return (uchCRCHi  | uchCRCLo << 8);
    }

    U16 MRTU_CRC(BYTE* data, ushort len)
    {
            ushort res_CRC = 0xFFFF;
            ushort count = 0;
            BYTE count_crc;
            BYTE dt;
            while(count < len)
            {
                    //
                    count_crc = 0;
                    dt = (BYTE)(data[count]);
                    res_CRC ^= (ushort)(dt);
                    //
                    while(count_crc < 8)
                    {
                            if((res_CRC & 0x0001) < 1)
                            {
                                    res_CRC = (res_CRC >> 1) & 0x7FFF;
                            }
                            else
                            {
                                    res_CRC = (res_CRC >> 1) & 0x7FFF;
                                    res_CRC ^= 0xA001;
                            };
                            count_crc++;
                    };
                    count++;
            }
            return (res_CRC);
    }

    int main(int argc, char* argv[])
    {
        U8    tbuf[32];
        U16    crc;
        //
        tbuf[0]    = 0x10;
        tbuf[1]    = 0x06;
        tbuf[2]    = 0x10;
        tbuf[3]    = 0x20;
        tbuf[4]    = 0x33;
        tbuf[5]    = 0x00;
        tbuf[6]    = 0x00;
        tbuf[7]    = 0x00;
        //
        printf("======== test CRC math =====\n");
        crc    = MRTU_CRC(&tbuf[0], 6);
        (*(U16*)(&tbuf[6])) = crc;
        printf("buf out: %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X\n",tbuf[0],tbuf[1],tbuf[2],tbuf[3],tbuf[4],tbuf[5],tbuf[6],tbuf[7]);
       
        printf("======== test CRC table =====\n");
        crc    = crc16(&tbuf[0], 6);
        (*(U16*)(&tbuf[6])) = crc;
        printf("buf out: %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X\n",tbuf[0],tbuf[1],tbuf[2],tbuf[3],tbuf[4],tbuf[5],tbuf[6],tbuf[7]);

        return 0;
    }
     
    тест совпадает правда если делать не так:
    Код (C++):
    return (uchCRCHi  << 8 | uchCRCLo );
     
    а вот так:
    Код (C++):
    return (uchCRCHi  | uchCRCLo << 8);
     
    понимаю... да и в описании сказано, чтобы не "вертеть" байтами.
     
    Alex19 нравится это.
  9. Igor68

    Igor68 Гуру

    Доброго времени суток!
    Не ошибается только тот, кто ничего не делает! Бывает!
    Сейчас на время переключусь на другой WIFI дабы испытать... связи пока не будет!
     
  10. Igor68

    Igor68 Гуру

    Как хорошо, что был поднят этот вопрос!!!
    Всплыл косяк!
    А табличный метод работает!!!!!
    Со стороны приёма табличный метод, а со стороны приёма простой подсчёт!
     
    Alex19 нравится это.
  11. Alex19

    Alex19 Гуру

    Нашел, ошибку с CRC16, файлы верху перезалил.

    Да, а у моего слейва меня вот так
    Код (C++):
    /* Table of CRC values for high–order byte */
    const uint8_t auchCRCHi[256]=
    {
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
            0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
            0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
            0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
            0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
            0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
            0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
            0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
            0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
            0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
            0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
            0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
            0x40
    };

    const int8_t auchCRCLo[256]=
    {
            0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
            0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
            0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
            0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
            0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
            0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
            0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
            0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
            0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
            0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
            0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
            0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
            0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
            0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
            0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
            0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
            0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
            0x40
    };

    uint16_t Modbus::CRC16(uint8_t *puchMsg, uint16_t usDataLen)
    {
        unsigned char uchCRCHi = 0xFF ; /* high byte of CRC initialized */
        unsigned char uchCRCLo = 0xFF ; /* low byte of CRC initialized */
        unsigned uIndex ; /* will index into CRC lookup table */
        while (usDataLen--) /* pass through message buffer */
        {
            uIndex = uchCRCHi ^ (*puchMsg++); /* calculate the CRC */
            uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
            uchCRCLo = auchCRCLo[uIndex];
        }
        return (uchCRCHi  << 8 | uchCRCLo );
    }      
     
    Все один, в один по документации.

    Интересный компьютер, странно, что, там это не сделали. Такое оборудование все равно общается с доп. модулями по Modbus. Могли сделать базовую функцию, но поленились.

    Да множество, но все в 1-ном пакете не требовалось. Сейчас у самого Weintek 8090XE (пришлось купить его, хотел Овен СП310-Р, но ждать пока сделают не хотел), было желание подключить по Modbus IP, но мои модули W5100 не проходили через домашний роутер Zyxel (без него как часы). А вот W5200 друга, без проблем, но пока оставил как есть.
     
    Igor68 нравится это.
  12. Igor68

    Igor68 Гуру

    Я тоже придерживаюсь стандарта... но сделал косяк с перестановкой байтов в CRC. Проекты по упомянутом ссылкам:
    тоже с этим косяком... но там неправильно со стороны и клиента и сервера. В результате получилось правильно - ведь устройства на модбасе откликаются и работают. Наверное переделаю, Ой и ругают наверное меня, если конечно на том форуме стали самостоятельно делали программы-клиенты, а не пользовались теми файлами.
    Но зато схема... мне самому даже понравилась:
    1 - запускаем необходимый сервер на устройстве для доступа к нужным ресурсам.
    2 - запускаем необходимый клиент к этим ресурсам... и не обязательно на этом же устройстве.
    И всё крутится... система охлаждения, управление порезкой кабеля, дозирование и т.п. А коммуникационный контроллер IA240-LX, UC7112-LX-Plus и т.п. мне больше по душе нежели ПЛК. В основном универсальностью и возможностью "собрать их всех в кучу" по сети ETHERNET. Хотя на ПЛК легко получить готовый проект. Сейчас смотрю в сторону TRIM5 от Segnetics. На нём Debian!!!!!!!!!!!

    А W5200 через роутер пингуется? По ходу надо поднять низкоуровневый протокол. Но к сожалению я с такими устройствами не работал. Простите не помогу!
     
  13. Alex19

    Alex19 Гуру

    Тогда зря скрипел:).

    Будут пользоваться, будут спрашивать. Если все работает, то мне кажется лучше оставьте на потом, иногда можно погрязнуть в поисках идеала.

    Сам пока не пользуюсь ни тем ни другим, но систему с ОС не рискнул бы ставить. А вот ПЛК по сути тот же контролер, у него есть 1 невероятный плюс, можно показать релейную схему человеку который их понимает, а писать как обычно. Но когда нибудь, обязательно попробую ПЛК, эх найти бы время.

    По универсальности, это да, тут ПЛК курит в сторонке.

    Да и это стоит не мало.

    Там уже настоящий компьютер.

    Спасибо, не нужно, проблема аппаратная.

    С W5200 все работает Modbus IP с данной библиотекой https://github.com/andresarmento/modbus-arduino, надо лишь подправить ссылки на библиотеку W5200. С W5100 мне не везет, оригинальный был бракованный, 2 китайских использовали не те конденсаторы (отошли от документации), если их перепаять все заработает. Но там мелкая пайка, сам не смогу, а отдавать кому-то, проще и дешевле заказать другие.
     
    Igor68 нравится это.
  14. Igor68

    Igor68 Гуру

    По сути дела если пользователи в своих приложениях не будут расставлять младший и старший байты по местам самостоятельно, а будут в них пользоваться так, как и я:
    Код (C++):
    (*(uint16_t*)(&txbuf[addrCRC])) = crc;
     
    То вообще никаких проблем - сервер на другом конце расставит как надо и проблем не будет!
    Сейчас ухожу в другую сеть WIFI доделывать то что завершил (пост #45) и может что со связью изменю.
     
    Alex19 нравится это.
  15. Igor68

    Igor68 Гуру

    В процессе работы вот что получилось: snapshot10.png
    Сейчас веб камера повёрнута влево сервомашиннами на стену... уже темно и в комнате настольная лампа. Картинка практически в реальном времени. Отображение производится только закраской красными пикселями (другие цвета зарезервированы для индикации). Никакой "утечки" памяти больше не происходит на ПК. Управление несколько замедленно в связи с замедлением перерисовки элементов формы на экране когда подключены к серверу "видео" на малине. К серверу управления на малине мы так же подключены. Он передаёт команды по Serial в Arduino UNO, который в свою очередь по I2C управляет ComMotion driver for 4 motors и Multiservo(Amperka). В принципе всё готово для дальнейшей работы... конечно надо дорабатывать. Серверы пока плохо восстанавливаются после разрыва соединения - в доработке.
    Конечно много вопросов не решено но:
    1. С Вашей же помощью и Вашими рекомендациями сделана так сказать прошивка для ардуино. Для ардуино мой дебют:
    r1_uno_plus.zip

    2. Не без Вашего участия сервер управления для Raspberry 3 который принимает команды от программы управления. (Для запуска скрипт start в архиве):
    arbot.zip

    3. Сервер на малине на основе OpenCV для передачи картинки от USB веб камеры программе управления. Предварительно цветное изображение конвертировано в градации яркости. (./camserver -p 8991 для запуска. Вообще-то параметр --help для подсказки)
    camserver.zip

    4 Программа управления (скриншот в начале поста). Изменения - применение отделяемых потоков клиента управления и клиента приёма картинки. Можно по WIFI относительно ... ну сносно смотреть картинки с телевизора и смотреть как игаются коты(котята)... ну рывками небольшими. Так же не без Вашего участия:
    qtarpi.zip

    Но устройство не собрано... чисто механически много непонятного. И хотелось бы датчик препятствий - малогабаритный сонар для размещения на поворотном устройстве рядом с камерой. Ну чтобы не только видеть, но и "щупать" так сказать. Скетч для ардуино тоже довести до ума.

    С глубоким уважением!
    Спасибо!
     

    Вложения:

    • r1_uno_plus.zip
      Размер файла:
      18,3 КБ
      Просмотров:
      373
    • arbot.zip
      Размер файла:
      31,9 КБ
      Просмотров:
      375
    • camserver.zip
      Размер файла:
      64,4 КБ
      Просмотров:
      372
    • qtarpi.zip
      Размер файла:
      66,8 КБ
      Просмотров:
      390
    Последнее редактирование: 8 дек 2016
    Alex19 нравится это.
  16. Igor68

    Igor68 Гуру

    - Возник вопрос про if и switch/case:
    Ранее в KEIL UV3 (для ARM) при применении кнструкции CASE в отчёте компиляции опорный параметр загружался в регистр и далее сравнивался с вновь загружаемыми значениями. В то время как в конструкции IF опорный параметр загружался каждый раз вместе со сравниваемыми значениями, т.е. увеличивалось количество обращений к памяти и соответственно увеличивалось время выполнения. Как по данному вопросу дело обстоит в Arduino IDE.
    - Ранее когда я первый раз появился на форуме... с ComMotion... задал вопрос про замениу X*256 на X << 8 мне ответили, что сдвиг 8 раз "дороже" умножения на 256 по времени (сам смотрел систему коман MUL. В программе, где получаю контрольную сумму:
    Код (C++):
    //incrc    = (uint16_t)(dmrtu.rxbuf[cntbytes + 7] << 8);
        incrc    = (uint16_t)(dmrtu.rxbuf[cntbytes + 7] * 256);
        incrc    |= (uint16_t)(dmrtu.rxbuf[cntbytes + 8]);
    Понимаю, что деления нет (не нашел). Сдвиг в обратную сторону (вправо) - есть ли альтернатива.
    - Имеет ли смысл все параметры целлого типа заменить на 8-ми битные везде, где это возможно и/или допустимо.

    Спасибо!
    С глубоким уважением!
     
    Последнее редактирование: 8 дек 2016
  17. Alex19

    Alex19 Гуру

    День добрый.

    Когда-то присматривался к аналогичному решению, вот, что тогда было найдено - http://blog.ac-versailles.fr/techno...capteur-ultrason-SRF05-servo-processing-Sonar. Впрочем, подобных решений в сети не мало.

    Не подскажу, так как не знаю, надеюсь более опытные подскажут.

    Из документа AVR4027.
    Прямого сравнения не искал.

    Да Вы сами сказали, сдвиг вправо
    Код (C++):
    uint16_t temp = 2560 >> 8;
    Вы имеете ввиду uint16_t на uint8_t. Да, но преждевременная оптимизация отнимает много сил и времени, а в итоге код может претерпеть сильные изменения.
     
    Igor68 нравится это.
  18. Igor68

    Igor68 Гуру

    Доброго времени суток!
    По этой теме:
    1. Сдвиг влево (сначала)
    Команда
    MUL Rd, Rr (R1:R0 ← Rd x Rr) количество тактов = 2
    в то время как сдвиг влево на один бит
    LSL Rd (Rd(n+1) ← Rd(n), Rd(0) ← 0) количество тактов = 1
    Одним словом для сдвига на 8 бит влево требуется выполнить 8 раз. против одного.
    Эта история... когда я попытался переделать прошивку ComMotion... то стал заменять явный сдвиг влево, где ранее было умножение на 256. Задал вопрос тут на форуме и мне ответили что умножение (ну прям как в ARM) занимает меньше времени.
    Потому и задал этот вопрос... но деления тут (в системе команд) нет.

    Что касается замены на uint8_t то требуется только одно обращение к памяти для чтения параметра. Для uint16_t уже два обращения - шина 8-ми битная.
    Или я что-то не так сказал!
    Спасибо!
     
    Последнее редактирование: 9 дек 2016
    Alex19 нравится это.
  19. Igor68

    Igor68 Гуру

    Кстати вот... начал тестировать и изменять... ну если можно так сказать проект. Уткнулся... там и там не то, что хотел... устал и... решил изменить тестовую программу, что в QtCteator:
    snapshot11.png
    snapshot12.png
    Как раз наткнулся на неперермсовку картинки, если не обновляю значения на форме. Потому и оставил индикацию маркера времени (условный параметр от camserver - увеличивается с каждым циклом камеры в отдельном потоке). Ну и динамическую индикацию вывел на картинку.
     
  20. Alex19

    Alex19 Гуру

    Не понял о каких командах говорите, теперь буду знать.

    Все правильно.