An mbed implementation of IEC 61850-9-2LE Sample Values. Creating using the rapid61850 library, available at: https://github.com/stevenblair/rapid61850.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /**
00002  * IEC 61850-9-2LE Sampled Values demonstration
00003  *
00004  * Copyright (c) 2012 Steven Blair
00005  * 
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010 
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015 
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00019  */
00020 
00021 #include "mbed.h"
00022 #include "iec61850.h"
00023 
00024 #include <stdio.h>
00025 
00026 #define NUMBER_OF_SIGNALS           8
00027 #define NUMBER_OF_SIGNALS_PHASES    6
00028 #define NUMBER_OF_SAMPLES           80
00029 
00030 #define PI                          3.1415926535897932384626433832795f
00031 #define TWO_PI                      6.283185307179586476925286766559f
00032 #define TWO_PI_OVER_THREE           2.0943951023931954923084289221863f
00033 
00034 
00035 CTYPE_INT32 signal[NUMBER_OF_SIGNALS_PHASES][NUMBER_OF_SAMPLES] = {0};
00036 
00037 float phi = 0.1 * PI;        // phase angle between voltage and current (rad)
00038 float freq = 50.0;           // frequency of waveforms (Hz)
00039 float w = 2.0 * PI * freq;
00040 float Ts = 250e-6;           // timestep; should equal 1 / (freq * NUMBER_OF_SAMPLES)
00041 float V = 8981.462390205;    // voltage magnitude; equals 11 kV * sqrt(2) / sqrt(3)
00042 float Zmag = 15.0;           // impedance magnitude - defines the current magnitude
00043 float harmonic = 7;          // harmonic number
00044 float harmonicMagPu = 0.03;  // harmonic magnitude (p.u.); set to zero to ignore
00045 
00046 unsigned char buf[1024] = {0};
00047 int len = 0;
00048 
00049 DigitalOut watchdogLED(LED1);
00050 DigitalOut ethLink(p29);
00051 DigitalOut ethAct(p30);
00052 Ethernet eth;
00053 Ticker sv;
00054 
00055 /**
00056  *  Pre-calculate all voltage and current samples (only possible if exactly 50 Hz frequency is used).
00057  */
00058 void preCalculate() {
00059     int t = 0;
00060     for (t = 0; t < NUMBER_OF_SAMPLES; t++) {
00061         double theta = w * (((float) t) * Ts);
00062         
00063         signal[0][t] = (CTYPE_INT32) (V * sin(theta) / ((float) LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_1.Vol.sVC.scaleFactor) + (V * harmonicMagPu * sin(theta * harmonic) / ((float) LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_1.Vol.sVC.scaleFactor)));
00064         signal[1][t] = (CTYPE_INT32) (V * sin(theta - TWO_PI_OVER_THREE) / LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_2.Vol.sVC.scaleFactor) + (V * harmonicMagPu * sin(theta * harmonic - TWO_PI_OVER_THREE) / ((float) LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_1.Vol.sVC.scaleFactor));
00065         signal[2][t] = (CTYPE_INT32) (V * sin(theta + TWO_PI_OVER_THREE) / LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_3.Vol.sVC.scaleFactor) + (V * harmonicMagPu * sin(theta * harmonic + TWO_PI_OVER_THREE) / ((float) LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_1.Vol.sVC.scaleFactor));
00066         
00067         signal[3][t] = (CTYPE_INT32) ((V / Zmag) * sin(theta - phi) / LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_1.Amp.sVC.scaleFactor) + ((harmonicMagPu * V / Zmag) * sin(theta * harmonic - phi) / LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_1.Amp.sVC.scaleFactor);
00068         signal[4][t] = (CTYPE_INT32) ((V / Zmag) * sin(theta - phi - TWO_PI_OVER_THREE) / LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_2.Amp.sVC.scaleFactor) + ((harmonicMagPu * V / Zmag) * sin(theta * harmonic - phi - TWO_PI_OVER_THREE) / LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_2.Amp.sVC.scaleFactor);
00069         signal[5][t] = (CTYPE_INT32) ((V / Zmag) * sin(theta - phi + TWO_PI_OVER_THREE) / LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_3.Amp.sVC.scaleFactor) + ((harmonicMagPu * V / Zmag) * sin(theta * harmonic - phi + TWO_PI_OVER_THREE) / LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_3.Amp.sVC.scaleFactor);
00070     }
00071 }
00072 
00073 /**
00074  * Transmit the next set of samples.
00075  */
00076 void svSnapshot() {
00077     static int t = 0;
00078     
00079     LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_1.Vol.instMag.i = signal[0][t];
00080     LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_2.Vol.instMag.i = signal[1][t];
00081     LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_3.Vol.instMag.i = signal[2][t];
00082     LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_4.Vol.instMag.i = 0;
00083 
00084     LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_1.Amp.instMag.i = signal[3][t];
00085     LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_2.Amp.instMag.i = signal[4][t];
00086     LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_3.Amp.instMag.i = signal[5][t];
00087     LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_4.Amp.instMag.i = 0;
00088 
00089     len = sv_update_LE_IED_MUnn_MSVCB01(buf);
00090     
00091     if (len > 0) {
00092         ethAct = 1;
00093         eth.write((const char *) buf, len);
00094         eth.send();
00095         ethAct = 0;
00096     }
00097     
00098     if (++t >= NUMBER_OF_SAMPLES) {
00099         t = 0;
00100     }
00101 }
00102 
00103 /**
00104  * Overriding this function sets the MAC address.
00105  * Set to the destination MAC of all received SV or GOOSE packets to simplify hardware MAC filtering.
00106  */
00107 extern "C" void mbed_mac_address(char *s) {
00108     char mac[6];
00109     
00110     mac[0] = 0x01;
00111     mac[1] = 0x0C;
00112     mac[2] = 0xCD;
00113     mac[3] = 0x04;
00114     mac[4] = 0x00;
00115     mac[5] = 0x00;
00116 
00117     memcpy(s, mac, 6);
00118 }
00119 
00120 int main() {
00121     initialise_iec61850();   
00122      
00123     // enable hardware MAC address filtering
00124     LPC_EMAC->RxFilterCtrl = 1 << 5;
00125     
00126     eth.set_link(eth.FullDuplex100);
00127     while (!eth.link()) {
00128         wait(1);
00129     }
00130     ethLink = 1;
00131     
00132     wait(1);
00133     
00134     preCalculate();
00135     
00136     sv.attach_us(&svSnapshot, 250);     // create 250 us (for 50 Hz, 80 samples/cycle) periodic timer
00137 
00138     // loop forever, toggling LED
00139     while(1) {
00140         watchdogLED = 1;
00141         wait(0.01);
00142         watchdogLED = 0;
00143         wait(2);
00144     }
00145 }