/*
JVC
Communicate with JVC car radio over 3.5mm Remote connector
Connect Arduino PIN to Base of NPN transistor
Emitter is tied to ground
Collector is tied to 3.5mm TIP
Ground 3.5mm Ring/Sleeve
By Dan Guerra ([email protected])
*/
int PIN = 7; // Digital IO pin connected to base of transistor
int Length = 537; // Length in Microseconds
int IncomingByte = 0; // Initialize Serial Buffer
int Reps = 3; // Number of times to repeat each transmission
void setup() {
pinMode(PIN, OUTPUT); // Set pin to output
digitalWrite(PIN, LOW); // Make PIN low to shut off transistor
Serial.begin(9600);
Serial.println("1 - Volume Up");
Serial.println("2 - Volume Down");
Serial.println("3 - Source");
Serial.println("4 - Sound");
Serial.println("5 - Mute");
Serial.println("6 - Skip Fwd");
Serial.println("7 - Skip Back");
Serial.println("8 - Skip Fwd Hold");
Serial.println("9 - Skip Back Hold");
}
void loop() {
if (Serial.available() > 0) {
IncomingByte = Serial.read();
switch (IncomingByte) {
case '1':
JVCVolUp();
break;
case '2':
JVCVolDn();
break;
case '3':
JVCSource();
break;
case '4':
JVCSound();
break;
case '5':
JVCMute();
break;
case '6':
JVCSkipFwd();
break;
case '7':
JVCSkipBack();
break;
case '8':
JVCSkipFwdHold();
break;
case '9':
JVCSkipBackHold();
break;
default:;
}
}
}
void JVCVolUp() { // Send 0x04
for (int i = 1; i <= Reps; i++); {
Preamble();
bZERO();
bZERO();
bONE(); // 4
bZERO();
bZERO();
bZERO(); // 0
bZERO();
Postamble();
}
}
void JVCVolDn() { // Send 0x05
for (int i = 1; i <= Reps; i++); {
Preamble();
bONE();
bZERO();
bONE(); // 5
bZERO();
bZERO();
bZERO(); // 0
bZERO();
Postamble();
}
}
void JVCSource() { // Send 0x08
for (int i = 1; i <= Reps; i++); {
Preamble();
bZERO();
bZERO();
bZERO(); // 8
bONE();
bZERO();
bZERO(); // 0
bZERO();
Postamble();
}
}
void JVCSound() { // Send 0x0D
for (int i = 1; i <= Reps; i++); {
Preamble();
bONE();
bZERO();
bONE(); // D (13)
bONE();
bZERO();
bZERO(); // 0
bZERO();
Postamble();
}
}
void JVCMute() { // Send 0x0E
for (int i = 1; i <= Reps; i++); {
Preamble();
bZERO();
bONE();
bONE(); // E (14)
bONE();
bZERO();
bZERO(); // 0
bZERO();
Postamble();
}
}
void JVCSkipFwd() { // Send 0x12
for (int i = 1; i <= Reps; i++); {
Preamble();
bZERO();
bONE();
bZERO(); // 2
bZERO();
bONE();
bZERO(); // 1
bZERO();
Postamble();
}
}
void JVCSkipBack() { // Send 0x13
for (int i = 1; i <= Reps; i++); {
Preamble();
bONE();
bONE();
bZERO(); // 3
bZERO();
bONE();
bZERO(); // 1
bZERO();
Postamble();
}
}
void JVCSkipFwdHold() { // Send 0x14
for (int i = 1; i <= Reps; i++); {
Preamble();
bZERO();
bZERO();
bONE(); // 4
bZERO();
bONE();
bZERO(); // 1
bZERO();
Postamble();
}
}
void JVCSkipBackHold() { // Send 0x15
for (int i = 1; i <= Reps; i++); {
Preamble();
bONE();
bZERO();
bONE(); // 5
bZERO();
bONE();
bZERO(); // 1
bZERO();
Postamble();
}
}
void bONE() { // Send a binary ONE over the line
digitalWrite(PIN, HIGH); // Pull 3.5mm TIP low
delayMicroseconds(Length); // for 537us
digitalWrite(PIN, LOW); // Allow 3.5mm TIP to go high
delayMicroseconds(Length * 3); // for 537 * 3 = 1611us
}
void bZERO() { // Send a binary ZERO over the line
digitalWrite(PIN, HIGH); // Pull 3.5mm TIP low
delayMicroseconds(Length); // for 537us
digitalWrite(PIN, LOW); // Allow 3.5mm TIP to go high
delayMicroseconds(Length); // for 537us
}
void Preamble() {
digitalWrite(PIN, LOW); // Not sure what this does
delayMicroseconds(Length * 1);
digitalWrite(PIN, HIGH); // AGC
delayMicroseconds(Length * 16);
digitalWrite(PIN, LOW); // AGC
delayMicroseconds(Length * 8);
bONE(); // 1 Start Bit
bONE(); // (7 bit device code)
bONE();
bONE(); // 7
bZERO();
bZERO();
bZERO(); //4
bONE();
}
void Postamble() {
bONE();
bONE(); // 2 stop bits
}
/*
Test platform to determine what IR codes are getting a respons.
Simply transmits hex codes from 00 to FF in a 10 second cycle, the idea is to see if the radio respondes to the codes displayed in the log, its a hack of the real
transmitter code so there is plenty of redundant code in here
Thanks are due to:
The multi button class: Original code by Jeff Saltzman // http://jmsarduino***************/2009/10/4-way-button-click-double-click-hold.html
The JVC codes and testing interface by Dan Guerra ([email protected])
The rest (not much) by Rob Lloyd ([email protected]) March 5 2013
*/
int BPVirt = 0; // Virtual event number, used in case selection
int adddouble = 4; // number to be bumped to pin number to identify double click event
int addhold = 8; // number to be bumped to pin number to identify hold event
int VolUB = 4; // Input pin 4 corresponds to volume up switch
int VolDB = 5; // Input pin 5 corresponds to volume down switch
int WaveB = 6; // Input pin 6 corresponds to wave switch
int TuneB = 7; // Input pin 7 corresponds to Tune switch
int ConOut = 0; // by default no output to console
int PINO = 8; // Digital IO pin connected to base of transistor
int Length = 537; // Length in Microseconds
int IncomingByte = 0; // Initialize Serial Buffer
int RepTime = 11; // Number of times to repeat each transmission
int Reps = 4; // Number of times to repeat each transmission
int b = 0; // detected event number i.e. what button action is detected
int buttonPin= 0; // the input pin, coresponds to one of 4 real pins (4 to 7)
int i = 1;
int j2 = 1;
int DebugOn = 0;
// Button timing variables
int debounce = 20; // ms debounce period to prevent flickering when pressing or releasing the button, default 20
int DCgap = 250; // max ms between clicks for a double click event, default 250
int holdTime = 1000; // ms hold period: how long to wait for press+hold event
int longHoldTime = 3000; // ms long hold period: how long to wait for press+hold event
int event = 0; // event number
unsigned int number = 0x00;
char temp[2];
// Initialisation
void setup() {
pinMode(PINO, OUTPUT);
digitalWrite(PINO, LOW); // Make PIN low to shut off transistor
Serial.begin(9600);
Serial.println("Enter 1 to Go");
}
// Process loop, dont start till console is running
void loop() {
if (Serial.available() > 0) {
while (number <= 0x7f)
{
temp[0] = (char) (number/16);
temp[1] = (char) (number%16);
Serial.println(" ");
Serial.print("Sending Hex ");
Serial.print(temp[0],HEX);
Serial.print(temp[1],HEX);
Serial.print(" for 10 seconds ");
// timer loop do 10 loops once a second
j2= 1;
i = 1;
while (j2 < RepTime)
{
i = 1;
while (i < Reps)
{
// IR repaeater 3 times
Preamble();
switch (temp[1]) {
case 0:
JVCA0();
break;
case 1:
JVCA1();
break;
case 2:
JVCA2();
break;
case 3:
JVCA3();
break;
case 4:
JVCA4();
break;
case 5:
JVCA5();
break;
case 6:
JVCA6();
break;
case 7:
JVCA7();
break;
case 8:
JVCA8();
break;
case 9:
JVCA9();
break;
case 10:
JVCAA();
break;
case 11:
JVCAB();
break;
case 12:
JVCAC();
break;
case 13:
JVCAD();
break;
case 14:
JVCAE();
break;
case 15:
JVCAF();
break;
default:;
}
switch (temp[0]) {
case 0:
JVCB0();
break;
case 1:
JVCB1();
break;
case 2:
JVCB2();
break;
case 3:
JVCB3();
break;
case 4:
JVCB4();
break;
case 5:
JVCB5();
break;
case 6:
JVCB6();
break;
case 7:
JVCB7();
break;
default:;
}
Postamble();
i++;
} // end of IR repeats
delay(1000);
j2++;
} // end of timer loop
number++;
} // end of hex count
} // end of console loop
} // end of setup
void JVCA0() { // Send 0x01
bZERO();
bZERO();
bZERO(); // 1
bZERO();
}
void JVCA1() { // Send 0x01
bONE();
bZERO();
bZERO(); // 1
bZERO();
}
void JVCA2() { // Send 0x02
bZERO();
bONE();
bZERO();
bZERO();
}
void JVCA3() { // Send 0x03
bONE();
bONE();
bZERO();
bZERO();
}
void JVCA4() { // Send 0x04
bZERO();
bZERO();
bONE();
bZERO();
}
void JVCA5() { // Send 0x05
bONE();
bZERO();
bONE();
bZERO();
}
void JVCA6() { // Send 0x06
bZERO();
bONE();
bONE();
bZERO();
}
void JVCA7() { // Send 0x07
bONE();
bONE();
bONE();
bZERO();
}
void JVCA8() { // Send 0x08
bZERO();
bZERO();
bZERO();
bONE();
}
void JVCA9() { // Send 0x09
bONE();
bZERO();
bZERO(); // 1
bONE();
}
void JVCAA() { // Send 0x10
bZERO();
bONE();
bZERO();
bONE();
}
void JVCAB() { // Send 0x11
bONE();
bONE();
bZERO();
bONE();
}
void JVCAC() { // Send 0x12
bZERO();
bZERO();
bONE();
bONE();
}
void JVCAD() { // Send 0x13
bONE();
bZERO();
bONE();
bONE();
}
void JVCAE() { // Send 0x13
bZERO();
bONE();
bONE();
bONE();
}
void JVCAF() { // Send 0x15
bONE();
bONE();
bONE();
bONE();
}
void JVCB0() { // Send 0x01
bZERO();
bZERO();
bZERO();
}
void JVCB1() { // Send 0x01
bONE();
bZERO();
bZERO();
}
void JVCB2() { // Send 0x02
bZERO();
bONE();
bZERO();
}
void JVCB3() { // Send 0x03
bONE();
bONE();
bZERO();
}
void JVCB4() { // Send 0x04
bZERO();
bZERO();
bONE();
}
void JVCB5() { // Send 0x05
bONE();
bZERO();
bONE();
}
void JVCB6() { // Send 0x06
bZERO();
bONE();
bONE();
}
void JVCB7() { // Send 0x07
bONE();
bONE();
bONE();
}
// Wire signals to be generated for a '1' bit
void bONE() { // Send a binary ONE over the line
if (DebugOn = 1) {
Serial.print(" 1 ");
}
digitalWrite(PINO, HIGH); // Pull 3.5mm TIP low
delayMicroseconds(Length); // for 537us
digitalWrite(PINO, LOW); // Allow 3.5mm TIP to go high
delayMicroseconds(Length * 3); // for 537 * 3 = 1611us
}
// Wire signals to be generated for a '0' bit
void bZERO() { // Send a binary ZERO over the line
if (DebugOn = 1) {
Serial.print(" 0 ");
}
digitalWrite(PINO, HIGH); // Pull 3.5mm TIP low
delayMicroseconds(Length); // for 537us
digitalWrite(PINO, LOW); // Allow 3.5mm TIP to go high
delayMicroseconds(Length); // for 537us
}
// Wire signals to be generated for a start of signal to a JVC
void Preamble() {
if (DebugOn = 1) {
Serial.println(" ");
Serial.print(" AGC ");
}
digitalWrite(PINO, LOW); // Not sure what this does
delayMicroseconds(Length * 1);
digitalWrite(PINO, HIGH); // AGC
delayMicroseconds(Length * 16);
digitalWrite(PINO, LOW); // AGC
delayMicroseconds(Length * 8);
bONE(); // 1 Start Bit
bONE(); // (7 bit device code)
bONE();
bONE(); // 7
bZERO();
bZERO();
bZERO(); //4
bONE();
}
// Wire signals to be generated for a end of signal
void Postamble() {
if (DebugOn = 1) {
Serial.print(" STOP ");
}
bONE();
bONE(); // 2 stop bits
}
int PINO = 8; // Digital IO pin connected to base of transistor
int Length = 537; // Length in Microseconds
int DebugOn = 0;
#define POWERNOFF 0x00
#define VOLUP 0x04
#define VOLDOWN 0x05
#define MUTE 0x06
#define SOURCE 0x08
#define EQUALIZER 0x0d///0x0C
#define MUTE2 0x0e//0x0D// - Mute/Unmute (and Power OFF with "press and hold" - see below)
#define SEARCHFORW 0x12// - Seach + / Track + (and Manual Tune + / Fast fwd with "press and hold")
#define SEARCHBACK 0x13// - Seach - / Track - (and Manual Tune - / Fast rwd with "press and hold")
#define BANDFORW 0x14// - Band cycle / Folder + //programs
#define BANDBACK 0x15// - Band cycle / Folder + //programs
#define PROGR 0x15// - Program 1-6 cycle / Folder -//programs
//#define UNKNOWN 0x16// - Sel cycle (it cycles between Fader/Balance/Loudness/Subwoofer out level/Volume gain for the current source)
#define GREENPIN 5
#define BLUEPIN 3
#define YELLOWPIN 6
#define BROWNPIN 7
#define REDPIN 4
#define BLACKPIN 2
#define OUT_PINS 3
unsigned char out_pins[OUT_PINS]={
GREENPIN,BLUEPIN,YELLOWPIN};
void setup() {
pinMode(PINO, OUTPUT);
digitalWrite(PINO, LOW); // Make PIN low to shut off transistor
Serial.begin(115200);
Serial.println("Enter 1 to Go");
pinMode(GREENPIN, OUTPUT);
pinMode(BLUEPIN, OUTPUT);
pinMode(YELLOWPIN, OUTPUT);
pinMode(BROWNPIN, INPUT_PULLUP);
pinMode(REDPIN, INPUT_PULLUP);
pinMode(BLACKPIN, INPUT_PULLUP);
}
unsigned char GetJoystic(void){
static unsigned char stage = 0;
static unsigned char scroll_stored;
unsigned char tmp,i;
if (++stage > (OUT_PINS-1)) stage=0;
for (i=0;i<(OUT_PINS);i++)
if (i==stage){
digitalWrite(out_pins[i], LOW);
}
else{
digitalWrite(out_pins[i], HIGH);
}
delay(10);
tmp = digitalRead(BROWNPIN);
if (!tmp){
if (stage != scroll_stored){
char scrl = stage-scroll_stored;
scroll_stored = stage;
if ((scrl == 1) ||(scrl==-2)) {
Serial.println("Scroll-");
return SEARCHFORW;
}else{
Serial.println("Scroll+");
return SEARCHBACK;
}
}
}
tmp = digitalRead(REDPIN);
if (!tmp){
switch(stage){
case 0:
Serial.println("Select");
return SOURCE;
case 1:
Serial.println("Vol+");
return VOLUP;
case 2:
Serial.println("Vol-");
return VOLDOWN;
}
}
tmp = digitalRead(BLACKPIN);
if (!tmp){
switch(stage){
case 0:
Serial.println("Source-");
return BANDFORW;
case 1:
Serial.println("Mute");
return MUTE2;
case 2:
Serial.println("Source+");
return BANDBACK;
}
}
return 0;
}
void loop() {
unsigned char Key = GetJoystic();
static unsigned char code = 0;
if (Key){
Serial.print("Key ");
Serial.println(Key,HEX);
JVCSendCommand(Key);
delay(2);
JVCSendCommand(Key);
delay(20);
}
if (Serial.available() > 0) {
char inp=Serial.read();
Serial.print("Received: ");
Serial.println(inp, DEC);
switch (inp){
case '1':
code--;
break;
case '2':
code++;
break;
case '3':
JVCSendCommand(code);
break;
}
}
} // end of loop
void JVCSendCode(unsigned char code){
unsigned char i,tmp=1;
for (i=0;i<sizeof(code)*8-1;i++){//7bits
if (code & tmp)
bONE();
else
bZERO();
tmp = tmp << 1;
}
}
void JVCSendCommand(unsigned char code){
Preamble();
JVCSendCode((unsigned char)code);
Postamble();
}
// Wire signals to be generated for a '1' bit
void bONE() { // Send a binary ONE over the line
if (DebugOn == 1) {
Serial.print(" 1 ");
}
digitalWrite(PINO, HIGH); // Pull 3.5mm TIP low
delayMicroseconds(Length); // for 537us
digitalWrite(PINO, LOW); // Allow 3.5mm TIP to go high
delayMicroseconds(Length * 3); // for 537 * 3 = 1611us
}
// Wire signals to be generated for a '0' bit
void bZERO() { // Send a binary ZERO over the line
if (DebugOn == 1) {
Serial.print(" 0 ");
}
digitalWrite(PINO, HIGH); // Pull 3.5mm TIP low
delayMicroseconds(Length); // for 537us
digitalWrite(PINO, LOW); // Allow 3.5mm TIP to go high
delayMicroseconds(Length); // for 537us
}
// Wire signals to be generated for a start of signal to a JVC
void Preamble() {
if (DebugOn == 1) {
Serial.println(" ");
Serial.print(" AGC ");
}
digitalWrite(PINO, LOW); // Not sure what this does
delayMicroseconds(Length * 1);
digitalWrite(PINO, HIGH); // AGC
delayMicroseconds(Length * 16);
digitalWrite(PINO, LOW); // AGC
delayMicroseconds(Length * 8);
bONE(); // 1 Start Bit
JVCSendCode(0x47);
}
// Wire signals to be generated for a end of signal
void Postamble() {
if (DebugOn == 1) {
Serial.print(" STOP ");
}
bONE();
bONE(); // 2 stop bits
}
What I found with a quick Google search is Steering Wheel control aftermarket radio Gen2 NON JBL. After bridging the two climate control wires with a 68 Ohm resistor, they're only using 3 wires to interface the steering wheel controls. Could be a resistor ladder with one common wire and a wire for left- & right-hand controls if you're lucky. At any rate, it looks like a good starting point.Any clue as to what code a Toyota Gen2 Prius uses? This just might be a doable project to familiarize myself with Arduino, even with my severe dislike of programming since building a 80C51 based study project in the late 90's...
Another variant of the program.
Works with steering wheel remote control of Renault clio like this
and jvc audio KD-x125
Code:
Code:int PINO = 8; // Digital IO pin connected to base of transistor int Length = 537; // Length in Microseconds int DebugOn = 0; #define POWERNOFF 0x00 #define VOLUP 0x04 #define VOLDOWN 0x05 #define MUTE 0x06 #define SOURCE 0x08 #define EQUALIZER 0x0d///0x0C #define MUTE2 0x0e//0x0D// - Mute/Unmute (and Power OFF with "press and hold" - see below) #define SEARCHFORW 0x12// - Seach + / Track + (and Manual Tune + / Fast fwd with "press and hold") #define SEARCHBACK 0x13// - Seach - / Track - (and Manual Tune - / Fast rwd with "press and hold") #define BANDFORW 0x14// - Band cycle / Folder + //programs #define BANDBACK 0x15// - Band cycle / Folder + //programs #define PROGR 0x15// - Program 1-6 cycle / Folder -//programs //#define UNKNOWN 0x16// - Sel cycle (it cycles between Fader/Balance/Loudness/Subwoofer out level/Volume gain for the current source) #define GREENPIN 5 #define BLUEPIN 3 #define YELLOWPIN 6 #define BROWNPIN 7 #define REDPIN 4 #define BLACKPIN 2 #define OUT_PINS 3 unsigned char out_pins[OUT_PINS]={ GREENPIN,BLUEPIN,YELLOWPIN}; void setup() { pinMode(PINO, OUTPUT); digitalWrite(PINO, LOW); // Make PIN low to shut off transistor Serial.begin(115200); Serial.println("Enter 1 to Go"); pinMode(GREENPIN, OUTPUT); pinMode(BLUEPIN, OUTPUT); pinMode(YELLOWPIN, OUTPUT); pinMode(BROWNPIN, INPUT_PULLUP); pinMode(REDPIN, INPUT_PULLUP); pinMode(BLACKPIN, INPUT_PULLUP); } unsigned char GetJoystic(void){ static unsigned char stage = 0; static unsigned char scroll_stored; unsigned char tmp,i; if (++stage > (OUT_PINS-1)) stage=0; for (i=0;i<(OUT_PINS);i++) if (i==stage){ digitalWrite(out_pins[i], LOW); } else{ digitalWrite(out_pins[i], HIGH); } delay(10); tmp = digitalRead(BROWNPIN); if (!tmp){ if (stage != scroll_stored){ char scrl = stage-scroll_stored; scroll_stored = stage; if ((scrl == 1) ||(scrl==-2)) { Serial.println("Scroll-"); return SEARCHFORW; }else{ Serial.println("Scroll+"); return SEARCHBACK; } } } tmp = digitalRead(REDPIN); if (!tmp){ switch(stage){ case 0: Serial.println("Select"); return SOURCE; case 1: Serial.println("Vol+"); return VOLUP; case 2: Serial.println("Vol-"); return VOLDOWN; } } tmp = digitalRead(BLACKPIN); if (!tmp){ switch(stage){ case 0: Serial.println("Source-"); return BANDFORW; case 1: Serial.println("Mute"); return MUTE2; case 2: Serial.println("Source+"); return BANDBACK; } } return 0; } void loop() { unsigned char Key = GetJoystic(); static unsigned char code = 0; if (Key){ Serial.print("Key "); Serial.println(Key,HEX); JVCSendCommand(Key); delay(2); JVCSendCommand(Key); delay(20); } if (Serial.available() > 0) { char inp=Serial.read(); Serial.print("Received: "); Serial.println(inp, DEC); switch (inp){ case '1': code--; break; case '2': code++; break; case '3': JVCSendCommand(code); break; } } } // end of loop void JVCSendCode(unsigned char code){ unsigned char i,tmp=1; for (i=0;i<sizeof(code)*8-1;i++){//7bits if (code & tmp) bONE(); else bZERO(); tmp = tmp << 1; } } void JVCSendCommand(unsigned char code){ Preamble(); JVCSendCode((unsigned char)code); Postamble(); } // Wire signals to be generated for a '1' bit void bONE() { // Send a binary ONE over the line if (DebugOn == 1) { Serial.print(" 1 "); } digitalWrite(PINO, HIGH); // Pull 3.5mm TIP low delayMicroseconds(Length); // for 537us digitalWrite(PINO, LOW); // Allow 3.5mm TIP to go high delayMicroseconds(Length * 3); // for 537 * 3 = 1611us } // Wire signals to be generated for a '0' bit void bZERO() { // Send a binary ZERO over the line if (DebugOn == 1) { Serial.print(" 0 "); } digitalWrite(PINO, HIGH); // Pull 3.5mm TIP low delayMicroseconds(Length); // for 537us digitalWrite(PINO, LOW); // Allow 3.5mm TIP to go high delayMicroseconds(Length); // for 537us } // Wire signals to be generated for a start of signal to a JVC void Preamble() { if (DebugOn == 1) { Serial.println(" "); Serial.print(" AGC "); } digitalWrite(PINO, LOW); // Not sure what this does delayMicroseconds(Length * 1); digitalWrite(PINO, HIGH); // AGC delayMicroseconds(Length * 16); digitalWrite(PINO, LOW); // AGC delayMicroseconds(Length * 8); bONE(); // 1 Start Bit JVCSendCode(0x47); } // Wire signals to be generated for a end of signal void Postamble() { if (DebugOn == 1) { Serial.print(" STOP "); } bONE(); bONE(); // 2 stop bits }
P.S. This JVC has not 3.5mm jack input - only wire with label "STEERING WHEEL REMOTE".
Hi there!
I've taken the code posted above and put in a lot of comments. Fixed a few bugs as well, most notably:
- I changed the pulse width from 537 us to 527 us. This is the same pulse width used by JVC IR remotes. The 537 us did work, but caused my radio's display to flicker.
- On startup, the previous code immediately sent the command associated with the scrollwheel changing position. This is because on startup there is no known last position for the scrollwheel, so its current position is interpreted as a change. I fixed this, so you can power up the chip together with the radio.
- Since I'm using an Arduino Nano with an on-board LED, I added some code that will output the data being sent to this LED as well for diagnostic purposes.
- Removed a seemingly unnecessary 10 ms delay from the code.
- Restructured the sending of commands: HEADER, START BIT, 3 x (ADDRESS, VALUE, 2 STOP BITS). When command are sent only once, the radio may not always pick up on them. This way the radio never misses a command, but also never unintentionally interprets a single button press as multiples of the same command.
The hardware I used:
- Arduino Nano (I used a cheap clone from China)
- DC-DC power supply for the Nano (I got this one)
- A 1k resistor
- An optocoupler (I used the 4N25)
- A fuse (I used 250mA because I had that lying around, you could use a smaller value as well)
- A prototyping PCB to connect everything up nice and tidy
- A small enclosure, some wires, heatshrink, etc.
A video of my contraption in action:
And a link to the code I wrote: [C] Renault Twingo / Clio steering wheel remote via Arduino Nano - Pastebin.com
Hi! I have JVC KD-X310BT. I use your code,but no result. Sketch with irda works well. I use transistor PN2222A in contrast of optocoupler. what could be the problem? Can you help me?Another variant of the program.
Works with steering wheel remote control of Renault clio like this
and jvc audio KD-x125
Code:
Code:int PINO = 8; // Digital IO pin connected to base of transistor int Length = 537; // Length in Microseconds int DebugOn = 0; #define POWERNOFF 0x00 #define VOLUP 0x04 #define VOLDOWN 0x05 #define MUTE 0x06 #define SOURCE 0x08 #define EQUALIZER 0x0d///0x0C #define MUTE2 0x0e//0x0D// - Mute/Unmute (and Power OFF with "press and hold" - see below) #define SEARCHFORW 0x12// - Seach + / Track + (and Manual Tune + / Fast fwd with "press and hold") #define SEARCHBACK 0x13// - Seach - / Track - (and Manual Tune - / Fast rwd with "press and hold") #define BANDFORW 0x14// - Band cycle / Folder + //programs #define BANDBACK 0x15// - Band cycle / Folder + //programs #define PROGR 0x15// - Program 1-6 cycle / Folder -//programs //#define UNKNOWN 0x16// - Sel cycle (it cycles between Fader/Balance/Loudness/Subwoofer out level/Volume gain for the current source) #define GREENPIN 5 #define BLUEPIN 3 #define YELLOWPIN 6 #define BROWNPIN 7 #define REDPIN 4 #define BLACKPIN 2 #define OUT_PINS 3 unsigned char out_pins[OUT_PINS]={ GREENPIN,BLUEPIN,YELLOWPIN}; void setup() { pinMode(PINO, OUTPUT); digitalWrite(PINO, LOW); // Make PIN low to shut off transistor Serial.begin(115200); Serial.println("Enter 1 to Go"); pinMode(GREENPIN, OUTPUT); pinMode(BLUEPIN, OUTPUT); pinMode(YELLOWPIN, OUTPUT); pinMode(BROWNPIN, INPUT_PULLUP); pinMode(REDPIN, INPUT_PULLUP); pinMode(BLACKPIN, INPUT_PULLUP); } unsigned char GetJoystic(void){ static unsigned char stage = 0; static unsigned char scroll_stored; unsigned char tmp,i; if (++stage > (OUT_PINS-1)) stage=0; for (i=0;i<(OUT_PINS);i++) if (i==stage){ digitalWrite(out_pins[i], LOW); } else{ digitalWrite(out_pins[i], HIGH); } delay(10); tmp = digitalRead(BROWNPIN); if (!tmp){ if (stage != scroll_stored){ char scrl = stage-scroll_stored; scroll_stored = stage; if ((scrl == 1) ||(scrl==-2)) { Serial.println("Scroll-"); return SEARCHFORW; }else{ Serial.println("Scroll+"); return SEARCHBACK; } } } tmp = digitalRead(REDPIN); if (!tmp){ switch(stage){ case 0: Serial.println("Select"); return SOURCE; case 1: Serial.println("Vol+"); return VOLUP; case 2: Serial.println("Vol-"); return VOLDOWN; } } tmp = digitalRead(BLACKPIN); if (!tmp){ switch(stage){ case 0: Serial.println("Source-"); return BANDFORW; case 1: Serial.println("Mute"); return MUTE2; case 2: Serial.println("Source+"); return BANDBACK; } } return 0; } void loop() { unsigned char Key = GetJoystic(); static unsigned char code = 0; if (Key){ Serial.print("Key "); Serial.println(Key,HEX); JVCSendCommand(Key); delay(2); JVCSendCommand(Key); delay(20); } if (Serial.available() > 0) { char inp=Serial.read(); Serial.print("Received: "); Serial.println(inp, DEC); switch (inp){ case '1': code--; break; case '2': code++; break; case '3': JVCSendCommand(code); break; } } } // end of loop void JVCSendCode(unsigned char code){ unsigned char i,tmp=1; for (i=0;i<sizeof(code)*8-1;i++){//7bits if (code & tmp) bONE(); else bZERO(); tmp = tmp << 1; } } void JVCSendCommand(unsigned char code){ Preamble(); JVCSendCode((unsigned char)code); Postamble(); } // Wire signals to be generated for a '1' bit void bONE() { // Send a binary ONE over the line if (DebugOn == 1) { Serial.print(" 1 "); } digitalWrite(PINO, HIGH); // Pull 3.5mm TIP low delayMicroseconds(Length); // for 537us digitalWrite(PINO, LOW); // Allow 3.5mm TIP to go high delayMicroseconds(Length * 3); // for 537 * 3 = 1611us } // Wire signals to be generated for a '0' bit void bZERO() { // Send a binary ZERO over the line if (DebugOn == 1) { Serial.print(" 0 "); } digitalWrite(PINO, HIGH); // Pull 3.5mm TIP low delayMicroseconds(Length); // for 537us digitalWrite(PINO, LOW); // Allow 3.5mm TIP to go high delayMicroseconds(Length); // for 537us } // Wire signals to be generated for a start of signal to a JVC void Preamble() { if (DebugOn == 1) { Serial.println(" "); Serial.print(" AGC "); } digitalWrite(PINO, LOW); // Not sure what this does delayMicroseconds(Length * 1); digitalWrite(PINO, HIGH); // AGC delayMicroseconds(Length * 16); digitalWrite(PINO, LOW); // AGC delayMicroseconds(Length * 8); bONE(); // 1 Start Bit JVCSendCode(0x47); } // Wire signals to be generated for a end of signal void Postamble() { if (DebugOn == 1) { Serial.print(" STOP "); } bONE(); bONE(); // 2 stop bits }
P.S. This JVC has not 3.5mm jack input - only wire with label "STEERING WHEEL REMOTE".