Entries Tagged 'Arduino' ↓

Using an Arduino + acceleromter to monitor sleep

I have heard that a trip to a sleep doctor entails hooking up a bunch of sensors to you and they tell you things like how many times you woke up in the night. I don’t have a bunch of sweet EEG nodes, but I realized that I could easily create something that measures my relative movement throughout the night. Looking at an over-arching chart would probably give me a good idea of how I was really sleeping.

The Parts

I am currently working on a system which involves control theory and I purchased one of these IMUs from Sparkfun.

6DOF IMU

Sparkfun Razor 6DOF IMU

This is a 6 degree of freedom inertial measurement unit. It uses 2 gyroscopes and an accelerometer to give you information about your hardware’s orientation. I am waiting for some parts to come in so I just had it hooked up to one of my development boards just hanging out. I realized I could just use the accelerometer chip to relatively measure “how much” I was moving.

Accelerometers are really simple devices and they have become completely ubiquitous. If you are reading this on a mac or an iphone, then you are using one right now. A 3 axis accelerometer, such as the one on this board, can measure the orientation of the chip in relation to the earth’s magnetic field. Due to it’s sensitivity, it is also really good at measuring general vibration.

The Build

Hooking up to the accelerometer is pretty simple. You only need 5 pins: a 3.3V VCC and GND pin, then 3 analog pins for x, y, and z.

Boarduino + IMU wired

Boarduino + IMU wired

Since most accelerometers run on 3.3V, you will likely need to account for that in some way if you are running your arduino at a higher voltage. The x, y, and z pins output a voltage b/w 0 and 3.3V for each axis. For instance, if you are holding the chip completely level, you may see something like 1.65V on the X pin, as you turn it towards 90 degrees, it will increase. You can measure this using analogRead(int pin); .

The Code

The code for this project was so simple it took me under 1 hour to write the firmware and the client software. First the Arduino code:

#define DEBUG 0 //set to 1 for debug mode
#define AX 0 //accelerometer pin X
#define AY 1 //accelerometer pin Y
#define AZ 2 //accelerometer pin Z
#define DELAY 1000
#define SENSITIVITY 3 //movement required to send a movement event

//storage for x,y,z values
int x, y, z;
//storing the old values to compare relation movement
int old_x, old_y, old_z;
//our 'relative motion'
int movementFactor;

void setup() {
  Serial.begin(9600);
  readSensors();
  saveValues();//initialize
}

void loop() {

   readSensors();
   determineMovementFactor();

   if (movementFactor > SENSITIVITY) { 

      if (DEBUG) {
         Serial.print("x = ");
         Serial.print(x);
         Serial.print(" | y = ");
         Serial.print(y);
         Serial.print(" | z = ");
         Serial.print(z);
         Serial.print(" | movement = ");
         Serial.println(movementFactor);
      } else {
         Serial.println(movementFactor);
      }

      saveValues();
      delay(DELAY);
   }
}

/**
 * All we are doing here is finding the greatest derivative from
 * the 3 axises and choosing that as our relative movement factor
 */
void determineMovementFactor() {
   movementFactor = abs(old_x - x);
   int temp = abs(old_y - y); //due to impl of max(), no inline functions
   movementFactor = max(movementFactor, temp);
   temp = abs(old_z - z);
   movementFactor = max(movementFactor, temp);
}

void readSensors() {
   x = analogRead(AX);
   y = analogRead(AY);
   z = analogRead(AZ);
}

void saveValues() {
   old_x = x;
   old_y = y;
   old_z = z;
}

Assuming you don’t have it in DEBUG mode, it constantly reads the values off the accelerometer and finds the greatest change b/w all the axises. If that is greater than your SENSITIVITY, it sends it to the computer. I chose to do it this way rather than sending the movement factor every second so I could exploit the sparsity of the data and just use a scatter plot to stretch it out over the time domain. Now for the client side…

The client code is just a single python script. To get it working you need to install pyserial of course.

#!/usr/bin/env python
#
# @file: monitor.py
# @author: Benjamin Eckel
#
# To Run -->
#     $python monitor.py > output_file.csv
#                                                                                                              

import serial
import datetime

FTDI_USB = "/dev/tty.usbserial-A3000RBH"

if __name__ == "__main__":
    print "Time,Movement"
    ser = serial.Serial(FTDI_USB, 9600)
    while 1:
        movement = ser.readline()
        print "%s,%s" % (datetime.datetime.now().strftime("%H:%M:%S"), movement.rstrip())

