Relay Switches Behaving Weirdly

HI! I'm making a Halloween decoration that uses relay switches, an ATtiny84, and other small components. I'm supplying the whole circuit with a 12V 2.5A DC adapter, however, I also have a buck step-down converter that steps down the power to 5V for the relay switches and the ATtiny84. I've programmed the relay switches to open and close with a delay in between but for some reason, they open and close at a fast rate which is not how they're programmed to be. Moreover, after a variable amount of activations, the activation doesn't work unless I shut off the power and supply the power once again. I tried using an external 5V 2A power supply for the relay switches alone but that was also problematic (they behaved differently as well). I'm thinking that the way I supply the relay switches or the ATiny84 may be the root of the problem but I'm not entirely sure. Does anyone know what I might be doing wrong? Many thanks! : )

Code:

//#include <SoftwareSerial.h>
//#include <DFRobotDFPlayerMini.h>

// ---- MACROS/PINS ----
#define TRY_ME_BUTTON 0 // 0
#define SENSOR_MODE   1 // 1
#define TRY_ME_MODE   2 // 2
#define SENSOR        3 // 3
#define RX            4 // 4
#define TX            5 // 5
#define CHANNEL_ONE   6 // 6
#define CHANNEL_TWO   7 // 7

// ---- VARIABLES ----
//SoftwareSerial mySoftSerial(TX, RX);
//DFRobotDFPlayerMini myDFMini;

// ---- FUNCTION PROTOTYPES ----
void activationDo();
void armOneMoveDo(byte numTimes, float waitInBetween);
void armTwoMoveDo(byte numTimes, float waitInBetween);
void upDownMoveDo(byte numTimes, float waitInBetween);
void wait(float timeInSeconds);

// ---- FUNCTIONS ----
void setup() {
  pinMode(TRY_ME_MODE  , INPUT_PULLUP);
  pinMode(SENSOR_MODE  , INPUT_PULLUP);
  pinMode(TRY_ME_BUTTON, INPUT_PULLUP);
  pinMode(SENSOR       , INPUT);
  pinMode(CHANNEL_ONE  , OUTPUT);
  pinMode(CHANNEL_TWO  , OUTPUT);
  
//  mySoftSerial.begin(9600);
//  myDFMini.begin(mySoftSerial);
//  myDFMini.volume(23); // 23
  
  digitalWrite(CHANNEL_ONE, LOW);
  digitalWrite(CHANNEL_TWO, LOW);
}

void loop() {
  if(!digitalRead(TRY_ME_MODE)){
    if(!digitalRead(TRY_ME_BUTTON)) activationDo();
  }
  else if(!digitalRead(SENSOR_MODE)){
    if(digitalRead(SENSOR)) activationDo();
  }
}

void activationDo(){
//  myDFMini.play(1);

  upDownMoveDo(1, 3);

  for(byte i = 0; i < 2; i++){
    armOneMoveDo(3, 2);
    armTwoMoveDo(3, 3);
    upDownMoveDo(3, 2);
    armTwoMoveDo(4, 2);
    upDownMoveDo(3, 2);
    armOneMoveDo(4, 2);
    upDownMoveDo(2, 3);
  }
}

void armOneMoveDo(byte numTimes, float waitInBetween){
  for(byte i = 0; i < numTimes; i++){
    digitalWrite(CHANNEL_ONE, HIGH);
    wait(waitInBetween);
    digitalWrite(CHANNEL_ONE, LOW);
    wait(waitInBetween);
  }
}

void armTwoMoveDo(byte numTimes, float waitInBetween){
  for(byte i = 0; i < numTimes; i++){
    digitalWrite(CHANNEL_TWO, HIGH);
    wait(waitInBetween);
    digitalWrite(CHANNEL_TWO, LOW);
    wait(waitInBetween);
  }
}

void upDownMoveDo(byte numTimes, float waitInBetween){ 
  for(byte i = 0; i < numTimes; i++){
    digitalWrite(CHANNEL_ONE, HIGH);
    digitalWrite(CHANNEL_TWO, HIGH);
    wait(waitInBetween);
    digitalWrite(CHANNEL_ONE, LOW);
    digitalWrite(CHANNEL_TWO, LOW);
    wait(waitInBetween);
  }
}

void wait(float timeInSeconds){
  delay(timeInSeconds * 1000);
}

Circuit:

Here's a video of the relay switch using step-down voltage, and here's a video of the relay switch using external 5V 2A voltage.

Put Serial.println(TRY_ME_MODE_BUTTON); and Serial.println(SENSOR); in the "if" conditions to see if your switch is making one transition or many transitions.

