Volume Control

Hello!

I am a beginner and want to make a simple volume control for my sound system.
I have a AD5206 Digital pot. I followed this link (http://arduino.cc/en/Tutorial/SPIDigitalPot) and managed to dimm some leds. Now i don't just want this in a loop but to control it with a rotary encoder.

So i got this code (http://bildr.org/2012/08/rotary-encoder-arduino/) and now i can read the rotary encoder. But now i wonder, how do i "merge" these two codes to control two channels of the AD5206 with the rotary encoder? Any inputs?

Thanks!

First: ..it seems a bit odd to me to use a rotatry encoder + dig.pot to make a potensiometer.
I'd understand better if you wantet to use a remote controller for this task..

You have working programs for each of your components.
Then copy one into the other. section by section.
Add the sequence where a given input from your rotart to set the corrensponding output to the dig.pot

I later want to do this wireless, thats why :slight_smile:

The last part you mention is where i fail, i don't know how use the input to write the output for the dig.pot!

post the set of codes. Lets try find a way merge them..

Thank you!

/*
  Digital Pot Control
  
  This example controls an Analog Devices AD5206 digital potentiometer.
  The AD5206 has 6 potentiometer channels. Each channel's pins are labeled
  A - connect this to voltage
  W - this is the pot's wiper, which changes when you set it
  B - connect this to ground.
 
 The AD5206 is SPI-compatible,and to command it, you send two bytes, 
 one with the channel number (0 - 5) and one with the resistance value for the
 channel (0 - 255).  
 
 The circuit:
  * All A pins  of AD5206 connected to +5V
  * All B pins of AD5206 connected to ground
  * An LED and a 220-ohm resisor in series connected from each W pin to ground
  * CS - to digital pin 10  (SS pin)
  * SDI - to digital pin 11 (MOSI pin)
  * CLK - to digital pin 13 (SCK pin)
 
 created 10 Aug 2010 
 by Tom Igoe
 
 Thanks to Heather Dewey-Hagborg for the original tutorial, 2005
 
*/


// inslude the SPI library:
#include <SPI.h>


// set pin 10 as the slave select for the digital pot:
const int slaveSelectPin = 10;

void setup() {
  // set the slaveSelectPin as an output:
  pinMode (slaveSelectPin, OUTPUT);
  // initialize SPI:
  SPI.begin(); 
}

void loop() {
  // go through the six channels of the digital pot:
  for (int channel = 0; channel < 6; channel++) { 
    // change the resistance on this channel from min to max:
    for (int level = 0; level < 255; level++) {
      digitalPotWrite(channel, level);
      delay(10);
    }
    // wait a second at the top:
    delay(100);
    // change the resistance on this channel from max to min:
    for (int level = 0; level < 255; level++) {
      digitalPotWrite(channel, 255 - level);
      delay(10);
    }
  }

}

void digitalPotWrite(int address, int value) {
  // take the SS pin low to select the chip:
  digitalWrite(slaveSelectPin,LOW);
  //  send in the address and value via SPI:
  SPI.transfer(address);
  SPI.transfer(value);
  // take the SS pin high to de-select the chip:
  digitalWrite(slaveSelectPin,HIGH); 
}
//From bildr article: http://bildr.org/2012/08/rotary-encoder-arduino/

//these pins can not be changed 2/3 are special pins
int encoderPin1 = 2;
int encoderPin2 = 3;

volatile int lastEncoded = 0;
volatile long encoderValue = 0;

long lastencoderValue = 0;

int lastMSB = 0;
int lastLSB = 0;

void setup() {
  Serial.begin (9600);

  pinMode(encoderPin1, INPUT); 
  pinMode(encoderPin2, INPUT);

  digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
  digitalWrite(encoderPin2, HIGH); //turn pullup resistor on

  //call updateEncoder() when any high/low changed seen
  //on interrupt 0 (pin 2), or interrupt 1 (pin 3) 
  attachInterrupt(0, updateEncoder, CHANGE); 
  attachInterrupt(1, updateEncoder, CHANGE);

}

void loop(){ 
  //Do stuff here

  Serial.println(encoderValue);
  delay(1000); //just here to slow down the output, and show it will work  even during a delay
}


void updateEncoder(){
  int MSB = digitalRead(encoderPin1); //MSB = most significant bit
  int LSB = digitalRead(encoderPin2); //LSB = least significant bit

  int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value

  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++;
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --;

  lastEncoded = encoded; //store this value for next time
}

merged code

// hearder removed - see originals
#include <SPI.h>

// set pin 10 as the slave select for the digital pot:
const int slaveSelectPin = 10;
// for encoder
//these pins can not be changed 2/3 are special pins
int encoderPin1 = 2;
int encoderPin2 = 3;
volatile int lastEncoded = 0;
volatile  byte encoderValue = 0; // contains the vaulue to be set to potmeter
// changed from long to byte because pot has only 256 posotions.  (knut_ny)
long lastencoderValue = 0;
int lastMSB = 0;
int lastLSB = 0;
// end encoder variables

void setup() {
  // set the slaveSelectPin as an output:
  pinMode (slaveSelectPin, OUTPUT);
  // initialize SPI:
  SPI.begin(); 
  // then the encoder
  Serial.begin (9600); // can be removed
  pinMode(encoderPin1, INPUT); 
  pinMode(encoderPin2, INPUT);
  digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
  digitalWrite(encoderPin2, HIGH); //turn pullup resistor on
  //call updateEncoder() when any high/low changed seen
  //on interrupt 0 (pin 2), or interrupt 1 (pin 3) 
  attachInterrupt(0, updateEncoder, CHANGE); 
  attachInterrupt(1, updateEncoder, CHANGE);
}

void loop() 
{
  // go through the six channels of the digital pot:
  // REMOVE this for-loop   use one og the pots only
  for (int channel = 0; channel < 6; channel++) 
  { 
    digitalPotWrite(channel, encoderValue);
    delay(10);
  }
}

void digitalPotWrite(int address, int value) {
  // take the SS pin low to select the chip:
  digitalWrite(slaveSelectPin,LOW);
  //  send in the address and value via SPI:
  SPI.transfer(address);
  SPI.transfer(value);
  // take the SS pin high to de-select the chip:
  digitalWrite(slaveSelectPin,HIGH); 
}
void updateEncoder() //
{
  int MSB = digitalRead(encoderPin1); //MSB = most significant bit
  int LSB = digitalRead(encoderPin2); //LSB = least significant bit
  int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value
  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) if (encoderValue<254)encoderValue ++;
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) if (encoderValue>0 ) encoderValue --;
  // changed above to keep encodervalue in range 0..255 )knut_ny)
  lastEncoded = encoded; //store this value for next time
}

