Emulate rotary encoder on car stereo

Ok so I want to add a wired volume control to my car stereo. The stereo has an ALPS EC12 http://www.alps.com/WebObjects/catalog.woa/E/HTML/Encoder/Incremental/EC12E/EC12D1524406.html rotary encoder. I want to be able to either control the volume through the encoder itself or through buttons wired to the encoder.

I've soldered wires to terminals A, B and C on the encoder and connected them to 12, 13, and GND respectively. According to datasheet A and B are the two encoder signals. I can read them fine, the arduino shows 00, 01, 10, 11, as I'm turning the encoder. When I switch Pin 12 and 13 to digital output, the encoder stops functioning.

void setup()
{
  Serial.begin(9600);  
  Serial.println("Ready.");

  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
}

void loop()
{

}

That's all I'm doing. I haven't even got to the point of sending my own commands or emulating the turning of the switch. I'm just setting the pins to output mode and I even tried writing LOW to both before the loop. Why does the encoder become non-responsive after setting the pins to OUTPUT?

brianhj:
Why does the encoder become non-responsive after setting the pins to OUTPUT?

The encoder consists of switch contacts that are designed to be read by high impedance inputs: if you connect them to Arduino output pins they can't operate as intended.

brianhj:
I want to be able to either control the volume through the encoder itself or through buttons wired to the encoder.

I'm not sure what you want mean by "... or through buttons wired to the encoder" . Do you mean to use push buttons to increase or decrease the volume remotely? If so, you would need to route the outputs from the switches to the Arduino.

If you wish to control the volume from either of two controls connected at the same time, you'll need to use the Arduino to read the encoder contacts and the push button contacts and then use an algorithm to determine appropriate output voltages to send to the contacts to which the encoder would normally be connected.

If the volume control is to remain on the stereo, you would need to break its existing connections and wire them to the Arduino, then route the Arduino outputs back to the contacts to which the encoder would normally be connected.

I don't see any alternative...

cld_1:
I'm not sure what you want mean by "... or through buttons wired to the encoder" . Do you mean to use push buttons to increase or decrease the volume remotely? If so, you would need to route the outputs from the switches to the Arduino.

I meant instead of a second rotary controller I'll be sending volumn up/down commands with a push button on the steering wheel. That signal will go to the arduino which will emulate a rotary turn. Does that make sense? :~

cld_1:
If you wish to control the volume from either of two controls connected at the same time, you'll need to use the Arduino to read the encoder contacts and the push button contacts and then use an algorithm to determine appropriate output voltages to send to the contacts to which the encoder would normally be connected.

If the volume control is to remain on the stereo, you would need to break its existing connections and wire them to the Arduino, then route the Arduino outputs back to the contacts to which the encoder would normally be connected.

I see so the the arduino would be acting as the middle man? (receiving signals from the rotary switch, sending signals to contacts on circuit board)

Also, what kind of algorithm? The datasheet shows 5V?

brianhj:
I meant instead of a second rotary controller I'll be sending volume up/down commands with a push button on the steering wheel. That signal will go to the arduino which will emulate a rotary turn. Does that make sense? :~

Yes...

cld_1:
I see so the arduino would be acting as the middle man? (receiving signals from the rotary switch, sending signals to contacts on circuit board)

I don't see any alternative given the way the rotary encoder works, but if I'm missing something no doubt someone else will correct me...

cld_1:
... what kind of algorithm?

The algorithm would have to look at the two different inputs and decide what outputs to send to the stereo to emulate the 10... pattern normally sent by the encoder. Designing the algorithm would take some logical thought, but basically it would decide whether the encoder or switches were requesting an increase or decrease in volume and then send the appropriate two-bit 10... code depending on the last state of the code sent to the stereo -- the two-bit pattern repeats in a cycle of four states as you've seen.

I'm about to go to bed, by the way!

The existing encoder will be shorting A and B to ground at various points in the cycle
so you cannot just take over those signals. You need to break the connections and
insert your own signals. You could read the original encoder as well as your externally
mounted one and use the steps from both of them to step your emulated encoder that
you feed to the unit.

To emulate an encoder you need to first check what voltages are expected, the unit will
probably have pull-ups on A and B to 5V or 3.3V. Any higher than 5 and you have a problem,
if its not switching them to 0V then this description isn't going to work:

You configure two pins as open-drain outputs to be the emulated A & B:

  digitalWrite (pinA, LOW) ;   // ensure the pin pulls LOW when an OUTPUT, never pulls HIGH
  digitalWrite (pinB, LOW) ;

And then to drive them you use pinMode:

  switch (phase)
  {
  case 0:
    pinMode (pinA, OUTPUT) ;
    pinMode (pinB, OUTPUT) ; // both low
    break ;
  case 1:
    pinMode (pinA, OUTPUT) ; // one low
    pinMode (pinB, INPUT) ;  // other is undriven, pullup pulls it up...
    break ;
  case 2:
    pinMode (pinA, INPUT) ;
    pinMode (pinB, INPUT) ; // both high
    break ;
  case 3:
    pinMode (pinA, INPUT) ;
    pinMode (pinB, OUTPUT) ; // other low
    break ;
  }

Another thought, using opto-isolators might be possible, they are open-collector outputs
already and you get isolation.

MarkT:
The existing encoder will be shorting A and B to ground at various points in the cycle
so you cannot just take over those signals. You need to break the connections and
insert your own signals. You could read the original encoder as well as your externally
mounted one and use the steps from both of them to step your emulated encoder that
you feed to the unit.

To emulate an encoder you need to first check what voltages are expected, the unit will
probably have pull-ups on A and B to 5V or 3.3V. Any higher than 5 and you have a problem,
if its not switching them to 0V then this description isn't going to work:

You configure two pins as open-drain outputs to be the emulated A & B:

  digitalWrite (pinA, LOW) ;   // ensure the pin pulls LOW when an OUTPUT, never pulls HIGH

digitalWrite (pinB, LOW) ;




And then to drive them you use pinMode:


switch (phase)
  {
  case 0:
    pinMode (pinA, OUTPUT) ;
    pinMode (pinB, OUTPUT) ; // both low
    break ;
  case 1:
    pinMode (pinA, OUTPUT) ; // one low
    pinMode (pinB, INPUT) ;  // other is undriven, pullup pulls it up...
    break ;
  case 2:
    pinMode (pinA, INPUT) ;
    pinMode (pinB, INPUT) ; // both high
    break ;
  case 3:
    pinMode (pinA, INPUT) ;
    pinMode (pinB, OUTPUT) ; // other low
    break ;
  }

You just blew my mind a little bit.. why are we changing pin modes instead of digitalWrite'ing?