Monday 4 August 2014

Arduino miniDUBsiren - compact pocket-sized dub siren



While i have to wait for some bits && pots to finish the other prototype, i decided to go back to Arduino Uno and do something quick; Ended up creating the Pocket sized miniDubSiren.
* I have even seen some 3D-printed cases for it here .



LCD Keypad Shield, Arduino Uno and you'd only have to worry about filtering the output. Cant get easier than that .
So, that makes it a shirt-pocket sized Dub Siren.
LFO is linear, for simplicity.
LCD displays top frequency/range and rate of LFO ( both with a minus - and a plus+ button for selection) and when sound is ON (triggered by the SELECT button: toggle action - one click ON , another OFF).
Also made a quick sounds FX generator for it, code to come soon ( even a "slightly slanted" sound wave LCD Char to go with it).
It was nice to work around the limitations of the available buttons and the frequency range in the tone function. Parameters can be changed during play, which creates some nice musical artifacts . A nice little toy.
While at it, developed a nice way of creating menus with this shield( despite not using it in this particular project, where simplicity was needed).

Button arrangement is : Trigger Toggle=Select  ; Freq= left/right ; Rate LFO=up/down .






//Sample using LiquidCrystal library
#include < LiquidCrystal.h >
//
byte wavform2[8] = {
  B01100,
  B10001,
  B10001,
  B00001,
  B00000,
  B00000,
  B00000,
};
byte wavform[8] = {
  B00000,
  B00000,
  B00000,
  B00001,
  B10001,
  B10010,
  B01100,
};
/*******************************************************

miniDubSiren by
Dubworks- Aug 2014
LCD KeyPad Code original by
Mark Bramwell- Jul 2010

********************************************************/// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
uint16_t i = 100; // tone minimum
boolean play = false;
boolean down = false;
uint16_t topFreq = 864;
uint16_t rate = 0;

int outPin = 3; // define number of output pin
// define some values used by the panel and buttons
int lcd_key     = 0;
int adc_key_in  = 0;
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

// read the buttons
int read_LCD_buttons()
{
  adc_key_in = analogRead(0);      // read the value from the sensor
  // my buttons when read are centered at these valies: 0, 144, 329, 504, 741
  // we add approx 50 to those values and check to see if we are close
  if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
  //
  if (adc_key_in < 50)   return btnRIGHT;
  if (adc_key_in < 250)  return btnUP;
  if (adc_key_in < 450)  return btnDOWN;
  if (adc_key_in < 650)  return btnLEFT;
  if (adc_key_in < 850)  return btnSELECT;

  return btnNONE;  // when all others fail, return this...
}

void setup()
{
  //  Serial.begin(9600);
  pinMode(outPin, OUTPUT);
  lcd.begin(16, 2);              // start the library
  lcd.createChar(0, wavform );
  lcd.createChar(1, wavform2 );
  lcdInit();
}

void loop()
{
  lcd_key = read_LCD_buttons();  // read the buttons

  switch (lcd_key)               // depending on which button was pushed, we perform an action
  {
    case btnRIGHT:
      {
        topFreq += 13;
        if (topFreq > 4000)
          topFreq = 4000;
        lcdFnct();
        delay(40);
        break;
      }
    case btnLEFT:
      {
        if (topFreq < 100)
          topFreq = 100;
        else
          topFreq -= 13 ;
        lcdFnct();
        delay(40);
        break;
      }
    case btnUP:
      {
        rate += 1 ;
        if (rate > 150) {
          rate = 150;
        }
        lcdFnct();
        delay(40);
        break;
      }
    case btnDOWN:
      {
        if (rate < 1)
          rate = 0;
        else
          rate -= 1 ;
        delay(40);
        lcdFnct();
        break;
      }
    case btnSELECT:
      {
        play = !play;
        if (play == false) {
          i = 100;
          noTone(3);
          delay(50);
        }
        delay(100);
        lcdFnct();
        break;
      }
    case btnNONE:
      {
        break;
      }
  }
  if (play == true) {
    tone(outPin, i);
    delay(5); // !!
  }
  else if (play == false) {
    i = 100;
    noTone(3);
    delay(50);
  }
  if (down == false) {
    i++;
    i += rate;
  }
  else if (down == true) {
    i--;
    i -= rate;
  }
  if (i > topFreq) {
    down = true;
    i = topFreq;
  }
  else if (i < 180) {
    down = false;
    i = 180;
  }
}
void lcdFnct() {
  lcd.clear();
  lcd.setCursor(0, 0);           //
  lcd.print("F= ");
  lcd.setCursor(4, 0);
  lcd.print(topFreq);
  lcd.setCursor(0, 1);
  lcd.print("R= ");
  lcd.setCursor(4, 1);
  lcd.print(rate);

  if (play == 1) {
    lcd.setCursor(10, 0);
    lcd.write(byte(0)); //
    lcd.setCursor(11, 0);
    lcd.write(byte(1));
    lcd.setCursor(10, 1);
    lcd.print("ON");
  }
}
void lcdInit() {
  lcd.setCursor(0, 0);
  lcd.print(" =  DubWorks  = "); // 
  lcd.setCursor(0, 1);
  lcd.print(" mini Dub Siren ");
  // scroll 12 positions to the right
  // to move it offscreen left:
  for (int positionCounter = 0; positionCounter < 12; positionCounter++) {
    // scroll one position left:
    lcd.scrollDisplayLeft();
    // wait a bit:
    delay(50);
  }

  // scroll 26 positions to the right
  // to move it offscreen right:
  for (int positionCounter = 0; positionCounter < 26; positionCounter++) {
    // scroll one position right:
    lcd.scrollDisplayRight();
    // wait a bit:
    delay(50);
  }

  // scroll 14 positions to the left
  // to move it back to center:
  for (int positionCounter = 0; positionCounter < 14; positionCounter++) {
    // scroll one position left:
    lcd.scrollDisplayLeft();
    // wait a bit:
    delay(50);
  }

  // delay at the end of the full loop:
  delay(500);

}



3D-Printed case : http://apcmag.com/arduino-project-digital-clock.htm
LCD KEYPAD : http://www.dfrobot.com/wiki/index.phptitle=Arduino_LCD_KeyPad_Shield_(SKU:_DFR0009)