Remote 2 device with the same remote

Hello to everyone,

I've recently started with arduino and programming, and i did some project already;
I would like to modify and extend the project i realized:
The project is a steering wheel remote control of my car that converts the button pressed for my JVC headunit (that's already working fine).
i want to add a bluetooth audio board that has 3 switches (play/pause, vol+ / Netx, Vol - / Back); The switches shorts the pin to ground when pressed, and some functions are available with short/long press.
I would like to use one of the buttons (for example MODE button) to switch between headunit or bluetooth board control.

The actual sketch read wich button has ben pressed and start to send the signal to the headunit with a precise pulse width and you will find it below.

// Define commands
#define VOLUP       0x04
#define VOLDOWN     0x05
#define SOURCE      0x08
#define EQUALIZER   0x0D
#define MUTE        0x0E
#define TRACKFORW   0x12
#define TRACKBACK   0x13
#define FOLDERFORW  0x14
#define FOLDERBACK  0x15
#define UNKNOWN1    0x37
#define UNKNOWN2    0x58
 
// Renault Twingo / Clio steering wheel remote wire functions
// pin_cycle_current  1     0              2
//         OUTPUTS    BLUE  GREEN          YELLOW
// INPUTS  PIN#       3     5              6
// BLACK   2          MUTE  TOP RIGHT BTN  TOP LEFT BTN
// RED     4          VOL+  BOTTOM BTN     VOL-
//                    HIGH  HIGH           LOW    SCROLL UP (CCW)
// BROWN   7          HIGH  LOW            HIGH  SCROLLWHEEL
//                    LOW   HIGH           HIGH   SCROLL DN (CW)
// Outputs are set LOW one at a time (the other outputs will be HIGH). Inputs (with internal pull-up) are then evaluated.
//   If an input is being pulled LOW this means a button is being pressed. Taking into account which output is currently LOW
//   we know which button this is. For example, is output pin 3 (Blue wire) is currently LOW and we also read LOW on
//   input pin 2 (Black) we know the MUTE button is being pressed.
// For the scrollwheel we must take into account its last known position in order to determine if there has been a change.
// We can determine the direction based on which pins are being pulled LOW.
 
// Connect Renault Twingo / Clio steering wheel remote wires to these pins
#define BLACKPIN    2 // D2
#define BLUEPIN     3 // D3
#define REDPIN      4 // D4
#define GREENPIN    5 // D5
#define YELLOWPIN   6 // D6
#define BROWNPIN    7 // D7
 
// Connect optocoupler input through a 1k resistor to this pin
#define OUTPUTPIN   8 // D8
 
// On-board LED, useful for debugging
#define LEDPIN     13 // D13
 
// Pulse width in µs
#define PULSEWIDTH 527
 
// Address that the radio responds to
#define ADDRESS 0x47
 
// Set number of output pins and put those pins in an array to cycle through when polling the input pins
#define OUT_PINS 3
unsigned char out_pins[OUT_PINS] = {GREENPIN, BLUEPIN, YELLOWPIN};
 
void setup() {
  pinMode(OUTPUTPIN, OUTPUT);    // Set the proper pin as output
  digitalWrite(OUTPUTPIN, LOW);  // Output LOW to make sure optocoupler is off
 
  // Set the pins connected to the steering wheel remote as input / output
  pinMode(BLACKPIN, INPUT_PULLUP);
  pinMode(BLUEPIN, OUTPUT);
  pinMode(REDPIN, INPUT_PULLUP);
  pinMode(GREENPIN, OUTPUT);
  pinMode(YELLOWPIN, OUTPUT);
  pinMode(BROWNPIN, INPUT_PULLUP);
 
  pinMode(LEDPIN, OUTPUT);                  // Set pin connected to on-board LED as output...
  digitalWrite(LEDPIN, LOW);                // ...and turn LED off
  for (unsigned char i = 0; i <= 7; i++) {  // Flash on-board LED a few times so it's easy to see when the Arduino is ready
    delay(100);
    digitalWrite(LEDPIN, !digitalRead(LEDPIN));
  }
  delay(100);
  digitalWrite(LEDPIN, LOW);                // Make sure LED ends up being off
}
 
// The steering wheel remote has 6 buttons and a scrollwheel, interfaced via 6 wires.
// This function will cycle through the output pins, setting one pin LOW at a time.
// It will then poll the input pins to see which input pins - if any - are pulled LOW.
unsigned char GetInput(void) {
  static unsigned char pin_cycle_current = 0;  // To keep track of which output pin is currently LOW
  static unsigned char pin_cycle_stored;       // To store the last known scrollwheel position
  static boolean first_run = true;             // After booting, there is no known last position for the scrollwheel
                                               // So on the first poll of the scrollwheel just store the current position and don't send a command
  unsigned char i;
 
  if (++pin_cycle_current > (OUT_PINS - 1)) pin_cycle_current = 0;     // Reset pin_cycle_current counter after last pin
 
  for (i = 0; i < OUT_PINS; i++) {                                     // Cycle through the output pins, setting one of them LOW and the rest HIGH
    if (i == pin_cycle_current)
      digitalWrite(out_pins[i], LOW);
    else
      digitalWrite(out_pins[i], HIGH);
  }
 
  if (!digitalRead(BROWNPIN)) {                                        // We're only interested if this pin is being pulled LOW
    if (pin_cycle_current != pin_cycle_stored) {                       // If the output that's currently LOW is different from the one that was LOW the last time
                                                                       //   we came through here, then the scrollwheel has changed position
      signed char scrollwheel_current = pin_cycle_current - pin_cycle_stored; // Result of this calculation can range from -2 to 2
      pin_cycle_stored = pin_cycle_current;                            // Store which output pin is currently LOW
      if (first_run) {                                                 // If this is the first run, don't send a command
        first_run = false;                                             //   (since there was no previously known scrollwheel position)
        return 0;
      }
      if ((scrollwheel_current == 1) || (scrollwheel_current == -2)) { // If above calculation resulted in 1 or -2 the scrollwheel was rotated up (ccw)
        return FOLDERBACK;
      }else {                                                          // If above calculation resulted in anything else the scrollwheel was rotated down (cw)
        return FOLDERFORW;
      }
    }
  }
 
  if (!digitalRead(REDPIN)) {   // We're only interested if this pin is being pulled LOW
    switch(pin_cycle_current) {
    case 0:                     // RED (input) is LOW while GREEN (output) is LOW: bottom button pressed
      return SOURCE;
    case 1:                     // RED (input) is LOW while BLUE (output) is LOW: volume + button pressed
      return VOLUP;
    case 2:                     // RED (input) is LOW while YELLOW (output) is LOW: volume - button pressed
      return VOLDOWN;
    }
  }
 
  if (!digitalRead(BLACKPIN)) { // We're only interested if this pin is being pulled LOW
    switch(pin_cycle_current) {
    case 0:                     // BLACK (input) is LOW while GREEN (output) is LOW: top right button is pressed
      return TRACKFORW;
    case 1:                     // BLACK (input) is LOW while BLUE (output) is LOW: mute button is pressed
      return MUTE;
    case 2:                     // BLACK (input) is LOW while YELLOW (output) is LOW: top left button is pressed
      return TRACKBACK;
    }
  }
 
  return 0;
}
 
void loop() {
  unsigned char Key = GetInput();  // If any buttons are being pressed the GetInput() function will return the appropriate command code
 
  if (Key) {  // If no buttons are being pressed the function will have returned 0 and no command will be sent
    SendCommand(Key);
  }
}
 
// Send a value (7 bits, LSB is sent first, value can be an address or command)
void SendValue(unsigned char value) {
  unsigned char i, tmp = 1;
  for (i = 0; i < sizeof(value) * 8 - 1; i++) {
    if (value & tmp)  // Do a bitwise AND on the value and tmp
      SendOne();
    else
      SendZero();
    tmp = tmp << 1; // Bitshift left by 1
  }
}
 
// Send a command to the radio, including the header, start bit, address and stop bits
void SendCommand(unsigned char value) {
  unsigned char i;
  Preamble();                         // Send signals to precede a command to the radio
  for (i = 0; i < 3; i++) {           // Repeat address, command and stop bits three times so radio will pick them up properly
    SendValue(ADDRESS);               // Send the address
    SendValue((unsigned char)value);  // Send the command
    Postamble();                      // Send signals to follow a command to the radio
  }
}
 
// Signals to transmit a '0' bit
void SendZero() {
  digitalWrite(OUTPUTPIN, HIGH);      // Output HIGH for 1 pulse width
  digitalWrite(LEDPIN, HIGH);         // Turn on on-board LED
  delayMicroseconds(PULSEWIDTH);
  digitalWrite(OUTPUTPIN, LOW);       // Output LOW for 1 pulse width
  digitalWrite(LEDPIN, LOW);          // Turn off on-board LED
  delayMicroseconds(PULSEWIDTH);
}
 
// Signals to transmit a '1' bit
void SendOne() {
  digitalWrite(OUTPUTPIN, HIGH);      // Output HIGH for 1 pulse width
  digitalWrite(LEDPIN, HIGH);         // Turn on on-board LED
  delayMicroseconds(PULSEWIDTH);
  digitalWrite(OUTPUTPIN, LOW);       // Output LOW for 3 pulse widths
  digitalWrite(LEDPIN, LOW);          // Turn off on-board LED
  delayMicroseconds(PULSEWIDTH * 3);
}
 
// Signals to precede a command to the radio
void Preamble() {
  // HEADER: always LOW (1 pulse width), HIGH (16 pulse widths), LOW (8 pulse widths)
  digitalWrite(OUTPUTPIN, LOW);       // Make sure output is LOW for 1 pulse width, so the header starts with a rising edge
  digitalWrite(LEDPIN, LOW);          // Turn off on-board LED
  delayMicroseconds(PULSEWIDTH * 1);
  digitalWrite(OUTPUTPIN, HIGH);      // Start of header, output HIGH for 16 pulse widths
  digitalWrite(LEDPIN, HIGH);         // Turn on on-board LED
  delayMicroseconds(PULSEWIDTH * 16);
  digitalWrite(OUTPUTPIN, LOW);       // Second part of header, output LOW 8 pulse widths
  digitalWrite(LEDPIN, LOW);          // Turn off on-board LED
  delayMicroseconds(PULSEWIDTH * 8);
  
  // START BIT: always 1
  SendOne();
}
 
// Signals to follow a command to the radio
void Postamble() {
  // STOP BITS: always 1
  SendOne();
  SendOne();
}

Can somebody have some advice about it?
Thanks :slight_smile:

I don't understand your question. Are you trying to read the buttons of your audio board? It looks like the code is already doing that?

A schematic would be helpful, even a hand drawn one

Hello!

Sorry if my explanations wasn't clear, i'll try to explain better :slight_smile:
My arduino is actually doing what's in the code: Reads the buttons of the steering wheel, and deliver the command to the headunit.
I want to use one of the existent button to control also the audio board (example: when the arduino boots, you control the headunit, if you press MODE button, the buttons now will command the audio board, if you press again MODE, it will control again the headunit).

this is the schematic of the actual project, i'll add the audio board ASAP.

and here the video of the project (as is right now).

my questions are: there is a way to use a button to switch between 2 scripts? how can i do it?

Thanks

You could change which function is called when pressing a button but you will need to write the functions such that reading the button input is not blocked

now I see that is absolutely doable.
how is audio board connected and should be controlled?
and show MODE button on schema

the audio board would be connected as below

the digital pins would be pull low the button desired when pressed, both devices would be connected to the same power supply (that has 2 usb).

the "MODE BUTTON" on the sketch is named SOURCE, and is obtained by "shorting" the red and green pins.

i don't know if something is wrong, but open to suggestions :slight_smile: Thanks

they are not interfering each other. what is the problem then?

I look on sketch code and see input and output pins are interleaved. Why do you not made them separated?
e.g. 2,3,4 for input and 8,9,10,11,12,13, output,
or A0,A1,A2 input and 2,3,4,5,6,7,8,9,10... output

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.