Infrarot-Übertragung: Der ATARI steuert Geräte drahtlos fern!

In der ST-Computer 11/91 habe ich beschrieben, wie ein ATARI benutzt werden kann, um Geräte mit SIRCS(Control-S)-Eingang fernzusteuern. Dieser Beitrag soll zeigen, wie der ATARI auch Geräte mit RC5-Code fernsteuern kann - und das sogar drahtlos!

Die kleine Schaltung kann auch in Verbindung mit dem Programm aus 11/91 benutzt werden, und sie kostet dabei weniger als 20 DM.

Vielleicht nicht jeder hat sich wohlgefühlt, seinen ST über ein Kabel direkt mit seinem Videorekorder zu verbinden, oder das betreffende Gerät hatte eventuell gar keinen Control-S-Eingang. Mit der kleinen Schaltung aus Abb. 1 kann der ATARI jedoch Geräte drahtlos fernsteuern. Da die Geräte dadurch elektrisch getrennt sind, braucht niemand mehr Angst zu haben, daß, wenn der Blitz in den Videorekorder einschlägt, auch noch der ST beschädigt wird. Doch zunächst ein wenig Theorie... (keine Angst, die Schaltung funktioniert auch ohne!)

Wie funktioniert’s?

Die meisten Infrarot-Fernbedienungen benutzen einen gepulsten Infrarotstrahl. Das bedeutet, daß, wenn ein High-Bit übertragen werden soll, das Licht nicht einfach eingeschaltet, sondern mit einer bestimmten Frequenz ein- und ausgeschaltet (moduliert) wird. Soll ein Low-Bit übertragen werden, wird das Licht ausgeschaltet. Diese Modulationsfrequenz liegt meistens bei 36-38 kHz. Die kleine Schaltung aus Abbildung 1 schaltet eine Infrarot-Leuchtdiode mit dieser Frequenz ein und aus. Dabei kann der ST die Schaltung über Pin 4 vom IC 555 ein- und ausschalten. Liegt am Pin 4 der High-Pegel an, arbeitet die Schaltung, sonst bleibt die LED aus. Die Frequenz ergibt sich aus:

TI = 0,693 * C1 * R1 = 6,93 µs
T2 = 0,693 * C1 * (R1+R2+P1) = 20,19 µs
f = 1/(T1+T2) = ca. 37kHz

Aufbau und Abgleich

Der Aufbau der Schaltung gestaltet sich recht einfach. Sie kann auf einem kleinen Stück Lochrasterplatine aufgebaut werden. Natürlich kann sich der erfahrenere Bastler auch eine Platine selbst herstellen, ein Platinenvorschlag findet sich in Abbildung 2. Der Eingang der Schaltung (Pin 4 von IC 555) wird mit dem Anschluß des ST verbunden, der das Gerät steuern soll. Die Software in diesem Artikel verwendet dazu Bit 0 des Centronics-Ports, kann aber leicht an einen anderen Port angepaßt werden. Die Versorgungsspannung von 5 Volt kann z.B. am Joystickport abgegriffen werden.

Die genaue Frequenz läßt sich mit PI einstellen. Hat P1 ca. 7kΩ, erzeugt die Schaltung ungefähr 37kHz. Zum Abgleich sollte die LED möglichst dicht an das IR-Auge des zu steuernden Gerätes herangebracht werden. Dann wird P1 langsam (!) verdreht, bis das Gerät reagiert. Dazu muß natürlich die Schaltung an den ST angeschlossen sein und der ST mit der Routine aus Heft 11/91 oder mit der am Ende dieses Artikels Befehle erzeugen, die das Gerät versteht. Hierzu sollte der times-Parameter auf einen sehr hohen Wert eingestellt werden, damit der ST ständig Befehle generiert. Um zu testen, ob die Schaltung überhaupt funktioniert, kann statt der Infrarot-LED eine normale LED eingebaut werden. Diese muß blinken, während der ST Befehle sendet, und sonst dunkel sein. Soll die Schaltung Geräte verschiedener Hersteller steuern, sollte P1 auf einen Mittelwert eingestellt werden, mit dem alle Geräte zurechtkommen. Und nicht vergessen, mit der LED auf das Infrarotauge des Gerätes zu zielen! Sonst kann es passieren, daß das Gerät nicht auf die Befehle reagiert, obwohl alles einwandfrei funktioniert.

