As I was leaving the shop this evening (morning?), I noticed this neat, tiny display thingie in one of the drawers I was returning components to. It had what looked like a row of tiny 7-segment LED displays on it, behind magnifying lenses, and was clearly a pull from some long gone piece of equipment. Not to be one to pass on a good reverse engineering challenge, I decided to hook it up and write a little driver for it.
At about 2″ long, and maybe 3/4″ tall, it seems like the perfect thing to adorn some suspicious baggage or unattended luggage cool project. Anyone have a good idea about what to do with it? It might end up as the display end of an agitator machine, as part of an automated PCB etching setup.
Source code (which could be used to drive any array of 7-segment displays) follows after the break.
// Arduino driver code for a tiny 7 segment display // By Matt Mets, May 2010 // Public domain // *** Change these to match your system ****************************************** // Define which Arduino pins the digit select lines are connected to. // Note that you can add or subtract pins to match the number of digits your display has. const uint8_t digitPins[] = {11, 9, 7, 5, 3, 14, 16}; // Define which Arduino pins the segment select lines are connected to // a // ___ // f | | b // |___| // | g | // e |___| c oP // d // {a, b, c, d, e, f, g} const uint8_t segmentPins[] = {8, 15, 12, 4, 6, 17, 2}; // Dot pin const uint8_t dotPin = 10; // *** Display driver code ******************************************************** // Lookup table to translate numbers into segment pins. // This is basically our seven segment 'font' const uint8_t segmentLookup[] = {0x7e, // 0 0x30, // 1 0x6d, // 2 0x79, // 3 0x33, // 4 0x5b, // 5 0x5f, // 6 0x70, // 7 0x7f, // 8 0x73, // 9 0x77, // a 0x1f, // b 0x4e, // c 0x3d, // d 0x4f, // e 0x47, // f 0x00, // (space) 0x01};// - (negative) #define SEGMENT_SPACE segmentLookup[16]; #define SEGMENT_SIGN segmentLookup[17]; // Look-up table that maps the bits in the font to display segments // For example, to determine if segment A should be drawn in a font character, // logical and (&) the character with segmentPositions[0] const uint8_t segmentPositions[] = {1<<6, 1<<5, 1<<4, 1<<3, 1<<2, 1<<1, 1}; // Buffer to store the current number that is being displayed uint8_t displayBuffer[sizeof(digitPins)]; // Variable that keeps track of which digit is currently being displayed uint8_t currentDigit = 0; // Draw the next digit in the display // This function is called when timer2 overflows ISR(TIMER2_OVF_vect) { // Turn off the current digit pin digitalWrite(digitPins[currentDigit], HIGH); // Increment the digit pin currentDigit = (currentDigit + 1) % sizeof(digitPins); // Update the segments to show the proper number for this digit for (uint8_t seg = 0; seg < sizeof(segmentPins); seg++) { digitalWrite(segmentPins[seg], displayBuffer[currentDigit] & segmentPositions[seg]); } // Turn on the new digit pin digitalWrite(digitPins[currentDigit], LOW); } // Display initialization void setupDisplay() { // Initialize all of the pins for (uint8_t i = 0; i < sizeof(segmentPins); i++) { pinMode(segmentPins[i], OUTPUT); digitalWrite(segmentPins[i], LOW); } for (uint8_t i = 0; i < sizeof(digitPins); i++) { pinMode(digitPins[i], OUTPUT); digitalWrite(digitPins[i], HIGH); } // Clear the display buffer for (uint8_t i = 0; i < sizeof(digitPins); i++) { displayBuffer[i] = SEGMENT_SPACE; } // Set up Timer 2 to generate interrupts on overflow, and start it. // The display is updated in the interrupt routine TCCR2A = 0; TCCR2B = (1<<CS22)|(0<<CS21)|(0<<CS21); TIMSK2 = (1<<TOIE2); } // Display a (signed) number // Returns false if the number couldn't fit boolean displayNumber(long number) { // Temporary buffer to store our results uint8_t outputBuffer[sizeof(digitPins)]; for (uint8_t i = 0; i < sizeof(digitPins); i++) { outputBuffer[i] = SEGMENT_SPACE; } // Store off the sign of the number boolean isNegative = (number < 0); number = abs(number); // Start filling from the right of the display int8_t bufferLocation = sizeof(digitPins) - 1; // Fill the output buffer from the right by dividing by ten and storing the // remainder to the display. while (bufferLocation >= 0 && number > 0) { uint8_t temp = number % 10; number = number / 10; // Pre-compute the segment value to save time during the interrupt outputBuffer[bufferLocation] = segmentLookup[temp]; // and decrement the buffer location bufferLocation -= 1; } // We've filled as much of the buffer as we can by now. If there is a remainder, // stop now and return false. if (number > 0) { return false; } // The last thing we need to check is if we need to draw a negative sign. if (isNegative) { // If there isn't space in the buffer, bail if (bufferLocation < 0) { return false; } // Otherwise, draw in the negative outputBuffer[bufferLocation] = SEGMENT_SIGN; } // We've made it, so copy out the buffer and return success. for (uint8_t i = 0; i < sizeof(digitPins); i++) { displayBuffer[i] = outputBuffer[i]; } return true; } // *** Sample program ************************************************************* void setup() { setupDisplay(); } long i = -99000; void loop() { // For an example, count up from -99000 displayNumber(i); delay(1); i++; } |
Hi
Thanks for posting your code on this display.
Could you please confirm, is this is a common anode display?
Thanks
I think it is actually common cathode… I am setting the digit pin (the common one) low to turn it on. To make this work for common anode, you I think you would just need to invert the output logic, so switch the
digitalWrite(digitPins[currentDigit], HIGH);
and
digitalWrite(digitPins[currentDigit], LOW);
lines,
and replace:
digitalWrite(segmentPins[seg], displayBuffer[currentDigit] & segmentPositions[seg]);
with
digitalWrite(segmentPins[seg], (~displayBuffer[currentDigit] & segmentPositions[seg]));
Let me know if that works for you
This is very amazing display.
would you please provide the part number or any furthure information, so I can buy some sample.
Unfortunately, I don’t think I have it anymore!
That is from the TI mba calculator. I have one!
Oh, nice!
so funny
I was searching for tiny 7digit displays and bumped into this.
I just scavanged one of those screens from an old Continental 1800a
they’re really cute, and it was easy to figure out how to drive them, since they keep the standard A-…-G + H(dp)
I’m quite unhappy with the 9th digit missing, though
happy hacking
ubi