Final Project - Execution
Design
Bottom line i want to have a full digit display with all 90 numbers (01,02,03,...88,89,90), have also a segmented dual number for the last number selected, an ON/OFF switch (probably on the back), a New Game button (have to press twice for Reset - New game) and a New Number button with a pressure sensor with leds indicators.
I started by designing some layout ideas and the positioning i thought it would be best. It will be a 90 number display, 9 rows by 10 columns and in addition i want to have a double digit segment display composed by 3 leds each segment.
In the first 3 images you can see the diferent layouts with the third beeing the one i'm going with. With this done i went into moldeing it so that i can carve it out of cork (no material is more portuguese).
Then there's an image of the numbers i've designed and thought about using casting and molding them, for that i designed each one and did the carve on the wax block so that i can make a few silicone molds to later cast a lot of numbers, it will be 180 in total or 18 each number. The numbers will be individualized so that they can all be made with the same molds.
Now for the buttons, i imagine only having 2, one for the "New game - Reset" and another for the "New number". For the first one i was thinking of a simple push button, but for the second i remembered that it would be cool to make a load button where the more i press the longer the numbers will be randomizing. So started to adress the "New number" buttom on the "Input Devices" week using the Step Response - Load Button. Designed a new layout with the integrated button on the pcb itself and added 3 LEDs to display the intensity, you can go on this link for more information.
Unfortunately i wasn't able to do this and decided i maybe should simplify a bit in order to be able to do all, so i just made a capacitive button directly connected to the processor and used a simple analogread.
Electronics design
As i said before i want to have a 90 number matrix and so i went and research about it, end up discovering the MAX7221 controller and after a bit about i realize it would be perfect for this project. A few things had to be changed/adapted but in the end it worked great.
So basically it's a LED controller and with one MAX7221 you're able to either control a 8x8 matrix or 8 segment digits. In my case i wanted to do both so i start reading more about it and considering the LED i wanted to use it would be safe in terms of current (wish was my main concern since i was using 2 LEDs for each number). After consulting the datasheet, the controller could supply at most around 330mA and according to my calculations and considering that each LED would run at 30mA max, it would need 480mA, so with the 330 mA we would get 20mA wish is not bad, all of this considering that all the numbers would be lit in that row wish won't happen on a regular basis according to the logic of the eBingo.
To be able to control the full matrix i had to do some work, in this case it would be a 9x10 matrix and so one MAX wouldn't be enought, on the other hand, even if i divide the matrix it will still have 9x5 matrix so i made a change on the row and changed it to collumm, this way the matrix would be 8x6 and it would workout. Also, i had 2 segment digits i needed to control and in the beginning i thought i could inclued it on one of the MAX since it has 24 pins, but soon realized that i needed some exclusives for the matrix and so i went and made an extra controller outside of the main board.
I decided i wanted to use the main components with pins since something might go wrong with the pcb (and it did happened) and that way i could easily swap without damaging any of them. To control the MAXs i went for the Attiny84 since the 44 might not have enough memory for the firmware, and i'm happy i choose this since it really was close to maximum. There were a coupple of good details on the MAXs, first the fact that it only uses 4 pins of the processor and then the second MAX is only connected to the first and the third is connected to the second. So it's only a matter of registry and cicles and it won't use to many pins of the processor. The other great particularity is the fact that the LEDs controlled by the MAX stay lit unless you tell them the shut all down, so for the game i wanted for the numbers that were selected to stay on while the game is being played and in the end it would clear all, so perfect caracteristic for my project.
Followed the schematics they had in the datasheet and designed the board, went for a double sided PCB since there were no way to make all the connections on one side only, below you can see the work done on eagle and then the result. The first attempt i used a Attiny45 and quickly realized it wouldn't work so then i made the second version with the 84 and the LEDs modules on the side.
On the LEDs i've design a simple number module that would take a couple of LEDs and that i could change it easily in case it wasn't working properly and had any problem. For the segmented digits i design them with 3 LEDs each segment to make sure it had enough light, unfortunately the red LEDs were a disapointment and they were all with diferent intensities and weren't very strongh. Below there's the schematic i used in both this cases.
Electronics fabrication
First the list of all electronics used on eBingo:
- 1 uni. Attiny84
- 3 uni. MAX7221
- 1 uni. Voltage regulator (9V to 5V)
- 1 uni. Push-button
- 180 uni. Blue LEDs
- 42 uni. Red LEDs
- 4 uni. Capacitor 10uF
- 3 uni. Capacitor 100nF
- 3 uni. Resistor 15kOhm
- 2 uni. Resistor 10kOhm
- 1 uni. Resistor 10MOhm
Then it was time for the segmented digits, milling that wasn't a big problem and soldering went well as well, the only big if was the red LEDs that were different in terms of intensity so i had to desolder some in order to make it as uniform as i could. You can see it in the images #03 and #05.
For the LED modules i've made over 120 units because some of them weren't evenly cut and didn't looked so good, so i made some spares so that i could choose the best ones. In the images #06, #07 and #08 you can see me sorting them and arranging in a way so that i could solder with ease. I place them all in lines and collums and that way i could industrialize the process a bit. Then just had to put a bit of solder on one side of the module, then solder each LED and at last solder the other side, allways making sure the correct orientation anode/cathode (images #10 to #13). Then was time for the pins, to do this i just pin first on the breadboard (image #14 and #15) and then push the module in, that way it was stable and i could solder all easily. Made a few batches since the breaboard would only take 28 modules at a time, but after 4 times it was all ready (images #16, #17 and #18).
Electronics assembly
With all the electronics ready i tought i might do a layout in thin cardboard so that all could be attached and understand all positions and check if it's all good. That being said i made the first drawing (left top) of the image #29 with an old pizza box i had in the lab. You can see the result in the images #19 and #20, but then in order to connecte all i decided to make a mdf board layout just to be more stiff and not bendy when i try to make all the connections. The inicial idea was to use jumper wires to wire all since it would be around 200 and i didn't want to solder all. Unfortunately the jumper wires were taking too long to arrive and so i decided to take a risk and went for it. It took me 3 days to solder all including making all the jumper connections to the controllers, but even better was the fact that the jumper wires arrived the day after i finished all the soldering...
So, in order to connect all right i did a small helper you can see in the image #21, this way i'd make sure i did all right. In the next image i had soldered both matrix wish was about a full weekend of soldering and then started on conecting to the controllers. In the image #23 it shows the wires between the segmented digits and the controller, i had to divide each seg pin so that it went to both segments and only the dig pin (red wires) are one to each number. From the image #24 to #26 you can see the wiring from both matrix to each controller and from second controller to the first and from the third to the second. Piece of advise, check, re-check and just in case check again that you connected to the correct pins, i bump a few times until i got it completelly right. On the next image it's the front of the board with everything connected and ready (a bit clumsy but it was just to make sure all worked before improving its looks).
Casing assembly
For the casing i went for a simpler look using just the laser cutter and the 3D printer, it wasn't what i idealized but i had some time contraints and limited acess to some equipment. So, the result was i designed a simple layer casing (as in image #29), had to make some spacers to acomodate the LEDs modules and the wiring in the back and then put some layers to give height and to direct the light from the modules to the acrylic numbers. Here i designed a few numbers (red part on image #29) and engraved to number and cut the outside, then painted the top with crayon and remove the excess, leaving only the engraved in black. From the image #30 on you can see the set up and then the layering in the correct order, decided in the end there to add a small cutout in the right side top corner with the word "eBingo" from eletronic Bingo, just to add some branding. I used the same technic as the numbers but this time i glued some green LEDs to the back of it, unfortunately by the time i took all the photos, one of the LED wasn't working but still it looked cool (fixed the LED later).
Making it blink
There's a world of code out there to find, to personalize, adapt and ultimately use to our needs, that's what i did. It was not easy at all, it's not my favorite thing and usually i have some trouble getting it, but with a bit of help and a lot of hours over it i was able to get to a code where the game worked. Not perfect yet but it's a work in progress.
It uses a random function to launch a new number each time we press the capacitive button (that uses an analogread) and after that there's the push button wish pressed for more then 3 seconds it will reset the game. Also, each time a new number comes out, it is displayed in the segmented digits. For the LED matrix and segment control i went here, there's some examples on the bottom, they have the basis for all LEDs. In terms of the random it's just the function, but had to make sure that the number would only be selected once so searched a bit and found this forum.
I'll leave the code in the downloads and if you want to take a look below the code is commented, so in any case you can check and in any doubt please fell free to contact. The code isn't perfect yet so please be pacient.
//All the libraries #include#include "LedControl.h" #include //Just to simplify #define LED_ON true #define LED_OFF false // pin 6 is DataIn ; pin 4 is CLK ; pin 5 is connected to LOAD ; 3 is the number of address LedControl lc=LedControl(6,4,5,3); //10M Resistor between pins 7 and 8, you may also connect an antenna on pin 8 CapacitiveSensor cs_7_8 = CapacitiveSensor(7,8); unsigned long cs; //Delay between updates of the display unsigned long delaytime=100; //pushbutton initiator int buttonState = 0; //constants int remainNumbers; uint8_t rightNumber; int newNumber; //intervals const PROGMEM uint8_t a[91] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 , 41 , 42 , 43 , 44 , 45 , 46 , 47 , 48 , 49 , 50 , 51 , 52 , 53 , 54 , 55 , 56 , 57 , 58 , 59 , 60 , 61 , 62 , 63 , 64 , 65 , 66 , 67 , 68 , 69 , 70 , 71 , 72 , 73 , 74 , 75 , 76 , 77 , 78 , 79 , 80 , 81 , 82 , 83 , 84 , 85 , 86 , 87 , 88 , 89 , 90 , 0 }; const PROGMEM uint8_t b[90] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 , 41 , 42 , 43 , 44 , 45 , 46 , 47 , 48 , 49 , 50 , 51 , 52 , 53 , 54 , 55 , 56 , 57 , 58 , 59 , 60 , 61 , 62 , 63 , 64 , 65 , 66 , 67 , 68 , 69 , 70 , 71 , 72 , 73 , 74 , 75 , 76 , 77 , 78 , 79 , 80 , 81 , 82 , 83 , 84 , 85 , 86 , 87 , 88 , 89 , 90 }; // 0 1 2 3 4 5 6 7 8 9 const PROGMEM uint8_t row[91] = { 0 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 4 , 3 , 2 , 1 , 0 , 4 , 3 , 2 , 1 , 0 , 4 , 3 , 2 , 1 , 0 , 4 , 3 , 2 , 1 , 0 , 4 , 3 , 2 , 1 , 0 , 4 , 3 , 2 , 1 , 0 , 4 , 3 , 2 , 1 , 0 , 4 , 3 , 2 , 1 , 0 , 4 , 3 , 2 , 1 , 0 , 4 , 3 , 2 , 1 , 0 , 4 , 3 , 2 , 1 , 0 , 4 , 3 , 2 , 1 , 0 , 4 , 3 , 2 , 1 , 0 , 4 , 3 , 2 , 1 , 0 , 4 , 3 , 2 , 1 , 0 , 4 , 3 , 2 , 1 , 0 }; // 0 1 2 3 4 5 6 7 8 9 const PROGMEM uint8_t col[91] = { 0 , 7 , 6 , 5 , 4 , 3 , 7 , 6 , 5 , 4 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 }; uint8_t availableNumbers[91]; uint8_t selectedNumbers[90]; //defining the interval max and min #define LOWER_BOUND 0 #define UPPER_BOUND 91 int capabutt; void setup() { //button pin pinMode(3, INPUT); randomSeed(analogRead(0)); //we have already set the number of devices when we created the LedControl int devices=lc.getDeviceCount(); //we have to init all devices in a loop for(int address=0;address 3000 ){ newGame = true; }else{ capabutt = 1600; } } //when new game will clean all and start over if ( newGame ) { lc.clearDisplay(0); lc.clearDisplay(1); lc.clearDisplay(2); for( int i = 0 ; i < 91 ; i++) { availableNumbers[i] = pgm_read_byte_near(a + i); } for( int i = 0 ; i < 90 ; i++) { selectedNumbers[i] = pgm_read_byte_near(b + i); } remainNumbers = UPPER_BOUND; newGame = false; } //Random a new Number: cs = cs_7_8.capacitiveSensor(80); if ( cs > 100 ) { while ( cs_7_8.capacitiveSensor(80) > 100){}; cs_7_8.reset_CS_AutoCal(); newNumber = random(LOWER_BOUND, remainNumbers); rightNumber = availableNumbers[newNumber]; selectedNumbers[remainNumbers - 1] = rightNumber; for (int i = newNumber; newNumber < remainNumbers; newNumber++) { // here we shift all elements (who come AFTER the chosen one) in the array one place to the left availableNumbers[newNumber] = availableNumbers[newNumber + 1]; } remainNumbers--; //Turn ON LEDs from Matrix uint8_t address; uint8_t _row = pgm_read_byte_near(row + rightNumber); uint8_t _col = pgm_read_byte_near(col + rightNumber); //since i had 2 matrix i have to assign diferent address to correspondest to the right ou left side of the matrix if ( (rightNumber > 0 && rightNumber < 6) || (rightNumber > 10 && rightNumber < 16) || (rightNumber > 20 && rightNumber < 26) || (rightNumber > 30 && rightNumber < 36) || (rightNumber > 40 && rightNumber < 46) || (rightNumber > 50 && rightNumber < 56) || (rightNumber > 60 && rightNumber < 66) || (rightNumber > 70 && rightNumber < 76) || (rightNumber > 80 && rightNumber < 86) ) address = 1; else address = 0; lc.setLed(address, _row, _col, LED_ON); //Turn ON LEDs from Segment Numbers uint8_t resto; uint8_t num; resto = rightNumber % 10; num = rightNumber / 10; lc.setChar(2, 0, resto, false); lc.setChar(2, 1, num, false); } }
Images
Files to download: