Sunday, January 30, 2011

VibraMotor as a Cat Toy

If you have an old cellphone lying around that doesn't work anymore or that you would have thrown away anyway, you might want to think about taking it apart for spare parts or looking inside to understand how it works.

Yesterday I disassembled an old cellphone to look for some parts which I could use. Besides some buttons, a microphone and a speaker, one particular component caught my attention. I extracted a small vibra motor. Vibra motors are responsible for the vibrating notification your cellphone can alert you with. In general they are just small DC motors. At the top of their shaft they have a weight in the form of a half circle. When the motor spins the weight, it gets out of balance and you experience a vibration.

You also can order those motors online if you don't have a cellphone lying around.

With the motor and an additional LED, I decided to build a toy for my cat.

Usually those little motors work with a 3V power supply. I used a coin cell battery holder for my circuit so I could keep the project really small. The only thing left to do was to attach a 150Ω resistor with a red LED to the circuit. Now the circuit can be placed in a casing. I used a surprise egg plastic casing. Make sure that you seal the casing or stand by when your cat plays with it, so your cat can't accidentally break it open and swallow the parts.

Let's have look at the setup:

Vibra Motor

Parts (150Ω resistor and LED are missing on that photo)

Assembled Circuit

Circuit in Casing




Here is the circuit diagram of the project:







If you assembled everything correctly, the result should look like this:


Friday, January 28, 2011

Capacitive Touch Sensor on Arduino

If you ever wanted to integrate touch sensitivity into your project, this board could just do the trick. It's a capacitive touch sensor. These sensors are used in our everyday consumer electronics like notebook trackpads, video game consoles, touchscreens...just to name a few.

They work on the principle of alteration of the electrostatic field. The sensor builds up an electrostatic field which will be altered if conductive objects get in contact with the field. In this case your finger is the conductive object which triggers the change in the field. For detailed information about capacitive sensing have a look here.

The board works in I2C mode and needs pull-up resistors for the SDA and SCL pins. The operating voltage range is from 2.7V to 5.25V, so you can use either the 3.3V or 5V socket of the Arduino.

The setup is pretty easy. I attached two LEDs to indicate if the sensor plate was touched.




Figuring out the communication with the device is a little bit tricky. I found a really good blog post from Marcus Nowotny who provides a sample code, so you don't have to get a headache while trying to understand the datasheet.

If you hooked up everything correctly, you can enjoy capacitive sensing in your project.

Wednesday, January 26, 2011

RFID with Arduino

If you ever wanted to integrate RFID functionality into your project, this small tutorial might help you accomplish that. I used the RDM630 module from seeedstudio in its UART version. It comes on a small board with presoldered connectors which fits perfectly on a breadboard. You only need to connect the antenna to the two pin socket. You also can connect a LED to indicate if the antenna picks up a signal. The signal output can be easily read by using the NewSoftSerial library and assigning the RX TX ports.

Here are the setup schematics:


The signal readings are transmitted in byte blocks. The first byte (02) is the start of text byte in HEX-ASCII format. Then following is the 10 byte data for the ID which has been recognized. After that a 2 byte checksum is transmitted. Followed by the last byte (03).
To translate the 10 byte HEX-ASCII data to the unique ID, you only have to map the bytes to the according ASCII character. For details have a look into the datasheet.

This is an example code which checks if the data was received correctly. It prints the ID and checks if the transmitted checksum is equal to the calculated checksum of the ID.
#include "NewSoftSerial.h"
#define stx 2
#define etx 3

NewSoftSerial mySerial(6, 7);
int counter;
byte data[14];
byte hexBlock1,hexBlock2,hexBlock3,hexBlock4,hexBlock5;
byte hexCalculatedChecksum,hexChecksum;

void setup() {
  Serial.begin(9600);
  mySerial.begin(9600);
}

void loop() {
  if (mySerial.available() > 0) {
    data[counter] = mySerial.read();
    counter++;
    if(counter > 13) {
      //we read the whole message, so reset counter
      counter = 0;
      //check if start of text and end of text is correct
      if(data[0] == stx && data[13] == etx) {
        Serial.println("Start of text and end of text correctly received.");
        Serial.print("ID: ");
        //show ID
        for(int x = 1; x < 11; x++) {
          Serial.print(data[x], BYTE);
        }
        Serial.println("");
        Serial.print("Checksum: ");
        //show checksum
        Serial.print(data[11], BYTE);
        Serial.println(data[12], BYTE);

        //Hex ID blocks. Two transmitted Bytes form one Hex ID block.
        //Hex ID blocks:      6   2  |  E   3  |  0   8  |  6   C  |  E   D
        //Transmitted Bytes: 36H 32H | 45H 33H | 30H 38H | 36H 43H | 45H 44H
        hexBlock1 = AsciiCharToNum(data[1])*16 + AsciiCharToNum(data[2]);
        hexBlock2 = AsciiCharToNum(data[3])*16 + AsciiCharToNum(data[4]);
        hexBlock3 = AsciiCharToNum(data[5])*16 + AsciiCharToNum(data[6]);
        hexBlock4 = AsciiCharToNum(data[7])*16 + AsciiCharToNum(data[8]);
        hexBlock5 = AsciiCharToNum(data[9])*16 + AsciiCharToNum(data[10]);
       
        //Transmitted checksum.
        hexChecksum = AsciiCharToNum(data[11])*16 + AsciiCharToNum(data[12]);

        //XOR algorithm to calculate checksum of ID blocks.
        hexCalculatedChecksum = hexBlock1 ^ hexBlock2 ^ hexBlock3 ^ hexBlock4 ^ hexBlock5;
        if ( hexCalculatedChecksum == hexChecksum )
        {
          Serial.println("Calculated checksum matched transmitted checksum.");
        }
        else {
          Serial.println("Calculated checksum didn't match transmitted checksum. Corrupt data!");
        }
      }
    }
  }
}

uint8_t AsciiCharToNum(byte data) {
  //First substract 48 to convert the char representation
  //of a number to an actual number.
  data -= '0';
  //If it is greater than 9, we have a Hex character A-F.
  //Substract 7 to get the numeral representation.
  if (data > 9)
    data -= 7;
  return data;
}
 
An example reading would look like this:
Start of text and end of text correctly received.
ID: 4200442C01
Checksum: 2B
Calculated checksum matched transmitted checksum.
Here is a demonstration of the RFID reader in action:

Tuesday, January 25, 2011

Color Wheel with Wii Nunchuck and Arduino

Today I want to show you how to use a Wii nunchuck to control your Arduino projects. In my example I used the nunchuck to simulate a color wheel with a full rgb LED. I connected a WiiChuck board directly to the Arduino using the analog ports. You can use them for the I2C communication and to power the board. There is a blog which already provides a library and some demo code to get you started.

I modified the demo code and had to adjust some coordinate bounds of my nunchuck. There are some formulars for calculating color wheels, but I took an easier approach and just mapped coordinate bounds of the color spectrums to the color wheel.
Note that my mapping is only a rough approximation. You also might need to adjust the bounds because your nunchuck readings could differ just a little bit.

