Pi + UART-FS20-Sender + Funksteckdose

Begonnen von Sincostan, 19 April 2014, 23:56:36

Vorheriges Thema - Nächstes Thema

Sincostan

Nabend.

Ich bin neu im Automatisierunggeschäft und möchte gerne mit meinem Pi eine Funksteckdose per Sprachsteuerung steuern. Das Skript / C-Programme für letzteres sind schon geschrieben, doch scheitere ich nun an der eigentlichen Funkübertragung.

Der FS20-Sender http://www.elv.de/output/controller.aspx?cid=74&detail=10&detail2=35109&refid=SEM_30003&gclid=CL30scrB7b0CFabLtAodcQwA7g ist per Steckbord mit meinem Pi verbunden. Vorher habe ich den seriellen Port des Pi´s geändert, so dass nun auch weitere Programme ihn benutzen können.

Testweise habe ich RxD und TxD des Pi´s miteinander verbunden und dann mit minicom die Verbindung überprüft. Resultat war, dass die Daten gesendet und zurückgeliefert wurden.

Das Problem beim FS20-Sender ist nun, dass ich bei minicom nur Punkte zurückerhalte sobald ich egal welche Taste drücke. Diese Punkte sind zwar 4 Zeichen lang, aber das mag vllt. nichts heißen, obwohl der return-Wert der Taste auf dem Sender 0x00 ist.

Die Funksteckdose hat schon Hauscode und Kanal eingestellt bekommen.

Kennt jemand eine möglichkeit, mit der ich den Sende-Befehl (besteht wohl aus mehreren Hex-Zahlen) des FS20-Senders übermitteln kann?

Noch einen schönen Abend und vorzeitige frohe Ostern  ;)

Sincostan

Zusatz:

Habe noch ein wenig weitergesucht und bin dabei auf diese Seite gestoßen: http://kampis-elektroecke.de/?page_id=1682 .

Dort wird gesagt, dass ich einfach mit einem echo in der shell, welches dann zu der Schnittstelle geleitet wird, Wörter übertragen kann. Beispielhaft also:

echo Text >> /dev/ttyAMA0

Leider macht die shell danach gar nichts mehr und gibt nichts zurück. Ich muss dann immer den Prozess stoppen.

Das würde für das übersenden von den hex-Werten der Funksteckdose natürlich funktionieren (Korrektur: hoffe ich), aber kann mir jemand sagen warum die shell nach der Eingabe nichts mehr macht?

Sincostan

Stand:

Ich habe nun erstmal Cutecom für die Übertragung der Werte benutzt. Da erhalte ich immerhin richtige Hex-Zahlen zurück, wenn ich beispielhaft die Taste des Senders drücke.

Nun schaffe ich es jedoch nicht, den Befehl im richtigen Format an den Controller des Senders zu schicken.

Ich möchte z.B. den Befehl aus der ELV-Anleitung senden:

0x02 0x06 0xF1 0xFD, 0x04, 0x02, 0x11,0xFF

Wie soll dieser dann nun eingegeben werden? Durch Leerzeichen getrennt, durch Backslashes getrennt, so wie der Rückgabewert beim Drücken der Taste?

Hat jemand da eine Idee?

Sincostan

Um das hier nochmal zum Abschluss zu bringen und eventuell andere vor diesen Fehlern zu bewahren:

Mit Cutecom konnte letztendlich doch der FS20-UART-Sender angesprochen werden. Dafür musste unten nur der Input-Typ auf Hex geändert werden und man kann dann die Zahlen einfach ohne den 0x-Präfix mit Leerzeichen eingeben.

Beispielweise: 02 06 F1 XX XX XX 12 FF, wobei die ersten für "X" für den Hauscode und die anderen beiden für den Gerätecode stehen. Dieser Befehl würde nun meine FS-20-Funktsteckdose tooglen.

Da Cutecom aber über GUI funktioniert habe ich nochmal weitergeguckt. Mir war schon zwischenzeitlich WiringSerial für C (Zusatz-Library von Gordon Henderson, hat auch WiringPi geschrieben) aufgefallen. Am Anfang konnte ich keine Hex-Werte übergeben, doch dann sind mir aber die Kommentare auf der Seite aufgefallen und letztendlich habe ich es dank einer gleichen Fragestellung dann doch hinbekommen.

Nun läuft mein Pi 24/7 mit einer Java-Programm, in welchem ich ein Socket für meine Android App bereitstelle. Die App liest die NFC-Sticker, die in meiner Wohnung verteilt sind und sendet die Android Geräte-ID + gespeicherter Sticker Name an den Pi und reagiert dann dementsprechend.

