M a r k   C r o s b i e

You are in: LEGO Tape reader  Home  Resume  Linux  LEGO  Electronics  Movies  Mac OS X 


Please update your bookmarks..

Go to my new LEGO website

http://mastincrosbie.com/Marks_LEGO_projects

LEGO Tape Reader

For fun I decided to build a LEGO tape drive. There seems to be a lot of interest in building LEGO analogies to digital computer hardware. I've seen LEGO plotters, scanners and even keyboards out there!

Tape drive This first version is primitive, with a storage capacity of 15 bits (yes folks, that's bits). I wanted to start with a very basic setup: a light sensor scans a piece of paper glued to a wheel. The paper has alternating marks of black and white on it, which the light sensor distinguishes as "bits" of data on the tape. The wheel is connected to a rotation sensor so that the bit location on the wheel can be deduced.

Tape Drive reader I measured the circumference of my LEGO wheel, and then measured a strip of paper to fit. I divided the paper into 16 segments, each of equal length. Each segment corresponds to one "bit" of data. Thus one pulse from the rotation sensor indicates that one bit of data has moved past the light sensor.

Each tape starts with a SYNC bit which is twice as wide as a regular bit.

Version 1 of the tape drive simply reads the bits off the tape and stops when it reaches the SYNC bit. The total count of bits read is the displayed. Click here to download the source code.

/* 
 * bitcounter.c
 *
 * Rotate a wheel with a paper barcode and read off the light values
 *
 * Extending on findsync.c, this version searches for a
 * synchronization bit on the paper. A sync bit is a black mark which
 * extends for SYNC rotation sensor pulses.
 *
 * Once we find the sync bit, count how many bits are read until we
 * hit the SYNC bit again
 *
 * Mark Crosbie  9/10/00  mark@mastincrosbie.com
 */

#define DEBUG
#define BEEP

#include 
#include 

#include 
#include 
#include 

#define ROTSENSOR SENSOR_1
#define LIGHTSENSOR SENSOR_3

#define MOTOR MOTOR_A

/* some motor speed settings */
#define CRAWL 10
#define SLOW 50
#define MID_SPEED ((MAX_SPEED - MIN_SPEED) / 2)

/* a handy abs() function */
#define ABS(x) ((x)>=0)?(x):-(x)

/* difference in light sensor reading */
#define THRESHOLD 20

/* function prototypes */
void initall(void);
void findSync(void);
int bitLength(void);
void tapeForwards(int speed);
void tapeBackwards(int speed);

int main(int argc, char *argv[]) {

  int length;

  initall();

  /* turn on the tape */
  tapeForwards(SLOW);

  /* find the SYNC bit marker on the tape and stop */
  findSync();

  /* turn the tape on again */
  tapeForwards(SLOW);

  /* and print how long it is */
  length = bitLength(); 
  lcd_int(length);

  return 0;
}

void initall(void) {
  /* initialize the sensors */
  ds_init(); 
  ds_active(&ROTSENSOR);
  ds_active(&LIGHTSENSOR);

  /* start sensor processing */
  ds_rotation_on(&ROTSENSOR);
  ds_rotation_set(&ROTSENSOR, 0);

  /* let sensor reading stabilize */
  msleep(500);
}

void tapeForwards(int speed) {
  /* and turn on the motor */
  motor_a_dir(fwd);
  motor_a_speed(speed);	   
}

void tapeBackwards(int speed) {
  /* and turn on the motor */
  motor_a_dir(rev);
  motor_a_speed(speed);	   
}

/*
 * Name:
 *    findSync
 *
 * Description:
 *    Rotate the tape until the sync bit is located
 *
 * Parameters:
 *    None
 *
 * Returns:
 *    None - returns when sensor is at sync bit
 * 
 * Globals affected:
 *    None
 *
 * Algorithm:
 *    The sync bit on the tape is SYNC rotation counter pulses long.
 *
 */
void findSync(void) {

  int lastlevel = 0;
  int level = 0, diff;

  /* take the initial reading */
  lastlevel = LIGHT_3;

  while(1) {

    level = LIGHT_3;
    diff = ABS(lastlevel - level); 

    /* darker gives a smaller reading from the light sensor.
     * A darker reading indicates the start of a bit. 
     */
    if( diff > THRESHOLD) {
      motor_a_dir(brake);
      msleep(300);
      motor_a_dir(off);
#ifdef BEEP
      dsound_system(DSOUND_BEEP);
#endif
      return;
    }

    lastlevel = level;

    /* for some reason, this msleep is needed to stabilize the reading
     * from the light sensor
     */
    msleep(1);

  }
}

/*
 * Name:
 *    bitLength
 *
 * Description:
 *    Returns the length of the current bit in rotation sensor pulses
 *
 * Parameters:
 *    None
 *
 * Returns:
 *    length
 * 
 * Globals affected:
 *    None
 *
 * Algorithm:
 *    Run the tape until we get a threshold transition and then return
 *    the rotation sensor count
 *
 */
int bitLength(void) {
  
  int lastlevel = 0;
  int level = 0, diff;

  /* take the initial reading */
  lastlevel = LIGHT_3;

  /* reset the rotation sensor */
  ds_rotation_set(&ROTSENSOR, 0);

  while(1) {

    level = LIGHT_3;
    diff = ABS(lastlevel - level); 

    /* darker gives a smaller reading from the light sensor.
     * A darker reading indicates the start of a bit. 
     * Count how long this bit is
     */
    if( diff > THRESHOLD) {
      motor_a_dir(brake);
      msleep(300);
      motor_a_dir(off);
      return ABS(ROTATION_1);
    }

    lastlevel = level;

    /* for some reason, this msleep is needed to stabilize the reading
     * from the light sensor
     */
    msleep(1);
  }
}


 
cover
Building Robots With Lego Mindstorms
Mario has written an excellent book on advanced building techniques using Mindstorms.
cover
Extreme Mindstorms: an Advanced Guide to LEGO Mindstorms
A more advanced programming guide: covers BrickOS and pbForth and NQC.
cover
Dave Baum's Definitive Guide to LEGO Mindstorms
One of the first good LEGO Mindstorms books. Well worth a read.
cover
Joe Nagata's Lego Mindstorms Idea Book
Wow - someday I want to be able to build LEGO like this!
cover
LEGO Mindstorms Interfacing
How to interface your RCX to the outside world with sensors and actuators.

© 2002-2004 Mark Crosbie   shareright © 2002 Phlash