Working with a large number of numbers

In my most recent project I’m working on a system for opening a turnstile based on a barcode written on a ticket that is purchased.
The idea is following:
To print the barcode according to some rules, one of which would be to include a six digit receipt number that is already being generated for taxation purposes. This is series of consecutive numbers starting on January 1 of each year and incremented by one for each receipt. The date of purchase is also included in the barcode. The barcode printing is done inside the cash register software and is not what troubles me.

The Arduino side would read the barcode, check if the date is current (comparison to a date from a RTC chip) and check the six digit number. Of those six digits I don’t need more than three, since I don’t expect more than a thousand visitors per day (a few hundred is much more realistic estimate). I would then discard the first three digits and use just the last three to get the unique number (when taken together with the date). Next I would store this number and effectively make the ticked no longer valid (single entrance only).

Storing this number is what I’m having a trouble optimizing. The only working idea I have is to have a bool array with 1000 places, then use the position in the array to mark the used tickets.
This however uses one byte per position, which totals an entire kB, leaving me with not much more room in SRAM.
Does anybody have a better suggestion?

SD card perhaps

Use bits instead of bytes for the boolean values.

jboyton: Use bits instead of bytes for the boolean values.

Going further: corresponding byte = card_Num / 8; corresponding bit = card_Num % 8;

125 bytes total to hold 1000 cards.

Karma +1

Thanks for the replies guys.

Yeah, I've been thinking about bits, but you can't have an array of bits. At least that's what AWOL says, and I'm inclined to take his word on it.

He does mention bitRead and bitWrite.

I've also found the bitArray library, but it's limited to an array of 8 bits. Using that would require 125 arrays since it doesn't appear to be capable of two dimensional arrays (I could be wrong on that).

Ok, while writing this, I have my brain spinning and this is what I came up with, thanks to you guys. Say I have a ticket number 100 I need to mark as used:

byte ticketArray [125]; // enough room for 1000 bits

  ticketNo = 100;                                                 // this would be the incoming ticket number as read by the barcode scanner
  bitWrite (ticketArray [(ticketNo / 8)], (ticketNo % 8), 1);     // 100 / 8 = 12, 100 % 8 = 4

It compiles, but unfortunately I don't have an Arduino to actually test this right now. The same process would be for bitRead.

Did I understand you correctly?

Yea, that works.

bitRead(ticketArray [(ticketNo / 8)], (ticketNo % 8)); // will return a 1 or 0.

How about:

byte ticketArray [128]; // enough room for 1024 bits

That's divisible by 8.

I think I would store the array in EEPROM in case the power goes off, although you only get 100,000 writes per EEPROM "page" (a page being 4 bytes). Still, that is probably adequate for your application. :)

4 bytes would hold 32 visitors (4 * 8) and assuming you write once per visitor, and you do that once per day (since after 32 those bits will all be "switched") you could therefore cope with 100000/32 visitor/days, which is 3125 days (8 years) after which you might have to swap out the $5 chip. And even that is a worst-case scenario, because you could "load balance" by using a different 128 bytes each day (as there are 1024 bytes of EEPROM), so every 8 days you use a different bank (based on the date from the RTC), thus increasing the time to 64 years, after which someone will probably have come up with a different design. ;)

Why use the EEPROM when you can write 128 bytes to a SD card as a txt file and then read that file on a computer if needed.

Of course, if you did use an SD card, you could make the system more sophisticated. For example, record exactly when a ticket got presented, so if there was a dispute you could say "oh no, you used that at 10:15 am today".

Also you could record ticket types (eg, child, adult, family) which you may or may not want to know. Recording the time could be useful, because you could print out at the end of the day what the busy times were, that sort of thing.

Why use the EEPROM when you can write 128 bytes to a SD card as a txt file and then read that file on a computer if needed.

Agreed, which I was typing up when you did your reply.

Nick, is 128 being divisible by 8 significant compared to 125? Other than it neatly fitting inside the 1024 bytes of EEPROM? Those 24 extra bits would never be used anyway. Lifespan of 32 years (I need two writes per visitor, once when the visitor comes, once to reset the address for the next time it is used, right?) is more than acceptable. If it fails then, whoever is left alive can deal with it. I'm not sure I'll be around :).

However, power outage is not of a major concern. If the power is gone, the visitors have no reason to stay and will probably go home/outside. When the power comes back, they again have a valid ticked, which is fine by me. After all, they paid for it, it's only nice to let them use it again.

HazardsMind: Why use the EEPROM when you can write 128 bytes to a SD card as a txt file and then read that file on a computer if needed.

Well, the main reason would be to avoid using more hardware than necessary. I don't need to be able to transfer that data to the PC because I already have it in the PC inside the cash register software that does entire financial and statistical processing. I can always pull it out with three clicks of the mouse. That software keeps track of types of tickets being sold (adults, kids, groups). Each ticket is also the receipt which is timestamped, and again recorded in the cash register.

Well, there is less to go wrong with your logic if you get an even result after a divide. But it's probably no big deal.

As for the two writes, I would be clearing all EEPROM at the start of the day (hence that is just one write per byte not one per bit) and then do a read/set bit/write per visitor as they arrive.

For that matter, if you are confident the power will stay on, just use RAM, and then you don't need to worry about EEPROM load balancing. But one small accident or lock-up and you've lost the day's records. At least with the data in EEPROM, if you have to reset it for some reason (program bug maybe) it will have remembered all that came before. Resetting at the start of a new day could be done by storing the current date in EEPROM, and if that differs from the RTC, clear all the (other) bytes to zero, ready for a new day's work.

I certainly can't be confident there won't be an outage, but in the last three years we've only had a handful of such cases, most being caused by us tripping the circuit breakers. Actual grid going down happened maybe twice. I believe this is acceptable, since this is not intended to be a security system.

In any case, the PCB will get the ISP headers so I'll be able to change the software if the need arises.