Tuesday, December 30, 2008

Network connections in (K)ubuntu

The network connection software for ubuntu and kubuntu is terrible. I have recently run into the problem of it failing to connect or connecting for only a few minutes. I would then have to reboot for it to connect again. I've found that lots of people have this problem on various hardware. The solution is to get ride of network-manager and instal wicd. Instructions for getting and installing are on their site.

http://wicd.net/

Sunday, July 20, 2008

CM15A X10 Home Automation with Linux

A lot of the information and source code is slightly out of date on the topic of X10 on Linux. Certain changes in the latest kernels prevent the code from compiling out of the box. The machine I did this on is Kubuntu with the 2.6.24-16 kernel. Neil Cherry did a lot of good work on this subject. His page is full of a lot of detail that you probably think you don't need. Read through it anyway if you are actually trying to get the CM15A working in Linux.

First you will need the driver and the daemon. Download and unpack both. To get either to compile you need to change a few lines and comment out some others. You have to do the same thing in both packages. Find the line that reads, "#include linux/config.h" and change it to "#include linux/autoconf.h" Then comment out any line that starts with "MODULE_PARM". Next, in the cm15a-driver package in the cm15a.c file find the usb_class_driver struct and comment out the line that begins with "mode:" and do the same for the line in the next struct that begins with "owner:". Save everything and then run ./configure;make;make install.

Once everything is installed you'll need to run these commands:

mkdir /dev/usb
mknod --mode=a=rw /dev/usb/iplc0 c 180 240

then go into ./iplc/driver/linux-2.6/ and run:

insmod iplc.ko

then into cm15a-driver/driver/linux-2.6/ and run:

insmod cm15a.ko

That should be it. Here is a simple perl script that will turn on or off A1 depending on which line is uncommented.

#!/usr/bin/perl
use Fcntl;

sysopen( cm15a, "/dev/usb/iplc0", O_RDWR |O_NOCTTY | O_NONBLOCK )
|| die "Cannot find $!";
syswrite cm15a, pack( "CC", 4, 0x66), 2;
sleep 1;

# Turns on
syswrite cm15a, pack( "CC", 6, 0x62 ), 2;

# Turns off
#syswrite cm15a, pack( "CC", 6, 0x63 ), 2;
close( CM15A );

Now for some explanation of the script. The sysopen line creates a pointer of "cm15a" to the device file we made earlier. This gives perl an easy name to send future data. The first syswrite line is what tells the cm15a what device we are sending a signal to. In this case it is A1. We have to wait about 1 second because an ACK packet is sent back. The next syswrite sends the 'turn on' signal and the commented out syswrite sends 'turn off'. The last line closes the pointer for a graceful exit. The '4' part of the syswrite is what tells the unit that you are sending a Unit address (A1, C3, etc). The '6' means you are sending a Function code (on, off, dim, etc). Below is a cheet sheet for the A codes. If you look on Neil Cherry's page you'll see his chart of whole break down of the codes. The codes are not in binary order and seemed to have been chosen randomly. I made this just to help myself out and not have to decifer the right code everytime I'm writing a script. For the other house codes like B and up, just change the 6 to whatever Neil's chart says it should be.

A1 0x66
A2 0x6E
A3 0x62
A4 0x6A
A5 0x61
A6 0x69
A7 0x65
A8 0x6D
A9 0x67
A10 0x6F
A11 0x63
A12 0x6B
A13 0x60
A14 0x68
A15 0x64
A16 0x6C

I hope this helps!

Friday, June 27, 2008

Arduino RFID Door lock

This project is for an RFID accessible door lock controlled by an Arduino microcontroller. Most of this kind of project is pretty straight forward and just takes some trial-and-error and a lot of reading. I'm sure a lot of people want to try something very similar for themselves, so here is what I have done.

The basic premise is that when an RFID tag is detected in the field the data is sent to the Arduino. The Arduino compares the tag to a list of valid tags. If it matches then the servo is turned and the LED changes color. Which way the servo turns is determined by which way it turned last. If its open, it closes. If its closed, it opens. Therefore, the only way to lock or unlock this door is with a valid RFID tag.

Things you'll need:
  • Arduino Decimilia (or equivalent)
  • Parallax RFID Reader
  • Standard Servo
  • Jumper Wires
  • Project Box
  • Deadbolt lock assembly you don't mind destroying
  • Standoffs
  • Cutting/drilling tool (Dremel)
Optional things:
  • LEDs (2)
  • LED Housings (2)
  • Breakaway headers (male and female)
  • Soldering iron
  • Solder
  • Basic soldering skills
  • Solder-less bread board
You will probably want to mock this up on a breadboard first to be sure everything works before you start cutting and soldering.

Once you are ready to build the final product the first thing to do is figure out how you want to mount the components. Keep in mind where wires, connectors, and LEDs are going to be. Be mindful of the height of your standoffs and how they will affect things mounted on the outside. I had installed the LED first without determining how far it would stick into the box and it almost touches the Arduino board. I ended up having to bend the connecting wires down slightly rather than drill another hole. Measure everything and drill as needed. This is alway an organic process for me and I always end up with more holes than I want or need.