The setup is easy. You just need to connect the WiiChuck board to the analog ports 5-2 and setup a circuit for your rgb LED. I have a rgb LED with 6 pins. Two for GND, two for blue, one for red and one for green. That's why my setup seems a little bit crowded.



The code isn't the prettiest one but it gets the job done for now.
#include <Wire.h>
#include "nunchuck_funcs.h"

//PWM Digital Pin layout for RGB LED
#define greenLED 6
#define blue1LED 9
#define blue2LED 10
#define redLED 11

byte joyx,joyy;
byte redVal,greenVal,blueVal;

void setup()
{
  nunchuck_setpowerpins();
  nunchuck_init(); // send the initilization handshake
}

void loop()
{
  nunchuck_get_data();

  joyx = nunchuck_joyx(); // idle position at approx 133, ranges from approx 31 - 232
  joyy = nunchuck_joyy(); // idle position at approx 130, ranges from approx 33 - 228

  //Red has its full intensity at y = 228 (approx upper bound).
  //When moving in x direction, y will decrease.
  //Red has its lowest intensity when it reaches the full intensity position of green or blue.
  //In my case approx y = 95.
  redVal = map(joyy >= 95 ? joyy : 95, 95, 228, 0, 255);

  //Green has its full intensity at approx x = 217 and approx y = 95.
  //Green has two x ranges. If y is above 95 then the x range is from 133 to 232.
  //If y is below 95 then the x range is from 44 to 217.
  greenVal = joyy >=95 ? map(joyx < 133 ? 133 : joyx, 133, 232, 0, 255) :
  map(joyx > 217 ? 217 : joyx < 44 ? 44 : joyx, 44, 217, 0, 255);

  //Blue has its full intensity at approx x = 44 and approx y = 95.
  //Blue has two x ranges. If y is above 95 then the x range is from 31 to 133.
  //If y is below 95 then the x range is from 44 to 217.
  blueVal = joyy >=95 ? map(joyx > 133 ? 133 : joyx, 133, 31, 0, 255) :
  map(joyx > 217 ? 217 : joyx < 44 ? 44 : joyx, 217, 44, 0, 255);

  //Because I also want to simulate white light I need to determine if the position is roughly in the middle.
  if(joyy > 125 && joyy < 135 && joyx > 125 && joyx < 135) {
    redVal=255;
    greenVal=255;
    blueVal=255;
  } 
  analogWrite(redLED, redVal);
  analogWrite(greenLED, greenVal);
  analogWrite(blue1LED, blueVal);
  analogWrite(blue2LED, blueVal);

  delay(100);
}
This video shows the nunchuck color wheel in action:

Saturday, January 22, 2011

DIY Nightlight

Since I became an uncle last year, I thought about building something with electronics for my niece. I already setup a circuit a while ago for pulsating LEDs. I used this circuit for one pulsating blue LED and added another blue LED and a Yellow LED. What I wanted to achieve is that the LEDs illuminate certain parts of an image which is put in front of them. I used a food container where I could put in a mini breadboard and a 9V battery. I searched the web for free images to use and found a clipart page which had just the image I needed.

For the circuit setup please have a look into my old post.

Here is a demo of the nightlight:

RGB Color Sensor on Arduino

The next board I want to show you is the ADJD-S371 Color Light Sensor Evaluation Board from sparkfun. It emits light and analyses the reflected color spectrum. The board can be controlled via I2C. The sleep and xclk pins were not used in this example. I found a really nice tutorial describing how to connect the sensor to the Arduino. The example also provided the code to communicate with the sensor. I only had to change minor parts to fit my needs.

My basic setup looks a little bit different because I used a full color rgb LED with six pins. Two for ground, one for red, one for green and two for blue. I also used another schematic this time. What you see here is a software developed by the University of Applied Sciences Potsdam, here in Germany. The software is called Fritzing. You can design your circuit on a protoboard, convert it into a circuit diagram and even into a PCB layout for later manufacturing. It's really nice and easy to use. Thanks for the tip Darsh!

Here is my setup:




As already mentioned I only changed the code from the tutorial a little bit to fit to my rgb LED.
//Configure gain here
//Higher numbers = less sencitive
// 0x00 through 0x0f
int redGain = 0x03;
int greenGain = 0x0;
int blueGain = 0x0f;
int clearGain = 0x01;

//Include the I2C Arduino library
#include <Wire.h>

//7 bit I2C address of this sensor
#define I2C_ADDRESS 0x74

#define REG_CAP_RED    0x06
#define REG_CAP_GREEN     0x07
#define REG_CAP_BLUE     0x08
#define REG_CAP_CLEAR     0x09

#define REG_INT_RED_LO    0x0A
#define REG_INT_RED_HI    0x0B
#define REG_INT_GREEN_LO 0x0C
#define REG_INT_GREEN_HI 0x0D
#define REG_INT_BLUE_LO    0x0E
#define REG_INT_BLUE_HI    0x0F
#define REG_INT_CLEAR_LO 0x10
#define REG_INT_CLEAR_HI 0x11

#define REG_DATA_RED_LO    0x40
#define REG_DATA_RED_HI    0x41
#define REG_DATA_GREEN_LO 0x42
#define REG_DATA_GREEN_HI 0x43
#define REG_DATA_BLUE_LO 0x44
#define REG_DATA_BLUE_HI 0x45
#define REG_DATA_CLEAR_LO 0x46
#define REG_DATA_CLEAR_HI 0x47

//PWM Digital Pin layout for RGB LED
#define greenLED 6
#define blue1LED 9
#define blue2LED 10
#define redLED 11

float redFactor=1;
float blueFactor=1;
float greenFactor=1;

//initial darkLevel;
int calibrationDarkness = 0;
byte calibrationRed = 5;
byte calibrationGreen = 5;
byte calibrationBlue = 5;

void setup(void){
  Serial.begin(9600);
  Wire.begin();

  // sensor gain setting (Avago app note 5330)
  // CAPs are 4bit (higher value will result in lower output)
  set_register(REG_CAP_RED, redGain);
  set_register(REG_CAP_GREEN, greenGain);
  set_register(REG_CAP_BLUE, blueGain);
  set_register(REG_CAP_CLEAR, clearGain);

  int ledGain = getColorGain();

  set_gain(REG_INT_RED_LO,ledGain);
  set_gain(REG_INT_GREEN_LO,ledGain);
  set_gain(REG_INT_BLUE_LO,ledGain);

  performMeasurement();

  int red=get_readout(REG_DATA_RED_LO);
  int green=get_readout(REG_DATA_GREEN_LO);
  int blue=get_readout(REG_DATA_BLUE_LO);

  int m=2000; //bigger anyway
  m=min(m,red);
  m=min(m,green);
  m=min(m,blue);

  //Serial.print("m - ");
  //Serial.println(m);

  redFactor=((float)m*255.0)/(1000*(float)red);
  greenFactor=((float)m*255.0)/(1000*(float)green);
  blueFactor=((float)m*255.0)/(1000*(float)blue);

}

