IOrouter

Aus C3MAWiki
Version vom 9. Februar 2014, 18:56 Uhr von Ollo (Diskussion | Beiträge)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Dies ist ein Projekt, an dem momentan aktiv gearbeitet wird. Wenn du Fragen hast oder mitarbeiten möchtest, wende dich an Pensoffsky.


DIE DOKU IST GERADE AM ENTSTEHEN...

Das Projekt zur Lichtsteuerung des Raumes ist Ueberschalter

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

Geöffneter 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.

Angelötete Pins auf dem Board

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.

uC-Platine mit Kabel (Noch ohne Quarz
uC-Platine an Board angeschlossen

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. ...

Modifizierung des Router Gehäuses
AVR ISP Programmer
Fertiger Router


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';
  } 
}