Dodajemy diody LED i przycisk do RouterStation Pro.

RouterStation Pro firmy Ubiquiti jest świetną platformą dla osób lubiących grzebać zarówno w oprogramowaniu(firmware) oraz samej elektronice. Należę właśnie do takich osób, zawsze lubiłem majsterkować, tworzyć coś własnego :-) Dlatego też wyprzedałem inne bezużyteczne zabawki i zakupiłem RSPRO. Warto! Oprócz naprawdę potężnego procesora (jak na współczesne routery) i sporej pamięci typu NAND i RAM dostajemy kilka linii GPIO do własnego wykorzystania. W tym artykule właśnie dla GPIO poświecę najwięcej miejsca.

GPIO (ang. General Purpose Input/Ouptut) to fizycznie pin - „nóżka” procesora, która może działać jako wejście lub wyjście. W RouterStation Pro dostępne jest 7 linii GPIO do własnego wykorzystania.

Ogólne założenia

Pora przejść do praktyki. Wykorzystamy kilka linii GPIO i podłączymy dwie diody LED i jeden przycisk. Pierwsza dioda LED to w zasadzie trzy, bo jest to RGB(Czerwona/Zielona/Niebieska). Jeżeli komuś szkoda trzech linii dla jednej diody można zastosować trzy rożne, nie ma problemu. Po prostu uwielbiam diody takiego tylu i taką zastosowałem. „Lampka” RGB jest ze wspólna anodą, o średnicy 5mm. Druga dioda jest koloru czerwonego o średnicy 3mm, w sam raz na „heartbeat” (o czym dalej). Przycisk jaki zastosowałem to normalnie otwarty, czyli daje przejście w obwodzie po jego wciśnięciu. Opisuje to ponieważ będzie to miało swoje odzwierciedlenie w kodzie jaki będziemy modyfikować.

Ważną sprawą w przypadku diod LED jest żeby nie podłączać ich bezpośrednio do pinów GPIO i GND/VCC. Należy zastosować rezystor ograniczający. Taki rezystor spełnia dwa zadania, ogranicza napięcie do potrzebnego dla diody oraz eliminuje zwarcie. Rezystor jest bardzo łatwo wyliczyć z prawa Ohma. Wystarczy odjąć napięcie zasilania od napięcia przewodzenia i podzielić przez prąd przewodzenia diody. Dla diody LED 3mm będzie to 3.3V-1.9V/0,02A. Z obliczeń wynika, że musimy zastosować co najmniej rezystor 70OM. Ciężko zdobyć taki rezystor w jednym elemencie, dlatego stosujemy 100OM. Jednak nie zalecałbym tego akurat w tym zastosowaniu, gdyż taka dioda będzie świecić ze swoją pełna mocą, co może w nocy fajnie oświetlać pokój :-) Proponuje te wartość 3-krotnie zwiększyć, rezystor na poziomie 200-300OM jest w sam raz. W przypadku diody RGB należy dobrać rezystory na każdą katodę(3). Ogólnie w przypadku diody RGB podłączenie będzie nieco inne, gdyż anodę(+) podłączamy do zasilania, a katody(-) do trzech oddzielnych GPIO. Podłączenie odwrotne z jednym sygnałem z GPIO załączało by trzy diody naraz, a tego nie chcemy. Zastosowanie RGB ze wspólna katodą odwróciło by to wszystko co wyżej napisałem. W przypadku przycisku również należy zastosować rezystor, tutaj będzie zabezpieczał przez bezpośrednim zwarciem masy z GPIO.

Modyfikujemy kod

Załóżmy, że mamy już wszystko polutowane, przejdźmy do sprawy programowej. Kod źródłowy na którym bazuje port RouterStation Pro jest na licencji GPL, tak więc zgodnie z jej treścią możemy go modyfikować. W naszym przypadku modyfikacjom ulegnie tylko jeden plik – mach-ubnt.c. Poniżej zamieszczam patch z modyfikacjami:

--- a/arch/mips/ar71xx/mach-ubnt.c	2010-04-03 08:51:26.000000000 +0200
+++ b/arch/mips/ar71xx/mach-ubnt.c	2010-11-28 17:50:31.477281669 +0100
@@ -22,6 +22,11 @@
 #include "dev-usb.h"
 
 #define UBNT_RS_GPIO_LED_RF	2
