Tag Archive: arduino


Having been rather addicted to understanding electronics lately, I’m always looking for something to play with. Last week I was about to throw out a broken wireless Microsoft mouse, but I caught myself and ended up taking it apart.

Rotary Encoder from a Mouse

I dug down to the scroll wheel and found out it was a nice little rotary encoder – there’s an LED pointed at two phototransistors (light detectors) in it, as well as a circle of tiny black posts that pass between the LED and the detectors, as you can see to the left.  When the posts pass in front of the detectors, the Arduino reads them and is able to determine which direction they are going and increments or decrements a variable that I can access.

It took me about 4 hours to figure out how to hook this thing up, so I figured I would share the info in case someone else wants to use a rotary encoder from a Microsoft mouse in their project.

If you are holding the encoder so that the rotating half is facing you and the wires are facing down, the pinout is as follows:

Pin 1: Photo Sensor 1
Pin 2: Vcc
Pin 3: Photo Sensor 2
Pin 4: IR LED +
Pin 5: IR LED –

Unlike most of the examples I found for using a rotary encoder, this one requires +Vcc on Pin 2 – power will not flow the other way.  The LED power is very picky too;  I am powering it from the 5v regulated supply on my Arduino through a 1k resistor to keep the right amount of light in the encoder.  Too much light and both sensors will be high for too long and too little, neither will go high.  The hardest part to figure out was the voltage divider circuit for the sensors.  I could get them working ok on an analog input – swinging between about 80-600, but it wasn’t clean enough to input as digital until I found the right resistor: 10k.  This nicely divides the input between ground and +5v so the encoder can be read.

Here is the Arduino sketch for the project as shown in the video above:

// Arduino Rotary Encoder from Mouse Scroll Wheel
// and SparkFun 4 Digit Serial 7-Segment Display
// by Steve Kamerman 12/18/2010
// http://www.stevekamerman.com/2010/12/understanding-a-mouse-scroll-wheel/

// These MUST be on interrupt pins!
#define encoderPinA 2
#define encoderPinB 3

#define displayTXPin 10
#define displayRXPin 11

// used only for sprintf()
#include <stdio.h>

// If you don't have NewSoftSerial, grab it from:
// http://arduiniana.org/libraries/NewSoftSerial/
#include <NewSoftSerial.h>
NewSoftSerial displaySerial(displayRXPin, displayTXPin);

// the value - this must be volatile because it is modified
// during an interrupt function and used in a normal function
volatile unsigned int encoderPos = 0;

void setup() {
  // setup the encoder
  pinMode(encoderPinA, INPUT);
  pinMode(encoderPinB, INPUT);
  attachInterrupt(0, readEncoderA, CHANGE);
  attachInterrupt(1, readEncoderB, CHANGE);  
 
  // setup the display
  pinMode(displayTXPin, OUTPUT);
  displaySerial.begin(9600);
  // reset display
  displaySerial.print("v");
  // Set display brightness
  displaySerial.print(0x7A, BYTE);
  displaySerial.print(0x05, BYTE);
  // set the display to "   0"
  displaySerial.print("xxx0");
}
void loop(){
  displayNumber(encoderPos);
}

// prints the given number, right justified padded with spaces
// sprtinf() is not a great idea if you want to save space
// but I'm really not too worried about it :)
void displayNumber(int num){
  char buf[4];
  sprintf(buf, "%4d", num);
  displaySerial.print(buf);
}

void readEncoderA(){
  if (digitalRead(encoderPinA) == HIGH){
    encoderPos += (digitalRead(encoderPinB) == LOW)? 1: -1;
  }else{
    encoderPos += (digitalRead(encoderPinB) == HIGH)? 1: -1;
  }
}
void readEncoderB(){
  if (digitalRead(encoderPinB) == HIGH){
    encoderPos += (digitalRead(encoderPinA) == HIGH)? 1: -1;
  }else{
    encoderPos += (digitalRead(encoderPinA) == LOW)? 1: -1;
  }
}

Yes, I’m still on the electronics kick. This is something I’ve been wanting to do as part of a complete home automation project down the road: monitor the temperature of the different rooms / zones in my house. Now that I’ve got a few Arduinos laying around and some thermal probes (thermistors) from some broken Radio Shack temperature displays, I’ve got the hardware necessary to make it happen! I first installed the thermal probes in the ceilings of the master bedroom, my daughter’s bedroom and our living room in locations that I thought were least affected by vents, fans, lights and other sources of heat. Here’s a picture of the probe in my living room:

Thermal Probe in my Living Room

