SSブログ

踏切警報音 UNO R4 [Arduino]

踏切警報音スケッチをUNO R4用にも作ってみた。
UNO R4にはDACがあるのと、速度も速いので、レジスタ操作なしの純粋Arduinoでいけた。
量子化ビット数は DACの12ビット。
micros()でタイミングをとっているので、サンプリング周波数は 1,000,000(μsec)の約数。そのなかで処理が間に合う最大の50kHzとした。

UNO R4はAVRマイコンに比べてドライブ能力が低いので、アンプを使わないとそこそこの音量が出ないのが難点。
r4_piezo.jpg
とりあえず圧電サウンダで。

// railroad crossing sounds and signals : UNO R4
#define F_SAMP    50000         // sampling frequency (Hz) (divisor of 1,000,000 (usec))
#define F_SIGN    100           // light signal : 100/min  (1.666Hz, 0.6  sec)
#define F_DING    130           // ding sound   : 130/min  (2.166Hz, 0.461sec)
#define ATHALF    200           // attenuation half-life : 200 msec
static const uint16_t FRQ[][2] = {      // frequency combination (Hz)
      { 700,  750 },            // JR etc.
      { 450,  550 },            // ODAKYU
      { 550,  650 },            // TOKYU, KEIKYU  
      { 600,  650 },            // TOBU
      { 520,  660 }             // SEIBU
};
static uint16_t  SIN[256];      // array of sine wave

void setup() {
  analogWriteResolution(12);    // A0 : DAC
  pinMode( A1, OUTPUT );        // A1 : LED1
  pinMode( A2, OUTPUT );        // A2 : LED2
  pinMode( A3, INPUT_PULLUP );  // A3 : SW
  for (uint16_t i = 0; i < 256; i++) {
    SIN[i] = 32767.9 * (1 - cos(6.283185 * i / 256)) / 2;       // 15bit
  }
}

void loop() {
  static uint8_t ch;
  uint16_t  cDing, iDing = 60 * F_SAMP / F_DING;        // counter and initial cycles of ding sound
  uint16_t  cSign, iSign = 60 * F_SAMP / F_SIGN;        // counter and initial cycles of lignt signal
  uint16_t  cAttn, iAttn = ATHALF * F_SAMP /1000 /356;  // counter and initial cycles of attenuation
  uint16_t  iA, diA = (FRQ[ch][0] << 16) / F_SAMP;      // array subscript and its difference
  uint16_t  iB, diB = (FRQ[ch][1] << 16) / F_SAMP;
  uint16_t  env;                                        // envelope
  uint32_t  usInt = 1000000 / F_SAMP;                   // sampling time interval(usec)
  uint32_t  usPre = micros();                           // sampling time previous value(usec)
  digitalWrite( A1, HIGH );     // LED1 On
  digitalWrite( A2, LOW  );     // LED2 Off
  cDing = cSign= 0;
  do {
    if( !cDing-- ) {            // reset ding counter
      cDing = iDing;
      cAttn = iAttn;
      env   = 0xffff;
      iA    = 0;
      iB    = 0;
    }
    if( !cAttn-- ) {            // reset attenuation counter
      cAttn = iAttn;
      env  -= env >> 9;
    }
    if( !cSign-- ) {            // reset light counter
      cSign = iSign;
      digitalWrite( A1, !digitalRead(A1) );
      digitalWrite( A2, !digitalRead(A2) );
    }
    analogWrite( DAC, (SIN[(iA+=diA)>>8] + SIN[(iB+=diB)>>8]) * env >> 20 );
    while( micros() - usPre < usInt );
    usPre += usInt;
  } while( digitalRead(A3) );   // Press the tact switch to end
  analogWrite( DAC, 0 );
  digitalWrite( A1, LOW  );     // LED1 Off
  digitalWrite( A2, LOW  );     // LED2 Off
  delay(1000);
  if( ++ch == sizeof(FRQ)/sizeof(*FRQ) ) ch = 0;
}


nice!(0)  コメント(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。