1. Обязательно представиться на русском языке кириллицей (заполнить поле "Имя").
  2. Фиктивные имена мы не приветствуем. Ивановых и Пупкиных здесь уже достаточно.
  3. Не надо писать свой вопрос в первую попавшуюся тему - всегда лучше создать новую тему.
  4. За поиск, предложение и обсуждение пиратского ПО и средств взлома - бан без предупреждения. Непонятно? - Читать здесь.
  5. Рекламу и частные объявления "куплю/продам/есть халтура" мы не размещаем ни на каких условиях.
  6. Перед тем как что-то написать - читать здесь, а затем здесь и здесь.
  7. Не надо писать в ЛС администраторам свои технические вопросы. Администраторы форума отлично знают как работает форум, а не все-все контроллеры, о которых тут пишут.

Java и ModBus RTU + RS-485

Модератор: Глоб.модераторы

Ответить

Автор темы
kolyagl
здесь недавно
здесь недавно
Сообщения: 19
Зарегистрирован: 28 апр 2017, 13:57
Имя: Николай
Страна: Россия
Благодарил (а): 2 раза
Поблагодарили: 1 раз

Java и ModBus RTU + RS-485

Сообщение kolyagl »

Всем привет. Возникла следующая проблема. Мне необходимо подключиться к контроллеру шагового двигателя OSM-17RA и по
протоколу ModBus RTU с ним пообщаться. Для этих целей мной был написан следующий класс

Код: Выделить всё

public class ModBus {
    private static Byte CRCHigh;//Переменная контрольной суммы
    private static Byte CRCLow;//Переменная контрольной суммы
    public static byte[] ModbusCommand8(byte id, byte command, byte startAddress, byte length)
    {
        byte[] data = new byte[8];
        //Адрес устройства
        data[0] = id;
        //Код функции Modbus
        data[1] = command;
        //Начальный адрес регистра
        byte[] _adr = BitConverter.getBytes(startAddress);
        data[2]=_adr[1] ;//[1] младший
        data[3] =_adr[0];//[0] старший
        //Колличество регистров которое необходимо считать
        byte[] _length = BitConverter.getBytes(length);
        data[4]=_length[1];//[1]
        data[5] =_length[0];//[0]
        //Контрольная сумма CRC
        myCRC(data, 6);
        data[6] = CRCLow;//[1]
        data[7] = CRCHigh;//[0]
        try {Thread.sleep( 200 );}
        catch (InterruptedException e){}
        return data;
    }



    //Метод расчёта контрольной суммы CRC-16
    public static void myCRC(byte[] message, int length)
    {
        char CRCFull = (char)0xFFFF;
        for (int i = 0; i < length; i++)
        {
            CRCFull = (char)(CRCFull ^ message[i]);
            for (int j = 0; j < 8; j++)
            {
                if ((CRCFull & 0x0001) == 0)
                    CRCFull = (char)(CRCFull >> 1);
                else
                {
                    CRCFull = (char)((CRCFull >> 1) ^ 0xA001);
                }
            }
        }
        CRCHigh = (byte)((CRCFull >> 8) & 0xFFFF);
        CRCLow = (byte)(CRCFull & 0xFFFF);
    }

} 
Далее был написан методы которые запускают и останавливаю двигатель

Код: Выделить всё

public void Move (Byte slaveAddress){
        arrModbusCommand =modBus.ModbusCommand8( slaveAddress,(byte) 6,(byte)5,(byte)1 );
        try {serialPort.writeBytes( arrModbusCommand );}
        catch (SerialPortException ex){ }
    }

    public void Stop (Byte slaveAddress){
        arrModbusCommand =modBus.ModbusCommand8( slaveAddress,(byte)06,(byte)5,(byte)0 );
    try {serialPort.writeBytes( arrModbusCommand );}
    catch (SerialPortException ex){ }
    }
Данные методы нормально работаю.
А вот следующий метод работает не нормально т.е вообще не работает

