Modbus-Master

Тема в разделе "Arduino & Shields", создана пользователем risele, 8 фев 2017.

  1. risele

    risele Нерд

    Добрый день!
    Пишу библиотечку для совместной работы Arduino и терморегулятора ОВЕН ТРМ210. (доделаю - выложу на гитхаб и Амперку).
    Протокол обмена - Modbus RTU (через RS485).
    Использую библиотеку ModbusMaster
    После некоторых чертыханий все работало прекрасно, пока я не дошел до необходимости записать информацию сразу в два регистра.

    Делаю я это следующим образом:
    Код (C++):
    //где-то в начале кода
    #include <ModbusMaster>
    ModbusMaser node;
    //описание функции
    void WriteMultRegFloat(int adress,float Temp,int StartReg)
    {
    node.setTransmitBuffer(0x0,highWord(Temp));
    node.setTransmitBuffer(0x1,lowWord(Temp));
    node.writeMultipleRegisters(StartReg,2);
    node.clearTransmitBuffer();
    }
    При этом на моей Arduino Leonardo ETH слетает загрузчик (теряется видимость через USB и никак не восстанавливается). Приходится брать другую плату и записывать через ISCP.
    В чем причина и как побороть?
     
  2. mcureenab

    mcureenab Гуру

    По кусочку кода не понятно. Может памяти не хватает?
     
  3. risele

    risele Нерд

    Ну, почему вылетает загрузчик, я выяснил. Я забыл строчку
    Код (C++):
    node.begin(adress, Serial1);
    Но код по-прежнему не работает. Я пытаюсь записать Float в два соседних регистра, но регулятор отзывается ошибкой "неверные данные".

    Код (C++):
      void WriteMultRegFloat(int adress,float Temp,int StartReg)
      {
        Start(adress);
        node.setTransmitBuffer(0x00,highWord(Temp));
        node.setTransmitBuffer(0x01,lowWord(Temp));
        int err=node.writeMultipleRegisters(StartReg,2);
        ErrorCode(err);
        node.clearTransmitBuffer();
        delay(2);
      }
     
    arkadyf нравится это.
  4. mcureenab

    mcureenab Гуру

    Это что за функции highWord, lowWord?
     
  5. risele

    risele Нерд

    вытаскивают старшую и младшую двухбайтовую часть числа.


    Код (C++):

    static uint16_t lowWord (uint32_t ww ) [inline], [static]
    {
    return (uint16_t) ((ww) & 0xFFFF);
    }
    Код (C++):

    static uint16_t highWord (uint32_t ww ) [inline], [static]
    {
    return (uint16_t) ((ww) >> 16);
    }
     
  6. mcureenab

    mcureenab Гуру

    Оно конечно да, но как вы себе представляете преобразование float в uint32_t?
     
  7. risele

    risele Нерд

    я сделал вот так:
    Код (C++):
    node.setTransmitBuffer(0x00,highWord(*( ( uint32_t* ) &Temp)));
    node.setTransmitBuffer(0x01,lowWord(*( ( uint32_t* ) &Temp)));
    Но оно все равно не работает =(
     
  8. Alex19

    Alex19 Гуру

    При работе с Modbus RTU использую функции преобразования float и double.
    Код (C++):
    void Float2UInt16(float floatVal, uint16_t* uint16Array)
    {
      // Create union of shared memory space
      union
      {
        float uFloat;
        uint16_t uArray[2];
      } u;
      // Overite bytes of union with float variable
      u.uFloat = floatVal;
      // Assign bytes to input array
      memcpy(uint16Array, u.uArray, 4);
    }

    void Double2UInt16(double doubleVal, uint16_t* uint16Array)
    {
      // Create union of shared memory space
      union
      {
        double uDouble;
        uint16_t uArray[2];
      } u;
      // Overite bytes of union with float variable
      u.uDouble = doubleVal;
      // Assign bytes to input array
      memcpy(uint16Array, u.uArray, 4);
    }
    Вызов
    Код (C++):
    float float_example = 1.11;
    uint16_t array_example[2];

    Float2UInt16(float_example,&array_example[0]);
    UPD.
    Ваши функции не годятся, Вы их даже не проверили.
     
    Последнее редактирование: 8 фев 2017
  9. risele

    risele Нерд

    Я брал их из библиотеки модбаса
     
  10. Alex19

    Alex19 Гуру

    Да не внимательно глянул, будет работать.
    Тут просто битовые операции.

    Что такое неверные данные?

    UPD. Может CRC не верно посчитан и т.д.
    Вечером гляну данную библиотеку.
     
    Последнее редактирование: 8 фев 2017
  11. risele

    risele Нерд

    В общем, чувствую себя идиотом. Попробовал разные способы записи, даже просто побайтово число готовое писать.
    А потом мне пришла одна крамольная мысль, я залез в даташит и оказался прав - этот регистр только для чтения.
     
  12. Alex19

    Alex19 Гуру

    Ни чего, сам почувствовал себя идиотом, когда глянул внимательно Ваше преобразование на битовых операциях:).

    Невнимательность и спешка, нас губит, удачи!
     
  13. DLS74

    DLS74 Гик

    Добрый день! Прочитал вашу работу с ОВЕН. Как я понял у вас получилось получать с него значения.
    Можете ли вы мне помочь с моим преобразователем температуры, который работает по RS-485. Но у меня никак не получается разобраться как забрать значения через Input Registers. После считывания идут только нули...
    С уважением Дмитрий. Оренбург.
     
  14. znamen

    znamen Guest

    Я могу Вам помочь. Но,для этого нужна схема подключения и список команд Вашего слейва.
     
  15. DLS74

    DLS74 Гик

    Датчик работает по протоколу RS-485. Считывание происходит через Input Registers.
    Адрес устройства - 01, Скорость передачи данных - 57600, Тип данных - float, длина - 2, адрес 0х0000.
    Библиотеку использую вот эту: https://github.com/smarmengol/Modbus-Master-Slave-for-Arduino
    Скетч взял из примера:
    Код (C++):
    /**
    *  Modbus master example 1:
    *  The purpose of this example is to query an array of data
    *  from an external Modbus slave device.
    *  The link media can be USB or RS232.
    *
    *  Recommended Modbus slave:
    *  diagslave http://www.modbusdriver.com/diagslave.html
    *
    *  In a Linux box, run
    *  "./diagslave /dev/ttyUSB0 -b 19200 -d 8 -s 1 -p none -m rtu -a 1"
    *   This is:
    *    serial port /dev/ttyUSB0 at 19200 baud 8N1
    *    RTU mode and address @1
    */


    #include <ModbusRtu.h>

    // data array for modbus network sharing
    uint16_t au16data[16];
    uint8_t u8state;
    byte i;

    /**
    *  Modbus object declaration
    *  u8id : node id = 0 for master, = 1..247 for slave
    *  u8serno : serial port (use 0 for Serial)
    *  u8txenpin : 0 for RS-232 and USB-FTDI
    *               or any pin number > 1 for RS-485
    */

    Modbus master(0,0,9); // this is master and RS-232 or USB-FTDI

    /**
    * This is an structe which contains a query to an slave device
    */

    modbus_t telegram;

    unsigned long u32wait;

    void setup() {
      master.begin( 57600 ); // baud-rate at 19200
      master.setTimeOut( 5000 ); // if there is no answer in 2000 ms, roll over
      u32wait = millis() + 1000;
      u8state = 0;

      Serial.begin (9600);
      pinMode(9, OUTPUT);
      digitalWrite(9, LOW);
    }

    void loop() {
      switch( u8state ) {
      case 0:
        if (millis() > u32wait) u8state++; // wait state
        break;
      case 1:
        telegram.u8id = 1; // slave address
        telegram.u8fct = 4; // function code (this one is registers read)
        telegram.u16RegAdd = 0; // start address in slave
        telegram.u16CoilsNo = 2; // number of elements (coils or registers) to read
        telegram.au16reg = au16data; // pointer to a memory array in the Arduino

        master.query( telegram ); // send query (only once)
        u8state++;
        break;
      case 2:
        master.poll(); // check incoming messages
        if (master.getState() == COM_IDLE) {
          u8state = 0;
          u32wait = millis() + 100;
        }
        for(int i=0; i<16; i++)
         {
          Serial.println(au16data[i]);
         }
    Serial.println();
    delay(1000);
        break;
      }
    }
    В интернете очень много разновидностей такой библиотеки... может мне нужно другую использовать.
    Возможно что-то с типами данных... так как au16data тип целый, а у мне нужно считать тип float.

    Ардуино Нано подключаю через https://amperka.ru/product/troyka-rs485 на Rx Tx (0 и 1)
    Управляющий использую 9 пин.

    С уважением Дмитрий.
     
  16. znamen

    znamen Guest

    Сейчас посмотрю ,для начала этот адаптер,а вы ответьте, что подключаете к этому адаптера,к его шине
    А и В и схему подключения
     
  17. DLS74

    DLS74 Гик

  18. DLS74

    DLS74 Гик

    У температурного датчика выводы все помечены: красный - Uпит, черный - GND, белый - A, зеленый - B.
     
  19. znamen

    znamen Guest

    Извените. Отпишусь через час.