WOW! Thank you, it's working perfectly! :slight_smile: Now i just have to make it wireless and add a display to show the volume!

What would you recommend if i want to send the rotary encoder signal wireless? RF? Xbee?
Will a Adafruit Trinket (Adafruit Trinket - Mini Microcontroller - 3.3V Logic [MicroUSB] : ID 1500 : $6.95 : Adafruit Industries, Unique & fun DIY electronics and kits) and RF/Xbee be sufficient?

Also is there anyway i can show the "Volume" With a bargraph led/series of leds?

Radio ?? why?? (ok, lets talk radio, you need 2pcs)
The nRF24 (2 different variants exists)
with PA - range 100m http://www.ebay.com/itm/NRF24L01-PA-LNA-SMA-Antenna-Wireless-Transceiver-communication-module-2-4G-S9-/310781092103?pt=LH_DefaultDomain_0&hash=item485bff2107
and without.- range 10m - http://www.ebay.com/itm/2PCS-NRF24L01-2-4GHz-Wireless-Transceiver-Module-NEW-/251099595360?pt=LH_DefaultDomain_0&hash=item3a76b3c260
Others exists; The type with a "zigzag" have shorter range is my experiance..
There are at least 2 different librarier to support this radio.

I'd use IR control Use any remote control you may have already og buy a simple one.
This one:
http://www.ebay.com/itm/Universal-Infrared-IR-Mini-TV-Set-Remote-Control-Keychain-Key-Ring-7-Keys-OH-/261328144482?pt=US_Remote_Controls&hash=item3cd85f0862
..is tricky because it will change codes if 'mute' is held down.
others may not have a desired layout
http://www.ebay.com/itm/24-Keys-IR-Remote-Control-Controller-For-RGB-5050-LED-Light-Strip-DC-12V-/350633562308?pt=US_Lighting_Parts_and_Accessories&hash=item51a36390c4
..maybe this one is suitable:
http://www.ebay.com/itm/IR-Remote-LED-Light-Lamp-Dimmer-Control-Controller-12-Keys-Brightness-Adjustable-/400600733701?pt=US_Lighting_Parts_and_Accessories&hash=item5d45aa1805
In addition you'll need a reciver, e.g. like this one.
http://www.ebay.com/itm/New-IR-Receiver-Module-38-kHz-TSOP4838-DIP-3-/230999762055?pt=AU_B_I_Electrical_Test_Equipment&hash=item35c8a8a487
There is also an OK working library for the IR receiver.

If you build this e.g. around a "mini pro" , you may need:
http://www.ebay.com/itm/New-IR-Receiver-Module-38-kHz-TSOP4838-DIP-3-/230999762055?pt=AU_B_I_Electrical_Test_Equipment&hash=item35c8a8a487
for programmin it (there are ways around it, but this makes it easy and clean)
"Mini pro" can drive 10 (small size, 3mm) LEDS @ 10mA each without additional hardware except resistors

Answer: You can build whatever you want