Connecting Arduino to Android Head Unit (car radio) through USB

I am trying to connect aftermarket sensors on a pre-OBDII vehicle to the Torque App. Torque has a wiki on how to use an Arduino to do this.

https://torque-bhp.com/wiki/Arduino

As shown in the above example, I can connect via bluetooth to an android tablet.

However, I am trying to connect to an adroid in-dash radio, and am having a lot of problems. The head unit manufacturer, Volsmart, says that their radio does not support SPP. The HC-06 I have on the Arduino is communicating over SPP.

I think it would be cleaner, and in some ways more convenient to connect to the head unit via USB instead of the bluetooth show in the wiki. Volsmart says that their USB's are COM ports.

So, my question is, what do I need to change in the code below to communicate with the Torque app on my head unit?

Thanks for your help! (I will a subsequent post).

Here is the code I need to modify:

#include 
#include 
 
/**
 * Torque for Android Arduino sample program by Ian Hawkins  http://torque-bhp.com/
 * You will require Torque Pro 1.8.82 or newer
 * 
 * Setup the bluetooth device as an OBD2 adapter in Torque.  Torque will automatically recognise the Arduino and will
 * import sensors automatically based on the configuration settings below.
 * 
 * This code is released under the LGPL v2 
 * 
 * This has been tested on the Arduino UNO board
 * 
 * Connect pins 2 and 3 to your bluetooth device's rx and tx pins (2 to txd on bluetooth device, 3 to rxd)
 * 
 * This code allows you to gather sensors from the arduino to display in the app. It can be extended to whatever you want.
 */
 
// Various constants.
const String ATE = "ATE"; // Echo off/on
const String ATI = "ATI"; // Version id
const String ATZ = "ATZ"; // Reset
const String ATS = "ATS"; // Set protocol X
const String ATH = "ATH"; // Headers off / on
const String ATL = "ATL"; // Linefeeds off/on
const String ATM = "ATM"; // Memory off/on
const String GETDEFINITIONS = "GETDEFINITIONS"; // Get sensor definitions
const String GETCONFIGURATION = "GETCONFIGURATION"; // Get config of app (hide car sensors, devices sensors, etc)
const String GETSENSORS = "G"; // Get sensor values, one shot.
const String SETSENSOR = "S"; // Set a sensor value
const String PROMPT = ">";
const String CANBUS = "6"; // canbus 500k 11 bit protocol id for elm.
const String ATDPN = "ATDPN";
const String ATDESC = "AT@1";
const String ATAT = "ATAT";
const String LF = "\n";
const String VERSION = "Torque Protocol Interface v0.0.1"; // Don't change this - it's used by Torque so it knows what interface it is connected to
const String VERSION_DESC = "Torque For Android Protocol Interface";
const String OK = "OK";
const String ANALOG = "a";
const String DIGITAL = "d";
const String IS_INPUT = "i";
const String IS_OUTPUT = "o";
 
String fromTorque = "";
 
/**
 * Array of sensors we will advertise to Torque so it can automatically import them. Using strings
 * Stucture is:
 *  
 *  Arduino Pin, Arduino pin type, Input/Ouput, Default value(if output), ShortName, Long name, units, minimum value, maximum value
 *  
 *  Caveats:  Don't use a '>' in any of the names, 
 *            Update 'sensorsSize' with the number of elements.
 *            Analog outputs are PWM on digital pins.
 *  
 */
const int SENSORSSIZE = 9 * 3; // each line is 9 attributes, and we have 3 lines.
const String sensors[SENSORSSIZE] = {
                    "0", ANALOG, IS_INPUT,   "-",   "Boost", "Boost", "PSI",    "0", "5",
                    "1", ANALOG, IS_INPUT,   "-",   "EGT", "Temp",  "F",    "0", "5",
                    "4", DIGITAL,IS_OUTPUT,  "0",  "Dout1", "Digital Out 1",   "bit", "0", "1"
                   }; 
/**
 * Configuration directives for the app to hide various things. Comma separated. Remove to enable visibility in Torque
 *  - handy if your project isn't car related or you want to make sensor selections relatively easy.
 *  
 *  Supported types:
 *    NO_CAR_SENSORS  - hide any car related sensors
 *    NO_DEVICE_SENSORS - hide any device (phone) sensors
 *    
 */
const String CONFIGURATION = "NO_CAR_SENSORS,NO_DEVICE_SENSORS"; 
 
// Setup bluetooth module on pins 2 and 3 (you can't use these digial pins in the sensor list or it'll break comms)
SoftwareSerial mySerial(2,3); // Most other boards can use pins 2 and 3
//SoftwareSerial mySerial(8,9); // Use pins 8,9 on Arduino Micro
 
 
void setup() {
  // Init the pins 
  initSensors();
  Serial.begin(9600);    // the GPRS baud rate 
  delay(600);
  mySerial.begin(9600);              
 }
 
void loop() {

  /**
   * Grab data from the bluetooth module, parse it.
   */
  if (mySerial.available()) {
     char c = mySerial.read();   
     if ((c == '\n' || c == '\r') && fromTorque.length() > 0) {
        fromTorque.toUpperCase();
        processCommand(fromTorque);
        fromTorque = "";
     } else if (c != ' ' && c != '\n' && c !='\r') {
        // Ignore spaces.
        fromTorque += c; 
     }
  }
}
 
/**
 * Parse the commands sent from Torque
 */