Код: Выделить всё

 public void SetSpeed(Byte slaveAddress){

        arrModbusCommand =modBus.ModbusCommand16( slaveAddress,(byte) 16,(byte)16385,(byte)100 );
        System.out.println( Arrays.toString( arrModbusCommand ) );
        try {serialPort.writeBytes( arrModbusCommand );}
        catch (SerialPortException ex){ }
    }

я хочу записать в
регистр 16385 значение скорости например 100, но скорость не меняется я понимаю, что проблема скорей всего в конвертации
значения 16385 в byte но не понимаю как его конвертировать чтобы все заработало) если кто писал что-то на Java проги для общения
с устройствами по ModBus RTU помогите советом или лучше куском кода)))

ссыль на pdf описания контроллера http://onitex.ru/files/Documentation/OS ... M42RA.pdf список команд с 33 страницы начинается
P.S если я все правильно понимаю то мне надо значение 16385 преобразовать в 2-а байта и засунуть вот сюда
byte[] _adr = BitConverter.getBytes(startAddress);
data[2]=_adr[1] ;//[1] младший
data[3] =_adr[0];//[0] старший
Но я не понимаю как это сделать. Представление в виде HEX 4001 результатов не дало.

Автор темы
kolyagl
здесь недавно
здесь недавно
Сообщения: 19
Зарегистрирован: 28 апр 2017, 13:57
Имя: Николай
Страна: Россия
Благодарил (а): 2 раза
Поблагодарили: 1 раз

Java и ModBus RTU + RS-485

Сообщение kolyagl »

Кто нибудь использовал библиотеку (ИМЕННО ИСПОЛЬЗОВАЛ КУЧУ ССЫЛОК НА ХЗ КАКИЕ ЛИБЫ Я И САМ НАШЕЛ) с нормальными доками (нормально описаны все методы, классы и т.д) которую я мог бы в свой проект забубенить. С устройством буду общаться через COM так что EasyModbusTCP/UDP/RTU не подойдёт (а то ведь особо ЖЕЛАЮЩИЕ ПОМОЧЬ первым делом на неё ссыль дадут) протокол ModBus RTU интерфейс RS-485. Кто юзал подобные штуки поделитесь ссылкой и если есть возможность примерчиком кода (подключались к устройству, читали, записывали в регистры). Всем ребятам с конкретными ответами (без язвительных замечаний и отсылками к почитать чего нить) + к карме.))

alex_ugrumov
почётный участник форума
почётный участник форума
Сообщения: 635
Зарегистрирован: 29 сен 2008, 17:05
Имя: Алексей Угрюмов
Страна: Россия
город/регион: СПб
Благодарил (а): 13 раз
Поблагодарили: 25 раз

Java и ModBus RTU + RS-485

Сообщение alex_ugrumov »

Хорошая либа для работы с СОМ - MOXA PComm . Но там заявлена только поддержка Visual, Basic, Borland. Если сможете прикрутить .lib к Жабе - ок.
Alex.

Автор темы
kolyagl
здесь недавно
здесь недавно
Сообщения: 19
Зарегистрирован: 28 апр 2017, 13:57
Имя: Николай
Страна: Россия
Благодарил (а): 2 раза
Поблагодарили: 1 раз

Java и ModBus RTU + RS-485

Сообщение kolyagl »

Тут не всё так просто) для .NET платформы у ребят есть прям нормальная рабочая либа (я её к шарпу прикручивал и всё норм работало), но мне надо реализацию на Java запилить)

maxamin
здесь недавно
здесь недавно
Сообщения: 68
Зарегистрирован: 17 апр 2019, 15:06
Имя: Максим
Страна: Россия
город/регион: СПб
Поблагодарили: 6 раз

Java и ModBus RTU + RS-485

Сообщение maxamin »

Я бы сначала отладил работу просто через mobus pull: https://www.modbustools.com/download.html посредством usb/485 конвертера. Просто пуляя в регистры нужные числа.
Аватара пользователя

