Keep Talking and No Kitty Explodes
by RémiD14 in Circuits > Arduino
1371 Views, 7 Favorites, 0 Comments
Keep Talking and No Kitty Explodes
![IMG_20180628_212618.jpg](/proxy/?url=https://content.instructables.com/FSN/IAEY/KBKSRHFF/FSNIAEYKBKSRHFF.jpg&filename=IMG_20180628_212618.jpg)
![ktane3.jpg](/proxy/?url=https://content.instructables.com/FKA/Z8HZ/KBKSRI7F/FKAZ8HZKBKSRI7F.jpg&filename=ktane3.jpg)
![ktaneback.jpg](/proxy/?url=https://content.instructables.com/FZ6/S2C3/KBKSRJDB/FZ6S2C3KBKSRJDB.jpg&filename=ktaneback.jpg)
The goal is to make a version of the great Keep talking and nobody explodes ( https://keeptalkinggame.com/ ), but in real ! (Ok, without the exploding part, for this version...No animal was hurt during these howto)
Manual printed instruction
Because I have to made some change to make it work, I have change the orignale manual to :
- Remove un umplemented part (we don't use a anoying alarm clock in the room, ...)
- Change some stuff (you have to push the button to have the clue about the maze in the maze module, you're player position is flashing, in the morse module the correct position is working with a yellow / green led system,...)
But the good news is that the manual is in HTML, so we can change it easilly ( but i suppose there is copyright on it, so you have to do you're own manual )
Supplies
- 1 arduino nano for the core
- 1 4x8 segment for the timer
- 1 Arduino nano for each module (actually 4, 3 documented here)
- 1 nice suite case ( pink, it's best in my point of view )
- A lot of wire, resistance, button,
- A externale usb battery, if you don't wan't to have a power usb cable.... (here a unused 10000mAh)
- Decorative stuff (wood, tape, paint, ...)
- A lot of time
Price
About 25euro in my case for all (4x arduino nano, led button, matrix, segment screen, joystick), if you already have some electonic stuff.
Maybe up to 50euro if you don't have a old usb battery, some tools, wire....
Core
![IMG_20180628_183641.jpg](/proxy/?url=https://content.instructables.com/FHW/D4NX/KBKSRGZC/FHWD4NXKBKSRGZC.jpg&filename=IMG_20180628_183641.jpg)
![IMG_20180628_212643.jpg](/proxy/?url=https://content.instructables.com/FYT/HQFR/KBL9O8V2/FYTHQFRKBL9O8V2.jpg&filename=IMG_20180628_212643.jpg)
The core is an arduino plugged to :
- A 4x8segment display for the timer
- A 2 line screen for the instruction (number of failure, number of module solved, win or booom)
- A i2c "bus" (just screw terminal)
- A switch to turn in on/off
Here is the Arduino code :
The const NODE_ABOUT_XXX is the I2C adress of each module
#include <Wire.h> #include <MultiFuncShield.h> #include <TimerOne.h> //Common part to put in every core/node 130 #define NODE_SAMPLE_ADDR 9 #define NODE_ABOUT_MEMORY 10 #define NODE_MORSE 11 #define NODE_ABOUT_WIRE 12 #define NODE_ABOUT_LABYRINTHE 13 #define START 1 #define SLEEP 2 #define TURN_ON 3 #define DISARMED 4 #define EXPLOSED 5 #define SERIAL_EVEN 10 //ex 213478927398 #define SERIAL_ODD 11 //ex 213478927391 //End of common part #define START_BUTTON_PIN 7 #define DBG true #define MAX_TIME 19 #define MAX_MODULES 12 byte modAddress[MAX_MODULES]; volatile byte modMonitor[MAX_MODULES]; byte modN; int total_failure=0; int module_solved=0; int module_to_win=3; char strOut[4]; unsigned int running=ON; volatile unsigned int clockMilliSeconds = 1000; volatile byte clockSeconds = MAX_TIME; void setup(){ Serial.begin(9600); Serial.println("Start core"); Timer1.initialize(); MFS.initialize(&Timer1); // initialize multi-function shield library MFS.userInterrupt = clockISR; strcpy(strOut, " "); MFS.write(strOut); Serial.println("Module turnon send"); MFS.writeLeds(LED_1, OFF); MFS.writeLeds(LED_2, OFF); MFS.writeLeds(LED_3, OFF); MFS.writeLeds(LED_4, OFF); displayLives(); } void loop(){ delay(300); if(Wire.available()) { int failure=Wire.read(); int win=Wire.read(); Serial.print("Requested data, win");Serial.print(win);Serial.print(" loose "); Serial.println(failure); total_failure=failure; module_solved=win; displayLives(); succesReceived(); } displayTimes(); Serial.print("Sec ");Serial.println(clockSeconds); int buttonState = digitalRead(START_BUTTON_PIN); byte btn = MFS.getButton(); if (btn) { byte buttonNumber = btn & B00111111; byte buttonAction = btn & B11000000; if (btn == BUTTON_1_PRESSED || btn == BUTTON_1_LONG_PRESSED) { Serial.print("Send restart"); send(NODE_ABOUT_LABYRINTHE,TURN_ON); running=ON; } } if (clockSeconds<=0){ loose(); } } void clockISR (){ if (running){ clockMilliSeconds--; if (clockMilliSeconds <= 0){ clockMilliSeconds = 1000; clockSeconds--; } } } void send(int address,int info){ Wire.beginTransmission(address); Wire.write(info); Wire.endTransmission(); } void displayTimes(){ if (running){ sprintf(strOut, "%02d %d", clockSeconds,module_to_win); MFS.write(strOut); } } void displayLives(){ if (total_failure==0){ MFS.writeLeds(LED_3, ON); } else { MFS.writeLeds(LED_3, OFF); } if (total_failure<1){ MFS.writeLeds(LED_2, ON); } else { MFS.writeLeds(LED_2, OFF); } if (total_failure<2){ MFS.writeLeds(LED_1, ON); } else { MFS.writeLeds(LED_1, OFF); } if (total_failure==2){ loose(); } } void succesReceived() { /* if (module_solved>2){ digitalWrite(SOLVE_LED_PIN3, HIGH); } else { digitalWrite(SOLVE_LED_PIN3, LOW); } if (module_solved>1){ digitalWrite(SOLVE_LED_PIN2, HIGH); } else { digitalWrite(SOLVE_LED_PIN2, LOW); } if (module_solved>0){ digitalWrite(SOLVE_LED_PIN1, HIGH); } else { digitalWrite(SOLVE_LED_PIN1, LOW); }*/ Serial.println("Succes revieved"); if (module_solved==module_to_win){ win(); } } void win(){ Serial.println("Win"); send(NODE_SAMPLE_ADDR,DISARMED); /*MFS.beep(5, // beep for 50 milliseconds 5, // silent for 50 milliseconds 4, // repeat above cycle 4 times 3, // loop 3 times 50 // wait 500 milliseconds between loop );*/ } void loose(){ running=OFF; Serial.println("Loose"); MFS.write("EE"); send(NODE_SAMPLE_ADDR,EXPLOSED); clockSeconds = MAX_TIME; } void requestPayloads(){ for (int i = 0 ; i < modN ; i++) { #ifdef DBG Serial.println("Request comm w mod"); #endif if (modMonitor[i] == 1){ #ifdef DBG Serial.println(" Request !"); #endif Wire.requestFrom(modAddress[i], 2); // request data from module --> /!\ requestFrom(int, int) or (uint8_t, uint8_t) if (Wire.available() == 2) { int failure=Wire.read(); int win=Wire.read(); } } } } void I2Cscanner(){ //I2C scanner (build a tab w addresses (and payload size ?)) byte error, address; #ifdef DBG Serial.println("Scanning..."); #endif delay(500); // wait for modules to initialize... modN = 0; for (address = 1; address < 127; address++ ){ // The i2c_scanner uses the return value of // the Write.endTransmisstion to see if // a device did acknowledge to the address. Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0){ modAddress[modN] = address; modMonitor[modN] = 0; // set monitoring to 0 by default (mod is inactive) #ifdef DBG Serial.print("I2C device found at address 0x"); if (address < 16) { Serial.print("0"); } Serial.print(address, HEX); Serial.println(" !"); #endif modN++; } else if (error == 4) { #ifdef DBG Serial.print("Unknown error at address 0x"); if (address < 16) Serial.print("0"); Serial.println(address, HEX); #endif } } #ifdef DBG if (modN == 0) Serial.println("No I2C devices found\n"); else Serial.println("done\n"); #endif }</font> </font>
Module Communication
![IMG_20180628_183631.jpg](/proxy/?url=https://content.instructables.com/FMU/0HSV/KBKSRI5Y/FMU0HSVKBKSRI5Y.jpg&filename=IMG_20180628_183631.jpg)
For all the module, we have the common librairy to talk by I2C to the core :
Just 2 method to call : moduleSolved when module is done, and madeAFault when player make a fault, and that all
KTGame.h
/* KTGame.h - Library for KT slave code. Created by RDI, Mar 2018. Released into the public domain. */ #ifndef KTGame_h #define KTGame_h #include <Arduino.h> // library interface description class KTGame { public: KTGame(int nodeAdress,int ledSolved, int ledOn); static void moduleSolved(); static void madeAFault(); static void restart(); static void sleepUntil(); static boolean isSerialEven(); private: static void updateLed(); }; extern KTGame game; #endifKTGame.cpp
#include <Wire.h> #include "KTGame.h" #include <avr/sleep.h> #define START 1 #define SLEEP 2 #define SERIAL_EVEN 10 //ex 213478927398 #define SERIAL_ODD 11 //ex 213478927391 volatile int _fail; volatile int _done; volatile int _serialEven=false; int _ledSolved; int _ledOn; void requestEvent() { Wire.write(_fail); Wire.write(_done); } void receiveEvent(int bytes){ while (Wire.available() > 0){ int read = Wire.read(); switch (read){ case(START): KTGame::restart(); break; case(SLEEP): KTGame::sleepUntil(); break; case(SERIAL_EVEN): _serialEven=true; break; case(SERIAL_ODD): _serialEven=false; break; } } } KTGame::KTGame(int nodeAdress, int ledSolved, int ledOn){ Wire.begin(nodeAdress); // Activate I2C network // Wire.onReceive([] (int howMany) {receiveEvent(howMany);}); Wire.onRequest(requestEvent); // master node requests some writing Wire.onReceive(receiveEvent); // master node requests some reading if (ledSolved>=0){ pinMode(ledSolved, OUTPUT); } if (ledOn>=0){ pinMode(ledOn, OUTPUT); } _ledSolved=ledSolved; _ledOn=ledOn; } static boolean KTGame::isSerialEven(){ return _serialEven; } void KTGame::moduleSolved() { Serial.print("Well done, fault:");Serial.println(_fail); _done=true; updateLed(); } void KTGame::madeAFault(){ _fail++; Serial.print("Fault:");Serial.println(_fail); } static void KTGame::restart(){ _fail=0; _done=false; updateLed(); Serial.println("Restart module:"); } static void KTGame::updateLed(){ if (_ledSolved>=0){ digitalWrite(_ledSolved, _done); } if (_ledOn>=0){ digitalWrite(_ledOn, !_done); } } static void KTGame::sleepUntil(){ if (_ledSolved>=0){ digitalWrite(_ledSolved, LOW); } if (_ledOn>=0){ digitalWrite(_ledOn, LOW); } set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); sleep_mode(); // System sleeps here sleep_disable(); // System continues execution here when interrupt is received }
Module : Maze
![IMG_20180628_182629.jpg](/proxy/?url=https://content.instructables.com/F21/2OAW/KBKSRI5W/F212OAWKBKSRI5W.jpg&filename=IMG_20180628_182629.jpg)
![IMG_20180625_200603.jpg](/proxy/?url=https://content.instructables.com/FCU/H3QW/KBKSRH9R/FCUH3QWKBKSRH9R.jpg&filename=IMG_20180625_200603.jpg)
For the maze :
- A arduino nano
- A 8x8 led matrix
- A joystick (there is one button integrated in these one, else you need one more button)
To simulate the game feature (we only have led dot, no other shape....), you're position it flashing, you have the clue to identify the good maze when you push the button.
Here, I'mcheating a little bit, there is actually only 1 maze, but you can easylly add the other one (lab1 matrix define the maze wall)
#include <KTGame.h> #define NODE_ABOUT_LAB 13 #define Max7219_pinCLK 10 #define Max7219_pinCS 11 #define Max7219_pinDIN 12 #define ONLED 6 #define SOLVEDLED 7 #define UPPIN 1 #define DOWNPIN 2 #define LEFTPIN 3 #define RIGHTPIN 4 #define DISPLAYPIN 5 #define DOWN B1 #define UP B10 #define LEFT B100 #define RIGHT B1000 #define LANDMARK B10000 KTGame game = KTGame(NODE_ABOUT_LAB,SOLVEDLED,ONLED); int lab1 [6][6] = {{DOWN+RIGHT, LEFT+RIGHT, DOWN+LEFT, DOWN+RIGHT, LEFT+RIGHT, LEFT}, {DOWN+UP+LANDMARK, DOWN+RIGHT, LEFT+UP, UP+RIGHT, LEFT+RIGHT, DOWN+LEFT}, {DOWN+UP, UP+RIGHT, DOWN+LEFT, DOWN+RIGHT, LEFT+RIGHT, DOWN+UP+LEFT+LANDMARK}, {DOWN+UP, RIGHT, RIGHT+DOWN+LEFT, UP+LEFT, RIGHT, DOWN+UP+LEFT}, {DOWN+UP, LEFT+RIGHT, DOWN+LEFT, DOWN+RIGHT, LEFT, UP+DOWN}, {RIGHT+UP, LEFT, RIGHT+UP, UP+LEFT, RIGHT, LEFT+UP} }; volatile int positionX; volatile int positionY; int finishX; int finishY; volatile boolean blink; void setup() { Serial.begin(9600); pinMode(Max7219_pinCLK,OUTPUT); pinMode(Max7219_pinCS,OUTPUT); pinMode(Max7219_pinDIN,OUTPUT); delay(50); //Initialiser Write_Max7219(0x09, 0x00); //decoding :BCD Write_Max7219(0x0a, 0x03); //brightness Write_Max7219(0x0b, 0x07); //scanlimit;8 LEDs Write_Max7219(0x0c, 0x01); //power-down mode:0,normal mode:1 Write_Max7219(0x0f, 0x00); //test display:1;EOT,display:0 pciSetup(UPPIN); pciSetup(DOWNPIN); pciSetup(LEFTPIN); pciSetup(RIGHTPIN); pinMode(DISPLAYPIN,INPUT_PULLUP); } //Ecriture sur une rangee void Write_Max7219(unsigned char address,unsigned char dat){ digitalWrite(Max7219_pinCS,LOW); Write_Max7219_byte(address); //address,code of LED Write_Max7219_byte(dat); //data,figure on LED digitalWrite(Max7219_pinCS,HIGH); } // Ecriture sur un 8x8 void Write_Max7219_byte(unsigned char DATA) { unsigned char i; digitalWrite(Max7219_pinCS,LOW); for(i=8;i>=1;i--) { digitalWrite(Max7219_pinCLK,LOW); digitalWrite(Max7219_pinDIN,DATA&0x80);// Extracting a bit data DATA = DATA<<1; digitalWrite(Max7219_pinCLK,HIGH); } } void pciSetup(byte pin) { pinMode(pin,INPUT_PULLUP); *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin PCIFR |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt PCICR |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group } ISR (PCINT2_vect) { if (digitalRead(UPPIN)==LOW){ if ((lab1[positionX][positionY]& (UP )) >> 2){ positionY--; } else { game.madeAFault(); } } if (digitalRead(DOWNPIN)==LOW){ if ((lab1[positionX][positionY]& (DOWN )) >> 1){ positionY++; } else { game.madeAFault(); } } if (digitalRead(LEFTPIN)==LOW){ if ((lab1[positionX][positionY]& (LEFT )) >> 3){ positionX++; } else { game.madeAFault(); } } if (digitalRead(RIGHTPIN)==LOW){ if ((lab1[positionX][positionY]& (RIGHT )) >> 4){ positionX--; } else { game.madeAFault(); } } if (positionX==finishX && positionY==finishY){ game.moduleSolved(); } } void display(){ unsigned char DATA; if (digitalRead(DISPLAYPIN)==LOW){ for(int x=6;x>=1;x--) { DATA = B0; for(int y=6;y>=1;y--) { DATA = DATA<<1; if ((lab1[x][y]& (LANDMARK )) >> 5){ DATA = DATA+B1; } else if (blink && x==positionX && y==positionY){ DATA = DATA+B1; } } Write_Max7219(x, DATA); } } else { for(int x=6;x>=1;x--) { DATA = B0; for(int y=6;y>=1;y--) { DATA = DATA<<1; if (blink && x==positionX && y==positionY){ DATA = DATA+B1; } if (x==finishX && y==finishY){ DATA = DATA+B1; } } Write_Max7219(x, DATA); } } } //Need 6 analog, can do only 5 with interrupt, but it's not a button, we can wait for next loop void loop() { delay(100); blink=!blink; }
Module : Morse Code
![IMG_20180628_182635.jpg](/proxy/?url=https://content.instructables.com/FLH/L0WD/KBKSRI5X/FLHL0WDKBKSRI5X.jpg&filename=IMG_20180628_182635.jpg)
![IMG_20180628_183703.jpg](/proxy/?url=https://content.instructables.com/FLX/U5H4/KBKSRH4L/FLXU5H4KBKSRH4L.jpg&filename=IMG_20180628_183703.jpg)
- 1 arduino nano
- 1 rotary button
- 1 Led, bliking for the morse code
- 1 Led for the module status
When you plug all these (check the arduino pin in the code or change the const of course), you can also change the word to guest :
char *Phrase[] = {"AMBRE", "BOULE", "CHAUD", "DIESE", "ENFER", "BARBE", "GARDE", "HAMPE","BISOU","BIERE"} ;
but in these case, don't forget to change the printed manual !
/* Morse4_I2C // interruption en provenance du timer 2, // Supression du vernier * Avec I2C */ #include <Adafruit_NeoPixel.h> #include <Wire.h> //Common part to put in every core/node 120 #define NODE_SAMPLE_ADDR 9 #define NODE_ABOUT_MEMORY 10 #define NODE_MORSE 11 #define FAILED 1 #define SUCCED 2 #define TURN_ON 3 #define EXPLOSED 4 #define DISARMED 5 //End of common part #define PIXEL_PIN 11 #define Led 12 #define PotFreq A0 #define Valider 2 volatile byte LeClic = false ; byte Brillant = false ; enum EtatLed { END, LEDON, LEDOF } ; #define MaxElem 100 #define DURELEM 5 byte Action[MaxElem]= {END} ; // Actions elementaires byte Duree[MaxElem] ; // Durée de l'action volatile byte Compteur = 0xFF ; // Compteur de durée de l'action volatile byte Index = 0 ; // Action elementaire en cours Adafruit_NeoPixel strip = Adafruit_NeoPixel(1, PIXEL_PIN, NEO_GRB + NEO_KHZ800); int Frequences[] = {30,110, 220, 330, 440, 550, 660, 770, 880,990, 0} ; char *Phrase[] = {"AMBRE", "BOULE", "CHAUD", "DIESE", "ENFER", "BARBE", "GARDE", "HAMPE","BISOU","BIERE"} ; byte Choisi ; byte Resultat ; uint32_t LedDiff ; void setup () { pinMode (Led, OUTPUT); strip.begin(); strip.show(); strip.setBrightness(16); randomSeed(analogRead(7)); Choisi = random(10); cli(); // Désactive l'interruption globale bitClear (TCCR2A, WGM20); // WGM20 = 0 bitClear (TCCR2A, WGM21); // WGM21 = 0 TCCR2B = 0b00000110; // Clock / 256 soit 16 micro-s et WGM22 = 0 TIMSK2 = 0b00000001; // Interruption locale autorisée par TOIE2 TCNT2 = 0 ; sei(); // Active l'interruption globale Serial.begin(57600); Wire.begin(NODE_SAMPLE_ADDR); // join i2c bus with address #2 Action[0] = END ; Serial.println(Phrase[Choisi]); Serial.print(ChargeUnePhrase(Phrase[Choisi])) ; Serial.println(" Elements"); pinMode(Valider, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(Valider), Clic, FALLING ); } // Routine d'interruption ISR(TIMER2_OVF_vect) { static byte varCompteur = 0; // La variable compteur TCNT2 = 256 - 250; // 250 x 16 µS = 4 ms if (varCompteur++ > 10) { // 10 * 4 ms = 40 ms (demi-période) varCompteur = 0; do { if (Action[Index] == END) break ; // pas d'action en cours if (Compteur == 0xFF) { //si Compteur n'est pas initialisé (1ere fois) switch (Action[Index]) { //on effectue l'action case LEDOF : digitalWrite (Led, LOW) ; //PORTB |= _BV(Led); break ; case LEDON : digitalWrite (Led, HIGH) ; //PORTB &= ~_BV(Led); break ; } Compteur = Duree[Index] ; } if (Compteur-- != 0) break ; //si Compteur n'est pas à 0 if (Action[++Index] == END) Index = 0 ; // si Fin des actions, on repart a 0 switch (Action[Index]) { //on effectue l'action case LEDOF : digitalWrite (Led, LOW) ; break ; case LEDON : digitalWrite (Led, HIGH) ; break ; } Compteur = Duree[Index] ; // et on charge le delai } while (false) ; } } void Clic(void) { LeClic = true ; } void loop () { static char Freq = -1 ; Freq = QuelleFrequence() ; Resultat = (Freq == Choisi) ; if (LeClic) { LeClic=false ; if (Resultat) { Brillant=true ; strip.setPixelColor(0, strip.Color(0,255,0)); } else { Brillant=false ; strip.setPixelColor(0, strip.Color(255,0,0)); } strip.setBrightness(Brillant ? 64 : 8); } strip.show(); delay (100); } byte ChargeUnePhrase(char *s) { char c ; byte i = 0 ; cli() ; while (c = *s++) { switch (toupper(c)) { case 'A' : i = ChargeUnCaractere( i , ".-") ; break ; case 'B' : i = ChargeUnCaractere( i , "-...") ; break ; case 'C' : i = ChargeUnCaractere( i , "-.-.") ; break ; case 'D' : i = ChargeUnCaractere( i , "-..") ; break ; case 'E' : i = ChargeUnCaractere( i , ".") ; break ; case 'F' : i = ChargeUnCaractere( i , "..-.") ; break ; case 'G' : i = ChargeUnCaractere( i , "--.") ; break ; case 'H' : i = ChargeUnCaractere( i , "....") ; break ; case 'I' : i = ChargeUnCaractere( i , "..") ; break ; case 'J' : i = ChargeUnCaractere( i , ".---") ; break ; case 'K' : i = ChargeUnCaractere( i , "-.-") ; break ; case 'L' : i = ChargeUnCaractere( i , ".-..") ; break ; case 'M' : i = ChargeUnCaractere( i , "--") ; break ; case 'N' : i = ChargeUnCaractere( i , "-.") ; break ; case 'O' : i = ChargeUnCaractere( i , "---") ; break ; case 'P' : i = ChargeUnCaractere( i , ".--.") ; break ; case 'Q' : i = ChargeUnCaractere( i , "--.-") ; break ; case 'R' : i = ChargeUnCaractere( i , ".-.") ; break ; case 'S' : i = ChargeUnCaractere( i , "...") ; break ; case 'T' : i = ChargeUnCaractere( i , "-") ; break ; case 'U' : i = ChargeUnCaractere( i , "..-") ; break ; case 'V' : i = ChargeUnCaractere( i , "...-") ; break ; case 'W' : i = ChargeUnCaractere( i , ".--") ; break ; case 'X' : i = ChargeUnCaractere( i , "-..-") ; break ; case 'Y' : i = ChargeUnCaractere( i , "-.--") ; break ; case 'Z' : i = ChargeUnCaractere( i , "--..") ; break ; case ' ' : i = ChargeUnCaractere( i , " ") ; break ; case '0' : i = ChargeUnCaractere( i , "-----") ; break ; case '1' : i = ChargeUnCaractere( i , ".----") ; break ; case '2' : i = ChargeUnCaractere( i , "..---") ; break ; case '3' : i = ChargeUnCaractere( i , "...--") ; break ; case '4' : i = ChargeUnCaractere( i , "....-") ; break ; case '5' : i = ChargeUnCaractere( i , ".....") ; break ; case '6' : i = ChargeUnCaractere( i , "-....") ; break ; case '7' : i = ChargeUnCaractere( i , "--...") ; break ; case '8' : i = ChargeUnCaractere( i , "---..") ; break ; case '9' : i = ChargeUnCaractere( i , "----.") ; break ; } } i = ChargeUnCaractere( i , " ") ; sei() ; return i ; } byte ChargeUnCaractere(byte i, char *s) { char c ; while (c = *s++) { if (i >= MaxElem - 5) break ; switch (c) { case '.' : Action[i] = LEDON ; Duree[i] = DURELEM ; i++ ; Action[i] = LEDOF ; Duree[i] = DURELEM ; i++ ; break ; case '-' : Action[i] = LEDON ; Duree[i] = DURELEM * 3 ; i++ ; Action[i] = LEDOF ; Duree[i] = DURELEM ; i++ ; break ; } } Action[i] = LEDOF ; Duree[i] = DURELEM * 3 ; i++ ; Action[i] = END ; return i ; } void CliCli() { cli() ; byte i=0 ; Action[i] = LEDON ; Duree[i] = 1 ; i++ ; Action[i] = LEDOF ; Duree[i] = 1 ; i++ ; Action[i] = END ; Compteur = 0 ; sei() ; } char QuelleFrequence(void) { byte f ; int D ; int Dif = 1025 ; int Lu = analogRead(PotFreq) ; int Ajuste ; Ajuste = Lu ; for ( byte i = 0 ; Frequences[i] > 0 ; i++ ) { D = abs(Ajuste - Frequences[i]) ; if (D < Dif) { f = i ; Dif = D ; } } if (Dif > 20) f = -1 ; Serial.print(f); Serial.print(" Dif:"); Serial.println(Dif); // Led allumée selon la valeur de Dif LedDiff = strip.Color(Dif*5,0,0) ; if (Dif<=10) LedDiff = strip.Color(100+Dif*15,125-Dif*5,0) ; if (Dif>50) LedDiff = strip.Color(255,0,0) ; if (Dif<2) LedDiff = strip.Color(0,255,0) ; return f ; } /****** #include <Wire.h> //Common part to put in every core/node 120 #define NODE_SAMPLE_ADDR 9 #define NODE_ABOUT_MEMORY 10 #define NODE_MORSE 11 #define FAILED 1 #define SUCCED 2 #define TURN_ON 3 #define EXPLOSED 4 #define DISARMED 5 //End of common part #define SOLVE_BUTTON_PIN 6 #define FAILED_BUTTON_PIN 7 #define STARTED_LED_PIN 8 boolean started=false; int lastSuccessButtonState=HIGH; int lastFailureButtonState=HIGH; int failure=0; int win=0; void setup() { Wire.begin(NODE_SAMPLE_ADDR); // join i2c bus with address #2 Serial.begin(9600); Serial.println("Start NODE_SAMPLE"); pinMode(SOLVE_BUTTON_PIN, INPUT_PULLUP); pinMode(FAILED_BUTTON_PIN, INPUT_PULLUP); pinMode(STARTED_LED_PIN, OUTPUT); digitalWrite(STARTED_LED_PIN, LOW); Wire.onReceive(receiveEvent); Wire.onRequest(requestEvent); } void receiveEvent(int bytes) { int x = Wire.read(); // read one character from the I2C Serial.print("Received "); Serial.println(x); if (x==TURN_ON){ startModule(); } } void startModule(){ started=true; digitalWrite(STARTED_LED_PIN, HIGH); int failure=0; int win=0; } void loop() { delay(50); if (started){ if (readSuccessButton()) { sendSuccess(); } else if (readFailureButton()) { sendFailure(); } } } void requestEvent() { Serial.print("Request data, win");Serial.print(win);Serial.print(" loose "); Serial.println(failure); Wire.write(win); Wire.write(failure); } boolean readSuccessButton(){ int buttonState = digitalRead(SOLVE_BUTTON_PIN); if (buttonState != lastSuccessButtonState) { if (buttonState == LOW) { lastSuccessButtonState = buttonState; return true; } lastSuccessButtonState = buttonState; } return false; } boolean readFailureButton(){ int buttonState = digitalRead(FAILED_BUTTON_PIN); if (buttonState != lastFailureButtonState) { if (buttonState == LOW) { lastFailureButtonState = buttonState; return true; } lastFailureButtonState = buttonState; } return false; } void sendFailure() { failure++; Serial.println("Failure added"); } void sendSuccess() { win++; digitalWrite(STARTED_LED_PIN, LOW); started=false; Serial.println("Success added, turn off"); } */
Module Simon's
![IMG_20180628_182623.jpg](/proxy/?url=https://content.instructables.com/FPD/USTK/KBKSRI5U/FPDUSTKKBKSRI5U.jpg&filename=IMG_20180628_182623.jpg)
![IMG_20180625_200611.jpg](/proxy/?url=https://content.instructables.com/F17/8RN9/KBKSRHF6/F178RN9KBKSRHF6.jpg&filename=IMG_20180625_200611.jpg)
![IMG_20180628_212643.jpg](/proxy/?url=https://content.instructables.com/FBK/UQ33/KBKSRHKN/FBKUQ33KBKSRHKN.jpg&filename=IMG_20180628_212643.jpg)
- 4 led button
- 1 arduino nano
- 1 status led
Hum, embarasing...i don't find the code anymore...view these a an exercise (I made these one in less than one hour befroe an event, so i forgot to put it on git sorry) There a lot of Simon's sample for Arduino on the web, the 2 methods to call to communicate with the core are described in step 2 and you have 2 other exemple juste before.
You're supose to change the solving table according to the serial number. For these I have cheat for now, and put a fix printed serial number on the bomb.
Make It a Impressive Bomb
![IMG_20180628_185234.jpg](/proxy/?url=https://content.instructables.com/FD3/WLQA/KBKSRI5K/FD3WLQAKBKSRI5K.jpg&filename=IMG_20180628_185234.jpg)
![IMG_20180628_183649.jpg](/proxy/?url=https://content.instructables.com/FE1/ADO2/KBKSRGZE/FE1ADO2KBKSRGZE.jpg&filename=IMG_20180628_183649.jpg)
![IMG_20180628_185238.jpg](/proxy/?url=https://content.instructables.com/FK2/JZSY/KBKSRI5N/FK2JZSYKBKSRI5N.jpg&filename=IMG_20180628_185238.jpg)
![IMG_20180628_201429.jpg](/proxy/?url=https://content.instructables.com/FJC/X9NT/KBKSRHFC/FJCX9NTKBKSRHFC.jpg&filename=IMG_20180628_201429.jpg)
Now, you have to put all these together and make it shiny.
The wire
Don't hide the wire, it's a bomb you have to put a lot of visible wire. Forget what you now about wire color put them all !
The briefcase
You have to find a briefcase. At first I was looking for a second hand old briedcase, like in spy movie....but I have found these nice hello kitty case for 1euro, and think it was perfect for this !
You can do these in a small case, mine is less than 30cm
The TNT
I just cut a wood bar (a bar for a broom in a supermarket...) in 3 part, paint in red, put some black tape on it and it make a really good effet, and the other good part is that it hide the ugly USB battery
Glue
Fixe all these carefully, because you're in a briefcase so it will move.
More
![IMG_20180628_212645.jpg](/proxy/?url=https://content.instructables.com/F5G/BA4U/KBKSRHKO/F5GBA4UKBKSRHKO.jpg&filename=IMG_20180628_212645.jpg)
You can already play it, and enjoy it like that ! I've made a lot of people play to it, and the default timer is easy, but still stressfull and fun.
Stuff that can be improved :
- A buzzer, or lighting show, when the player failed and the bomb explode.
- More and more module.
Enjoy !