Entries Tagged 'Leopard' ↓

IRC and Arduino

A while back, I wrote a small python script to act as a proxy between IRC and an Arduino. This video illustrates some of the details.

Here is a zip file with everything to download.

The basic idea was this, the python IRC bot sits in the chat room and waits until someone addresses it’s nick like so:

     {NICK}: {command} {arg1} {arg2} ... {etc}

The bot parses the response into a command and a series of arguments. Originally, all this was hardcoded, but through python’s powers of introspection, I realized I could make this way more dynamic. The end result is a framework of sorts. The user can edit the Commands.py file adding functions and settings to his/her specification. The example in the video would be written like this:

#
# module for configuration and commands
#
from Arduinos import Arduino

# Program Settings
DEBUG = True

# IRC Settings
NICK = "arduino"
SERVER = "irc.paraphysics.net"
CHANNEL = "#arduinoroom"
PORT = 6667

# Arduino Settings
USB_PATH = '/dev/tty.usbserial-A7006Qe8'
BAUD = 9600

# define methods
def lightLed(arduino, args):
	arduino.send('~') # header
	arduino.send(args[0])
	arduino.send('~') # terminating
	return arduino.read(4) # read 4 bytes from arduino

def readPot(arduino):
	arduino.send('}}') # header
	return arduino.read(4) # read 4 bytes from arduino

Obviously, you can change the constants to what you need and the daemon picks up on these when it is started. The nice thing about this ‘framework’ is the second half of the script. When you define a method, the IRC bot automagically “understands” it. This is because every time it receives a message directed to it, it calls

    reload(Commands)

and reads the function names. So you don’t have to restart the server while developing your functions [An idea stolen from Rails]! Then it parses the message coming in and tries to call the first word as a method and parses the rest of the message into a list. There is no need to worry about the details, what you do need to know to use it is that there are two types of functions, ones with and ones without arguments. The above example illustrates both. Let’s say we define 2 functions:

# define methods
def function1(arduino, args):
    print "function1"
    print args

def function2(arduino):
    print "function 2"
    print "no args"

Now, we go into the IRC chat room and issue a command like this:

   arduino: function2

The output would be this:

   function 2
   no args

Then lets say we send this:

   arduino: function1 hello world!

The bot would parse it and you would see this output:

   function1
   ['hello', 'world!']

so args becomes a list by splitting the rest of the statement between whitespaces. Your function always needs to have the ‘arduino’ argument. This argument is a custom class I created which looks like this:

   import serial

class Arduino():

	def __init__(self, path='/dev/tty.usbserial', baud=9600):
		self.ser = serial.Serial(path, baud)	

	def send(self, data):
		self.ser.write(data)

	def read(self, bytes):
		while (1):
			if (self.ser.inWaiting() > bytes-1):
				return self.ser.read(bytes)

	def flush():
		self.ser.flushInput()

It is pretty simple, send() sends a string. read() waits for the defined number of bytes to come in and returns the results. To better understand how the example Commands.py script works, take a look at the arduino sketch:

#define LED 13

void setup() {
  pinMode(LED, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  if (nextByte() == 126) { // header byte ('~' character) led command
    char args[] = {0,0,0,0,0,0,0,0,0,0};
    char charIn = 0;
    byte i = 0;
    while (charIn != 126) {  // wait for header byte again
       charIn = nextByte();
       args[i] = charIn;
       i += 1;
    }
    if ((args[0] == 'o') && (args[1] == 'n')) {
      digitalWrite(LED, HIGH);
      Serial.print("on  ");
    }
    else if ((args[0] == 'o') && (args[1] == 'f')) {
      digitalWrite(LED, LOW);
      Serial.print("off ");
    }
    delay(10);
    Serial.flush();
  }
  else if (nextByte() == 125) { // header byte pot command
    int val = analogRead(0);
    if (val < 10) {
      Serial.print(val);
      Serial.print("   ");
    }
    else if (val < 100) {
      Serial.print(val);
      Serial.print("  ");
    }
    else if (val < 1000) {
      Serial.print(val);
      Serial.print(" ");
    }
    else {
      Serial.print(val);
    }
  }
  delay(10);
  //if(Serial.available() > 0) {
    Serial.flush();
  //}
}

byte nextByte() {
    while(1) {
      if(Serial.available() > 0) {
          byte b =  Serial.read();
	  return b;
       }
    }
}

Yeah, not the cleanest code but hopefully you get the idea. I am not releasing a whole lot of detail on how to use this because I figure If you are using it, then you already know enough about python and Arduino to get by. I have created this to allow for support for firmata but have yet to implement it and probably never will until/if people beg. To run, first get pyserial and irclib.py. Upload the sketch to your arduino and run:

   python Main.py

Mysql preference pane Leopard

Have you noticed that the Mysql pref. pane in Leopard does not work? Here is the temporary fix, run this command:

sudo /usr/local/mysql/bin/mysqld_safe

Leopard disc ejects on MacBook

I had another problem that I forgot to mention. When I tired to install Leopard, the disc would just keep ejecting after a few seconds and it would never mount. I consulted a Mac forum which told me that many people have had this problem. I tried every bizarre method the suggested which included inserting the disc while your computer was upside down. I was half expecting the next post to tell me to pull out my disc and blow in the slot while moving my mouth in a side-to-side, fan-like fashion. The only thing that worked for me was installing and using this program. I am starting to think that I shouldn’t have done this.

Leopard – Terminal launches multiple X11 processes

As a member of ADC, you usually get all the new operating systems sent to you in the mail. I have had a copy of Leopard on my coffee table since it’s release. I finally broke down and decided to install it after a friend told me it wasn’t so bad. The problem is that I really didn’t want to back everything up so I did and upgrade. As I suspected, there are a host of problems. The first one I have managed to solve is the Terminal.app problem. When you open up Terminal, it opens X11. Also, X11 takes multiple clicks to close. After I opened up Terminal, for the 3rd time, I ran the ‘ps’ command. There were 2 different X11 daemons running. Well, that solved the problem with X11 not closing properly, but why were they there? After checking out ‘~/.bash_profile’ on both my machines, I noticed this line that shouldn’t have been there.

test -r /sw/bin/init.sh && . /sw/bin/init.sh

After taking that line out, Everything worked properly. I still can’t figure out why it was there.