Arduino Powered Tachistoscope

, in Computing

About fifteen hundred years ago I wrote WordAppNo longer online, because who runs Java applets these days?, a Java applet tachistoscope that reads a text file from either the local filesystem or the Internet and displays it one word at a time. The idea is that it trains your brain to recognise words quickly, increasing your reading speed. I thought it was a little silly, but according to me web host's logs WordUp still sees a bit of use even though I haven't touched it for years.

I was hunting around for something to do with my Arduino while I waited for some other parts to arrive when I had the idea of making a physical tachistoscope that reads its data off an SD card and displays the text using an LCD display I have lying around.

Arduino powered tachistoscope
Arduino powered tachistoscope

The SD card contains the text to be shown. One of the potentiometers is used to vary the contrast on the LCD. The other is sampled by the CPU and converted into a delay to vary the speed at which the words appear.

Unfortunately the refresh rate of the LCD is very poor, so the text becomes almost impossible to read at even modest speeds. A better display might help, but I am not going to spend any more time and money on something so simple. Fortunately, the other parts I ordered arrived yesterday so I have other things to play with.

/*
An Arduino implementation of a Tachistoscope.
This uses both the LiquidCrystal and SD libraries (and repective devices). The 
words are read one at a time from a file on the SD card. A simple variable resistor
is used to control the speed.
In practice this does not work terribly well since the LCD display has a poor
refresh rate.

Pins: 
The LCD is connected via pins 2-8. Technically I could get away without the RW pin.
The SD card reader is connected via pins 10-13 (the standard SPI pins)
The variable resistor is connected via analog A0

Author: Andrew Stephens http://sheep.horse/
*/

#include <LiquidCrystal.h>
#include <SD.h>

LiquidCrystal lcd(8, 7, 6, 5, 4, 3, 2);
File file;

void setup()
{
  lcd.begin( 16, 2 );
  lcd.clear();
  lcd.setCursor(0, 0);

  pinMode(10, OUTPUT);  // required if I ever change the CS pin from 10
  pinMode(A0, INPUT);

  SD.begin(10);
  file = SD.open("test.txt");
}

// Skip over whitespace, positions the file position at the start of the next
// word
bool findNextWord( File& file )
{
  int r;
  while ((r = file.peek()) != -1 )
  {
    if ( !isSpace(r) )
    {
      return true;
    }
    file.read();
  }
  return false;  
}

// Reads a single word (anything up to the next whitespace character) into
// the given buffer
bool getNextWord( File& file, char* buffer, int bufferSize )
{
  int r;
  while ((r = file.read()) != -1 )
  {
    if ( isSpace( r ) )
    {
      *buffer = '\0';
      return true;
    }
    if (bufferSize > 1 )
    {
      *buffer = r;
      ++buffer;
      bufferSize--;
    }
  }

  *buffer = '\0';
  return false;
}


// originally this function did more
int readResistor()
{
  return analogRead(A0);
}


void loop()
{
  char buffer[17];

  if (findNextWord( file ) )
  {
    getNextWord( file, buffer, sizeof(buffer) );
    lcd.clear();
    lcd.print( buffer );
  }
  else
  {
    lcd.clear();
    lcd.print("--end--");
  }
  int v = readResistor();
  lcd.setCursor(0, 1);
  lcd.print( v );
  delay(v);  
}