void loop() {

  //set rgb LED off
  analogWrite(redLED, 0);
  analogWrite(greenLED, 0);
  analogWrite(blue1LED, 0);
  analogWrite(blue2LED, 0);

  int clearGain = getClearGain();
  set_gain(REG_INT_CLEAR_LO,clearGain);
  int colorGain = getColorGain();
  set_gain(REG_INT_RED_LO,colorGain);
  set_gain(REG_INT_GREEN_LO,colorGain);
  set_gain(REG_INT_BLUE_LO,colorGain);

  //reset the RGB (and clear) values
  int cc = 0;
  int red=0;
  int green=0;
  int blue=0;

  // Take 4 samples, and add them together.
  for (int i=0; i<4 ;i ++) {
    performMeasurement();
    cc +=get_readout(REG_DATA_CLEAR_LO);
    red +=get_readout(REG_DATA_RED_LO);
    green +=get_readout(REG_DATA_GREEN_LO);
    blue +=get_readout(REG_DATA_BLUE_LO);
  }

  //now, divide the totals for each by 4 to get their average.
  cc/=4;
  red /=4;
  green /=4;
  blue /=4;

  //take the values mesured from above, and multiply them with the factors to
  //find out what value should be sent to the external RGB LED to reproduce this color
  float redValue = (float)red*redFactor;
  float greenValue = (float)green*greenFactor;
  float blueValue = (float)blue*blueFactor;

  //Print the recognized color to the Serial Monitor and light up rgb LED accordingly.
  if(redValue > 100 && greenValue > 100 && blueValue > 100) {
    Serial.println("White or Clear");
    analogWrite(redLED, 255);
    analogWrite(greenLED, 255);
    analogWrite(blue1LED, 255);
    analogWrite(blue2LED, 255);
  }
  else if(redValue > 100 && greenValue > 100) {
    Serial.println("Yellow");
    analogWrite(redLED, 255);
    analogWrite(greenLED, 255);
  }
  else if(redValue > 100 && blueValue > 100) {
    Serial.println("Magenta");
    analogWrite(redLED, 255);
    analogWrite(blue1LED, 255);
    analogWrite(blue2LED, 255);
  }
  else if(greenValue > 100 && blueValue > 100) {
    Serial.println("Cyan");
    analogWrite(greenLED, 255);
    analogWrite(blue1LED, 255);
    analogWrite(blue2LED, 255);
  }
  else if(redValue > 100) {
    Serial.println("Red");
    analogWrite(redLED, 255);
  }
  else if(greenValue > 100) {
    Serial.println("Green");
    analogWrite(greenLED, 255);
  }
  else if(blueValue > 100) {
    Serial.println("Blue");
    analogWrite(blue1LED, 255);
    analogWrite(blue2LED, 255);
  }

  //Print reflected light spectrum to the Serial Monitor.
  Serial.print("red: ");
  Serial.println(redValue);

  Serial.print("green: ");
  Serial.println(greenValue);

  Serial.print("blue: ");
  Serial.println(blueValue);
  Serial.println("");

  //hold it for one second
  delay(1000);
}

int getClearGain() {
  int gainFound = 0;
  int upperBox=4096;
  int lowerBox = 0;
  int half;

  while (!gainFound) {
    half = ((upperBox-lowerBox)/2)+lowerBox;

    if (half == lowerBox) { //no further halfing possbile
      break; //no further halfing possbile
    }
    else {
      set_gain(REG_INT_CLEAR_LO,half);
      performMeasurement();
      int halfValue = get_readout(REG_DATA_CLEAR_LO);

      if (halfValue > 1000) {
        upperBox=half;
      }
      else if (halfValue<1000) {
        lowerBox = half;
      }
      else {
        break; //no further halfing possbile
      }
    }
  }
  return half;
}

int getColorGain() {
  int gainFound = 0;
  int upperBox=4096;
  int lowerBox = 0;
  int half;
  while (!gainFound) {
    half = ((upperBox-lowerBox)/2)+lowerBox;

    if (half==lowerBox) { //no further halfing possbile
      break; // gain found
    }
    else {

      set_gain(REG_INT_RED_LO,half);
      set_gain(REG_INT_GREEN_LO,half);
      set_gain(REG_INT_BLUE_LO,half);
      performMeasurement();
      int halfValue = 0;

      halfValue=max(halfValue,get_readout(REG_DATA_RED_LO));
      halfValue=max(halfValue,get_readout(REG_DATA_GREEN_LO));
      halfValue=max(halfValue,get_readout(REG_DATA_BLUE_LO));

      if (halfValue>1000) {
        upperBox=half;

      }
      else if (halfValue<1000) {
        lowerBox=half;

      }
      else {
        break; // gain found
      }
    }
  }
  return half;
}

void performMeasurement() {
  set_register(0x00,0x01); // start sensing

  while(read_register(0x00) != 0) {
    // waiting for a result
  }
}

int get_readout(int readRegister) {
  return read_register(readRegister) + (read_register(readRegister+1)<<8);
}

void set_gain(int gainRegister, int gain) {
  if (gain <4096) {
    uint8_t hi = gain >> 8;
    uint8_t lo = gain;

    set_register(gainRegister, lo);
    set_register(gainRegister+1, hi);
  }
}

void set_register(unsigned char r, unsigned char v){

  Wire.beginTransmission(I2C_ADDRESS);
  Wire.send(r);
  Wire.send(v);
  Wire.endTransmission();
}

unsigned char read_register(unsigned char r){

  unsigned char v;
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.send(r); // register to read
  Wire.endTransmission();

  Wire.requestFrom(I2C_ADDRESS, 1); // read a byte
  while(!Wire.available()) {
    // waiting
  }
  v = Wire.receive();
  return v;
}
This is a demo of the sensor in action. It had a really hard time recognizing the green spectrum. It may have been my room lighting though.

IR distance sensor on Arduino

The next little device is an IR distance sensor. It comes on a tiny, easy to use board. It operates on 5V and the output voltage which is sent out of the signal pin gets lower the closer an object gets. Theses little sensors are used on robots to measure the distance to an obstacle or to sense edges. The on-board IR LED emits light which is reflected and sensed by an IR sensitive phototransistor. The setup is pretty easy so I don't even need to provide a schematic. Just connect the Vin pin of the board to the 5V port of the Arduino and the GND pin to GND. You can connect the signal pin to any analog port of the Arduino. That's all there is to it.

The source code is straight forward too:
#define signal 0

int adcRawValue;
//You have to determine your normal reflection to set an upper bound.
int normalReflectionValue;

void setup() {
  Serial.begin(9600);
}

void loop() {
  adcRawValue = analogRead(signal);
  //If you get higher values due to interferences, fallback to your upper bound.
  if(adcRawValue > 500) {
    adcRawValue = 500;
  }
  //I mapped my boundaries inverse to a 0-100 scale. (500 = 0; 0 = 100)
  //The closer the Object gets, the lower the ADC value.
  Serial.println(map(adcRawValue, 500, 0, 0, 100));
  delay(50);
}
Here is a demo reading when hovering my finger over the sensor:

Thursday, January 20, 2011

7-Segment Display on Arduino

A new package with electronic components arrived today, so let's get busy.

