driving 30 5v micro solenoids with 4 8-channel relay modules

Hello everyone,

We are currently working on a project that needs to control 30 micro solenoids. The data is transferred via Bluetooth module to determine the state of each solenoid. We use four 74HCT595 shift registers to increase the number of output pins of our Arduino Uno. We also interfaced buttons to navigate to the next/previous set of data. We used four 5V 8-channel relay as the switching medium for the solenoid. The problem is that when we press the buttons, the relay modules switches properly for a second and unexpectedly pulse again with a different output causing some solenoids to turn on and off rapidly.

Additionally, when using serial monitor, it displays a special character “ÿ” which the relays pulse into a wrong output.

Things we have tried include:

1.External power source for the relay: Tried powering each relay individually with dedicated 5V supply. Connected PS(power supply) 5V to JD-VCC and PS GND to Relay GND.
(No Difference)
2.Instead of using shift registers, we used Arduino Mega 2560 to output the data directly to the relays.

Here’s the partial schematic of the relays and micro solenoids.

relays solenoids schematic.JPG

Hi, and welcome to the forum.

5volt relay modules draw about 80mA per relay when active.
Can the relay supply deliver that current?

Relay supply should be connected to JD-VCC (jumper removed) and relay ground.
Arduino 5volt should be connected to relay VCC, and relay inputs to 595 outputs.
There should be NO ground connection between relay board(s) and Arduino/595s.
A shared ground disables opto isolation.
The solenoids should have a kickback diode across the coils.

That said, you should have used the TPIC6B595 (assuming micro solenoid current is <=150mA).
They work exactly the same as the 74HC595, but have mosfet outputs.
No relay boards needed.
Leo…

By kickback diode, you mean this?

If so, this is what we are missing. We'll try to add them to our solenoids. Hope it works.

Thanks for the help.

most multichanel relay boards: - already have flyback diodes or use ICs like ULN800x that incorporate the flyback. - include transistors or said ULN ICs to provide adequate relay coil current, so they can be driven directly by microcontroller TTL output level.

My question is... Why use relay drivers to drive relays - that drive solenoids? Why. not use relay drivers to drive the solnoids directly?

Relays and solenoids are 'electrically' virtually identical.

A 30v rated relay driver (at appropriate current)will eliminate the middle man. Also consider using PWM to pull, then hold the solenoids. Less power, less heat.

I take it that "relay driver" means a PCB with relays and driver soldered to it like this http://yourduino.com/sunshop//images/products/large_156_8-Relays-6-800.jpg

I offer a board with up to 12 TPIC6B595 shift registers that would be perfect for driving 80mA relay/solenoids. Just need to add the diodes on your coils. Board has a '328P also for Arduino functionality - plug on an FTDI Basic or equivalent for code downloading/debugging, remove it when you install the card. http://www.crossroadsfencing.com/BobuinoRev17/ |500x455

CrossRoads: I offer a board with up to 12 TPIC6B595 shift registers that would be perfect for driving 80mA relay/solenoids. Just need to add the diodes on your coils. Board has a '328P also for Arduino functionality - plug on an FTDI Basic or equivalent for code downloading/debugging, remove it when you install the card. http://www.crossroadsfencing.com/BobuinoRev17/ |500x455

DONE! It's even already populated for 40 48 outputs! (not looking too closely!)

Hi,
Have you got code for just one array of 8 relays/solenoids and see if they are stable.
Did you develop this code all at once or in stages, get them working then combine.

Can you please post a copy of your sketch, using code tags?
They are made with the </> icon in the reply Menu.
See section 7 http://forum.arduino.cc/index.php/topic,148850.0.html

Tom… :slight_smile:

At the risk of repeating myself... My question is... Why use relay drivers to drive relays - that drive solenoids? Why. not use relay drivers to drive the solnoids directly? Relays and solenoids are 'electrically' virtually identical.

A 30v rated relay driver (at appropriate current)will eliminate the middle man. Also consider using PWM to pull, then hold the solenoids. Less power, less heat.

Tom's hardware is perfect if you need a local CPU, or do [u]exactly[/u] the same thing - minus the AVR to get the simplest easy solution. 5 bytes of storage to hold 40 relay states, shift them out as often as needed to maintain your relay switchng frequency/interval.

TomGeorge:
Hi,
Have you got code for just one array of 8 relays/solenoids and see if they are stable.
Did you develop this code all at once or in stages, get them working then combine.