This code is self explanatory, you run it and it prints out a comma-separated file with the hours, minutes, seconds, and the relative motion. You can redirect the output to whatever file or program you choose. Here is an example of some output:

Time,Movement
01:31:47,4
01:31:48,12
01:31:49,15
01:31:50,4
01:31:51,4
01:31:53,4
01:31:54,27
01:31:55,6
01:31:56,12
01:31:57,16
01:31:58,6
01:31:59,5
01:32:00,5
01:32:02,4
01:32:03,4
01:32:06,4
01:32:07,4
01:32:08,4
01:32:09,4

All you need to change is your FTDI_USB location. If you don’t know yours, plug in your arduino and run this command:

ls /dev/usb.tty.usb*

This is assuming you are running OS X or Linux of course. Windows uses COM ports. Refer to pyserial for help.

The Installation

To get good readings, it is best to place the sensor somewhere on your mattress that experiences the maximum displacement of the surface (the anti-node) caused by your movements. You can program it in DEBUG mode and try different locations out. I just wrapped the sensor in a sock and stuck it in one of my pillows.

Sock wrapped sensor

Sock wrapped sensor

The Results

To graph the results, I imported the resulting csv file into excel and created a scatter plot. This is my sleep from June 20 1:30AM to 11:00AM [ took a while to get out of bed :) ]:

Sleep chart thumb

Click to view full chart

From what little I know about the subject, I think I should be seeing spikes separated by intervals of about 90 minutes (the time it takes to get a full cycle of sleep). There are definitely some abnormalities in there. I am going attempt to do this for about a week and maybe send the results to a doctor friend.

Radioshack Infrared Receiver <--> Arduino

I just posted up an article on the Gumbolabs blog explaining how to use the Radioshack infrared receiver module. It contains Arduino code along with the explanations.

Aruduino ethernet shield and Rails

I just wrote an article on the GumboLabs blog about using the Arduino Ethernet shield. Be sure to check it out.

Parallax RFID reader <--> Arduino

Parallax RFID reader

Parallax RFID reader

I just recently wrote an article at the Gumbo Labs blog on interfacing to the Parallax RFID reader. Here is the final code if you are only looking for that:

/**
 * author Benjamin Eckel
 * date 10-17-2009
 *
 */
#define RFID_ENABLE 2   //to RFID ENABLE
#define CODE_LEN 10      //Max length of RFID tag
#define VALIDATE_TAG 1  //should we validate tag?
#define VALIDATE_LENGTH  200 //maximum reads b/w tag read and validate
#define ITERATION_LENGTH 2000 //time, in ms, given to the user to move hand away
#define START_BYTE 0x0A
#define STOP_BYTE 0x0D

char tag[CODE_LEN];  

void setup() {
  Serial.begin(2400);
  pinMode(RFID_ENABLE,OUTPUT);
}

void loop() {
  enableRFID();
  getRFIDTag();
  if(isCodeValid()) {
    disableRFID();
    sendCode();
    delay(ITERATION_LENGTH);
  } else {
    disableRFID();
    Serial.println("Got some noise");
  }
  Serial.flush();
  clearCode();
} 

/**
 * Clears out the memory space for the tag to 0s.
 */
void clearCode() {
  for(int i=0; i<CODE_LEN; i++) {
    tag[i] = 0;
  }
}

/**
 * Sends the tag to the computer.
 */
void sendCode() {
    Serial.print("TAG:");
    //Serial.println(tag);
    for(int i=0; i<CODE_LEN; i++) {
      Serial.print(tag[i]);
    }
}

/**************************************************************/
/********************   RFID Functions  ***********************/
/**************************************************************/

void enableRFID() {
   digitalWrite(RFID_ENABLE, LOW);
}

void disableRFID() {
   digitalWrite(RFID_ENABLE, HIGH);
}

/**
 * Blocking function, waits for and gets the RFID tag.
 */
void getRFIDTag() {
  byte next_byte;
  while(Serial.available() <= 0) {}
  if((next_byte = Serial.read()) == START_BYTE) {
    byte bytesread = 0;
    while(bytesread < CODE_LEN) {
      if(Serial.available() > 0) { //wait for the next byte
          if((next_byte = Serial.read()) == STOP_BYTE) break;
          tag[bytesread++] = next_byte;
      }
    }
  }
}

/**
 * Waits for the next incoming tag to see if it matches
 * the current tag.
 */
