Устройство отдает данные при подключении и отключении, причем при подключении стабильно одно и то же приходит. Я думаю, что с ловлей ответов проблем нет. Проблема с отправкой запроса ИМХО.
Что значит "отдает" ?
В мониторе порта при подаче питания на устройство я вижу цифры 02550 каждый раз
Это ничего не значит. Вполне вероятно, что процессор устройства как то дергает выходные ноги при настройке.
При отключении питания получаю что-то типа такой строки:
002522401280160003200000000000014000040300002240000001287000128166413617724222249002041872281459631220813000000
Хорошо, в мануале описана стандартная Modbus-команда Read Coils.
Я опять подключился к компу, и отпарвил команду на изменение скорости подключения:
01 46 06 00 06 00 00 00 01 00 00 FC B3
В ответ получил, что все ОК (01 46 06 01 00 00 00 00 00 0A BF). Теперь 100% скорость установлена 9600 и протокол Modbus. После перезагрузки оно отвечало только на скорости 9600.
Дальше отправил команду чтения:
01 01 00 00 00 01 FD CA
И получил на нее ответ:
01 01 01 00 51 88
После этого изменил скетч вот так:
#include <SoftwareSerial.h>
byte SendData[8];
unsigned long lastMillis;
#define DE_RE_PIN 7 // The pin controlling Recieve Enable and Driver Enable on the RS485 adapter
#define RX_PIN 5 // to R0 on RS485 adapter
#define TX_PIN 4 // to DI on RS485 adapter
SoftwareSerial modbusSerial(RX_PIN, TX_PIN);
void setup() {
pinMode(DE_RE_PIN, OUTPUT);
Serial.begin(9600);
modbusSerial.begin(9600);
lastMillis = millis();
// 3.1 01 (0x01) Read Coils
SendData[0] = 0x01; //Address
SendData[1] = 0x01; //Function code
SendData[2] = 0x00; //Starting channel numbers
SendData[3] = 0x00; //Starting channel numbers
SendData[4] = 0x00; //Output channel number
SendData[5] = 0x01; //Output channel number
SendData[6] = 0xFD; //checksum
SendData[7] = 0xCA; //checksum
}
void loop() {
if (millis() - lastMillis >= 5000) {
digitalWrite(DE_RE_PIN, HIGH);
for (byte i = 0; i < 8; i++) {
modbusSerial.write(SendData[i]);
delay(10);
}
digitalWrite(DE_RE_PIN, LOW);
Serial.println("-------");
lastMillis = millis();
}
modbusSerial.listen();
while (modbusSerial.available()) {
Serial.print(modbusSerial.read());
}
}
И в ответ опять тишина. Нолики в мониторе. Хрень какая-то.
Писал уже. Если это модбас, то в цикле отправки делей ставить нельзя. У тебя делей 10 мс. При такой задержке между символами модбас не работает. Неужели трудно прочитать стандарт? Там написано, что сообщение воспринимается как новое, если тишина в линии больше чем 3.5 длительности посылки 14 бит на скорости передачи. На скорости 9600 14 бит будут передаваться около 1.5 мс. Т.е. любая пауза в передаче больше чем 5.5 мс будет восприниматься как начало новой передачи. Т.е. задержка 10 мс должна стоять после передачи последнего символа. 36 строку надо перенести на 38 .
СПАСИБО ВСЕМ!
Наконец-то получилось отправлять правильные запросы и получать на них ответы от устройства. Действительно delay() там не нужны, вообще нигде. Без них заработали и стандартные Modbus запросы, типа Read Coils и нестандартные, например запрос версии прошивки.
Единственное - иногда в начале ответа добавляется лишний ноль, или наоборот убавляется. Но, как мне кажется, это из-за Serial.println(). Его я оставил для удобства просмотра результата в мониторе порта, иначе получается длинная строка, читать которую не очень удобно.
Вот итоговый скетч:
#include <SoftwareSerial.h>
byte SendData[8];
unsigned long lastMillis;
#define DE_RE_PIN 7 // The pin controlling Recieve Enable and Driver Enable on the RS485 adapter
#define RX_PIN 5 // to R0 on RS485 adapter
#define TX_PIN 4 // to DI on RS485 adapter
SoftwareSerial modbusSerial(RX_PIN, TX_PIN);
void setup() {
pinMode(DE_RE_PIN, OUTPUT);
Serial.begin(9600);
modbusSerial.begin(9600);
lastMillis = millis();
//3.7.5 Sub-function 32 (0x20) Read firmware version
SendData[0] = 0x01; //Address
SendData[1] = 0x46; //Function code
SendData[2] = 0x20; //Sub-function code
SendData[3] = 0x13; //checksum
SendData[4] = 0xB8; //checksum
// 3.1 01 (0x01) Read Coils
/*SendData[0] = 0x01; //Address
SendData[1] = 0x01; //Function code
SendData[2] = 0x00; //Starting channel numbers
SendData[3] = 0x00; //Starting channel numbers
SendData[4] = 0x00; //Output channel number
SendData[5] = 0x01; //Output channel number
SendData[6] = 0xFD; //checksum
SendData[7] = 0xCA; //checksum*/
}
void loop() {
if (millis() - lastMillis >= 5000) {
digitalWrite(DE_RE_PIN, HIGH);
for (byte i = 0; i < 8; i++) {
modbusSerial.write(SendData[i]);
}
digitalWrite(DE_RE_PIN, LOW);
Serial.println();
lastMillis = millis();
}
modbusSerial.listen();
while (modbusSerial.available()) {
Serial.print(modbusSerial.read());
}
}
Делей нужен перед переключением направлением передачи. Его длительность надо подбирать. Причина в том, что ардуина выдаёт символ около миллисекунды. Если переключить раньше, то символ будет обрезан. Вам везёт в том, что используется софтверный сериал. Если использовать хардовый точно ничего не работало бы.
Вообще delay() у меня появился из этой темы, в частности из этого поста. Там у ТС задержка в цикле по 2 мс (в предыдущих постах была 1 мс). И задержка после окончания передачи аж 500 мс. При этом все работало, но у него действительно мега2560 и хардовый сериал.
Со всеми этими задержками я тоже вдоволь наэксперементировался, и 1 мс в цикле ставил и 5 и 10. Видимо 10 осталось после какого-то из эксперимента (забыл обратно вернуть).
В моем случае (с софтовым Serial), пауза в 5 мс после передачи (перед переключением направления) уже приводит к выводу непонятного мусора в порт. Видимо с софтовым сериал все проще, там задержки появляются сами по себе.
Delay может и не нужен, но дождаться опустошения буфера отправки вы обязаны. Потому что вы можете переключить направление передачи раньше чем все данные уйдут из буфера отправки. Сделать это можно двумя способами:
1. проверкой опустошения буфера
2. расчетом времени передачи данного количества байт на данной скорости
Первый вариант точнее. Вы этого не делаете. Я вам дал ссылку на готовую процедуру отправки. Странно, что вы даже не поинтересовались.
Причем важно именно вовремя переключить направление передачи и принять ответ в буфер. Кода вы будете забирать данные из буфера уже не важно. Так вот это 500 миллисекунд, это время в течении которого данные считываются в буфер порта. Тем более, что буфер, как правило меньше пакета.
В софтовом сериале, при отправке нет буферизации, возврат из .write происходит по окончании передачи данных. Но это в вашей реализации, есть софт сериалы, где это не так.
Знакомые циферки-то и активити туда-сюда все равно увидеть должен.
Устройство отдает данные при подключении и отключении, причем при подключении стабильно одно и то же приходит. Я думаю, что с ловлей ответов проблем нет. Проблема с отправкой запроса ИМХО.
Что значит "отдает" ?
В мониторе порта при подаче питания на устройство я вижу цифры 02550 каждый раз
Это ничего не значит. Вполне вероятно, что процессор устройства как то дергает выходные ноги при настройке.
Скажите пожалуйста какой именно модбас вы пытаетесь реализовать ? ModBus RTU ?
Да, ModBus RTU
Зачем ? Судя по описанию у вас вообще не ModBus.
В мануале написано так:
При отключении питания получаю что-то типа такой строки:
002522401280160003200000000000014000040300002240000001287000128166413617724222249002041872281459631220813000000
Потому что вот это все что угодно, но не модбас.
Хорошо, в мануале описана стандартная Modbus-команда Read Coils.
Я опять подключился к компу, и отпарвил команду на изменение скорости подключения:
В ответ получил, что все ОК (01 46 06 01 00 00 00 00 00 0A BF). Теперь 100% скорость установлена 9600 и протокол Modbus. После перезагрузки оно отвечало только на скорости 9600.
Дальше отправил команду чтения:
И получил на нее ответ:
После этого изменил скетч вот так:
И в ответ опять тишина. Нолики в мониторе. Хрень какая-то.
Писал уже. Если это модбас, то в цикле отправки делей ставить нельзя. У тебя делей 10 мс. При такой задержке между символами модбас не работает. Неужели трудно прочитать стандарт? Там написано, что сообщение воспринимается как новое, если тишина в линии больше чем 3.5 длительности посылки 14 бит на скорости передачи. На скорости 9600 14 бит будут передаваться около 1.5 мс. Т.е. любая пауза в передаче больше чем 5.5 мс будет восприниматься как начало новой передачи. Т.е. задержка 10 мс должна стоять после передачи последнего символа. 36 строку надо перенести на 38 .
Не хочется повторять в десятый раз. Вот по ссылке http://arduino.ru/forum/programmirovanie/ne-mogu-razobratsya-s-modbus-rtu-i-485-interfeisom?page=1#comment-571366 , возьмите процедуру чтения-записи и колдуйте.
СПАСИБО ВСЕМ!
Наконец-то получилось отправлять правильные запросы и получать на них ответы от устройства. Действительно delay() там не нужны, вообще нигде. Без них заработали и стандартные Modbus запросы, типа Read Coils и нестандартные, например запрос версии прошивки.
Единственное - иногда в начале ответа добавляется лишний ноль, или наоборот убавляется. Но, как мне кажется, это из-за Serial.println(). Его я оставил для удобства просмотра результата в мониторе порта, иначе получается длинная строка, читать которую не очень удобно.
Вот итоговый скетч:
на всякий скажу, раз уж не нужен delay между байтами. можно и так в шину говорить,без цикла for:
Делей нужен перед переключением направлением передачи. Его длительность надо подбирать. Причина в том, что ардуина выдаёт символ около миллисекунды. Если переключить раньше, то символ будет обрезан. Вам везёт в том, что используется софтверный сериал. Если использовать хардовый точно ничего не работало бы.
Вообще delay() у меня появился из этой темы, в частности из этого поста. Там у ТС задержка в цикле по 2 мс (в предыдущих постах была 1 мс). И задержка после окончания передачи аж 500 мс. При этом все работало, но у него действительно мега2560 и хардовый сериал.
Со всеми этими задержками я тоже вдоволь наэксперементировался, и 1 мс в цикле ставил и 5 и 10. Видимо 10 осталось после какого-то из эксперимента (забыл обратно вернуть).
В моем случае (с софтовым Serial), пауза в 5 мс после передачи (перед переключением направления) уже приводит к выводу непонятного мусора в порт. Видимо с софтовым сериал все проще, там задержки появляются сами по себе.
на всякий скажу, раз уж не нужен delay между байтами. можно и так в шину говорить,без цикла for:
Так у меня компилятор ругается no matching function for call to 'write(byte [8])', видимо метод не переопределен для работы с типом byte.
Цикл меня вполне устраивает. Имхо, он более наглядный.
Макс забыл второй аргумент для write() - sizeof(array).
СПАСИБО ВСЕМ!
Delay может и не нужен, но дождаться опустошения буфера отправки вы обязаны. Потому что вы можете переключить направление передачи раньше чем все данные уйдут из буфера отправки. Сделать это можно двумя способами:
1. проверкой опустошения буфера
2. расчетом времени передачи данного количества байт на данной скорости
Первый вариант точнее. Вы этого не делаете. Я вам дал ссылку на готовую процедуру отправки. Странно, что вы даже не поинтересовались.
Причем важно именно вовремя переключить направление передачи и принять ответ в буфер. Кода вы будете забирать данные из буфера уже не важно. Так вот это 500 миллисекунд, это время в течении которого данные считываются в буфер порта. Тем более, что буфер, как правило меньше пакета.
В софтовом сериале, при отправке нет буферизации, возврат из .write происходит по окончании передачи данных. Но это в вашей реализации, есть софт сериалы, где это не так.
точно, чёто впарился. Так можно только char [] отправлять