Can you please post a copy of your sketch, using code tags?
They are made with the </> icon in the reply Menu.
See section 7 http://forum.arduino.cc/index.php/topic,148850.0.html

Tom… :slight_smile:

Hi TomGeorge,

We already tried developing the code in stages. As requested, here’s our code.

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

const int CAPTURE_CMD = 1;
const int PREVIOUS_CMD = 2;
const int NEXT_CMD = 3;
const String ERROR_CODE = "#*0#*0#*";

const int captBtnPin = 9, prevBtnPin = 12, nxtBtnPin = 13;
const int buzzerPin = 8;
const int ledStripPin = 7;
const int ir1Pin = 2, ir2Pin = 3;

boolean isConvert = true;

String receivedString = "";
String stopReceiving = "|";

int index = 0;
int prevBtnRead, prevBtnPrev = LOW;
int nxtBtnRead, nxtBtnPrev = LOW;
int captBtnRead, captBtnPrev = LOW;
int ir1Read = LOW, ir2Read = LOW;
long time = 0, debounce = 200;

void setup() {

  Serial.begin(9600);
  Serial.println("Serial Ready");

  mySerial.begin(9600);

  pinMode(buzzerPin, OUTPUT);
  pinMode(ledStripPin, OUTPUT);
  pinMode(prevBtnPin, INPUT);
  pinMode(nxtBtnPin, INPUT);
  pinMode(captBtnPin, INPUT);
  pinMode(ir1Pin, INPUT);
  pinMode(ir2Pin, INPUT);
  
  for(int i = 22; i <= 51; i++){
    pinMode(i, OUTPUT);
    digitalWrite(i, HIGH);
  }
}

void loop() {
  
// ----------------------------- IR -----------------------------------------

  ir1Read = digitalRead(ir1Pin);
  ir2Read = digitalRead(ir2Pin);

  if (ir1Read == LOW && ir2Read == LOW)
    digitalWrite (ledStripPin, HIGH);
  else
    digitalWrite (ledStripPin, LOW);

  
// --------------------- NAVIGATION BUTTONS -------------------------------

  prevBtnRead = digitalRead(prevBtnPin);
  nxtBtnRead = digitalRead(nxtBtnPin);
  captBtnRead = digitalRead(captBtnPin);
  
  if (captBtnRead == HIGH && captBtnPrev == LOW && millis() - time > debounce) {
    buttonPress(CAPTURE_CMD);
    time = millis();
  }

  if (prevBtnRead == HIGH && prevBtnPrev == LOW && millis() - time > debounce) {
    buttonPress(PREVIOUS_CMD);
    time = millis();    
  }  

  if (nxtBtnRead == HIGH && nxtBtnPrev == LOW && millis() - time > debounce) {
    buttonPress(NEXT_CMD);
    time = millis();    
  }
  
  captBtnPrev = captBtnRead;
  prevBtnPrev = prevBtnRead;
  nxtBtnPrev = nxtBtnRead;

// ------------ RECEIVED DATA FROM BT MODULE -------------------------

  while (mySerial.available()) {
    delay(100);
    receivedString = mySerial.readString();

    Serial.println(receivedString);
    if(receivedString.charAt(0) != '|'){
      Serial.println("extra character received");
    }
    else{
      receivedString = receivedString.substring(1,receivedString.length()-1);
      convertText();
    }
  }

// ----------- RECEIVE DATA FROM SERIAL MONITOR ---------------------

  while (Serial.available()) {
    delay(100);
    String temp = Serial.readString();

    Serial.println(temp);
    if(temp.equals("n"))
      buttonPress(NEXT_CMD);
    else if(temp.equals("p"))
      buttonPress(PREVIOUS_CMD);
  }
}

void buttonPress(int button){
  switch(button){
    case CAPTURE_CMD:
      Serial.println("Capture button pressed");
      tone(buzzerPin, 1000, 200);
      delay(200);
      tone(buzzerPin, 1000, 200);
      mySerial.write("CAPTURE");
      break;
    case PREVIOUS_CMD:
      Serial.println("Previous button pressed");
      tone(buzzerPin, 1000, 200);
      mySerial.write("PREVIOUS");
      break;
    case NEXT_CMD:
      Serial.println("Next button pressed");
      tone(buzzerPin, 1000, 200);
      mySerial.write("NEXT");
      break;
  }
}

