2014年2月6日 星期四

PGA2311 + Arduino 音量控制

做完PCM5102a DAC之後,我一直覺得他太大聲...
我的音量控制都在0~3之間跳,間隔真的不太夠,所以開始來找音量控制的方法
最簡單的當然就是拿一個VR上去,但是這樣的話,軟體控制就需要帶有步進馬達的VR
而且最重要的是....好的VR很貴,一分錢一分貨就是了,兩邊的電阻值差異真的很小
我不想用便宜的VR....所以就找別的方法吧
就找到PGA系列了,這個PGA2311需要+-5V雙電壓,就可以+31.5dB 到 −95.5dB
兩個散熱片差很大的+-5V線性電源....沒辦法,現在整台Raspberry pi都是靠5V,小散熱片根本撐不住

UPDATE:
剛剛把編碼器也加上去了,現在可以獨立運作~~

可以準備搭棚了

UPDATE'2:


製作完畢, CODE如下:


#define LED_PIN 13

#define PGA_ZCEN_PIN     9
#define PGA_MUTE_PIN     4
#define PGA_CS_PIN      8
#define PGA_SDATA_PIN   7
#define PGA_SCK_PIN     5


int val;
int encoder0PinA = 11;
int encoder0PinB = 10;
int encoder0Pos = 130;
int encoder0PinALast = LOW;
int n = LOW;

int volume_left, old_l;
int volume_right, old_r;

void pga2311_init(void)
{
  pinMode(PGA_CS_PIN,    OUTPUT);    // pga-chipselect pin
  pinMode(PGA_SDATA_PIN, OUTPUT);    // pga-data-out (our data out to it) pin
  pinMode(PGA_SCK_PIN,   OUTPUT);    // pga-clock pin

  pinMode(PGA_ZCEN_PIN, OUTPUT);
pinMode (encoder0PinA,INPUT);
   pinMode (encoder0PinB,INPUT);
   Serial.begin (9600);
}

void pga2311_enable_zero_crossing_detection()
{
  digitalWrite(PGA_ZCEN_PIN, HIGH);
}

void pga2311_disable_zero_crossing_detection()
{
  digitalWrite(PGA_ZCEN_PIN, LOW);
}

void SPI_write(uint8_t out_spi_byte )
{
  uint8_t  i;

  // loop thru each of the 8-bits in the byte
  for (i=0; i < 8; i++) {

    // strobe clock
    digitalWrite(PGA_SCK_PIN, LOW);

    // send the bit (we look at the high order bit and 'print' that to the remote device)
    if (0x80 & out_spi_byte) {  // MSB is set
      digitalWrite(PGA_SDATA_PIN, HIGH);
    }
    else {
      digitalWrite(PGA_SDATA_PIN, LOW);
    }

    // unstrobe the clock via local SPI
    digitalWrite(PGA_SCK_PIN, HIGH);

    // get the next bit
    out_spi_byte <<= 1;   // left-shift the byte by 1 bit
  }
}

void pga2311_mute()
{
  pga2311_set_volume(0, 0);
}


void pga2311_set_volume( uint8_t left, uint8_t right )
{
  // Gain (dB) = 31.5 − [0.5 * (255 − N)]

  digitalWrite(PGA_CS_PIN, LOW);     // assert CS

  SPI_write(left);    // left value (0..255)
  SPI_write(right);   // right value (0..255)

  digitalWrite(PGA_CS_PIN, HIGH);    // deassert CS
}



void setup()   {
  Serial.begin(9600);
  Serial.println("PGA2311 Volume Control");

  pinMode(LED_PIN, OUTPUT);

  // set muting
  pinMode(PGA_MUTE_PIN, OUTPUT);
  digitalWrite(PGA_MUTE_PIN, HIGH); // high -> not muted, low -> muted

  pga2311_init();

  // set zero crossing detection
  pga2311_enable_zero_crossing_detection();

}

void loop()                  
{
  n = digitalRead(encoder0PinA);
   if ((encoder0PinALast == LOW) && (n == HIGH)) {
     if (digitalRead(encoder0PinB) == LOW) {
       encoder0Pos--;
     } else {
       encoder0Pos++;
     }
     Serial.print (encoder0Pos);
      pga2311_set_volume(encoder0Pos,encoder0Pos);
     Serial.print ("/");
   }
   encoder0PinALast = n;

}

12 則留言:

  1. 請問經過這個覺得音色變化大嗎?

    回覆刪除
  2. 請問有詳細一點的電路圖嗎?
    新手看不太懂...

    回覆刪除
  3. #define LED_PIN 13

    #define PGA_ZCEN_PIN 9
    #define PGA_MUTE_PIN 4
    #define PGA_CS_PIN 8
    #define PGA_SDATA_PIN 7
    #define PGA_SCK_PIN 5

    PGA照Datasheet接,PGA到Arduino可以隨便接到任何一隻GPIO
    把前面的變數改改就好

    回覆刪除
  4. 請問pga2311U下方的板子是甚麼

    回覆刪除
  5. SO-16 (1.27mm) TSSOP-16 (0.65mm) 轉 DIP 轉接板
    這可以用嗎

    回覆刪除
    回覆
    1. 其實只要規格符合就可以了,選SOP-16

      刪除
  6. 有arduino連pga2311u的程式碼嗎

    回覆刪除
  7. #define PGA_SDATA_PIN 7
    是哪一腳

    回覆刪除