Electronic dice application for the mBuino platform. Notes: The mBuino starts in Demo mode. In Demo mode the LEDs are lighted, showing sweeps and demo rolls. Connect a button or tilt-switch between P0.4 and GND. No soldering required! When the switch is triggered mBuino goes into Roll mode. In Roll mode mBuino starts with rapid flickering LEDs. Each subsequent switch trigger will perform a roll of the dice, of which the result is shown for ten seconds unless the switch is triggered for another roll. To preserve power, Power down mode is entered after inactivity in Demo mode or Roll mode. Press any button to revive.

Dependencies:   mbed

Fork of mBuino_Dice by Valentin Ivanov

mBuino_Dice

The hardware: No soldering required

As you can see in the picture gallery below, this is a very simple mBuino project, requiring only one extra component: a switch such as a push button or a tilt switch.

Push button

The push-button I used fits neatly between P0.4 and GND. By just bending the legs flat to the PCB, the button attached sturdy enough to make a usable connection.

Tilt switch

The tilt switch version is much more fun. No pushing, just a shake to roll the dice! In the tilt switch version two short wires were used to connect the switch. The wires were twisted around the legs of the tilt switch without any soldering! By adjusting the horizontal level of the switch you can make the dice react more sensitively to small movement.

For a production version, I would of course make it all a bit more durable by soldering the connections and using hot glue to keep everything in place. But going that route, I would also want to make a nicely fitting box, perhaps use other LEDs in a traditional dice-eye position and add an on-off switch...

Committer:
maxint
Date:
Mon Sep 08 10:01:38 2014 +0000
Revision:
3:52997a5f2fbc
Parent:
2:0d311a6cfb96
Child:
4:0c3a1b829d8c
0.1.140908 Added deep sleep mode, explanatory comments, incorporated suggestions, improved randomness

Who changed what in which revision?

