Добрый день! Пишу библиотечку для совместной работы 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. В чем причина и как побороть?
Ну, почему вылетает загрузчик, я выяснил. Я забыл строчку Код (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); }
вытаскивают старшую и младшую двухбайтовую часть числа. Код (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); }
я сделал вот так: Код (C++): node.setTransmitBuffer(0x00,highWord(*( ( uint32_t* ) &Temp))); node.setTransmitBuffer(0x01,lowWord(*( ( uint32_t* ) &Temp))); Но оно все равно не работает =(
При работе с 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. Ваши функции не годятся, Вы их даже не проверили.
Да не внимательно глянул, будет работать. Тут просто битовые операции. Что такое неверные данные? UPD. Может CRC не верно посчитан и т.д. Вечером гляну данную библиотеку.
В общем, чувствую себя идиотом. Попробовал разные способы записи, даже просто побайтово число готовое писать. А потом мне пришла одна крамольная мысль, я залез в даташит и оказался прав - этот регистр только для чтения.
Ни чего, сам почувствовал себя идиотом, когда глянул внимательно Ваше преобразование на битовых операциях. Невнимательность и спешка, нас губит, удачи!
Добрый день! Прочитал вашу работу с ОВЕН. Как я понял у вас получилось получать с него значения. Можете ли вы мне помочь с моим преобразователем температуры, который работает по RS-485. Но у меня никак не получается разобраться как забрать значения через Input Registers. После считывания идут только нули... С уважением Дмитрий. Оренбург.
Датчик работает по протоколу 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 пин. С уважением Дмитрий.
Сейчас посмотрю ,для начала этот адаптер,а вы ответьте, что подключаете к этому адаптера,к его шине А и В и схему подключения