Small Relay Box

relayboxschsplashSome of my posts were dedicated to Remote controlled relay board or [2]. But in many situations, this board was too big. I made another board for this cases and, of course, I made new application for DCTR module. Now, straight, for DPA, but if you want, you can make a simple P2P application from published source code.

Hardware

This board was made on double sided prototype PCB, bought on AliExpress, but you can use, whatever you have. It is based on IQRF KONSIM breakout board published earlier, thru-hole ULN2803 and small RAYEX RSY-12 relays. Size of PCB was modified for KP45 plastic box. Fill schematic is below.

relayboxsch

relayboxfoto

Software

Application for DCTR is based on Custom DPA handler. We have five peripherals (PNUM):

  • “0” All relays
  • “1” Relay 1
  • “2” Relay 2
  • “3” Relay 3
  • “4” Relay 4

And three commands (PCMD):

  • “0” Switch-off relay(s) – No data
  • “1” Switch-on relay(s) – No data
  • “2” Switch-on relay(s) for specific time – one byte of data (N x 100ms).
36
37
38
39
40
41
42
43
44
45
46
// Peripheral map
#define PER_ALL		0x00
#define PER_RE1		0x01
#define PER_RE2		0x02
#define PER_RE3		0x03
#define PER_RE4		0x04
 
// command map
#define CMD_OFF		0x00
#define CMD_ON		0x01
#define CMD_BLINK	0x02

At the beginning we need set-up ports:

132
133
134
135
136
137
138
139
140
141
case DpaEvent_Reset:
    // Called after module is reset
    TRISA.0 = 0;        // Pin 1 = RE1
 
    TRISC.3 = 0;        // Pin 6 = RE2
 
    TRISC.4 = 0;        // Pin 7 = RE3
 
    TRISC.5 = 0;        // Pin 8 = RE4
    TRISC.7 = 1;        // paralel pin (input)

Then we can use some simple definition for port manipulation:

23
24
25
26
27
28
29
30
31
32
33
#define	RE1_SET    LATA.0 = 1
#define	RE1_CLR    LATA.0 = 0
 
#define	RE2_SET    LATC.3 = 1
#define	RE2_CLR    LATC.3 = 0
 
#define	RE3_SET    LATC.4 = 1
#define	RE3_CLR    LATC.4 = 0
 
#define	RE4_SET    LATC.5 = 1
#define	RE4_CLR    LATC.5 = 0

Now we can process command 0x00 (Switch-off relay):

384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
// Handle peripheral command - all peripherals are the same - same commands
switch (_PCMD)
{
    case 0x00:
        switch (_PNUM)
        {
            case (PNUM_USER + PER_RE1):
                RE1_CLR;
                goto DpaHandleReturnTRUE;
                break;
            case (PNUM_USER + PER_RE2):
                RE2_CLR;
                goto DpaHandleReturnTRUE;
                break;
            case (PNUM_USER + PER_RE3):
                RE3_CLR;
                goto DpaHandleReturnTRUE;
                break;
            case (PNUM_USER + PER_RE4):
                RE4_CLR;
                goto DpaHandleReturnTRUE;
                break;	
            case (PNUM_USER + PER_ALL):
                RE1_CLR; RE2_CLR; RE3_CLR; RE4_CLR;
                goto DpaHandleReturnTRUE;
                break;						
            default:
                DpaApiReturnPeripheralError(ERROR_PNUM);
                break;
        }
        break;

Similarly for the command 0x01 (Switch-on Relay). The 0x02 command (switch for specific time) is more interesting:

288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
case 0x02:
    if ( _DpaDataLength != 1 )
        DpaApiReturnPeripheralError( ERROR_DATA_LEN );                
    switch (_PNUM)
    {
        case (PNUM_USER + PER_RE1):
            RE1_SET;
            RE1_Counter = _DpaMessage.Response.PData[0];
            goto DpaHandleReturnTRUE;
            break;
        case (PNUM_USER + PER_RE2):
            RE2_SET;
            RE2_Counter = _DpaMessage.Response.PData[0];
            goto DpaHandleReturnTRUE;
            break;
        case (PNUM_USER + PER_RE3):
            RE3_SET;
            RE3_Counter = _DpaMessage.Response.PData[0];
            goto DpaHandleReturnTRUE;
            break;
        case (PNUM_USER + PER_RE4):
            RE4_SET;
            RE4_Counter = _DpaMessage.Response.PData[0];                    
            goto DpaHandleReturnTRUE;
            break;    
        case (PNUM_USER + PER_ALL):
            RE1_SET; RE2_SET; RE3_SET; RE4_SET;
            RE1_Counter = _DpaMessage.Response.PData[0];                        
            RE2_Counter = _DpaMessage.Response.PData[0];                    
            RE3_Counter = _DpaMessage.Response.PData[0];
            RE4_Counter = _DpaMessage.Response.PData[0];                        
            goto DpaHandleReturnTRUE;
            break;                        
        default:
            DpaApiReturnPeripheralError(ERROR_PNUM);
            break;
    }            
    break;

This source code is similar to previous source code. In addition, counter specific for each relay is preset to received data byte. This byte determines time for relay-on state. Time is equal data byte * 100ms. Following source code shows, how Timer6 interrupt is used for relay switch-off after timeout expiration:

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//  If TMR6 interrupt occurred
if ( TMR6IF )
{
	// Unmask interrupt
	TMR6IF = 0;
 
	if (cntr > 0)
	{
		cntr -= 1;
	}
	else
	{		
		cntr = 10-1;
 
		// Decrement counts
		if ( RE1_Counter == 1 )
			RE1_CLR;
		if ( RE1_Counter > 0 )
			RE1_Counter -= 1;
 
		if ( RE2_Counter == 1 )
			RE2_CLR;
		if ( RE2_Counter > 0 )
			RE2_Counter -= 1;
 
		if ( RE3_Counter == 1 )
			RE3_CLR;
		if ( RE3_Counter > 0 )
			RE3_Counter -= 1;
 
		if ( RE4_Counter == 1 )
			RE4_CLR;
		if ( RE4_Counter > 0 )
			RE4_Counter -= 1;		  
	}		  
}

Examples of DPA packets:

  • NADR: 0x01; PNUM: 0x20; PCMD: 0x01; HWPID: 0xFFFF (switch-on all LEDs)
  • NADR: 0x01; PNUM: 0x20; PCMD: 0x00; HWPID: 0xFFFF (switch-off all LEDs)
  • NADR: 0x01; PNUM: 0x22; PCMD: 0x02; HWPID: 0xFFFF; DATA: 0x64 (switch-on Relay 2 for 10 seconds)

Full source code is attached.

Download Attachments

Leave a Reply

Your email address will not be published. Required fields are marked *