Micro bit relay

Good day. Just want to know if it is possible to use a Microbit, low voltage solid state relay with Arduino NANO. I am going to use it to drive the "shift" function on my Sony car radio SWC. The NANO is working 100% with the SWC, but the BS170 transistor used as a switch to ground the sleeve of the mini jack to activate the shift function keeps on malfunction. So I though this relay could work using a nano pin to switch it. Any comments or other idees would be appreciated.

Do you have a link to this relay - people here may not be familiar with it . Also a hand drawn circuit diagram of what you propose would be good

They make very inexpensive relays for the Arduino, which will work just fine with the Nano. They generally have driver of some type built in so the Nano only has to supply only a few mills. They come in units from 1 to 16 in multiples of 2 relays. The relays are rated at 10 amps so should do a nice job for you. There are several brands and a wide range pf prices.

Good day. I apologize in advance if I offend anyone with my drawing or post. I am a newbie to Arduino and with the help of my son I compiled this code.

The code has been tested and is working fine so the problem must be on the hardware/circuit side. The circuit works 100% with out the shift function , so I need help in solving my problem.

I am using the SWC of the citroen. It has 8 wire that I input to the Arduino Nano, with internal pull up that reads each push of the button. the information is then send to the MCP4131 digipot as resitor values activating the radio remote input of the SONY XAV 601BT. The tip and sleeve of the mini jack is used. Sofar this part of the circuit and code is working like a dream, and that includes the encoder we use with polling.

The problem is to use the encoder we need to activate the "shift" function, where we ground the ring input of the radio (3.3Volt) to the sleeve of the mini jack. We are doing this by activating PIN 9 on the NANO to activate the transistor to close the circuit from the ring to the sleeve. I have tried a 2N2222 and BS170 to no avail. It doesn't work and it is as if its shorting to the tip input or are permanently activate. The SEEK function becomes the VOL function and the VOL function switches the radio off. I used from a 1 kOhm to a 2.2kOhm resistor in series from the PIN to the BASE of the transistor and a 10 to 12 kOhm to pull the BASE to GROUND. I have even remove the 10 - 12 kOhm from the circuit but still the same.

I was think as an alternative to use a small relay to activate the shift function, but its puzzling why the transistors isn't working. I have even gone so far as to swap the SOURCE and DRAIN of the transistor, but the same problem remains. I have tested the circuit without the transistors and is 100%.

Hany help would be appreciated.

Here is a raw copy of the code. All the libraries are included.

"
#include <PinButton.h>
#include <arduino-timer.h>
#include <SPI.h>

#include "Rotary.h"

// Set the Citroën SWC input buttons to pin numbers
// MultiButton automatically initializes the inputs with the internal pullup
PinButton SOURCE(2);
PinButton SEEK_UP(3);
PinButton SEEK_DN(5);
PinButton VOL_UP(7);
PinButton VOL_DN(4);

uint8_t ENCODER_WHEEL_A_PIN = 6;
uint8_t ENCODER_WHEEL_B_PIN = 8;

Rotary rotary = Rotary(ENCODER_WHEEL_A_PIN, ENCODER_WHEEL_B_PIN);

const int BUTTON_HOLD_TIME_MS = 500;

// Resistive values for the digital potentiometer output
const float SOURCE_OUTPUT_KOHM = 2.1;
const float SEEK_UP_OUTPUT_KOHM = 8.8;
const float SEEK_DN_OUTPUT_KOHM = 12.1;
const float VOL_UP_OUTPUT_KOHM =16.6;
const float VOL_DN_OUTPUT_KOHM = 23.6;
const float PRESET_DN_OUTPUT_KOHM = 12.9;
const float PRESET_UP_OUTPUT_KOHM = 8.1;

enum MCP413X_REGISTERS {
MCP413X_REG_WIPER = 0x00,
MCP413X_REG_TCON = 0x04
};

enum MCP413X_TCON_BITS {
MCP413X_TCON_TERM_B = 0x01,
MCP413X_TCON_TERM_W = 0x02,
MCP413X_TCON_TERM_A = 0x04,
MCP413X_TCON_HARDWARE_CTRL = 0x08
};

enum MCP413X_COMMAND_TYPES {
MCP413X_COMMAND_WRITE = 0x0,
MCP413X_COMMAND_READ = 0x3,
};