UserRevisionLine numberNew contents of line
maxint 1:38fcbf88615a 1 /*
maxint 1:38fcbf88615a 2 ** mBuino_Dice
maxint 1:38fcbf88615a 3 **
maxint 1:38fcbf88615a 4 ** This electronic dice application allows the user to throw an electronic dice by the press of a button
maxint 1:38fcbf88615a 5 ** Setup requirements: connect any type of switch between P0.4 and GND.
maxint 1:38fcbf88615a 6 ** On mBuino P0.4 is close to GND and the two pitch distance is exactly the same as a mini-switch!
maxint 1:38fcbf88615a 7 **
maxint 3:52997a5f2fbc 8 ** 0.1.140908 Added deep sleep mode after one iteration of demo or ten seconds of wating, credits: Andy A and Erik Olieman
maxint 3:52997a5f2fbc 9 ** Added explanatory comments and incorporated suggestion by Erik Olieman
maxint 3:52997a5f2fbc 10 ** Improved randomness as per suggestion of Andy A
maxint 3:52997a5f2fbc 11 ** 0.1.140901 First version mad for mBuino on mbed.org by maxint on 1-sep-2014
maxint 1:38fcbf88615a 12 **
maxint 3:52997a5f2fbc 13 ** Feel free to use this code anyway you want, but please acknowledge my work by mentioning maxint as creator.
maxint 1:38fcbf88615a 14 **
maxint 1:38fcbf88615a 15 */
maxint 1:38fcbf88615a 16
maxint 1:38fcbf88615a 17
Architect 0:5d9ccbe9d49d 18 #include "mbed.h"
maxint 1:38fcbf88615a 19
maxint 1:38fcbf88615a 20 DigitalOut LED[] = {(P0_7), (P0_8), (P0_2), (P0_20), (P1_19), (P0_17), (P0_23)};// declare 7 LEDs
maxint 1:38fcbf88615a 21
maxint 3:52997a5f2fbc 22 InterruptIn ActionButton(P0_4); // declare the input for the button (or for other single switch, such as movement switch). On mBuino P0.4 is close to GND
maxint 3:52997a5f2fbc 23 AnalogIn RandomIn(P0_14); // use the random noise on this analog input to seed the random generator
maxint 1:38fcbf88615a 24
maxint 3:52997a5f2fbc 25 // Define the LED pattern of each dice number
maxint 3:52997a5f2fbc 26 // Can be made more compact by using binary values instead of a nested array.
maxint 1:38fcbf88615a 27 bool DicePattern[6][7]=
maxint 1:38fcbf88615a 28 {
maxint 1:38fcbf88615a 29 {0, 0, 0, 1, 0, 0, 0 },
maxint 1:38fcbf88615a 30 {0, 1, 0, 0, 0, 1, 0 },
maxint 1:38fcbf88615a 31 {0, 1, 0, 1, 0, 1, 0 },
maxint 1:38fcbf88615a 32 {1, 0, 1, 0, 1, 0, 1 },
maxint 1:38fcbf88615a 33 {1, 0, 1, 1, 1, 0, 1 },
maxint 1:38fcbf88615a 34 {1, 1, 1, 0, 1, 1, 1 }
maxint 1:38fcbf88615a 35 };
Architect 0:5d9ccbe9d49d 36
maxint 3:52997a5f2fbc 37 /*
maxint 3:52997a5f2fbc 38 // TODO: Suggestion by Erik Olieman: alternatively BusOut can be used to combine all used pins in one bus that can be set using a single write
maxint 3:52997a5f2fbc 39 BusOut LEDS(P0_7, P0_8, P0_2, P0_20, P1_19, P0_17, P0_23);
maxint 3:52997a5f2fbc 40 char byteDice[6]=
maxint 3:52997a5f2fbc 41 {
maxint 3:52997a5f2fbc 42 0x08, // 0B00001000
maxint 3:52997a5f2fbc 43 0x22, // 0B00100010
maxint 3:52997a5f2fbc 44 0x2A, // 0B00101010
maxint 3:52997a5f2fbc 45 0x55, // 0B01010101
maxint 3:52997a5f2fbc 46 0x5D, // 0B01011101
maxint 3:52997a5f2fbc 47 0x77 // 0B01110111
maxint 3:52997a5f2fbc 48 };
maxint 3:52997a5f2fbc 49 */
Architect 0:5d9ccbe9d49d 50
maxint 3:52997a5f2fbc 51 Timer tWait; // time used for tickcounts
maxint 3:52997a5f2fbc 52
maxint 3:52997a5f2fbc 53 void myDeepSleep()
maxint 3:52997a5f2fbc 54 { // Go into deep sleep to safe power. Use onboard or off-board interrupt triggered button to revive
maxint 3:52997a5f2fbc 55 // see http://mbed.org/forum/repo-52552-mBuino_low_power_led_flasher-community/topic/5130/
maxint 3:52997a5f2fbc 56 LPC_PMU->PCON = 0x1;
maxint 3:52997a5f2fbc 57 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
maxint 3:52997a5f2fbc 58 LPC_SYSCON->PDAWAKECFG &= 0xFFFFF800;
maxint 3:52997a5f2fbc 59 __WFI();
maxint 3:52997a5f2fbc 60 }
maxint 3:52997a5f2fbc 61
maxint 1:38fcbf88615a 62
maxint 1:38fcbf88615a 63 void SwitchAllLeds(bool fOn)
maxint 1:38fcbf88615a 64 { // switch all leds on or off
maxint 3:52997a5f2fbc 65 // Suggestion by Erik Olieman: alternatively BusOut can be used to combine all used pins in one bus that can be set using a single write
maxint 1:38fcbf88615a 66 for(int x = 0; x < 7; x++)
maxint 1:38fcbf88615a 67 {
maxint 1:38fcbf88615a 68 LED[x] = fOn?1:0; // turn on or off
maxint 1:38fcbf88615a 69 }
maxint 1:38fcbf88615a 70 }
maxint 1:38fcbf88615a 71
maxint 1:38fcbf88615a 72 void BlinkAllLeds(float flDelay=0.2)
maxint 1:38fcbf88615a 73 { // blink all leds
maxint 1:38fcbf88615a 74 SwitchAllLeds(true);
maxint 1:38fcbf88615a 75 wait(flDelay);
maxint 1:38fcbf88615a 76 SwitchAllLeds(false);
maxint 1:38fcbf88615a 77 wait(flDelay);
maxint 1:38fcbf88615a 78 }
maxint 1:38fcbf88615a 79
maxint 1:38fcbf88615a 80 void BlinkOneLed(int nLed=0, float flDelayOn=0.2, float flDelayOff=0.2)
maxint 3:52997a5f2fbc 81 { // blink just one led once, for the specified time
maxint 1:38fcbf88615a 82 LED[nLed] = 1; // turn on
maxint 1:38fcbf88615a 83 wait(flDelayOn); // delay
maxint 1:38fcbf88615a 84
maxint 1:38fcbf88615a 85 LED[nLed] = 0; // turn off
maxint 1:38fcbf88615a 86 wait(flDelayOff); // delay
maxint 1:38fcbf88615a 87 }
maxint 1:38fcbf88615a 88
maxint 1:38fcbf88615a 89 void SweepSingleLed(bool fLeftToRight=true, float flDelay=0.2)
maxint 1:38fcbf88615a 90 { // sweep a single led from left to rigth or vise-versa
maxint 1:38fcbf88615a 91 for(int n=0; n<7; n++)
maxint 1:38fcbf88615a 92 BlinkOneLed(fLeftToRight?n:6-n, flDelay, 0);
maxint 1:38fcbf88615a 93 }
maxint 1:38fcbf88615a 94
maxint 1:38fcbf88615a 95 void SweepAllLeds(bool fLeftToRight=true, float flDelay=0.1)
maxint 1:38fcbf88615a 96 { // light all leds up from left to rigth or vise-versa and then switch them of from reverse direction
maxint 1:38fcbf88615a 97 // leds on, left to right
maxint 1:38fcbf88615a 98 for(int n=0; n<7; n++)
maxint 1:38fcbf88615a 99 {
maxint 1:38fcbf88615a 100 LED[fLeftToRight?n:6-n] = 1; // turn on
maxint 1:38fcbf88615a 101 wait(flDelay); // delay
maxint 1:38fcbf88615a 102 }
maxint 1:38fcbf88615a 103 // leds off, right to left
maxint 1:38fcbf88615a 104 for(int n=0; n<7; n++)
maxint 1:38fcbf88615a 105 {
maxint 1:38fcbf88615a 106 LED[!fLeftToRight?n:6-n] = 0; // turn off
maxint 1:38fcbf88615a 107 wait(flDelay); // delay
maxint 1:38fcbf88615a 108 }
maxint 1:38fcbf88615a 109 }
maxint 1:38fcbf88615a 110
maxint 1:38fcbf88615a 111 void SwitchDiceLed(int nNumber, bool fOn=true)
maxint 1:38fcbf88615a 112 { // switch the leds of a particular dice-number on or off
maxint 1:38fcbf88615a 113 if(nNumber<1) nNumber=1;
maxint 1:38fcbf88615a 114 if(nNumber>6) nNumber=6;
maxint 1:38fcbf88615a 115
maxint 1:38fcbf88615a 116 for(int n=0; n<7; n++)
maxint 1:38fcbf88615a 117 if(DicePattern[nNumber-1][n])
maxint 1:38fcbf88615a 118 LED[n]=fOn;
maxint 1:38fcbf88615a 119 }
maxint 1:38fcbf88615a 120
maxint 1:38fcbf88615a 121 void BlinkDiceLed(int nNumber, float flDelayOn=0.6, float flDelayOff=0.1)
maxint 1:38fcbf88615a 122 { // blink a particular dice value
maxint 1:38fcbf88615a 123 SwitchDiceLed(nNumber, true);
maxint 1:38fcbf88615a 124 wait(flDelayOn);
maxint 1:38fcbf88615a 125 SwitchDiceLed(nNumber, false);
maxint 1:38fcbf88615a 126 wait(flDelayOff);
maxint 1:38fcbf88615a 127 }
maxint 1:38fcbf88615a 128
maxint 3:52997a5f2fbc 129 int RollDice(int nRolls=10, int nBlinks=2, float flDelayRoll=0.15)
maxint 1:38fcbf88615a 130 { // roll the dice and show the outcome value
maxint 1:38fcbf88615a 131 int nDiceValue;
maxint 3:52997a5f2fbc 132
maxint 3:52997a5f2fbc 133 // improve randomness: seed the random generator with the background noise of an analog input combined with passed time at user triggered moment
maxint 3:52997a5f2fbc 134 srand(RandomIn.read_u16()+tWait.read_us());
maxint 1:38fcbf88615a 135
maxint 1:38fcbf88615a 136 // first roll the dice
maxint 1:38fcbf88615a 137 for(int n=0; n<nRolls; n++)
maxint 1:38fcbf88615a 138 {
maxint 1:38fcbf88615a 139 nDiceValue=rand()%6+1;
maxint 1:38fcbf88615a 140 BlinkDiceLed(nDiceValue, flDelayRoll, 0);
maxint 1:38fcbf88615a 141 }
maxint 1:38fcbf88615a 142
maxint 1:38fcbf88615a 143 // then show the result
maxint 1:38fcbf88615a 144 nDiceValue=rand()%6+1;
maxint 1:38fcbf88615a 145 for(int n=0; n<nBlinks; n++)
maxint 1:38fcbf88615a 146 BlinkDiceLed(nDiceValue, flDelayRoll, 0);
maxint 3:52997a5f2fbc 147 SwitchDiceLed(nDiceValue, true); // return while keeping dice led's on
maxint 1:38fcbf88615a 148
maxint 1:38fcbf88615a 149 return(nDiceValue);
maxint 1:38fcbf88615a 150 }
maxint 1:38fcbf88615a 151
maxint 1:38fcbf88615a 152 bool fButtonPressed=false; // if the button is pressed, mBuino will switch from demo mode to play mode.
maxint 1:38fcbf88615a 153 bool fDemoDone=false;
maxint 1:38fcbf88615a 154
maxint 1:38fcbf88615a 155 void interruptButtonPressed()
maxint 1:38fcbf88615a 156 {
maxint 1:38fcbf88615a 157 fButtonPressed=true;
maxint 1:38fcbf88615a 158 }
maxint 1:38fcbf88615a 159
maxint 1:38fcbf88615a 160 void setup(void)
maxint 1:38fcbf88615a 161 { // perform initialisations
maxint 1:38fcbf88615a 162 srand(RandomIn.read_u16()); // seed the random generator with the background noise of an analog input
maxint 1:38fcbf88615a 163
maxint 2:0d311a6cfb96 164 ActionButton.fall(interruptButtonPressed); // using the fall requires the button to be unpressed before the interrupt is triggered again
maxint 3:52997a5f2fbc 165 tWait.start(); // start the timer
maxint 1:38fcbf88615a 166 }
maxint 1:38fcbf88615a 167
maxint 1:38fcbf88615a 168 void loop(void)
maxint 1:38fcbf88615a 169 { // run forever
maxint 1:38fcbf88615a 170 if(!fDemoDone && !fButtonPressed)
maxint 1:38fcbf88615a 171 { // Run an entertaining demo show until button is pressed
maxint 1:38fcbf88615a 172 // For all parts of the show we check to see if the actionbutton was pressed to stop the show asap
maxint 1:38fcbf88615a 173 if(!fButtonPressed)
maxint 1:38fcbf88615a 174 SweepAllLeds(true);
maxint 1:38fcbf88615a 175 if(!fButtonPressed)
maxint 1:38fcbf88615a 176 SweepAllLeds(false);
maxint 1:38fcbf88615a 177 if(!fButtonPressed)
maxint 1:38fcbf88615a 178 SweepAllLeds(true, 0.05);
maxint 1:38fcbf88615a 179 if(!fButtonPressed)
maxint 1:38fcbf88615a 180 SweepAllLeds(false, 0.05);
maxint 1:38fcbf88615a 181
maxint 1:38fcbf88615a 182 // show the dice numbers from one to six
maxint 1:38fcbf88615a 183 for(int n=1; n<=6; n++)
maxint 1:38fcbf88615a 184 if(!fButtonPressed)
maxint 1:38fcbf88615a 185 BlinkDiceLed(n);
maxint 1:38fcbf88615a 186
maxint 1:38fcbf88615a 187 if(!fButtonPressed)
maxint 1:38fcbf88615a 188 SweepSingleLed(true, 0.2);
maxint 1:38fcbf88615a 189 if(!fButtonPressed)
maxint 1:38fcbf88615a 190 SweepSingleLed(false, 0.1);
maxint 1:38fcbf88615a 191
maxint 1:38fcbf88615a 192 // show three random dice throws
maxint 1:38fcbf88615a 193 for(int n=0; n<3; n++)
maxint 1:38fcbf88615a 194 {
maxint 1:38fcbf88615a 195 if(!fButtonPressed)
maxint 1:38fcbf88615a 196 {
maxint 1:38fcbf88615a 197 RollDice();
maxint 1:38fcbf88615a 198 wait(1);
maxint 1:38fcbf88615a 199 SwitchAllLeds(false);
maxint 1:38fcbf88615a 200 }
maxint 1:38fcbf88615a 201 }
maxint 1:38fcbf88615a 202
maxint 1:38fcbf88615a 203 // blink all leds as the same time at increasing and decreasing speeds
maxint 1:38fcbf88615a 204 for(float flDelay=0.3; flDelay>0; flDelay-=0.05)
maxint 1:38fcbf88615a 205 if(!fButtonPressed)
maxint 1:38fcbf88615a 206 BlinkAllLeds(flDelay);
maxint 1:38fcbf88615a 207 for(float flDelay=0.05; flDelay<0.4; flDelay+=0.05)
maxint 1:38fcbf88615a 208 if(!fButtonPressed)
maxint 1:38fcbf88615a 209 BlinkAllLeds(flDelay);
maxint 1:38fcbf88615a 210
maxint 1:38fcbf88615a 211 if(!fButtonPressed)
maxint 1:38fcbf88615a 212 wait(1);
maxint 3:52997a5f2fbc 213
maxint 3:52997a5f2fbc 214 if(!fButtonPressed)
maxint 3:52997a5f2fbc 215 myDeepSleep(); // enter deep sleep after one demo iteration
maxint 1:38fcbf88615a 216 }
maxint 1:38fcbf88615a 217 else
maxint 1:38fcbf88615a 218 { // demo mode is ended, roll the dice upon each button press
maxint 1:38fcbf88615a 219 fDemoDone=true;
maxint 1:38fcbf88615a 220 fButtonPressed=false;
maxint 1:38fcbf88615a 221
maxint 3:52997a5f2fbc 222 unsigned uTickStop=tWait.read_ms()+10000;
maxint 1:38fcbf88615a 223 while(!fButtonPressed)
maxint 1:38fcbf88615a 224 { // flash the LEDS to show we wait for a roll call
maxint 1:38fcbf88615a 225 SweepAllLeds(true, 0.01);
maxint 1:38fcbf88615a 226 SweepAllLeds(false, 0.01);
maxint 3:52997a5f2fbc 227
maxint 3:52997a5f2fbc 228 if(!fButtonPressed && tWait.read_ms()>uTickStop)
maxint 3:52997a5f2fbc 229 myDeepSleep(); // enter deep sleep when waited for more than 10 seconds without button pressed
maxint 1:38fcbf88615a 230 }
maxint 1:38fcbf88615a 231 fButtonPressed=false;
maxint 1:38fcbf88615a 232
maxint 3:52997a5f2fbc 233 // roll the dice and show the outcome while waiting max. 10 seconds
maxint 1:38fcbf88615a 234 int nDiceValue=RollDice();
maxint 1:38fcbf88615a 235 wait(1);
maxint 1:38fcbf88615a 236 fButtonPressed=false;
maxint 3:52997a5f2fbc 237
maxint 3:52997a5f2fbc 238 uTickStop=tWait.read_ms()+10000;
maxint 3:52997a5f2fbc 239 while(!fButtonPressed && tWait.read_ms()<uTickStop)
maxint 3:52997a5f2fbc 240 //wait(0.1);
maxint 3:52997a5f2fbc 241 BlinkDiceLed(nDiceValue, 0.2, 0.01); // to indicate waiting for a new roll, blink the thrown dice value...
maxint 1:38fcbf88615a 242 SwitchAllLeds(false);
maxint 1:38fcbf88615a 243 }
maxint 1:38fcbf88615a 244 }
Architect 0:5d9ccbe9d49d 245
Architect 0:5d9ccbe9d49d 246 int main()
maxint 1:38fcbf88615a 247 { // implement Arduino-style setup() and loop()
maxint 1:38fcbf88615a 248 setup();
maxint 1:38fcbf88615a 249 while(true)
maxint 1:38fcbf88615a 250 loop();
Architect 0:5d9ccbe9d49d 251 }