And if the buttons are good, put LEDs in place of relays to see if the problem is relay-holding power.

I wonder why you use float values to control timing.

Have you tried with int instead?

2 Likes

I'll try this out and see what happens, thanks! : )

Initially, I was using float values (like 0.7 or 0.8) that were a little too fast so I moved on to integer values for testing (though I just sort of realized that they're all integers which makes the use of the float data type seem trivial lol).

Hello a_friend

Take a look here:

armOneMoveDo(3, 2); 

and here:

void armOneMoveDo(byte numTimes, float waitInBetween){
  for(byte i = 0; i < numTimes; i++){
    digitalWrite(CHANNEL_ONE, HIGH);
    wait(waitInBetween);
    digitalWrite(CHANNEL_ONE, LOW);
    wait(waitInBetween);
  }
}

The variabe named waitInBetween has to be from the type uint32_t and has to contain a reasonable value for the time in msec.

This must also be changed for the corresponding parts of the programme.

Have a nice day and enjoy coding in C++.

Without knowing what components you are using were only guessing. Please post a link to the data sheet.

Did you look up the use of "delay" and what type of variable is required? Float is certainly not an option. Try serial.Printing(timeInSeconds).

Hi! I made the circuit again on a breadboard, however, instead of using an ATtiny84, I used an Arduino Nano where I powered the relays via the 5V pin (the Nano was powered using the USB). Everything seems to work exactly how I wanted but I'm a little puzzled as to why I can't get this to work properly with the old circuit. The wiring is correct and the voltage going into the ATtiny84 and relays is ~5V and no more than that. I'm guessing it has to do with the ATtiny84 since even trying to activate it with the button or sensor is finicky. I might just go with the Nano if I can't find the solution but do you have any idea what might be causing the problem?

Here's a link to the relays, and here's a link to the ATtiny84.

EDIT: I just tried the program out with a different ATtiny84 and it seems to be working as expected now (I'm guessing the other one I was using must've been defective). Going to do some more tests and see if it fully works. Thanks nonetheless! : )

I don't see any supply decoupling on your ATtiny84, and I don't see any kickback diodes across your solenoids. That, and the build quality, could easilly upset or reset the MCU.
Leo..

Take a look at this similar project...

1 Like

Nice simple video for beginners. Some comments though. He talks about Sainsmart 2/4/8/16 relay boards, without mentioning that the 16-channel Sainsmart boards have a design fault. Opto couplers, but no user configurable opto isolation possible (no JD_VCC jumper).
The need to use diodes (DC) or snubber circuits (AC) is also not covered.
Arduino LED pin current is not correct. Ralph states 20mA, but it is 2mA.
Leo..

Near the 3/4 mark, Ralph mentions a design fault (maybe this is what you mentioned).

I think he only talks about the jumper causing a short when you put it on the wrong pins.
What I mean is that the 16-channel relay version of Sainsmart (and clones) is falsely advertised as opto isolated while it's not. Always use two 8-channel boards if you need 16-channels and opto isolation.
Leo..

1 Like

Also, setting the relay pin LOW before setting the relay pin as OUTPUT to avoid any noise setting the relay HIGH (when OUTPUT is set) and possibly connecting devices too soon.

The opposite, because a HIGH on the pin turns (most) opto isolated relays OFF.
And you actually turn the pull up resistor on with digitalWrite(relaypin, HIGH);, because the pin is still an input. The preferred way (same effect) is digitalWrite(relayPin, INPUT_PULLUP);

void setup() {
  digitalWrite(relayPin, INPUT_PULLUP); // preferred, but same as HIGH
  pinMode(relayPin, OUTPUT); // pin doesn't go briefly LOW during boot, and stays HIGH
}

Leo..

Hi! I'm still fairly new to working with circuits, could you elaborate on what you mean by the use of decoupling capacitors on my ATtiny84? Moreover, the use of kickback diodes across the solenoid valves? Many thanks! : )

The buck converter has buffer/decoupling caps on it's 5volt output, but you still must use a 100n ceramic cap between VCC and GND of the ATtiny84, very close to the chip.

Inductive loads (your solenoids) create high voltage spikes when you cut the power to the solenoid. That high voltage spike could upset/restart the MCU and/or burn in the relay contacts over time, making them weld shut. The solution is to add a (kickback) diode (1N4004) across the solenoid.

Both topics are extensively covered on Google and Youtube.
Spend some time there, and learn.
Leo..

See here:

Hi, @a_friend
Can you please post some pictures of your project?
So we can see your component layout.

Thanks.. Tom.. :grinning: :+1: :coffee: :australia: