Help deciding between IO expanders or shift registers

Hopefully this is in the correct topic, sorry if it's not - first post here.

I am looking at building some punch card scanners using probably an Arduino Nano or UNO that would send data to a PC where it would be pulled into a DB system.
Current thinking is an array of opto switches/IR sensors.

The cards are as shown:

Card Image

The black shapes are punched out of the card.
I'm planning 5 columns of opto's plus one to read the black column to check the orientation of the card is correct.
The card will be placed into a reader in a registered recess.
I'm thinking each numeral location would have a light source on one side of the card and the opto on the other, except the black column which would use a reflective sensor.

Sometimes when the cards are punched the holes are poorly aligned but they invariably remove the digit.
If a mistake is made and the wrong digit is punched the correction is made by punching out all digits except the correct one. This should be OK to deal with in software. It's a fairly manual process so it's no big deal if the odd card can't be scanned correctly as long as I can flag that there's a possible error. I'm thinking a LED on the reader that lights if the results aren't sensible - eg no reading from a row, or a double reading. Maybe a LED for each row so the operator can see that the correct number of rows are read and also which row has a possible error. Details really.

I don't really care at this stage how the data appears in the Arduino but my first thoughts are:

  • Bitwise eg "00001" for the first row shown.
  • individual digital inputs

I've had a bit of a look at options to connect the sensors but I'm not too sure which might be the best way to go.
I've seen I2C & SPI I/O expanders and also Shift Registers but I don't really understand the pros and cons of each. It seems to me that they both end up with the Arduino receiving pretty much the same data - 8 bits for each group of 8 inputs.

I've also seen multiplexers, but they look to me like there might be a fair bit more work writing the code to make it all work, and possibly also setting up the electronics.

Speed isn't an issue but reduced software complexity would be good for a beginner like me.

Buying pre-built boards/shields would be preferable, if it works out OK I'd probably end up making 10-20 devices so the less assembly required the better. I've seen the centipede shield which is much more than I need but would certainly provide all the I/O's if I went that way. Still looking around to see what other options are available.

I'll 3D print the housing.

I've very little experience with Arduino and limited electronics skills, but enough to put basic circuits like this together. And I've a handy friend who actually knows what he's doing on that front.

I know this is a pretty open question, but I hope to get a better reaction here than I did at Arduino Stackexchange!
Thanks

That is true but I think that the I2C devices are the easiest to use regarding both hardware and software.

Since you are reading 5 columns and 15 rows, I would suggest a 16 pin GPIO expansion for each column. In the Arduino program, use a converter function to transfer from the column bits into a byte for each row.

The black strip does not need a sensor for every row, but needs some additional sensors above and below it to make sure it is in the correct position.

You might only need 5 sensors, if you can find a way to get them to scan along the length of the card.

The easiest way do do that might be to allow the card to drop through a slot, with the sensors inside the slot. The difficulty of allowing it to drop is that the speed of the card moving past the sensors won't be constant, it will be accelerating. But it will be accelerating at a known rate, so perhaps that's not a problem.

More complex would be to use a motor to move the card past the sensors at a steady speed, perhaps using a rubber pinch wheel to grip the card.

If physically moving the card or sensors is not possible or practical, perhaps the card can be scanned electronically. This could be achieved by connecting all 16 sensors in each column together, so only 5 input pins are needed. Connect the sensor illuminators together into rows and illuminate one row at a time. This way, only 5 inputs would be needed and as few as 4 outputs to select which row is illuminated using a 4-to-16 line decoder, for example.

I considered passing the card through a single row of sensors but decided it was probably all a bit tricky to be sure that each row was correctly scanned before moving to the next. The cards can also get pretty wet, muddy and dirty so moving things aren't such a good look I think.
But maybe a 'carriage' with the sensors that slides above the card which the operator pulls across - a bit like the old click-clack credit card imprinters. Maybe it could trigger a sensor at each row to record positively which row each byte of data relates to? Hmmm.

The electronic scanning is a concept I'd certainly not thought of. I'll look into what's involved in achieving that. I suspect at this early stage of my Arduino experience it might be biting off more than I can chew.

Definitely some stuff to consider there, thanks.