First I want to show you a seven segment display which I hooked up to the Arduino. The display is from sparkfun and it is really easy to connect and to control it. You can control it via SPI or via serial. For more info refer to the datasheet. I used the serial communication, so I only would need one wire to transmit data to the component. You just have to connect the Vcc pin to 5V of the Arduino and the GND pin to GND. Then you only need to connect the RX pin to one of the digital ports of the Arduino. For sending data to the component I used the NewSoftSerial library.

The example program I wrote is a simple seconds counter.
#include "NewSoftSerial.h"

//The second parameter (TX) is the digital port which sends data to the display.
//The first parameter (RX) isn ot used.
NewSoftSerial mySerial(2, 3);
int minutes;
int deciminutes;
int seconds;
int deciseconds;

void setup() {
  Serial.begin(9600);
  // set the data rate for the NewSoftSerial port
  mySerial.begin(9600);
  //all digits off
  mySerial.print("xxxx");
  //activate colon
  mySerial.print(0x77, BYTE);
  mySerial.print(0x10, BYTE);
  //reset display
  mySerial.print(0x76, BYTE);
}

void loop() {
  seconds++;
  if(seconds > 9) {
    seconds = 0;
    deciseconds++;
  }
  if(deciseconds > 5) {
    deciseconds = 0;
    minutes++;
  }
  if(minutes > 9) {
    minutes = 0;
    deciminutes++;
  }
  if(deciminutes > 9) {
    deciminutes = 0;
    mySerial.print("xxxx");
  }
  if(deciminutes > 0) {
    mySerial.print(deciminutes);
    mySerial.print(minutes);
    mySerial.print(deciseconds);
    mySerial.print(seconds);
  } else {
    mySerial.print("x");
    if(minutes > 0) {
      mySerial.print(minutes);
      mySerial.print(deciseconds);
      mySerial.print(seconds);
    } else {
      mySerial.print("x");
      if(deciseconds > 0) {
        mySerial.print(deciseconds);
        mySerial.print(seconds);
      } else {
        mySerial.print("x");
        mySerial.print(seconds);
      }
    }
  }
  delay(1000); 
}
Here is a small demonstration. You could also use the module as a timer, a counter or simply a digital clock.

Tuesday, January 18, 2011

Waving Display with Arduino

When I first got my SunSPOT kit two years ago, the first example I ran on it was a demo called AirText. The SPOTs have 8 LEDs aligned in a row on-board. What the example did was to light up the on-board LEDs at a certain frequency. You have to imagine that a character consists of several columns. When displaying one column after another you get the whole character. For example for an 'H' you would set all LEDs of the column to high. Afterwards you would set all LEDs to low except for the middle one. Then again you would set all LEDs to high.

I build a small array of 5 red LEDs and hooked them up to the Arduino board. If I start the program with the board just lying on the table, you would see some flashing LEDs. Nothing fancy so far. But if I pick up the board and wave it continously from left to right at a certain frequency, you can see each column of a character after another "written" into the air, which forms the whole character.

The setup is pretty easy. Here is a simplified schematic:

The source code is easy as well. You can extend it to write new characters. You might need to enhance the LED array or the column count if you want to display special characters, as I only worked with a 3x5 display.

int top = 8;
int topmiddle = 9;
int middle = 10;
int bottommiddle = 11;
int bottom = 12;
int characterDelay = 500;
int columnDelay = 15;

void setup() {
}

void loop() {
  displayH();
  allOff();
  displayE();
  allOff();
  displayL();
  allOff();
  displayL();
  allOff();
  displayO();
  allOff();
}

//I found that by displaying the columns from left to right
//and then again from right to left gives a better result.
void displayH() {
    //set left column all high
    digitalWrite(top, HIGH);
    digitalWrite(topmiddle, HIGH);
    digitalWrite(middle, HIGH);
    digitalWrite(bottommiddle, HIGH);
    digitalWrite(bottom, HIGH);
    delay(columnDelay);
    //set all low except middle
    digitalWrite(top, LOW);
    digitalWrite(topmiddle, LOW);
    digitalWrite(bottommiddle, LOW);
    digitalWrite(bottom, LOW);
    delay(columnDelay);
    //set right column all high (middle is still high)
    digitalWrite(top, HIGH);
    digitalWrite(topmiddle, HIGH);
    digitalWrite(bottommiddle, HIGH);
    digitalWrite(bottom, HIGH);
    delay(columnDelay);
    //second delay so that right column is still high
    delay(columnDelay);
    //set all low except middle
    digitalWrite(top, LOW);
    digitalWrite(topmiddle, LOW);
    digitalWrite(bottommiddle, LOW);
    digitalWrite(bottom, LOW);
    delay(columnDelay);
    //set right column all high (middle is still high)
    digitalWrite(top, HIGH);
    digitalWrite(topmiddle, HIGH);
    digitalWrite(bottommiddle, HIGH);
    digitalWrite(bottom, HIGH);
    delay(columnDelay);
}

void displayE() {
    digitalWrite(top, HIGH);
    digitalWrite(topmiddle, HIGH);
    digitalWrite(middle, HIGH);
    digitalWrite(bottommiddle, HIGH);
    digitalWrite(bottom, HIGH);
    delay(columnDelay);
    digitalWrite(topmiddle, LOW);
    digitalWrite(bottommiddle, LOW);
    delay(columnDelay);
    delay(columnDelay);
    delay(columnDelay);
    delay(columnDelay);
    digitalWrite(topmiddle, HIGH);
    digitalWrite(bottommiddle, HIGH);
    delay(columnDelay);
}

void displayL() {
  digitalWrite(top, HIGH);
  digitalWrite(topmiddle, HIGH);
  digitalWrite(middle, HIGH);
  digitalWrite(bottommiddle, HIGH);
  digitalWrite(bottom, HIGH);
  delay(columnDelay);
  digitalWrite(top, LOW);
  digitalWrite(topmiddle, LOW);
  digitalWrite(middle, LOW);
  digitalWrite(bottommiddle, LOW);
  delay(columnDelay);
  delay(columnDelay);
  delay(columnDelay);
  delay(columnDelay);
  digitalWrite(top, HIGH);
  digitalWrite(topmiddle, HIGH);
  digitalWrite(middle, HIGH);
  digitalWrite(bottommiddle, HIGH);
  delay(columnDelay);
}

void displayO() {
    digitalWrite(top, HIGH);
    digitalWrite(topmiddle, HIGH);
    digitalWrite(middle, HIGH);
    digitalWrite(bottommiddle, HIGH);
    digitalWrite(bottom, HIGH);
    delay(columnDelay);
    digitalWrite(topmiddle, LOW);
    digitalWrite(middle, LOW);
    digitalWrite(bottommiddle, LOW);
    delay(columnDelay);
    digitalWrite(topmiddle, HIGH);
    digitalWrite(middle, HIGH);
    digitalWrite(bottommiddle, HIGH);
    delay(columnDelay);
    delay(columnDelay);
    digitalWrite(topmiddle, LOW);
    digitalWrite(middle, LOW);
    digitalWrite(bottommiddle, LOW);
    delay(columnDelay);
    digitalWrite(topmiddle, HIGH);
    digitalWrite(middle, HIGH);
    digitalWrite(bottommiddle, HIGH);
    delay(columnDelay);
}

