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:
Tue Sep 16 08:19:55 2014 +0000
Revision:
6:e52dbebd7465
Parent:
5:e2f89a6f4d6c
0.1.140916 Using the Outrageous Circuits mBuino platform instead of LPC11U24 (available now); Renamed LED ports to newly available mBuino LED constants; Earlier power down after dice roll, showing by flashes slowing down

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 6:e52dbebd7465 8 ** 0.1.140916 Using the Outrageous Circuits mBuino platform instead of LPC11U24 (available now)
maxint 6:e52dbebd7465 9 ** Renamed LED ports to newly available mBuino LED constants
maxint 6:e52dbebd7465 10 ** Earlier power down after dice roll, showing by flashes slowing down
maxint 6:e52dbebd7465 11 ** 0.1.140915 Energy use in power down mode down to 3 uA, credits: Andy A
maxint 4:0c3a1b829d8c 12 ** 0.1.140910 Power down after one iteration of demo or ten seconds of wating, credits: Andy A
maxint 3:52997a5f2fbc 13 ** 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 14 ** Added explanatory comments and incorporated suggestion by Erik Olieman
maxint 3:52997a5f2fbc 15 ** Improved randomness as per suggestion of Andy A
maxint 3:52997a5f2fbc 16 ** 0.1.140901 First version mad for mBuino on mbed.org by maxint on 1-sep-2014
maxint 1:38fcbf88615a 17 **
maxint 3:52997a5f2fbc 18 ** Feel free to use this code anyway you want, but please acknowledge my work by mentioning maxint as creator.
maxint 1:38fcbf88615a 19 **
maxint 1:38fcbf88615a 20 */
maxint 1:38fcbf88615a 21
maxint 1:38fcbf88615a 22
Architect 0:5d9ccbe9d49d 23 #include "mbed.h"
maxint 1:38fcbf88615a 24
maxint 6:e52dbebd7465 25 DigitalOut LED[] = {(LED1), (LED2), (LED3), (LED4), (LED5), (LED6), (LED7)};// declare 7 LEDs
maxint 1:38fcbf88615a 26
maxint 3:52997a5f2fbc 27 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 28 AnalogIn RandomIn(P0_14); // use the random noise on this analog input to seed the random generator
maxint 1:38fcbf88615a 29
maxint 3:52997a5f2fbc 30 // Define the LED pattern of each dice number
maxint 3:52997a5f2fbc 31 // Can be made more compact by using binary values instead of a nested array.
maxint 1:38fcbf88615a 32 bool DicePattern[6][7]=
maxint 1:38fcbf88615a 33 {
maxint 1:38fcbf88615a 34 {0, 0, 0, 1, 0, 0, 0 },
maxint 1:38fcbf88615a 35 {0, 1, 0, 0, 0, 1, 0 },
maxint 1:38fcbf88615a 36 {0, 1, 0, 1, 0, 1, 0 },
maxint 1:38fcbf88615a 37 {1, 0, 1, 0, 1, 0, 1 },
maxint 1:38fcbf88615a 38 {1, 0, 1, 1, 1, 0, 1 },
maxint 1:38fcbf88615a 39 {1, 1, 1, 0, 1, 1, 1 }
maxint 1:38fcbf88615a 40 };
Architect 0:5d9ccbe9d49d 41
maxint 3:52997a5f2fbc 42 /*
maxint 3:52997a5f2fbc 43 // 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 44 BusOut LEDS(P0_7, P0_8, P0_2, P0_20, P1_19, P0_17, P0_23);
maxint 3:52997a5f2fbc 45 char byteDice[6]=
maxint 3:52997a5f2fbc 46 {
maxint 3:52997a5f2fbc 47 0x08, // 0B00001000
maxint 3:52997a5f2fbc 48 0x22, // 0B00100010
maxint 3:52997a5f2fbc 49 0x2A, // 0B00101010
maxint 3:52997a5f2fbc 50 0x55, // 0B01010101
maxint 3:52997a5f2fbc 51 0x5D, // 0B01011101
maxint 3:52997a5f2fbc 52 0x77 // 0B01110111
maxint 3:52997a5f2fbc 53 };
maxint 3:52997a5f2fbc 54 */
Architect 0:5d9ccbe9d49d 55
maxint 3:52997a5f2fbc 56 Timer tWait; // time used for tickcounts
maxint 3:52997a5f2fbc 57
maxint 5:e2f89a6f4d6c 58 DigitalIn progMode(P0_3); // need to disable pull-down for minimal power deep sleep
maxint 4:0c3a1b829d8c 59 void myPowerDown(uint8_t uMode=0x02)
maxint 4:0c3a1b829d8c 60 { // Go into power-down mode (0x2) to safe most power. Use onboard or off-board interrupt triggered button to revive
maxint 4:0c3a1b829d8c 61 // See https://mbed.org/forum/electronics/topic/5138/
maxint 4:0c3a1b829d8c 62 // Alternative: Go into deep sleep mode (0x1) to safe less power. Is quicker than power-down. Also revived using onboard button or interrupt.
maxint 4:0c3a1b829d8c 63 // See http://mbed.org/forum/repo-52552-mBuino_low_power_led_flasher-community/topic/5130/
maxint 4:0c3a1b829d8c 64 // Power usage (CR3032 battery life):
maxint 4:0c3a1b829d8c 65 // Running 13mA (1.5 day)
maxint 4:0c3a1b829d8c 66 // Sleep 7mA (3 days)
maxint 4:0c3a1b829d8c 67 // Deep-sleep 480uA (43 days)
maxint 4:0c3a1b829d8c 68 // Power-down 120uA (170 days)
maxint 5:e2f89a6f4d6c 69 // Power-down with fix 3uA (years)
maxint 5:e2f89a6f4d6c 70 progMode.mode(PullNone); // fix the 120uA. see http://mbed.org/forum/electronics/topic/5138/?page=1#comment-25338
maxint 5:e2f89a6f4d6c 71
maxint 4:0c3a1b829d8c 72 LPC_PMU->PCON = uMode; // 0x2 = power down, 0x1 = deep sleep
maxint 3:52997a5f2fbc 73 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
maxint 3:52997a5f2fbc 74 LPC_SYSCON->PDAWAKECFG &= 0xFFFFF800;
maxint 3:52997a5f2fbc 75 __WFI();
maxint 3:52997a5f2fbc 76 }
maxint 1:38fcbf88615a 77
maxint 1:38fcbf88615a 78 void SwitchAllLeds(bool fOn)
maxint 1:38fcbf88615a 79 { // switch all leds on or off
maxint 3:52997a5f2fbc 80 // 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 81 for(int x = 0; x < 7; x++)
maxint 1:38fcbf88615a 82 {
maxint 1:38fcbf88615a 83 LED[x] = fOn?1:0; // turn on or off
maxint 1:38fcbf88615a 84 }
maxint 1:38fcbf88615a 85 }
maxint 1:38fcbf88615a 86
maxint 1:38fcbf88615a 87 void BlinkAllLeds(float flDelay=0.2)
maxint 1:38fcbf88615a 88 { // blink all leds
maxint 1:38fcbf88615a 89 SwitchAllLeds(true);
maxint 1:38fcbf88615a 90 wait(flDelay);
maxint 1:38fcbf88615a 91 SwitchAllLeds(false);
maxint 1:38fcbf88615a 92 wait(flDelay);
maxint 1:38fcbf88615a 93 }
maxint 1:38fcbf88615a 94
maxint 1:38fcbf88615a 95 void BlinkOneLed(int nLed=0, float flDelayOn=0.2, float flDelayOff=0.2)
maxint 3:52997a5f2fbc 96 { // blink just one led once, for the specified time
maxint 1:38fcbf88615a 97 LED[nLed] = 1; // turn on
maxint 1:38fcbf88615a 98 wait(flDelayOn); // delay
maxint 1:38fcbf88615a 99
maxint 1:38fcbf88615a 100 LED[nLed] = 0; // turn off
maxint 1:38fcbf88615a 101 wait(flDelayOff); // delay
maxint 1:38fcbf88615a 102 }
maxint 1:38fcbf88615a 103
maxint 1:38fcbf88615a 104 void SweepSingleLed(bool fLeftToRight=true, float flDelay=0.2)
maxint 1:38fcbf88615a 105 { // sweep a single led from left to rigth or vise-versa
maxint 1:38fcbf88615a 106 for(int n=0; n<7; n++)
maxint 1:38fcbf88615a 107 BlinkOneLed(fLeftToRight?n:6-n, flDelay, 0);
maxint 1:38fcbf88615a 108 }
maxint 1:38fcbf88615a 109
maxint 1:38fcbf88615a 110 void SweepAllLeds(bool fLeftToRight=true, float flDelay=0.1)
maxint 1:38fcbf88615a 111 { // light all leds up from left to rigth or vise-versa and then switch them of from reverse direction
maxint 1:38fcbf88615a 112 // leds on, left to right
maxint 1:38fcbf88615a 113 for(int n=0; n<7; n++)
maxint 1:38fcbf88615a 114 {
maxint 1:38fcbf88615a 115 LED[fLeftToRight?n:6-n] = 1; // turn on
maxint 1:38fcbf88615a 116 wait(flDelay); // delay
maxint 1:38fcbf88615a 117 }
maxint 1:38fcbf88615a 118 // leds off, right to left
maxint 1:38fcbf88615a 119 for(int n=0; n<7; n++)
maxint 1:38fcbf88615a 120 {
maxint 1:38fcbf88615a 121 LED[!fLeftToRight?n:6-n] = 0; // turn off
maxint 1:38fcbf88615a 122 wait(flDelay); // delay
maxint 1:38fcbf88615a 123 }
maxint 1:38fcbf88615a 124 }
maxint 1:38fcbf88615a 125
maxint 1:38fcbf88615a 126 void SwitchDiceLed(int nNumber, bool fOn=true)
maxint 1:38fcbf88615a 127 { // switch the leds of a particular dice-number on or off
maxint 1:38fcbf88615a 128 if(nNumber<1) nNumber=1;
maxint 1:38fcbf88615a 129 if(nNumber>6) nNumber=6;
maxint 1:38fcbf88615a 130
maxint 1:38fcbf88615a 131 for(int n=0; n<7; n++)
maxint 1:38fcbf88615a 132 if(DicePattern[nNumber-1][n])
maxint 1:38fcbf88615a 133 LED[n]=fOn;
maxint 1:38fcbf88615a 134 }
maxint 1:38fcbf88615a 135
maxint 1:38fcbf88615a 136 void BlinkDiceLed(int nNumber, float flDelayOn=0.6, float flDelayOff=0.1)
maxint 1:38fcbf88615a 137 { // blink a particular dice value
maxint 1:38fcbf88615a 138 SwitchDiceLed(nNumber, true);
maxint 1:38fcbf88615a 139 wait(flDelayOn);
maxint 1:38fcbf88615a 140 SwitchDiceLed(nNumber, false);
maxint 1:38fcbf88615a 141 wait(flDelayOff);
maxint 1:38fcbf88615a 142 }
maxint 1:38fcbf88615a 143
maxint 3:52997a5f2fbc 144 int RollDice(int nRolls=10, int nBlinks=2, float flDelayRoll=0.15)
maxint 1:38fcbf88615a 145 { // roll the dice and show the outcome value
maxint 1:38fcbf88615a 146 int nDiceValue;
maxint 3:52997a5f2fbc 147
maxint 3:52997a5f2fbc 148 // 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 149 srand(RandomIn.read_u16()+tWait.read_us());
maxint 1:38fcbf88615a 150
maxint 1:38fcbf88615a 151 // first roll the dice
maxint 1:38fcbf88615a 152 for(int n=0; n<nRolls; n++)
maxint 1:38fcbf88615a 153 {
maxint 1:38fcbf88615a 154 nDiceValue=rand()%6+1;
maxint 1:38fcbf88615a 155 BlinkDiceLed(nDiceValue, flDelayRoll, 0);
maxint 1:38fcbf88615a 156 }
maxint 1:38fcbf88615a 157
maxint 1:38fcbf88615a 158 // then show the result
maxint 1:38fcbf88615a 159 nDiceValue=rand()%6+1;
maxint 1:38fcbf88615a 160 for(int n=0; n<nBlinks; n++)
maxint 1:38fcbf88615a 161 BlinkDiceLed(nDiceValue, flDelayRoll, 0);
maxint 3:52997a5f2fbc 162 SwitchDiceLed(nDiceValue, true); // return while keeping dice led's on
maxint 1:38fcbf88615a 163
maxint 1:38fcbf88615a 164 return(nDiceValue);
maxint 1:38fcbf88615a 165 }
maxint 1:38fcbf88615a 166
maxint 1:38fcbf88615a 167 bool fButtonPressed=false; // if the button is pressed, mBuino will switch from demo mode to play mode.
maxint 1:38fcbf88615a 168 bool fDemoDone=false;
maxint 1:38fcbf88615a 169
maxint 1:38fcbf88615a 170 void interruptButtonPressed()
maxint 1:38fcbf88615a 171 {
maxint 1:38fcbf88615a 172 fButtonPressed=true;
maxint 1:38fcbf88615a 173 }
maxint 1:38fcbf88615a 174
maxint 1:38fcbf88615a 175 void setup(void)
maxint 1:38fcbf88615a 176 { // perform initialisations
maxint 1:38fcbf88615a 177 srand(RandomIn.read_u16()); // seed the random generator with the background noise of an analog input
maxint 1:38fcbf88615a 178
maxint 2:0d311a6cfb96 179 ActionButton.fall(interruptButtonPressed); // using the fall requires the button to be unpressed before the interrupt is triggered again
maxint 3:52997a5f2fbc 180 tWait.start(); // start the timer
maxint 1:38fcbf88615a 181 }
maxint 1:38fcbf88615a 182
maxint 1:38fcbf88615a 183 void loop(void)
maxint 1:38fcbf88615a 184 { // run forever
maxint 1:38fcbf88615a 185 if(!fDemoDone && !fButtonPressed)
maxint 1:38fcbf88615a 186 { // Run an entertaining demo show until button is pressed
maxint 1:38fcbf88615a 187 // For all parts of the show we check to see if the actionbutton was pressed to stop the show asap
maxint 1:38fcbf88615a 188 if(!fButtonPressed)
maxint 1:38fcbf88615a 189 SweepAllLeds(true);
maxint 1:38fcbf88615a 190 if(!fButtonPressed)
maxint 1:38fcbf88615a 191 SweepAllLeds(false);
maxint 1:38fcbf88615a 192 if(!fButtonPressed)
maxint 1:38fcbf88615a 193 SweepAllLeds(true, 0.05);
maxint 1:38fcbf88615a 194 if(!fButtonPressed)
maxint 1:38fcbf88615a 195 SweepAllLeds(false, 0.05);
maxint 1:38fcbf88615a 196
maxint 1:38fcbf88615a 197 // show the dice numbers from one to six
maxint 1:38fcbf88615a 198 for(int n=1; n<=6; n++)
maxint 1:38fcbf88615a 199 if(!fButtonPressed)
maxint 1:38fcbf88615a 200 BlinkDiceLed(n);
maxint 1:38fcbf88615a 201
maxint 1:38fcbf88615a 202 if(!fButtonPressed)
maxint 1:38fcbf88615a 203 SweepSingleLed(true, 0.2);
maxint 1:38fcbf88615a 204 if(!fButtonPressed)
maxint 1:38fcbf88615a 205 SweepSingleLed(false, 0.1);
maxint 1:38fcbf88615a 206
maxint 1:38fcbf88615a 207 // show three random dice throws
maxint 1:38fcbf88615a 208 for(int n=0; n<3; n++)
maxint 1:38fcbf88615a 209 {
maxint 1:38fcbf88615a 210 if(!fButtonPressed)
maxint 1:38fcbf88615a 211 {
maxint 1:38fcbf88615a 212 RollDice();
maxint 1:38fcbf88615a 213 wait(1);
maxint 1:38fcbf88615a 214 SwitchAllLeds(false);
maxint 1:38fcbf88615a 215 }
maxint 1:38fcbf88615a 216 }
maxint 1:38fcbf88615a 217
maxint 1:38fcbf88615a 218 // blink all leds as the same time at increasing and decreasing speeds
maxint 1:38fcbf88615a 219 for(float flDelay=0.3; flDelay>0; flDelay-=0.05)
maxint 1:38fcbf88615a 220 if(!fButtonPressed)
maxint 1:38fcbf88615a 221 BlinkAllLeds(flDelay);
maxint 1:38fcbf88615a 222 for(float flDelay=0.05; flDelay<0.4; flDelay+=0.05)
maxint 1:38fcbf88615a 223 if(!fButtonPressed)
maxint 1:38fcbf88615a 224 BlinkAllLeds(flDelay);
maxint 1:38fcbf88615a 225
maxint 1:38fcbf88615a 226 if(!fButtonPressed)
maxint 1:38fcbf88615a 227 wait(1);
maxint 3:52997a5f2fbc 228
maxint 3:52997a5f2fbc 229 if(!fButtonPressed)
maxint 4:0c3a1b829d8c 230 myPowerDown(); // enter dpower-down mode after one demo iteration
maxint 1:38fcbf88615a 231 }
maxint 1:38fcbf88615a 232 else
maxint 1:38fcbf88615a 233 { // demo mode is ended, roll the dice upon each button press
maxint 1:38fcbf88615a 234 fDemoDone=true;
maxint 1:38fcbf88615a 235 fButtonPressed=false;
maxint 1:38fcbf88615a 236
maxint 3:52997a5f2fbc 237 unsigned uTickStop=tWait.read_ms()+10000;
maxint 6:e52dbebd7465 238 float ftDelay=0.01;
maxint 1:38fcbf88615a 239 while(!fButtonPressed)
maxint 1:38fcbf88615a 240 { // flash the LEDS to show we wait for a roll call
maxint 6:e52dbebd7465 241 SweepAllLeds(true, ftDelay);
maxint 6:e52dbebd7465 242 SweepAllLeds(false, ftDelay);
maxint 3:52997a5f2fbc 243
maxint 3:52997a5f2fbc 244 if(!fButtonPressed && tWait.read_ms()>uTickStop)
maxint 4:0c3a1b829d8c 245 myPowerDown(); // enter power-down mode when waited for more than 10 seconds without button pressed
maxint 6:e52dbebd7465 246 else
maxint 6:e52dbebd7465 247 ftDelay=(10-((float)uTickStop-tWait.read_ms())/1000)/100; // make the fast flashes slow down while closer to power down mode
maxint 1:38fcbf88615a 248 }
maxint 1:38fcbf88615a 249 fButtonPressed=false;
maxint 1:38fcbf88615a 250
maxint 3:52997a5f2fbc 251 // roll the dice and show the outcome while waiting max. 10 seconds
maxint 1:38fcbf88615a 252 int nDiceValue=RollDice();
maxint 1:38fcbf88615a 253 wait(1);
maxint 1:38fcbf88615a 254 fButtonPressed=false;
maxint 3:52997a5f2fbc 255
maxint 3:52997a5f2fbc 256 uTickStop=tWait.read_ms()+10000;
maxint 6:e52dbebd7465 257 ftDelay=0.01;
maxint 3:52997a5f2fbc 258 while(!fButtonPressed && tWait.read_ms()<uTickStop)
maxint 6:e52dbebd7465 259 {
maxint 6:e52dbebd7465 260 BlinkDiceLed(nDiceValue, 0.2, ftDelay); // to indicate waiting for a new roll, flash the thrown dice value...
maxint 6:e52dbebd7465 261 ftDelay=(10-((float)uTickStop-tWait.read_ms())/1000)/100; // make the fast flashes slow down while closer to power down mode
maxint 6:e52dbebd7465 262 }
maxint 1:38fcbf88615a 263 SwitchAllLeds(false);
maxint 6:e52dbebd7465 264
maxint 6:e52dbebd7465 265 if(!fButtonPressed)
maxint 6:e52dbebd7465 266 myPowerDown(); // enter power-down mode when waited for more than 10 seconds without button pressed
maxint 1:38fcbf88615a 267 }
maxint 1:38fcbf88615a 268 }
Architect 0:5d9ccbe9d49d 269
Architect 0:5d9ccbe9d49d 270 int main()
maxint 1:38fcbf88615a 271 { // implement Arduino-style setup() and loop()
maxint 1:38fcbf88615a 272 setup();
maxint 1:38fcbf88615a 273 while(true)
maxint 1:38fcbf88615a 274 loop();
Architect 0:5d9ccbe9d49d 275 }