Soll die Schaltung mit dem Listing aus Heft 11/91 benutzt werden, sollten die Aufrufe im C-Programm von

send_sony(VTR,x,3);

in

send_sony(VTR,x,8);

geändert werden. Das kann notwendig sein, damit das zu steuernde Gerät einen Infrarotbefehl sicher versteht.

Der RC5-Code

In der ST-Computer 11/91 habe ich den SIRCS-Code beschrieben. Ein anderer vielbenutzter Code ist der RC5-Code. Er findet u.a. in Geräten von Philips und Marantz Verwendung. Der RC5-Code kann 32 Subsysteme mit bis zu 64 Befehlen steuern. Tabelle 1 zeigt einige Befehle, wie sie etliche Geräte (siehe Tabelle 2) benutzen. Manche Befehle haben jedoch bei anderen Geräten eine andere Bedeutung. Notfalls ist Experimentieren angesagt, schließlich gibt es nur 32*64 Befehlskombinationen! Ein guter Anfang ist immer der An/Aus-Befehl (12), in Verbindung mit einer Variation der Gerätenummer. Ist die richtige Gerätenummer gefunden (Achtung: manche Geräte können durchaus zwei Gerätenummern beanspruchen!), können die Befehle variiert werden. Dabei kann es sich durchaus mal herausstellen, daß das Gerät mehr kann, als die Entwickler auf die Fernbedienung gelegt haben, z.B. weil sie die Funktion nicht für wichtig gehalten haben.

Der Code besteht aus insgesamt 14 Bits, beginnend mit 2 Start-Bits, einem ,C‘-Bit, gefolgt von Geräteadresse und Befehlsnummer. Die letzten beiden Felder beginnen jeweils mit dem höchstwertigen Bit. Mit dem C-Bit hat es eine besondere Bewandtnis: Anhand dieses Bits kann das zu steuernde Gerät entscheiden, ob eine Taste immer noch oder schon wieder gedrückt worden ist. Mit jedem neuen Tastendruck wechselt dieses Bit seinen Zustand. Daher wird es auch Toggle-Bit genannt. Die einzelnen Bits sind biphasen-codiert. Das bedeutet, daß immer in der Mitte einer Bit-Zeit der Zustand wechselt. Bei einer log. 1 wechselt der Zustand in der Bit-Mitte von low nach high, bei einer log. 0 von high nach low.

Das Programm

Auch diesmal soll ein Beispielprogramm nicht fehlen, das die Theorie in die Praxis umsetzt. Das Programm kann einen CD-Spieler fernbedienen und als Accessory oder als Programm gestartet werden. Es ist mit Turbo-C geschrieben und leicht anpaßbar. So läßt sich z.B. ein anderer Port zur Steuerung der Schaltung benutzen. Momentanist dies Bit 0 des Centronics Ports. Um einen anderen Port zu verwenden, müssen nur die Routinen set_one bzw. set_zero geändert werden.

Das Listing enthält eine Assembler-Routine zur Erzeugung von RC5-Befehlen, die mit eigenen Programmen gelinkt werden kann. Als Parameter werden die Gerätenummer und der zu sendende Befehl benötigt. Außerdem kann angegeben werden, wie oft der Befehl wiederholt werden soll. Diese Zahl sollte höher als 3 liegen, damit der Befehl sicher erkannt wird. Ich wünsche nun allen Bastlern erfolgreiches Experimentieren und viel Spaß mit dieser interessanten Schaltung.

Oliver Scholz

Literatur:

[1] Datenblatt zum SAA 3027

[2] Sony-Geräte selbstgesteuert, ST-Computer 11/91

