Nano + X9C104 to control Pioneer Stereo

Hi all,

I'm very new to Arduino and have never used a digital potentiometer before, so please forgive me if I'm asking very simple questions. I've installed a new stereo in my vehicle, but the stereo does not have a volume control knob.

Pioneer stereos have a wired 3.5mm input to interface with steering wheel controls. This input looks for resistance values to control the stereo, for example, placing a 16k Ohm resister across the tip and base of a stereo cable will result in the volume increasing.

I'm following this instructable to create a volume control knob using a Arduino Nano, X9C104, and rotary encoder. Link I have the volume control knob all wired up and programmed using the Sketch provided in the instructable, but I'm not getting the desired control outputs.

I'm testing the set up buy placing my DMM across RH and RW of the X9C104 while using the rotary encoder. I get resistance changes, but not what I would expect. From what I've read, the X9C104 should have 100 "steps" of resistance at about 1k Ohm for a total of 100k Ohm. When using the sketch from the instructable, I only get about 30 steps of resistance with each being close to 3.7K ohm of resistance. This prevents me from sending the correct resistance values to the stereo.

I've also found this thread Link which isn't directly related to what I'm trying to do, but was using the same testing technique with a DMM. There is some discussion in there regarding not being able to use a DMM to measure resistance of a X9C104, but that thread also links to a youtube video where the person IS testing their X9C using a DMM to measure resistance.

My questions is:

  1. Can I use a DMM to measure the resistance directly from the X9C and if not, how do I ensure I'm setting the right resistance value for my stereo controls?

Any help would be greatly appreciated.

Thanks!

Should be able to; you need to have the negative lead of the DMM connected to ground on the system - which is also connected to the "bottom" end of the digital potentiometer.

But you could do the same control function with a 74HC4066 (or 74HC4051 etc) to select one of four actual resistors.

Just want to control the volume with buttons? If that's all, Arduino may not be necessary.

Thanks I'll give that a try and see if it works!

No difference putting the meter on ground. I have new/different X9C's on the way to see if that maybe is the problem.

I want to have FF, Rewind, Volume up, Volume Down, and Mute. A rotary encoder can give me all of those functions, but each function is a different resistance value on the wired remote input. if there is a better way, I'm up for any ideas!!!!!

Oh, I didn't know about choosing a function by resistance. Then wouldn't it be better to use an Arduino with a digital potentiometer that allows you to set the value directly? For example, MCP4018 or MCP41100.

I thought that is what the X9C does, at least from what I read, it should have 100 "steps" of resistance up to 100k in 1k ohm steps. So I should be able to set the resistance to:

16k = Volume Up
23K = Volume Down
7k = FF
2k = Mute
10k = Prev/Rewind

I've never worked with Digital Pots before, so I'm not sure how what you linked and what I have are different.

Only different in the individual IC specifications.

They perform the same function.

Just a matter of reading the datasheets to figure out how to use them.

But frankly - for up to eight resistor choices, a 74HC4051 would do it perfectly and be dead simple to code. :grin:

I agree. I also prefer this simplified variant.

How? I can see that an encoder with push button could give you volume up (rotate encoder clockwise), volume down (rotate anticlockwise) and mute (push encoder). How would you select FF and rewind?

EDIT: Ah, turn while pushing?

The code from the instructable uses click for ff, double click for rewind and click hold for mute.

I've got different X9C's on the way. I'm thinking maybe the ones I ordered are bad, but I doubt that is the issue. If I can't get the new ones working, I might ask for some help to use the 74HC4051. I only jumped into this because someone took the time to already code it and made a nice tutorial. I'm in way over my head already. LOL

Thanks for all the input so far all, I really appreciate it.

Ok, so my new X9C's came in and I'm getting the exact same results. it is either something in the sketch I don't understand, or something with how I'm hooking it up. Either way I can't figure it out.

I'm up for trying this with 74HC4051. I did a bit of research and I think this is how I would wire it all up.

Drawing

I'm lost when it comes to the Arduino sketch, so any help with that would be greatly appreciated.

If that is too much to ask, I totally understand and appreciate the help so far!!

Thanks!

did you ever get anywhere with this i'm currently working on the same project

