Thursday, July 26, 2012

Punch Card Reader - The Hardware

Having used PIL to create software that could scan a card, I spent quite some time mulling over possible ways to make a scanner.   At some point it occurred to me that I could recycle some old curtain rails and use gravity to do the card transport.   This lead to a final design that could be built from materials all ready to hand:  some old curtain rails, an old piece of shelving, tracing paper, a desk lamp, some masking tape, and Blu-Tack.  I made some cutouts in the rails so that the software scanner could identify the side edges of each card and automatically calibrate the card's width (the power drill grabbed as it made it through, so it's best to clamp the rail down securely).  I rounded off all cut edges with a file to minimise the chance of a card catching on entering the rails or while passing through the cutout.



The breadboard connected to the Arduino was wired up by combining aspects of the designs that came with the SparkFun Inventor's Kit for Arduino (I'm in New Zealand, so I ordered it from mindkits.co.nz).   I subsequently found the Fritzing circuit design tool which I have now used to document my design (I've not had the courage to dismantle and rewire the breadboard to test the design schematics, so the schematics are untried).  




The card feed was a initially a bit of a problem.  I had originally thought about making the whole reader from Lego, but then thought why torture myself?  I also considered photo printers with straight through paper paths, I tried mine and it worked quite well, but I still needed to figure out how to get the card from the printer's output tray into the rails - probably by tipping the printer on an angle to let gravity feed the output onto a shoot (perhaps with relatively empty ink cartridges).  In the end I went with a crude manual Lego feeder.  It has the advantage that jams can be dealt with before any cards are mangled.  It's not perfect, but it's adequate.




The camera was fairly easy, I have an old Canon S2 IS, I just put CHDK enhanced firmware on an SD card.  I cut open an old USB cable to attach the camera to the Arduino.  The hardest part of dealing with the camera was experimenting with the timing sequence on the USB shutter release.  The documentation is a bit technical, but I eventually settled on using a short half press delay to focus, followed by a full press delay to take the photo. Here is the Arduino-Sketch code for the controller:
// Shutter Controller
// by Michael Hamilton  
// The code is GPL 3.0(GNU General Public License)


#include  

int SERVO_PIN = 9;
int SERVO_CLOSE = 120;
int SERVO_OPEN = 15;
int SERVO_DELAY = 250;
int SERVO_CARD_MOVE_DELAY = 1000;

int PHOTO_RESIST_PIN = 0;
int PHOTO_RESIST_DIFF = 40;
int PHOTO_RESIST_DELAY = 1000;

int CAMERA_PIN = 11;
int CAMERA_FULL_PRESS_DELAY = 1000;
int CAMERA_HALF_PRESS_DELAY = 500;
int CAMERA_FOCUS_DELAY = 400;
int CAMERA_CAPTURE_DELAY = 1500;

Servo myservo;  // create servo object to control a servo 
                // a maximum of eight servo objects can be created 
 
int lastlevel = 0; 
 
void setup() 
{ 
  Serial.begin(9600);
  Serial.println("Card Rdr");
  myservo.attach(SERVO_PIN);  // attaches the servo on pin 9 to the servo object 
  myservo.write(SERVO_CLOSE); 
  delay(SERVO_DELAY);
  myservo.detach();
} 
 
 
void loop() 
{ 
   int lightlevel = analogRead(0);
   if (lastlevel != lightlevel) {  
      Serial.print("lightlevel="); 
      Serial.println(lightlevel);
      int diff = lastlevel - lightlevel;
      if (diff >= PHOTO_RESIST_DIFF) {  
          digitalWrite(CAMERA_PIN, HIGH);
          delay(CAMERA_HALF_PRESS_DELAY);      // press shutter -focus
          digitalWrite(CAMERA_PIN, LOW);
          delay(CAMERA_FOCUS_DELAY);
          digitalWrite(CAMERA_PIN, HIGH);
          delay(CAMERA_FULL_PRESS_DELAY);      // press shutter
          digitalWrite(CAMERA_PIN, LOW);
          
          delay(CAMERA_CAPTURE_DELAY);   // wait for photo to be taken
          myservo.attach(SERVO_PIN);   
          myservo.write(SERVO_OPEN);
          delay(SERVO_DELAY + SERVO_CARD_MOVE_DELAY);      // wait for servo to open and card to move
          myservo.write(SERVO_CLOSE); 
          delay(SERVO_DELAY);       // wait for servo to close
          myservo.detach();
      } 
      lastlevel = lightlevel;
      delay(PHOTO_RESIST_DELAY);
   }
} 

7 comments:

  1. Great project!I really appreciate your great creative effort keep it up...printed circuit board manufacturers

    ReplyDelete
  2. So cute! I love this idea and so would my kiddos!!
    I'm a new follower too!
    I'd love for you to buzz by sometime=)
    www.plasticcardmonster.com

    ReplyDelete
  3. How many cards per minute are you rated at?

    ReplyDelete
  4. A zippy 20 cards per minute tops :-) The main limit is the photoresistor card detector, if I go too fast it may fail to detect the change in light levels. The python image scanner can decode approximately 450 card images per minute.

    ReplyDelete
  5. Good job for publishing this type of positive information for other people interested in the same topic. click here

    ReplyDelete
  6. I have 152,000 80 column IBM punch cards that I need to read, does anyone know who I can call to complete this job? Thanks

    ReplyDelete
    Replies
    1. There is an outfit that seems to be doing something like this on a commercial basis - http://punchcardreader.com/ - I noticed them when I was writing this up.

      Delete