//set all LEDs off in between characters and provide a bigger delay
void allOff() {
  digitalWrite(top, LOW);
  digitalWrite(topmiddle, LOW);
  digitalWrite(middle, LOW);
  digitalWrite(bottommiddle, LOW);
  digitalWrite(bottom, LOW);
  delay(characterDelay);
}
 
In the video you can see me waving the breadboard continously from left to right varying my waving frequency until you can see the letters a little bit better. I think the result right at the end is the best one.

Monday, January 17, 2011

Shell Game Arduino

Since I have no new sensors left to connect to the Arduino for now, I thought about various small experiments I could do with the components I have. One of those experiments is a Shell Game.

You know those shady guys on the street that bet, you can't spot under which cup they put a ball while shuffling them? Well, this is called a shell game, because in the past it was played with walnut shells. Unfortunately those games are fraud and after someone else wins (another con man), you are up to a big loss.

In this experiment you can build your own shell game. Its intended to be used as an eye training and not to rip off your friends. So don't do anything evil with it.

At each round three LEDs are turned on at random for a very short amount of time. At the end you can guess which light flashed last. If you press the correct button, a green LED blinks. If you were wrong, a red LED blinks.

The setup is simple. Here is a schematic on how to connect everything to the Arduino Uno. Note that I left out the resistors in front of each LED so that the image doesn't get too crowded. I used 470Ω resistors. You need the resistors so that the LEDs don't get damaged by too much current.

The source code is pretty simple. You can change the On/Off delays for the LEDs to adjust the difficulty.
int leftLED = 2;
int middleLED = 3;
int rightLED = 4;
int upperLED = 5;
int lowerLED = 6;
int leftButton = 7;
int middleButton = 8;
int rightButton = 9;
int randomLED;
int lastLED;
int answerLED;
int analogReadSum;
boolean answerGiven = false;

void setup() {
  digitalWrite(leftButton, HIGH);
  digitalWrite(middleButton, HIGH);
  digitalWrite(rightButton, HIGH);
}

void loop() {
  answerGiven = false;
  //All analog ports are read, summed up and devided by their count.
  //There are fluctuations on the ports, so we should get a new number in each run.
  for(int x = 0; x < 6; x++) {
    analogReadSum += analogRead(x);
  }
  analogReadSum /= 6;
  //Initialize random sequence by unique number
  randomSeed(analogReadSum);
  analogReadSum = 0;
  for(int x = 0; x < 10; x++) {
    randomLED = random(2,5);
    digitalWrite(randomLED, HIGH);
    delay(15);
    digitalWrite(randomLED, LOW);
    delay(10);
    if(x == 9) {
      lastLED = randomLED;
    }
  }
  while(answerGiven == false) {
    if(digitalRead(leftButton) == LOW) {
      answerLED = 2;
      answerGiven = true;
    } else if(digitalRead(middleButton) == LOW) {
      answerLED = 3;
      answerGiven = true;
    } else if(digitalRead(rightButton) == LOW) {
      answerLED = 4;
      answerGiven = true;
    }
  }
  if(answerLED == lastLED) {
    for(int x = 0; x < 3; x++) {
      digitalWrite(upperLED, HIGH);
      delay(1000);
      digitalWrite(upperLED, LOW);
      delay(500);
    }
  } else {
    for(int x = 0; x < 3; x++) {
      digitalWrite(lowerLED, HIGH);
      delay(1000);
      digitalWrite(lowerLED, LOW);
      delay(500);
    }
  }
}
Here is a small clip of the game:

Friday, January 14, 2011

LAN Webserver with Arduino

Just to make things complete, I wanted to show you the alternative to the WiFly shield, the Ethernet shield. It is a heck of a lot easier to work with. There are already some example ethernet sketches available in the Arduino IDE and the board comes preassembled, so you really only have to stack it on top of your Arduino, connect it to your network and define some settings in the code. You could even log some data with the onboard micro SD card slot.

Here is a sample image of the Webserver in action.



The code is pretty much the same as in the example which is provided by the IDE and only differs from my WiFly example in the setup part. You only have to define your network settings accordingly.

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
byte ip[] = { 127, 0, 0, 1 };

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
Server server(80);

void setup()
{
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();
}

void loop()
{
  // listen for incoming clients
  Client client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          // print something, in HTML format:
          client.print("LAN Webserver Running!");
          client.println("<br />");
          client.print("Visit ");
          client.print("<a href=\"http://marioboehmer.blogspot.com\">marioboehmer.blogspot.com</a>");
          client.print(" for more experiments!");
          client.println("<br />"); 
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
  }
}

WiFi Webserver with Arduino

Today I want to show you, how to use your Arduino as a webserver or how to transmit data wirelessly. I used the WiFly shield from sparkfun. The only thing I had to do was to solder on some connector pins, so I could stack the module on the Arduino. The module itself works out of the box. You only need some configurations for your network connection. The first thing to do is to connect the board with your Arduino and run a first example sketch to see if works properly. You can find an excellent tutorial for some basic first steps here.

After uploading the first example sketch to the Arduino, open the Serial Monitor and explore some of the commands from the datasheet. One of the most important things you might want to know is the MAC address of your WiFly module. After you switched to the command mode, just enter "get mac". Now you can configure your router to assign a DHCP address for example. For details about all the commands and how the module works look into the datasheet.

One thing to remember is to introduce the module to your network at startup time. So in your setup method you have to send all the necessary information like passphrase, listenport and stuff like that to your module. To communicate easily with the module, I used a high level WiFly Shield library found here.

Source (just insert your configurations where marked with <insert> :
#include "WiFly.h"

Server server(80);

void setup() {
  Serial.begin(9600);
  SpiSerial.begin();
 
  //exit CMD mode if not already done
  SpiSerial.println("");
  SpiSerial.println("exit");
  delay(1000);
 
  //set into CMD mode
  SpiSerial.print("$$$");
  delay(1000);

  //set authorization level
  SpiSerial.println("set w a <insert>");
  delay(1000);

  //set passphrase
  SpiSerial.println("set w p <insert>");
  delay(1000);
 
  //set localport
  SpiSerial.println("set i l 80");
  delay(1000);
 
  //disable *HELLO* default message on connect
  SpiSerial.println("set comm remote 0");
  delay(1000);

  //join wifi network <ssid>
  SpiSerial.println("join <insert>"); 
  delay(5000);
 
  //exit CMD mode
  SpiSerial.println("exit"); 
  delay(1000);  
}


void loop() {
  listenForClients();
}

void listenForClients() {
  // listen for incoming clients
  Client client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          // print something, in HTML format:
          client.print("WiFly Webserver Running!");
          client.println("<br />");
          client.print("Visit ");
          client.print("<a href=\"http://marioboehmer.blogspot.com\">marioboehmer.blogspot.com</a>");
          client.print(" for more experiments!");
          client.println("<br />"); 
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
  }
}
You can see in the video that the WiFly board is blinking when I send a request to its address.

