The Problem
A friend of mine is working on a project that involves reading data from the seven-segment display of another device. I was thinking about this over dinner, and started to wonder whether you need to read all of the segments to distinguish which number was being displayed, or if some can be ignored. For instance, the top LED cannot be removed because then you would not be able to distinguish between 1 and 7. If some of the segments are extraneous, then they do not have to be hooked up to the microcontroller. This means that more pins are available on the micro for other things.
The numbers being considered (each line counts as an LED): _ _ _ _ _ _ _ _ | | | _| _| |_| |_ |_ | |_| |_| |_| | |_ _| | _| |_| | |_| _|
Method of Analysis
Well, I tried in vain to explain the problem to my friend until the waitress was kind enough to bring me a pen to use (I think also she wanted some sort of signature, but I digress.) Anyway, we sketched it out on a napkin and found at least one digit (the bottom one), that could be removed while still allowing each decimal number to be uniquely identified. Now, at this point, I got carried away designing a program and spent the next x time working out the best method for computing it. This approach worked out in the end, however it would have been much easier to just try out all the combinations by hand.
The Solution
It turns out that only 5 bits are necessary. The bottom and bottom-right ones can be removed with no loss of information (although it makes it harder for a human to read!):
With the unnecessary bits removed: _ _ _ _ _ _ _ _ | | | _| _| |_| |_ |_ | |_| |_| | | | |
The horrid code is after the break. It is here so I can laugh at it later on for how wonky it is, and so I remember not to design programs at bars.
#!/usr/bin/env python from copy import deepcopy class number: """ Simple class to represent a seven-segment number """ def __init__(self, A,B,C,D,E,F,G): self.num = [A,B,C,D,E,F,G] def get_top(self): return ' ' + \ ('_' if self.num[0] == 1 else ' ') + \ ' ' def get_middle(self): return ('|' if self.num[5] == 1 else ' ') + \ ('_' if self.num[6] == 1 else ' ') + \ ('|' if self.num[1] == 1 else ' ') def get_bottom(self): return ('|' if self.num[4] == 1 else ' ') + \ ('_' if self.num[3] == 1 else ' ') + \ ('|' if self.num[2] == 1 else ' ') def equals(self, other, mask=[0,0,0,0,0,0,0]): for index in range(0,7): if mask[index] == 0: if self.num[index] != other.num[index]: return False return True def applyMask(self, mask): for index in range(0,7): if (mask[index] == 1): self.num[index] = 0 def printAll(numbers): """ Print the numbers to the display """ for number in numbers.itervalues(): print number.get_top(), print for number in numbers.itervalues(): print number.get_middle(), print for number in numbers.itervalues(): print number.get_bottom(), print def stillUnique(numbers, mask): """ determine if the numbers are still unique after mask is applied """ for i in range(0,10): for j in range(i+1,10): if(numbers[i].equals(numbers[j], mask)): return False return True numbers = {0 : number(1,1,1,1,1,1,0), 1 : number(0,1,1,0,0,0,0), 2 : number(1,1,0,1,1,0,1), 3 : number(1,1,1,1,0,0,1), 4 : number(0,1,1,0,0,1,1), 5 : number(1,0,1,1,0,1,1), 6 : number(1,0,1,1,1,1,1), 7 : number(1,1,1,0,0,0,0), 8 : number(1,1,1,1,1,1,1), 9 : number(1,1,1,1,0,1,1)} for i in range(0, 128): if(stillUnique(numbers, [(i & 1), (i & 2) >> 1, (i & 4) >> 2, \ (i & 8) >> 3, (i & 16) >> 4, (i & 32) >> 5, \ (i & 64) >> 6])): print "Mask", i, "works:" temps = deepcopy(numbers) for temp in temps.itervalues(): temp.applyMask([(i & 1), (i & 2) >> 1, (i & 4) >> 2, \ (i & 8) >> 3, (i & 16) >> 4, (i & 32) >> 5, \ (i & 64) >> 6]) printAll(temps) |
Hahaha! Great minds yes? In fact I used this exact technique when reading values from the seven-seg displays on my breathalyzer! I was getting ready to start soldering wires to it and I thought “Man it’s going to suck to solder all these tiny wires, I wonder if they’re actually all necessary?” Of course I came up with the same answer — they’re not! Only the five are salient. My solution was a little less elegant — I just drew all the numbers on the whiteboard and systematically checked each segment asking, “If I remove this, are any two numbers indistinguishable?”
Ah, excellent! Next time though, I’ll just give you a call to check.
You also don’t need the upper right vertical bar… If it doesn’t have it, the number is either a 5 or a 6, determinable from the other bars.
I think if you take out the upper right vertical bar, you can’t tell 6 and 8 apart either. With some extra logic (AND two of the bits together), I think you can can reduce the inputs to four, but I didn’t think the extra trouble was worth it.
Now thats what karnaugh diagrams are for lol
Pingback: Just need 5 bits to differentiate symbols on 7seg display « Jonny Zone : Copyleft – all rights reversed