I did. To be honest I didn't know (and still) don't know enough about the sketch part to make it work, so I paid a guy on Fivver to code it up for me. I ended up not using the digital pot. I'm not in front of my computer now but will be later and I'll post the diagram and sketch.

The good news I have it in my truck now and it works great.

1 Like

The drawing I linked above is how the circuit is wired. Draft-Circuit hosted at ImgBB — ImgBB

Here is the sketch. If you try to test with a multi-meter, you won't see the state change. There is a delay down near the bottom that is set to 50ms. Change that to 4000 ms and you will see the resistance values on a meter, but for the sketch to work right you need to keep it at 50 ms when using it with the head unit.

// Multiplexer Input
#define m1 8
#define m2 9
#define m3 10

// Rotary Encoder Input
#define CLK A0
#define DT A1
#define SW A2

int doubleclickdelay = 300; // Timeout for doubleclick

int tripleclickdelay = 300; // Timeout for tripclick

int currentStateCLK, lastStateCLK;
unsigned long clickdelay, holdwait, doubleclick, lastButtonPress, mymillis;
bool waitsingle, holddelay;

void setup() {
  pinMode(CLK, INPUT);
  pinMode(DT, INPUT);
  pinMode(SW, INPUT_PULLUP);

  pinMode(m1, OUTPUT);
  pinMode(m2, OUTPUT);
  pinMode(m3, OUTPUT);

  Serial.begin(9600);

  lastStateCLK = digitalRead(CLK);
}

void loop() {
  mymillis = millis();

  currentStateCLK = digitalRead(CLK);

  if (currentStateCLK != lastStateCLK  && currentStateCLK == 1) {

    if (digitalRead(DT) != currentStateCLK) {
      Serial.println("CCW");
      SendChannel(1);
    } else {
      Serial.println("CW");
      SendChannel(2);
    }
  }

  lastStateCLK = currentStateCLK;

  bool btnState = digitalRead(SW);

  if (btnState == LOW) {

    if (mymillis - lastButtonPress > 60) {
      
      holdwait = mymillis;    // Reset hold wait timeout.
      holddelay = true;     // Enable hold function.

      if (doubleclick + doubleclickdelay >= mymillis) {   // If the button was activated 2 times in (300ms).
        waitsingle = false;
        holddelay = false;
        Serial.println("Double click");
        SendChannel(4);
      }
      else {          // If not enable 300ms timeout to get the time to doubleclick.
        waitsingle = true;
        clickdelay = mymillis;
      }
      doubleclick = mymillis;
    }

    lastButtonPress = mymillis;
  }

  if (holddelay && holdwait + doubleclickdelay < mymillis) {      // Hold function
    waitsingle = false;
    holddelay = false;
    Serial.println("Long click");
    SendChannel(5);
  }

  if (btnState) {
    holddelay = false;
  }

  if (clickdelay + doubleclickdelay < mymillis && waitsingle) {
    waitsingle = false;
    Serial.println("Single click");
    SendChannel(3);
  }
}

void SendChannel(int channel) {

  int controlPin[] = {m1, m2, m3};

  int Channels[8][3] = {
    {0, 0, 0}, //channel 0
    {1, 0, 0}, //channel 1
    {0, 1, 0}, //channel 2
    {1, 1, 0}, //channel 3
    {0, 0, 1}, //channel 4
    {1, 0, 1}, //channel 5
    {0, 1, 1}, //channel 6
    {1, 1, 1}, //channel 7
  };

  for (int i = 0; i < 3; i ++) {
    digitalWrite(controlPin[i], Channels[channel][i]);
  }

  delay(50);      // Delay for sending, shorter = faster response from rotary encoder

  for (int i = 0; i < 3; i ++) {
    digitalWrite(controlPin[i], LOW);
  }

}
1 Like

your awesome, thank you. i was about to go to fiver and do the same thing

Sure thing. Were you ever able to get this working for you? Mine is still running solid. I have a few small issues where sometimes the volume goes up one notch when turning it down or vice versa, but I think that is due to the rotary encoder and not the sketch.

I think that is the sketch. I think if you comment-out all those Serial.println(), the problem might go away.

Serial.println() is quite slow, especially at 9600 baud. This can cause the code to miss some signal edges from the encoder, which can fool it into thinking the encoder has moved in the opposite direction.

1 Like

Thanks for the tip, I'll give that a shot and see if it helps!!!