Recent Changes - Search:

Home

edit SideBar

ArduinoMini

On this page... (hide)

  1. 1. Use of Arduino
  2. 2. Programming
    1. 2.1 Shaft Encoders
    2. 2.2 I2C on the Mini
Arduino Mini of Flickr 
Arduino Mini on Flickr 

The Arduino Mini  board is a 24-pin board with an ATmega168  microcontroller broken out to its pins. The board is a faster and more feature-rich upgrade for a Basic Stamp or BX-24 unit, however they are not pin-compatible. It is a smaller version of the Arduino board, an open-source hardware project focused on providing a capable yet easy to use microcontroller for the masses.

1.  Use of Arduino

Since we already have a fast computer on our 'bot, the Arduino isn't necessarily needed, but we added it because it brings on-board D/A converters and ease of hardware integration. We also thought it would make a good exercise in using multiple computers and syncing data between them

2.  Programming

2.1  Shaft Encoders

The primary purpose of the Arduino is to provide an interface to the optical encoders. Initially, we thought it would be easiest to create an interrupt on a rising edge of the phototransistor, but since the fully-saturated output of the element is only about 0.5 V - well below the interrupt threshold - we decided to just use one of the on-board D/A lines and continuously poll it. We attached the output of the phototransistor to the analog input pin 3. In order to detect the rising edge of the output, we had to come up with a bit of logic, as such:

int analogPin = 3;
int val = 0; // variable to store analog value read
int alreadyHigh = 0;
int i; // looper
unsigned long startTime, totalTime;
int count, totalCount;

void setup() // empty
{
}

void loop()
{
  startTime = millis();
  count = 0;
  for (i = 0; i < 1000; i++) {
    val = analogRead(analogPin); // read the input pin
    if (val > 410) {
      if(!alreadyHigh) {
        alreadyHigh = 1;
        count++;
      }
    } else if (alreadyHigh) {
      alreadyHigh = 0;
    }
  }
  totalTime = millis() - startTime;
  totalCount = count;
}

This sets two variables at the end of every loop:

  • totalCount with the number of rising edges detected
  • totalTime containing the duration of time it took to get totalCount readings in milliseconds

It should be noted that millis() rolls over to zero every ~9.5 hours, so totalTime will give erroneous readings once every 9.5 hours or so.

\\The Arduino Stamp as it sits on the 'bot."rframe"

2.2  I2C on the Mini

I2C is available on the Arduino mini by way of the Wire  library from the Wiring project. There are some steps that need to be take on the Mini to get everything to compile, available at Near Future Laboratory .

To summarize:

  • Analog In 4 goes to SDA (not broken out, you must solder to the Mini)
  • Analog In 5 goes to SCL (not broken out, you must solder to the Mini)
  • Delete lib/targets/libraries/Wire/Wire.o
  • Delete lib/targets/libraries/Wire/utility/twi.o
  • Uncomment //#define ATMEGA8 from lib/targets/libraries/Wire/utility/twi.h (line ~27)

Of course, there is a great reference for all the Arduino-specific commands at the Arduino Extended Reference .

Adding I2C functionality, we came up with:

#include <Wire.h>

#define ADDRESS 32
#define C_REG 0
#define T_REG 1
#define THRESHOLD 410

int toSend = 0;
int analogPin = 3;
int val = 0; // variable to store analog value read
int alreadyHigh = 0;
int i; // looper
int startTime, stopTime, totalTime;
int count, totalCount;

void setup()
{
  Wire.begin(ADDRESS);                // join i2c bus with address #32
  Wire.onRequest(requestEvent); // register event
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);  // start serial for output
}

void loop()
{
  startTime = millis();
  count = 0;
  for (i = 0; i < 1000; i++) {
    val = analogRead(analogPin); // read the input pin
    if (val > THRESHOLD) {
      if(!alreadyHigh) {
        alreadyHigh = 1;
        count++;
      }
    } else if (alreadyHigh) {
      alreadyHigh = 0;
    }
  }
  stopTime = millis();
  totalTime = stopTime - startTime;
  totalCount = count;
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent()
{  
  Wire.send(toSend);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
{
  while(1 < Wire.available()) // loop through all but the last
  {
    char c = Wire.receive(); // receive byte as a character
  }
  int x = Wire.receive();    // receive byte as an integer
  switch(x) {
    case C_REG:
      toSend = totalCount;
      totalCount = -1; // reset
    break;
    case T_REG:
      toSend = totalTime;
      totalTime = -1; // reset
    break;
    default: // Bad/Empty register
      toSend = -1; // reset
    break;
  }
}

This creates two registers that can be read from the board

  • Register 0; contains the latest totalCount
  • Register 1; contains the latest totalTime

It takes about 100 microseconds to perform an analog read on the Arduino. In practice, we take 1,000 readings (as defined in the for loop above) in ~112 milliseconds or so. This setup doesn't have any "memory", so you must take a reading at least every 112ms in order to avoid missing any potentially new values from the encoder. This code can be easily extended to take readings over a longer or shorter time period. In an ideal situation the counter would reset whenever the registers are read, but for now we found it easiest to take 1000 readings.

Edit - History - Print - Recent Changes - Search
Page last modified on June 04, 2008, at 05:54 PM EST