+#define UBNT_RS_GPIO_LED_C0	0
+#define UBNT_RS_GPIO_LED_C1	1
+#define UBNT_RS_GPIO_LED_C2	3
+#define UBNT_RS_GPIO_LED_HB	4
+#define UBNT_RS_GPIO_CB0	7
 #define UBNT_RS_GPIO_SW4	8
 
 #define UBNT_LS_SR71_GPIO_LED_D25	0
@@ -45,6 +50,22 @@
 		.name		= "ubnt:green:rf",
 		.gpio		= UBNT_RS_GPIO_LED_RF,
 		.active_low	= 0,
+	}, {
+		.name		= "ubnt:red:c0",
+		.gpio		= UBNT_RS_GPIO_LED_C0,
+		.active_low	= 1,
+	}, {
+		.name		= "ubnt:green:c1",
+		.gpio		= UBNT_RS_GPIO_LED_C1,
+		.active_low	= 1,
+	}, {
+		.name		= "ubnt:blue:c2",
+		.gpio		= UBNT_RS_GPIO_LED_C2,
+		.active_low	= 1,
+	}, {
+		.name		= "ubnt:red:hb",
+		.gpio		= UBNT_RS_GPIO_LED_HB,
+		.active_low	= 0,
 	}
 };
 
@@ -108,6 +129,13 @@
 		.threshold	= 3,
 		.gpio		= UBNT_RS_GPIO_SW4,
 		.active_low	= 1,
+	}, {
+		.desc		= "cb0",
+		.type		= EV_KEY,
+		.code		= BTN_1,
+		.threshold	= 3,
+		.gpio		= UBNT_RS_GPIO_CB0,
+		.active_low	= 1,
 	}
 };
 

Plik z patchem można pobrać stąd.

Wykorzystujemy cztery GPIO do podłączania diod LED. Pierwsze trzy(0-2) dla diody RGB, oraz 4 dla diody 3mm czerwonej (GPIO 2 pomijamy bo tam podpieta jest dioda RF). Na początku definiujemy nazwę GPIO oraz pin. Nazwa sprawa dowolna, pin już nie. Następnie w strukturze gpio_led ubnt_rs_leds_gpio[] dokładnie definiujemy jak nasze GPIO będzie widoczne w systemie. Nazewnictwo (.name) zgodnie z przyjętą konwencją platforma:kolor:przeznaczenie. Pozycja .active_low oznacza stan jaki ma panować na wyjściu w stanie spoczynku. W tym przypadku jest 1 ponieważ dioda LED będzie załączana stanem niskim na wyjściu. W przypadku diody 3mm jest już „normalnie”. W stanie spoczynku panuje 0 i załączamy 1, czyli 5V na GPIO. W przypadku przycisku jest podobnie. Definicja nazwy, pinu GPIO i potem bardziej szczegółowy opis przycisku. Ważne tutaj jest poprawne wpisanie nazwy (.code), .desc, który jest aliasem(skrótem) do .code oraz .gpio. Możemy się posługiwać obiema nazwami w OpenWrt. U mnie jest to BTN_1 oraz cb0 od „custom button”. .active_low musi być 1 przy zastosowaniu przycisku zwiernego, przy rozwiernym dajemy 0 i podłączamy przycisk miedzy GPIO, a VCC.

Ostatecznie, mamy 4 diody nazwane: ubnt:red:c0, ubnt:green:c1, ubnt:blue:c2, ubnt:red:hb, oraz przycisk cb0. Tymi nazwami będziemy się posługiwać konfigurując odpowiednie sekcje w /etc/config/system

Pozostaje umieścić patch w target/linux/ar71xx/patches-2.6.3X/ pod nazwą 1000-custom-buttons-and-leds.patch i skompilować od nowa OpenWrt, wykonując make clean, gdyż kernel będzie paczowany.

Podłączamy podzespoły

Poniżej zamieszczam schemat ideowy. Przewody zaznaczone kolorem białym oznaczają masy, kolorem niebieskim sygnały z GPIO, kolor żółty to zworka przy GP7 wymuszająca stan wysoki. Konieczna jest do poprawności działania przycisku. Po poprawnym podłączeniu należy wgrać uprzednio skompilowany firmware.

Konfiguracja w OpenWrt

Przydało by się sprawdzić czy dodane elementy działają. W przypadku przycisku tworzymy prosty skrypt w /etc/hotplug.d/button o nazwie button i zawartości:

#!/bin/sh
logger $BUTTON
logger $ACTION

Potem tylko

logread -f

I ciskamy przyciska ;-) U mnie pokazuje się w logu:

