Доступ к регистрам Modbus свыше 255 невозможен SimpleModbus

Я французский студент, и я играл с SimpleModbus в течение 1 недели, и это работало нормально... Пока я не попытался реализовать ведомое устройство с большим количеством регистров (1000 необходимо). Доступ к регистрам за пределами 255 с использованием ведомого устройства 1 недоступен. Что бы я ни делал, я получаю ошибку тайм-аута, как только чтение регистров выходит за пределы 255:

control.modbus.CommunicationException: While reading holding registers 255 on slave 1

В документации ничего не сказано о таком ограничении. Чтение SimpleModbusSlave.cpp не помогло... возможно, мне нужно изменить начальный адрес в функции "обновления modbus", но я слишком новичок, чтобы понять...

unsigned int modbus_update() {
  if (*(ModbusPort).available())
  {
    unsigned char buffer = 0;
    unsigned char overflow = 0;

    while ((*ModbusPort).available())
    {
      // The maximum number of bytes is limited to the serial buffer size of 128 bytes
      // If more bytes is received than the BUFFER_SIZE the overflow flag will be set and the
      // serial buffer will be red untill all the data is cleared from the receive buffer.
      if (overflow)
        (*ModbusPort).read();
      else
      {
        if (buffer == BUFFER_SIZE)
          overflow = 1;
        frame[buffer] = (*ModbusPort).read();
        buffer++;
      }
      delayMicroseconds(T1_5); // inter character time out
    }

    // If an overflow occurred increment the errorCount
    // variable and return to the main sketch without
    // responding to the request i.e. force a timeout
    if (overflow)
      return errorCount++;

    // The minimum request packet is 8 bytes for function 3 & 16
    if (buffer > 7)
    {
      unsigned char id = frame[0];

      broadcastFlag = 0;

      if (id == 0)
        broadcastFlag = 1;

      if (id == slaveID || broadcastFlag) // if the recieved ID matches the slaveID or broadcasting id (0), continue
      {
        unsigned int crc = ((frame[buffer - 2] << 8) | frame[buffer - 1]); // combine the crc Low & High bytes
        if (calculateCRC(buffer - 2) == crc) // if the calculated crc matches the recieved crc continue
        {
          function = frame[1];
          unsigned int startingAddress = ((frame[2] << 8) | frame[3]); // combine the starting address bytes
          unsigned int no_of_registers = ((frame[4] << 8) | frame[5]); // combine the number of register bytes
          unsigned int maxData = startingAddress + no_of_registers;
          unsigned char index;
          unsigned char address;
          unsigned int crc16;

          // broadcasting is not supported for function 3
          if (!broadcastFlag && (function == 3))
          {
            if (startingAddress < holdingRegsSize) // check exception 2 ILLEGAL DATA ADDRESS
            {
              if (maxData <= holdingRegsSize) // check exception 3 ILLEGAL DATA VALUE
              {
                unsigned char noOfBytes = no_of_registers * 2;
                // ID, function, noOfBytes, (dataLo + dataHi)*number of registers,
                //  crcLo, crcHi
                unsigned char responseFrameSize = 5 + noOfBytes;
                frame[0] = slaveID;
                frame[1] = function;
                frame[2] = noOfBytes;
                address = 3; // PDU starts at the 4th byte
                unsigned int temp;

                for (index = startingAddress; index < maxData; index++)
                {
                  temp = regs[index];
                  frame[address] = temp >> 8; // split the register into 2 bytes
                  address++;
                  frame[address] = temp & 0xFF;
                  address++;
                }

                crc16 = calculateCRC(responseFrameSize - 2);
                frame[responseFrameSize - 2] = crc16 >> 8; // split crc into 2 bytes
                frame[responseFrameSize - 1] = crc16 & 0xFF;
                sendPacket(responseFrameSize);
              }
              else
                exceptionResponse(3); // exception 3 ILLEGAL DATA VALUE
            }
            else
              exceptionResponse(2); // exception 2 ILLEGAL DATA ADDRESS
          }
          else if (function == 16)
          {
            // Check if the recieved number of bytes matches the calculated bytes
            // minus the request bytes.
            // id + function + (2 * address bytes) + (2 * no of register bytes) +
            // byte count + (2 * CRC bytes) = 9 bytes
            if (frame[6] == (buffer - 9))
            {
              if (startingAddress < holdingRegsSize) // check exception 2 ILLEGAL DATA ADDRESS
              {
                if (maxData <= holdingRegsSize) // check exception 3 ILLEGAL DATA VALUE
                {
                  address = 7; // start at the 8th byte in the frame

                  for (index = startingAddress; index < maxData; index++)
                  {
                    regs[index] = ((frame[address] << 8) | frame[address + 1]);
                    address += 2;
                  }

                  // only the first 6 bytes are used for CRC calculation
                  crc16 = calculateCRC(6);
                  frame[6] = crc16 >> 8; // split crc into 2 bytes
                  frame[7] = crc16 & 0xFF;

                  // a function 16 response is an echo of the first 6 bytes from
                  // the request + 2 crc bytes
                  if (!broadcastFlag) // don't respond if it's a broadcast message
                    sendPacket(8);
                }
                else
                  exceptionResponse(3); // exception 3 ILLEGAL DATA VALUE
              }
              else
                exceptionResponse(2); // exception 2 ILLEGAL DATA ADDRESS
            }
            else
              errorCount++; // corrupted packet
          }
          else
            exceptionResponse(1); // exception 1 ILLEGAL FUNCTION
        }
        else // checksum failed
          errorCount++;
      } // incorrect id
    }
    else if (buffer > 0 && buffer < 8)
      errorCount++; // corrupted packet
  }
  return errorCount;
}