I soldered all my wires to breakaway headers to make it easier to connect and disconnect components. The male pins visible below are for the servo and the female connector is for an optional external LED mounted on the door knob to see the door state on the outside. You can also see the LED mounted on the box. This one is so the door state can be determined on the inside of the door


Here is the basic wiring diagram:

If you copy and paste the code I have below make sure you connect all the wires in the same places. In my setup the RFID GND is connected to the GND on the top row, SOUT goes to 8, /ENABLE goes to 2, and VCC goes down and around to 5V on the bottom. The yellow or white wire of your servo is the control wire. It will go to pin 4. Red gets spliced on to the same wire on the reader that connects to 5V. Black is ground and is connected to GND on the bottom.

The hardest part is figuring out how the servo is going to interface with your deadbolt. I'm afraid there isn't much help I can give you on this part. I went through three or four designs before I found one that worked with my deadbolt and the parts I have. Consider this a mechanical engineering exercise. All you have to do is find some way of connecting that servo wheel to the overcentering portion of the deadbolt. Since all deadbolts are different and there is no way you'll be able to replicate what I have done (mostly because I don't know where these pieces came from) I'm not going to bother posting pictures of it.

All of that, plus this code and you should be off and ready to over complicate your entry procedures!


//BEGIN CODE

#define servoPin 4 // control pin for servo motor (White or yellow wire of servo)
#define minPulse 500 // minimum servo position (Open position)
#define maxPulse 2200 // maximum servo position (Closed position)
#define rxPin 8 // SOUT pin of RFID module
#define txPin 9
#define enable 2 // /ENABLE pin of RFID module
#define LED1 13 // LED output pin
#define LED2 12 // other LED output pin for two-way LED (yellow)
#define switchPin 7

boolean open = true; // default start up is to assume the lock is open
int val = 0;
char code[10];
int bytesread = 0;
int pulse, switchVal;

char tag1[11] = "0800335036"; // this is size 11 because it is a NULL terminating string
char tag2[11] = "0800330A99";
char tag3[11] = "0F03028B4F";



void LEDControl(int state){

switch (state){
case 1:
digitalWrite(LED1,HIGH);
digitalWrite(LED2,LOW);
break;
case 2:
digitalWrite(LED2,HIGH);
digitalWrite(LED1,LOW);
break;
case 3:
for(int y=0;y<5;y++){
digitalWrite(LED1,HIGH);
digitalWrite(LED2,LOW);
delay(250);
digitalWrite(LED2,HIGH);
digitalWrite(LED1,LOW);
delay(250);
}
}

}

boolean checkTag(char *tag){

for (int x=0;x<10;x++){
if( tag[x] != code[x]){
return false;
}
}
return true;
}

boolean findGoodTag(){
if (checkTag(tag1)){ return true;}
else if (checkTag(tag2)){ return true;}
else if (checkTag(tag3)){ return true;}

// Add more lines right here like the one above if you have more tags

else{
Serial.print("Bad tag: ");
Serial.println(code);
LEDControl(3);
return false;
}

}
void moveServo(){

if (open){
pulse = minPulse;
open = false;
LEDControl(1);
}
else if (!open){
pulse = maxPulse;
open = true;
LEDControl(2);
}

for (int x =1;x<150;x++){
delay (10); // don't know why this works, but it does
digitalWrite(servoPin, HIGH); // start the pulse
delayMicroseconds(pulse); // pulse width
digitalWrite(servoPin, LOW); // stop the pulse
}

}



void setup() {

pinMode(servoPin, OUTPUT); // Set servo pin as an output pin
pinMode(LED1,OUTPUT); // Set LED pin as output
pinMode(LED2,OUTPUT); // Set LED pin as output
Serial.begin(9600);
Serial.println("Begin");
pinMode(enable,OUTPUT); // Set digital pin 2 as OUTPUT to connect it to the RFID /ENABLE pin
digitalWrite(enable, LOW); // Activate the RFID reader
pinMode(switchPin, INPUT);
}

void loop() {
SoftwareSerial RFID = SoftwareSerial(rxPin,txPin);
RFID.begin(2400);

switchVal = digitalRead(switchPin);



if((val = RFID.read()) == 10)
{ // check for header
if(switchVal == HIGH){
Serial.println("Button");
moveServo();
}
bytesread = 0;
while(bytesread<10)
{ // read 10 digit code
val = RFID.read();
if((val == 10)||(val == 13))
{ // if header or stop bytes before the 10 digit reading
break; // stop reading
}
code[bytesread] = val; // add the digit
bytesread++; // ready to read next digit
}



if((bytesread == 10) && (findGoodTag()))
{ // if 10 digit read is complete
digitalWrite(enable, HIGH); // dectivate the RFID reader
moveServo();
delay(500);
digitalWrite(enable, LOW); // Activate the RFID reader
}
}
}

Sunday, June 22, 2008

Introduction

This is meant to be a chronicle of my further adventures in the use of all kinds of technology. I am an avid Linux user and also have become involved in electronics and robot creation. Specifically, I use the Arduino microcontroller. I have also used the BASIC Stamp and will give my input on that later. Look forward to posts on how I accomplish things that you probably are trying or want to try with Linux and the Arduino/BASIC Stamp.