Thursday, January 13, 2011

Motion Sensor on Arduino

I already showed you the example of connecting a radar sensor to the Arduino. While radar sensors are very good at detecting frontal motion, they have their weaknesses when it comes to detecting motion in a wider angle. They are triggered by any object which reflects their radar waves.
For bypassing motion you normally use a passive infrared motion sensor (PIR). They aren't that great when it comes to detecting frontal motion, but they are sensitive to motion in a wider angle. They are called passive infrared motion sensors, because they detect infrared radiation which is emitted by every living person. The hotter your body temperature, the more you emit.

I used the ePIR sensor board from Zilog. You can configure the sensors sensitivity, you can set it to sleep to preserve energy and you can couple it with a light sensor so it won't be triggered at day time. For details on how to configure it, have a look into the datasheet. I used a simple default connection and didn't want to configure anything.

Here is a default setup:



The source code is also pretty simple:
int sleepModePin = 4;
int motionDetectPin = 2;
int alarmLED = 12;
int val;

void setup() {
  //the sleep pin has to be active high to enable detection
  digitalWrite(sleepModePin, HIGH);
}

void loop() {
  val = digitalRead(motionDetectPin);
  //the ePIR sensor is active low so if motion is detected the output is low
  if(val == LOW) {
    digitalWrite(alarmLED, HIGH);
  } else {
    digitalWrite(alarmLED, LOW);
  }
}
Motion sensor in action:

Microphone on Arduino

Today I connected a microphone mini board from sparkfun to the Arduino. After soldering on some connector pins you have three connections. Vcc, which works from 2.7V up to 5.5V, GND and the Signal pin. I used 5V for Vcc. I used an additional 4.7kΩ resistor to pull up the ADC value read from the analog port of the Arduino. You might not need it though. As an indicator for signal strength / loudness, I used three LEDs which were triggered if a certain threshold is passed. So it is kind of an equalizer.

Here is the basic setup:


The code is pretty easy. The only thing you might change are the threshold values, because your background noise might differ.
int audioPort = 0;
int val;
int greenLed = 7;
int yellowLed = 4;
int redLed = 2;
int lowThreshold = 780;
int mediumThreshold = 890;
int highThreshold = 1000;

void setup() {
  pinMode(greenLed, OUTPUT);
  pinMode(yellowLed, OUTPUT);
  pinMode(redLed, OUTPUT); 
}

void loop() {
  val = analogRead(audioPort);
  if(val > highThreshold) {
    digitalWrite(redLed, HIGH);
    delay(10);             
    digitalWrite(redLed, LOW);
  } else if(val > mediumThreshold) {
    digitalWrite(yellowLed, HIGH);
    delay(10);             
    digitalWrite(yellowLed, LOW);
  } else if(val > lowThreshold) {
    digitalWrite(greenLed, HIGH);
    delay(10);             
    digitalWrite(greenLed, LOW);
  }
}
I wanted to use one of my favorite songs to demonstrate this experiment, but since I don't want to get into any trouble with the RIAA or the GEMA, I used a recording of me playing my dobro.

Wednesday, January 12, 2011

Temperature and Humidity Sensor on Arduino

I already posted about connecting a temperature sensor to the Arduino, but I wanted to use the opportunity to introduce a small combo board. The SHT15 mini board from sparkfun. They made a convenient mini board to easily access the SHT15 sensor from sensirion, which is well documented. After soldering on a connector for the breadboard, I found a blog post which provided a good working source code to access the data. I changed it only slightly because it already provided the access methods to get the data from the sensor.

The setup is trivial but here it is anyway:



All of the credits for the source go to Maurice Ribble:
int gTempCmd  = 0b00000011;
int gHumidCmd = 0b00000101;
int theDataPin  = 10;
int theClockPin = 11;
int temperatureVal;
int currentTemperatureInF;
int currentTemperatureInC;
int humidityVal;
int currentHumidityInPercent;
int ack;
 
int shiftIn(int dataPin, int clockPin, int numBits)
{
   int ret = 0;
   int i;

   for (i=0; i<numBits; ++i)
   {
      digitalWrite(clockPin, HIGH);
      delay(10);  // I don't know why I need this, but without it I don't get my 8 lsb of temp
      ret = ret*2 + digitalRead(dataPin);
      digitalWrite(clockPin, LOW);
   }

   return(ret);
}

void sendCommandSHT(int command, int dataPin, int clockPin)
{
  // Transmission Start
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  digitalWrite(dataPin, HIGH);
  digitalWrite(clockPin, HIGH);
  digitalWrite(dataPin, LOW);
  digitalWrite(clockPin, LOW);
  digitalWrite(clockPin, HIGH);
  digitalWrite(dataPin, HIGH);
  digitalWrite(clockPin, LOW);
          
  // The command (3 msb are address and must be 000, and last 5 bits are command)
  shiftOut(dataPin, clockPin, MSBFIRST, command);

  // Verify we get the correct ack
  digitalWrite(clockPin, HIGH);
  pinMode(dataPin, INPUT);
  ack = digitalRead(dataPin);
  if (ack != LOW)
    Serial.println("Ack Error 0");
  digitalWrite(clockPin, LOW);
  ack = digitalRead(dataPin);
  if (ack != HIGH)
     Serial.println("Ack Error 1");
}

void waitForResultSHT(int dataPin)
{
  int i;
 
  pinMode(dataPin, INPUT);
 
  for(i= 0; i < 100; ++i)
  {
    delay(10);
    ack = digitalRead(dataPin);

    if (ack == LOW)
      break;
  }
 
  if (ack == HIGH)
    Serial.println("Ack Error 2");
}

int getData16SHT(int dataPin, int clockPin)
{
  int val;
 
  // Get the most significant bits
  pinMode(dataPin, INPUT);
  pinMode(clockPin, OUTPUT);
  val = shiftIn(dataPin, clockPin, 8);
  val *= 256;

  // Send the required ack
  pinMode(dataPin, OUTPUT);
  digitalWrite(dataPin, HIGH);
  digitalWrite(dataPin, LOW);
  digitalWrite(clockPin, HIGH);
  digitalWrite(clockPin, LOW);
          
  // Get the least significant bits
  pinMode(dataPin, INPUT);
  val |= shiftIn(dataPin, clockPin, 8);

  return val;
}

void skipCrcSHT(int dataPin, int clockPin)
{
  // Skip acknowledge to end trans (no CRC)
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);

  digitalWrite(dataPin, HIGH);
  digitalWrite(clockPin, HIGH);
  digitalWrite(clockPin, LOW);
}

void setup()
{
   Serial.begin(9600); // open serial
}

