DIE DOKU IST GERADE AM ENTSTEHEN...
Info
Ziel dieses Projektes ist es einen Router im mehrere digitale Input / Outputs zu erweitern. Das Projekt soll so billig und einfach wie möglich realisierbar sein. Die benötigte Hardware besteht aus Standardbauteile die fast überall gekauft werden können.
Hardware
- Ein Router der mit OpenWRT geflasht werden kann
- mit RS232 auf dem Board
- Ein Mikrocontroller mit passender Anzahl IO-Ports
- Ein Quarz mit 3.6864MHz für den Mikrcontroller
- Einen Programmer für den Mikrocontroller
- Kleinzeugs wie Kabel, Wannenstecker, 2 Kondensatoren, Lüsterklemme
HowTo
Hardware
Modifikationen am Router
Das Projekt basiert auf dem TP-Link 741 Router. Dieser wurde ausgewählt weil er der billigste Router war der lokal im Geschäft gekauft werden konnte und der OpenWRT tauglich ist. Informationen zu OpenWRT auf diesem Gerät findet sich auf http://wiki.openwrt.org/toh/tp-link/tl-wr741nd.
Um den Mikrocontroller anzuschließen wird der serielle Anschluss auf dem Routerboard verwendet. Die Position des Ports ist auf dem oben genannten link zu OpenWRT klar zu erkennen. Auf diesem Port befindet sich standardmäßig eine Rootshell die deaktiviert werden sollte. Mehr dazu im Software Kapitel. Man kann die Kabel für die serielle Verbindung direkt an die Lötstellen der Platine löten oder kleine Metallpins einsetzen. Die Pins erlauben es einen Stecker für die Verbindung mit dem Controller zu verwenden. Die Pins können etwas schwierig zu löten sein, da der Masse Pin die Wärme sehr stark ableitet.
Mikrocontroller Platine
Die Spannungsversorgung erhält der Controller über die 3,3V Leitung die neben den RS232 Pins auf dem Routerboard zu finden ist. Dies erspart ein zusätzliches Netzteil.
Die Controllerplatine besteht aus nicht viel mehr als einem AVR Controller der mit 3,3V VCC zurecht kommt. Da der Router nicht sehr tolerant ist beim RS232 Timing, musste der Controller mit einem Quarz ausgestattet werden. ...
Router Datei:IOrouter gehaeuse.jpg öffnen, und Pins für den seriellen Datei:IOrouter SeriellPins.jpg Anschluss anlöten. Gehäuse muss modifiziert Datei:IOrouter gehaeueseMod.jpg werden, damit das serielle Kabel zum Mikrocontollerboard geführt werden kann.
Ein Verbinungskabel Mikrocontoller zum Seriellenanschluss erstellen
Eine Platine mit dem Mikrocontroller bauen. Die OutputPins des Mikrocontoller mit der Lüsterklemme verbinden.
Software
Software
Installation
Über das Web-UI aus den eingestellten Paketqueuellen
- ser2net (Version 2.7-2)
Konfiguration
Auf der seriellen Konsole läuft für Recoveryzwecke ein Shell die deaktiviert werden muss. Dies erreicht man indem man in der Datei /etc/inittab folgende 2 Zeilen auskommentiert:
#tts/0::askfirst:/bin/ash --login #ttyS0::askfirst:/bin/ash --login
In der Konfigurationsdatei /etc/ser2net.conf von ser2net aktiviert man folgende Konfiguration. Alle weiteren können auskommentiert werden:
2001:raw:120:/dev/ttyS0:9600 NONE 1STOPBIT 8DATABITS -XONXOFF -LOCAL -RTSCTS
Startup Script
File: /etc/init.d/ser2net
#!/bin/ash /etc/rc.common # Copyright (C) 2006 OpenWrt.org START=99 start() { /usr/sbin/ser2net sleep 1 nc localhost 2001 & sleep 1 ; killall nc for i in 0 1 2 3 4 5 ; do echo "ollpec${i}o" | nc localhost 2001 ; sleep 1 done echo 'ollpec6i' | nc localhost 2001 ; sleep 1 echo 'ollpew0h' | nc localhost 2001 ; sleep 1 echo 'ollpew0l' | nc localhost 2001 ; sleep 1 # clear data # nc localhost 2001 &; sleep 1 ; killall nc } stop() { killall ser2net }
Das Skript muss auch in den Startvorgang ganz zum Schluss angetriggert werden.
cd /etc/rc.d/ ln -s ../init.d/ser2net S99ser2net
Controller Code
/* control software for "find name" ports to control are 8, 7, 6, 5 accepts only messages with the prefix: ollpe */ int CMD_MAX = 128; char myCmd[128]; int port; char booted = 0; // bool variable void setup(){ resetPorts(); Serial.begin(9600); Serial.println("booted"); } void resetPorts() { pinMode(8, INPUT); pinMode(7, INPUT); pinMode(6, INPUT); pinMode(5, INPUT); pinMode(4, INPUT); pinMode(3, INPUT); pinMode(2, INPUT); digitalWrite(8, LOW); digitalWrite(7, LOW); digitalWrite(6, LOW); digitalWrite(5, LOW); digitalWrite(4, LOW); digitalWrite(3, LOW); digitalWrite(2, LOW); } void clearCmdArray(){ //clear the cmd array for (int i = 0; i < CMD_MAX; i++){ myCmd[i] = '\0'; } } //returns number of read bytes int readFromSerialIntoCmdArray(){ //read from the serial buffer and flush int inputSize = Serial.available(); //give serial a chance to receive all bytes if(inputSize > 0){ delay(100); inputSize = Serial.available(); } if(inputSize > 0 && inputSize < CMD_MAX){ Serial.print("inputSize: "); Serial.println(inputSize); for (int i = 0; i < inputSize; i++){ myCmd[i] = Serial.read(); } }else if(inputSize >= CMD_MAX){ Serial.flush(); Serial.println("too much data, flush"); } return inputSize; } //check if command has the required prefix int checkCmdArrayForPrefix(){ if (myCmd[0] == 'o' && myCmd[1] == 'l' && myCmd[2] == 'l' && myCmd[3] == 'p' && myCmd[4] == 'e'){ return 1; } return 0; } void sendAckOverSerial(){ Serial.println("ACK"); } void sendNackOverSerial(){ Serial.println("NACK"); } void sendPingAckOverSerial(){ Serial.println("PACK"); } void loop() { //delay needed to have a chance to get the whole message delay(100); clearCmdArray(); int inputSize = readFromSerialIntoCmdArray(); if (inputSize > 0) { //debug Serial.print("receiced: "); Serial.println(myCmd); int checkCmd = checkCmdArrayForPrefix(); if(checkCmd == 0){ Serial.println("if you dont know what to do type \"ollpehelp\""); sendNackOverSerial(); return; } //check for write command if (myCmd[5] == 'w') { port = decodePort(myCmd[6]); if (myCmd[7] == 'h') { digitalWrite(port, HIGH); Serial.println("HIGH"); sendAckOverSerial(); } else if (myCmd[7] == 'l'){ digitalWrite(port, LOW); Serial.println("LOW"); sendAckOverSerial(); } else { sendNackOverSerial(); } } else if(myCmd[5] == 'r' && myCmd[6] == 'e' && myCmd[7] == 's' && myCmd[8] == 'e' && myCmd[9] == 't') { resetPorts(); sendAckOverSerial(); } else if (myCmd[5] == 'r') { port = decodePort(myCmd[6]); int readValue = digitalRead(port); Serial.println(readValue); } //check for ping command else if(myCmd[5] == 'p' && myCmd[6] == 'i' && myCmd[7] == 'n' && myCmd[8] == 'g') { sendPingAckOverSerial(); } else if(myCmd[5] == 'h' && myCmd[6] == 'e' && myCmd[7] == 'l' && myCmd[8] == 'p') { sendHelpOverSerial(); } else if (myCmd[5] == 'c') { port = decodePort(myCmd[6]); if (myCmd[7] == 'i') { pinMode(port, INPUT); Serial.println("INPUT"); sendAckOverSerial(); } else if (myCmd[7] == 'o'){ pinMode(port, OUTPUT); Serial.println("OUTPUT"); sendAckOverSerial(); } else { sendNackOverSerial(); } } else { //no write command sendNackOverSerial(); } } } void sendHelpOverSerial() { Serial.println("----help is coming----"); Serial.println("all commands must be prefixed with \"ollpe\""); Serial.println("----commands----"); Serial.println("w0h\t set port 0 high"); Serial.println("w0l\t set port 0 low"); Serial.println("c0o\t config port 0 output"); Serial.println("c0i\t config port 0 input"); Serial.println("r0\t returns binary state of port 0 (values 0,1)"); Serial.println("reset\t resets all ports to input and LOW"); Serial.println("ping\t returns \"PACK\""); Serial.println("help\t prints this help"); Serial.println("----help end----"); } //converts a char with the port number 0-6 //to the arduino port numbers int decodePort(char c) { switch(c) { case '0': return 8; case '1': return 7; case '2': return 6; case '3': return 5; case '4': return 4; case '5': return 3; case '6': return 2; default: return '8'; } }