Next, I connected the three probes to my Arduino’s Analog Inputs using the thermistors as voltage dividers between +5VDC and Ground.  In order to detect the temperatures and make them accessible via the Arduino’s serial interface, I used a few examples on the Arduino site as the basis for this program, which waits for a character to be sent to the serial port, then outputs the temperatures:

#include <math.h>
//Schematic:
// [Ground] ---- [10k-Resister] -------|------- [Thermistor] ---- [+5v]
//                                     |
//                                Analog Pin 0

double Thermistor(int RawADC) {
 // Inputs ADC Value from Thermistor and outputs Temperature in Celsius
 //  requires: include <math.h>
 // Utilizes the Steinhart-Hart Thermistor Equation:
 //    Temperature in Kelvin = 1 / {A + B[ln(R)] + C[ln(R)]^3}
 //    where A = 0.001129148, B = 0.000234125 and C = 8.76741E-08
 long Resistance;  double Temp;
 Resistance=((10240000/RawADC) - 10000);
 Temp = log(Resistance);
 Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp));
 // Convert Kelvin to Celsius
 Temp = Temp - 273.15;
 // Convert to Fahrenheit
 Temp = (Temp * 9.0)/ 5.0 + 32.0;
 return Temp;
}

void printDouble(double val, byte precision) {
  Serial.print (int(val));  //prints the int part
  if( precision > 0) {
    Serial.print("."); // print the decimal point
    unsigned long frac, mult = 1;
    byte padding = precision -1;
    while(precision--) mult *=10;
    if(val >= 0) frac = (val - int(val)) * mult; else frac = (int(val) - val) * mult;
    unsigned long frac1 = frac;
    while(frac1 /= 10) padding--;
    while(padding--) Serial.print("0");
    Serial.print(frac,DEC) ;
  }
}

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

#define ZoneOne 1   // Analog Pin 0
#define ZoneTwo 2   // Analog Pin 1
#define ZoneThree 3   // Analog Pin 2

double temp;
int inByte = 0;
int sensorDelay = 10;

void loop() {
  if (Serial.available() > 0) {
    inByte = Serial.read();
    Serial.print("Zone1:");
    printDouble(Thermistor(analogRead(ZoneOne)),3);
    Serial.print(" ");
    delay(sensorDelay);
    Serial.print("Zone2:");
    printDouble(Thermistor(analogRead(ZoneTwo)),3);
    Serial.print(" ");
    delay(sensorDelay);
    Serial.print("Zone3:");
    printDouble(Thermistor(analogRead(ZoneThree)),3);
    Serial.print(" ");

    Serial.println("");
  }
}

I had an old laptop with a dead battery that I wasn’t using, so I loaded it with Ubuntu 10.10 x64, Apache, MySQL, PHP and Cacti and put it up in the attic, connected to the Arduino via USB.  I went through the painfully dry Cacti Documentation and wrote a custom Perl script that Cacti uses to poll the Arduino for temperatures:

#!/usr/bin/perl

use Device::SerialPort;
use Time::HiRes qw( usleep );

# Serial Settings
$PORT = "/dev/ttyUSB0";
$ob = Device::SerialPort->new ($PORT) || die "Can't Open $PORT: $!";
$ob->baudrate(115200)   || die "failed setting baudrate";
$ob->parity("none")    || die "failed setting parity";
$ob->databits(8)       || die "failed setting databits";
$ob->handshake("none") || die "failed setting handshake";
$ob->write_settings    || die "no settings";
$ob->read_const_time(50);

while(1){
        $ob->write("x");
        if($_ = $ob->read(255)){
                chomp;
                print "$_\n";
                undef $ob;
                exit;
        }
        usleep(1000 * 10);
}

undef $ob;

Cacti Graph of my Home's Temperature

Lastly, I put a nice graph together that shows a comparison of the three temperatures over time, with a composite average of all three.  Now I can see that my daughter’s room spikes to nearly 90 deg when the heat comes on – ouch!  Using this data I am better able to adjust the vents in each room to keep the temperature consistent throughout the house.  Next I want to take one of those cheap LCD picture displays and tie it to the Cacti graph and put it near the thermostat so I can think twice about turning on the heat or AC!


Arduino Duemilanove

Arduino Duemilanove

I recently bought  a 2010 Honda Accord Crosstour and was shocked to see how large it really is in my garage!  When it’s parked correctly, I have about 18 inches behind it and 26 in front of it, when it’s not, I can’t shut the garage door, or I can’t walk in front of it.  As a fun project, I decided to make a device that would let me know when I’m exactly in position!