Подчиненный: SimpleModbusSlave Есть мысли?

Изменить: я думаю, что у кого-то была такая же проблема, но я действительно не понял, что он изменил :( здесь

Заранее спасибо тем, кто сможет меня просветить!


person Gabriel    schedule 06.07.2018    source источник
comment
Вы уверены, что не получаете ответ об исключении? У вас есть оператор if (буфер › 7), я думаю, что размер ответа об исключении составляет всего 5 байт: адрес подчиненного устройства (1), код функции (1), код исключения (1), crc (2).   -  person Marker    schedule 06.07.2018
comment
Спасибо за ваш ответ! с этой стороны проблем нет, я использую старую версию этой библиотеки: github.com/pepsilla/Arduino/tree/master/MODBUS/ASCII/libraries/   -  person Gabriel    schedule 06.07.2018
comment
Я также вижу комментарий Максимальное количество байтов ограничено размером последовательного буфера 128 байт. Максимальный размер Modbus ADU (RTU) составляет 256 байт. Вы можете никогда не достичь этого предела, если одновременно читаете только несколько регистров. Сколько регистров вы пытаетесь прочитать одновременно? Было бы полезно увидеть весь ваш код.   -  person Marker    schedule 06.07.2018
comment
Значит, вы используете Modbus ASCII, а не RTU?   -  person Marker    schedule 06.07.2018
comment
Я использую Modbus для связи в Java с моим Arduino. Ардуино собирает данные датчиков и хранит их в кольцевом буфере. Потом на мастер (в java) захожу периодически собираю данные кольцевого буфера. Прочитал реестр сразу. Имеется 10 датчиков с кольцевым буфером 64*16 бит данных. На первых 3-х датчиках проблем нет, но на 4-м у меня появляется это сообщение об ошибке, потому что я пытаюсь прочитать индекс 256 ...   -  person Gabriel    schedule 06.07.2018
comment
Думаю тут нужно что-то изменить: адрес хранится только на 8 битах так что после 255... Но вообще не знаю я немного запутался... unsigned int startupAddress = ((frame[2] ‹‹ 8) |кадр [3]); // объединить байты начального адреса unsigned int no_of_registers = ((frame [4] ‹‹ 8) | frame [5]); // объединяем количество байтов регистра (я использую RTU Master)   -  person Gabriel    schedule 06.07.2018
comment
Хорошо, я был сбит с толку. Код, который вы используете, имеет ASCII в URL-адресе (/MODBUS/ASCII/libraries/SimpleModbusSlave), поэтому я думал, что вы используете протокол Modbus ASCII, но комментарии в заголовке указывают, что это RTU.   -  person Marker    schedule 06.07.2018
comment
Я посмотрел (отсканировал) код слейва. Не слишком надежный и немного сложный для понимания, но похоже, что он должен работать. Я также посмотрел мастер-код и, кажется, понял его, но я надеялся увидеть, как выглядит пакет, который он отправляет. Я предлагаю вам протестировать ведомое устройство с помощью CAS Modbus Scanner (бесплатно) или Modbus Poll (бесплатная пробная версия). Оба являются мастер-инструментами Modbus, и я знаю, что они работают. Если ваш ведомый код работает с этими инструментами, то ваша проблема в ведущем коде; если с ними не работает, то проблема в ведомом коде.   -  person Marker    schedule 06.07.2018
comment
Большое спасибо ! Я попробую :)   -  person Gabriel    schedule 06.07.2018
comment
Большое спасибо @Marker, теперь это работает! Я изменил свою библиотеку для подчиненного устройства: github.com/smarmengol/Modbus-Master- Раб для Arduino   -  person Gabriel    schedule 09.07.2018


Ответы (1)


Большое спасибо @Marker, теперь это работает! Я изменил свою библиотеку для ведомого устройства: github.com/smarmengol/Modbus-Master-Slave-for-Arduino —

person Gabriel    schedule 09.07.2018
comment
Отлично, рад, что смог помочь! - person Marker; 09.07.2018