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

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

  1. Igor68

    Igor68 Гуру

    Посмотрите не переставлены ли старший и младший байты местами. В указанной функции мне именно это и не понравилось... точнее не подходило.
     
  2. Igor68

    Igor68 Гуру

    Да фактически всё готово... дополнительных функций на ардуине вроде как не предвидится. Но задержка ответа по протоколу смущает!
    Кстати про контрольную сумму, принятую:
    Код (C++):
    //контрольная сумма для приёма - результат сравнение: 0 - совпало
    inline uint8_t sMRTU_CRCi(uint8_t * data, uint16_t len, uint8_t * crch, uint8_t * crcl)
    {
        uint8_t uchCRCHi = 0xFF;
        uint8_t uchCRCLo = 0xFF;
        uint16_t uIndex ;
        //uint8_t res;
        while(len--)
        {
            uIndex = uchCRCHi ^ *data++ ;
            uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
            uchCRCLo = auchCRCLo[uIndex] ;
        }
        return (*crch ^ uchCRCLo) | (*crcl ^ uchCRCHi);
    }
    Вот так применял:
    Код (C++):
    //проверка контрольной суммы
        if(sMRTU_CRCi(&dmrtu.rxbuf[0], 6, &dmrtu.rxbuf[_ADDR_03_INCRC_H], &dmrtu.rxbuf[_ADDR_03_INCRC_L]) == 0)
              {
    ....................
    }
     
     
  3. Alex19

    Alex19 Гуру

    Да смотрю.

    У меня на панели HMI есть простой RS232, но нет переходника, точнее будет завтра RS232 - UART, надо допилить под RS485.

    Ок, думал, что еще дописывать будете.

    UPD. Да у меня, панель рассчитывает CRC16 по стандарту.
    Код (C++):
    //Так было, до.
    //return (uint16_t)(uchCRCHi | uchCRCLo * 256) ;
    return (uint16_t)(uchCRCLo | uchCRCHi * 256) ;
    UPD 2.
    Кстати, какая у Вас задержка?
    У меня при скорости 9600, пакет 120 слов, максимальное время цикла 0,496ms.
     
    Последнее редактирование: 24 дек 2016
    Igor68 нравится это.
  4. Igor68

    Igor68 Гуру

    Сейчас настройка для запуска сервера управления:
    Код (Bash):
    #!/bin/bash

    echo "...starting Arduino & Raspberry conrol"
    ./arbot -p 8971 -sp /dev/ttyUSB0 9600 48 -wd 50
    то есть настройка для ожидания ответа 48 символов. Задание задержки формируется:
    Код (C++):
    //ожидание в символах
                symbols     = atoi(argv[scnt]);
                symwait     = (int)((1000000.0f / (float)(baudrate)) * 10.0f * (float)(symbols));
    параметр ожидания в символах определена при соединении:
    Код (C++):
    //|соединяемся с Arduino
        res = MRTU_Connect(&serialname[0], baudrate, symwait);
    Где при соединении ф функции:
    Код (C++):
    int MRTU_Connect(char* strPort, int baud, int stout)
    {
       ...............................
       wait_tx_rx = stout;
       ...............................
    }
    сам цикл приёма (рассматриваем команду 3 на малине:
    Код (C++):

        .......................................................
        tcflush(fd, TCIOFLUSH);
        wcount = write(fd, &txbuf[0], 8);
            if (wcount < 8) {
            #if(_mdbg == 1)
                    printf("send CMD3 error! ...dev: %i  addr: %i\n", Dev, Addr);
            #endif
                return _tx_err;
            }
        //tcflush(fd, TCIOFLUSH);
        usleep(wait_tx_rx);
        memset(&rxbuf[0], 0, _szbuf);
        fcntl(fd, F_SETFL, FNDELAY);
        rcount = read(fd, &rxbuf[0], _szbuf);
        ...................................................
     
    Но измерить фактически у меня нет возможности
     
    Последнее редактирование: 24 дек 2016
  5. Alex19

    Alex19 Гуру

    Не правильно выразился, сколько всего обрабатывает сам пакет я не знаю, просто не интересно, хотя тоже можно узнать. Меня интересует максимальное время цикла Ардуино, AVR. То есть максимальное время исполнения loop, в начало loop вставляем таймер.
    Код (C++):
     #if defined(DEBUGGING_THROUGH_UART) && defined(TEST_SPEED_CYCLE)
          // Начальное время цикла.
          timeCycleBegin = micros();
      #endif
    В конец, что-то аналогичное.
    Код (C++):
      #if defined(DEBUGGING_THROUGH_UART) && defined(TEST_SPEED_CYCLE)
          // Определяем скорость работы.
          timeCycle = GetDifferenceULong(timeCycleBegin, micros());
          // Если текущее значение больше, последнего максимального, отображаем его.
          if (timeCycle > timeCycleMax)
          {
            timeCycleMax = timeCycle;

            DEBUG_PRINT("Max - ");
            DEBUG_PRINTLN(timeCycleMax);
          }
      #endif
    У меня к примеру, максимальное время цикла loop.
    1. Время чтения по Modbus, максимальное 0,488мл.
    2. Чтение всех ADC для пропорциональных клапанов 0,024мл.
    3. Чтение MAX6675 0,008мл.
    4. Чтение MAX6675 + PID Arduino 0,212мл.

    UPD. По сути, скорость приема пакета от начала до конца, это всего лишь скорость UART. Мало увеличиваем скорость, меняем шину.

    К размышлению, сейчас, тот же пакет до 1,2ms (максимальное время loop) с стандартной библиотекой Serial и до 0,5ms (максимальное время loop) c библиотекой UART которую скидывал, на UART не зависимо от скорости. На Serial не знаю, есть ли зависимость.

    Так же можно сделать расчет CRC16 на ассемблере, это дорогая операция у меня.

    Дождусь завтра, с переходником будет веселей, делать еще 1 реализацию RS485, которая ни кому не нужна, не хочется.
     
    Последнее редактирование: 24 дек 2016
    Igor68 нравится это.
  6. Igor68

    Igor68 Гуру

    Прошу прощения... если не сложно подбросьте мне GetDifferenceULong
    Спасибо!
     
  7. Alex19

    Alex19 Гуру

    Конечно не сложно, забыл про них.
     

    Вложения:

    • Timer.cpp
      Размер файла:
      3 КБ
      Просмотров:
      472
    • Timer.h
      Размер файла:
      1,2 КБ
      Просмотров:
      532
  8. Igor68

    Igor68 Гуру

    Простите найдено!
     
  9. Igor68

    Igor68 Гуру

    Реализовал в команде 3:
    Код (C++):
    ................
    //Измерение времени цикла
            else if((bsreg == _timeCycleMax) && (bcntreg == 1))
            {
                dmrtu.txbuf[_ADDR_MADDR]      = _MRTU_Addr;            //адрес устройства
                dmrtu.txbuf[_ADDR_MCMD]      = 3;                //команда
                dmrtu.txbuf[_ADDR_03_CNT_BYTES]    = 2;                //счётчик байтов для передачи
                dmrtu.txbuf[_ADDR_03_DATA]    = (timeCycleMax >> 8);
                dmrtu.txbuf[_ADDR_03_DATA + 1]    = (timeCycleMax & 0xFF);
                sMRTU_CRCo(&dmrtu.txbuf[0], 5, &dmrtu.txbuf[5], &dmrtu.txbuf[6]);
                Serial.write(&dmrtu.txbuf[0], 7);
                return;
            }
    ........................
    брал тип параметра uint16_t для передачи... внутри сервера управления добавил:
    Код (C++):
    case 4: //время цикла
                res = MRTU_CMD_3(1, 2, (U16*)(&tloop), 1);
                printf("time loop: %i\n", tloop);
                break;
     
    не работал с подобным ранее но в консоли сервера получил:
    Код (Bash):
    igor@debian-i:/home/ext_projects/arbot$ ./start
    ...starting Arduino & Raspberry conrol
    ---- opening tcp/ip  8971 ----
    time loop: 16044
    time loop: 16044
    time loop: 16044
    time loop: 16044
    time loop: 16044
    time loop: 16044
    time loop: 16044
    time loop: 16044
    time loop: 16044
    time loop: 16044
    time loop: 16044
    time loop: 16044
    time loop: 16044
    time loop: 16044
    time loop: 16044
    time loop: 16044
    time loop: 16044
    time loop: 16044
    ^C
    igor@debian-i:/home/ext_projects/arbot$
     
    но не забывайте, что в этом цикле у меня обращение по I2C с ComMotion и Multiservo:
    Код (C++):
    void loop()
    {
        uint16_t timeCycleBegin = micros();
         //штатная работа
        switch(dnum)
          {
            //Multiservo
                case 0:
                      servo[0].write(dservo[0]);
                      dnum = 1;//dnum++;
                      break;
                 case 1:
                      servo[1].write(dservo[1]);
                      dnum = 2;//dnum++;
                      break;
                //ComMotion driver for 4 motors - значения моторов
                case 2:
                      //IndividualMotorControl(dmotor[0], dmotor[1], dmotor[2], dmotor[3]);
                mIndividualMotorControl((uint8_t*)&dmotor[0], (uint8_t*)&dmotor[1], (uint8_t*)&dmotor[2], (uint8_t*)&dmotor[3]);
                delay(15); //оставил для MCU1 и MCU2
                      dnum = 0;
                      break;
                default:
                      dnum = 0;
                      break;
          }
        uint16_t timeCycle = (uint16_t)GetDifferenceULong((uint32_t)timeCycleBegin, (uint32_t)micros());
        if (timeCycle > timeCycleMax)
                timeCycleMax = timeCycle;
    //
        delay(10); //это оставил
    }
     
  10. Alex19

    Alex19 Гуру

    Это мелочи, хотя не знаю, какая реализация у стандартной библиотеки.

    16,044мк из них 15 delay, получается что 1,044мк.

    Вообщем не плохо для Serial, но delay надо убирать, а то получаем 15мк. Так же у Вас еще есть 10мк которые не включены в расчет, получается, что 26мк простоя на каждом цикле, кол-во циклов loop в секунде 38, это очень плохо. Если delay будут убраны и можно будет уложиться в 1,044мк, если ошибок не будет, можно остановиться на достигнутом, этого будет достаточно.
     
  11. Igor68

    Igor68 Гуру

    delay конечно можно убрать, но для ComMotion потребуется оставить - по I2C mcu0 и mcu1 производят некоторый обмен между собой и шина I2C в этот момент занята и требуется молчание на ней со стороны Arduino. Но беспокоит не столько сам цикл (хотя беспокоит конечно), сколько время отклика на команды по Serial. Буду допиливать конечно же.
     
  12. Alex19

    Alex19 Гуру

    Не говорил, что требуется убрать задержки, говорил о delay.

    К примеру у меня 6 термопар, каждый со своим ПИД. Толку их опрашивать каждую 1мл., делаю простую задержку на таймере, если время не прошло, код идет дальше. Не блокируя выполнения других блоков кода.

    Вот пример

    Код (C++):
     static uint32_t previousMillis = 0;
          uint32_t currentMillis = millis();

          if (currentMillis - previousMillis >= 250UL)
          {
            static uint8_t selectThermocouple = 0;

            if (!selectThermocouple)
            {
              Double2UInt16(thermocoupleZ1.readCelsius(), &INPUT_Z1);
             }

            if (selectThermocouple == 1)
            {
              Double2UInt16(thermocoupleZ2.readCelsius(), &INPUT_Z2);
            }

            if (selectThermocouple == 2)
            {
              Double2UInt16(thermocoupleZ3.readCelsius(), &INPUT_Z3);
            }

            if (selectThermocouple == 3)
            {
              Double2UInt16(thermocoupleZ4.readCelsius(), &INPUT_Z4);
            }

            if (selectThermocouple == 4)
            {
              Double2UInt16(thermocoupleZ5.readCelsius(), &INPUT_Z5);
            }

            if (selectThermocouple == 5)
            {
              Double2UInt16(thermocoupleHC.readCelsius(), &INPUT_HC);
             }

            selectThermocouple++;

            if (selectThermocouple == 6)
            {
              selectThermocouple = 0;

              previousMillis = currentMillis;
            }
          }
    Есть еще такие варианты.
    Код (C++):
    if (u8current != u8lastRec)
            {
                u8lastRec = u8current;
                u32time = millis() + T35;
                return 0;
            }

            if (millis() < u32time)
            {
                return 0;
            }
    Но суть от этого не меняется. Все эти примеры построены на millis или micros. Вот описание - http://arduino.ru/tutorials/BlinkWithoutDelay. Сам delay не использую в loop, только в setup.

    UPD.
    После этого, если ошибок не будет, скорость отклика увеличится.

    Что такое delay, это останов программы на заданное время. Когда выполняется delay все стоит, кроме прерываний, подробнее тут - http://arduino.ru/Reference/Delay. Да Ваш Serial получает данные в свой буфер, но не идет обработка Modbus и может случится ситуация, когда буфер Serial забьется быстрее, чем Вы его обработаете. Хоть мало вероятно, скорость всего 9600, но все же.

    Я отдыхать, утро вечера мудренее.
     
    Последнее редактирование: 25 дек 2016
    Igor68 нравится это.
  13. Igor68

    Igor68 Гуру

    Извините... если я понял: время выполнения loop влияет на реакцию по void serialEvent(). То есть serialEvent() сработает не ранее завершения цикла loop ну или перед ним? но только не во время его выполнения... я правильно понял?
     
  14. Igor68

    Igor68 Гуру

    Это точно!
     
  15. Alex19

    Alex19 Гуру

    Да, он сработает только после того как цикл loop отработает, после чего будет запущен serialEvent. Это не прерывание, поэтому во время цикла loop он не работает. Как-то у меня не сложилось с serialEvent, пользуюсь в loop простой проверкой наличия байт в буфере Serial. Поэтому у меня он убран
    Код (C++):
    /// <summary>
    /// Основная функция main.
    /// </summary>
    int main(void)
    {
      init();

    #if defined(USBCON)
      USBDevice.attach();
    #endif

      setup();

      for (;;)
      {
        loop();
        // В проекте не используется стандартная библиотека Serial.
        //if (serialEventRun) serialEventRun();
      }

      return 0;
    }
    Как видим он просто вызывается после завершения loop.

    UPD. Есть пару нюансов в использовании временных задержек на основании millis, micros, но об этом уже завтра.
     
    Igor68 нравится это.
  16. Igor68

    Igor68 Гуру

    Доброго времени суток!
    Про последовательность внутри MAIN, в обработку в котором присутствует loop и serialEvent... всё становится на свои места. Спасибо! Сейчас переделаю.
     
  17. Igor68

    Igor68 Гуру

    вот новый отчёт по связи (в arbot):
    Код (Bash):
    igor@debian-i:/home/ext_projects/arbot$ ./start
    ...starting Arduino & Raspberry conrol
    ---- opening tcp/ip  8971 ----
    receive ansver CMD16 error! ...dev: 1  addr: 48
    receive ansver CMD3 error! ...dev: 1  addr: 48
    receive ansver CMD16 error! ...dev: 1  addr: 64
    receive ansver CMD3 error! ...dev: 1  addr: 64
    receive ansver CMD3 error! ...dev: 1  addr: 2
    time loop: 0
    receive ansver CMD16 error! ...dev: 1  addr: 48
    receive ansver CMD3 error! ...dev: 1  addr: 48
    receive ansver CMD16 error! ...dev: 1  addr: 64
    receive ansver CMD3 error! ...dev: 1  addr: 64
    receive ansver CMD3 no main CMD! ...dev: 1  addr: 2 sendCMD: 03 recvCMD: 10
    send bytes: 01 03 00 02 00 01 CA 25
    recv bytes: 01 10 00 30 00 04 C5 C1
    time loop: 0
    time loop: 1952
    time loop: 1952
    time loop: 1964
    time loop: 1964
    time loop: 1964
    time loop: 1964
    time loop: 1968
    time loop: 1968
    time loop: 1972
    time loop: 1972
    time loop: 1972
    time loop: 1972
    time loop: 1972
    time loop: 1972
    time loop: 1972
    time loop: 1972
    time loop: 1972
    time loop: 1972
    time loop: 1972
    time loop: 1972
    time loop: 1972
    time loop: 1976                                                                                                                                                                  
    time loop: 1976                                                                                                                                                                            
    time loop: 1976                                                                                                                                                                            
    time loop: 1976                                                                                                                                                                            
    time loop: 1976  
    Работоспособность нормальная. Но теперь время ожидания уменьшилось с 48 до 35 символов для скорости 9600. Спасибо за Прогресс!!!!!!
     
    Последнее редактирование: 25 дек 2016
  18. Alex19

    Alex19 Гуру

    День добрый.

    Не за что.

    Если все делать без задержек, то можно опустить до 1,2 -1мс. У меня сейчас Modbus RTU + 2 устройства на TWI (ADS1115 + AT24C256 времянка вместо FRAM с отложенным сохранением), максимальное время 0,532мс. Но библиотеки UART, TWI.

    Сейчас уезжаю, вечером продолжим.
     
    Igor68 нравится это.
  19. Igor68

    Igor68 Гуру

    Вот отчёт консоли приблизительно через 2 часа эксплуатации а arbot:
    Код (Bash):
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
    time loop: 2036
     
    Вот это код loop:
    Код (C++):

    void loop()
    {
       uint16_t timeCycleBegin = micros();
       //штатная работа
    switch(dnum)
          {
            //Multiservo
                case 0:
                if(GetDifferenceULong(pwait, micros()) > _i2c_wait)
                {
                    pwait = GetDifferenceULong(pwait, micros());
                          servo[0].write(dservo[0]);
                          dnum = 1;//dnum++;
                }
                      break;
                 case 1:
                if(GetDifferenceULong(pwait, micros()) > _i2c_wait)
                {
                    pwait = GetDifferenceULong(pwait, micros());
                          servo[1].write(dservo[1]);
                          dnum = 2;//dnum++;
                }
                      break;
                //ComMotion driver for 4 motors - значения моторов
                case 2:
                if(GetDifferenceULong(pwait, micros()) > _i2c_wait)
                {
                    pwait = GetDifferenceULong(pwait, micros());
                    mIndividualMotorControl((uint8_t*)&dmotor[0], (uint8_t*)&dmotor[1], (uint8_t*)&dmotor[2], (uint8_t*)&dmotor[3]);
                          dnum = 0;
                }
                      break;
                default:
                      dnum = 0;
                      break;
          }
        uint16_t timeCycle = (uint16_t)GetDifferenceULong((uint32_t)timeCycleBegin, (uint32_t)micros());
        if (timeCycle > timeCycleMax)
                timeCycleMax = timeCycle;
    }
     
    В команде 16 MRTU тоже изменение:
    Код (C++):
    /*
    ****************************
    CMD16 - запись в несколько
    регистров
    ****************************
    */

    inline void    MRTU_CMD16(void)
    {
        #if(_opt_8 == 0)
            uint16_t  sreg;        //стартовый регистр
            uint16_t  cntreg;    //количество регистров
        #endif
        int    addr;
        uint8_t      bsreg;
        uint8_t   bcntreg;
        uint8_t      cntbytes;        //счётчик байт в поле данных
        uint8_t   wregcnt;
        uint8_t   wcntb        = 0;
        //стартовый регистр
        #if(_opt_8 == 0)
            sreg          = (uint16_t) (dmrtu.rxbuf[_ADDR_16_ADDR_REG_H] * 256)
                    | (uint16_t) (dmrtu.rxbuf[_ADDR_16_ADDR_REG_L]);
        #else
            bsreg        = dmrtu.rxbuf[_ADDR_16_ADDR_REG_L];
        #endif
        //количество регистров
        #if(_opt_8 == 0)
            cntreg      = (uint16_t) (dmrtu.rxbuf[_ADDR_16_CNT_REG_H] * 256)
                    | (uint16_t) (dmrtu.rxbuf[_ADDR_16_CNT_REG_L]);
        #else
            bcntreg        = dmrtu.rxbuf[_ADDR_16_CNT_REG_L];
        #endif
        //количество байт данных
        cntbytes = dmrtu.rxbuf[_ADDR_16_CNT_BYTES];
        //проверка контрольной суммы
        if(sMRTU_CRCi(&dmrtu.rxbuf[0], cntbytes + 7, &dmrtu.rxbuf[cntbytes + 7], &dmrtu.rxbuf[cntbytes + 8]) == 0)
        {
            /*
                ****************************
                проверка границ данных
                ****************************
                */

            #if(_opt_8 == 0)
                bsreg    = (uint8_t)(sreg);
                bcntreg    = (uint8_t)(cntreg);
            #endif
            //проверка предельного размера
            if(bcntreg >= _cntreg)
            {
                dmrtu.txbuf[0]  =  _MRTU_Addr;
                dmrtu.txbuf[1]  =  16 | _CMD_ERR_MODE;
                dmrtu.txbuf[2]  =  _ILLEGAL_DATA_ADDRESS;
                sMRTU_CRCo(&dmrtu.txbuf[0], 3, &dmrtu.txbuf[3], &dmrtu.txbuf[4]);
                Serial.write(&dmrtu.txbuf[0], 5);
                return;
            }
                //ComMotion
            else if((bsreg >= _ComMotion_RMS) &&
                (bsreg < (_ComMotion_RMS + _ComMotion_SzRM)) &&
                ((bsreg + bcntreg) <= (_ComMotion_RMS + _ComMotion_SzRM)))
            {
                dmrtu.txbuf[0]  =  _MRTU_Addr;
                dmrtu.txbuf[1]  =  16;
                dmrtu.txbuf[2]  =  0;
                dmrtu.txbuf[3]  =  bsreg;
                dmrtu.txbuf[4]  =  0;
                dmrtu.txbuf[5]  =  bcntreg;
                bsreg     -= _ComMotion_RMS;    //стартовый регистр
                wcntb     += _ADDR_16_DAT_H;    //счётчик байтов + смещение
                bcntreg    += bsreg;        //количество регистров со смещением
                addr    = (int)&dmotor[bsreg];
                while(bsreg < bcntreg)
                {
                    //dmotor[bsreg++]    = ((int16_t)(dmrtu.rxbuf[wcntb]) * 256)
                    //        | (int16_t)(dmrtu.rxbuf[++wcntb]);
                    (*(uint8_t*)(addr++))    = dmrtu.rxbuf[wcntb + 1];
                    (*(uint8_t*)(addr++))    = dmrtu.rxbuf[wcntb];
                    bsreg++;
                    wcntb    += 2;
                }
                sMRTU_CRCo(&dmrtu.txbuf[0], 6, &dmrtu.txbuf[6], &dmrtu.txbuf[7]);
                Serial.write(&dmrtu.txbuf[0], 8);
                return;
            }
            //Multiservo
            else if((bsreg >= _Multiservo_RSS1) &&
                (bsreg < (_Multiservo_RSS1 + _Multiservo_SzRS)) &&
                ((bsreg + bcntreg) <= (_Multiservo_RSS1 + _Multiservo_SzRS)))
            {
                dmrtu.txbuf[0]  =  _MRTU_Addr;
                dmrtu.txbuf[1]  =  16;
                dmrtu.txbuf[2]  =  0;            //стартовый регистр
                dmrtu.txbuf[3]  =  bsreg;        //стартовый регистр
                bsreg         -= _Multiservo_RSS1;    //стартовый регистр
                wcntb         += _ADDR_16_DAT_H;    //счётчик байтов + смещение
                dmrtu.txbuf[4]  =  0;
                dmrtu.txbuf[5]    =  bcntreg;        //количество регистров
                bcntreg        += bsreg;        //количество регистров со смещением
                addr        = (int)&dservo[bsreg];
                while(bsreg < bcntreg)
                {
                    //dservo[bsreg++]    = ((int16_t)(dmrtu.rxbuf[wcntb]) * 256)
                    //        | (int16_t)(dmrtu.rxbuf[++wcntb]);
                    //        | (int16_t)(dmrtu.rxbuf[++wcntb]);
                    (*(uint8_t*)(addr++))    = dmrtu.rxbuf[wcntb + 1];
                    (*(uint8_t*)(addr++))    = dmrtu.rxbuf[wcntb];
                    bsreg++;
                    wcntb += 2;
                }
                sMRTU_CRCo(&dmrtu.txbuf[0], 6, &dmrtu.txbuf[6], &dmrtu.txbuf[7]);
                Serial.write(&dmrtu.txbuf[0], 8);
                return;
            }
            // ILLEGAL DATA ADDRESS - вышли за предел данных
            else
            {
                dmrtu.txbuf[0]  =  _MRTU_Addr;
                dmrtu.txbuf[1]  =  16 | _CMD_ERR_MODE;
                dmrtu.txbuf[2]  =  _ILLEGAL_DATA_ADDRESS;
                sMRTU_CRCo(&dmrtu.txbuf[0], 3, &dmrtu.txbuf[3], &dmrtu.txbuf[4]);
                Serial.write(&dmrtu.txbuf[0], 5);
                return;
            }
        }
    }
     
    Простите, что очень "размыто"
     
    Alex19 нравится это.
  20. Igor68

    Igor68 Гуру

    Может это и глупо... или слишком... но Требуется раздел "СМОТРИТЕ ЧТО МЫ (Все Вместе Сделали... Ну или Делаем) Спасибо!