BooshBEATS

BooshBeats is a flame driven drum machine. It can be driven via MIDI, onboard buttons, or external direct drive interface.

Built by Tim Deagan, author of 'Make Fire: The Art and Science of Working with Propane' and licensed Texas Flame Effect Operator (FEO)

See the history and progress on Twitter @TimDeagan, hashtag #BooshBeats

Check out the segment Discovery Canada's Daily Planet show did on BooshBeats!!!

------------------------------------------------------

ME!

Collaboration with Ponytrap at Maker Faire Austin 2018

  • 2 Liquid Flame Effects
  • 6 Vapor Flame Effects
  • 4 'Strike Plates'
  • 120V AC auto ignition pilots
  • 27' wide, 18' deep
  • MIDI, Manual and External control

Want to learn to safely make flame effects? Check out my book:

Here's my current Arduino Uno code for BooshBeats:

// BooshBeats controller// 2018 - T. Deagan
#include <MIDI.h>#include <Wire.h> #include <LiquidCrystal_I2C.h>#include <Event.h>#include <Timer.h>#include <EEPROM.h> //Needed to access the eeprom read write functions
// start reading from the first byte (address 0) of the EEPROMint address = 0;byte value;
// MIDI Channel stored in 10th byte of the EEPROMint MIDICHaddr = 10;byte MIDICHval;
// MIDI base note stored in 20th byte of the EEPROMint MIDINOTEaddr = 20;byte MIDINOTEval;
// define input pinsint ModePin = 1;int SelectPin = 14;
const int MIDILED = 2;
// define valve pinsconst int b1 = 6;const int b2 = 7;const int b3 = 8;const int b4 = 9;const int b5 = 10;const int b6 = 11;const int b7 = 12;const int b8 = 13;
// declare MIDI notesint Note_1;int Note_2;int Note_3;int Note_4;int Note_5;int Note_6;int Note_7;int Note_8;
int BeatLen = 0;int MIDIChan = 0;int StartNote = 60;int SysMode = 0;
// Initialize MIDI libraryMIDI_CREATE_DEFAULT_INSTANCE();
// initialize the library with the numbers of the interface pinsLiquidCrystal_I2C lcd(0x3F,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
// SETUP TimerTimer t;
/*********************************************************/void setup(){//------------------------------------
// SETUP SOLENOID PINS pinMode(b1,OUTPUT); digitalWrite(b1,LOW); pinMode(b2,OUTPUT); digitalWrite(b2,LOW); pinMode(b3,OUTPUT); digitalWrite(b3,LOW); pinMode(b4,OUTPUT); digitalWrite(b4,LOW); pinMode(b5,OUTPUT); digitalWrite(b5,LOW); pinMode(b6,OUTPUT); digitalWrite(b6,LOW); pinMode(b7,OUTPUT); digitalWrite(b7,LOW); pinMode(b8,OUTPUT); digitalWrite(b8,LOW);
// SETUP UI PINS pinMode(ModePin, INPUT); pinMode(SelectPin, INPUT); digitalWrite(SelectPin, HIGH); // setup internal pullup resistor pinMode(MIDILED, OUTPUT);
SetupEEPROMDefaults();
lcd_StartUp();
// If the Select Pin is pressed on startup, go into mode selection if (digitalRead(SelectPin) == LOW) { ModeSelect(); }
// SETUP MIDI if (MIDIChan < 1){ MIDI.begin(MIDI_CHANNEL_OMNI); // Launch MIDI and listen to all channels } else { MIDI.begin(MIDIChan); }
// Draw Active Display on LCD lcd_ActiveDisplay();}
//********************************************************void loop(){ t.update(); // update the timer if (MIDI.read()) // If we have received a message { switch(MIDI.getType()) // look for NoteOn messages { // blink MIDI LED for visual feedback on MIDI signal received digitalWrite(MIDILED,HIGH); t.after(1, MIDILED_Off, (void*)10);
int rcvNote;
//################ NOTE ON ############################# case midi::NoteOn: // NoteOn message received // open the appropriate valve, start timer if in drum mode rcvNote = MIDI.getData1(); // get MIDI Note # if (rcvNote == Note_1){ digitalWrite(b1,HIGH); if (!SysMode){ t.after(BeatLen, Note1_Off, (void*)10); } } else if(rcvNote == Note_2){ digitalWrite(b2,HIGH); if (!SysMode){ t.after(BeatLen, Note2_Off, (void*)10); } } else if(rcvNote == Note_3){ digitalWrite(b3,HIGH); if (!SysMode){ t.after(BeatLen, Note3_Off, (void*)10); } } else if(rcvNote == Note_4){ digitalWrite(b4,HIGH); if (!SysMode){ t.after(BeatLen, Note4_Off, (void*)10); } } else if(rcvNote == Note_5){ digitalWrite(b5,HIGH); if (!SysMode){ t.after(BeatLen, Note5_Off, (void*)10); } } else if(rcvNote == Note_6){ digitalWrite(b6,HIGH); if (!SysMode){ t.after(BeatLen, Note6_Off, (void*)10); } } else if(rcvNote == Note_7){ digitalWrite(b7,HIGH); if (!SysMode){ t.after(BeatLen, Note7_Off, (void*)10); } } else if(rcvNote == Note_8){ digitalWrite(b8,HIGH); if (!SysMode){ t.after(BeatLen, Note8_Off, (void*)10); } } break; //################ NOTE OFF ############################# case midi::NoteOff: // NoteOff message received rcvNote = MIDI.getData1(); // get MIDI Note # // close the appropriate valve if in instrument mode if (rcvNote == Note_1 && SysMode){ digitalWrite(b1,LOW); } else if(rcvNote == Note_2 && SysMode){ digitalWrite(b2,LOW); } else if(rcvNote == Note_3 && SysMode){ digitalWrite(b3,LOW); } else if(rcvNote == Note_4 && SysMode){ digitalWrite(b4,LOW); } else if(rcvNote == Note_5 && SysMode){ digitalWrite(b5,LOW); } else if(rcvNote == Note_6 && SysMode){ digitalWrite(b6,LOW); } else if(rcvNote == Note_7 && SysMode){ digitalWrite(b7,LOW); } else if(rcvNote == Note_8 && SysMode){ digitalWrite(b8,LOW); } break; //#############################################// ----- Unmonitored Messages ------ // case midi::ProgramChange: // break;// case midi::ControlChange: // break;// case midi::AfterTouchPoly: // break;// case midi::AfterTouchChannel: // break;// case midi::PitchBend: // break;//----------------------------------- //############################################# default: break; } }}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//This function will write a 2 byte integer to the eeprom at the specified address and address + 1void EEPROMWriteInt(int p_address, int p_value) { byte lowByte = ((p_value >> 0) & 0xFF); byte highByte = ((p_value >> 8) & 0xFF);
EEPROM.write(p_address, lowByte); EEPROM.write(p_address + 1, highByte); }
//This function will read a 2 byte integer from the eeprom at the specified address and address + 1unsigned int EEPROMReadInt(int p_address) { byte lowByte = EEPROM.read(p_address); byte highByte = EEPROM.read(p_address + 1);
return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00); }
//**********************************************************88888void SetupEEPROMDefaults(){ // read a byte from the current address of the EEPROM, write default val if nothing's there. BeatLen = EEPROMReadInt(address); if (BeatLen < 10){ BeatLen = 500; EEPROMWriteInt(address, BeatLen); }
// read a byte from the current address of the EEPROM, write default val if nothing's there. MIDIChan = EEPROMReadInt(MIDICHaddr); if (MIDIChan > 16){ MIDIChan = 0; EEPROMWriteInt(MIDICHaddr, MIDIChan); }
// read a byte from the current address of the EEPROM, write default val if nothing's there. StartNote = EEPROMReadInt(MIDINOTEaddr); if (StartNote > 120){ StartNote = 60; EEPROMWriteInt(MIDINOTEaddr, StartNote); } // based on MIDINOTE Note_1 = StartNote; Note_2 = Note_1 + 1; Note_3 = Note_1 + 2; Note_4 = Note_1 + 3; Note_5 = Note_1 + 4; Note_6 = Note_1 + 5; Note_7 = Note_1 + 6; Note_8 = Note_1 + 7;}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//********************************************************void lcd_write(const String &lcd_msg){
lcd.setCursor(0,1); // set the cursor to column 11, line 0 lcd.print(lcd_msg); // Print a message to the LCD.}
//*********************************************************void lcd_ActiveDisplay(){ lcd.clear(); // top row lcd.setCursor(0,0); lcd.print("CH:"); lcd.setCursor(3,0); if (MIDIChan == 0){ lcd.print("OMNI"); } else { lcd.print(MIDIChan); } lcd.setCursor(8,0); lcd.print("1st#:"); lcd.setCursor(13,0); lcd.print(StartNote);
// bottom row lcd.setCursor(0,1); lcd.print(">"); lcd.setCursor(1,1); if (SysMode){ lcd.print("Inst"); } else { lcd.print("Drum"); } lcd.setCursor(10,1); lcd.print(BeatLen); lcd.setCursor(14,1); lcd.print("ms");}
//*********************************************************88void lcd_StartUp(){ // LCD INIT lcd.init(); lcd.backlight(); //init the backlight lcd.print("---BooshBeats---"); lcd_write("WAITING TO BURN!"); // BLINK LED SLOWLY TO INDICATE INPUT DESIRED while(digitalRead(SelectPin) == HIGH){ digitalWrite(MIDILED, HIGH); delay(500); digitalWrite(MIDILED, LOW); delay(500); }
// BLINK LED QUICKLY TO INDICATE INPUT RECEIVED for (int i = 0; i < 4; i++){ digitalWrite(MIDILED, HIGH); delay(100); digitalWrite(MIDILED, LOW); delay(100); }}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//********************************************************void ModeSelect(){ int mode_val = 0;
// wait until the select button is released while(digitalRead(SelectPin) == LOW){ delay(1); }
// until the Select button is pressed then chek mode pot while(digitalRead(SelectPin) == HIGH){ mode_val = analogRead(ModePin); mode_val = map(mode_val, 0, 1023, 0, 4); switch (mode_val){ case 0: lcd_write("Set System Mode "); break; case 1: lcd_write("-CHANGE BEAT ms-"); break; case 2: lcd_write("Set MIDI Channel"); break; case 3: lcd_write("Set Initial Note"); break; default: break; } }
// select was pressed, go to desired mode switch (mode_val){ case 0: SetSysMode(); break; case 1: BeatLenSelect(); break; case 2: SetMIDIChannel(); break; case 3: SetStartNote(); break;
}}
//********************************************************void BeatLenSelect(){ int beat_val = 0; // wait until the select button is released while(digitalRead(SelectPin)== LOW){ delay(1); }
// until select button is pressed, check mode pot for beat len while (digitalRead(SelectPin) == HIGH){ beat_val = analogRead(ModePin); lcd_write("BEAT ms: "); lcd.setCursor(9,1); lcd.print(beat_val); }
// write new beat len val to EEPROM and set global var EEPROMWriteInt(address, beat_val); BeatLen = beat_val; }
//********************************************************void SetMIDIChannel(){ int MIDICH_val = 0; // wait until the select button is released while(digitalRead(SelectPin)== LOW){ delay(1); }
// until select button is pressed, check mode pot for channel while (digitalRead(SelectPin) == HIGH){ MIDICH_val = analogRead(ModePin); MIDICH_val = map(MIDICH_val, 0, 1023, 0, 16); lcd_write("Rcv MIDI CH: "); lcd.setCursor(12,1); if (MIDICH_val == 0){ lcd.print("OMNI"); } else { lcd.print(MIDICH_val); } }
// write new beat len val to EEPROM and set global var EEPROMWriteInt(MIDICHaddr, MIDICH_val); MIDIChan = MIDICH_val; }
//********************************************************void SetStartNote(){ int StartNote_val = 0; // wait until the select button is released while(digitalRead(SelectPin)== LOW){ delay(1); }
// until select button is pressed, check mode pot for channel while (digitalRead(SelectPin) == HIGH){ StartNote_val = analogRead(ModePin); StartNote_val = map(StartNote_val, 0, 1023, 0, 120); lcd_write("Start Note#: "); lcd.setCursor(12,1); lcd.print(StartNote_val); }
// write new beat len val to EEPROM and set global var EEPROMWriteInt(MIDINOTEaddr, StartNote_val); StartNote = StartNote_val; // based on MIDINOTE Note_1 = StartNote; Note_2 = Note_1 + 1; Note_3 = Note_1 + 2; Note_4 = Note_1 + 3; Note_5 = Note_1 + 4; Note_6 = Note_1 + 5; Note_7 = Note_1 + 6; Note_8 = Note_1 + 7;}
//********************************************************void SetSysMode(){ int SysMode_val = 0; // wait until the select button is released while(digitalRead(SelectPin)== LOW){ delay(1); }
// until select button is pressed, check mode pot for channel while (digitalRead(SelectPin) == HIGH){ SysMode_val = analogRead(ModePin); SysMode_val = map(SysMode_val, 0, 1023, 0, 2); lcd_write("System Mode: "); lcd.setCursor(12,1); switch (SysMode_val){ case 0: lcd.print("Drum"); break; case 1: lcd.print("Inst"); break; } } SysMode = SysMode_val;}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

//********************************************************void Note1_Off(){ digitalWrite(b1,LOW);}
//********************************************************void Note2_Off(){ digitalWrite(b2,LOW);}
//********************************************************void Note3_Off(){ digitalWrite(b3,LOW);}
//********************************************************void Note4_Off(){ digitalWrite(b4,LOW);}
//********************************************************void Note5_Off(){ digitalWrite(b5,LOW);}
//********************************************************void Note6_Off(){ digitalWrite(b6,LOW);}
//********************************************************void Note7_Off(){ digitalWrite(b7,LOW);}
//********************************************************void Note8_Off(){ digitalWrite(b8,LOW);}
//**********************************************void MIDILED_Off(){ digitalWrite(MIDILED, LOW);}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%