Anschließen von Servoantrieben in OpenWrt

Schlüsselwörter für diesen Artikel (für diejenigen, die diese Wörter nicht kennen, wird dieser Artikel wahrscheinlich nicht interessant) sind: Analog-und Digital-Servoantriebe, Steuerung von Servoantrieben, Hexapod, Droiden, Flugmodell, Automodel, Roboter; im Allgemeinen alles, was mit der Robotik verbunden ist.

Alle vorhergehenden Artikel hatten einen einführenden Charakter und öffneten die verborgenen Nutzungsmöglichkeiten der alternativen Funktionen eines Routers. Jetzt schlage ich vor, zum praktischen Teil überzugehen.

Als ich begonnen habe sich für die Robotik zu interessieren, war eine der ständigen Fragen: "wie werden die Servoantriebe gesteuert?". Dafür ist eine spezielle Steuerkarte auf einem Prozessor notwendig. Man möchte einen funktionsmächtigen Prozessor nehmen, weil man anfangs überhaupt nicht weiß, welche Aufgaben von ihm zu erfüllen sind. Daher ist die Reihenfolge der Wörter: Servoantrieb - Router — OpenWrt klingt sehr verlockend, obwohl ich auf diesen Gedanken noch vor einiger Zeit nicht gekommen wäre )))

Also wollen wir versuchen folgende Struktur, welche auf dem Bild dargestellt ist, zu realisieren:

Es ist natürlich gut einen Servoantrieb zu steuern, aber das ist nicht interessant für uns. Es ist viel wichtiger zu lernen eine Netz aus den Servoantrieben bauen. In unserem Falle tritt ein Router als ein Netzassistent der Servoantriebe. Alle Servoantriebe werden mittels Uart mit dem Assistenten verbunden. Ich verstehe, dass I2C ein Standard de facto ist, aber Uart aus irgendeinem Grund benutzerfreundlicher und flexibler für mich zu sein scheint)))

Für den Netzwerkbau der Servoantriebe brauchen wir einen USB-Uart-Adapter(wir haben ihn im Abschnitt "Debug Port" verwendet):

Auf jeden Servoantrieb wird ein kleines Platine auf dem Chip mega8 montiert, welches Befehle aufnimmt und Steuerimpulse erzeugt:

Anscheinend haben wir mit dem Hardware-Teil beendet. Wie wird solch ein Netzwerk von OpenWrt gesteuert? Natürlich gibt es eine Vielfalt von Varianten. Seit kurzer Zeit hat mir der Scriptsprache Lua gefallen. Es reicht die Kenntnisstandebene "HelloWorld" für unsere Aufgabenlösung.

Steuerungsalgorithmus.

1. Der Assistent (Router) sendet ein Paket andas Servoantriebnetzwerk(über Uart). Das Paket hat folgende Standardstruktur:
|Länge|An|Befehlsnummer|Befehlshauptteil|Kontrollsumme|
Beispiel:Es wurde ein Paket mit der Größe von 5 Bytes übergegeben: 5 1 10 179 195

2. Ein Servoantrien, für welchen dieses Paket bestimmt ist, empfängt es und antwortet mit dem folgenden Paket:
|Länge|Von|Befehlsnummer+1|Befehlshauptteil|Kontrollsumme|
Es wurde ein Paket mit der Größe von 5 Bytes empfangen: 5 1 11 0 17
Alles ist ziemlich einfach.

Softwarelösung.

Ich werde nichts über die Firmware für mega8 schreiben. Sie kann von der Webseite heruntergeladen werden und Sie können sich selber vertraut machen. Sie ist sehr einfach.

Treten wir dem Lua Script in Detail näher. Der Script sollte Folgendes machen:

1. den Port /dev/ttyUSBx aufmachen

2. den Benutzer bitten die Nummer des Servoantriebs einzugeben sowie auch den neuen Zustand für ihn

3. ein Paket mit neuen Daten erzeugen und es senden

4. eine Rückmeldung vom Servoantrieb abwarten

5. den Zustand auf Wartezustand für Eingabe der neuen Daten zu ändern oder ein Programm beenden, wobei er den Port /dev/ttyUSBx schließt.

Mit der Lua kann diese Aufgabe sehr einfach realisiert werden. Deshalb kam mir Lust an die Lua für diesen Zweck zu verwenden.

