communicate with PT2258 Volume controller

Hi!
I just ordered a PT2258 Volume controller IC, that i'm going to use on my amplifier.
This is an I2C controlled IC, but the problem is that almot no one have interfaced it with an arduino before.
I don't have too much experience with the I2C protocol, so I might need some help.
I found a code on this forum, interfacing this IC with a bunch of other components, but I don't really understand the code:

can anyone help me?
I know that I can change the i2c address, but what kind of hex/bin numbers should I send to adjust the volume up and down using the arduino? (1db steps, like the datasheets says)
there is a list on page 9 on the datasheet, but that don't tell me anything!

Datasheet PT2258:

Link to forum post:
http://arduino.cc/forum/index.php/topic,71325.0.html

thanks!

Page 6 tells you how you calculate the I2C address of the chip. If you connect CODE1/2 to Vcc the corresponding bit is set to 1, if connected to GND it's 0. The address is then:

1 0 0 0 CODE1 CODE2 0

That means if CODE1 and CODE2 are connected to GND, the address is 0x40.

A test sketch can then be for channel 1:

#include "Wire.h"
#define PT_ADDR

void setup() {
  Wire.begin();
  Wire.beginTransmission(PT_ADDR);
  Wire.write(0xC0);
  Wire.endTransmission();
}

void loop() {
  uint8_t i;
  for (i = 70; i; i--) {
    set_volume(i);
    delay(100);
  }
  for (i = 1; i <= 70; i++) {
    set_volume(i);
    delay(100);
  }
}

void set_volume(uint8_t value) {
  uint8_t tens = value / 10;
  uint8_t ones = value % 10;
  Wire.beginTransmission(PT_ADDR);
  Wire.write(0x80 | tens);
  Wire.write(0x90 | ones);
  Wire.endTransmission();
}

I want to use a rotary switch and a remote control to control the volume, but I'll fix that part myself :slight_smile:
I've looked at the code example in the other forum post, but it's kinda complicated time consuming to write 40 cases.
is it possible to control the volume without using the case 1, case 2 ?

is it possible to control the volume without using the case 1, case 2 ?

Do I have any case in my code? What do you mean with this question? Describe in more detail? Do you mean the 6 different channels?

I want to use a rotary switch and a remote control to control the volume, but I'll fix that part myself smiley

Does that mean that the code I posted works for you?

The following is a routine that sets the volume on any channel and needs absolutely no case statement. The code in the forum thread you linked to is too bad to be adapted (my opinion).

uint8_t bases[] = { 0x80, 0x40, 0x00, 0x20, 0x60, 0xA0 };

void set_volume(uint8_t value, uint8_t channel) {
  uint8_t tens = value / 10;
  uint8_t ones = value % 10;
  uint8_t base = bases[channel -1];
  Wire.beginTransmission(PT_ADDR);
  Wire.write(base | tens);
  Wire.write(base | 0x10 | ones);
  Wire.endTransmission();
}

Thank you for the great answer! It have helped me a lot. Can I replace the uint8_t with int? I want to store the current volume settings, so when I plug in the power, the volume automatically turn back to the last used value (between 0- 70 or so).

anyways, here is my code. it's not finished yet, but I'm working in it. I'm making an arduino controlled amplifier, but I still need to impliment PWM controlled, temperature regulated fans and an LCD display that show temp, volume, audio source etc.

#include <IRremote.h>
#include <EEPROM.h>
#include <Wire.h>
#define PT_ADDR 0x80   //PT2258 i2c adress
#define CLEAR_REG 0xC0 // Clear PT2258's register
#define EEPROM_ADDR 0x00

int ch_1 = 0;
int ch_2 = 1;
int ch_3 = 2;
int ch_4 = 3;
int ch_5 = 4;
int ch_6 = 5;
int ch_7 = 6;
int ch_8 = 7;
int power_pin = 8;
int fan_pin = 9;
int indicator_led = 10;
int ir_pin = 11;
int temp_pin = A0;
int i;
int volume;
int raw;
int temperature;
int on = 0;


decode_results results;
IRrecv irrecv(ir_pin);

void setup() {
  pinMode(ir_pin, INPUT);
  pinMode(temp_pin, INPUT);
  pinMode(fan_pin, OUTPUT);
  pinMode(power_pin, OUTPUT);
  pinMode(ch_1,OUTPUT);
  pinMode(ch_2,OUTPUT);
  pinMode(ch_3,OUTPUT);
  pinMode(ch_4,OUTPUT);
  pinMode(ch_5,OUTPUT);
  pinMode(ch_6,OUTPUT);
  pinMode(ch_7,OUTPUT);
  pinMode(ch_8,OUTPUT);
  Wire.begin();
  Wire.beginTransmission(PT_ADDR);
  Wire.write(CLEAR_REG); 
  Wire.endTransmission();
  volume = EEPROM.read(EEPROM_ADDR);
  irrecv.enableIRIn(); 
  digitalWrite(power_pin,HIGH);
  }
    
    