boolean isCodeValid() {
  byte next_byte;
  int count = 0;
  while (Serial.available() < 2) {  //there is already a STOP_BYTE in buffer
    delay(1); //probably not a very pure millisecond
    if(count++ > VALIDATE_LENGTH) return false;
  }
  Serial.read(); //throw away extra STOP_BYTE
  if ((next_byte = Serial.read()) == START_BYTE) {
    byte bytes_read = 0;
    while (bytes_read < CODE_LEN) {
      if (Serial.available() > 0) { //wait for the next byte
          if ((next_byte = Serial.read()) == STOP_BYTE) break;
          if (tag[bytes_read++] != next_byte) return false;
      }
    }
  }
  return true;
}

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

Python based Arduino serial utility

I was looking at this link on the todbot blog. It is a utility C program that sends some serial data to your Arduino. I decided to customize this concept for my own use and also to make it a little simpler to read, use, or re-use. I was going to write this in C mostly b/c I wanted the user to be able to use UNIX pipes to send data over the line and I wanted it to be as little terminal typing as possible. Here is the desired result for the user’s CLI experience:

    $ arduino-serial < data.txt

and not something like this:

    $ python arduino-serial.py -b 9600
       -p /usr/dev/tty.usbserial-A4000QZG
       -f /usr/ben/Documents/data.txt
    # you get the idea

So, like I was saying, I originally thought I should do this in C; but, then I realized I could easily achieve these results and have a much shorter program even if I used python. Here is the program in tarred and gzipped. I’m not really going to explain how the program works b/c it is so simple, but I will explain how I put it together.
**Before I get started, you should know that I created this for my MacBook Pro (OS X 10.4.11, Python 2.5) and this program should work with most BSDish systems but probably not Windows. Also, you need pyserial. Download it and do the usual install commands after you unarchive it:

    $ python setup.py build
    $ python setup.py install

Moving on now…..
First, I created a symlink to the arduino serial port called usbserial.arduino by opening up my Terminal application and dropping in this:

    $ sudo ln -s /dev/tty.usbserial-A4000QZG /dev/tty.arduino

My postfix is A4000QZG but yours will be different, if you don’t know it, run this command:

    $ ls /dev/tty.usbserial*

This path is set as a constant in my program so if you create this symlink, you won’t have to change it.

    ARDUINO_PATH = "/dev/tty.arduino"

Next thing you want to do is copy this file to your /usr/bin directory, you will probably need sudo:

    $ sudo cp ./arduino-serial.py /usr/bin/arduino-serial

This assumes, of course, you are currently in the directory that contains the arduino-serial.py file. Keep in mind that this also strips off the .py extension. I think as long as you have the correct shebang in there “#!/usr/bin/env python”, you should be fine. Now you have to give the file the proper permissions:

    $ chmod 755 /usr/bin/arduino-serial

After this, everything should be running swimmingly. You can just send an ASCII text file byte by byte doing something like show above:

    $ arduino-serial < data.txt

You can run this from any directory in your terminal because the program was put in “/usr/bin/”. You can verify its status as a global program by typing:

    $ which arduino-serial

There are a few ways to use this program:
You can use the ‘-b’ option to set the baud rate. If you don’t enter this option, it is default=9600. This is a common baud rate for me but if you have a different preference, you can change this in the program in the ‘default’ parameter of this function:

    parser.add_option("-b", "--baud", dest="baud",
                      default=9600, help="serial baud rate")

There is also the -d option for ‘data’. You can use that to send just one character or sequence of characters.
In conclusion, this could probably best be used to test your serial reading code on your arduino or maybe even send it configuration files or possibly hex binaries.

Control Arduino remotely with HTML forms