Jan  1 23:56:58 OpenWrt user.notice root: BTN_1
Jan  1 23:56:58 OpenWrt user.notice root: pressed
Jan  1 23:56:59 OpenWrt user.notice root: BTN_1
Jan  1 23:56:59 OpenWrt user.notice root: released

Działa!

Sprawdźmy „lampki”:

  • ubnt:red:c0
echo 1 > /sys/class/leds/ubnt:red:c0/brightness (zapala się czerwona dioda RGB)
echo 0 > /sys/class/leds/ubnt:red:c0/brightness (gaśnie)
  • ubnt:green:c1
echo 1 > /sys/class/leds/ubnt:green:c1/brightness (zapala się zielona dioda RGB)
echo 0 > /sys/class/leds/ubnt:green:c1/brightness (gaśnie)
  • ubnt:blue:c2
echo 1 > /sys/class/leds/ubnt:blue:c2/brightness (zapala się niebieska dioda RGB)
echo 0 > /sys/class/leds/ubnt:blue:c2/brightness (gaśnie)
  • ubnt:red:hb
echo 1 > /sys/class/leds/ubnt:red:hb/brightness (zapala się czerwona dioda 3mm)
echo 0 > /sys/class/leds/ubnt:red:hb/brightness (gaśnie)

U mnie działają wszystkie :)

Należało by przyjąć jakieś funkcje dla nowo dodanych elementów. W moim przypadku dioda czerwona 3mm (ubnt:red:hb) będzie odzwierciedleniem obciążenia systemu. Przydzielę jej trigger heartbeat i będzie sobie spokojnie migać jak alarm w aucie :P Gdy router dostanie w kość to trochę ożywi się :-D Oto konfiguracja:

uci add system led
uci set system.@led[-1].name=HB
uci set system.@led[-1].trigger='heartbeat'
uci set system.@led[-1].sysfs='ubnt:red:hb'
uci commit system

Pod przycisk przypiszę ogólnie już oklepany pomysł - włączanie i wyłączanie wifi. Konfiguracja:

uci add system button
uci set system.@button[-1].button=BTN_1
uci set system.@button[-1].action=released
uci set system.@button[-1].handler="logger wifi on; uci set wireless.radio0.disabled=0;wifi"
uci set system.@button[-1].min=1
uci set system.@button[-1].max=3

uci add system button
uci set system.@button[-1].button=BTN_1
uci set system.@button[-1].action=released
uci set system.@button[-1].handler="logger wifi off; uci set wireless.radio0.disabled=1;wifi"
uci set system.@button[-1].min=3
uci set system.@button[-1].max=5
uci commit system

Przytrzymanie przycisku na 1-3sek włącza radio, a na 3-5sek wyłącza.

Pod diodę RGB koloru niebieskiego przypiszę aktywność wsadzonego urządzenia USB. Przykład pliku /etc/hotplug.d/usb/10-usb:

#!/bin/sh

case "$ACTION" in
	add)
		echo 1 > /sys/class/leds/ubnt:blue:c2/brightness
		;;
	remove)
		echo 0 > /sys/class/leds/ubnt:blue:c2/brightness
		;;
esac	

Zaznaczę, że to tylko przykłady i docelowe funkcje należy sobie przydzielić wg. własnych potrzeb.

Podsumowanie

Takim oto sposobem wykorzystaliśmy klika linii GPIO. Chciałem w artykule przedstawić zastosowanie które będzie w sposób maksymalny wykorzystywało zintegrowanie z systemem OpenWrt. Chodzi mi tutaj o sposób konfiguracji w /etc/config/system.

Żeby w ogóle sterować GPIO nie trzeba modyfikować kodu, wystarczy tylko uaktywnić GPIO w /sys/class/gpio i dalej nim sterować. Jednak tutaj nie wykorzystalibyśmy zdarzeń jakie zachodzą w systemie (heardbeat, aktywność na interfejsie) w sposób tak łatwy jak to jest domyślnie.

Przytoczone zastosowanie to tylko przedbiegi przez poważnymi projektami. Można spróbować podłączyć inne elementy elektroniczne, jak przekaźniki i załączać nimi inne urządzenia. Możliwości jest wiele.

przerobki/ledy-przyciski-w-rspro.txt · ostatnio zmienione: 2011/01/24 12:09 przez arteq
CC Attribution-Noncommercial-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki Recent changes RSS feed Valid XHTML 1.0
Profesjonalny Hosting