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:
Wed Sep 10 10:00:23 2014 +0000
Revision:
4:0c3a1b829d8c
Parent:
3:52997a5f2fbc
Child:
5:e2f89a6f4d6c
Use power down mode to safe even more power than deep sleep.

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