void convertText(){
  String completeBinary = "";

  Serial.println();
  for(int i = 0; i < 5 && i < receivedString.length(); i++){
    completeBinary += charToBin(receivedString.charAt(i));
  }
  Serial.println();
  Serial.println(completeBinary);
  
  int a = completeBinary.length();
  while(a < 30){
    completeBinary += "0";
    a++;
  }
  
  int x = 0;
  for(int i = 0; i < 30; i++){
    int y = completeBinary.charAt(i) - '0'; // convert character to int
    
    if(y > 0)
      digitalWrite(i+22, HIGH);
    else if(y == 0)
      digitalWrite(i+22, LOW);
  }
}

String charToBin(char charToConvert){

  switch(charToConvert){
  case 'a':
  case 'A':
  case '1':
    return "100000";
    break;

  case 'b':
  case 'B':
  case '2':
    return "110000";
    break;
  case 'c':
  case 'C':
  case '3':
    return "100100";
    break;
  case 'd':
  case 'D':
  case '4':
    return "100110";
    break;
  case 'e':
  case 'E':
  case '5':
    return "100010";
    break;
  case 'f':
  case 'F':
  case '6':
    return "110100";
    break;
  case 'g':
  case 'G':
  case '7':
    return "110110";
    break;
  case 'h':
  case 'H':
  case '8':
    return "110010";
    break;
  case 'i':
  case 'I':
  case '9':
    return "010100";
    break;
  case 'j':
  case 'J':
  case '0':
    return "010110";
    break;
  case 'k':
  case 'K':
    return "101000";
    break;
  case 'l':
  case 'L':
    return "111000";
    break;
  case 'm':
  case 'M':
    return "101100";
    break;
  case 'n':
  case 'N':
    return "101110";
    break;
  case 'o':
  case 'O':
    return "101010";
    break;
  case 'p':
  case 'P':
    return "111100";
    break;
  case 'q':
  case 'Q':
    return "111110";
    break;
  case 'r':
  case 'R':
    return "111010";
    break;
  case 's':
  case 'S':
    return "011100";
    break;
  case 't':
  case 'T':
    return "011110";
    break;
  case 'u':
  case 'U':
    return "101001";
    break;
  case 'v':
  case 'V':
    return "111001";
    break;
  case 'w':
  case 'W':
    return "010111";
    break;
  case 'x':
  case 'X':
    return "101101";
    break;
  case 'y':
  case 'Y':
    return "101111";
    break;
  case 'z':
  case 'Z':
    return "101011";
    break;
  case '?':
    return "011001";
    break;
  case '!':
    return "011010";
    break;
  case '\'':
    return "001000";
    break;
  case ',':
    return "010000";
    break;
  case '.':
    return "010011";
    break;
  case '-':
    return "100001";
    break;
  case '#':
    return "001111";
    break;
  case '*':
    return "001010";
    break;
  case ':':
    return "010010";
    break;
  case ';':
    return "011000";
    break;
  case '/':
    return "001100";
    break;
  default:
    return "000000";
    break;
  }
}

Thank you!

Hi, Have you got bypass capacitors on each of the 595 register IC's?

Have you tried just controlling one 595 array of relays?

Thanks.. Tom.. :)

Here's the image of the relay modules we're using. JD-VCC GND jumper removed. We're using 4 of this. |500x378

JD-VCC and GND of the relay modules are connected to this, Bavin 7A Fast Charger 6 USB Ports.

VCCs of the relay modules are connected to Arduino 5V. No ground connection in the relay modules. The power of the solenoids come from 12V 1A power adapter in each relay modules. So, we have 4 power adapters in total. The data pins of the relay modules are connected directly to our Arduino Mega 2560 pins 22 to 51. The data is received through Bluetooth 4.0 Module sent from Android Smartphone. |500x500

We already added flyback diodes across solenoids. The problem is that sometimes, when certain data is received, some solenoids fluctuate or turn on and off rapidly. What probably causes the problem?

Any help is much appreciate.

If Tom's proposition is not to your liking, Stack FOUR of these http://www.freetronics.com.au/products/relay8-8-channel-relay-driver-shield#.WBHY-dg8af0 onto your Arduino. No need for 74595s, use the wire library, address the drivers as per the instructions. Connect these directly to your 32 solenoids...

Arduino - drivers - solenoids - Power supply... done. The code will be much simpler, faster and more flexible.