[for everyone who is continuing to read this, it probably won't work anymore and it isn't too reliable in general. I would suggest a better method like this : http://blog.datasingularity.com/?p=148. It works for botnets right? ]

Well, this is the culmination of a lot of posts I have been writing. I devised a simple way to get HTML form data, or URL encoded CGI data, to the Arduino using a remote server. Here is the package to download. Here is a flow chart of how the system works:


CGI_Arduino chart
Let’s look at this from the top down. The “user input” in the demonstration is an HTML form with “radio” buttons. Take a look at the source for cgi_socket_script.html either in the downloaded package or right here. I basically hacked the HTML file from this post, giving it a new CGI parameter [name="message"] and sending it to the new script. The CGI script is also a hack from the post on python CGI. It opens up a fifo in the filesystem and writes the value of the “message” parameter to the fifo:

    form = cgi.FieldStorage()

    message = form.getvalue('message')

    pipe = open("./cgififo", 'w')

    pipe.write(str(message))

    pipe.close()

I got this fifo idea from this post. All you do is use the *nix command ‘mkfifo’ and it creates a fifo in the file-system. I used this to communicate between the CGI script and the socket server processes. To get an idea of how to get this section to run, read my post on python CGI linked above. Now to the socket server. This is basically a work in progress but I think it is good enough for right now. I encountered a lot of weird problems that caused me to write some irresponsible code but it isn’t exactly meant to be used without modification so no problem. It simply waits for a client then continually checks the fifo and passes the information off to the client. The client comes in 2 flavors. First is a bare command line interface and the second has a tkinter GUI and is multi-threaded. The problem with the bare single threaded version is that it doesn’t inform the server when the socket is disconnected. The GUI version may or may not work for you. I built a mac app in the dist folder on my intel based MacBook Pro. You can rebuild it on your machine. To get this socket stuff working, look at my post on python sockets. Now for the serial side.

Inside the socket client thread is a pySerial instance. It works exactly the same as my post on sending strings to the Arduino. It waits for the socket to get a string, sends the header to the Arduino, sends the string, then sends another header. The Arduino program is exactly the same as it is on that post as well. You should configure the program to do whatever it is you want to do with that string.

To use all this software, you have to run them in a certain order. First you give the proper permissions to the cgi script and make the fifo. Call it ‘cgififo’ so you don’t have to change any code. Then you run the socket server on your server. After that, you can run the client on your machine and connect. Here are the definitions for the fields:

CGI_APP

For host, choose your domain name [e.g. www.datasingularity.com]. The port number is the port which you have bound your socket server. The serial location is the tty file used to identify your Arduino. Baud rate is the serial baud rate and the header character is your serial header byte. Have your ssh or telnet window open to the socket server process on the remote server. When you hit connect you should see the connection in your server window. When you hit start, it will start the child thread and start listening for data. Quit closes the connection and ‘hopefully’ tells the server that you have disconnected. If not, you will need to restart the server to use again.

In conclusion, this code may be pretty ragged, but the concept is what is important and it should be enough to get you started. You obviously can’t do anything too intense with this. It could be used to do some simple but cool things though such as controlling your house from your cell phone, or feeding your dog or cat over the internet, etc. Once again, please e-mail me if you need help getting it working for your project.

**Update** Here is a demonstration video:

Getting information to the Arduino

There are many times when you need to design a protocol that retrieves multiple pieces of data in a single instance. You can do this by serially sending a string from your computer and letting the Arduino decide which part of the string means what. In this example, I am going to show a protocol I designed to get strings of varying lengths to the Arduino at irregular intervals decided by the computer. This particular example is a python script that prompts the user for a string and sends it to a serial-enabled LCD screen connected to the Arduino. Here is the package for download.

Because the computer decides when to send the information, hand-shaking is useless. I have decided to use a header byte to tell the Arduino that a string is coming in and the next bytes will be the data. Then I send the same header byte after the string is sent to tell the Arduino that the string transmission is over. Here is what the python side looks like:

    ser.write(HEADER) #header byte
    ser.write(data)
    ser.write(HEADER)

For the HEADER constant, I chose ‘~’ considering I wouldn’t use that in any string literal I am sending. You can choose whatever is right for your protocol from an ASCII chart. Now for the Arduino side. First you need to establish a special “blocking” function for your serial port. A blocking function blocks everything until the serial event is completed. So, if you are trying to read a byte, it will wait until you receive the byte to move on:

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

This function waits until info is available in the buffer, then reads and returns the byte treating the buffer like a fast FIFO queue. Now, as for the main loop, you have 2 options. If your Arduino has stuff to do other than read serial data, you want to start off the main loop with:

    if(Serial.available() > 0){
       // do serial communications
    }
    // do what the Arduino needs to do all the time

Since this example is dedicated only to reading serial information. I started with my blocking function nextByte(). So, we check to see if this is the header byte ‘~’, or 126 on the ASCII chart. If it is, we go into the read loop:

    char charIn = 0;
    byte i = 0;
    while (charIn != 126) {  // wait for header again
        charIn = nextByte();
        stringIn[i] = charIn;
        i += 1;
    }

This is a pretty simple loop, it keeps reading bytes into the string until the header byte comes again, then we break the loop. From there, we can null out the string:

    for (int j=i-1; j<16; j++) {
        stringIn[j] = ' ';    // null out string
    }

The rest of the code is self-explanatory. You should be able to easily hack it to your liking.