Das ist wirklich ganz schön und auch schnell, aber leider zieht das Java-Programm zu viel Ram in meinen Augen. Eventuell versuche ich das noch in C zu schreiben um so die Auslastung zu verringern.

Ich dokumentiere den Verlauf einfach mal weiterhin hier.


Letztendlich möchte ich im Sommer einen Touchscreen an den Pi schließen und ihn in den Flur hängen um so auch noch eine weitere Input-Möglichkeit zu stellen.

sparkie

#4
ein kleines C Programm wie ich es mit Pi +FS20-Sender  nutze. EInfach mit 'make <filename>' compilieren.

Aufruf direkt mit den Hexcodes z.B.

fs20_serial_io 02 06 f1 f2 f0 40 06 00

es wird dann auf stdout der Status ausgegeben. Der sollte im Gutfall dann etwa so aussehen

02 02 00 01



#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <termios.h>
#include <fcntl.h>

int
set_interface_attribs(fd, speed, parity)
    int fd;
    int speed;
    int parity;
{
    struct termios tty;

    memset(&tty, 0, sizeof tty);
    if (tcgetattr(fd, &tty)) {
        printf("tcgetattr: %s\n", strerror(errno));
        return -1;
    }
    cfsetospeed(&tty, speed);
    cfsetispeed(&tty, speed);
    tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
    // disable IGNBRK for mismatched speed tests; otherwise receive break
    // as \000 chars
    tty.c_iflag &= ~IGNBRK;         // ignore break signal
    tty.c_lflag = 0;                // no signaling chars, no echo,
                                    // no canonical processing
    tty.c_oflag = 0;                // no remapping, no delays
    tty.c_cc[VMIN]  = 0;            // read doesn't block
    tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout
    tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
    tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
                                    // enable reading
    tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
    tty.c_cflag |= parity;
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag &= ~CRTSCTS;
    if (tcsetattr(fd, TCSANOW, &tty)) {
        printf("tcsetattr: %s\n", strerror(errno));
        return -1;
    }
    return 0;
}

int
set_blocking(fd, should_block)
    int fd;
    int should_block;
{
    struct termios tty;

    memset(&tty, 0, sizeof tty);
    if (tcgetattr(fd, &tty)) {
        printf("tcgetattr: %s\n", strerror(errno));
        return -1;
    }
    tty.c_cc[VMIN]  = should_block ? 1 : 0;
    tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout
    if (tcsetattr(fd, TCSANOW, &tty)) {
        printf("tcsetattr: %s\n", strerror(errno));
        return -1;
    }
    return 0;
}

#ifdef __ARMEL__
#define PORT "/dev/ttyAMA0"
#else
#define PORT "/dev/ttyS0"
#endif

main (argc, argv)
    char **argv;
{
    int i, n, fd, cnt;
    char buf[100];

    if (argc < 2) {
        printf("more args\n");
        exit(-1);
    }
    cnt = 0;
    for (i = 1; i < argc; ++i) {
        buf[cnt++] = strtol(*(argv + i), 0, 16);
    }
    fd = open(PORT, O_RDWR | O_NOCTTY | O_SYNC);
    if (fd < 0) {
        printf("open %s: %s\n", PORT, strerror(errno));
        exit(-1);
    }
    if (flock(fd, LOCK_EX | LOCK_NB)) {
        printf("flock %s: %s\n", PORT, strerror(errno));
        exit(-1);
    }

    // for fs20 transmitter
    set_interface_attribs(fd, B9600, 0);  // set speed to 115,200 bps, 8n1 (no parity)
    set_blocking(fd, 1);   // blocks if cmds are sent in repeat mode
//    set_blocking(fd, 0);

// for fs20 receiver
//    set_interface_attribs(fd, B4800, 0);  // set speed to 115,200 bps, 8n1 (no parity)
//    set_blocking(fd, 1);

    write(fd, buf, cnt);
    n = read(fd, buf, sizeof buf);  // read up to 100 characters if ready to read
    for (i = 0; i < n; ++i) {
        printf("%02x ", buf[i]);
    }
    printf("\n");
}

Sincostan

Sieht gut aus. Meins ist sehr ähnlich. Machst du was bestimmtes mit dem Rückgabe wert oder lässt du den einfach ausgeben?

sparkie

ich nutze das Ganze aus Scripten. Wenn der Rueckgabewert 'nicht ok' zeigt, dann liegt es meist daran, dass die Maximalzahl der Sendepulse erreicht ist und der Sender eine Pause einlegen muss. Ist nur zu meiner Information, das Programm macht nichts damit.