# 3v3 GPIO trigger a set of 5V relays with delays

#### *synonymous*

Joined Nov 29, 2013
35
Hello

I have a set of relays that I would like to trigger with a 3.3v GPIO signal.

The GPIO signal is but enough to power a small LED.
I have an adequate 5VDC supply to power the relays.
When the GPIO signal goes high, I'd like to have the first relay come on as fast as possible with the second come on after a small (1sec) delay.
When the GPIO signal is removed, I'd like to have the relays remain on for a time of around 10 minutes and both switch off at the same time.

Any help appreciated!

#### Attachments

• 19.2 KB Views: 14

#### LesJones

Joined Jan 8, 2017
2,729
For your "FANCY-RELAY-CIRCUIT" use an 8 pin micro such as an ATtiny13A running of 3.3 volts with a transistor driver for each relay. The timing would be simpler to implement with a microconntroller than other timing methods. Do you not have another spare GPIO pin on the original device and implement the timing in software on that device. you would then only need two transistors. One for each relay. (Don't forget to put a diode across the relay coils to protect the driver transistors from back EMF.)

Les.

#### *synonymous*

Joined Nov 29, 2013
35
I'm attempting to get this done in a discreet fashion if possible. Technically I could do this in some way of programming, although it's more my intention to omit that aspect as much as possible. Cost is not an issue near as much as anything else..

I've attached another image of something that I've cobbled together..
Any obvious issues that you can see?
I realize that the second relay will disengage before the first, however this is not an issue in the least. The big part is having a slight delay for the second relay on engagement and then a nice long wait before they let go..

Thanks for any improvements or critique

#### Attachments

• 23.5 KB Views: 7

#### LesJones

Joined Jan 8, 2017
2,729
the 12 second delay circuit using Q1 and K1 should work but the timing will have poor accuracy. I do not think the 1 second delay will work as R3 and R4 form a potential divider. This means that when Q1 is conducting there will only be 18/28 * 5 volts = 3.2 volts across R4. As Q2 is being used as an emitter follower it will drop about another 0.6 of a volt so you will only get about 2.6 volts across the coil of K2 which will probably not be enough to pull it in. For the 1 second delay I would suggest using an P channel mosfet in a similar configuration to the Q1. Another alternative would be to use a dual comparator such as an LM393 as this would give a better defined switching voltage. You would need to check that the LM393 had a low enough input current rating to work with your very high value 68 meg resistor.

Les.

#### *synonymous*

Joined Nov 29, 2013
35
OK I'm with you now..
How does this look?

See attachment

Any insight on code for this thing?
Thanks

#### Attachments

• 20.8 KB Views: 6

#### LesJones

Joined Jan 8, 2017
2,729
With that circuit (Post #5) K2 will give the 1 second delay both switching on and switching off. I would use one output from the ATTINY13a to drive K1 and another to drive K2. I would use a 2N7000 for each relay driver.

The code below should give you a good start. The code relating to timing is what you can use You do not need the ADC input code as this is monitoring battery voltage. the device is for timing a battery opperated LRD light. there is just one button to switch it on. it will also switch it off if required before the end of the iming period. If the battery voltage is low it also flashes a warning light to show that the battery needs charging. If the voltage is even lower it shuts down before the timing period.
the line ".equ Shutdown_minutes = 5 ;Time to shutdown in minutes." can be changed to give to give a different number of minutes.
There is also a subroutine "Inc_Sec:" (Increment seconds.) That you can use to control K2
Code:
;
/*
* Shutdown timer  (Shutdown_timer03)  (To shut off a light after a preset period and also if the battery voltage is too low.)
*
*  Created: 03/09/2015
*  Author: Les
*  Version 2 being modified by adding low battery warning light
*/
;   using ATTINY13
; Fuse bit settings
; Low       0x62  (0x6A is also OK)
; High      0xFF
; Extended    0xFF
; Lock       0xFF

;
;

;Use internal clock at 9.6 Mhz  (Default value) and divide by 8 by setting CKDIV8 fuse bit (These are the default setting on a new chip.)
; 9.6 Mhz/8 = 1.2 Mhz
;(So Instruction time = 833.3 nS)

; So for 50 uS delay requires 50/0.8333 = 60 instructions

; Burst needs to be 5 mS long. This will be 50 cycles of 10 Khz

;
;**************************************************************************
.nolist
.include   <tn13def.inc>   ; ATtiny 13
.list
.listmac

;***************************************************************************
;*
;* Global Register Variables
;*
;***************************************************************************
; Note register number is in decimal

.def   N200mS     = r17   ;Number of 200 mS
.def   Seconds     = r18   ;Number of seconds
.def   Minutes     = r19   ;Number of minutes
.def   count_L     = r22   ;Used for time delay
.def   Flags     = r23   ;Bit 0 used for battery low warning flag

.equ   Shutdown_volts   = 0xA4   ;battery voltage shutdown value. (164 decimal. Divide battery voltage using a 4.7K resistor to ground and a 10 K resistor to the )
;  (collector ofthe power switching transistor. This gives a ratio of 0.32. So for a cut off voltage )
;  (of 10.0 we need to detect 3.2 volts This is 256 x 3.2/5 = 164 )
.equ   Battery_Low   = 0xB4   ;Battery voltage low warning level. (Set to come on at 11.0 volts so this will be 1.0 * 0.32 = 3.52 volts at ADC input
;                  (This will be a count of 256 * 3.52/5 = 180 = 0xB4 )
;
.equ   Shutdown_minutes = 5   ;Time to shutdown in minutes.
;
;
;******************************** INTERRUPT VECTORS ***********************
.CSEG
.ORG   00
rjmp   reset
reti
reti
rjmp    TC_overflow   ;Timer/Counter Overflow
reti
reti   ;   rjmp   timer1_OVF
reti
reti
reti
reti
;
;******************************* RESET *************************************
;
; Initialise the stack-pointer
reset:
ldi   R16,low(RAMEND)
out   SPL,R16

; initialize PORTB
;   Bit 0   Input  (pin 5)  (Input will be low when button is pressed.
;   Bit 1   Input
;   Bit 2   Input  ADC input (Pin 7)
;   Bit 3   Output  (Pin 2)  (Drive to low battery warning LED High for LED on)
;   Bit 4   Output   (Pin 3)  (Drive to power control tansistor base.)
;   Bit 5   Input

ldi   R16,0x18   ; Bits 3 and 4 as outputs.
out   DDRB,R16   ;
ldi   R16,0x10
out   PORTB,R16   ; PORTB Bit 3 low, bit 4 high

; initialize Flags
ldi Flags,0x00

ldi R16,0x84       ;Enable ,  Prescale value 16,  No auto triggering

ldi  R16,0b00000000

ldi R16,0x21   ;Select AD1 (pin 7) input, Select VCC as analogue reference. ADLAR (Left justify result)

ldi R16,0x04   ;Set PB2 as analoge input
out DIDR0,R16

;Initialize timer / counter

ldi R16,0x00       ;Normal operation
Out TCCR0A,R16

ldi R16,0x05       ;  Prescale value 1024 (Inc counter every 0.8333 uS x 1024 = 853.3 uS  (1171.88 hZ)
Out TCCR0B,R16       ; Counter will overflow every 218.445 mS  (4,58 hZ)
; Counting to 234 would give 199.7 mS  ( 256 - 234 = 22 = 0x16)

ldi R16,0x02       ;TOIE0 (Bit1) : Timer/Counter0 Overflow Interrupt Enable
Out TIMSK0,R16

;Init time counters
ldi N200mS,0x05
ldi Seconds,0x00
ldi Minutes,0x00

;Wait for button to be released  (Wait for input to go high

Wait_Button_High:
sbis PINB,0
rjmp Wait_Button_High

bset 7     ;Enable global interrupst.

rjmp main

;Timer/Counter Overflow interrupt handler.
TC_overflow:

ldi R20,0x16     ;Preset timer so interrupt occures every 199.7 mS
out   TCNT0,R20

dec   N200mS ;200mS
breq TC01
RETI
TC01:
ldi N200mS,0x05

Inc_Sec:

SBRS Flags, 0
CBI PORTB,0x03     ;Clear battery low warning LED
SBRS Flags,0     ;Bat_Warning   ;Skip if battery warning bit is set
RJMP Inc_S2

in R20,PORTB
ldi R21,0x08     ;Bits 3
eor R20,R21       ; Toggle bit 3 (Pin 2) (Every second)
out PORTB,R20

Inc_S2:
ldi R20,0x3C     ;60 decimal

inc   Seconds       ;Increment seconds counter
cpse Seconds,R20
rjmp TC_End
CLR Seconds

Inc_Min:
ldi R20,0x3C     ;60 decimal

inc   Minutes       ;Increment minute counter
cpse Minutes,R20
rjmp TC_End
CLR Minutes

TC_End:
RETI

;     ------------------------------------- End of interrupt handlers --------------------------------------

;
;  Main program code
;
Main:
nop
nop
ldi R20,Shutdown_minutes
cpse Minutes,R20         ;Is it time to shutdown ?
rjmp Not_Time
cbi PORTB,4             ;Clear PORTB bit 4
rjmp End_Loop

Not_Time:
nop
nop
nop
;       rjmp Main   ; Just loop waiting for interrupt

ldi R16,0x84       ;Enable ,  Prescale value 16,  No auto triggering

ldi R16,0x21   ;Select AD1 input (pin 7) Select VCC as analogue reference, ADLAR (Left justify result)

nop

;Test for battery warning level
CBR Flags,0x01 ;Bat_Warning       ;Clear battery warning flag

CLC         ;Clear carry flag
SBCI R20,Battery_Low
BRBC 0x00,Test_Shutdown     ;Branch if carry bit is clear
SBR Flags,0x01 ;Bat_Warning       ;Set battery warning flag bit

;Test for battery shutdown level
Test_Shutdown:
CLC         ;Clear carry flag
SBCI R20,Shutdown_volts
BRBS 0x00,Bat_Low       ;Branch if carry bit is set
RJMP Bat_OK

Bat_Low:
CBI PORTB,0x04       ; Shutdown

End_loop:
NOP
RJMP End_loop       ; Loop until power removed.

Bat_OK:

Test_button:               ;If button pressed input will be low.
sbic   PINB,0

rjmp Main   ; Just loop waiting for interrupt

;Now wait 100 mS and recheck that button is pressed. (De bounce switch contacts)
rcall Delay_100ms
sbic   PINB,0
rjmp Main
cbi PORTB,4             ;Clear PORTB bit 4
rjmp End_Loop

;Test_button:
sbis   PINB,0
rjmp   Test_button   ;Loop until button pressed

;Now wait 100 mS and recheck that button is pressed. (De bounce switch contacts)
rcall Delay_100ms
sbis   PINB,0
rjmp   Test_button   ;Loop until button is pressed

Button_open_loop:
sbic   PINB,0   ;
rjmp   Button_open_loop; loop until pedal released

;Subroutines.
;
;
;                 ----------------------------------------------
; Instruction cycle time is 0.83333 uS

; Delay 1mS  Rcall to get here takes 3 instruction cycles. ret instruction takes 4 instruction cycles, ldi takes 1 instruction cycle (total 8)

; For 1 mS (1000 uS) we need 1000/0.83333 = 1200 instructions  so need additional 1192 instructions  5 cycles in loop.

Delay_1_mS:
ldi    count_L,0xEE   ;Decimal 238  0xEE (Once round the loop is 5 instructions)
D_1mS_Loop:
dec   count_L     ; Count_L is R22  (1 cycle)
nop         ;(1 cycle)
nop         ;(1 cycle)
brne    D_1mS_Loop   ;If not zero  (2 cycles while looping, 1 on exit)
ret

Delay_100ms:
ldi R21,0x64   ;100 decimal
Del_100ms_Loop:
rcall Delay_1_mS
dec R21
brne Del_100ms_Loop
ret

;  -------------End of subroutines --------------
;

Les.

#### *synonymous*

Joined Nov 29, 2013
35
Thank you

It'll take a few to look through it and refine it to work for me..

Can you tell me if these things can do an accurate job of comparing analog signals?
I'm reading that they have that capacity more than devices like the RPI etc..
At some point and when, I may be interested in constructing a circuit that can give an indication when identical signals deviate to an extent.

Thanks again Les
Scott

#### LesJones

Joined Jan 8, 2017
2,729
It depends on what you mean by "accurate" The A to D converter has a resolution of 10 bits (That is about 0.1% of the full range value.) You would need to read the data sheet to see if the internal voltage reference for the ADC met your accuracy requirement. I assume by "RPI" that you mean a Raspberry Pi computer. If so I have never checked if they have an analogue to digital converter.

Les.

#### *synonymous*

Joined Nov 29, 2013
35
Thanks again,

Here's an updated image attachment..

Since going with the AVR, I've added a 'perk' to it, sensing another device. I may add indicator LED's as well.
Any particular reason in using the FET to drive the relays other than the easy BJT?
I've got a supply of the BJT

#### Attachments

• 23.9 KB Views: 4

#### LesJones

Joined Jan 8, 2017
2,729
The only reason I suggested ysing the mosfet was to save using a couple of resistors. Your driver circuit in post #9 looks fine. I suggest programming in only the most basic functions first. when they are working add some other features. For example when I wrote the code in post #6 I probably just wrote the timer code and had it toggeling the output of one output pin as a first step. I then would have added the code to divide the basic timming into seconds then the code to divide into minutes and so on.

Les.