Stückliste

   
R1 10KΩ
R2 12KΩ
R3 4,7KΩ
R4 220Ω
P1 10KΩ Spindeltrimmer
C1 InF
C2 47nF
IC Timer 555
T1 BC 238
LED IR-Leuchtdiode

RC5-Befehlscodes

   
0-9 Ziffern 0-9
10 Select Track/Time
11 Recall
12 An/Aus/Standby
13 Mute
14 Ideal
15 Display
16 Volume +
17 Volume -
18 Helligkeit +
19 Helligkeit -
20 Farbsättigung +
21 Farbsättigung -
22 Bässe +
23 Bässe -
24 Hohen +
25 Hohen -
26 Balance rechts
27 Balance links
28 Random
29 Repeat
30 Skip +
31 Program
33 Enter
35 l/ll
36 Skip-
37 Surround Mode
39 Balance Rear
40 Balance Front
44 Search -
45 Open/Close
46 Search +
48 Pause
49 Cancel/Erase
50 Rewind
51 Goto
52 FF
53 Play
54 Stop
55 Recording
56 Connect
57 Disconnect
59 A-B
61 System Standby
62 System Select / Digital/ Analog Soundtrack

Tabelle 1

RC5-Subsystemadressen

   
0 TV 1
1 TV 2
2 Videotext
3 BTX
4 Laservision
5 Video 1
6 Video 2 12 CDV/LD
16 Surround Decoder/ Verstärker
17 Tuner
18 Tape 20 CD

Tabelle 2


PHILIPS.PRG

=

TCSTART.O 
PHILIPS.C 
SEND.S

TCTOSLIB.LIB 
TCSTDLIB.LIB 
TCGEMLIB.LIB

#define DIALOG 0    /* TREE */
#define POWER 1     /* OBJECT in TREE #0 */
#define PAUSE 3     /* OBJECT in TREE #0 */
#define STOP 4      /* OBJECT in TREE #0 */
#define PLAY 5      /* OBJECT in TREE #0 */
#define REW 6       /* OBJECT in TREE #0 */
#define DISPLAY 7   /* OBJECT in TREE #0 */
#define FF 8        /* OBJECT in TREE #0 */
#define OPEN 9      /* OBJECT in TREE #0 */
#define FERTIG 10   /* OBJECT in TREE «0 */