// Shift connection
const uint8_t SHIFT = 9;

// Digipot ChipSelect Pin
const uint8_t MCP413X_CS_PIN = 10;

// Encoder wheel state variables
uint8_t encoder_state = 0xFF;

void setDigipotWiperState(bool setWiperConnected) {

// Digipot ChipSelect enable
digitalWrite(MCP413X_CS_PIN, LOW);

uint16_t tcon_command = (MCP413X_REG_TCON << 12);
tcon_command |= (MCP413X_COMMAND_WRITE << 10);
tcon_command |= 0x100; // Weird TCON reserve bit should always be 1
tcon_command |= MCP413X_TCON_HARDWARE_CTRL; // Hardware enabled

if(setWiperConnected){
tcon_command |= MCP413X_TCON_TERM_W; // Enable Terminal W
tcon_command |= MCP413X_TCON_TERM_A; // Enable Terminal A
tcon_command |= MCP413X_TCON_TERM_B; // Enable Terminal B
}
Serial.print(F("TCOP SPI: "));
Serial.println(tcon_command, HEX);
SPI.transfer16(tcon_command);

digitalWrite(MCP413X_CS_PIN, HIGH);
}

void setDigipotWiperValue(float resistance_kohm) {
float wiper_base_kohm = 0.100; // Base wiper resistance (this needs tuning based on the input voltage)
float digipot_resistor_range = 50.0; // The full range of the resistor network excluding wiper resistance (from terminal A to terminal B).
float step_count = 128; // 128 for 7 bit digipots

float step_value = digipot_resistor_range / step_count;

if (resistance_kohm > digipot_resistor_range) {
// We can't set the resistance over 50kOhm, so clamp it to the max
resistance_kohm = digipot_resistor_range;
} else if (resistance_kohm < 0)
{
// There is no such thing as negative resistance. Do nothing and return.
return;
}
// resistance_kohm -= wiper_base_kohm; // subtract the wiper resistance from the desired value

uint8_t wiper_value = (uint8_t) round(resistance_kohm / step_value);

// Digipot ChipSelect enable
digitalWrite(MCP413X_CS_PIN, LOW);

uint16_t wiper_command = (MCP413X_REG_WIPER << 12);
wiper_command |= (MCP413X_COMMAND_WRITE << 10);
wiper_command |= wiper_value;

Serial.print(F("WIPER SPI: "));
Serial.println(wiper_command, HEX);
SPI.transfer16(wiper_command);

digitalWrite(MCP413X_CS_PIN, HIGH);
}

void setup() {
delay(50); // some microcontrollers reboot twice
Serial.begin(9600);
while (!Serial); // Wait until Serial is ready
Serial.println(F("setup(): begin"));

// Set ChipSelect pin output
pinMode(MCP413X_CS_PIN, OUTPUT);
//Set digital pin as output pin for ring to sleeve connection to be used as shift function
pinMode(SHIFT, OUTPUT);
digitalWrite(SHIFT, LOW); // Make sure the output is low on startup

SPI.begin();

setDigipotWiperState(false); // Initialize the digipot, but disconnect the wiper (open circuit)
}

/***** Timer stuff for "holding" the resistance till the radio has responded *****/
auto timer = timer_create_default(); // create a timer with default settings
uintptr_t button_disconnect_task = NULL;

bool timedWiperDisconnect(void *){
// Clear the state, once this task runs it shouldn't run again
button_disconnect_task = NULL;

// Clear the shift line
digitalWrite(SHIFT, LOW);
// Disconnect the digipot wiper
setDigipotWiperState(false);

}

// Push the "button" by applying the resistance value to the digipot output and then connecting the terminals for a set amount of time using the timer
void pushTheButton(float resistance_kohm, bool connectShift){
// Interrupt the existing timer if it exists and disconnect the digipot and shift
if(button_disconnect_task != NULL){
timer.cancel(button_disconnect_task);
timedWiperDisconnect(0);
}
Serial.print("Attempting to set resistance to ");
Serial.print(resistance_kohm);
Serial.println("kOhm");

// Check if we need to connect the SHIFT line
if(connectShift){
  digitalWrite(SHIFT, HIGH);      
  Serial.println("SHIFT enabled");
} else {      
  digitalWrite(SHIFT, LOW);
  Serial.println("SHIFT disabled");
}

// Set the resistance wiper register 
setDigipotWiperValue(resistance_kohm);    
delay(5);
// Enable the wiper connection
setDigipotWiperState(true);

// Schedule the disconnect in BUTTON_HOLD_TIME_MS milliseconds
button_disconnect_task = timer.in(BUTTON_HOLD_TIME_MS, timedWiperDisconnect);

}

