![]() |
|
|
#51 |
|
Junior Member
Регистрация: 19.12.2012
Адрес: Марбелья
Сообщений: 18
Вес репутации: 0 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
В качестве сервера работал роутер TP-Link TL-MR3220 v1, на котором установлен OpenWrt Attitude Adjustment 12.09-rc1.
libmodbus для роутера можно установить стандартными средствами (opkg install libmodbus) Тестовая программа (unit-test-client) собиралась стандартными средствами OpenWrt на Ubuntu. В качестве клиента работал LaunchPad MSP430 ( IDE energia-0101E0009 ), здесь работал немного модифицированный скетч из четвёрторо поста. Дело в том, что у LaunchPad есть два встроенных светодиода и датчик температуры. Вот их-то и задейсвовал. Slave ID = 1 Декларировано 10 регистров. Первый (0) и второй (1) регистр управляет включением-выключением светодиодов. Последний регистр (9) читает температуру процессора с встроенного термодатчика. В остальные регисры пишутся случайные числа. Исходник программы на C - Код:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <modbus.h>
#include "unit-test.h"
#define SL_ID 1
int main(int argc, char *argv[])
{
uint16_t tab_reg[64];
modbus_t *ctx;
int i, n , rc;
ctx = modbus_new_rtu("/dev/ttyACM0", 9600, 'N', 8, 1);
if (ctx == NULL) {
fprintf(stderr, "Unable to allocate libmodbus context\n");
return -1;
}
modbus_set_debug(ctx, TRUE);
modbus_set_error_recovery(ctx,
MODBUS_ERROR_RECOVERY_LINK |
MODBUS_ERROR_RECOVERY_PROTOCOL);
modbus_set_slave(ctx, SL_ID);
if (modbus_connect(ctx) == -1) {
fprintf(stderr, "Connection failed: %s\n",
modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
printf("** UNIT TESTING **\n");
printf("\nTEST WRITE/READ:\n");
tab_reg[0] = 0;
tab_reg[1] = 1;
for ( n=0 ; n<100 ; n++ ) {
rc = modbus_read_registers(ctx, 0, 10, tab_reg);
if (rc == -1) {
fprintf(stderr, "%s\n", modbus_strerror(errno));
return -1;
}
for (i=0; i < rc; i++) {
printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
}
if (tab_reg[0] == 1) tab_reg[0]=0; else tab_reg[0]=1;
if (tab_reg[1] == 1) tab_reg[1]=0; else tab_reg[1]=1;
tab_reg[2] = rand();
tab_reg[3] = rand();
tab_reg[4] = rand();
tab_reg[5] = rand();
tab_reg[6] = rand();
tab_reg[7] = rand();
tab_reg[8] = rand();
rc = modbus_write_registers(ctx, 0, 10, tab_reg);
if (rc == -1) {
fprintf(stderr, "%s\n", modbus_strerror(errno));
return -1;
}
for (i=0; i < rc; i++) {
printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
}
sleep(1);
}
/* Close the connection */
modbus_close(ctx);
modbus_free(ctx);
return 0;
}
Код:
#include <Modbusino.h>
const int ledPin_g = GREEN_LED;
const int ledPin_r = RED_LED;
const int RL0 = GREEN_LED;
const int RL1 = RED_LED;
const int RL2 = 12;
const int RL3 = 13;
const int rl_arr[] = { RL0,RL1,RL2,RL3 };
const int regs = 10; // количество регистров
const int ID_slave = 1;
uint16_t tab_reg[regs]; //задаем массив регистров
// Инициализация SLAVE, идентификатор (адрес) в сети ID = 1
ModbusinoSlave modbusino_slave(ID_slave);
// на цифр. выходы сразу записываем значение регистров
// любое значение > 0 это HIGH, 0 - LOW
void SetRelay() {
int i;
for (i = 0; i < 4; i++) {
digitalWrite(rl_arr[i], tab_reg[i]);
}
}
void setup() {
modbusino_slave.setup(9600);
// установка цифровых вх/вых в режим выхода
pinMode(RL0, OUTPUT);
pinMode(RL1, OUTPUT);
pinMode(RL2, OUTPUT);
pinMode(RL3, OUTPUT);
}
void loop() {
modbusino_slave.loop(tab_reg, regs);
SetRelay();
tab_reg[9] = analogRead(TEMPSENSOR); //запись аналогового значения в 9-ый регистр
}
Код:
root@zuriuslev:~# /home/ServoManager/ACM0/unit-test-client Opening /dev/ttyACM0 at 9600 bauds (N, 8, 1) ** UNIT TESTING ** TEST WRITE/READ: [01][03][00][00][00][0A][C5][CD] Waiting for a confirmation... <01><03><14><00><00><00><01><99><38><E8><E0><CA><79><5C><4D><EA><3D><1A><34><5D><BC><01><3E><40><7D> reg[0]=0 (0x0) reg[1]=1 (0x1) reg[2]=39224 (0x9938) reg[3]=59616 (0xE8E0) reg[4]=51833 (0xCA79) reg[5]=23629 (0x5C4D) reg[6]=59965 (0xEA3D) reg[7]=6708 (0x1A34) reg[8]=23996 (0x5DBC) reg[9]=318 (0x13E) [01][10][00][00][00][0A][14][00][01][00][00][45][67][23][C6][98][69][48][73][DC][51][5C][FF][94][4A][01][3E][6A][82] Waiting for a confirmation... <01><10><00><00><00><0A><40><0E> reg[0]=1 (0x1) reg[1]=0 (0x0) reg[2]=17767 (0x4567) reg[3]=9158 (0x23C6) reg[4]=39017 (0x9869) reg[5]=18547 (0x4873) reg[6]=56401 (0xDC51) reg[7]=23807 (0x5CFF) reg[8]=37962 (0x944A) reg[9]=318 (0x13E) [01][03][00][00][00][0A][C5][CD] Метод отлично работает ! LaunchPad MSP430 весело моргает светодиодами и показывает изменения температуры ![]() Програмка для роутера в аттачменте |
|
|
|
|
|
#52 |
|
Administrator
Регистрация: 12.04.2010
Адрес: Москва
Сообщений: 9,618
Вес репутации: 9824 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Программу для роутера не совсем понял как запускать?
|
|
|
|
|
|
#53 |
|
Junior Member
Регистрация: 19.12.2012
Адрес: Марбелья
Сообщений: 18
Вес репутации: 0 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Хочу управлять шиной при помощи PHP.
НО ! для PHP, нашел вразумительные классы только для ModBus TCP, для ModBus RTU, ничего нет. Начал рыться и наткнулся на замечательную программу - Free MODBUS/TCP to MODBUS/RTU gateway Действительно ! скомпилировал, запустил на роутере (mbusd -d -v9 -L- -p/dev/ttyACM0 -s9600 -P502) и подключился уже с виндозы, через ModbusPoll. Всё работает ! ![]() Даже собрал .ipk для OpenWrt. Завтра продолжу уже из PHP. |
|
|
|
|
|
#54 |
|
Junior Member
Регистрация: 19.12.2012
Адрес: Марбелья
Сообщений: 18
Вес репутации: 0 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Скопировать на роутер. (Например в /usr/bin)
Сделать "chmod 755 /usr/bin/unit-test-client" и запустить unit-test-client ![]() Немножко доработал прогу, новое название mbtest Usage: mbtest [-p name] [-s value] [-e value] -p<name> set serial port device name (default /dev/ttyACM0) -s<value> set serial port speed (default 9600) -e<value> set slave id (default 1) Т.Е можно изменять порт, скорость и номер слейв устройства, запуск без параметров эквивалентен комманде - mbtest -p ttyACM0 -s 9600 -e 1 список параметров - mbtest -h комплект прилагается. Последний раз редактировалось zuriuslev; 20.12.2012 в 02:15. |
|
|
|
|
|
#55 |
|
Senior Member
Регистрация: 16.09.2012
Адрес: Irkutsk
Сообщений: 555
Вес репутации: 1606 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Отлично наш человек!
PHP хорошо работает через сокеты. Вот пример клиента: PHP код:
PHP код:
Код:
Arduino (slave) <---> Modbus RTU (Master) - Sokcet TCP(Server) <---> PHP Socket TCP (Client) -- Web страница Хотя если использовать библиотеки от нашей версии то... Последний раз редактировалось andr128; 20.12.2012 в 15:08. |
|
|
|
|
|
#56 |
|
Senior Member
Регистрация: 16.09.2012
Адрес: Irkutsk
Сообщений: 555
Вес репутации: 1606 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Для тех кто хочет поуправлять ардуиной с Web сервера (без модбас) можно использовать шлюз server serial-tcp: ser2net (есть в репозитории) или suart.
Стучаться к нему соответственно через сокет (пример на PHP выше) указав порт TCP. Пример html страницы. (Используется JQuery, JSON, AJAX - фоновое обновление параметров): Код HTML:
<html> <head> <meta http-equiv="Content-Type" content="text/html; Charset=UTF-8"> <script type="text/javascript" src="jquery.js"></script> </head> <body> <div id="info">Загрузка...</div> <script> function json_example() { $.getJSON('client_socket.php', function(data) { s = ""; $.each(data, function(key, val) { s= s + key+' = ' + val + '<br/>' }); $("#out").html(s) }); } setInterval(json_example, 1000); //вызывать скрипт через 1 с // json_example(); //вызвать 1 раз </script> <div id="out"></div> </body> </html> Пример вывода отдельных элементов массива текстовой структуры JSON Код HTML:
<html> <head> <meta http-equiv="Content-Type" content="text/html; Charset=UTF-8"> <script type="text/javascript" src="jquery.js"></script> </head> <body> <div id="info"> Данные с сервера php </div> <script> function json_example() { $.getJSON('client_socket.php', function(data) { $("#out").html(" ID : " +data.id+"<br>"+ " Server : " +data.server+"<br>"+ " Time : " +data.time); } ); } setInterval(json_example, 1000); //вызывать скрипт через 1000 мс </script> <div id="out"></div> <!-- сюда будет выводится страница --> </body> </html> Последний раз редактировалось andr128; 26.01.2013 в 08:21. |
|
|
|
|
|
#57 |
|
Senior Member
Регистрация: 16.09.2012
Адрес: Irkutsk
Сообщений: 555
Вес репутации: 1606 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
PHP код:
|
|
|
|
|
|
#58 |
|
Member
|
ANDR128 Пример сервера для работы с сокетами:
Скрипт написан на PHP--??? |
|
|
|
|
|
#59 | |
|
Senior Member
Регистрация: 16.09.2012
Адрес: Irkutsk
Сообщений: 555
Вес репутации: 1606 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Цитата:
Пример клиента написан на PHP. Для более полного понимания нарисовал картинку Последний раз редактировалось andr128; 20.12.2012 в 17:50. |
|
|
|
|
|
|
#60 |
|
Junior Member
Регистрация: 19.12.2012
Адрес: Марбелья
Сообщений: 18
Вес репутации: 0 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
|
|
|
|
![]() |
| Здесь присутствуют: 5 (пользователей: 0 , гостей: 5) | |
|
|