hell_boy
почётный участник форума
почётный участник форума
Сообщения: 1746
Зарегистрирован: 18 янв 2009, 12:25
Имя: Дмитрий
Страна: Россия
город/регион: Москва
Благодарил (а): 6 раз
Поблагодарили: 143 раза

Java и ModBus RTU + RS-485

Сообщение hell_boy »

kolyagl писал(а): 28 авг 2019, 07:43 Для этих целей мной был написан следующий класс

Код: Выделить всё

...
    public static byte[] ModbusCommand8(byte id, byte command, byte startAddress, byte length)
...
следующий метод работает не нормально т.е вообще не работает

Код: Выделить всё

...
        arrModbusCommand =modBus.ModbusCommand16( slaveAddress,(byte) 16,(byte)16385,(byte)100 );
...
Где, собственно, исходник ModbusCommand16?

Структура FC06 и FC10 немного разная
Write single register (FC 6)

Request
Byte 0: FC = 06
Byte 1-2: Reference number
Byte 3-4: Register value

Response
Byte 0: FC = 06
Byte 1-2: Reference number
Byte 3-4: Register value

Exceptions
Byte 0: FC = 86 (hex)
Byte 1: exception code = 01 or 02

Example
Write 1 register at reference 0 (40001 in Modicon 984) of value 1234 hex
06 00 00 12 34 => 06 00 00 12 34
Write multiple registers (FC 16)

Request
Byte 0: FC = 10 (hex)
Byte 1-2: Reference number
Byte 3-4: Word count (1-100)
Byte 5: Byte count (B=2 x word count)
Byte 6-(B+5): Register values

Response
Byte 0: FC = 10 (hex)
Byte 1-2: Reference number
Byte 3-4: Word count

Exceptions
Byte 0: FC = 90 (hex)
Byte 1: exception code = 01 or 02

Example
Write 1 register at reference 0 (40001 in Modicon 984) of value 1234 hex
10 00 00 00 01 02 12 34 => 10 00 00 00 01
Просили библиотеку https://github.com/steveohara/j2mod
Там хотя бы можно помотреть как конвертировать
/**
* Converts the register (a 16 bit value) into an unsigned short.
*/
public static int registerToUnsignedShort(byte[] bytes) {
return ((bytes[0] & 0xff) << 8 | (bytes[1] & 0xff));
}

/**
* Converts the given unsigned short into a register
* (2 bytes).
*/
public static byte[] unsignedShortToRegister(int v) {
byte[] register = new byte[2];
register[0] = (byte)(0xff & (v >> 8));
register[1] = (byte)(0xff & v);
return register;
}
"Умные люди обсуждают идеи, средние - события, а глупые - людей" Л.Н. Толстой

Idelle
здесь недавно
здесь недавно
Сообщения: 21
Зарегистрирован: 13 ноя 2017, 14:48
Имя: Саяр
Поблагодарили: 1 раз

Java и ModBus RTU + RS-485

Сообщение Idelle »

Подозреваю, что ты посылаешь тупо число 255, а остальные 16185 срезаются, т.к. у byte максимальное десятичное число 255. Попробуй массивом из byte отправлять. Покупай в эту сторону в общем, в конвертацию типов данных.
Аватара пользователя

keysansa
эксперт
эксперт
Сообщения: 2471
Зарегистрирован: 20 дек 2018, 04:45
Имя: Сергей
Страна: РБ/РФ
город/регион: РФ Сергиев Посад
Благодарил (а): 2121 раз
Поблагодарили: 208 раз

Java и ModBus RTU + RS-485

Сообщение keysansa »

kolyagl писал(а): 28 авг 2019, 07:43 arrModbusCommand =modBus.ModbusCommand16( slaveAddress,(byte) 16,(byte)16385,(byte)100 );
Думаю, беда тут. Вы используете команду 16 - Write multiple registers, следует использовать команду 6 - Write single register.
ЗЫ. И да, регистра 16385 может не существовать в реализации клиента. Тест на регистр #16384.
В трансформаторной будке живет трансформаторная собака (с) Прозрачный гонщик.
Ответить

Вернуться в «Вопросы от студентов»