I was thinking similar (I realised I had a brain fart when I said the 64 i/o centipede was more than I need - I need at least 76 inputs if there's one for each digit plus a registration check). I could use one or two of the 16th bits to check the black stripe.

Have you thought about image processing? Takes away the physical I/O, just image of card, some method of determining orientation(that could be physical), and 'some software'. Granted, the latter could become more intense.

That's where I started quite a long time ago and I decided the software to do that was way, way over my head and I couldn't find anything existing that was really suitable.
Now I've started playing with Arduino it occurred to me that I could revisit the idea of the scanner using this discrete opto method.
Still possibly over my head, but I can feel the bottom at least :slight_smile:

I like @PaulRB 's idea of electronic scanning with a line decoder, but having spent a little bit of time looking into that now I think it's probably adding more complexity than I can realistically manage at this stage.
5 x 16 pin GPIO expanders on I2C seems like a somewhat brute force method, but I think it might keep things a bit more manageable for me. I think I'll chip away down that path for now.

Thanks everyone.

You might be interested in this project, https://www.youtube.com/watch?v=Qtcqx2pZbrI, he uses an array of IR sensors to detect black or white marbles, and also absence of a marble. He goes through a number of issues with those sensors and how he resolved them.

I don't think it's any more or less difficult than interfacing 16x5 sensors using shift registers or I/o extenders. Probably fewer components and less wiring, because the whole thing would be wired like a matrix instead of 16x5 separate sensors.

Please post a link to the specs of these sensors, so we can advise different ways they could be connected to the Arduino. Are they simply IR/visible light phototransistors?

Some techniques used in the past -

http://www.decodesystems.com/ce-punched-readers.html

1 Like

It's still early days, so I'm not really at the point of choosing specific parts, but having done some measurements of the cards and thought about things subsequent to the info provided here, these BPR-301 look to me like they tick some of the boxes.

  • The digit spacing is 5mm & these are 4.8mm wide packages.
  • They have a focused detection point which I think will be beneficial to reduce false positives.
  • From what I can tell (my ability to interpret datasheets is very limited!) these should give a distinct enough switching that they could be connected to digital I/O pins with just a couple of resistors. ?
  • The price is OK, although nowhere near what I can get TCRT5000 for, but the TCRT is 5.8mm wide so I'd have to modify them which may or may not be feasible.

I'm thinking I might get a BPR-301 to test, and a few TCRT5000 modules just because they are so ludicrously cheap - if they work without too much mucking around that would be nice.

I'm increasingly thinking that working out a way to scan rows down the length of the card will be best. I think setting up a full array of sensors will just get out of hand.
Current thinking is a semi-manual carriage, probably beneath the card, reading the white backside.
Possibly a sensor with indexed marks permanently in the card holder aligned with the rows. It would signal the Arduino when to read a row. It could help prevent false reads from misaligned punch holes, dirt on the card or rows that are not punched at all.
I suspect the movement of the scanner can be very basic and just manually operated as the sensors and the Arduino will be able to read considerably faster than anyone is likely to operate the slide. I have considered putting in something like a drawer soft-close mechanism to do the movement, with the operator just resetting the slide. To be determined after testing.
I'm also considering how to implement some card coding (these cards are score cards for observed trials. Entering data in the scoring system requires looking up the rider name or number and filling in the scores for the relevant lap - each lap is one card.). A bar code would be ideal, but adds another device to do the scanning. I haven't yet worked out how I could encode a 3 digit rider number using just the 5 or 6 main sensors, but it seems it should be possible.

Getting data into the PC looks relatively simple using the Arduino Keyboard library. That had me a bit bothered until I realised that was possible - potentially absolutely no changes needed to the PC software.
Have a button on the card reader that sends the keystrokes to the PC when the operator has the correct entry selected and ready to fill. They can then quickly verify the entered data against the card and move on to the next.

I see. I was thinking that, because the cards are punched, it makes more sense to me to have the emitter on one side of the card and the sensor on the other side. Where there is a hole, more light can pass. Where there is no hole, it will be much reduced. But I guess the BPR-301 could work. Worth getting a couple to experiment.

These sensors consist of an IR LED and an IR phototransistor. You might save money simply buying these components separately. IR LEDs and phototransistors are available cheaply in 3mm round packages. If your 3D printing skills are good, maybe you could print something to hold an array of them.

No resistors. Just connect them between the Arduino pin and ground and use INPUT_PULLUP mode. You can adjust the sensitivity by controlling the amount of IR light produced by the emitters by adjusting their series resistors.

Choose an Arduino model that supports that library. Many do not.

Another idea....

A 16x6 matrix of IR or optical emitters/LEDs immediately behind the card. In front of the card, set some distance back, possibly inside a box to exclude ambient light, a single sensor/phototransistor with a field of view covering the entire card.

The Arduino would electronically scan the led matrix, one led at a time, working through the rows & columns. The sensor would be read individually for each led.

Initially I was thinking the same, but if I'm going to scan the card with a moving array it simplifies things to have all the electronics on one side of the card. It starts looking more and more like a very low resolution flatbed scanner!
Flatbed seems preferable because the cards could come in with folds, creases, mud, dirt etc. The flatbed isn't going to jam on any of that and it's easy to wipe the top window clean.

I'm not at all confident my ability to read datasheets is up to the job of picking an IR phototransistor with the right characteristics to be able to use it without comparators or whatever extra bits some devices seem to have. I also figure there's probably a bit of R&D getting them physically setup with a narrow focus point. If someone could tell me what specifics to look for I'd happily save the money and try printing a custom holder.
I pay for my lack of skills & knowledge in $$.

Thanks for the advice on using the BPR-301 with just the Arduino pullup resistor - I hoped that was the case, but wasn't sure at all.

I've been hoping it might run on a clone Pro Micro ATmega32U4 based board. I believe these should support the Keyboard library, but if not I could use the UNO R4. I have both here to experiment with so I'll give the Pro Micro a try with the library & see what happens.

That's an interesting idea with several advantages. I'll consider that. Or perhaps a hybrid with 2 sensors to cover the length of the card to maintain better sensitivity? I just had a quick look and the wide angle sensor's sensitivity seems to drop off pretty fast with angle.
Probably still need a plate to press the card flat.
The LED's would need to be fairly tightly shrouded to keep the beam within about a 3mm diameter circle where it passes the card to ensure adjacent inaccurately punched holes don't give a false reading. Maybe flat-top LED's so they are flush with the surface to make wiping clean easier?
A bit to think about there.

I'm thinking that with either the flatbed or "camera stand" concept the operator would load the card, compare loaded card to PC software record to confirm correct rider & lap up, then close the top of the reader which would trigger a switch (hall? another opto?) to start the scan. The Arduino would then keyboard in the details to the PC and indicate complete (LED/Beeper).
Possibly the LED/Beeper would indicate potential read errors - multiple punches on one row, no punches on one row, etc.

If I can figure a viable way to encode rider/lap data on the card it would become two steps sending keystrokes to PC - first key in the search criteria, wait for operator to confirm, then type data. A button on the scanner to confirm.

I can see it getting really fancy with visible LED's lighting up beneath each recognised hole so when the lid is opened it's super easy to confirm that the recognition matches what the operator reads. That's Mark II or III. :slight_smile:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.