Enter the Arduino.  The Arduino is an open-source microcontroller board that can programmed with a C-like language called Processing via USB.  It’s a great way to leverage your programming skills to interact with the world around you.  In order to help me park my car, I used an ultrasonic range finder from Radio Shack called the PING))) Parallax.  This device has a transmitter, receiver and a few processing chips on it.  It sends out a signal and listens for the echo, then returns the total time duration in microseconds.  Since sound travels one inch in about 74 microseconds, you can take this time and divide it by 74 to get the total distance that the sound traveled, then divide it by 2 since you only care about the distance too the object, not its return trip.  My plan was to put the range finder in the back of garage and use three LEDs to show me if my car was too far, too close or parked just the right distance away.  I wrote the code below to get a distance reading every 1.5 seconds, and if the distance changed since the last time it was polled, my car (or something in the garage) must have moved.  In this case, the Arduino starts polling for changes every 100ms and lights up an orange LED if it is over 26 inches away, a green LED if it is between 26 and 20 inches and a red LED if it is under 20 inches away.  I mounted the LEDs on a piece of aluminum and attached it to the wall so I could see it from my car while I’m parking.  After I’m finished parking and the Arduino sees that nothing has moved in over 10 seconds, it turns all the LEDs off and starts polling at 1.5 seconds again.  Simple and effective!

// PING))) Sensor
const int pingPin = 7;

// Indicator LEDs
const int tooFarPin = 13;     // Orange LED
const int justRightPin = 12;  // Green LED
const int tooClosePin = 11;   // Red LED

// Distance Thresholds
const int outOfRange = 108;
const int tooFar = 26;
const int tooClose = 20;

// Sensor Polling Delay (ms)
const int idleSenseDelay = 1500;
// High-Speed Polling Timeout
const int idleTimeout = 10000;
int senseDelay = 1500;

/*  States
0 = Out of range (no car present)
1 = Too Far
2 = Just Right
3 = Too Close
*/

int currentState = 0;
int lastState = 0;
unsigned long lastDistanceChange;
long distance;

void setup() {
    lastDistanceChange = millis();
    pinMode(tooFarPin, OUTPUT);
    digitalWrite(tooFarPin, LOW);
    pinMode(justRightPin, OUTPUT);
    digitalWrite(justRightPin, LOW);
    pinMode(tooClosePin, OUTPUT);
    digitalWrite(tooClosePin, LOW);
}

void loop() {
    long duration, newDistance;

    // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
    // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
    pinMode(pingPin, OUTPUT);
    digitalWrite(pingPin, LOW);
    delayMicroseconds(2);
    digitalWrite(pingPin, HIGH);
    delayMicroseconds(5);
    digitalWrite(pingPin, LOW);

    // The same pin is used to read the signal from the PING))): a HIGH
    // pulse whose duration is the time (in microseconds) from the sending
    // of the ping to the reception of its echo off of an object.
    pinMode(pingPin, INPUT);
    duration = pulseIn(pingPin, HIGH);
    newDistance = duration / 74 / 2;
    if (distance != newDistance) {
        // Something is moving, increase polling rate
        lastDistanceChange = millis();
        senseDelay = 100;
    }
    distance = newDistance;
    currentState = getState(distance);
    if (currentState != lastState) {
        // State changed
        indicateState();
    } else {
        if (senseDelay != idleSenseDelay && (millis() - lastDistanceChange > idleTimeout)) {
            // Idle Timeout has Passed, turn off LEDs
            digitalWrite(tooFarPin, LOW);
            digitalWrite(justRightPin, LOW);
            digitalWrite(tooClosePin, LOW);
            senseDelay = idleSenseDelay;
        }
    }
    lastState = currentState;
    delay(senseDelay);
}

int getState(long distance) {
    if (distance >= outOfRange) { return 0; }
    if (distance >= tooFar) { return 1; }
    if (distance <= tooClose) { return 3; }
    return 2;
}

void indicateState() {
    // Turn off the LEDs that are on
    switch (lastState) {
        case 1:
            digitalWrite(tooFarPin, LOW);
            break;
        case 2:
            digitalWrite(justRightPin, LOW);
            break;
        case 3:
            digitalWrite(tooClosePin, LOW);
            break;
    }
    switch(currentState){
        case 0:
            break;
        case 1:
            digitalWrite(tooFarPin, HIGH);
            break;
        case 2:
            digitalWrite(justRightPin, HIGH);
            break;
        case 3:
            digitalWrite(tooClosePin, HIGH);
            break;
    }
}

And here it is, the finished product!

Fritzing Sketch

PING))) Parallax

Arduino ParkAssist

LED Indicator