onsdag 6 januari 2010

Computer controlled wall outlets

Got hold of three radio controlled wall outlets on sale. Modified the remote to be able to control the outlets with a pc parallel port (or some other port compatible with a 74xxx05)




The remote contains a sc2262 and is powered by a 12V battery.

After a look under the hood of the remote the conclusion was made that a press of a button connect two pins to ground, totally 5 pins are used giving six buttons (see schematic).
To control this from a computer a 74LS05 (hex inverter with open collector outputs) was used (any 7405 should do but if it's going to be powered by the parallel port it won't hurt using a low power one), connecting the open collector outputs directly to the control chip. The 7405 is powered using bit 5,6 and 7 of the data port, this is enough using the parallel port on my motherboard.


Schematic:




inside (the white wire is the antenna)



To control the parallel port this small (linux) program is used, ppdev module has to be loaded.


Remote.c
//Control of remote to remote controlled wall outlets using the parallel port
//Written for linux
//Written by Mikael Ågren 2009
//
//gcc remote.c -o remote

#include <stdlib.h>
#include <stdio.h>
#include <sys/io.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/ppdev.h>
#include <fcntl.h>

int fd;

//map bits of pp data port
#define PWR    (1<<7)|(1<<6)|(1<<5)    //used to power buffer
#define ROD    1<<0
#define LILA    1<<1
#define GUL    1<<2
#define VIT    1<<3
#define SVART    1<<4

#define ON    ROD
#define OFF    LILA
#define ONE    GUL
#define TWO    VIT
#define THREE    SVART

unsigned char setParPortData(unsigned char data) {
    ioctl(fd, PPDATADIR, 0);
    if(ioctl(fd, PPWDATA, &data)) {
        printf("error writing to port");
        exit(2);
    }
}

delay_enough() {
    char i;
    for(i=0; i<5; i++) {
        delay_1s();
    }
}

delay_1s() {
    time_t t;
    time_t old_t;

    old_t = time(NULL);
    while ((t=time(NULL)) < old_t+1) {
    }
}

void printHelp(char **argv, int exitcode) {
    printf("usage: %s reciever on|off\nreciever = 1, 2 or 3\n", argv[0]);
    exit(exitcode);
}

int main(int argc, char **argv)
{
    if(argc!=3) {
        printHelp(argv, 1);
    }

    printf("Försöker öppna /dev/parport0\n");
    fd = open("/dev/parport0", O_RDONLY);
    if(ioctl(fd, PPCLAIM)) {
        perror ("PPCLAIM");
        close(fd);
        return 1;
    }
    printf("/dev/parport0 öppnad\n");

    unsigned char out=0;
    //which reciever
    if(!strcmp(argv[1], "1"))
        out |= ONE;
    else if(!strcmp(argv[1], "2"))
        out |= TWO;
    else if(!strcmp(argv[1], "3"))
        out |= THREE;
    else
        printHelp(argv, 1);
    //which state
    if(!strcmp(argv[2], "on"))
        out |= ON;
    else if(!strcmp(argv[2], "off"))
        out |= OFF;
    else
        printHelp(argv, 1);
    //keep buffer powered
    out |= PWR;

    printf("%x\n", PWR);    
    setParPortData(PWR);
    delay_enough();    
    printf("%x\n", out);    
    setParPortData(out);
    delay_enough();    
    printf("%x\n", 0);    
    setParPortData(0);

    close(fd);
    return 0;
}

Coffee...
Wrote some simple scripts so i can wake up to the smell and sound of fresh coffee in the morning

kaffeON
remote 3 on

kaffeOFF
remote 3 off

kaffe
if [ "$1" = "" ];
then
        echo "usage:    $0 now"
        echo "  $0 HH:MM"
        exit -1
fi

timeoff=$(date -d "$1 30 min" +%H:%M)
$(echo kaffeOFF | at $timeoff)

if [ "$1" = "now" ];
then
        void=$(kaffeON)
        echo $void
else
        timeon="$1"
        $(echo kaffeON | at $timeon)
fi