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:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。