void processCommand(String command) {
 
   // Debug - see what torque is sending on your serial monitor
   Serial.println(command);
 
   // Simple command processing from the app to the arduino..
   if (command.equals(ATZ)) {
       initSensors(); // reset the pins
       mySerial.print(VERSION);
       mySerial.print(LF); 
       mySerial.print(OK);
   } else if (command.startsWith(ATE)) {
       mySerial.print(OK); 
   } else if(command.startsWith(ATI)) {
       mySerial.print(VERSION);
       mySerial.print(LF);
       mySerial.print(OK);
   } else if (command.startsWith(ATDESC)) {
       mySerial.print(VERSION_DESC); 
       mySerial.print(LF);
       mySerial.print(OK);
   } else if (command.startsWith(ATL)) {
       mySerial.print(OK);
   } else if (command.startsWith(ATAT)) {
       mySerial.print(OK);
   } else if (command.startsWith(ATH)) {
       mySerial.print(OK);
   } else if (command.startsWith(ATM)) {
       mySerial.print(OK);
   } else if (command.startsWith(ATS)) {
       // Set protocol
       mySerial.print(OK);
   } else if (command.startsWith(ATDPN)) {
       mySerial.print(CANBUS);
   } else if (command.startsWith(GETDEFINITIONS)) {
       showSensorDefinitions();
   } else if (command.startsWith(GETSENSORS)) {
       getSensorValues();
   } else if (command.startsWith(GETCONFIGURATION)) {
       getConfiguration();
   } else if (command.startsWith(SETSENSOR)) {
       setSensorValue(command);
   }
 
   mySerial.print(LF); 
   mySerial.print(PROMPT);
 
 
}
 
/**
 * List all the sensors to the app
 */
void showSensorDefinitions() {
   int id = 0;
   for (int i = 0; i < SENSORSSIZE/9; i++) {
      for (int j = 0; j < 9; j++) {
         id = (i*9)+j;
         mySerial.print(sensors[id]);
 
         if (id+1 < SENSORSSIZE) {
            mySerial.print(',');
         }
      }
      mySerial.print(LF);
   }
}
 
/**
 * Dump sensor information for input sensors.
 * 
 * Format to Torque is id:type:value
 */
void getSensorValues() {
   for (int i = 0; i < SENSORSSIZE/9; i++) {
      int group = i * 9;
      int id = sensors[group].toInt();
      String type = sensors[group+1];
      boolean isOutput = sensors[group+2].equals(IS_OUTPUT);
 
 
      if (!isOutput) {
         mySerial.print(id);
         mySerial.print(":");
         mySerial.print(type);
         mySerial.print(":");
         if (type.equals(ANALOG)) {
            if (i==0) {
              mySerial.print((((analogRead(id)*5.1/1024)/(5.1)-0.04)/0.009)*0.145);
              }
            else if (i==1) {
              mySerial.print (analogRead(id));
              } 
            }
            else if (type.equals(DIGITAL)) {
            mySerial.print(digitalRead(id));
         }
         mySerial.print('\n');
      }
   }
}
 
/**
 * Sets a sensors value
 */
void setSensorValue(String command) {
  int index = command.indexOf(":");
  int id = command.substring(1,index).toInt();
  int value = command.substring(index+1, command.length()).toInt();
 
  for (int i = 0; i < SENSORSSIZE/9; i++) {
     int group = i * 9;
     int sid = sensors[group].toInt();
     boolean isOutput = sensors[group+2].equals(IS_OUTPUT);
     if (isOutput) {
 
       if (sid == id) {
 
          String type = sensors[group+1];
          if (type.equals(ANALOG)) {
            analogWrite(sid, constrain(value,0,255));
          } else if (type.equals(DIGITAL)) {
            digitalWrite(sid, value > 0 ? HIGH: LOW);
          }
          break;
       }
    }
  }
}
 
/** 
 *  Init the sensor definitions (input/output, default output states, etc)
 */
void initSensors() {
   for (int i = 0; i < SENSORSSIZE/9; i++) {
      int group = i * 9;
      int id = sensors[group].toInt();
      String type = sensors[group+1];
      boolean isOutput = sensors[group+2].equals(IS_OUTPUT);
      int defaultValue = sensors[group+3].toInt();
 
 
      if (isOutput) {
         if (type.equals(ANALOG)) {
             pinMode(id, OUTPUT);
             analogWrite(id, constrain(defaultValue, 0, 255));
         } else if (type.equals(DIGITAL)) {
             pinMode(id, OUTPUT);
             digitalWrite(id, defaultValue > 0 ? HIGH : LOW);
         }
      }
   }
}
 
void getConfiguration() {
  mySerial.print(CONFIGURATION);
}

Here is the code I need to modify:

Which won't even compile. First thing you need to do is make it compile.

Second thing is to get rid of ALL the Strings.

If the device is actually a serial device, and uses TTL levels, all you need to do is connect the RX and TX pins of the device to the SoftwareSerial port's RX and TX pins. No code changes are needed.

If the device is truly a USB device, you'd need a USB Host shield, and you'd need to develop a USB driver. That is not a trivial task.

I have not had an issue with it compiling - it has compiled fine for me, and it communicates and works well with the Torque app on my Android Tablet. Unfortunately, I cannot connect to my android Head Unit. I have pasted from the Torque app wiki.

(For some reason, it looks like the code may have not posted correctly - I notice <SoftwareSerial.h> and <string.h> did not show up at the top of the pasted code).

If I would have to develop a USB driver, etc, than it is probably too complicated for me.

It doesn’t sound this simple, but I’ll ask: Is there code for a USB driver already developed that I could just include in my sketch? Or does it have to be all customized to communicate with the Android Torque App? I think that is what all the strings are for.