void loop()
{
  sendCommandSHT(gTempCmd, theDataPin, theClockPin);
  waitForResultSHT(theDataPin);
  temperatureVal = getData16SHT(theDataPin, theClockPin);
  skipCrcSHT(theDataPin, theClockPin);
  Serial.print("Temperature in F:");
  currentTemperatureInF = -40.2 + 0.018 * (float)temperatureVal;
  Serial.println(currentTemperatureInF, DEC);
  Serial.print("Temperature in C:");
  currentTemperatureInC = -40.1 + 0.01 * (float)temperatureVal;
  Serial.println(currentTemperatureInC, DEC); 
 
  sendCommandSHT(gHumidCmd, theDataPin, theClockPin);
  waitForResultSHT(theDataPin);
  humidityVal = getData16SHT(theDataPin, theClockPin);
  skipCrcSHT(theDataPin, theClockPin);
  Serial.print("Humidity in percent:");
  currentHumidityInPercent = -4.0 + 0.0405 * humidityVal + -0.0000028 * humidityVal * humidityVal;
  Serial.println(currentHumidityInPercent, DEC);
  Serial.println("");
}
Here is a small demonstration:

LCD Display on Arduino

Let's hook up a LCD display to our Arduino. It is actually pretty easy to do that because there are already pre assembled boards, which can be soldered to adapter boards if you want to use a bus system for example, like I did. However, you could just connect the display board itself directly to the Arduino. Here is a simple schematic of how to do that. You can find plenty of information about LCD displays on the web. Here is a good introduction of the Hitachi HD44780, if you're interested.

To interface the LCD display with an Arduino is also made pretty easy. There already is the LiquidCrystal library which can be used with the Hitachi HD44780 or any compatible chipset. The Arduino IDE comes with an example on how to use it. I share my modified code anyway, so you can have a look at how easy it is.

Souce code:
#include <LiquidCrystal.h> // include a library headfile
// LiquidCrystal display with:
// rs on pin 10
// rw on pin 11
// enable on pin 12
// d4, d5, d6, d7 on pins 13, 14, 15, 16
LiquidCrystal lcd(10, 11, 12, 13, 14, 15, 16);

void setup() {
  lcd.begin(16, 2);
}

void loop() {
  lcd.clear(); //clears the LCD and positions the cursor in the upper-left corner
  lcd.setCursor(3,0); //move cursor to column 4 row 1
  lcd.print("Hi there!"); //print a message to the LCD
  delay(2000);
  lcd.setCursor(3,1); //move cursor to column 4 row 2
  lcd.print("Check out");
  delay(2000);
  lcd.clear();
  lcd.print("marioboehmer.");
  lcd.setCursor(3,1);
  lcd.print("blogspot.com");
  delay(2000);
  lcd.clear();
  lcd.setCursor(3,0);
  lcd.print("for more");
  delay(2000);
  lcd.setCursor(1,1);
  lcd.print("experiments!");
  delay(2000);
}
Here it is in action:

Tilt Switch on Arduino

Another simple component is a tilt switch. This simple tilt switch has a mercury ball inside which closes the circuit and sends a high to the input if it is tilted. As an indicator I chose a LED mini board. Both boards can be found in the starter kit from seeedstudio.

This is the souce code. Plain and simple.
int tiltSwitch = 9;
int led = 8;

void setup() {
  pinMode(led,OUTPUT);
  pinMode(tiltSwitch,INPUT);
}

void loop() {
  if(digitalRead(tiltSwitch))
    digitalWrite(led,HIGH);
  else
    digitalWrite(led,LOW);
}

Here is a small demonstration:

Tuesday, January 11, 2011

Light Sensor on Arduino

The next board I'd like to write about, is the light sensor mini board. The situation is similar to the temperature board. Easy to connect, but this time there was no datasheet at all. I couldn't find out which photoresistor was used, so the value which was read had to be approximated as well. I found a good resource of the theory of calculation here.

Here is the source code to this example:
int lightSensor = 2;
int lightADCReading;
double currentLightInLux;
double lightInputVoltage;
double lightResistance;

void setup() {
  Serial.begin(9600);
}

void loop() {
  lightADCReading = analogRead(lightSensor);
  // Calculating the voltage of the ADC for light
  lightInputVoltage = 5.0 * ((double)lightADCReading / 1024.0);
  // Calculating the resistance of the photoresistor in the voltage divider
  lightResistance = (10.0 * 5.0) / lightInputVoltage - 10.0;
  // Calculating the intensity of light in lux       
  currentLightInLux = 255.84 * pow(lightResistance, -10/9);

  Serial.print("Light ADC reading: ");
  Serial.println(lightADCReading);
  Serial.print("Light in lux: ");
  Serial.println(currentLightInLux);
  delay(2000);
}

This is the output of the program:

Temperature Sensor on Arduino

The temperature sensor mini board from seeedstudio is also really easy to connect to the Arduino board. That's the beauty of those mini boards. However, it has one flaw though. The thermistor which is used on the board has not a very good datasheet. I wasn't able to come up with an exact formular to calculate the ADC readings to degrees celsius. I used a formular which I found on the web. Note that this formular is for linear thermistors and is meant for a certain circuit setup. So my readings are more or less approximations based on that formular. To shortly increase the value I breathed on the thermistor.

Here is the source:
int temperatureSensor = 1;
int temperatureADCReading;
float currentTemperatureInCelsius;

void setup() {
  Serial.begin(9600);
}

void loop() {
  temperatureADCReading = analogRead(temperatureSensor);
  currentTemperatureInCelsius = 25 + (temperatureADCReading - 512) / 11.3;

  Serial.print("Temperature ADC reading: ");
  Serial.println(temperatureADCReading);
  Serial.print("Temperature in C: ");
  Serial.println(currentTemperatureInCelsius);
  delay(2000);
}
This is the program printing out those readings:

Piezo Buzzer on Arduino

The piezo buzzer has a thin metal membrane. When voltage is applied to the component at a certain frequency, the membrane gets into a vibrating motion which produces soundwaves. With changes in frequency you can control the sound output.

Another great thing is, that you can use the piezo buzzer also as an input device. Audio waves can influence its membrane and can set it into a vibrating motion. When this happens, the output voltage of the component changes and you can detect sound.

There were already some great tutorials on the web, so I only had to change the source code according to pin layout or threshold values. Connecting the buzzer is pretty easy. In most cases you only might need a resistor in your circuit to limit the current, that's all. I simplified my experiments with an Arduino shield from seeedstudio.com which adapts the Arduino pins to connector ports and busses, which can be easily used when connecting to other boards. I also got some mini sensor circuit boards which makes prototyping quite easy. Here you can find the piezo buzzer used in this experiment.

Some simple experiments using the connector shield and the buzzer can be found here.

So first, let's hear the buzzer in action:


When experimenting with the frequencies and duration of the output, you even can produce some melodies. A tutorial of playing some notes can be found on the Arduino tutorial page.

Here is my attempt:


Now, to use the piezo buzzer for detecting sound or vibration you have to experiment with the threshold value in your code, so it won't be triggered by background noise. The Arduino tutorial page provides source code for this experiment as well.

I could have improved my threshold even more, but you can see that it works anyway.

Monday, January 10, 2011

GpsArduino

I also wanted to provide an example of how to connect the EM-406A GPS module to the Arduino Uno.

The setup is pretty easy and equal to the setup which was used for the GpsSPOT experiment. You only have to connect the respective ports of the Arduino board.

This is a simplified schematic of the connections which have to be made:

