The goal of this software is to automatically generate C/C++ code which reads and writes GOOSE and Sampled Value packets. Any valid IEC 61850 Substation Configuration Description (SCD) file, describing GOOSE and/or SV communications, can be used as the input. The output code is lightweight and platform-independent, so it can run on a variety of devices, including low-cost microcontrollers. It\'s ideal for rapid-prototyping new protection and control systems that require communications. This mbed project is a simple example of this functionality. Other code: https://github.com/stevenblair/rapid61850 Project homepage: http://personal.strath.ac.uk/steven.m.blair/
main.cpp@1:9399d44c2b1a, 2011-10-07 (annotated)
- Committer:
- sblair
- Date:
- Fri Oct 07 13:48:18 2011 +0000
- Revision:
- 1:9399d44c2b1a
- Parent:
- 0:230c10b228ea
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
sblair | 1:9399d44c2b1a | 1 | /** |
sblair | 1:9399d44c2b1a | 2 | * Rapid-prototyping protection schemes with IEC 61850 |
sblair | 1:9399d44c2b1a | 3 | * |
sblair | 1:9399d44c2b1a | 4 | * Copyright (c) 2011 Steven Blair |
sblair | 1:9399d44c2b1a | 5 | * |
sblair | 1:9399d44c2b1a | 6 | * This program is free software; you can redistribute it and/or |
sblair | 1:9399d44c2b1a | 7 | * modify it under the terms of the GNU General Public License |
sblair | 1:9399d44c2b1a | 8 | * as published by the Free Software Foundation; either version 2 |
sblair | 1:9399d44c2b1a | 9 | * of the License, or (at your option) any later version. |
sblair | 1:9399d44c2b1a | 10 | |
sblair | 1:9399d44c2b1a | 11 | * This program is distributed in the hope that it will be useful, |
sblair | 1:9399d44c2b1a | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
sblair | 1:9399d44c2b1a | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
sblair | 1:9399d44c2b1a | 14 | * GNU General Public License for more details. |
sblair | 1:9399d44c2b1a | 15 | |
sblair | 1:9399d44c2b1a | 16 | * You should have received a copy of the GNU General Public License |
sblair | 1:9399d44c2b1a | 17 | * along with this program; if not, write to the Free Software |
sblair | 1:9399d44c2b1a | 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
sblair | 1:9399d44c2b1a | 19 | */ |
sblair | 1:9399d44c2b1a | 20 | |
sblair | 0:230c10b228ea | 21 | #include "mbed.h" |
sblair | 0:230c10b228ea | 22 | #include "iec61850.h" |
sblair | 0:230c10b228ea | 23 | |
sblair | 0:230c10b228ea | 24 | #define TWO_PI 6.283185307179586476925286766559 |
sblair | 0:230c10b228ea | 25 | #define TWO_PI_OVER_THREE 2.0943951023931954923084289221863 |
sblair | 0:230c10b228ea | 26 | #define MAGNITUDE 100 |
sblair | 0:230c10b228ea | 27 | #define INCREMENT 0.39269908169872415480783042290994 // 2 * pi / 16 |
sblair | 0:230c10b228ea | 28 | #define ERROR (1.0 + (rand() % 5) / 100.0) |
sblair | 0:230c10b228ea | 29 | |
sblair | 0:230c10b228ea | 30 | unsigned char bufOut[2048] = {0}; |
sblair | 0:230c10b228ea | 31 | unsigned char bufIn[2048] = {0}; |
sblair | 0:230c10b228ea | 32 | int waitTime = 0; |
sblair | 0:230c10b228ea | 33 | int lenIn = 0; |
sblair | 0:230c10b228ea | 34 | int lenOut = 0; |
sblair | 0:230c10b228ea | 35 | float phase = 0.0; |
sblair | 0:230c10b228ea | 36 | float MAGNITUDE_NEG_SEQ = 0.0; |
sblair | 0:230c10b228ea | 37 | float MAGNITUDE_ZERO_SEQ = 0.0; |
sblair | 0:230c10b228ea | 38 | float offset = 0.0; |
sblair | 0:230c10b228ea | 39 | |
sblair | 0:230c10b228ea | 40 | void setFault() { |
sblair | 0:230c10b228ea | 41 | MAGNITUDE_NEG_SEQ = 50.0; |
sblair | 0:230c10b228ea | 42 | MAGNITUDE_ZERO_SEQ = 25.0; |
sblair | 0:230c10b228ea | 43 | } |
sblair | 0:230c10b228ea | 44 | |
sblair | 0:230c10b228ea | 45 | void setNormal() { |
sblair | 0:230c10b228ea | 46 | MAGNITUDE_NEG_SEQ = 0.0; |
sblair | 0:230c10b228ea | 47 | MAGNITUDE_ZERO_SEQ = 0.0; |
sblair | 0:230c10b228ea | 48 | offset = 0.0; |
sblair | 0:230c10b228ea | 49 | } |
sblair | 0:230c10b228ea | 50 | |
sblair | 0:230c10b228ea | 51 | DigitalOut watchdogLED(LED1); |
sblair | 0:230c10b228ea | 52 | DigitalOut inputLED(LED4); |
sblair | 0:230c10b228ea | 53 | Ethernet eth; |
sblair | 0:230c10b228ea | 54 | DigitalOut ethLink(p29); |
sblair | 0:230c10b228ea | 55 | DigitalOut ethAct(p30); |
sblair | 0:230c10b228ea | 56 | Ticker sv; |
sblair | 0:230c10b228ea | 57 | |
sblair | 0:230c10b228ea | 58 | void svSnapshot() { |
sblair | 0:230c10b228ea | 59 | E1Q1SB1.S1.C1.RMXU_1.AmpLocPhsA.instMag.f = MAGNITUDE * sin(phase + offset) * ERROR + MAGNITUDE_NEG_SEQ * sin(phase + offset) + MAGNITUDE_ZERO_SEQ * sin(phase + offset); |
sblair | 0:230c10b228ea | 60 | E1Q1SB1.S1.C1.RMXU_1.AmpLocPhsB.instMag.f = MAGNITUDE * sin(phase + offset - TWO_PI_OVER_THREE) * ERROR + MAGNITUDE_NEG_SEQ * sin(phase + offset + TWO_PI_OVER_THREE) + MAGNITUDE_ZERO_SEQ * sin(phase + offset); |
sblair | 0:230c10b228ea | 61 | E1Q1SB1.S1.C1.RMXU_1.AmpLocPhsC.instMag.f = MAGNITUDE * sin(phase + offset + TWO_PI_OVER_THREE) * ERROR + MAGNITUDE_NEG_SEQ * sin(phase + offset - TWO_PI_OVER_THREE) + MAGNITUDE_ZERO_SEQ * sin(phase + offset); |
sblair | 0:230c10b228ea | 62 | |
sblair | 0:230c10b228ea | 63 | lenOut = sv_update_rmxuCB_rmxu(bufOut); |
sblair | 0:230c10b228ea | 64 | |
sblair | 0:230c10b228ea | 65 | if (lenOut > 0) { |
sblair | 0:230c10b228ea | 66 | ethAct = 1; |
sblair | 0:230c10b228ea | 67 | eth.write((const char *) bufOut, lenOut); |
sblair | 0:230c10b228ea | 68 | eth.send(); |
sblair | 0:230c10b228ea | 69 | ethAct = 0; |
sblair | 0:230c10b228ea | 70 | } |
sblair | 0:230c10b228ea | 71 | |
sblair | 0:230c10b228ea | 72 | phase += INCREMENT; |
sblair | 0:230c10b228ea | 73 | if (phase > TWO_PI) { |
sblair | 0:230c10b228ea | 74 | phase = phase - TWO_PI; |
sblair | 0:230c10b228ea | 75 | } |
sblair | 0:230c10b228ea | 76 | } |
sblair | 0:230c10b228ea | 77 | |
sblair | 0:230c10b228ea | 78 | int main() { |
sblair | 0:230c10b228ea | 79 | initialise_iec61850(); |
sblair | 0:230c10b228ea | 80 | |
sblair | 0:230c10b228ea | 81 | eth.set_link(eth.FullDuplex100); |
sblair | 0:230c10b228ea | 82 | while (!eth.link() && waitTime++ < 60) { |
sblair | 0:230c10b228ea | 83 | wait(1); |
sblair | 0:230c10b228ea | 84 | } |
sblair | 0:230c10b228ea | 85 | ethLink = 1; |
sblair | 0:230c10b228ea | 86 | |
sblair | 0:230c10b228ea | 87 | wait(1); |
sblair | 0:230c10b228ea | 88 | |
sblair | 0:230c10b228ea | 89 | sv.attach_us(&svSnapshot, 1250); |
sblair | 0:230c10b228ea | 90 | |
sblair | 0:230c10b228ea | 91 | wait(5); |
sblair | 0:230c10b228ea | 92 | |
sblair | 0:230c10b228ea | 93 | while(1) { |
sblair | 0:230c10b228ea | 94 | wait_us(100); |
sblair | 0:230c10b228ea | 95 | |
sblair | 0:230c10b228ea | 96 | lenIn = eth.receive(); |
sblair | 0:230c10b228ea | 97 | if (lenIn == 272) { |
sblair | 0:230c10b228ea | 98 | eth.read((char *) bufIn, lenIn); |
sblair | 0:230c10b228ea | 99 | gseDecode(bufIn, lenIn); |
sblair | 0:230c10b228ea | 100 | |
sblair | 1:9399d44c2b1a | 101 | //printf("%f\n", D1Q1SB4.S1.C1.RSYN_1.gse_inputs.instMag_1.f); // monitor values from serial port |
sblair | 0:230c10b228ea | 102 | |
sblair | 0:230c10b228ea | 103 | if (D1Q1SB4.S1.C1.RSYN_1.gse_inputs.instMag_1.f > 0) { |
sblair | 0:230c10b228ea | 104 | setFault(); |
sblair | 0:230c10b228ea | 105 | } |
sblair | 0:230c10b228ea | 106 | else { |
sblair | 0:230c10b228ea | 107 | setNormal(); |
sblair | 0:230c10b228ea | 108 | } |
sblair | 0:230c10b228ea | 109 | } |
sblair | 0:230c10b228ea | 110 | } |
sblair | 0:230c10b228ea | 111 | } |