void loop() {
// Update the button states (read the inputs)
SOURCE.update();
SEEK_UP.update();
SEEK_DN.update();
VOL_UP.update();
VOL_DN.update();

// Check clicked states with cascade.
// If more than one button is clicked, only the first one on this list should activate
if (SOURCE.isClick())
{
pushTheButton(SOURCE_OUTPUT_KOHM, false);
Serial.println(F("Click SOURCE"));
}
else if (SEEK_UP.isClick())
{
pushTheButton(SEEK_UP_OUTPUT_KOHM, false);
Serial.println(F("Click SEEK_UP"));
}
else if (SEEK_DN.isClick())
{
pushTheButton(SEEK_DN_OUTPUT_KOHM, false);
Serial.println(F("Click SEEK_DN"));
}
else if (VOL_DN.isClick())
{
pushTheButton(VOL_DN_OUTPUT_KOHM, false);
Serial.println(F("Click VOL_DN"));
}
else if (VOL_UP.isClick())
{
pushTheButton(VOL_UP_OUTPUT_KOHM, false);
Serial.println(F("Click VOL_UP"));
}

unsigned char result = rotary.process();
if (result == DIR_CW)
{
pushTheButton(PRESET_DN_OUTPUT_KOHM, true);
Serial.println(F("Rolled PRESET_DN"));
}
else if (result == DIR_CCW)
{
pushTheButton(PRESET_UP_OUTPUT_KOHM, true);
Serial.println(F("Rolled PRESET_UP"));
}

timer.tick();
}

Is the sleeve supposed to connect to GND? I don't see that connection anywhere. If it's missing, I can see how that theoretically could blow up a BS170.

Are you sure the ring, when shorted to the sleeve, will have a current limit that is below what the BS170 can handle? What do the specifications of the Sony radio say about this?

Keep in mind the automotive environment is fairly hostile for electronics and you generally need to think about protection of components in various ways. Your circuit doesn't seem to have any kind of protection anywhere.

Hi and thanks for the reply. The SLEEVE connects to the ground of the Radio as the radio works on a resistance ladder setup. so the Tip is 3.3 volts and the sleeve is ground. The ring is also 3.3 volt as must be grounded to the sleeve to acjieve the "shift" function. The radio wired remote is "tip = 3.3 volt", the "ring = 3.3 volts" and the are all at 0.5mill amps. the 5volt input is a stable power supply

Did you measure this?

Yes the reading I got was. the highest was 1mA. So sorry we should work on 1mA. Do you think that an optocoupler PC 817C would work better, than a transistor. Was thinking may be use a relay, like the one from Monkmakes.

for the shift function.

Not really; as long as we don't know what fries your transistor in that spot, it might as well fry an optocoupler. Throwing a relay at it might help, but it's still patching up an unknown defect and then hoping for the best. I wouldn't like that in a car (starting a fire behind your dashboard isn't fun!)

Hi I think the problem is that the ground of the radio (sleeve) and ground of the Arduino Nano is not on the same circuit, as the radio's ground is seperate from the Arduino, therfor the transistor is grounded to the circuit. I will have to keep the grounds seperate and was think on either using an optocoupler or a SSR on the circuit

I considered that, but if this is a car, then you generally have a pretty reliable common ground all over the place. It's kind of hard to have any kind of circuit floating in a car, in practice. But yes, do make sure that the Arduino has a common ground with the Sony radio.

Hi all. Here is a update on the problem, we have had with the BS-170. I discovered that the ground of the wired remote input of the radio was on a separate circuit and not part of the normal grounding circuit. That meant that the BS-170 was floating, causing it to malfunction. I replaced the BS-170 with a TLP221AF photorelay, and at this stage the circuit is working 100%. Thanks all for the input.

Ah, that explains a lot! Nice piece of detective work and good you've been able to solve it.