void temp() {
  raw = analogRead(temp_pin);
  temperature = (raw/10); } //test value
  
  
void ir() {
  if(results.value == 0xC5E8 || results.value == 0xC0E8) { //  I/O button
    on = !on;
    digitalWrite(power_pin, on ? HIGH : LOW);
    delay(100); }
    
  if(results.value == 0xF587 || results.value ==0xC57C) { //  AUX Channel 1
    delay(300);
    digitalWrite(ch_1,LOW);
    digitalWrite(ch_2,LOW);
    digitalWrite(ch_3,HIGH);
    digitalWrite(ch_4,HIGH);
    digitalWrite(ch_5,HIGH);
    digitalWrite(ch_6,HIGH);
    digitalWrite(ch_7,HIGH);
    digitalWrite(ch_8,HIGH); }
    
  if(results.value == 0xF547 || results.value ==0xC5D0) { // AUX Channel 2
    delay(300);
    digitalWrite(ch_1,HIGH);
    digitalWrite(ch_2,HIGH);
    digitalWrite(ch_3,LOW);
    digitalWrite(ch_4,LOW);
    digitalWrite(ch_5,HIGH);
    digitalWrite(ch_6,HIGH);
    digitalWrite(ch_7,HIGH);
    digitalWrite(ch_8,HIGH); }  

  if(results.value == 0xF5C7 || results.value ==0xC130) { // AUX Channel 3
    delay(300);
    digitalWrite(ch_1,HIGH);
    digitalWrite(ch_2,HIGH);
    digitalWrite(ch_3,HIGH);
    digitalWrite(ch_4,HIGH);
    digitalWrite(ch_5,LOW);
    digitalWrite(ch_6,LOW);
    digitalWrite(ch_7,HIGH);
    digitalWrite(ch_8,HIGH); }
    
  if(results.value == 0xF527 || results.value ==0xF772) { // AUX Channel 4
    delay(300);
    digitalWrite(ch_1,HIGH);
    digitalWrite(ch_2,HIGH);
    digitalWrite(ch_3,HIGH);
    digitalWrite(ch_4,HIGH);
    digitalWrite(ch_5,HIGH);
    digitalWrite(ch_6,HIGH);
    digitalWrite(ch_7,LOW);
    digitalWrite(ch_8,LOW); }
    
    irrecv.resume(); 
  }  
 
 
/*
void set_volume(uint8_t value) {
  uint8_t tens = value / 10;
  uint8_t ones = value % 10;
  Wire.beginTransmission(PT_ADDR);
  Wire.write(0xD0 | tens);
  Wire.write(0xE0 | ones);
  Wire.endTransmission();
}  
*/

void loop() {
  if(irrecv.decode(&results)) { ir(); }
 
// Volume control    
    /*     uint8_t i;
        for (i = 70; i; i--) {
          set_volume(i);
          delay(100); } 
        for (i = 1; i <= 70; i++) {
          set_volume(i);
          delay(100); } */
          
        // Store current volume value in the EEPROM memory    
        EEPROM.write(EEPROM_ADDR, i);  

// Fan control
  if(digitalRead(power_pin) == HIGH) { 
    digitalWrite(fan_pin, LOW);}
  temp();
  if(temperature < 30 && on == 0) {
    digitalWrite(fan_pin,LOW);
    digitalWrite(power_pin,LOW); }
  else if(temperature >= 30 && temperature < 35 && on == 0 && digitalRead(power_pin) == LOW) {
    analogWrite(fan_pin,25);
    digitalWrite(power_pin,LOW); }  
  else if(temperature >= 35 && temperature < 40 && on == 0 && digitalRead(power_pin) == LOW) {
    analogWrite(fan_pin,65);
    digitalWrite(power_pin,LOW); }  
  else if(temperature >= 45 && temperature < 50 && on == 0 && digitalRead(power_pin) == LOW) {
    analogWrite(fan_pin,130);
    digitalWrite(power_pin,LOW); }
  else if(temperature >= 55 && temperature < 60 && on == 0 && digitalRead(power_pin) == LOW) {
    analogWrite(fan_pin,200);
    digitalWrite(power_pin,LOW); } 
  else if(temperature >= 60 && temperature < 75 && on == 0) {
    digitalWrite(fan_pin,HIGH);
    digitalWrite(power_pin,LOW); }   
  else if(temperature >= 75) {
    digitalWrite(power_pin,HIGH);
    digitalWrite(fan_pin,LOW); }  
 
}

Can I replace the uint8_t with int?

Why? uint8_t is the correct type. Int is a signed type so it would introduce a potential problem you don't have with uint8_t.

I want to store the current volume settings, so when I plug in the power, the volume automatically turn back to the last used value (between 0- 70 or so).

You could store that in the EEPROM but keep in mind that you have a limited number of write operations on the EEPROM so don't store it to often.

In your code you're storing the value in every loop run. I guess it will run about 1000 times a second, so in about two minutes your EEPROM will be history (not writable anymore).