Der eintige unangenehmer Punkt in diesem Prozess ist das Fehlen der Bibliothek der Lua in OpenWrt für die Arbeit mit einem Serienport. Die Bibliothek kann hier geladen werden. Versuchen wir sie dem OpenWrt hinzufügen.

Wie ein neues Paket dem OpenWrt hinzufügen ist, wurde früher beschrieben, aber ich glaube, man kann noch einmal dies wiederholen, damit ich das auch nicht vergesse )))

1. Erstellen wir das Verzeichnis luars232 im Verzeichnis /trunk/package. Darin erstellen wir die Datei makefile, indem wir eine beliebige Datei makefile aus dem Verzeichnis /trunk/package als Basis nehmen. Unsere makefile sieht wie folgt aus:

#
# Copyright (C) 2007-2009 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#

include $(TOPDIR)/rules.mk

PKG_NAME:=luars232
PKG_VERSION:=1.0.1

PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_FIXUP:=libtool

include $(INCLUDE_DIR)/package.mk

PKG_INSTALL=1

define Package/luars232
  SECTION:=libs
  CATEGORY:=Libraries
  TITLE:=Lua lib for serial communication over rs-232
endef

define Package/luars232/description
	Lua lib for serial communication over rs-232
endef

TARGET_CFLAGS += -DLUA_USE_LINUX $(FPIC)

define Build/Configure
        $(call Build/Configure/Default, \
        CFLAGS="$(TARGET_CFLAGS)" \
        )
endef

define Build/InstallDev
	$(INSTALL_DIR) $(1)/usr/include
	$(CP) $(PKG_INSTALL_DIR)/usr/include/librs232 $(1)/usr/include/
	$(INSTALL_DIR) $(1)/usr/lib/lua
	$(CP) $(PKG_INSTALL_DIR)/usr/lib/librs232.{a,so*} $(1)/usr/lib/lua/
	$(CP) $(PKG_INSTALL_DIR)/usr/lib/luars232.{a,so*} $(1)/usr/lib/lua/	
	$(INSTALL_DIR) $(1)/usr/lib/pkgconfig
	$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/librs232.pc $(1)/usr/lib/pkgconfig/
endef

define Package/luars232/install
	$(INSTALL_DIR) $(1)/usr/lib/lua
	$(CP) $(PKG_INSTALL_DIR)/usr/lib/librs232.so* $(1)/usr/lib/
	$(CP) $(PKG_INSTALL_DIR)/usr/lib/luars232.so* $(1)/usr/lib/	
	$(CP) $(PKG_INSTALL_DIR)/usr/lib/librs232.so* $(1)/usr/lib/lua
	$(CP) $(PKG_INSTALL_DIR)/usr/lib/luars232.so* $(1)/usr/lib/lua	
endef

$(eval $(call BuildPackage,luars232))

2. Gehen wir in die make menuconfig, wählen wir die notwendigen Module und dann starten wir make V=99.
LuCI :
Collections:
<M> luci
Libraries:
<M> luars232 (Lua lib for serial communication over rs-232)

Anscheinend hätte sich alles zusammengebaut, aber die Bibliothek in luars232/bindings/lua/.libs/luars232.so wurde nicht zusammengebaut. Prüfen wir das Zusammenbau-Log im Moment der configure-Bearbeitung:

checking whether stripping libraries is possible... yes 
checking if libtool supports shared libraries... yes 
checking whether to build shared libraries... yes 
checking whether to build static libraries... yes 
checking for pkg-config... pkg-config 
checking for Lua headers and librairies with pkg-config... 
checking for Lua compiling and linking... no 
configure: WARNING: 
*** Lua (>=5.0) headers and/or librairies couldn't be found in your system. 
*** Try to install liblua, liblualib and liblua-dev with your software package manager. 
*** librs232 will be built without Lua bindings library. 
./configure: line 11780: 1: command not found 
configure: creating ./config.status 
config.status: creating Makefile 
config.status: creating src/Makefile 
config.status: creating bindings/Makefile

Wie wir sehen können, hat das Programm configure die Lua headers and/or librairies nicht gefunden. Zuerst prüfen wir deren Anwesenheit. Wenn wir das Log prüfen, können wir den Pfad, wo sie sind, sehen.
headers:"-I/trunk/staging_dir/target-mipsel_uClibc-0.9.32/usr/include"
Dort sollten folgende Datein sein: lua.h, luaconf.h, lualib.h
librairies:"-L/trunk/staging_dir/target-mipsel_uClibc-0.9.32/usr/lib"
Dort sollten folgende Datein sein: liblua.a, liblua.so, liblua.so.5.1.4, liblualib.so.