The source code was a little bit trickier to figure out. Since the module works with a baud rate of 4800 bits per second, you have to consider appropriate delays before reading the next bit. Because we read one bit at a time, we have to use bit shifting to get the whole byte which can be translated to a character via an Ascii-table. Note that I only implemented the GPPGA format in this example.

The data is transmitted via the serial port to the PC. You can use Hyperterminal to display the data. Just configure the port where your Arduino is connected to and set a baud rate of 9600. The data is displayed in a comma seperated format which could be parsed.

Source code:

#include <string.h>

#define bit4800Delay 200
#define halfBit4800Delay 100

byte rx = 4;
byte tx = 2;

void setup() {
  //reads EM-406A tx line
  pinMode(rx,INPUT);
  //writes to EM-406A rx line
  pinMode(tx,OUTPUT);
  //if rx of the EM-406A is not used it must be set to high
  digitalWrite(tx,HIGH);
 
  //init serial port to write output to terminal
  Serial.begin(9600);
 
  //init done, flash LED
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH); 
  delay(500);            
  digitalWrite(13, LOW);
}

byte readByte()
{
  byte val = 0;
  while (digitalRead(rx));
  //wait for start bit
  if (digitalRead(rx) == LOW) {
    delayMicroseconds(halfBit4800Delay);
    for (int offset = 0; offset < 8; offset++) {
    delayMicroseconds(bit4800Delay);
    val |= digitalRead(rx) << offset;
    }
    //wait for stop bit + extra
    delayMicroseconds(bit4800Delay);
    delayMicroseconds(bit4800Delay);
    return val;
  }
}

String getGPGGAMessage() {
  char val;
  String message = "";
  byte thresholdCounter = 0;
  while (thresholdCounter < 10) {
    val = readByte();
    if (val == '\n') {
      if (message.startsWith("$GPGGA")) {
        return message;
      } else {
        thresholdCounter++;
        message = "";
      }
    } else {
    // recover from bad read .. reset
      if (val == '$') {
       message = "";
      }
      message += (char) val;
    }
  }
  return "";
}

void loop() {
  Serial.println(getGPGGAMessage());
}
 
And here we go with a little demonstration:

Sunday, January 9, 2011

RadarArduino

Just to give a comparison, I decided to repeat the experiments that I did with the SunSPOT also with the Arduino. So today I present the RadarArduino. The circuit setup stayed the same as in the SunSPOT post. You only have to connect the 5V port, the GND port and the A0 port of the Arduino respectively.

This is the simplified schematic of the connections which have to be made:



The source code is really easy and quite short:
/*
  Radar Arduino.
  Analog input is read continously and the onboard LED reacts
  if a certain threshold is passed.
*/

int a0 = 0;
int currentReading;

void setup() {
  pinMode(13, OUTPUT);
}

void loop() {
  currentReading = analogRead(a0);
  if(currentReading > 250) {
    digitalWrite(13, HIGH); 
    delay(100);            
    digitalWrite(13, LOW);
  }
  delay(100);
}
Here is the short clip of the experiment:

Saturday, January 8, 2011

ServoArduino

Today I wanted to check out how the Arduino Uno handles a servo. Since I wanted to create a similar setup as with the SunsPOT, I had to connect switches to the Arduino first.

Handling switches is pretty easy. All you need to do is to connect one connection of the switch to a digital port and the other connection of the switch to GND. In the software later on, you can use the boards integrated pull up resistors to set the digital port to high. Now if the switch is pressed, you have a connection to GND and the signal on the port changes to low. This setup had to be done for two switches.

Now the only thing left to do was to connect the servo to the Arduino. The Vin connector of the servo has to be connected to the 5V port of the Arduino. The GND connector has to be connected to a GND port of the Arduino and the signal connector to a port with PWM (pulse-width modulation). They are marked with a ~ sign.

Here is a simple schematic of the setup:



The source code is pretty straight forward. You only need to include the servo library.

#include <Servo.h>
Servo servo;
int pos;
int switchLeft = 4;
int switchRight = 2;
int switchValueLeft;
int switchValueRight;

void setup() {
  //assign pin 9 to the servo
  servo.attach(9);
  pinMode(13, OUTPUT);
  //assign the two switches
  pinMode(switchLeft, INPUT);
  pinMode(switchRight, INPUT);
  //set both digital ports to high
  digitalWrite(switchLeft, HIGH);
  digitalWrite(switchRight, HIGH);
 
  //just shows a LED signal that the arduino is ready
  digitalWrite(13, HIGH);  
  delay(500);             
  digitalWrite(13, LOW);
  delay(500);
}

void loop() {
  //read current value on the port
  switchValueLeft = digitalRead(switchLeft);
  switchValueRight = digitalRead(switchRight);
  if(switchValueLeft == LOW) {
    //if left button is pressed, move left
    pos+=10;
  } else if(switchValueRight == LOW) {
    //if right button is pressed, move right
    pos-=10;
  }
  //keeps the servo value in its range
  if(pos > 180) {
    pos=180;
  } else if(pos < 0){
    pos=0;
  }
  //move servo
  servo.write(pos);
  delay(100);
}
This is a demonstration of the Arduino controlled servo:

Friday, January 7, 2011

Arduino Hello World in Morse Code

Finally, it arrived! The Arduino kit and some additional hardware has just arrived today and as always, the all time favorite "Hello World" has to serve as a first experiment. I decided to spice it up a little bit though. I let the Arduino board "talk" in morse code through its onboard LED.

So here it goes. The first code snippet and a video of the Arduino board greeting all of you :).

/*
  Morse Code Hello World.
  One unit is equal to 250 ms in this example.
 */

void setup() {               
  // initialize the digital pin as an output.
  pinMode(13, OUTPUT);    
}

void loop() {
  //show H . . . .
  for(int x = 0; x < 4; x++) {
    dot();
  }

  //show E .
  dot();

  //show L . - . . (2 times)
  for(int x = 0; x < 2; x++) {
    dot();
    dot();
    dash();
    dot();
  }

  //show O - - -
  for(int x = 0; x < 3; x++) {
    dash();
  }
 
  //show space (waiting time between words is equal to seven units)
  digitalWrite(13, LOW);   
  delay(7 * 250);

  //show W . - -
  dot();
  dash();
  dash();

  //show O - - -
  for(int x = 0; x < 3; x++) {
    dash();
  }

  //show R . - .
  dot();
  dash();
  dot();
 
  //show L . - . .
  dot();
  dash();
  dot();
  dot();
 
  //show D - . .
  dash();
  dot();
  dot();
 
  //show space (waiting time between words is equal to seven units)
  digitalWrite(13, LOW);   
  delay(7 * 250);
}

//dot is equal to one unit
void dot() {
  digitalWrite(13, HIGH);  
  delay(250);             
  digitalWrite(13, LOW);
  //pause between next sign is one unit 
  delay(250);
}

//dash is equal to 3 units
void dash() {
  digitalWrite(13, HIGH);  
  delay(750);             
  digitalWrite(13, LOW);
  //pause between next sign is one unit   
  delay(250);
}