OBJECT rs_object[] = {
    -1, 1, 10, G_BOX, NONE, OUTLINED, 0x21100L, 0,0, 34,12,
    2, -1, -1, G_BUTTON, 0x5, NORMAL, (long)"POWER", 2,1, 8,1,
    3, -1, -1, G_STRING, NONE, NORMAL, (long)"RC-5 Fernbedienung", 13,1, 19,1,
    4, -1, -1, G_BUTTON, 0x5, NORMAL, (long)"PAUSE", 3,4, 8,1,
    5, -1, 1, G_BUTTON, 0x5, NORMAL, (long)"STOP", 13,4, 8,1,
    6, -1, -1, G_BUTTON, 0x5, NORMAL, (long)"PLAY", 23.4, 8,1,
    7, -1, -1, G_BUTTON, 0x5, NORMAL, (long)"< SKIP", 3,6, 8,1,
    8, -1, -1, G_BUTTON, 0x5, NORMAL, (long)"DISPLAY", 8,8, 8,1,
    9, -1, -1, GJBUTTON, 0x5, NORMAL, (long)"SKIP >", 23,6, 8,1,
    10, -1, -1, G_BUTTON, 0x5, NORMAL, (long)"OPEN/ CLOSE", 18,8, 10,1,
    0, -1, -1, G_BUTTON, 0x27, NORMAL, (long)"FERTIG1 13,10, 8,1);

LONG rs_trindex[] = {
0L};

struct foobar {
    WORD    dummy;
    WORD    *image;
} rs_imdope[] = { 0};

#define NUM_OBS 11 
#define NUM_TREE 1

/*
 * RC5 Steuerprogramm
 * von Oliver Scholz
 * (c) 1992 MAXON Computer 
 */

#include "portab.h"
#include "stdio.h"
#include "tos.h"
#include "aes.h"
#include "stdlib.h"
#include "philips.h"
#include "philips.rsh"

#define TRUE    1
#define FALSE   0

#define CD          12
/* #define CD       20 */

VOID send_rc5(WORD device, WORD command, WORD times);
OBJECT *get_traddr(WORD tree_index);
VOID do_dialog(OBJECT *dial);
VOID redo_obj(OBJECT *tree, WORD index);

extern _app;

WORD main(VOID)
{
    OBJECT *dialog;
    WORD i,dummy;
    WORD event;
    WORD msgbuff[8];
    WORD ap_id, mn_id;

    /* Programm initialisieren */ 
    ap_id = appl_init(); 
    if(ap.id == -1) exit(-1);

    /* Dialogadresse berechnen */ 
    for (i = 0; i<NUM_OBS; i++)
        rsrc_obfix(rs_object, i); 
    dialog=get_traddr(DIALOG);

    if (_app)
    {
        /* Applikation */ 
        graf_mouse(ARROW,0L); 
        do_dialog(dialog);
    }
    else
    { /* Accessory */
        mn_id = menu_register( ap_id, "  CD-Player" );

        do
        {
            event = evnt_multi (MU_MESAG,
                                0, 0, 0,
                                0, 0, 0, 0, 0,
                                0, 0, 0, 0, 0,
                                msgbuff,
                                0, 0,
                                &dummy, &dummy, &dummy, 
                                &dummy, &dummy, &dummy );

            if(event & MU_MESAG)
                if((msgbuff[0] == AC_OPEN) && (msgbuff[4] == mn_id)) 
                    do_dialog(dialog);
        }
        while (TRUE);
    }
    appl_exit(); 
    exit(0);

    return(0);
}

/* Adresse eines Baumes ermitteln */

OBJECT *get_traddr(WORD tree_index)
{
    WORD i,j;

    for (i=0,j=0; i<=tree_index; i++) 
        while (rs_object[j++].ob_next!=-1);

    return (&rs_object[--j]);
}

VOID do_dialog(OBJECT *dial)
{
    WORD cx,cy,cw,ch;
    WORD xflag, exitobj;

    form_center(dial,&cx,&cy,&cw,&ch);

    form_dial(FMD_START,cx,cy,cw,ch,cx,cy,cw,ch); 
    xflag = FALSE;

    objc_draw (dial, ROOT, MAX_DEPTH, cx, cy, cw, ch);

    do
    {
        exitobj = form_do(dial,0) & 0x7fff;

        dial[exitobj].ob_state &= ~SELECTED; 
        switch(exitobj)
        {
            case FERTIG:
                xflag = TRUE; 
                break;
            case POWER:
                send_rc5(CD,12,4); 
                break; 
            case PAUSE:
                send_rc5(CD,48,4); 
                break; 
            case PLAY:
                send_rc5(CD, 53,4); 
                break; 
            case STOP:
                send_rc5(CD, 54,4); 
                break; 
            case REW:
                send_rc5(CD,36,4); 
                break; 
            case FF:
                send_rc5(CD, 30,4); 
                break; 
            case DISPLAY:
                send_rc5(CD,15,4); 
                break; 
            case OPEN:
                send_rc5(CD,45,4); 
                break;
        }
        redo_obj(dial,exitobj);
    } while(!xflag);

    form_dial(FMD_FINISH,cx,cy,cw,ch,cx,cy,cw,ch);
}

VOID redo_obj(OBJECT *tree, WORD index)
{ WORD x,y,w,h;

    objc_offset(tree,index,&x,&y); 
    w = tree[index].ob_width; 
    h = tree[index].ob_height;

    objc_draw(tree,ROOT,MAX_DEPTH,x,y,w,h);
}



Aus: ST-Computer 09 / 1993, Seite 100

Links

Copyright-Bestimmungen: siehe Über diese Seite