Ich habe diese Dateien, aber das configure hat diese nicht gefunden.

Jetzt habe wir herauszufinden, warum das configure diese Dateien nicht findet, obwohl diese existieren und alle Pfäde geschrieben sind. Da das configure aus der Datei configure.in generiert wird, versuchen wir die Fehlerursache in ihr zu finden....

Also habe ich folgende Zeile in der Datei configure.in gefunden:

LUA_TEST=`LT=luatest.c ; echo "#include........
if test "x$LUA_TEST" != "x0" ; then
        AC_MSG_RESULT(no)
        AC_MSG_WARN([

Ehrlich gesagt, ist es für mich schwer zu verstehen, was hier los ist )))...Aber kurz gesagt, wird eine Datei zur Prüfung erstellt, welche sich dann zusammenzubauen und zu erfüllen versucht. Und wenn dies gelingt, heißt das, dass die notwendigen Headers und Bibliotheken vorhanden sind. Daher ist es mir nicht ganz klar, wie eine Datei auf einem PS erfüllt werden kann, wenn die Bibliothek der Lua von einem Cross-Compiler für mips zusammengebaut ist. Es könnte aber sein, dass ich mich irre ))). Aber jedoch schlage ich vor eine Inversoperation für dieses if.

Es sollte wie folgt aussehen:
if !(test "x$LUA_TEST" != "x0") ; then

Starten wir make V=99 wieder und prüfen wir das Build-Log:

checking for Lua headers and librairies with pkg-config... 
checking for Lua compiling and linking... yes 
./configure: line 11780: 1: command not found 
configure: creating ./config.status 
config.status: creating Makefile 
config.status: creating src/Makefile 
config.status: creating bindings/Makefile 
config.status: creating bindings/lua/Makefile 
config.status: creating include/Makefile 
config.status: creating include/librs232/Makefile 
config.status: creating src/librs232.pc 
config.status: executing depfiles commands 
config.status: executing libtool commands 
configure: WARNING: unrecognized options: --disable-nls 

 librs232 version 0.0.1 configured successfully.

Jetzt ist alles OK und die Bibliothek hat sich zusammengebaut. Das ist mein Arbeitsarchiv (alle restlichen Dateien können dem Abschnitt «Herunterladen» entnommen werden).

Bevor die Script geschrieben wird, sind noch ein paar wichtigen Sachen zu erledigen ))

Wollen wir die Beispieldatei doc/example.lua) aus der Bibliothek prüfen. Und zwar folgende Zeilen:

-- write without timeout 
err, len_written = p:write("test") 
assert(e == rs232.RS232_ERR_NOERROR)

Wie wir sehen können, eine Zeile wird in die Funktion write transportiert. Und es ist für mich nicht ganz klar, wie das Protokoll, welches auf der Design-Stufe erstellt wurde, in diese Funktion transportiert werden kann. Natürlich kann dies irgendwie realisiert werden, aber leider weiß ich nicht wie! ((( Im Prinzip kann man das Protokoll ändern und mit den Zeilen arbeiten, aber dies ist nicht so gut. Es könnte aber anders sein.... Grundsätzlich ist ein Problem dort entstanden, wo ich nicht erwartet habe!

Die einfachste Lösung für mich war die Änderung der Funktion write in der Bibliothek, damit sie ein Datenmassiv anstatt der Zeilen empfangen könnte.

Wie dies zu machen ist? Es gibt in der Datei bindings/lua/luars232.c die Funktion static int lua_port_write(lua_State *L), welche die write-Methode aus der Lua фusführt. Machen wir ein Update:

/*
 * error, written_len = port:write(data [, timeout_ms])
 */
static int lua_port_write(lua_State *L)
{
	int ret = 0;
	int argc = 0;
	//unsigned int timeout = 0;
	unsigned int wlen = 0;
	//size_t len = 0;
	//const char *data;
	struct rs232_port_t *p = NULL;

	p = (struct rs232_port_t*) luaL_checkudata(L, 1, MODULE_NAMESPACE);
	lua_remove(L, 1);

	if (p == NULL || !rs232_port_open(p)) {
		lua_pushinteger(L, RS232_ERR_PORT_CLOSED);
		lua_pushinteger(L, 0);
		return 2;
	}

	argc = lua_gettop(L);
	
	/* моя правка. Из луа должна передоваться таблица, а не строка.
	 * Здесь происходит разбор элементов таблицы */
	switch (argc) {
		case 1:
			{
				/* заведем две переменные. длина массива и сам массив, куда
				 * будем складывать элементы таблицы из луа */
				unsigned char array_len=0, lua_array[20]={0};
				
				lua_pushnil(L);
				while (lua_next(L, argc) != 0)
				{ 
					lua_array [array_len] = (int)(lua_tonumber(L,-1));
					//printf ("value=%d\n",lua_array [array_len]);					
					array_len++;
					lua_pop(L, 1); 
				}
				ret = rs232_write(p, lua_array, array_len, &wlen);	
			}
		break;
					
		default:
			lua_pushinteger(L, RS232_ERR_CONFIG);
			lua_pushinteger(L, 0);
		return 2;		
	}

	lua_pushinteger(L, ret);
	lua_pushinteger(L, wlen);
	return 2;
}

Es hat sich herausgestellt, dass alles nicht so schlimm. Wieder vielen Dank zu dem Autor der Bibliothek.

Nun hier ist noch ein kleines Exkurs, welches ich mehr für mich selbst mache um nicht zu vergessen... Nach dem Zusammenbau der Bibliothek wäre es sinnvoll diese zu prüfen, d.h. das Programminterface der dynamischen Bibliothek zu prüfen:

1. Prüfen wir die Reaktion von dlopen mittels eines kleinen Programms:

#include 
#include 

int main (int argc, char **argv){
		void *handle;
		char *error;

		printf ("str=%s\n",argv[1]);
		handle = dlopen (argv[1], RTLD_LAZY);
		if (!handle) {
				fputs (dlerror(), stderr);
				printf ("\n");
				return (1);
		}
		printf ("handle=%p\n",handle);
		dlclose (handle);
}

root@OpenWrt:/# /home/test_dlopen /usr/lib/luars232.so 
str=/usr/lib/luars232.so 
handle=0x9dc170 

Ergebnis — die Bibliothek wurde geladen.

2. Prüfen wir die Zusammenhänge:

$ ldd luars232.so 
	linux-gate.so.1 =>  (0x00d58000) 
	librs232.so.0 => /usr/local/lib/librs232.so.0 (0x00ed9000) 
	liblua5.1.so.0 => /usr/lib/liblua5.1.so.0 (0x00a34000) 
	libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x00260000) 
	libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0x00960000) 
	libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0x00110000) 
	/lib/ld-linux.so.2 (0x0071f000) 

	$ ldd librs232.so 
	linux-gate.so.1 =>  (0x00375000) 
	libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x008f1000) 
	/lib/ld-linux.so.2 (0x00f76000) 

Ergebnis — die Zusammenhänge sind vorhanden.

Erledigt!!!! Jetzt können wir den Lua Script für die Steuerung unseres Servoantriebnetzwerkes schreiben.

Nach einiger Zeit ist der Script fertig ))). Er ist eigentlich sehr einfach und hat Vermerke fast in jeder Zeile:

--[[ Подключаем библиотеку для работы с com портом. Можно былоб
			написать просто require("luars232"), то тогда обращение бы шло
			по имени модуля luars232.RS232_BAUD_115200 ]]
rs232 = require("luars232")

local SET_NEW_STATE					=		10
local SET_NEW_STATE_ANSWER	=		11

-- Определяем имя порта
port_name = "/dev/ttyUSB1"

-- определим канал для вывода сообщений
local out = io.stderr

-- определим канал для ввода данных с клавиатуры
local user_in = io.stdin

--[[ Вызываем функцию open для открытия порта.Эта функция возвращает 
		 два значения, которые присваиваются переменным e и p
		 e - тип ошибки, p - дескриптор порта ]]
local e, p = rs232.open(port_name)

-- если ошибка открытия
if e ~= rs232.RS232_ERR_NOERROR then
	-- handle error
	out:write(string.format("can't open serial port '%s', error: '%s'\n",
			port_name, rs232.error_tostring(e)))
	return
end

-- Настраиваем порт, вызывая соотвествующие методы.Методы описаны в luars232.c
assert(p:set_baud_rate(rs232.RS232_BAUD_115200)	== rs232.RS232_ERR_NOERROR)
assert(p:set_data_bits(rs232.RS232_DATA_8)			== rs232.RS232_ERR_NOERROR)
assert(p:set_parity(rs232.RS232_PARITY_NONE)		== rs232.RS232_ERR_NOERROR)
assert(p:set_stop_bits(rs232.RS232_STOP_1)			== rs232.RS232_ERR_NOERROR)
assert(p:set_flow_control(rs232.RS232_FLOW_OFF)	== rs232.RS232_ERR_NOERROR)

out:write(string.format("OK, port open with values '%s'\n", tostring(p)))

--[[ Порт настроен. Можно осуществлять обмен данными. Алгоритм управления 
   сервой следующий: 1. Мастер посылает пакет в котором указывается номер
   сервы и то состояние в которое она должна перейти. 2. Серва отвечает
   мастеру что пакет получен и команда исполнена
   Протокол общения:                                      
		Запрос:                                                
		|Длина|Кому|№команды|Тело|Кс|
		Ответ:                                                 
		|Длина|ОтКого|№команды+1|Тело|Кс| ]]

-- бесконечный цикл		
while true do		
	local input_error
	
	repeat
		out:write (string.format("Введите номер сервы(0-10) и положение(0-180) или q для выхода\n"))
		out:write (string.format("Пример:0 90 (выставить серву №0 в положение 90 градусов)\n"))

		-- Считаем данные которые ввел пользователь
		local keyboard_input = user_in:read()

		-- Разберем данные которые ввел пользователь
		input_args = {}
		local cnt=0
		for next_word in string.gmatch(keyboard_input, "%w+") do
			-- поместим в таблицу введеный символ
			table.insert (input_args,next_word)
			cnt = cnt + 1

			if (cnt >= 2) then
				break
			end
		end
	
		-- проверим корректность введеных данных
		if cnt < 2 or tonumber(input_args[1]) == nil or tonumber(input_args[2]) == nil then
			if input_args[1] == "q" then
				input_error = 0
				exit_flag   = 1;	-- выставим флаг что пользователь хочет выйти из проги
			else
				out:write (string.format("Ошибка ввода - нужно повторить ввод!\n"))
				input_error = 1
			end
		else
			exit_flag   = 0
			input_error = 0
		end
		
	until input_error == 0
	
	if (exit_flag == 1) then
		out:write (string.format("Выходим из программы...\n"))
		break;
	end
	
	--[[ сформируем буфер для отправки
		Запрос:                                                
		|Длина|Кому|№команды|Тело|Кс| ]]
		
	local tx_buf={5}
	table.insert (tx_buf,input_args[1])
	table.insert (tx_buf,SET_NEW_STATE)
	table.insert (tx_buf,input_args[2])
	table.insert (tx_buf,(tx_buf[1]+tx_buf[2]+tx_buf[3]+tx_buf[4])%0xff)

	-- Посылаем пакет
	err, len_written = p:write(tx_buf)
	assert(e == rs232.RS232_ERR_NOERROR)
	
	-- выведем на экран то что послали
	out:write (string.format(">Передан пакет %d байт:",len_written))
	for i=1,len_written,1 do
		out:write(string.format(" %d",tx_buf[i])) 
	end
	out:write(string.format("\n"))	

	-- Ждем ответа

	-- предположим что максимальный пакет не может быть больше 100 байт
	local read_len = 100 

	-- ждать ответа будем 100мс
	local timeout = 100

	-- запускаем функцию чтения данных из порта
	local err, data_read, size = p:read(read_len, timeout,1)
	assert(e == rs232.RS232_ERR_NOERROR)

	-- выведем на экран то что получили через уарт
	out:write(string.format("<Принят пакет %d байт:",size))
	for i=1,size,1 do
		out:write(string.format(" %d",string.byte(data_read,i))) 
	end
	out:write(string.format("\n"))

end

-- close
assert(p:close() == rs232.RS232_ERR_NOERROR)

Booten wir und installieren die Pakete.

root@OpenWrt:/# opkg install luci luars232 
Installing luci (0.10+svn6982-1) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/luci_0.10+svn6982-1_brcm47xx.ipk. 
Installing uhttpd (22) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/uhttpd_22_brcm47xx.ipk. 
Installing luci-mod-admin-full (0.10+svn6982-1) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/luci-mod-admin-full_0.10+svn6982-1_brcm47xx.ipk. 
Installing luci-mod-admin-core (0.10+svn6982-1) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/luci-mod-admin-core_0.10+svn6982-1_brcm47xx.ipk. 
Installing luci-lib-web (0.10+svn6982-1) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/luci-lib-web_0.10+svn6982-1_brcm47xx.ipk. 
Installing luci-lib-core (0.10+svn6982-1) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/luci-lib-core_0.10+svn6982-1_brcm47xx.ipk. 
Installing lua (5.1.4-7) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/lua_5.1.4-7_brcm47xx.ipk. 
Installing liblua (5.1.4-7) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/liblua_5.1.4-7_brcm47xx.ipk. 
Installing libuci-lua (2011-03-27.2-1) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/libuci-lua_2011-03-27.2-1_brcm47xx.ipk. 
Installing luci-lib-sys (0.10+svn6982-1) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/luci-lib-sys_0.10+svn6982-1_brcm47xx.ipk. 
Installing luci-lib-nixio (0.10+svn6982-1) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/luci-lib-nixio_0.10+svn6982-1_brcm47xx.ipk. 
Installing luci-sgi-cgi (0.10+svn6982-1) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/luci-sgi-cgi_0.10+svn6982-1_brcm47xx.ipk. 
Installing luci-lib-lmo (0.10+svn6982-1) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/luci-lib-lmo_0.10+svn6982-1_brcm47xx.ipk. 
Installing luci-i18n-english (0.10+svn6982-1) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/luci-i18n-english_0.10+svn6982-1_brcm47xx.ipk. 
Installing luci-lib-ipkg (0.10+svn6982-1) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/luci-lib-ipkg_0.10+svn6982-1_brcm47xx.ipk. 
Installing luci-theme-openwrt (0.10+svn6982-1) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/luci-theme-openwrt_0.10+svn6982-1_brcm47xx.ipk. 
Installing luci-theme-base (0.10+svn6982-1) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/luci-theme-base_0.10+svn6982-1_brcm47xx.ipk. 
Installing luci-app-firewall (0.10+svn6982-1) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/luci-app-firewall_0.10+svn6982-1_brcm47xx.ipk. 
Installing luci-app-initmgr (0.10+svn6982-1) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/luci-app-initmgr_0.10+svn6982-1_brcm47xx.ipk. 
Installing libiwinfo (13) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/libiwinfo_13_brcm47xx.ipk. 
Installing luars232 (1.0.1) to root... 
Downloading ftp://ftp:ftp@192.168.0.9/luars232_1.0.1_brcm47xx.ipk. 
Configuring luci-lib-sys. 
Configuring liblua. 
Configuring libuci-lua. 
Configuring lua. 
Configuring luci-lib-core. 
Configuring luci-lib-nixio. 
Configuring luci-sgi-cgi. 
Configuring luci-lib-lmo. 
Configuring luci-lib-web. 
Configuring luci-i18n-english. 
Configuring luci-mod-admin-core. 
Configuring libiwinfo. 
Configuring luci-theme-base. 
Configuring luci-theme-openwrt. 
Configuring luci-app-firewall. 
Configuring luci-lib-ipkg. 
Configuring luci-mod-admin-full. 
Configuring luars232. 
Configuring uhttpd. 
Configuring luci-app-initmgr. 
Configuring luci. 

Wollen wir die Script testen. Starten wir sie:

root@OpenWrt:/# lua /home/ServoManager/ServoManager.lua 
OK, port open with values 'device: /dev/ttyUSB0, baud: 115200, data bits: 8, parity: none, stop bits: 1, flow control: off' 
Введите номер сервы(0-10) и положение(0-180) или q для выхода 
Пример:0 90 (выставить серву №0 в положение 90 градусов) 
1 179 
>Передан пакет 5 байт: 5 1 10 179 195 
<Принят пакет 5 байт: 5 1 11 0 17 
Введите номер сервы(0-10) и положение(0-180) или q для выхода 
Пример:0 90 (выставить серву №0 в положение 90 градусов) 
^[[A 
Ошибка ввода - нужно повторить ввод! 
Введите номер сервы(0-10) и положение(0-180) или q для выхода 
Пример:0 90 (выставить серву №0 в положение 90 градусов) 
1 10 
>Передан пакет 5 байт: 5 1 10 10 26 
<Принят пакет 5 байт: 5 1 11 0 17 
Введите номер сервы(0-10) и положение(0-180) или q для выхода 
Пример:0 90 (выставить серву №0 в положение 90 градусов) 
q 
Выходим из программы... 
root@OpenWrt:/# 

Sie funktioniert und das ist cool!



Bestellen Sie Servoantriebe bei uns:

Servoantriebe