Some 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.
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.