From 1e485a51669aa192dce702484868c82e41c101a0 Mon Sep 17 00:00:00 2001 From: Elorza Iker Date: Wed, 13 Dec 2017 10:42:04 +0100 Subject: [PATCH 01/17] added ipc and yaw by ipc to cl-windcon controller --- CMakeLists.txt | 4 + OpenWitcon | 2 +- doc/svg/ikClwindconWTCon_block_diagram.svg | 711 ++++++++++++++++-- doc/svg/ikClwindconWTCon_unit_block.svg | 303 ++++++-- src/discon/discon.c | 15 +- src/ikClwindconWTCon/ikClwindconWTCon.c | 45 +- src/ikClwindconWTCon/ikClwindconWTCon.h | 18 + src/ikClwindconWTConfig/ikClwindconWTConfig.c | 231 +++++- src/ikClwindconWTConfig/ikClwindconWTConfig.h | 10 + 9 files changed, 1182 insertions(+), 157 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 345a112..08b2155 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,8 @@ set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/Op set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikStpgen) set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikTfList) set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikVfnotch) +set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikIpc) +set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikVector) # OpenWitcon source files set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikConLoop/ikConLoop.c) @@ -35,6 +37,8 @@ set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/s set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikStpgen/ikStpgen.c) set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikTfList/ikTfList.c) set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikVfnotch/ikVfnotch.c) +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikIpc/ikIpc.c) +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikVector/ikVector.c) # shared OpenDiscon library include_directories ("${OPENDISCON_INCLUDE_DIRS}") diff --git a/OpenWitcon b/OpenWitcon index 5b3537a..ff09cd6 160000 --- a/OpenWitcon +++ b/OpenWitcon @@ -1 +1 @@ -Subproject commit 5b3537a935cde8f88c80a1d012c4136a2657384e +Subproject commit ff09cd61ac1cac776c2cbc2c8d4cdc6ebe6cb60d diff --git a/doc/svg/ikClwindconWTCon_block_diagram.svg b/doc/svg/ikClwindconWTCon_block_diagram.svg index 743aa47..cad4d7f 100644 --- a/doc/svg/ikClwindconWTCon_block_diagram.svg +++ b/doc/svg/ikClwindconWTCon_block_diagram.svg @@ -9,9 +9,9 @@ xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="570.57776mm" - height="322.54263mm" - viewBox="0 0 2021.732 1142.8675" + width="684.97382mm" + height="440.59653mm" + viewBox="0 0 2427.0723 1561.1687" id="svg2" version="1.1" inkscape:version="0.92.1 r15371" @@ -807,38 +807,6 @@ transform="matrix(-0.8,0,0,-0.8,-10,0)" inkscape:connector-curvature="0" /> - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml - + @@ -2085,52 +2341,40 @@ x="1007.5291" y="950.25769" id="tspan4718-8-5">ikTpman - - pitch demand for blade 1 pitch demand for blade 2 pitch demand for blade 3 - + + individual pitch control + ikIpc + 0 + blade root moments + azimuth + 0 + 0 + maximum individual pitch + + + + + + + + + + + + + + + + + yaw by ipc + ikConLoop + + + yaw error reference + yaw error + individual pitch for yaw + + -1 + + + + + diff --git a/doc/svg/ikClwindconWTCon_unit_block.svg b/doc/svg/ikClwindconWTCon_unit_block.svg index 1f3c89e..874589b 100644 --- a/doc/svg/ikClwindconWTCon_unit_block.svg +++ b/doc/svg/ikClwindconWTCon_unit_block.svg @@ -9,9 +9,9 @@ xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="197.91646mm" - height="132.59679mm" - viewBox="0 0 701.2788 469.83109" + width="207.45264mm" + height="182.10945mm" + viewBox="0 0 735.06841 645.26965" id="svg2" version="1.1" inkscape:version="0.92.1 r15371" @@ -31,8 +31,8 @@ inkscape:stockid="Arrow1Lend"> @@ -47,8 +47,8 @@ + + + + + + + + + + + + + + + image/svg+xml - + @@ -465,7 +540,7 @@ inkscape:label="Capa 1" inkscape:groupmode="layer" id="layer1" - transform="translate(28.219161,-256.24312)"> + transform="translate(62.20234,-256.24311)"> ikClwindconWTCon derating ratio + + + + + + blade root moments + maximum individual pitch + yaw error reference + yaw error + azimuth diff --git a/src/discon/discon.c b/src/discon/discon.c index 3f6c221..7177390 100644 --- a/src/discon/discon.c +++ b/src/discon/discon.c @@ -37,7 +37,7 @@ void OpenDiscon_EXPORT DISCON(float *DATA, int FLAG, const char *INFILE, const c ikClwindconWTCon_init(&con, ¶m); f = fopen("log.bin", "wb"); } -//TODO lower maximum torque according to maximum power with derating (it may be time to bring the power manager back) + con.in.deratingRatio = deratingRatio; con.in.externalMaximumTorque = 230.0; /* kNm */ con.in.externalMinimumTorque = 0.0; /* kNm */ @@ -45,6 +45,19 @@ void OpenDiscon_EXPORT DISCON(float *DATA, int FLAG, const char *INFILE, const c con.in.externalMinimumPitch = 0.0; /* deg */ con.in.generatorSpeed = (double) DATA[19]; /* rad/s */ con.in.maximumSpeed = 480.0/30*3.1416; /* rpm to rad/s */ + con.in.azimuth = 180.0/3.1416 * (double) DATA[59]; /* rad to deg */ + con.in.maximumIndividualPitch = 10.0; /* deg */ + con.in.yawErrorReference = 0.0; /* deg */ + con.in.yawError = 180.0/3.1416 * (double) DATA[23]; /* rad to deg */ + con.in.bladeRootMoments[0].c[0] = 1.0e-3 * (double) DATA[68]; /* Nm to kNm */ + con.in.bladeRootMoments[0].c[1] = 1.0e-3 * (double) DATA[29]; /* Nm to kNm */ + con.in.bladeRootMoments[0].c[2] = 0.0; /* kNm */ + con.in.bladeRootMoments[1].c[0] = 1.0e-3 * (double) DATA[69]; /* Nm to kNm */ + con.in.bladeRootMoments[1].c[1] = 1.0e-3 * (double) DATA[30]; /* Nm to kNm */ + con.in.bladeRootMoments[1].c[2] = 0.0; /* kNm */ + con.in.bladeRootMoments[2].c[0] = 1.0e-3 * (double) DATA[70]; /* Nm to kNm */ + con.in.bladeRootMoments[2].c[1] = 1.0e-3 * (double) DATA[31]; /* Nm to kNm */ + con.in.bladeRootMoments[2].c[2] = 0.0; /* kNm */ ikClwindconWTCon_step(&con); diff --git a/src/ikClwindconWTCon/ikClwindconWTCon.c b/src/ikClwindconWTCon/ikClwindconWTCon.c index 1b25e4e..433c1f5 100644 --- a/src/ikClwindconWTCon/ikClwindconWTCon.c +++ b/src/ikClwindconWTCon/ikClwindconWTCon.c @@ -48,6 +48,10 @@ int ikClwindconWTCon_init(ikClwindconWTCon *self, const ikClwindconWTConParams * if (err) return -5; err = ikPowman_init(&(self->priv.powerManager), &(params_.powerManager)); if (err) return -6; + err = ikIpc_init(&(self->priv.ipc), &(params_.individualPitchControl)); + if (err) return -7; + err = ikConLoop_init(&(self->priv.yawByIpc), &(params_.yawByIpc)); + if (err) return -8; /* initialise feedback signals */ self->priv.torqueFromTorqueCon = 0.0; @@ -63,9 +67,12 @@ void ikClwindconWTCon_initParams(ikClwindconWTConParams *params) { ikConLoop_initParams(&(params->torqueControl)); ikTpman_initParams(&(params->torquePitchManager)); ikPowman_initParams(&(params->powerManager)); + ikIpc_initParams(&(params->individualPitchControl)); + ikConLoop_initParams(&(params->yawByIpc)); } int ikClwindconWTCon_step(ikClwindconWTCon *self) { + int i; /* run power manager */ self->priv.maxTorqueFromPowman = ikPowman_step(&(self->priv.powerManager), self->in.deratingRatio, self->in.maximumSpeed, self->in.generatorSpeed); @@ -94,11 +101,29 @@ int ikClwindconWTCon_step(ikClwindconWTCon *self) { /* run collective pitch control */ self->priv.collectivePitchDemand = ikConLoop_step(&(self->priv.colpitchcon), self->in.maximumSpeed, self->in.generatorSpeed, self->priv.minPitch, self->priv.maxPitch); + + /* run yaw by ipc */ + self->priv.individualPitchForYaw = ikConLoop_step(&(self->priv.yawByIpc), self->in.yawErrorReference, self->in.yawError, -self->in.maximumIndividualPitch, self->in.maximumIndividualPitch); + + /* run individual pitch control */ + self->priv.ipc.in.azimuth = self->in.azimuth; + self->priv.ipc.in.collectivePitch = self->priv.collectivePitchDemand; + self->priv.ipc.in.maximumPitch = self->priv.maxPitch; + self->priv.ipc.in.minimumPitch = self->priv.minPitch; + for (i = 0; i < 3; i++) { + self->priv.ipc.in.bladeRootMoments[i] = self->in.bladeRootMoments[i]; + } + self->priv.ipc.in.demandedMy = 0.0; + self->priv.ipc.in.demandedMz = 0.0; + self->priv.ipc.in.maximumIndividualPitch = self->in.maximumIndividualPitch; + self->priv.ipc.in.externalPitchY = self->priv.individualPitchForYaw; + self->priv.ipc.in.externalPitchZ = 0.0; + ikIpc_step(&(self->priv.ipc)); /* run IPC */ - self->out.pitchDemandBlade1 = self->priv.collectivePitchDemand; - self->out.pitchDemandBlade2 = self->priv.collectivePitchDemand; - self->out.pitchDemandBlade3 = self->priv.collectivePitchDemand; + self->out.pitchDemandBlade1 = self->priv.ipc.out.pitch[0]; + self->out.pitchDemandBlade2 = self->priv.ipc.out.pitch[1]; + self->out.pitchDemandBlade3 = self->priv.ipc.out.pitch[2]; return self->priv.tpManState; } @@ -144,6 +169,10 @@ int ikClwindconWTCon_getOutput(const ikClwindconWTCon *self, double *output, con *output = self->priv.minPitchFromPowman; return 0; } + if (!strcmp(name, "individual pitch for yaw")) { + *output = self->priv.individualPitchForYaw; + return 0; + } /* pick up the block names */ sep = strstr(name, ">"); @@ -173,6 +202,16 @@ int ikClwindconWTCon_getOutput(const ikClwindconWTCon *self, double *output, con if (err) return -1; else return 0; } + if (!strncmp(name, "individual pitch control", strlen(name) - strlen(sep))) { + err = ikIpc_getOutput(&(self->priv.ipc), output, sep + 1); + if (err) return -1; + else return 0; + } + if (!strncmp(name, "yaw by ipc", strlen(name) - strlen(sep))) { + err = ikConLoop_getOutput(&(self->priv.yawByIpc), output, sep + 1); + if (err) return -1; + else return 0; + } return -2; diff --git a/src/ikClwindconWTCon/ikClwindconWTCon.h b/src/ikClwindconWTCon/ikClwindconWTCon.h index 04ae6fb..5a0a5e6 100644 --- a/src/ikClwindconWTCon/ikClwindconWTCon.h +++ b/src/ikClwindconWTCon/ikClwindconWTCon.h @@ -33,6 +33,7 @@ extern "C" { #include "ikConLoop.h" #include "ikTpman.h" #include "ikPowman.h" +#include "ikIpc.h" /** * @struct ikClwindconWTConInputs @@ -46,6 +47,11 @@ extern "C" { double maximumSpeed; /**. #include "ikClwindconWTConfig.h" void setParams(ikClwindconWTConParams *param) { - double T = 0.01; + const double T = 0.01; ikTuneDrivetrainDamper(&(param->drivetrainDamper), T); ikTuneSpeedRange(&(param->torqueControl)); @@ -58,9 +58,9 @@ void ikTuneDrivetrainDamper(ikConLoopParams *params, double T) { Set parameters here: */ - double G = 0.0382; /* [kNm s^2/rad] 4 Nm s/rpm */ - double d = 0.1; /* [-] */ - double w = 21.1; /* [rad/s] */ + const double G = 0.0382; /* [kNm s^2/rad] 4 Nm s/rpm */ + const double d = 0.1; /* [-] */ + const double w = 21.1; /* [rad/s] */ /* #################################################################### */ @@ -228,8 +228,8 @@ void ikTunePitchLowpassFilter(ikConLoopParams *params, double T) { Set parameters here: */ - double w = 5.6; /* [rad/s] */ - double d = 0.5; /* [-] */ + const double w = 5.6; /* [rad/s] */ + const double d = 0.5; /* [-] */ /* #################################################################### */ @@ -276,9 +276,9 @@ void ikTunePitchNotches(ikConLoopParams *params, double T) { Set parameters here: */ - double w = 1.59; /* [rad/s] */ - double dnum = 0.01; /* [-] */ - double dden = 0.2; /* [-] */ + const double w = 1.59; /* [rad/s] */ + const double dnum = 0.01; /* [-] */ + const double dden = 0.2; /* [-] */ /* #################################################################### */ @@ -307,8 +307,8 @@ void ikTunePitchPI(ikConLoopParams *params, double T) { Set parameters here: */ - double Kp = -0.3939; /* [degs/rad] 7.2e-4 rad/rpm */ - double Ki = -0.1313; /* [deg/rad] 2.4e-4 rad/rpms */ + const double Kp = -0.3939; /* [degs/rad] 7.2e-4 rad/rpm */ + const double Ki = -0.1313; /* [deg/rad] 2.4e-4 rad/rpms */ /* #################################################################### */ @@ -354,8 +354,8 @@ void ikTuneTorqueLowpassFilter(ikConLoopParams *params, double T) { Set parameters here: */ - double w = 3.39; /* [rad/s] */ - double d = 0.5; /* [-] */ + const double w = 3.39; /* [rad/s] */ + const double d = 0.5; /* [-] */ /* #################################################################### */ @@ -402,9 +402,9 @@ void ikTuneTorqueNotches(ikConLoopParams *params, double T) { Set parameters here: */ - double w = 1.59; /* [rad/s] */ - double dnum = 0.01; /* [-] */ - double dden = 0.2; /* [-] */ + const double w = 1.59; /* [rad/s] */ + const double dnum = 0.01; /* [-] */ + const double dden = 0.2; /* [-] */ /* #################################################################### */ @@ -433,14 +433,13 @@ void ikTuneTorquePI(ikConLoopParams *params, double T) { Set parameters here: */ - double Kp = -34.3775; /* [kNms/rad] 3600 Nm/rpm */ - double Ki = -11.4592; /* [kNm/rad] 1200 Nm/rpms */ + const double Kp = -34.3775; /* [kNms/rad] 3600 Nm/rpm */ + const double Ki = -11.4592; /* [kNm/rad] 1200 Nm/rpms */ /* #################################################################### */ /*! [Torque PI] */ - /* tune the torque control to this tf: (Kp + Ki*T/2)z - (Kp - Ki*T/2) @@ -465,3 +464,197 @@ void ikTuneTorquePI(ikConLoopParams *params, double T) { params->linearController.postGainTfs.tfParams[0].a[2] = 0.0; } + +void ikConfigureRotorForIpc(ikIpcParams *params) { + + params->azimuthOffset = 0.0; + params->bladeOrder = 1; + +} + +void ikTuneIpcMyPI(ikConLoopParams *params, double T) { + + /*! [IPC My PI] */ + /* + #################################################################### + IPC My PI + + Transfer function: + + C(s) = (Kp*s + Ki)/s + + The sampling time is given by function parameter T. + + Set parameters here: + */ + const double Kp = 0.0; /* [deg/kNm] */ + const double Ki = 0.0; /* [deg/kNms] */ + /* + #################################################################### + */ + /*! [IPC My PI] */ + + /* + tune the ipc My control to this tf: + (Kp + Ki*T/2)z - (Kp - Ki*T/2) + C(z) = ------------------------------ + z - 1 + rad/s --> kNm + */ + params->linearController.errorTfs.tfParams[0].enable = 1; + params->linearController.errorTfs.tfParams[0].b[0] = (Kp + Ki*T/2); + params->linearController.errorTfs.tfParams[0].b[1] = -(Kp - Ki*T/2); + params->linearController.errorTfs.tfParams[0].b[2] = 0.0; + params->linearController.errorTfs.tfParams[0].a[0] = 1.0; + params->linearController.errorTfs.tfParams[0].a[1] = 0.0; + params->linearController.errorTfs.tfParams[0].a[2] = 0.0; + + params->linearController.postGainTfs.tfParams[0].enable = 1; + params->linearController.postGainTfs.tfParams[0].b[0] = 1.0; + params->linearController.postGainTfs.tfParams[0].b[1] = 0.0; + params->linearController.postGainTfs.tfParams[0].b[2] = 0.0; + params->linearController.postGainTfs.tfParams[0].a[0] = 1.0; + params->linearController.postGainTfs.tfParams[0].a[1] = -1.0; + params->linearController.postGainTfs.tfParams[0].a[2] = 0.0; + +} + +void ikTuneIpcMzPI(ikConLoopParams *params, double T) { + + /*! [IPC Mz PI] */ + /* + #################################################################### + IPC Mz PI + + Transfer function: + + C(s) = (Kp*s + Ki)/s + + The sampling time is given by function parameter T. + + Set parameters here: + */ + const double Kp = 0.0; /* [deg/kNm] */ + const double Ki = 0.0; /* [deg/kNms] */ + /* + #################################################################### + */ + /*! [IPC Mz PI] */ + + /* + tune the ipc Mz control to this tf: + (Kp + Ki*T/2)z - (Kp - Ki*T/2) + C(z) = ------------------------------ + z - 1 + rad/s --> kNm + */ + params->linearController.errorTfs.tfParams[0].enable = 1; + params->linearController.errorTfs.tfParams[0].b[0] = (Kp + Ki*T/2); + params->linearController.errorTfs.tfParams[0].b[1] = -(Kp - Ki*T/2); + params->linearController.errorTfs.tfParams[0].b[2] = 0.0; + params->linearController.errorTfs.tfParams[0].a[0] = 1.0; + params->linearController.errorTfs.tfParams[0].a[1] = 0.0; + params->linearController.errorTfs.tfParams[0].a[2] = 0.0; + + params->linearController.postGainTfs.tfParams[0].enable = 1; + params->linearController.postGainTfs.tfParams[0].b[0] = 1.0; + params->linearController.postGainTfs.tfParams[0].b[1] = 0.0; + params->linearController.postGainTfs.tfParams[0].b[2] = 0.0; + params->linearController.postGainTfs.tfParams[0].a[0] = 1.0; + params->linearController.postGainTfs.tfParams[0].a[1] = -1.0; + params->linearController.postGainTfs.tfParams[0].a[2] = 0.0; + +} + +void ikTuneYawByIpc(ikConLoopParams *params, double T) { +/* +This is an original implementation of the yaw by IPC strategy in 87e4a2fe8e8ac8fc51305a3f840e23a0deaf6caa of https://github.com/TUDelft-DataDrivenControl/DRC_Fortran +*/ + + /*! [Yaw by IPC PI] */ + /* + #################################################################### + Yaw by IPC PI + + Transfer function: + + C(s) = (Kp*s + Ki)/s + + The sampling time is given by function parameter T. + + Set parameters here: + */ + const double Kp = -0.064; /* [-] */ + const double Ki = -0.0008; /* [1/s] */ + /* + #################################################################### + */ + /*! [Yaw by IPC PI] */ + + /* + tune the yaw by ipc control to this tf: + (Kp + Ki*T/2)z - (Kp - Ki*T/2) + C(z) = ------------------------------ + z - 1 + deg --> deg + */ + params->linearController.errorTfs.tfParams[0].enable = 1; + params->linearController.errorTfs.tfParams[0].b[0] = (Kp + Ki*T/2); + params->linearController.errorTfs.tfParams[0].b[1] = -(Kp - Ki*T/2); + params->linearController.errorTfs.tfParams[0].b[2] = 0.0; + params->linearController.errorTfs.tfParams[0].a[0] = 1.0; + params->linearController.errorTfs.tfParams[0].a[1] = 0.0; + params->linearController.errorTfs.tfParams[0].a[2] = 0.0; + + params->linearController.postGainTfs.tfParams[0].enable = 1; + params->linearController.postGainTfs.tfParams[0].b[0] = 1.0; + params->linearController.postGainTfs.tfParams[0].b[1] = 0.0; + params->linearController.postGainTfs.tfParams[0].b[2] = 0.0; + params->linearController.postGainTfs.tfParams[0].a[0] = 1.0; + params->linearController.postGainTfs.tfParams[0].a[1] = -1.0; + params->linearController.postGainTfs.tfParams[0].a[2] = 0.0; + +} + +void ikTuneYawByIpcLowpassFilter(ikConLoopParams *params, double T) { +/* +This is an original implementation of the yaw by IPC strategy in 87e4a2fe8e8ac8fc51305a3f840e23a0deaf6caa of https://github.com/TUDelft-DataDrivenControl/DRC_Fortran +*/ + + /*! [Yaw by IPC lowpass filter] */ + /* + #################################################################### + Yaw error feedback low pass filter + + Transfer function: + H(s) = w^2 / (s^2 + 2*d*w*s + w^2) + + The sampling time is given by function parameter T. + + Set parameters here: + */ + const double w = 0.6283185; /* [rad/s] */ + const double d = 1.0; /* [-] */ + /* + #################################################################### + */ + /*! [Yaw by IPC lowpass filter] */ + + /* + tune the yaw by ipc control feedback filter to this tf: + (0.5*T*w)^2 z^2 + 2z + 1 + H(z) = ----------------------------- ------------------------------------------------------------------------------------------------------------------------ + 1 + T*d*w + (0.5*T*w)^2 z^2 - 2*(1 - (0.5*T*w)^2) / (1 + T*d*w + (0.5*T*w)^2)z + (1 - T*d*w + (0.5*T*w)^2) / (1 + T*d*w + (0.5*T*w)^2) + */ + params->linearController.measurementTfs.tfParams[0].enable = 1; + params->linearController.measurementTfs.tfParams[0].b[0] = 1.0; + params->linearController.measurementTfs.tfParams[0].b[1] = 2.0; + params->linearController.measurementTfs.tfParams[0].b[2] = 1.0; + params->linearController.measurementTfs.tfParams[0].a[0] = 1.0; + params->linearController.measurementTfs.tfParams[0].a[1] = -2 * (1 - (0.5*T*w)*(0.5*T*w)) / (1 + T*d*w + (0.5*T*w)*(0.5*T*w)); + params->linearController.measurementTfs.tfParams[0].a[2] = (1 - T*d*w + (0.5*T*w)*(0.5*T*w)) / (1 + T*d*w + (0.5*T*w)*(0.5*T*w)); + + params->linearController.measurementTfs.tfParams[1].enable = 1; + params->linearController.measurementTfs.tfParams[1].b[0] = (0.5*T*w)*(0.5*T*w) / (1 + T*d*w + (0.5*T*w)*(0.5*T*w)); + +} diff --git a/src/ikClwindconWTConfig/ikClwindconWTConfig.h b/src/ikClwindconWTConfig/ikClwindconWTConfig.h index c5e3e7e..8cbf976 100644 --- a/src/ikClwindconWTConfig/ikClwindconWTConfig.h +++ b/src/ikClwindconWTConfig/ikClwindconWTConfig.h @@ -58,6 +58,16 @@ extern "C" { void ikTunePitchPIGainSchedule(ikConLoopParams *params); + void ikConfigureRotorForIpc(ikIpcParams *params); + + void ikTuneIpcMyPI(ikConLoopParams *params, double T); + + void ikTuneIpcMzPI(ikConLoopParams *params, double T); + + void ikTuneYawByIpc(ikConLoopParams *params, double T); + + void ikTuneYawByIpcLowpassFilter(ikConLoopParams *params, double T); + #ifdef __cplusplus } #endif From 094d6fb7748351023a22f3e327df0b3d62f9859a Mon Sep 17 00:00:00 2001 From: Elorza Iker Date: Mon, 18 Dec 2017 08:44:50 +0100 Subject: [PATCH 02/17] added some missing includes they just resulted in implicit declarations --- src/ikPowman/ikPowman.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ikPowman/ikPowman.c b/src/ikPowman/ikPowman.c index 29b515f..b7447c3 100644 --- a/src/ikPowman/ikPowman.c +++ b/src/ikPowman/ikPowman.c @@ -25,6 +25,9 @@ along with OpenDiscon. If not, see . /* @cond */ +#include +#include + #include "ikPowman.h" int ikPowman_init(ikPowman *self, const ikPowmanParams *params) { From a9e4a1ea391a88531c336b8ebada4d4652597a55 Mon Sep 17 00:00:00 2001 From: Elorza Iker Date: Mon, 18 Dec 2017 14:53:09 +0100 Subject: [PATCH 03/17] builds fine in matlab2014a --- CMakeLists.txt | 59 +- CONFIGURATION/CL-Windcon/CMakeLists.txt | 47 + .../DISTRIBUTION/DISCON/CMakeLists.txt | 14 + .../DISTRIBUTION/S-Function/CMakeLists.txt | 10 + .../CL-Windcon/src}/discon/discon.c | 0 .../src}/ikClwindconWTCon/ikClwindconWTCon.c | 0 .../src}/ikClwindconWTCon/ikClwindconWTCon.h | 0 .../ikClwindconWTConfig/ikClwindconWTConfig.c | 0 .../ikClwindconWTConfig/ikClwindconWTConfig.h | 0 .../CL-Windcon/src}/ikPowman/ikPowman.c | 0 .../CL-Windcon/src}/ikPowman/ikPowman.h | 0 .../CL-Windcon/src}/ikTpman/ikTpman.c | 0 .../CL-Windcon/src}/ikTpman/ikTpman.h | 0 .../CL-Windcon/src/sfunc/OpenDiscon_block.mdl | 1147 ++++++++++++ .../CL-Windcon/src/sfunc/makeOpenDiscon.m | 3 + CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c | 1602 +++++++++++++++++ README.md | 14 +- doc/Doxyfile | 8 +- 18 files changed, 2844 insertions(+), 60 deletions(-) create mode 100644 CONFIGURATION/CL-Windcon/CMakeLists.txt create mode 100644 CONFIGURATION/CL-Windcon/DISTRIBUTION/DISCON/CMakeLists.txt create mode 100644 CONFIGURATION/CL-Windcon/DISTRIBUTION/S-Function/CMakeLists.txt rename {src => CONFIGURATION/CL-Windcon/src}/discon/discon.c (100%) rename {src => CONFIGURATION/CL-Windcon/src}/ikClwindconWTCon/ikClwindconWTCon.c (100%) rename {src => CONFIGURATION/CL-Windcon/src}/ikClwindconWTCon/ikClwindconWTCon.h (100%) rename {src => CONFIGURATION/CL-Windcon/src}/ikClwindconWTConfig/ikClwindconWTConfig.c (100%) rename {src => CONFIGURATION/CL-Windcon/src}/ikClwindconWTConfig/ikClwindconWTConfig.h (100%) rename {src => CONFIGURATION/CL-Windcon/src}/ikPowman/ikPowman.c (100%) rename {src => CONFIGURATION/CL-Windcon/src}/ikPowman/ikPowman.h (100%) rename {src => CONFIGURATION/CL-Windcon/src}/ikTpman/ikTpman.c (100%) rename {src => CONFIGURATION/CL-Windcon/src}/ikTpman/ikTpman.h (100%) create mode 100644 CONFIGURATION/CL-Windcon/src/sfunc/OpenDiscon_block.mdl create mode 100644 CONFIGURATION/CL-Windcon/src/sfunc/makeOpenDiscon.m create mode 100644 CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 08b2155..3106d51 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,54 +1,11 @@ -cmake_minimum_required (VERSION 3.5.1) +cmake_minimum_required (VERSION 3.0.0) project (OpenDiscon) -# OpenDiscon include directories -set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/src/ikClwindconWTCon/) -set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/src/ikClwindconWTConfig/) -set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/src/ikTpman/) -set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/src/ikPowman/) +# choose a configuration +set( CONFIGURATION "CL-Windcon" CACHE STRING +"Choose a configuration.\n\ +Available configurations are:\n\ +CL-Windcon" ) -# OpenDiscon source files -set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/src/ikTpman/ikTpman.c) -set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/src/ikPowman/ikPowman.c) -set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/src/ikClwindconWTConfig/ikClwindconWTConfig.c) -set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/src/ikClwindconWTCon/ikClwindconWTCon.c) -set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/src/discon/discon.c) - -# OpenWitcon include directories -set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikConLoop) -set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikLinCon) -set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikLutbl) -set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikNotchList) -set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikRegionSelector) -set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikSlti) -set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikStpgen) -set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikTfList) -set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikVfnotch) -set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikIpc) -set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikVector) - -# OpenWitcon source files -set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikConLoop/ikConLoop.c) -set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikLinCon/ikLinCon.c) -set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikLutbl/ikLutbl.c) -set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikNotchList/ikNotchList.c) -set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikRegionSelector/ikRegionSelector.c) -set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikSlti/ikSlti.c) -set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikStpgen/ikStpgen.c) -set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikTfList/ikTfList.c) -set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikVfnotch/ikVfnotch.c) -set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikIpc/ikIpc.c) -set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikVector/ikVector.c) - -# shared OpenDiscon library -include_directories ("${OPENDISCON_INCLUDE_DIRS}") -include_directories ("${OPENWITCON_INCLUDE_DIRS}") -include_directories ("${PROJECT_BINARY_DIR}") -include (GenerateExportHeader) -add_library (OpenDiscon SHARED ${OPENDISCON_SOURCES}) -GENERATE_EXPORT_HEADER (OpenDiscon - BASE_NAME OpenDiscon - EXPORT_MACRO_NAME OpenDiscon_EXPORT - EXPORT_FILE_NAME OpenDiscon_EXPORT.h - STATIC_DEFINE OpenDiscon_BUILT_AS_STATIC -) +# run configuration-specific cmake script +include( ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/CMakeLists.txt ) diff --git a/CONFIGURATION/CL-Windcon/CMakeLists.txt b/CONFIGURATION/CL-Windcon/CMakeLists.txt new file mode 100644 index 0000000..bb9c353 --- /dev/null +++ b/CONFIGURATION/CL-Windcon/CMakeLists.txt @@ -0,0 +1,47 @@ +# choose a distribution +set( DISTRIBUTION "DISCON" CACHE STRING +"Choose a distribution.\n\ +Available distributions are:\n\ +DISCON\n\ +S-Function" ) + +# OpenDiscon include directories +set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconWTCon/) +set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconWTConfig/) +set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikTpman/) +set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikPowman/) + +# OpenDiscon source files +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikTpman/ikTpman.c) +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikPowman/ikPowman.c) +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconWTConfig/ikClwindconWTConfig.c) +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconWTCon/ikClwindconWTCon.c) + +# OpenWitcon include directories +set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikConLoop) +set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikLinCon) +set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikLutbl) +set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikNotchList) +set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikRegionSelector) +set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikSlti) +set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikStpgen) +set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikTfList) +set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikVfnotch) +set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikIpc) +set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikVector) + +# OpenWitcon source files +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikConLoop/ikConLoop.c) +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikLinCon/ikLinCon.c) +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikLutbl/ikLutbl.c) +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikNotchList/ikNotchList.c) +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikRegionSelector/ikRegionSelector.c) +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikSlti/ikSlti.c) +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikStpgen/ikStpgen.c) +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikTfList/ikTfList.c) +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikVfnotch/ikVfnotch.c) +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikIpc/ikIpc.c) +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikVector/ikVector.c) + +# run distribution-specific cmake script +include( ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/DISTRIBUTION/${DISTRIBUTION}/CMakeLists.txt ) diff --git a/CONFIGURATION/CL-Windcon/DISTRIBUTION/DISCON/CMakeLists.txt b/CONFIGURATION/CL-Windcon/DISTRIBUTION/DISCON/CMakeLists.txt new file mode 100644 index 0000000..f170fdc --- /dev/null +++ b/CONFIGURATION/CL-Windcon/DISTRIBUTION/DISCON/CMakeLists.txt @@ -0,0 +1,14 @@ +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/discon/discon.c) + +# shared OpenDiscon library +include_directories ("${OPENDISCON_INCLUDE_DIRS}") +include_directories ("${OPENWITCON_INCLUDE_DIRS}") +include_directories ("${PROJECT_BINARY_DIR}") +include (GenerateExportHeader) +add_library (OpenDiscon SHARED ${OPENDISCON_SOURCES}) +GENERATE_EXPORT_HEADER (OpenDiscon + BASE_NAME OpenDiscon + EXPORT_MACRO_NAME OpenDiscon_EXPORT + EXPORT_FILE_NAME OpenDiscon_EXPORT.h + STATIC_DEFINE OpenDiscon_BUILT_AS_STATIC +) diff --git a/CONFIGURATION/CL-Windcon/DISTRIBUTION/S-Function/CMakeLists.txt b/CONFIGURATION/CL-Windcon/DISTRIBUTION/S-Function/CMakeLists.txt new file mode 100644 index 0000000..7fd08ca --- /dev/null +++ b/CONFIGURATION/CL-Windcon/DISTRIBUTION/S-Function/CMakeLists.txt @@ -0,0 +1,10 @@ +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/sfunc/sfunc.c) + +string (REPLACE ";" " -I" OPENDISCON_INCLUDE_DIRS "${OPENDISCON_INCLUDE_DIRS}") +string (REPLACE ";" " " OPENDISCON_SOURCES "${OPENDISCON_SOURCES}") + +string (REPLACE ";" " -I" OPENWITCON_INCLUDE_DIRS "${OPENWITCON_INCLUDE_DIRS}") +string (REPLACE ";" " " OPENWITCON_SOURCES "${OPENWITCON_SOURCES}") + +configure_file (${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/sfunc/makeOpenDiscon.m ${PROJECT_BINARY_DIR}/) +configure_file (${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/sfunc/OpenDiscon_block.mdl ${PROJECT_BINARY_DIR}/) diff --git a/src/discon/discon.c b/CONFIGURATION/CL-Windcon/src/discon/discon.c similarity index 100% rename from src/discon/discon.c rename to CONFIGURATION/CL-Windcon/src/discon/discon.c diff --git a/src/ikClwindconWTCon/ikClwindconWTCon.c b/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.c similarity index 100% rename from src/ikClwindconWTCon/ikClwindconWTCon.c rename to CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.c diff --git a/src/ikClwindconWTCon/ikClwindconWTCon.h b/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.h similarity index 100% rename from src/ikClwindconWTCon/ikClwindconWTCon.h rename to CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.h diff --git a/src/ikClwindconWTConfig/ikClwindconWTConfig.c b/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c similarity index 100% rename from src/ikClwindconWTConfig/ikClwindconWTConfig.c rename to CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c diff --git a/src/ikClwindconWTConfig/ikClwindconWTConfig.h b/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.h similarity index 100% rename from src/ikClwindconWTConfig/ikClwindconWTConfig.h rename to CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.h diff --git a/src/ikPowman/ikPowman.c b/CONFIGURATION/CL-Windcon/src/ikPowman/ikPowman.c similarity index 100% rename from src/ikPowman/ikPowman.c rename to CONFIGURATION/CL-Windcon/src/ikPowman/ikPowman.c diff --git a/src/ikPowman/ikPowman.h b/CONFIGURATION/CL-Windcon/src/ikPowman/ikPowman.h similarity index 100% rename from src/ikPowman/ikPowman.h rename to CONFIGURATION/CL-Windcon/src/ikPowman/ikPowman.h diff --git a/src/ikTpman/ikTpman.c b/CONFIGURATION/CL-Windcon/src/ikTpman/ikTpman.c similarity index 100% rename from src/ikTpman/ikTpman.c rename to CONFIGURATION/CL-Windcon/src/ikTpman/ikTpman.c diff --git a/src/ikTpman/ikTpman.h b/CONFIGURATION/CL-Windcon/src/ikTpman/ikTpman.h similarity index 100% rename from src/ikTpman/ikTpman.h rename to CONFIGURATION/CL-Windcon/src/ikTpman/ikTpman.h diff --git a/CONFIGURATION/CL-Windcon/src/sfunc/OpenDiscon_block.mdl b/CONFIGURATION/CL-Windcon/src/sfunc/OpenDiscon_block.mdl new file mode 100644 index 0000000..bffa8ce --- /dev/null +++ b/CONFIGURATION/CL-Windcon/src/sfunc/OpenDiscon_block.mdl @@ -0,0 +1,1147 @@ +Model { + Name "OpenDiscon_block" + Version 8.3 + MdlSubVersion 0 + SavedCharacterEncoding "windows-1252" + GraphicalInterface { + NumRootInports 0 + NumRootOutports 0 + ParameterArgumentNames "" + ComputedModelVersion "1.6" + NumModelReferences 0 + NumTestPointedSignals 0 + } + SaveDefaultBlockParams on + ScopeRefreshTime 0.035000 + OverrideScopeRefreshTime on + DisableAllScopes off + DataTypeOverride "UseLocalSettings" + DataTypeOverrideAppliesTo "AllNumericTypes" + MinMaxOverflowLogging "UseLocalSettings" + MinMaxOverflowArchiveMode "Overwrite" + FPTRunName "Run 1" + MaxMDLFileLineLength 120 + Object { + $PropName "BdWindowsInfo" + $ObjectID 1 + $ClassName "Simulink.BDWindowsInfo" + Object { + $PropName "WindowsInfo" + $ObjectID 2 + $ClassName "Simulink.WindowInfo" + IsActive [1] + Location [750.0, 130.0, 800.0, 713.0] + Object { + $PropName "ModelBrowserInfo" + $ObjectID 3 + $ClassName "Simulink.ModelBrowserInfo" + Visible [0] + DockPosition "Left" + Width [50] + Height [50] + Filter [9] + } + Object { + $PropName "ExplorerBarInfo" + $ObjectID 4 + $ClassName "Simulink.ExplorerBarInfo" + Visible [1] + } + Object { + $PropName "EditorsInfo" + $ObjectID 5 + $ClassName "Simulink.EditorInfo" + IsActive [1] + ViewObjType "SimulinkTopLevel" + LoadSaveID "0" + Extents [750.0, 538.0] + ZoomFactor [1.0] + Offset [-18.600000000000136, 77.6500011026859] + } + } + } + Created "Mon Dec 18 14:05:42 2017" + Creator "ielorza" + UpdateHistory "UpdateHistoryNever" + ModifiedByFormat "%" + LastModifiedBy "ielorza" + ModifiedDateFormat "%" + LastModifiedDate "Mon Dec 18 14:51:22 2017" + RTWModifiedTimeStamp 435509080 + ModelVersionFormat "1.%" + ConfigurationManager "none" + SampleTimeColors off + SampleTimeAnnotations off + LibraryLinkDisplay "disabled" + WideLines off + ShowLineDimensions off + ShowPortDataTypes off + ShowDesignRanges off + ShowLoopsOnError on + IgnoreBidirectionalLines off + ShowStorageClass off + ShowTestPointIcons on + ShowSignalResolutionIcons on + ShowViewerIcons on + SortedOrder off + ExecutionContextIcon off + ShowLinearizationAnnotations on + BlockNameDataTip off + BlockParametersDataTip off + BlockDescriptionStringDataTip off + ToolBar on + StatusBar on + BrowserShowLibraryLinks off + BrowserLookUnderMasks off + SimulationMode "normal" + PauseTimes "5" + NumberOfSteps 1 + SnapshotBufferSize 10 + SnapshotInterval 10 + NumberOfLastSnapshots 0 + LinearizationMsg "none" + Profile off + ParamWorkspaceSource "MATLABWorkspace" + AccelSystemTargetFile "accel.tlc" + AccelTemplateMakefile "accel_default_tmf" + AccelMakeCommand "make_rtw" + TryForcingSFcnDF off + Object { + $PropName "DataLoggingOverride" + $ObjectID 6 + $ClassName "Simulink.SimulationData.ModelLoggingInfo" + model_ "OpenDiscon_block" + overrideMode_ [0.0] + Array { + Type "Cell" + Dimension 1 + Cell "OpenDiscon_block" + PropName "logAsSpecifiedByModels_" + } + Array { + Type "Cell" + Dimension 1 + Cell [] + PropName "logAsSpecifiedByModelsSSIDs_" + } + } + RecordCoverage off + CovPath "/" + CovSaveName "covdata" + CovMetricSettings "dw" + CovNameIncrementing off + CovHtmlReporting on + CovForceBlockReductionOff on + CovEnableCumulative on + covSaveCumulativeToWorkspaceVar on + CovSaveSingleToWorkspaceVar on + CovCumulativeVarName "covCumulativeData" + CovCumulativeReport off + CovReportOnPause on + CovModelRefEnable "Off" + CovExternalEMLEnable off + CovSFcnEnable off + CovBoundaryAbsTol 0.000010 + CovBoundaryRelTol 0.010000 + ExtModeBatchMode off + ExtModeEnableFloating on + ExtModeTrigType "manual" + ExtModeTrigMode "normal" + ExtModeTrigPort "1" + ExtModeTrigElement "any" + ExtModeTrigDuration 1000 + ExtModeTrigDurationFloating "auto" + ExtModeTrigHoldOff 0 + ExtModeTrigDelay 0 + ExtModeTrigDirection "rising" + ExtModeTrigLevel 0 + ExtModeArchiveMode "off" + ExtModeAutoIncOneShot off + ExtModeIncDirWhenArm off + ExtModeAddSuffixToVar off + ExtModeWriteAllDataToWs off + ExtModeArmWhenConnect on + ExtModeSkipDownloadWhenConnect off + ExtModeLogAll on + ExtModeAutoUpdateStatusClock on + BufferReuse on + ShowModelReferenceBlockVersion off + ShowModelReferenceBlockIO off + Array { + Type "Handle" + Dimension 1 + Simulink.ConfigSet { + $ObjectID 7 + Version "1.14.2" + Array { + Type "Handle" + Dimension 9 + Simulink.SolverCC { + $ObjectID 8 + Version "1.14.2" + StartTime "0.0" + StopTime "10.0" + AbsTol "auto" + FixedStep "auto" + InitialStep "auto" + MaxNumMinSteps "-1" + MaxOrder 5 + ZcThreshold "auto" + ConsecutiveZCsStepRelTol "10*128*eps" + MaxConsecutiveZCs "1000" + ExtrapolationOrder 4 + NumberNewtonIterations 1 + MaxStep "auto" + MinStep "auto" + MaxConsecutiveMinStep "1" + RelTol "1e-3" + SolverMode "Auto" + EnableConcurrentExecution off + ConcurrentTasks off + Solver "ode45" + SolverName "ode45" + SolverJacobianMethodControl "auto" + ShapePreserveControl "DisableAll" + ZeroCrossControl "UseLocalSettings" + ZeroCrossAlgorithm "Nonadaptive" + AlgebraicLoopSolver "TrustRegion" + SolverResetMethod "Fast" + PositivePriorityOrder off + AutoInsertRateTranBlk off + SampleTimeConstraint "Unconstrained" + InsertRTBMode "Whenever possible" + } + Simulink.DataIOCC { + $ObjectID 9 + Version "1.14.2" + Decimation "1" + ExternalInput "[t, u]" + FinalStateName "xFinal" + InitialState "xInitial" + LimitDataPoints on + MaxDataPoints "1000" + LoadExternalInput off + LoadInitialState off + SaveFinalState off + SaveCompleteFinalSimState off + SaveFormat "Array" + SignalLoggingSaveFormat "Dataset" + SaveOutput on + SaveState off + SignalLogging on + DSMLogging on + InspectSignalLogs off + VisualizeSimOutput on + SaveTime on + ReturnWorkspaceOutputs off + StateSaveName "xout" + TimeSaveName "tout" + OutputSaveName "yout" + SignalLoggingName "logsout" + DSMLoggingName "dsmout" + OutputOption "RefineOutputTimes" + OutputTimes "[]" + ReturnWorkspaceOutputsName "out" + Refine "1" + } + Simulink.OptimizationCC { + $ObjectID 10 + Version "1.14.2" + Array { + Type "Cell" + Dimension 8 + Cell "BooleansAsBitfields" + Cell "PassReuseOutputArgsAs" + Cell "PassReuseOutputArgsThreshold" + Cell "ZeroExternalMemoryAtStartup" + Cell "ZeroInternalMemoryAtStartup" + Cell "OptimizeModelRefInitCode" + Cell "NoFixptDivByZeroProtection" + Cell "UseSpecifiedMinMax" + PropName "DisabledProps" + } + BlockReduction on + BooleanDataType on + ConditionallyExecuteInputs on + InlineParams off + UseIntDivNetSlope off + UseFloatMulNetSlope off + DefaultUnderspecifiedDataType "double" + UseSpecifiedMinMax off + InlineInvariantSignals off + OptimizeBlockIOStorage on + BufferReuse on + EnhancedBackFolding off + CachingGlobalReferences off + GlobalBufferReuse on + StrengthReduction off + ExpressionFolding on + BooleansAsBitfields off + BitfieldContainerType "uint_T" + EnableMemcpy on + MemcpyThreshold 64 + PassReuseOutputArgsAs "Structure reference" + ExpressionDepthLimit 128 + FoldNonRolledExpr on + LocalBlockOutputs on + RollThreshold 5 + SystemCodeInlineAuto off + StateBitsets off + DataBitsets off + ActiveStateOutputEnumStorageType "Native Integer" + UseTempVars off + ZeroExternalMemoryAtStartup on + ZeroInternalMemoryAtStartup on + InitFltsAndDblsToZero off + NoFixptDivByZeroProtection off + EfficientFloat2IntCast off + EfficientMapNaN2IntZero on + OptimizeModelRefInitCode off + LifeSpan "inf" + MaxStackSize "Inherit from target" + BufferReusableBoundary on + SimCompilerOptimization "Off" + AccelVerboseBuild off + ParallelExecutionInRapidAccelerator on + } + Simulink.DebuggingCC { + $ObjectID 11 + Version "1.14.2" + RTPrefix "error" + ConsistencyChecking "none" + ArrayBoundsChecking "none" + SignalInfNanChecking "none" + SignalRangeChecking "none" + ReadBeforeWriteMsg "UseLocalSettings" + WriteAfterWriteMsg "UseLocalSettings" + WriteAfterReadMsg "UseLocalSettings" + AlgebraicLoopMsg "warning" + ArtificialAlgebraicLoopMsg "warning" + SaveWithDisabledLinksMsg "warning" + SaveWithParameterizedLinksMsg "warning" + CheckSSInitialOutputMsg on + UnderspecifiedInitializationDetection "Simplified" + MergeDetectMultiDrivingBlocksExec "none" + CheckExecutionContextPreStartOutputMsg off + CheckExecutionContextRuntimeOutputMsg off + SignalResolutionControl "UseLocalSettings" + BlockPriorityViolationMsg "warning" + MinStepSizeMsg "warning" + TimeAdjustmentMsg "none" + MaxConsecutiveZCsMsg "error" + MaskedZcDiagnostic "warning" + IgnoredZcDiagnostic "warning" + SolverPrmCheckMsg "warning" + InheritedTsInSrcMsg "warning" + DiscreteInheritContinuousMsg "warning" + MultiTaskDSMMsg "error" + MultiTaskCondExecSysMsg "error" + MultiTaskRateTransMsg "error" + SingleTaskRateTransMsg "none" + TasksWithSamePriorityMsg "warning" + SigSpecEnsureSampleTimeMsg "warning" + CheckMatrixSingularityMsg "none" + IntegerOverflowMsg "warning" + Int32ToFloatConvMsg "warning" + ParameterDowncastMsg "error" + ParameterOverflowMsg "error" + ParameterUnderflowMsg "none" + ParameterPrecisionLossMsg "warning" + ParameterTunabilityLossMsg "warning" + FixptConstUnderflowMsg "none" + FixptConstOverflowMsg "none" + FixptConstPrecisionLossMsg "none" + UnderSpecifiedDataTypeMsg "none" + UnnecessaryDatatypeConvMsg "none" + VectorMatrixConversionMsg "none" + InvalidFcnCallConnMsg "error" + FcnCallInpInsideContextMsg "EnableAllAsError" + SignalLabelMismatchMsg "none" + UnconnectedInputMsg "warning" + UnconnectedOutputMsg "warning" + UnconnectedLineMsg "warning" + SFcnCompatibilityMsg "none" + FrameProcessingCompatibilityMsg "warning" + UniqueDataStoreMsg "none" + BusObjectLabelMismatch "warning" + RootOutportRequireBusObject "warning" + AssertControl "UseLocalSettings" + EnableOverflowDetection off + ModelReferenceIOMsg "none" + ModelReferenceMultiInstanceNormalModeStructChecksumCheck "error" + ModelReferenceVersionMismatchMessage "none" + ModelReferenceIOMismatchMessage "none" + ModelReferenceCSMismatchMessage "none" + UnknownTsInhSupMsg "warning" + ModelReferenceDataLoggingMessage "warning" + ModelReferenceSymbolNameMessage "warning" + ModelReferenceExtraNoncontSigs "error" + StateNameClashWarn "none" + SimStateInterfaceChecksumMismatchMsg "warning" + SimStateOlderReleaseMsg "error" + InitInArrayFormatMsg "warning" + StrictBusMsg "ErrorLevel1" + BusNameAdapt "WarnAndRepair" + NonBusSignalsTreatedAsBus "none" + LoggingUnavailableSignals "error" + BlockIODiagnostic "none" + SFUnusedDataAndEventsDiag "warning" + SFUnexpectedBacktrackingDiag "warning" + SFInvalidInputDataAccessInChartInitDiag "warning" + SFNoUnconditionalDefaultTransitionDiag "warning" + SFTransitionOutsideNaturalParentDiag "warning" + SFUnconditionalTransitionShadowingDiag "warning" + SFUndirectedBroadcastEventsDiag "warning" + SFTransitionActionBeforeConditionDiag "warning" + } + Simulink.HardwareCC { + $ObjectID 12 + Version "1.14.2" + ProdBitPerChar 8 + ProdBitPerShort 16 + ProdBitPerInt 32 + ProdBitPerLong 32 + ProdBitPerLongLong 64 + ProdBitPerFloat 32 + ProdBitPerDouble 64 + ProdBitPerPointer 32 + ProdLargestAtomicInteger "Char" + ProdLargestAtomicFloat "None" + ProdIntDivRoundTo "Undefined" + ProdEndianess "Unspecified" + ProdWordSize 32 + ProdShiftRightIntArith on + ProdLongLongMode off + ProdHWDeviceType "32-bit Generic" + TargetBitPerChar 8 + TargetBitPerShort 16 + TargetBitPerInt 32 + TargetBitPerLong 32 + TargetBitPerLongLong 64 + TargetBitPerFloat 32 + TargetBitPerDouble 64 + TargetBitPerPointer 32 + TargetLargestAtomicInteger "Char" + TargetLargestAtomicFloat "None" + TargetShiftRightIntArith on + TargetLongLongMode off + TargetIntDivRoundTo "Undefined" + TargetEndianess "Unspecified" + TargetWordSize 32 + TargetTypeEmulationWarnSuppressLevel 0 + TargetPreprocMaxBitsSint 32 + TargetPreprocMaxBitsUint 32 + TargetHWDeviceType "Specified" + TargetUnknown off + ProdEqTarget on + } + Simulink.ModelReferenceCC { + $ObjectID 13 + Version "1.14.2" + UpdateModelReferenceTargets "IfOutOfDateOrStructuralChange" + CheckModelReferenceTargetMessage "error" + EnableParallelModelReferenceBuilds off + ParallelModelReferenceErrorOnInvalidPool on + ParallelModelReferenceMATLABWorkerInit "None" + ModelReferenceNumInstancesAllowed "Multi" + PropagateVarSize "Infer from blocks in model" + ModelReferencePassRootInputsByReference on + ModelReferenceMinAlgLoopOccurrences off + PropagateSignalLabelsOutOfModel off + SupportModelReferenceSimTargetCustomCode off + } + Simulink.SFSimCC { + $ObjectID 14 + Version "1.14.2" + SFSimEnableDebug on + SFSimOverflowDetection on + SFSimEcho on + SimBlas on + SimCtrlC on + SimExtrinsic on + SimIntegrity on + SimUseLocalCustomCode off + SimParseCustomCode on + SimBuildMode "sf_incremental_build" + SimGenImportedTypeDefs off + } + Simulink.RTWCC { + $BackupClass "Simulink.RTWCC" + $ObjectID 15 + Version "1.14.2" + Array { + Type "Cell" + Dimension 15 + Cell "IncludeHyperlinkInReport" + Cell "GenerateTraceInfo" + Cell "GenerateTraceReport" + Cell "GenerateTraceReportSl" + Cell "GenerateTraceReportSf" + Cell "GenerateTraceReportEml" + Cell "PortableWordSizes" + Cell "GenerateWebview" + Cell "GenerateCodeMetricsReport" + Cell "GenerateCodeReplacementReport" + Cell "GenerateErtSFunction" + Cell "CreateSILPILBlock" + Cell "CodeExecutionProfiling" + Cell "CodeProfilingSaveOptions" + Cell "CodeProfilingInstrumentation" + PropName "DisabledProps" + } + SystemTargetFile "grt.tlc" + TLCOptions "" + GenCodeOnly off + MakeCommand "make_rtw" + GenerateMakefile on + PackageGeneratedCodeAndArtifacts off + PackageName "" + TemplateMakefile "grt_default_tmf" + PostCodeGenCommand "" + Description "" + GenerateReport off + SaveLog off + RTWVerbose on + RetainRTWFile off + ProfileTLC off + TLCDebug off + TLCCoverage off + TLCAssert off + ProcessScriptMode "Default" + ConfigurationMode "Optimized" + ProcessScript "" + ConfigurationScript "" + ConfigAtBuild off + RTWUseLocalCustomCode off + RTWUseSimCustomCode off + CustomSourceCode "" + CustomHeaderCode "" + CustomInclude "" + CustomSource "" + CustomLibrary "" + CustomInitializer "" + CustomTerminator "" + Toolchain "Automatically locate an installed toolchain" + BuildConfiguration "Faster Builds" + IncludeHyperlinkInReport off + LaunchReport off + PortableWordSizes off + CreateSILPILBlock "None" + CodeExecutionProfiling off + CodeExecutionProfileVariable "executionProfile" + CodeProfilingSaveOptions "SummaryOnly" + CodeProfilingInstrumentation off + SILDebugging off + TargetLang "C" + IncludeBusHierarchyInRTWFileBlockHierarchyMap off + IncludeERTFirstTime off + GenerateTraceInfo off + GenerateTraceReport off + GenerateTraceReportSl off + GenerateTraceReportSf off + GenerateTraceReportEml off + GenerateCodeInfo off + GenerateWebview off + GenerateCodeMetricsReport off + GenerateCodeReplacementReport off + RTWCompilerOptimization "Off" + RTWCustomCompilerOptimizations "" + CheckMdlBeforeBuild "Off" + CustomRebuildMode "OnUpdate" + DataInitializer "" + SharedConstantsCachingThreshold 1024 + Array { + Type "Handle" + Dimension 2 + Simulink.CodeAppCC { + $ObjectID 16 + Version "1.14.2" + Array { + Type "Cell" + Dimension 23 + Cell "IgnoreCustomStorageClasses" + Cell "IgnoreTestpoints" + Cell "InsertBlockDesc" + Cell "InsertPolySpaceComments" + Cell "SFDataObjDesc" + Cell "MATLABFcnDesc" + Cell "SimulinkDataObjDesc" + Cell "DefineNamingRule" + Cell "SignalNamingRule" + Cell "ParamNamingRule" + Cell "InternalIdentifier" + Cell "InlinedPrmAccess" + Cell "CustomSymbolStr" + Cell "CustomSymbolStrGlobalVar" + Cell "CustomSymbolStrType" + Cell "CustomSymbolStrField" + Cell "CustomSymbolStrFcn" + Cell "CustomSymbolStrFcnArg" + Cell "CustomSymbolStrBlkIO" + Cell "CustomSymbolStrTmpVar" + Cell "CustomSymbolStrMacro" + Cell "CustomSymbolStrUtil" + Cell "ReqsInCode" + PropName "DisabledProps" + } + ForceParamTrailComments off + GenerateComments on + CommentStyle "Auto" + IgnoreCustomStorageClasses on + IgnoreTestpoints off + IncHierarchyInIds off + MaxIdLength 31 + PreserveName off + PreserveNameWithParent off + ShowEliminatedStatement off + OperatorAnnotations off + IncAutoGenComments off + SimulinkDataObjDesc off + SFDataObjDesc off + MATLABFcnDesc off + IncDataTypeInIds off + MangleLength 1 + CustomSymbolStrGlobalVar "$R$N$M" + CustomSymbolStrType "$N$R$M_T" + CustomSymbolStrField "$N$M" + CustomSymbolStrFcn "$R$N$M$F" + CustomSymbolStrFcnArg "rt$I$N$M" + CustomSymbolStrBlkIO "rtb_$N$M" + CustomSymbolStrTmpVar "$N$M" + CustomSymbolStrMacro "$R$N$M" + CustomSymbolStrUtil "$N$C" + DefineNamingRule "None" + ParamNamingRule "None" + SignalNamingRule "None" + InsertBlockDesc off + InsertPolySpaceComments off + SimulinkBlockComments on + MATLABSourceComments off + EnableCustomComments off + InternalIdentifier "Shortened" + InlinedPrmAccess "Literals" + ReqsInCode off + UseSimReservedNames off + } + Simulink.GRTTargetCC { + $BackupClass "Simulink.TargetCC" + $ObjectID 17 + Version "1.14.2" + Array { + Type "Cell" + Dimension 14 + Cell "GeneratePreprocessorConditionals" + Cell "IncludeMdlTerminateFcn" + Cell "CombineOutputUpdateFcns" + Cell "SuppressErrorStatus" + Cell "ERTCustomFileBanners" + Cell "GenerateSampleERTMain" + Cell "GenerateTestInterfaces" + Cell "ModelStepFunctionPrototypeControlCompliant" + Cell "GenerateAllocFcn" + Cell "PurelyIntegerCode" + Cell "SupportComplex" + Cell "SupportAbsoluteTime" + Cell "SupportContinuousTime" + Cell "SupportNonInlinedSFcns" + PropName "DisabledProps" + } + TargetFcnLib "ansi_tfl_table_tmw.mat" + TargetLibSuffix "" + TargetPreCompLibLocation "" + GenFloatMathFcnCalls "NOT IN USE" + TargetLangStandard "C89/C90 (ANSI)" + CodeReplacementLibrary "None" + UtilityFuncGeneration "Auto" + ERTMultiwordTypeDef "System defined" + ERTMultiwordLength 256 + MultiwordLength 2048 + GenerateFullHeader on + GenerateSampleERTMain off + GenerateTestInterfaces off + ModelReferenceCompliant on + ParMdlRefBuildCompliant on + CompOptLevelCompliant on + ConcurrentExecutionCompliant on + IncludeMdlTerminateFcn on + GeneratePreprocessorConditionals "Disable all" + CombineOutputUpdateFcns on + CombineSignalStateStructs off + SuppressErrorStatus off + ERTFirstTimeCompliant off + IncludeFileDelimiter "Auto" + ERTCustomFileBanners off + SupportAbsoluteTime on + LogVarNameModifier "rt_" + MatFileLogging on + MultiInstanceERTCode off + CodeInterfacePackaging "Nonreusable function" + SupportNonFinite on + SupportComplex on + PurelyIntegerCode off + SupportContinuousTime on + SupportNonInlinedSFcns on + SupportVariableSizeSignals off + EnableShiftOperators on + ParenthesesLevel "Nominal" + MATLABClassNameForMDSCustomization "Simulink.SoftwareTarget.GRTCustomization" + ModelStepFunctionPrototypeControlCompliant off + CPPClassGenCompliant on + AutosarCompliant off + GRTInterface off + GenerateAllocFcn off + UseMalloc off + ExtMode off + ExtModeStaticAlloc off + ExtModeTesting off + ExtModeStaticAllocSize 1000000 + ExtModeTransport 0 + ExtModeMexFile "ext_comm" + ExtModeIntrfLevel "Level1" + RTWCAPISignals off + RTWCAPIParams off + RTWCAPIStates off + RTWCAPIRootIO off + GenerateASAP2 off + MultiInstanceErrorCode "Error" + } + PropName "Components" + } + } + hdlcoderui.hdlcc { + $ObjectID 18 + Version "1.14.2" + Description "HDL Coder custom configuration component" + Name "HDL Coder" + Array { + Type "Cell" + Dimension 1 + Cell " " + PropName "HDLConfigFile" + } + HDLCActiveTab "0" + } + PropName "Components" + } + Name "Configuration" + CurrentDlgPage "Solver" + ConfigPrmDlgPosition [ 420, 220, 1500, 860 ] + } + PropName "ConfigurationSets" + } + Simulink.ConfigSet { + $PropName "ActiveConfigurationSet" + $ObjectID 7 + } + Object { + $PropName "DataTransfer" + $ObjectID 19 + $ClassName "Simulink.GlobalDataTransfer" + DefaultTransitionBetweenSyncTasks "Ensure deterministic transfer (maximum delay)" + DefaultTransitionBetweenAsyncTasks "Ensure data integrity only" + DefaultTransitionBetweenContTasks "Ensure deterministic transfer (minimum delay)" + DefaultExtrapolationMethodBetweenContTasks "None" + AutoInsertRateTranBlk [0] + } + ExplicitPartitioning off + BlockDefaults { + ForegroundColor "black" + BackgroundColor "white" + DropShadow off + NamePlacement "normal" + FontName "Helvetica" + FontSize 10 + FontWeight "normal" + FontAngle "normal" + ShowName on + BlockRotation 0 + BlockMirror off + } + AnnotationDefaults { + HorizontalAlignment "center" + VerticalAlignment "middle" + ForegroundColor "black" + BackgroundColor "white" + DropShadow off + FontName "Helvetica" + FontSize 10 + FontWeight "normal" + FontAngle "normal" + UseDisplayTextAsClickCallback off + } + LineDefaults { + FontName "Helvetica" + FontSize 9 + FontWeight "normal" + FontAngle "normal" + } + MaskDefaults { + SelfModifiable "off" + IconFrame "on" + IconOpaque "on" + RunInitForIconRedraw "off" + IconRotate "none" + PortRotate "default" + IconUnits "autoscale" + } + MaskParameterDefaults { + Evaluate "on" + Tunable "on" + NeverSave "off" + Internal "off" + ReadOnly "off" + Enabled "on" + Visible "on" + ToolTip "on" + } + BlockParameterDefaults { + Block { + BlockType Inport + Port "1" + OutputFunctionCall off + OutMin "[]" + OutMax "[]" + OutDataTypeStr "Inherit: auto" + LockScale off + BusOutputAsStruct off + PortDimensions "-1" + VarSizeSig "Inherit" + SampleTime "-1" + SignalType "auto" + SamplingMode "auto" + LatchByDelayingOutsideSignal off + LatchInputForFeedbackSignals off + Interpolate on + } + Block { + BlockType Outport + Port "1" + OutMin "[]" + OutMax "[]" + OutDataTypeStr "Inherit: auto" + LockScale off + BusOutputAsStruct off + PortDimensions "-1" + VarSizeSig "Inherit" + SampleTime "-1" + SignalType "auto" + SamplingMode "auto" + SourceOfInitialOutputValue "Dialog" + OutputWhenDisabled "held" + InitialOutput "[]" + } + Block { + BlockType S-Function + FunctionName "system" + SFunctionModules "''" + PortCounts "[]" + SFunctionDeploymentMode off + } + Block { + BlockType SubSystem + ShowPortLabels "FromPortIcon" + Permissions "ReadWrite" + PermitHierarchicalResolution "All" + TreatAsAtomicUnit off + MinAlgLoopOccurrences off + PropExecContextOutsideSubsystem off + CheckFcnCallInpInsideContextMsg off + SystemSampleTime "-1" + RTWSystemCode "Auto" + RTWFcnNameOpts "Auto" + RTWFileNameOpts "Auto" + FunctionInterfaceSpec "void_void" + FunctionWithSeparateData off + RTWMemSecFuncInitTerm "Inherit from model" + RTWMemSecFuncExecute "Inherit from model" + RTWMemSecDataConstants "Inherit from model" + RTWMemSecDataInternal "Inherit from model" + RTWMemSecDataParameters "Inherit from model" + SimViewingDevice off + DataTypeOverride "UseLocalSettings" + DataTypeOverrideAppliesTo "AllNumericTypes" + MinMaxOverflowLogging "UseLocalSettings" + Opaque off + MaskHideContents off + SFBlockType "NONE" + Variant off + GeneratePreprocessorConditionals off + ContentPreviewEnabled off + } + } + System { + Name "OpenDiscon_block" + Location [750, 130, 1550, 843] + Open on + ModelBrowserVisibility off + ModelBrowserWidth 200 + ScreenColor "white" + PaperOrientation "landscape" + PaperPositionMode "auto" + PaperType "A4" + PaperUnits "centimeters" + TiledPaperMargins [1.270000, 1.270000, 1.270000, 1.270000] + TiledPageScale 1 + ShowPageBoundaries off + ZoomFactor "100" + ReportName "simulink-default.rpt" + SIDHighWatermark "16" + Block { + BlockType SubSystem + Name "OpenDiscon" + SID "2" + Ports [10, 4] + Position [105, 101, 440, 499] + ZOrder 2 + RequestExecContextInheritance off + System { + Name "OpenDiscon" + Location [750, 130, 1550, 843] + Open off + ModelBrowserVisibility off + ModelBrowserWidth 200 + ScreenColor "white" + PaperOrientation "landscape" + PaperPositionMode "auto" + PaperType "A4" + PaperUnits "centimeters" + TiledPaperMargins [1.270000, 1.270000, 1.270000, 1.270000] + TiledPageScale 1 + ShowPageBoundaries off + ZoomFactor "100" + Block { + BlockType Inport + Name "derating ratio [-]" + SID "3" + Position [20, 38, 50, 52] + ZOrder 2 + IconDisplay "Port number" + } + Block { + BlockType Inport + Name "generator speed [rad/s]" + SID "4" + Position [20, 68, 50, 82] + ZOrder 3 + Port "2" + IconDisplay "Port number" + } + Block { + BlockType Inport + Name "azimuth [deg]" + SID "5" + Position [20, 98, 50, 112] + ZOrder 4 + Port "3" + IconDisplay "Port number" + } + Block { + BlockType Inport + Name "yaw error [deg]" + SID "6" + Position [20, 128, 50, 142] + ZOrder 5 + Port "4" + IconDisplay "Port number" + } + Block { + BlockType Inport + Name "blade 1 root Mx [kNm]" + SID "7" + Position [20, 158, 50, 172] + ZOrder 6 + Port "5" + IconDisplay "Port number" + } + Block { + BlockType Inport + Name "blade 1 root My [kNm]" + SID "8" + Position [20, 188, 50, 202] + ZOrder 7 + Port "6" + IconDisplay "Port number" + } + Block { + BlockType Inport + Name "blade 2 root Mx [kNm]" + SID "9" + Position [20, 218, 50, 232] + ZOrder 8 + Port "7" + IconDisplay "Port number" + } + Block { + BlockType Inport + Name "blade 2 root My [kNm]" + SID "10" + Position [20, 248, 50, 262] + ZOrder 9 + Port "8" + IconDisplay "Port number" + } + Block { + BlockType Inport + Name "blade 3 root Mx [kNm]" + SID "11" + Position [20, 278, 50, 292] + ZOrder 10 + Port "9" + IconDisplay "Port number" + } + Block { + BlockType Inport + Name "blade 3 root My [kNm]" + SID "12" + Position [20, 308, 50, 322] + ZOrder 11 + Port "10" + IconDisplay "Port number" + } + Block { + BlockType S-Function + Name "S-Function" + SID "1" + Ports [10, 4] + Position [165, 20, 305, 340] + ZOrder 1 + FunctionName "OpenDiscon" + EnableBusSupport off + } + Block { + BlockType Outport + Name "generator torque demand [kNm]" + SID "13" + Position [395, 53, 425, 67] + ZOrder 12 + IconDisplay "Port number" + } + Block { + BlockType Outport + Name "blade 1 pitch demand [deg]" + SID "14" + Position [395, 133, 425, 147] + ZOrder 13 + Port "2" + IconDisplay "Port number" + } + Block { + BlockType Outport + Name "blade 2 pitch demand [deg]" + SID "15" + Position [395, 213, 425, 227] + ZOrder 14 + Port "3" + IconDisplay "Port number" + } + Block { + BlockType Outport + Name "blade 3 pitch demand [deg]" + SID "16" + Position [395, 293, 425, 307] + ZOrder 15 + Port "4" + IconDisplay "Port number" + } + Line { + ZOrder 15 + SrcBlock "derating ratio [-]" + SrcPort 1 + DstBlock "S-Function" + DstPort 1 + } + Line { + ZOrder 17 + SrcBlock "azimuth [deg]" + SrcPort 1 + DstBlock "S-Function" + DstPort 3 + } + Line { + ZOrder 22 + SrcBlock "blade 2 root My [kNm]" + SrcPort 1 + DstBlock "S-Function" + DstPort 8 + } + Line { + ZOrder 23 + SrcBlock "blade 3 root Mx [kNm]" + SrcPort 1 + DstBlock "S-Function" + DstPort 9 + } + Line { + ZOrder 18 + SrcBlock "yaw error [deg]" + SrcPort 1 + DstBlock "S-Function" + DstPort 4 + } + Line { + ZOrder 19 + SrcBlock "blade 1 root Mx [kNm]" + SrcPort 1 + DstBlock "S-Function" + DstPort 5 + } + Line { + ZOrder 20 + SrcBlock "blade 1 root My [kNm]" + SrcPort 1 + DstBlock "S-Function" + DstPort 6 + } + Line { + ZOrder 21 + SrcBlock "blade 2 root Mx [kNm]" + SrcPort 1 + DstBlock "S-Function" + DstPort 7 + } + Line { + ZOrder 16 + SrcBlock "generator speed [rad/s]" + SrcPort 1 + DstBlock "S-Function" + DstPort 2 + } + Line { + ZOrder 24 + SrcBlock "blade 3 root My [kNm]" + SrcPort 1 + DstBlock "S-Function" + DstPort 10 + } + Line { + ZOrder 28 + SrcBlock "S-Function" + SrcPort 4 + DstBlock "blade 3 pitch demand [deg]" + DstPort 1 + } + Line { + ZOrder 27 + SrcBlock "S-Function" + SrcPort 3 + DstBlock "blade 2 pitch demand [deg]" + DstPort 1 + } + Line { + ZOrder 26 + SrcBlock "S-Function" + SrcPort 2 + DstBlock "blade 1 pitch demand [deg]" + DstPort 1 + } + Line { + ZOrder 29 + SrcBlock "S-Function" + SrcPort 1 + DstBlock "generator torque demand [kNm]" + DstPort 1 + } + } + } + } +} diff --git a/CONFIGURATION/CL-Windcon/src/sfunc/makeOpenDiscon.m b/CONFIGURATION/CL-Windcon/src/sfunc/makeOpenDiscon.m new file mode 100644 index 0000000..15c87bc --- /dev/null +++ b/CONFIGURATION/CL-Windcon/src/sfunc/makeOpenDiscon.m @@ -0,0 +1,3 @@ +function makeOpenDiscon + +mex -output OpenDiscon -I${OPENWITCON_INCLUDE_DIRS} -I${OPENDISCON_INCLUDE_DIRS} ${OPENWITCON_SOURCES} ${OPENDISCON_SOURCES} diff --git a/CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c b/CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c new file mode 100644 index 0000000..215c09e --- /dev/null +++ b/CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c @@ -0,0 +1,1602 @@ +/* +Copyright (C) 2015-2017 IK4-IKERLAN + +This file is part of OpenDiscon. + +OpenDiscon is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +OpenDiscon is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenDiscon. If not, see . +*/ + +/* + * This file is based on the following template: + * File: sfuntmpl_doc.c + * Abstract: + * A 'C' template for a level 2 S-function. + * + * See sfuntmpl_basic.c + * for a basic C-MEX template file that uses the + * most common methods. + * + * Copyright 1990-2013 The MathWorks, Inc. + */ + + +/* + * You must specify the S_FUNCTION_NAME as the name of your S-function. + */ + +#define S_FUNCTION_NAME OpenDiscon +#define S_FUNCTION_LEVEL 2 + +#include "ikClwindconWTConfig.h" + +/* + * Need to include simstruc.h for the definition of the SimStruct and + * its associated macro definitions. + * + * The following headers are included by matlabroot/simulink/include/simstruc.h + * when compiling as a MEX file: + * + * matlabroot/extern/include/tmwtypes.h - General types, e.g. real_T + * matlabroot/extern/include/mex.h - MATLAB MEX file API routines + * matlabroot/extern/include/matrix.h - MATLAB MEX file API routines + * + * The following headers are included by matlabroot/simulink/include/simstruc.h + * when compiling your S-function with RTW: + * + * matlabroot/extern/include/tmwtypes.h - General types, e.g. real_T + * matlabroot/rtw/c/libsrc/rt_matrx.h - Macros for MATLAB API routines + * + */ +#include "simstruc.h" + + +/* Error handling + * -------------- + * + * You should use the following technique to report errors encountered within + * an S-function: + * + * ssSetErrorStatus(S,"error encountered due to ..."); + * return; + * + * Note that the 2nd argument to ssSetErrorStatus must be persistent memory. + * It cannot be a local variable in your procedure. For example the following + * will cause unpredictable errors: + * + * mdlOutputs() + * { + * char msg[256]; {ILLEGAL: to fix use "static char msg[256];"} + * sprintf(msg,"Error due to %s", string); + * ssSetErrorStatus(S,msg); + * return; + * } + * + * The ssSetErrorStatus error handling approach is the suggested alternative + * to using the mexErrMsgTxt function. MexErrMsgTxt uses "exception handling" + * to immediately terminate S-function execution and return control to + * Simulink. In order to support exception handling inside of S-functions, + * Simulink must setup exception handlers prior to each S-function invocation. + * This introduces overhead into simulation. + * + * If you do not call mexErrMsgTxt or any other routines that cause exceptions, + * then you should use SS_OPTION_EXCEPTION_FREE_CODE S-function option. This + * is done by issuing the following command in the mdlInitializeSizes function: + * + * ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE); + * + * Setting this option, will increase the performance of your S-function by + * allowing Simulink to bypass the exception handling setup that is usually + * performed prior to each S-function invocation. Extreme care must be taken + * to verify that your code is exception free when using the + * SS_OPTION_EXCEPTION_FREE_CODE option. If your S-function generates + * an exception when this option is set, unpredictable results will occur. + * + * Exception free code refers to code which never "long jumps". Your S-function + * is not exception free if it contains any routine which when called has + * the potential of long jumping. For example mexErrMsgTxt throws an exception + * (i.e. long jumps) when called, thus ending execution of your S-function. + * Use of mxCalloc may cause unpredictable problems in the event of a memory + * allocation error since mxCalloc will long jump. If memory allocation is + * needed, you should use the stdlib.h calloc routine directly and perform + * your own error handling. + * + * All mex* routines have the potential of long jumping (i.e. throwing an + * exception). In addition several mx* routines have the potential of + * long jumping. To avoid any difficulties, only the routines which get + * a pointer or determine the size of parameters should be used. For example + * the following will never throw an exception: mxGetPr, mxGetData, + * mxGetNumberOfDimensions, mxGetM, mxGetN, mxGetNumberOfElements. + * + * If all of your "run-time" methods within your S-function are exception + * free, then you can use the option: + * ssSetOptions(S, SS_OPTION_RUNTIME_EXCEPTION_FREE_CODE); + * The other methods in your S-function need not be exception free. The + * run-time methods include any of the following: + * mdlGetTimeOfNextVarHit, mdlOutputs, mdlUpdate, and mdlDerivatives + * + * Warnings & Printf's + * ------------------- + * You can use ssWarning(S,msg) to display a warning. + * - When the S-function is compiled via mex for use with Simulink, + * ssWarning equates to mexWarnMsgTxt. + * - When the S-function is used with Real-Time Workshop, + * ssWarning(S,msg) equates to + * printf("Warning: in block '%s', '%s'\n", ssGetPath(S),msg); + * if the target has stdio facilities, otherwise it becomes a comment and + * is disabled. + * + * You can use ssPrintf(fmt, ...) to print a message. + * - When the S-function is compiled via mex for use with Simulink, + * ssPrintf equates to mexPrintf. + * - When the S-function is used with Real-Time Workshop, + * ssPrintf equates to printf, if the target has stdio facilities, + * otherwise it becomes a call to a empty function (rtPrintfNoOp). + * - In the case of Real-Time Workshop which may or may not have stdio + * facilities, to generate the most efficient code use: + * #if defined(SS_STDIO_AVAILABLE) + * ssPrintf("my message ..."); + * #endif + * - You can also use this technique to do other standard I/O related items, + * such as: + * #if defined(SS_STDIO_AVAILABLE) + * if ((fp=fopen(file,"w")) == NULL) { + * ssSetErrorStatus(S,"open failed"); + * return; + * } + * ... + * #endif + */ + +/*====================* + * S-function methods * + *====================*/ + +/* + * Level 2 S-function methods + * -------------------------- + * Notation: "=>" indicates method is required. + * [method] indicates method is optional. + * + * Note, many of the methods below are only available for use in level 2 + * C-MEX S-functions. + * + * Model Initialization in Simulink + * -------------------------------- + *=> mdlInitializeSizes - Initialize SimStruct sizes array + * + * [mdlSetInputPortFrameData] - Optional method. Check and set input and + * output port frame data attributes. + * + * NOTE: An S-function cannot use mdlSetInput(Output)PortWidth and + * mdlSetInput(Output)PortDimensionInfo at the same time. It can use + * either a width or dimension method, but not both. + * + * [mdlSetInputPortWidth] - Optional method. Check and set input and + * optionally other port widths. + * [mdlSetOutputPortWidth] - Optional method. Check and set output + * and optionally other port widths. + * + * [mdlSetInputPortDimensionInfo] + * - Optional method. Check and set input and + * optionally other port dimensions. + * [mdlSetOutputPortDimensionInfo] + * - Optional method. Check and set output + * and optionally other port dimensions. + * [mdlSetDefaultPortDimensionInfo] + * - Optional method. Set dimensions of all + * input and output ports that have unknown + * dimensions. + * + * [mdlSetInputPortSampleTime] - Optional method. Check and set input + * port sample time and optionally other port + * sample times. + * [mdlSetOutputPortSampleTime]- Optional method. Check and set output + * port sample time and optionally other port + * sample times. + *=> mdlInitializeSampleTimes - Initialize sample times and optionally + * function-call connections. + * + * [mdlSetInputPortDataType] - Optional method. Check and set input port + * data type. See SS_DOUBLE to SS_BOOLEAN in + * simstruc_types.h for built-in data types. + * [mdlSetOutputPortDataType] - Optional method. Check and set output port + * data type. See SS_DOUBLE to SS_BOOLEAN in + * simstruc_types.h for built-in data types. + * [mdlSetDefaultPortDataTypes] - Optional method. Set data types of all + * dynamically typed input and output ports. + * + * [mdlInputPortComplexSignal] - Optional method. Check and set input + * port complexity attribute (COMPLEX_YES, + * COMPLEX_NO). + * [mdlOutputPortComplexSignal] - Optional method. Check and set output + * port complexity attribute (COMPLEX_YES, + * COMPLEX_NO). + * [mdlSetDefaultPortComplexSignals] + * - Optional method. Set complex signal flags + * of all input and output ports who + * have their complex signals set to + * COMPLEX_INHERITED (dynamic complexity). + * + * [mdlSetWorkWidths] - Optional method. Set the state, iwork, + * rwork, pwork, dwork, etc sizes. + * + * [mdlStart] - Optional method. Perform actions such + * as allocating memory and attaching to pwork + * elements. + * + * [mdlInitializeConditions] - Initialize model parameters (usually + * states). Will not be called if your + * S-function does not have an initialize + * conditions method. + * + * ['constant' mdlOutputs] - Execute blocks with constant sample + * times. These are only executed once + * here. + * + * [mdlSetSimState] - Optional method. Load the complete simulation + * state for this block, which is called when + * starting the simulation from an initial + * simulation state and this s-function has set + * its ssSetSimStateCompliance to + * USE_CUSTOM_SIM_STATE. See also mdlGetSimState + * + * Model simulation loop in Simulink + * --------------------------------- + * [mdlCheckParameters] - Optional method. Will be called at + * any time during the simulation loop when + * parameters change. + * SimulationLoop: + * [mdlProcessParameters] - Optional method. Called during + * simulation after parameters have been + * changed and verified to be okay by + * mdlCheckParameters. The processing is + * done at the "top" of the simulation loop + * when it is safe to process the changed + * parameters. + * [mdlGetTimeOfNextVarHit] - Optional method. If your S-function + * has a variable step sample time, then + * this method will be called. + * [mdlInitializeConditions]- Optional method. Only called if your + * S-function resides in an enabled + * subsystem configured to reset states, + * and the subsystem has just enabled. + * => mdlOutputs - Major output call (usually updates + * output signals). + * [mdlUpdate] - Update the discrete states, etc. + * + * Integration (Minor time step) + * [mdlDerivatives] - Compute the derivatives. + * Do + * [mdlOutputs] + * [mdlDerivatives] + * EndDo - number of iterations depends on solver + * Do + * [mdlOutputs] + * [mdlZeroCrossings] + * EndDo - number of iterations depends on zero crossings signals + * EndIntegration + * + * EndSimulationLoop + * + * [mdlGetSimState] - Optional method. Called to get the complete simulation + * state for this block if the model is configured to + * save its final simulation state and this + * S-Function has set its ssSetSimStateCompliance to + * USE_CUSTOM_SIM_STATE. See also mdlSetSimState + * + * => mdlTerminate - End of model housekeeping - free memory, etc. + * + * Model initialization for code generation (rtwgen) + * ------------------------------------------------- + * + * + * [mdlRTW] - Optional method. Only called when + * generating code to add information to the + * model.rtw file which is used by the + * Real-Time Workshop. + * + * mdlTerminate - End of model housekeeping - free memory, + * etc. + * + * Noninlined S-function execution in Real-Time Workshop + * ----------------------------------------------------- + * 1) The results of most initialization methods are 'compiled' into + * the generated code and many methods are not called. + * 2) Noninlined S-functions are limited in several ways, for example + * parameter must be real (non-complex) double vectors or strings. More + * capability is provided via the Target Language Compiler. See the + * Target Language Compiler Reference Guide. + * + * => mdlInitializeSizes - Initialize SimStruct sizes array + * => mdlInitializeSampleTimes - Initialize sample times and optionally + * function-call connections. + * [mdlInitializeConditions] - Initialize model parameters (usually + * states). Will not be called if your + * S-function does not have an initialize + * conditions method. + * [mdlStart] - Optional method. Perform actions such + * as allocating memory and attaching to pwork + * elements. + * ExecutionLoop: + * => mdlOutputs - Major output call (usually updates + * output signals). + * [mdlUpdate] - Update the discrete states, etc. + * + * Integration (Minor time step) + * [mdlDerivatives] - Compute the derivatives. + * Do + * [mdlOutputs] + * [mdlDerivatives] + * EndDo - number of iterations depends on solver + * Do + * [mdlOutputs] + * [mdlZeroCrossings] + * EndDo - number of iterations depends on zero crossings signals + * EndExecutionLoop + * mdlTerminate - End of model housekeeping - free memory, + * etc. + */ + + +/*====================================================================* + * Parameter handling methods. These methods are not supported by RTW * + *====================================================================*/ + +#define MDL_CHECK_PARAMETERS /* Change to #undef to remove function */ +#if defined(MDL_CHECK_PARAMETERS) && defined(MATLAB_MEX_FILE) + /* Function: mdlCheckParameters ============================================= + * Abstract: + * mdlCheckParameters verifies new parameter settings whenever parameter + * change or are re-evaluated during a simulation. When a simulation is + * running, changes to S-function parameters can occur at any time during + * the simulation loop. + * + * This method can be called at any point after mdlInitializeSizes. + * You should add a call to this method from mdlInitalizeSizes + * to check the parameters. After setting the number of parameters + * you expect in your S-function via ssSetNumSFcnParams(S,n), you should: + * #if defined(MATLAB_MEX_FILE) + * if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) { + * mdlCheckParameters(S); + * if (ssGetErrorStatus(S) != NULL) return; + * } else { + * return; Simulink will report a parameter mismatch error + * } + * #endif + * + * When a Simulation is running, changes to S-function parameters can + * occur either at the start of a simulation step, or during a + * simulation step. When changes to S-function parameters occur during + * a simulation step, this method is called twice, for the same + * parameter changes. The first call during the simulation step is + * used to verify that the parameters are correct. After verifying the + * new parameters, the simulation continues using the original + * parameter values until the next simulation step at which time the + * new parameter values will be used. Redundant calls are needed to + * maintain simulation consistency. Note that you cannot access the + * work, state, input, output, etc. vectors in this method. This + * method should only be used to validate the parameters. Processing + * of the parameters should be done in mdlProcessParameters. + * + * See matlabroot/simulink/src/sfun_errhdl.c for an example. + */ + static void mdlCheckParameters(SimStruct *S) + { + } +#endif /* MDL_CHECK_PARAMETERS */ + + +#define MDL_PROCESS_PARAMETERS /* Change to #undef to remove function */ +#if defined(MDL_PROCESS_PARAMETERS) && defined(MATLAB_MEX_FILE) + /* Function: mdlProcessParameters =========================================== + * Abstract: + * This method will be called after mdlCheckParameters, whenever + * parameters change or get re-evaluated. The purpose of this method is + * to process the newly changed parameters. For example "caching" the + * parameter changes in the work vectors. Note this method is not + * called when it is used with the Real-Time Workshop. Therefore, + * if you use this method in an S-function which is being used with the + * Real-Time Workshop, you must write your S-function such that it doesn't + * rely on this method. This can be done by inlining your S-function + * via the Target Language Compiler. + */ + static void mdlProcessParameters(SimStruct *S) + { + } +#endif /* MDL_PROCESS_PARAMETERS */ + + + +/*=====================================* + * Configuration and execution methods * + *=====================================*/ + +/* Function: mdlInitializeSizes =============================================== + * Abstract: + * The sizes information is used by Simulink to determine the S-function + * block's characteristics (number of inputs, outputs, states, etc.). + * + * Direct Feedthough: + * The direct feedthrough flag can be either 1=yes or 0=no. It should be + * set to 1 if the input, "u", is used in the mdlOutput or + * mdlGetTimeOfNextVarHit() function. Setting this to 0 is akin to making + * a promise that "u" will not be used in the mdlOutput or + * mdlGetTimeOfNextVarHit() function. If you break the promise, then + * unpredictable results will occur. + * + * It is very common for S-function authors to write incorrect S-functions + * when configuring the S-function direct feedthrough flag. We often find + * that S-function authors are confused about what the correct setting for + * the direct feedthrough flag should be. Part of the confusion is because + * the term direct feedthrough is misleading. To reduce the confusion, you + * can think of the direct feedthrough setting as a 'needs input' + * setting. Specifically, if the S-function access an input signal in + * either mdlOutputs() or mdlGetTimeOfNextVarHit(), then the direct + * feedthrough flag must be set to 1 (true). + * + * For example, if a level 2 C-MEX S-function uses: + * ssGetInputPortSignal(S,inputPortIndex) + * in its mdlOutputs() or mdlGetTimeOfNextVarHit() methods, then the + * S-function is required to set the direct feedthrough flag to true in + * its mdlInitializeSizes() method: + * ssSetInputPortDirectFeedThrough(S, inputPortIdx, 1); + * + * If your S-Function uses ssGetInputPortSignal() in mdlOutputs() or + * mdlGetTimeOfNextVarHit() and fails to specify + * the direct feedthrough, or specifes it wrongly using + * ssSetInputPortDirectFeedThrough(S, inputPortIdx, 0); + * then the S-Function is incorreclty written and Simulink will not + * operate correctly and may crash. + * + * When you compile your S-function with debugging, e.g., + * mex -g sfunction_name.c + * your S-function will be instrumented such that an incorrect access to + * an input signal will generate a diagnostic message. + * + * The NumContStates, NumDiscStates, NumInputs, NumOutputs, NumRWork, + * NumIWork, NumPWork NumModes, and NumNonsampledZCs widths can be set to: + * DYNAMICALLY_SIZED - In this case, they will be set to the actual + * input width, unless you have a mdlSetWorkWidths + * to set the widths. + * 0 or positive number - This explicitly sets item to the specified + * value. + */ +static void mdlInitializeSizes(SimStruct *S) +{ + /* + * inputs are: + * 0 - derating ratio [-] + * 1 - generator speed [rad/s] + * 2 - azimuth [deg] + * 3 - yaw error [deg] + * 4 - blade 1 root Mx [kNm] + * 5 - blade 1 root My [kNm] + * 6 - blade 2 root Mx [kNm] + * 7 - blade 2 root My [kNm] + * 8 - blade 3 root Mx [kNm] + * 9 - blade 3 root My [kNm] + * + * outputs are: + * 0 - generator torque demand [kNm] + * 1 - blade 1 pitch demand [deg] + * 2 - blade 2 pitch demand [deg] + * 3 - blade 3 pitch demand [deg] + */ + int_T nInputPorts = 10; /* number of input ports */ + int_T nOutputPorts = 4; /* number of output ports */ + int_T needsInput = 1; /* direct feed through */ + + int_T inputPortIdx = 0; + int_T outputPortIdx = 0; + + + ssSetNumSFcnParams(S, 0); /* Number of expected parameters */ + if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) { + /* + * If the the number of expected input parameters is not equal + * to the number of parameters entered in the dialog box return. + * Simulink will generate an error indicating that there is a + * parameter mismatch. + */ + return; + } + + /* + * Configure tunability of parameters. By default, all parameters are + * tunable (changeable) during simulation. If there are parameters that + * cannot change during simulation, such as any parameters that would change + * the number of ports on the block, the sample time of the block, or the + * data type of a signal, mark these as non-tunable using a call like this: + * + * ssSetSFcnParamTunable(S, 0, 0); + * + * which sets parameter 0 to be non-tunable (0). + * + */ + + + /* Register the number and type of states the S-Function uses */ + + ssSetNumContStates( S, 0); /* number of continuous states */ + ssSetNumDiscStates( S, 0); /* number of discrete states */ + + + /* + * Configure the input ports. First set the number of input ports. + */ + if (!ssSetNumInputPorts(S, nInputPorts)) return; + /* + * Set input port dimensions for each input port index starting at 0. + * The following options summarize different ways for setting the input + * port dimensions. + * + * (1) If the input port dimensions are unknown, use + * ssSetInputPortDimensionInfo(S, inputPortIdx, DYNAMIC_DIMENSION)) + * + * (2) If the input signal is an unoriented vector, and the input port + * width is w, use + * ssSetInputPortVectorDimension(S, inputPortIdx, w) + * w (or width) can be DYNAMICALLY_SIZED or greater than 0. + * This is equivalent to ssSetInputPortWidth(S, inputPortIdx, w). + * + * (3) If the input signal is a matrix of dimension mxn, use + * ssSetInputPortMatrixDimensions(S, inputPortIdx, m, n) + * m and n can be DYNAMICALLY_SIZED or greater than zero. + * + * (4) Otherwise use: + * ssSetInputPortDimensionInfo(S, inputPortIdx, dimsInfo) + * This function can be used to fully or partially initialize the port + * dimensions. dimsInfo is a structure containing width, number of + * dimensions, and dimensions of the port. + */ + for (inputPortIdx = 0; inputPortIdx < nInputPorts; inputPortIdx++) + if(!ssSetInputPortVectorDimension(S, inputPortIdx, 1)) return; + /* + * Set direct feedthrough flag (1=yes, 0=no). + * A port has direct feedthrough if the input is used in either + * the mdlOutputs or mdlGetTimeOfNextVarHit functions. + * See sfuntmpl_directfeed.txt. + */ + for (inputPortIdx = 0; inputPortIdx < nInputPorts; inputPortIdx++) + ssSetInputPortDirectFeedThrough(S, inputPortIdx, needsInput); + + /* + * Configure the output ports. First set the number of output ports. + */ + if (!ssSetNumOutputPorts(S, nOutputPorts)) return; + + /* + * Set output port dimensions for each output port index starting at 0. + * See comments for setting input port dimensions. + */ + for(outputPortIdx = 0; outputPortIdx < nOutputPorts; outputPortIdx++) + if(!ssSetOutputPortVectorDimension(S,outputPortIdx,1)) return; + + /* + * Set the number of sample times. This must be a positive, nonzero + * integer indicating the number of sample times or it can be + * PORT_BASED_SAMPLE_TIMES. For multi-rate S-functions, the + * suggested approach to setting sample times is via the port + * based sample times method. When you create a multirate + * S-function, care needs to be taking to verify that when + * slower tasks are preempted that your S-function correctly + * manages data as to avoid race conditions. When port based + * sample times are specified, the block cannot inherit a constant + * sample time at any port. + */ + ssSetNumSampleTimes( S, 1); /* number of sample times */ + + /* + * Set size of the work vectors. + */ + ssSetNumRWork( S, 0); /* number of real work vector elements */ + ssSetNumIWork( S, 0); /* number of integer work vector elements*/ + ssSetNumPWork( S, 0); /* number of pointer work vector elements*/ + ssSetNumModes( S, 0); /* number of mode work vector elements */ + ssSetNumNonsampledZCs( S, 0); /* number of nonsampled zero crossings */ + + /* Specify the sim state compliance to be same as a built-in block */ + /* see sfun_simstate.c for example of other possible settings */ + ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE); + + /* + * All options have the form SS_OPTION_ and are documented in + * matlabroot/simulink/include/simstruc.h. The options should be + * bitwise or'd together as in + * ssSetOptions(S, (SS_OPTION_name1 | SS_OPTION_name2)) + */ + + ssSetOptions( S, 0); /* general options (SS_OPTION_xx) */ + +} /* end mdlInitializeSizes */ + + +#define MDL_SET_INPUT_PORT_FRAME_DATA /* Change to #undef to remove function */ +#if defined(MDL_SET_INPUT_PORT_FRAME_DATA) && defined(MATLAB_MEX_FILE) + /* Function: mdlSetInputPortFrameData ======================================== + * Abstract: + * This method is called with the candidate frame setting (FRAME_YES, or + * FRAME_NO) for an input port. If the proposed setting is acceptable, + * the method should go ahead and set the actual frame data setting using + * ssSetInputPortFrameData(S,portIndex,frameData). If + * the setting is unacceptable an error should be generated via + * ssSetErrorStatus. Note that any other dynamic frame input or + * output ports whose frame data setting are implicitly defined by virtue + * of knowing the frame data setting of the given port can also have their + * frame data settings set via calls to ssSetInputPortFrameData and + * ssSetOutputPortFrameData. + */ + static void mdlSetInputPortFrameData(SimStruct *S, + int portIndex, + Frame_T frameData) + { + } /* end mdlSetInputPortFrameData */ +#endif /* MDL_SET_INPUT_PORT_FRAME_DATA */ + + +#define MDL_SET_INPUT_PORT_WIDTH /* Change to #undef to remove function */ +#if defined(MDL_SET_INPUT_PORT_WIDTH) && defined(MATLAB_MEX_FILE) + /* Function: mdlSetInputPortWidth =========================================== + * Abstract: + * This method is called with the candidate width for a dynamically + * sized port. If the proposed width is acceptable, the method should + * go ahead and set the actual port width using ssSetInputPortWidth. If + * the size is unacceptable an error should generated via + * ssSetErrorStatus. Note that any other dynamically sized input or + * output ports whose widths are implicitly defined by virtue of knowing + * the width of the given port can also have their widths set via calls + * to ssSetInputPortWidth or ssSetOutputPortWidth. + */ + static void mdlSetInputPortWidth(SimStruct *S, int portIndex, int width) + { + } /* end mdlSetInputPortWidth */ +#endif /* MDL_SET_INPUT_PORT_WIDTH */ + + +#define MDL_SET_OUTPUT_PORT_WIDTH /* Change to #undef to remove function */ +#if defined(MDL_SET_OUTPUT_PORT_WIDTH) && defined(MATLAB_MEX_FILE) + /* Function: mdlSetOutputPortWidth ========================================== + * Abstract: + * This method is called with the candidate width for a dynamically + * sized port. If the proposed width is acceptable, the method should + * go ahead and set the actual port width using ssSetOutputPortWidth. If + * the size is unacceptable an error should generated via + * ssSetErrorStatus. Note that any other dynamically sized input or + * output ports whose widths are implicitly defined by virtue of knowing + * the width of the given port can also have their widths set via calls + * to ssSetInputPortWidth or ssSetOutputPortWidth. + */ + static void mdlSetOutputPortWidth(SimStruct *S, int portIndex, int width) + { + } /* end mdlSetOutputPortWidth */ +#endif /* MDL_SET_OUTPUT_PORT_WIDTH */ + + +#undef MDL_SET_INPUT_PORT_DIMENSION_INFO /* Change to #define to add function */ +#if defined(MDL_SET_INPUT_PORT_DIMENSION_INFO) && defined(MATLAB_MEX_FILE) + /* Function: mdlSetInputPortDimensionInfo ==================================== + * Abstract: + * This method is called with the candidate dimensions for an input port + * with unknown dimensions. If the proposed dimensions are acceptable, the + * method should go ahead and set the actual port dimensions. + * If they are unacceptable an error should be generated via + * ssSetErrorStatus. + * Note that any other input or output ports whose dimensions are + * implicitly defined by virtue of knowing the dimensions of the given + * port can also have their dimensions set. + * + * See matlabroot/simulink/src/sfun_matadd.c for an example. + */ + static void mdlSetInputPortDimensionInfo(SimStruct *S, + int_T portIndex, + const DimsInfo_T *dimsInfo) + { + } /* mdlSetInputPortDimensionInfo */ +#endif /* MDL_SET_INPUT_PORT_DIMENSION_INFO */ + + +#undef MDL_SET_OUTPUT_PORT_DIMENSION_INFO /* Change to #define to add function*/ +#if defined(MDL_SET_OUTPUT_PORT_DIMENSION_INFO) && defined(MATLAB_MEX_FILE) + /* Function: mdlSetOutputPortDimensionInfo =================================== + * Abstract: + * This method is called with the candidate dimensions for an output port + * with unknown dimensions. If the proposed dimensions are acceptable, the + * method should go ahead and set the actual port dimensions. + * If they are unacceptable an error should be generated via + * ssSetErrorStatus. + * Note that any other input or output ports whose dimensions are + * implicitly defined by virtue of knowing the dimensions of the given + * port can also have their dimensions set. + * + * See matlabroot/simulink/src/sfun_matadd.c for an example. + */ + static void mdlSetOutputPortDimensionInfo(SimStruct *S, + int_T portIndex, + const DimsInfo_T *dimsInfo) + { + } /* mdlSetOutputPortDimensionInfo */ +#endif /* MDL_SET_OUTPUT_PORT_DIMENSION_INFO */ + + +#undef MDL_SET_DEFAULT_PORT_DIMENSION_INFO /* Change to #define to add fcn */ +#if defined(MDL_SET_DEFAULT_PORT_DIMENSION_INFO) && defined(MATLAB_MEX_FILE) + /* Function: mdlSetDefaultPortDimensionInfo ================================== + * Abstract: + * This method is called when there is not enough information in your + * model to uniquely determine the port dimensionality of signals + * entering or leaving your block. When this occurs, Simulink's + * dimension propagation engine calls this method to ask you to set + * your S-functions default dimensions for any input and output ports + * that are dynamically sized. + * + * If you do not provide this method and you have dynamically sized ports + * where Simulink does not have enough information to propagate the + * dimensionality to your S-function, then Simulink will set these unknown + * ports to the 'block width' which is determined by examining any known + * ports. If there are no known ports, the width will be set to 1. + * + * See matlabroot/simulink/src/sfun_matadd.c for an example. + */ + static void mdlSetDefaultPortDimensionInfo(SimStruct *S) + { + } /* mdlSetDefaultPortDimensionInfo */ +#endif /* MDL_SET_DEFAULT_PORT_DIMENSION_INFO */ + + +#define MDL_SET_INPUT_PORT_SAMPLE_TIME +#if defined(MDL_SET_INPUT_PORT_SAMPLE_TIME) && defined(MATLAB_MEX_FILE) + /* Function: mdlSetInputPortSampleTime ======================================= + * Abstract: + * This method is called with the candidate sample time for an inherited + * sample time input port. If the proposed sample time is acceptable, the + * method should go ahead and set the actual port sample time using + * ssSetInputPortSampleTime. If the sample time is unacceptable an error + * should generated via ssSetErrorStatus. Note that any other inherited + * input or output ports whose sample times are implicitly defined by + * virtue of knowing the sample time of the given port can also have + * their sample times set via calls to ssSetInputPortSampleTime or + * ssSetOutputPortSampleTime. + * + * When inherited port based sample times are specified, we are guaranteed + * that the sample time will be one of the following: + * [sampleTime, offsetTime] + * continuous [0.0 , 0.0 ] + * discrete [period , offset ] where 0.0 < period < inf + * 0.0 <= offset < period + * Constant, triggered, and variable step sample times will not be + * propagated to S-functions with port based sample times. + * + * Generally the mdlSetInputPortSampleTime or mdlSetOutputPortSampleTime + * is called once with the input port sample time. However, there can be + * cases where this function will be called more than once. This happens + * when the simulation engine is converting continuous sample times to + * continuous but fixed in minor steps sample times. When this occurs, the + * original values of the sample times specified in mdlInitializeSizes + * will be restored before calling this method again. + * + * The final sample time specified at the port may be different (but + * equivalent to) from what was specified in this method. This occurs + * when: + * o) Using a fixed step solver and the port has a continuous but fixed + * in minor step sample time. In this case the sample time will + * be converted to the fundamental sample time for the model. + * o) We are adjusting sample times for numerical correctness. For + * example [0.2499999999999, 0] is converted to [0.25, 0]. + * S-functions are not explicitly notified of "converted" sample times. + * They can examine the final sample times in mdlInitializeSampleTimes. + */ + static void mdlSetInputPortSampleTime(SimStruct *S, + int_T portIdx, + real_T sampleTime, + real_T offsetTime) + { + } /* end mdlSetInputPortSampleTime */ +#endif /* MDL_SET_INPUT_PORT_SAMPLE_TIME */ + + +#define MDL_SET_OUTPUT_PORT_SAMPLE_TIME +#if defined(MDL_SET_OUTPUT_PORT_SAMPLE_TIME) && defined(MATLAB_MEX_FILE) + /* Function: mdlSetOutputPortSampleTime ====================================== + * Abstract: + * This method is called with the candidate sample time for an inherited + * sample time output port. If the proposed sample time is acceptable, the + * method should go ahead and set the actual port sample time using + * ssSetOutputPortSampleTime. If the sample time is unacceptable an error + * should generated via ssSetErrorStatus. Note that any other inherited + * input or output ports whose sample times are implicitly defined by + * virtue of knowing the sample time of the given port can also have + * their sample times set via calls to ssSetInputPortSampleTime or + * ssSetOutputPortSampleTime. + * + * Normally, sample times are propagated forwards, however if sources + * feeding this block have an inherited sample time, then Simulink + * may choose to back propagate known sample times to this block. + * When back propagating sample times, we call this method in succession + * for all inherited output port signals. + * + * See mdlSetInputPortSampleTimes for more information about when this + * method is called. + */ + static void mdlSetOutputPortSampleTime(SimStruct *S, + int_T portIdx, + real_T sampleTime, + real_T offsetTime) + { + } /* end mdlSetOutputPortSampleTime */ +#endif /* MDL_SET_OUTPUT_PORT_SAMPLE_TIME */ + + +/* Function: mdlInitializeSampleTimes ========================================= + * Abstract: + * + * This function is used to specify the sample time(s) for your S-function. + * You must register the same number of sample times as specified in + * ssSetNumSampleTimes. If you specify that you have no sample times, then + * the S-function is assumed to have one inherited sample time. + * + * The sample times are specified as pairs "[sample_time, offset_time]" + * via the following macros: + * ssSetSampleTime(S, sampleTimePairIndex, sample_time) + * ssSetOffsetTime(S, offsetTimePairIndex, offset_time) + * Where sampleTimePairIndex starts at 0. + * + * The valid sample time pairs are (upper case values are macros defined + * in simstruc.h): + * + * [CONTINUOUS_SAMPLE_TIME, 0.0 ] + * [CONTINUOUS_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET] + * [discrete_sample_period, offset ] + * [VARIABLE_SAMPLE_TIME , 0.0 ] + * + * Alternatively, you can specify that the sample time is inherited from the + * driving block in which case the S-function can have only one sample time + * pair: + * + * [INHERITED_SAMPLE_TIME, 0.0 ] + * or + * [INHERITED_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET] + * + * The following guidelines may help aid in specifying sample times: + * + * o A continuous function that changes during minor integration steps + * should register the [CONTINUOUS_SAMPLE_TIME, 0.0] sample time. + * o A continuous function that does not change during minor integration + * steps should register the + * [CONTINUOUS_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET] + * sample time. + * o A discrete function that changes at a specified rate should register + * the discrete sample time pair + * [discrete_sample_period, offset] + * where + * discrete_sample_period > 0.0 and + * 0.0 <= offset < discrete_sample_period + * o A discrete function that changes at a variable rate should + * register the variable step discrete [VARIABLE_SAMPLE_TIME, 0.0] + * sample time. The mdlGetTimeOfNextVarHit function is called to get + * the time of the next sample hit for the variable step discrete task. + * Note, the VARIABLE_SAMPLE_TIME can be used with variable step + * solvers only. + * o Discrete blocks which can operate in triggered subsystems. For your + * block to operate correctly in a triggered subsystem or a periodic + * system it must register [INHERITED_SAMPLE_TIME, 0.0]. In a triggered + * subsystem after sample times have been propagated throughout the + * block diagram, the assigned sample time to the block will be + * [INHERITED_SAMPLE_TIME, INHERITED_SAMPLE_TIME]. Typically discrete + * blocks which can be periodic or reside within triggered subsystems + * need to register the inherited sample time and the option + * SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME. Then in mdlSetWorkWidths, they + * need to verify that they were assigned a discrete or triggered + * sample time. To do this: + * mdlSetWorkWidths: + * if (ssGetSampleTime(S, 0) == CONTINUOUS_SAMPLE_TIME) { + * ssSetErrorStatus(S, "This block cannot be assigned a " + * "continuous sample time"); + * } + * + * If your function has no intrinsic sample time, then you should indicate + * that your sample time is inherited according to the following guidelines: + * + * o A function that changes as its input changes, even during minor + * integration steps should register the [INHERITED_SAMPLE_TIME, 0.0] + * sample time. + * o A function that changes as its input changes, but doesn't change + * during minor integration steps (i.e., held during minor steps) should + * register the [INHERITED_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET] + * sample time. + * + * To check for a sample hit during execution (in mdlOutputs or mdlUpdate), + * you should use the ssIsSampleHit or ssIsContinuousTask macros. + * For example, if your first sample time is continuous, then you + * used the following code-fragment to check for a sample hit. Note, + * you would get incorrect results if you used ssIsSampleHit(S,0,tid). + * if (ssIsContinuousTask(S,tid)) { + * } + * If say, you wanted to determine if the third (discrete) task has a hit, + * then you would use the following code-fragment: + * if (ssIsSampleHit(S,2,tid) { + * } + * + */ +static void mdlInitializeSampleTimes(SimStruct *S) +{ + /* Register one pair for each sample time */ + ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME); + ssSetOffsetTime(S, 0, 0.0); + +} /* end mdlInitializeSampleTimes */ + + +#define MDL_SET_INPUT_PORT_DATA_TYPE /* Change to #undef to remove function */ +#if defined(MDL_SET_INPUT_PORT_DATA_TYPE) && defined(MATLAB_MEX_FILE) + /* Function: mdlSetInputPortDataType ========================================= + * Abstract: + * This method is called with the candidate data type id for a dynamically + * typed input port. If the proposed data type is acceptable, the method + * should go ahead and set the actual port data type using + * ssSetInputPortDataType. If the data type is unacceptable an error + * should generated via ssSetErrorStatus. Note that any other dynamically + * typed input or output ports whose data types are implicitly defined by + * virtue of knowing the data type of the given port can also have their + * data types set via calls to ssSetInputPortDataType or + * ssSetOutputPortDataType. + * + * See matlabroot/simulink/include/simstruc_types.h for built-in + * type defines: SS_DOUBLE, SS_BOOLEAN, etc. + * + * See matlabroot/simulink/src/sfun_dtype_io.c for an example. + */ + static void mdlSetInputPortDataType(SimStruct *S, int portIndex,DTypeId dType) + { + } /* mdlSetInputPortDataType */ +#endif /* MDL_SET_INPUT_PORT_DATA_TYPE */ + + +#define MDL_SET_OUTPUT_PORT_DATA_TYPE /* Change to #undef to remove function */ +#if defined(MDL_SET_OUTPUT_PORT_DATA_TYPE) && defined(MATLAB_MEX_FILE) + /* Function: mdlSetOutputPortDataType ======================================== + * Abstract: + * This method is called with the candidate data type id for a dynamically + * typed output port. If the proposed data type is acceptable, the method + * should go ahead and set the actual port data type using + * ssSetOutputPortDataType. If the data type is unacceptable an error + * should generated via ssSetErrorStatus. Note that any other dynamically + * typed input or output ports whose data types are implicitly defined by + * virtue of knowing the data type of the given port can also have their + * data types set via calls to ssSetInputPortDataType or + * ssSetOutputPortDataType. + * + * See matlabroot/simulink/src/sfun_dtype_io.c for an example. + */ + static void mdlSetOutputPortDataType(SimStruct *S,int portIndex,DTypeId dType) + { + } /* mdlSetOutputPortDataType */ +#endif /* MDL_SET_OUTPUT_PORT_DATA_TYPE */ + + +#define MDL_SET_DEFAULT_PORT_DATA_TYPES /* Change to #undef to remove function*/ +#if defined(MDL_SET_DEFAULT_PORT_DATA_TYPES) && defined(MATLAB_MEX_FILE) + /* Function: mdlSetDefaultPortDataTypes ===================================== + * Abstract: + * This method is called when there is not enough information in your + * model to uniquely determine the input and output data types + * for your block. When this occurs, Simulink's data type propagation + * engine calls this method to ask you to set your S-function default + * data type for any dynamically typed input and output ports. + * + * If you do not provide this method and you have dynamically typed + * ports where Simulink does not have enough information to propagate + * data types to your S-function, then Simulink will assign the + * data type to the largest known port data type of your S-function. + * If there are no known data types, then Simulink will set the + * data type to double. + * + * See matlabroot/simulink/src/sfun_dtype_io.c for an example. + */ + static void mdlSetDefaultPortDataTypes(SimStruct *S) + { + } /* mdlSetDefaultPortDataTypes */ +#endif /* MDL_SET_DEFAULT_PORT_DATA_TYPES */ + + +#define MDL_SET_INPUT_PORT_COMPLEX_SIGNAL /* Change to #undef to remove */ +#if defined(MDL_SET_INPUT_PORT_COMPLEX_SIGNAL) && defined(MATLAB_MEX_FILE) + /* Function: mdlSetInputPortComplexSignal ==================================== + * Abstract: + * This method is called with the candidate complexity signal setting + * (COMPLEX_YES or COMPLEX_NO) for an input port whos complex signal + * attribute is set to COMPLEX_INHERITED. If the proposed complexity is + * acceptable, the method should go ahead and set the actual complexity + * using ssSetInputPortComplexSignal. If the complex setting is + * unacceptable an error should generated via ssSetErrorStatus. Note that + * any other unknown ports whose complexity is implicitly defined by virtue + * of knowing the complexity of the given port can also have their + * complexity set via calls to ssSetInputPortComplexSignal or + * ssSetOutputPortComplexSignal. + * + * See matlabroot/simulink/src/sfun_cplx.c for an example. + */ + static void mdlSetInputPortComplexSignal(SimStruct *S, + int portIndex, + CSignal_T cSignalSetting) + { + } /* mdlSetInputPortComplexSignal */ +#endif /* MDL_SET_INPUT_PORT_COMPLEX_SIGNAL */ + + +#define MDL_SET_OUTPUT_PORT_COMPLEX_SIGNAL /* Change to #undef to remove */ +#if defined(MDL_SET_OUTPUT_PORT_COMPLEX_SIGNAL) && defined(MATLAB_MEX_FILE) + /* Function: mdlSetOutputPortComplexSignal =================================== + * Abstract: + * This method is called with the candidate complexity signal setting + * (COMPLEX_YES or COMPLEX_NO) for an output port whos complex signal + * attribute is set to COMPLEX_INHERITED. If the proposed complexity is + * acceptable, the method should go ahead and set the actual complexity + * using ssSetOutputPortComplexSignal. If the complex setting is + * unacceptable an error should generated via ssSetErrorStatus. Note that + * any other unknown ports whose complexity is implicitly defined by virtue + * of knowing the complexity of the given port can also have their + * complexity set via calls to ssSetInputPortComplexSignal or + * ssSetOutputPortComplexSignal. + * + * See matlabroot/simulink/src/sfun_cplx.c for an example. + */ + static void mdlSetOutputPortComplexSignal(SimStruct *S, + int portIndex, + CSignal_T cSignalSetting) + { + } /* mdlSetOutputPortComplexSignal */ +#endif /* MDL_SET_OUTPUT_PORT_COMPLEX_SIGNAL */ + + +#define MDL_SET_DEFAULT_PORT_COMPLEX_SIGNALS /* Change to #undef to remove */ +#if defined(MDL_SET_DEFAULT_PORT_COMPLEX_SIGNALS) && defined(MATLAB_MEX_FILE) + /* Function: mdlSetDefaultPortComplexSignals ================================ + * Abstract: + * This method is called when there is not enough information in your + * model to uniquely determine the complexity (COMPLEX_NO, COMPLEX_YES) + * of signals entering your block. When this occurs, Simulink's + * complex signal propagation engine calls this method to ask you to set + * your S-function default complexity type for any input and output ports + * who's complex signal attribute is set to COMPLEX_INHERITED. + * + * If you do not provide this method and you have COMPLEX_INHERITED + * ports where Simulink does not have enough information to propagate + * the complexity to your S-function, then Simulink will set + * these unkown ports to COMPLEX_YES if any of your S-function + * ports are currently set to COMPLEX_YES, otherwise the unknown + * ports will be set to COMPLEX_NO. + * + * See matlabroot/simulink/src/sfun_cplx.c for an example. + */ + static void mdlSetDefaultPortComplexSignals(SimStruct *S) + { + } /* mdlSetDefaultPortComplexSignals */ +#endif /* MDL_SET_DEFAULT_PORT_COMPLEX_SIGNALS */ + + +#define MDL_SET_WORK_WIDTHS /* Change to #undef to remove function */ +#if defined(MDL_SET_WORK_WIDTHS) && defined(MATLAB_MEX_FILE) + /* Function: mdlSetWorkWidths =============================================== + * Abstract: + * The optional method, mdlSetWorkWidths is called after input port + * width, output port width, and sample times of the S-function have + * been determined to set any state and work vector sizes which are + * a function of the input, output, and/or sample times. This method + * is used to specify the nonzero work vector widths via the macros + * ssNumContStates, ssSetNumDiscStates, ssSetNumRWork, ssSetNumIWork, + * ssSetNumPWork, ssSetNumModes, and ssSetNumNonsampledZCs. + * + * Run-time parameters are registered in this method using methods + * ssSetNumRunTimeParams, ssSetRunTimeParamInfo, and related methods. + * + * If you are using mdlSetWorkWidths, then any work vectors you are + * using in your S-function should be set to DYNAMICALLY_SIZED in + * mdlInitializeSizes, even if the exact value is known at that point. + * The actual size to be used by the S-function should then be specified + * in mdlSetWorkWidths. + */ + static void mdlSetWorkWidths(SimStruct *S) + { + } +#endif /* MDL_SET_WORK_WIDTHS */ + + +#define MDL_INITIALIZE_CONDITIONS /* Change to #undef to remove function */ +#if defined(MDL_INITIALIZE_CONDITIONS) + /* Function: mdlInitializeConditions ======================================== + * Abstract: + * In this function, you should initialize the continuous and discrete + * states for your S-function block. The initial states are placed + * in the state vector, ssGetContStates(S) or ssGetDiscStates(S). + * You can also perform any other initialization activities that your + * S-function may require. Note, this method will be called at the + * start of simulation and if it is present in an enabled subsystem + * configured to reset states, it will be call when the enabled subsystem + * restarts execution to reset the states. + * + * You can use the ssIsFirstInitCond(S) macro to determine if this is + * is the first time mdlInitializeConditions is being called. + */ + static void mdlInitializeConditions(SimStruct *S) + { + } +#endif /* MDL_INITIALIZE_CONDITIONS */ + + +#define MDL_START /* Change to #undef to remove function */ +#if defined(MDL_START) + /* Function: mdlStart ======================================================= + * Abstract: + * This function is called once at start of model execution. If you + * have states that should be initialized once, this is the place + * to do it. + */ + static void mdlStart(SimStruct *S) + { + } +#endif /* MDL_START */ + + +/* Define to indicate that this S-Function has the mdlG[S]etSimState methods */ +#define MDL_SIM_STATE /* Change to #undef to remove this function */ +#if defined(MDL_SIM_STATE) + /* Function: mdlGetSimState =========================================== + * Abstract: + * Package complete simulation state (this includes all the run-time data + * that can change *after* mdlStart) as a MATLAB data structure and return + * it. + */ + static mxArray* mdlGetSimState(SimStruct* S) + { + } + + /* Function: mdlSetSimState =========================================== + * Abstract: + * Unack inSimState MATLAB data structure which contains the complete + * simulation state (this includes all the run-time data that can change + * *after* mdlStart) into the appropriate locations. + */ + static void mdlSetSimState(SimStruct* S, const mxArray* inSimState) + { + } +#endif /* MDL_SIM_STATE */ + + +#define MDL_GET_TIME_OF_NEXT_VAR_HIT /* Change to #undef to remove function */ +#if defined(MDL_GET_TIME_OF_NEXT_VAR_HIT) && (defined(MATLAB_MEX_FILE) || \ + defined(NRT)) + /* Function: mdlGetTimeOfNextVarHit ========================================= + * Abstract: + * This function is called to get the time of the next variable sample + * time hit. This function is called once for every major integration time + * step. It must return time of next hit by using ssSetTNext. The time of + * the next hit must be greater than ssGetT(S). + * + * Note, the time of next hit can be a function of the input signal(s). + */ + + static void mdlGetTimeOfNextVarHit(SimStruct *S) + { + time_T timeOfNextHit = ssGetT(S) /* + offset */ ; + ssSetTNext(S, timeOfNextHit); + } +#endif /* MDL_GET_TIME_OF_NEXT_VAR_HIT */ + + +#define MDL_ZERO_CROSSINGS /* Change to #undef to remove function */ +#if defined(MDL_ZERO_CROSSINGS) && (defined(MATLAB_MEX_FILE) || defined(NRT)) + /* Function: mdlZeroCrossings =============================================== + * Abstract: + * If your S-function has registered CONTINUOUS_SAMPLE_TIME and there + * are signals entering the S-function or internally generated signals + * which have discontinuities, you can use this method to locate the + * discontinuities. When called, this method must update the + * ssGetNonsampleZCs(S) vector. + */ + static void mdlZeroCrossings(SimStruct *S) + { + } +#endif /* MDL_ZERO_CROSSINGS */ + + +/* Function: mdlOutputs ======================================================= + * Abstract: + * In this function, you compute the outputs of your S-function + * block. Generally outputs are placed in the output vector(s), + * ssGetOutputPortSignal. + */ +static void mdlOutputs(SimStruct *S, int_T tid) +{ + static ikClwindconWTCon con; /* the controller instance */ + static init = 0; /* initialisation flag */ + + if (!init) { + /* initialise the controller */ + ikClwindconWTConParams param; + ikClwindconWTCon_initParams(¶m); + setParams(¶m); + ikClwindconWTCon_init(&con, ¶m); + /* remember we did this */ + init = 1; + } + + con.in.deratingRatio = **(ssGetInputPortRealSignalPtrs(S,0)); + con.in.externalMaximumTorque = 230.0; /* kNm */ + con.in.externalMinimumTorque = 0.0; /* kNm */ + con.in.externalMaximumPitch = 90.0; /* deg */ + con.in.externalMinimumPitch = 0.0; /* deg */ + con.in.generatorSpeed = **(ssGetInputPortRealSignalPtrs(S,1)); /* rad/s */ + con.in.maximumSpeed = 480.0/30*3.1416; /* rpm to rad/s */ + con.in.azimuth = **(ssGetInputPortRealSignalPtrs(S,2)); /* deg */ + con.in.maximumIndividualPitch = 10.0; /* deg */ + con.in.yawErrorReference = 0.0; /* deg */ + con.in.yawError = **(ssGetInputPortRealSignalPtrs(S,3)); /* deg */ + con.in.bladeRootMoments[0].c[0] = **(ssGetInputPortRealSignalPtrs(S,4)); /* kNm */ + con.in.bladeRootMoments[0].c[1] = **(ssGetInputPortRealSignalPtrs(S,5)); /* kNm */ + con.in.bladeRootMoments[0].c[2] = 0.0; /* kNm */ + con.in.bladeRootMoments[1].c[0] = **(ssGetInputPortRealSignalPtrs(S,6)); /* kNm */ + con.in.bladeRootMoments[1].c[1] = **(ssGetInputPortRealSignalPtrs(S,7)); /* kNm */ + con.in.bladeRootMoments[1].c[2] = 0.0; /* kNm */ + con.in.bladeRootMoments[2].c[0] = **(ssGetInputPortRealSignalPtrs(S,8)); /* kNm */ + con.in.bladeRootMoments[2].c[1] = **(ssGetInputPortRealSignalPtrs(S,9)); /* kNm */ + con.in.bladeRootMoments[2].c[2] = 0.0; /* kNm */ + + ikClwindconWTCon_step(&con); + + *(ssGetOutputPortRealSignal(S,0)) = con.out.torqueDemand; /* kNm */ + *(ssGetOutputPortRealSignal(S,1)) = con.out.pitchDemandBlade1; /* deg */ + *(ssGetOutputPortRealSignal(S,2)) = con.out.pitchDemandBlade2; /* deg */ + *(ssGetOutputPortRealSignal(S,3)) = con.out.pitchDemandBlade3; /* deg */ +} /* end mdlOutputs */ + + +#define MDL_UPDATE /* Change to #undef to remove function */ +#if defined(MDL_UPDATE) + /* Function: mdlUpdate ====================================================== + * Abstract: + * This function is called once for every major integration time step. + * Discrete states are typically updated here, but this function is useful + * for performing any tasks that should only take place once per + * integration step. + */ + static void mdlUpdate(SimStruct *S, int_T tid) + { + } +#endif /* MDL_UPDATE */ + + +#define MDL_DERIVATIVES /* Change to #undef to remove function */ +#if defined(MDL_DERIVATIVES) + /* Function: mdlDerivatives ================================================= + * Abstract: + * In this function, you compute the S-function block's derivatives. + * The derivatives are placed in the derivative vector, ssGetdX(S). + */ + static void mdlDerivatives(SimStruct *S) + { + } +#endif /* MDL_DERIVATIVES */ + + +/* Function: mdlTerminate ===================================================== + * Abstract: + * In this function, you should perform any actions that are necessary + * at the termination of a simulation. For example, if memory was allocated + * in mdlStart, this is the place to free it. + * + * Suppose your S-function allocates a few few chunks of memory in mdlStart + * and saves them in PWork. The following code fragment would free this + * memory. + * { + * int i; + * for (i = 0; i(S) + * Recall that you would have to set ssSetNum(S) + * in one of the initialization functions (mdlInitializeSizes + * or mdlSetWorkVectorWidths). + * + * See simulink/include/simulink.c for the definition (implementation) + * of this function, and ... no example yet :( + * + * 4) Finally the following functions/macros give you the ability to write + * arbitrary strings and [name, value] pairs directly into the .rtw + * file. + * + * if (!ssWriteRTWStr(S, const_char_*_string)) { + * return; + * } + * + * if (!ssWriteRTWStrParam(S, const_char_*_name, const_char_*_value)) { + * return; + * } + * + * if (!ssWriteRTWScalarParam(S, const_char_*_name, + * const_void_*_value, + * DTypeId_dtypeId)) { + * return; + * } + * + * if (!ssWriteRTWStrVectParam(S, const_char_*_name, + * const_char_*_value, + * int_num_items)) { + * return; + * } + * + * if (!ssWriteRTWVectParam(S, const_char_*_name, const_void_*_value, + * int_data_type_of_value, int_vect_len)){ + * return; + * } + * + * if (!ssWriteRTW2dMatParam(S, const_char_*_name, const_void_*_value, + * int_data_type_of_value, int_nrows, int_ncols)){ + * return; + * } + * + * The 'data_type_of_value' input argument for the above two macros is + * obtained using + * DTINFO(dTypeId, isComplex), + * where + * dTypeId: can be any one of the enum values in BuitlInDTypeID + * (SS_DOUBLE, SS_SINGLE, SS_INT8, SS_UINT8, SS_INT16, + * SS_UINT16, SS_INT32, SS_UINT32, SS_BOOLEAN defined + * in simstuc_types.h) + * isComplex: is either 0 or 1, as explained in Note-2 for + * ssWriteRTWParameters. + * + * For example DTINFO(SS_INT32,0) is a non-complex 32-bit signed + * integer. + * + * If isComplex==1, then it is assumed that 'const_void_*_value' array + * has the real and imaginary parts arranged in an interleaved manner + * (i.e., Simulink Format). + * + * If you prefer to pass the real and imaginary parts as two seperate + * arrays, you should use the follwing macros: + * + * if (!ssWriteRTWMxVectParam(S, const_char_*_name, + * const_void_*_rvalue, const_void_*_ivalue, + * int_data_type_of_value, int_vect_len)){ + * return; + * } + * + * if (!ssWriteRTWMx2dMatParam(S, const_char_*_name, + * const_void_*_rvalue, const_void_*_ivalue, + * int_data_type_of_value, + * int_nrows, int_ncols)){ + * return; + * } + * + * See simulink/include/simulink.c and simstruc.h for the definition + * (implementation) of these functions and simulink/src/ml2rtw.c for + * examples of using these functions. + * + */ + static void mdlRTW(SimStruct *S) + { + } +#endif /* MDL_RTW */ + + +/*=============================* + * Required S-function trailer * + *=============================*/ + +#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */ +#include "simulink.c" /* MEX-file interface mechanism */ +#else +#include "cg_sfun.h" /* Code generation registration function */ +#endif diff --git a/README.md b/README.md index 03d6685..66bfef8 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,15 @@ # OpenDiscon -Open source implementation of the legacy GHBladed external controller interface. +Open source implementation of popular wind turbine controller interfaces. -This code is for the production of a shared library implementing the DISCON interface for the DTU 10MW model. +Currently available distributions are for: +- The legacy GHBladed external controller interface (typically called DISCON, hence the name OpenDiscon). +- Level-2 MATLAB S-Function for Simulink. -The source code is at ./src. The main implementation file is discon.c. -It uses IK4-IKERLAN's library OpenWitcon, included as a submodule. +Currently available configurations are for: +- CL-Windcon (DTU 10MW model). + +This uses IK4-IKERLAN's library OpenWitcon, included as a submodule. Documentation is provided in Doxygen format. To generate it, run Doxygen on ./doc/Doxyfile. For compilation, run cmake here. -This will generate the VS solution or makefiles for straightforward compilation, depending on your toolchain. +This will generate the VS solution, makefiles or MATLAB function for straightforward compilation, depending on your toolchain. diff --git a/doc/Doxyfile b/doc/Doxyfile index 0b4589a..cbb2306 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -790,9 +790,9 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = ../src \ - ../OpenWitcon/src \ - ./ +INPUT = ../OpenWitcon/src \ + ./ \ + ../CONFIGURATION/CL-Windcon/src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -906,7 +906,7 @@ EXCLUDE_SYMBOLS = # that contain example code fragments that are included (see the \include # command). -EXAMPLE_PATH = ../src +EXAMPLE_PATH = ../CONFIGURATION/CL-Windcon/src # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and From 75551a0f84c6f0b919ffb45ccd38c20ef93d3373 Mon Sep 17 00:00:00 2001 From: Elorza Iker Date: Tue, 19 Dec 2017 12:02:19 +0100 Subject: [PATCH 04/17] INHERITED_SAMPLE_TIME !! --- CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c b/CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c index 215c09e..cb978e0 100644 --- a/CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c +++ b/CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c @@ -931,7 +931,7 @@ static void mdlInitializeSizes(SimStruct *S) static void mdlInitializeSampleTimes(SimStruct *S) { /* Register one pair for each sample time */ - ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME); + ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME); ssSetOffsetTime(S, 0, 0.0); } /* end mdlInitializeSampleTimes */ @@ -1218,8 +1218,22 @@ static void mdlInitializeSampleTimes(SimStruct *S) */ static void mdlOutputs(SimStruct *S, int_T tid) { +} /* end mdlOutputs */ + + +#define MDL_UPDATE /* Change to #undef to remove function */ +#if defined(MDL_UPDATE) + /* Function: mdlUpdate ====================================================== + * Abstract: + * This function is called once for every major integration time step. + * Discrete states are typically updated here, but this function is useful + * for performing any tasks that should only take place once per + * integration step. + */ + static void mdlUpdate(SimStruct *S, int_T tid) + { static ikClwindconWTCon con; /* the controller instance */ - static init = 0; /* initialisation flag */ + static int init = 0; /* initialisation flag */ if (!init) { /* initialise the controller */ @@ -1258,20 +1272,6 @@ static void mdlOutputs(SimStruct *S, int_T tid) *(ssGetOutputPortRealSignal(S,1)) = con.out.pitchDemandBlade1; /* deg */ *(ssGetOutputPortRealSignal(S,2)) = con.out.pitchDemandBlade2; /* deg */ *(ssGetOutputPortRealSignal(S,3)) = con.out.pitchDemandBlade3; /* deg */ -} /* end mdlOutputs */ - - -#define MDL_UPDATE /* Change to #undef to remove function */ -#if defined(MDL_UPDATE) - /* Function: mdlUpdate ====================================================== - * Abstract: - * This function is called once for every major integration time step. - * Discrete states are typically updated here, but this function is useful - * for performing any tasks that should only take place once per - * integration step. - */ - static void mdlUpdate(SimStruct *S, int_T tid) - { } #endif /* MDL_UPDATE */ From 5db7d3f291359ed3a0aa7681c6f8d1d9cc394618 Mon Sep 17 00:00:00 2001 From: Elorza Iker Date: Tue, 19 Dec 2017 15:09:45 +0100 Subject: [PATCH 05/17] pwork vector use for reentrancy --- CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c | 86 ++++++++++++---------- 1 file changed, 47 insertions(+), 39 deletions(-) diff --git a/CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c b/CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c index cb978e0..453fd20 100644 --- a/CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c +++ b/CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c @@ -602,7 +602,7 @@ static void mdlInitializeSizes(SimStruct *S) */ ssSetNumRWork( S, 0); /* number of real work vector elements */ ssSetNumIWork( S, 0); /* number of integer work vector elements*/ - ssSetNumPWork( S, 0); /* number of pointer work vector elements*/ + ssSetNumPWork( S, 1); /* number of pointer work vector elements*/ ssSetNumModes( S, 0); /* number of mode work vector elements */ ssSetNumNonsampledZCs( S, 0); /* number of nonsampled zero crossings */ @@ -1130,6 +1130,12 @@ static void mdlInitializeSampleTimes(SimStruct *S) */ static void mdlInitializeConditions(SimStruct *S) { + ikClwindconWTCon *con = (ikClwindconWTCon*) ssGetPWorkValue(S, 0); + /* Initialise controller */ + ikClwindconWTConParams param; + ikClwindconWTCon_initParams(¶m); + setParams(¶m); + ikClwindconWTCon_init(con, ¶m); } #endif /* MDL_INITIALIZE_CONDITIONS */ @@ -1144,6 +1150,14 @@ static void mdlInitializeSampleTimes(SimStruct *S) */ static void mdlStart(SimStruct *S) { + /* Allocate controller */ + void *ptr = calloc(1, sizeof(ikClwindconWTCon)); + if (ptr == NULL) { + /* report memory allocation error */ + ssSetErrorStatus(S, "Memory allocation error"); + return; + } + ssSetPWorkValue(S, 0, ptr); } #endif /* MDL_START */ @@ -1232,46 +1246,35 @@ static void mdlOutputs(SimStruct *S, int_T tid) */ static void mdlUpdate(SimStruct *S, int_T tid) { - static ikClwindconWTCon con; /* the controller instance */ - static int init = 0; /* initialisation flag */ - - if (!init) { - /* initialise the controller */ - ikClwindconWTConParams param; - ikClwindconWTCon_initParams(¶m); - setParams(¶m); - ikClwindconWTCon_init(&con, ¶m); - /* remember we did this */ - init = 1; - } - - con.in.deratingRatio = **(ssGetInputPortRealSignalPtrs(S,0)); - con.in.externalMaximumTorque = 230.0; /* kNm */ - con.in.externalMinimumTorque = 0.0; /* kNm */ - con.in.externalMaximumPitch = 90.0; /* deg */ - con.in.externalMinimumPitch = 0.0; /* deg */ - con.in.generatorSpeed = **(ssGetInputPortRealSignalPtrs(S,1)); /* rad/s */ - con.in.maximumSpeed = 480.0/30*3.1416; /* rpm to rad/s */ - con.in.azimuth = **(ssGetInputPortRealSignalPtrs(S,2)); /* deg */ - con.in.maximumIndividualPitch = 10.0; /* deg */ - con.in.yawErrorReference = 0.0; /* deg */ - con.in.yawError = **(ssGetInputPortRealSignalPtrs(S,3)); /* deg */ - con.in.bladeRootMoments[0].c[0] = **(ssGetInputPortRealSignalPtrs(S,4)); /* kNm */ - con.in.bladeRootMoments[0].c[1] = **(ssGetInputPortRealSignalPtrs(S,5)); /* kNm */ - con.in.bladeRootMoments[0].c[2] = 0.0; /* kNm */ - con.in.bladeRootMoments[1].c[0] = **(ssGetInputPortRealSignalPtrs(S,6)); /* kNm */ - con.in.bladeRootMoments[1].c[1] = **(ssGetInputPortRealSignalPtrs(S,7)); /* kNm */ - con.in.bladeRootMoments[1].c[2] = 0.0; /* kNm */ - con.in.bladeRootMoments[2].c[0] = **(ssGetInputPortRealSignalPtrs(S,8)); /* kNm */ - con.in.bladeRootMoments[2].c[1] = **(ssGetInputPortRealSignalPtrs(S,9)); /* kNm */ - con.in.bladeRootMoments[2].c[2] = 0.0; /* kNm */ + ikClwindconWTCon *con = (ikClwindconWTCon*) ssGetPWorkValue(S, 0); + + con->in.deratingRatio = **(ssGetInputPortRealSignalPtrs(S,0)); + con->in.externalMaximumTorque = 230.0; /* kNm */ + con->in.externalMinimumTorque = 0.0; /* kNm */ + con->in.externalMaximumPitch = 90.0; /* deg */ + con->in.externalMinimumPitch = 0.0; /* deg */ + con->in.generatorSpeed = **(ssGetInputPortRealSignalPtrs(S,1)); /* rad/s */ + con->in.maximumSpeed = 480.0/30*3.1416; /* rpm to rad/s */ + con->in.azimuth = **(ssGetInputPortRealSignalPtrs(S,2)); /* deg */ + con->in.maximumIndividualPitch = 10.0; /* deg */ + con->in.yawErrorReference = 0.0; /* deg */ + con->in.yawError = **(ssGetInputPortRealSignalPtrs(S,3)); /* deg */ + con->in.bladeRootMoments[0].c[0] = **(ssGetInputPortRealSignalPtrs(S,4)); /* kNm */ + con->in.bladeRootMoments[0].c[1] = **(ssGetInputPortRealSignalPtrs(S,5)); /* kNm */ + con->in.bladeRootMoments[0].c[2] = 0.0; /* kNm */ + con->in.bladeRootMoments[1].c[0] = **(ssGetInputPortRealSignalPtrs(S,6)); /* kNm */ + con->in.bladeRootMoments[1].c[1] = **(ssGetInputPortRealSignalPtrs(S,7)); /* kNm */ + con->in.bladeRootMoments[1].c[2] = 0.0; /* kNm */ + con->in.bladeRootMoments[2].c[0] = **(ssGetInputPortRealSignalPtrs(S,8)); /* kNm */ + con->in.bladeRootMoments[2].c[1] = **(ssGetInputPortRealSignalPtrs(S,9)); /* kNm */ + con->in.bladeRootMoments[2].c[2] = 0.0; /* kNm */ - ikClwindconWTCon_step(&con); + ikClwindconWTCon_step(con); - *(ssGetOutputPortRealSignal(S,0)) = con.out.torqueDemand; /* kNm */ - *(ssGetOutputPortRealSignal(S,1)) = con.out.pitchDemandBlade1; /* deg */ - *(ssGetOutputPortRealSignal(S,2)) = con.out.pitchDemandBlade2; /* deg */ - *(ssGetOutputPortRealSignal(S,3)) = con.out.pitchDemandBlade3; /* deg */ + *(ssGetOutputPortRealSignal(S,0)) = con->out.torqueDemand; /* kNm */ + *(ssGetOutputPortRealSignal(S,1)) = con->out.pitchDemandBlade1; /* deg */ + *(ssGetOutputPortRealSignal(S,2)) = con->out.pitchDemandBlade2; /* deg */ + *(ssGetOutputPortRealSignal(S,3)) = con->out.pitchDemandBlade3; /* deg */ } #endif /* MDL_UPDATE */ @@ -1309,6 +1312,11 @@ static void mdlOutputs(SimStruct *S, int_T tid) */ static void mdlTerminate(SimStruct *S) { + /* free the memory allocated in mdlStart */ + if (ssGetPWork(S) != NULL) { + void *ptr = ssGetPWorkValue(S,0); + if (ptr != NULL) free(ptr); + } } From 765c0454acbecb05093085b2697892b5bac354a6 Mon Sep 17 00:00:00 2001 From: Elorza Iker Date: Wed, 20 Dec 2017 14:50:50 +0100 Subject: [PATCH 06/17] doc for ipc and sampling interval --- doc/CL-Windcon.dox | 37 +++++++++++++++++-- src/ikClwindconWTConfig/ikClwindconWTConfig.c | 19 ++++++++-- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/doc/CL-Windcon.dox b/doc/CL-Windcon.dox index 5a905b8..5dbeceb 100644 --- a/doc/CL-Windcon.dox +++ b/doc/CL-Windcon.dox @@ -39,6 +39,11 @@ along with OpenDiscon. If not, see . * The basic controller provided by OpenDiscon for CL-Windcon is an instance of @link ikClwindconWTCon @endlink, * with the control loop parameters given by @link ikClwindconWTConfig.c @endlink. * +* @subsection samplinginterval Sampling interval +* +* The basic controller is a discrete-time implementation, with a sampling interval given in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: +* @snippet ikClwindconWTConfig.c Sampling interval +* * @subsection dtdamper Drivetrain damper * * The drivetrain damper is an implementation of the following transfer function from [1]: @@ -47,13 +52,14 @@ along with OpenDiscon. If not, see . * @f] * * The parameters are in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: -* @snippet ikClwindconWTConfig.c CL-Windcon drivetrain damper +* @snippet ikClwindconWTConfig.c Drivetrain damper * * @subsection torquecon Torque control * * @subsubsection torquepi PI * -* The torque controller is a PI, with its parameters given in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: +* The torque controller forces the generator torque against the optimum torque curve and regulates the generator speed when the minimum speed is reached. +* It is a PI, with its parameters given in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: * @snippet ikClwindconWTConfig.c Torque PI * Note the negative gains, which are necessary to make the torque increase when the speed error (setpoint minus measurement) is negative, and viceversa. * @@ -87,7 +93,8 @@ along with OpenDiscon. If not, see . * * @subsubsection pitchpi PI * -* The pitch controller is a PI, with its parameters given in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: +* The pitch controller forces the collective blade pitch against the minimum pitch and regulates the generator speed when the maximum speed is reached. +* It is a PI, with its parameters given in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: * @snippet ikClwindconWTConfig.c Pitch PI * Note the negative gains, which are necessary to make the pitch angle increase when the speed error (setpoint minus measurement) is negative, and viceversa. * @@ -125,6 +132,30 @@ along with OpenDiscon. If not, see . * The parameters are in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: * @snippet ikClwindconWTConfig.c Minimum pitch * +* @subsection ipc Individual pitch control +* +* @subsubsection regipc Regular IPC +* Regular individual pitch control consists of two PI controllers, for moments around axes y and z, respectively. +* The gains are in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: +* @snippet ikClwindconWTConfig.c IPC My PI +* @snippet ikClwindconWTConfig.c IPC Mz PI +* +* Note that regular IPC gains are zero, i.e. regular IPC is disabled, in this configuration. Yaw by IPC is used instead. +* +* @subsubsection yawbyipc Yaw by IPC +* +* Yaw by IPC introduces a moment around axis z to make the turbine yaw. It consists of a PI controller, which regulates the yaw error. +* Its gains are in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: +* @snippet ikClwindconWTConfig.c Yaw by IPC PI +* +* The yaw error measurement is low-pass filtered with a second order filter with the following transfer function: +* @f[ +* H(s) = \frac{\omega^2}{s^2 + 2 \xi \omega s + \omega^2} +* @f] +* +* The parameters are in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: +* @snippet ikClwindconWTConfig.c Yaw by IPC lowpass filter +* * @section references References * * [1] Tony Burton, Nick Jenkins, David Sharpe, Ervin Bossanyi, Wind Energy Handbook , ISBN: 978-0-470-69975-1. diff --git a/src/ikClwindconWTConfig/ikClwindconWTConfig.c b/src/ikClwindconWTConfig/ikClwindconWTConfig.c index 891905c..ab844a5 100644 --- a/src/ikClwindconWTConfig/ikClwindconWTConfig.c +++ b/src/ikClwindconWTConfig/ikClwindconWTConfig.c @@ -26,7 +26,18 @@ along with OpenDiscon. If not, see . #include "ikClwindconWTConfig.h" void setParams(ikClwindconWTConParams *param) { - const double T = 0.01; + /*! [Sampling interval] */ + /* + #################################################################### + Sampling interval + + Set sampling interval here: + */ + const double T = 0.01; /* [s] */ + /* + #################################################################### + */ + /*! [Sampling interval] */ ikTuneDrivetrainDamper(&(param->drivetrainDamper), T); ikTuneSpeedRange(&(param->torqueControl)); @@ -45,7 +56,7 @@ void setParams(ikClwindconWTConParams *param) { void ikTuneDrivetrainDamper(ikConLoopParams *params, double T) { - /*! [CL-Windcon drivetrain damper] */ + /*! [Drivetrain damper] */ /* #################################################################### Drivetrain damper @@ -64,7 +75,7 @@ void ikTuneDrivetrainDamper(ikConLoopParams *params, double T) { /* #################################################################### */ - /*! [CL-Windcon drivetrain damper] */ + /*! [Drivetrain damper] */ /* @@ -582,6 +593,7 @@ This is an original implementation of the yaw by IPC strategy in 87e4a2fe8e8ac8f The sampling time is given by function parameter T. + The default values have been kindly provided by TUDelft, who have calculated them to suit the DTU 10MW reference wind turbine from FP7 project INNWIND. Set parameters here: */ const double Kp = -0.064; /* [-] */ @@ -631,6 +643,7 @@ This is an original implementation of the yaw by IPC strategy in 87e4a2fe8e8ac8f The sampling time is given by function parameter T. + The default values have been kindly provided by TUDelft, who have calculated them to suit the DTU 10MW reference wind turbine from FP7 project INNWIND. Set parameters here: */ const double w = 0.6283185; /* [rad/s] */ From c232687a550cbbcb93f6f6d55ce4946982286ad9 Mon Sep 17 00:00:00 2001 From: Elorza Iker Date: Wed, 20 Dec 2017 15:51:20 +0100 Subject: [PATCH 07/17] doc for simulink dist --- README.md | 2 +- doc/OpenDiscon.dox | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 03d6685..f24c2cb 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Open source implementation of the legacy GHBladed external controller interface. This code is for the production of a shared library implementing the DISCON interface for the DTU 10MW model. The source code is at ./src. The main implementation file is discon.c. -It uses IK4-IKERLAN's library OpenWitcon, included as a submodule. +It uses [IK4-IKERLAN](http://www.ikerlan.es/en/)'s library OpenWitcon, included as a submodule. Documentation is provided in Doxygen format. To generate it, run Doxygen on ./doc/Doxyfile. For compilation, run cmake here. diff --git a/doc/OpenDiscon.dox b/doc/OpenDiscon.dox index 107e101..51717c9 100644 --- a/doc/OpenDiscon.dox +++ b/doc/OpenDiscon.dox @@ -19,18 +19,22 @@ along with OpenDiscon. If not, see . /** @mainpage * -* OpenDiscon is Ikerlan's open source implementation of the legacy GHBladed DISCON interface, -* which is also used by other wind turbine simulation software packages such as FAST. -* It is based on Ikerlan's open source wind turbine control software library @ref openwitcon. +* OpenDiscon is Ikerlan's open source implementation of popular wind turbine controller interfaces. +* based on Ikerlan's open source wind turbine control software library @ref openwitcon. * * OpenDiscon is publicly available under a rather permissive @subpage license "license", so * it may be used in many ways, possibly some of which have not been imagined by the authors. -* However, it provides out-of-the-box implementations for the following uses: -* - @ref clwindcon +* However, it provides some out-of-the-box implementations. Using them requires compilation and linking. +* CMake files are provided for easy production of the project files, makefiles or MATLAB functions suitable for the +* user's toolchain and options. * -* Using OpenDiscon's out-of-the-box implementations starts with their compilation and linking. -* CMake files are provided for easy production of the project or makefiles suitable for the -* user's toolchain. Simply run CMake on the OpenDiscon directory. +* To make the above happen, run CMake on the OpenDiscon directory. +* Two options are available: +* - CONFIGURATION +* - CL-Windcon: a controller for @ref clwindcon +* - DISTRIBUTION +* - DISCON: an implementation of the legacy GHBladed DISCON interface, which is also used by other wind turbine simulation software packages such as FAST. +* - S-Function: a Simulink block implementation. * */ @@ -54,7 +58,7 @@ along with OpenDiscon. If not, see . /** @page openwitcon OpenWitcon * -* OpenWitcon is Ikerlan's open source wind turbine controller software library. It is publicly available +* OpenWitcon is Ikerlan's open source wind turbine controller software library. It is publicly available * here. * * OpenDiscon makes heavy use of OpenWitcon, and the OpenDiscon repository has the OpenWitcon repository From 11f2ebb4ca1f27c2a41b57d90b48f648709d4624 Mon Sep 17 00:00:00 2001 From: Elorza Iker Date: Wed, 3 Jan 2018 13:37:46 +0100 Subject: [PATCH 08/17] for convenience --- CONFIGURATION/CL-Windcon/src/discon/discon.c | 17 +++++++++++++++-- .../ikClwindconWTConfig/ikClwindconWTConfig.c | 13 +++++++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/CONFIGURATION/CL-Windcon/src/discon/discon.c b/CONFIGURATION/CL-Windcon/src/discon/discon.c index 7177390..6f5036a 100644 --- a/CONFIGURATION/CL-Windcon/src/discon/discon.c +++ b/CONFIGURATION/CL-Windcon/src/discon/discon.c @@ -65,8 +65,21 @@ void OpenDiscon_EXPORT DISCON(float *DATA, int FLAG, const char *INFILE, const c DATA[41] = (float) (con.out.pitchDemandBlade1/180.0*3.1416); /* deg to rad */ DATA[42] = (float) (con.out.pitchDemandBlade2/180.0*3.1416); /* deg to rad */ DATA[43] = (float) (con.out.pitchDemandBlade3/180.0*3.1416); /* deg to rad */ - DATA[44] = (float) (con.out.pitchDemandBlade1/180.0*3.1416); /* deg to rad (collective pitch angle) */ + err = ikClwindconWTCon_getOutput(&con, &output, "collective pitch demand"); + DATA[44] = (float) (output/180.0*3.1416); /* deg to rad (collective pitch angle) */ - err = ikClwindconWTCon_getOutput(&con, &output, "maximum torque"); + err = ikClwindconWTCon_getOutput(&con, &output, "individual pitch control>pitch y from control"); + fwrite(&(output), 1, sizeof(output), f); + err = ikClwindconWTCon_getOutput(&con, &output, "individual pitch control>pitch z from control"); + fwrite(&(output), 1, sizeof(output), f); + err = ikClwindconWTCon_getOutput(&con, &output, "individual pitch control>My"); + fwrite(&(output), 1, sizeof(output), f); + err = ikClwindconWTCon_getOutput(&con, &output, "individual pitch control>Mz"); + fwrite(&(output), 1, sizeof(output), f); + err = ikClwindconWTCon_getOutput(&con, &output, "individual pitch control>pitch increment 1"); + fwrite(&(output), 1, sizeof(output), f); + err = ikClwindconWTCon_getOutput(&con, &output, "individual pitch control>pitch increment 2"); + fwrite(&(output), 1, sizeof(output), f); + err = ikClwindconWTCon_getOutput(&con, &output, "individual pitch control>pitch increment 3"); fwrite(&(output), 1, sizeof(output), f); } diff --git a/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c b/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c index ab844a5..4bec942 100644 --- a/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c +++ b/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c @@ -51,6 +51,11 @@ void setParams(ikClwindconWTConParams *param) { ikTuneTorqueLowpassFilter(&(param->torqueControl), T); ikTuneTorqueNotches(&(param->torqueControl), T); ikTuneTorquePI(&(param->torqueControl), T); + ikConfigureRotorForIpc(&(param->individualPitchControl)); + ikTuneIpcMyPI(&(param->individualPitchControl.controlMy), T); + ikTuneIpcMzPI(&(param->individualPitchControl.controlMz), T); + ikTuneYawByIpc(&(param->yawByIpc), T); + ikTuneYawByIpcLowpassFilter(&(param->yawByIpc), T); } @@ -499,7 +504,7 @@ void ikTuneIpcMyPI(ikConLoopParams *params, double T) { Set parameters here: */ const double Kp = 0.0; /* [deg/kNm] */ - const double Ki = 0.0; /* [deg/kNms] */ + const double Ki = -1.0e-3; /* [deg/kNms] */ /* #################################################################### */ @@ -546,7 +551,7 @@ void ikTuneIpcMzPI(ikConLoopParams *params, double T) { Set parameters here: */ const double Kp = 0.0; /* [deg/kNm] */ - const double Ki = 0.0; /* [deg/kNms] */ + const double Ki = -1.0e-3; /* [deg/kNms] */ /* #################################################################### */ @@ -596,8 +601,8 @@ This is an original implementation of the yaw by IPC strategy in 87e4a2fe8e8ac8f The default values have been kindly provided by TUDelft, who have calculated them to suit the DTU 10MW reference wind turbine from FP7 project INNWIND. Set parameters here: */ - const double Kp = -0.064; /* [-] */ - const double Ki = -0.0008; /* [1/s] */ + const double Kp = 0.0; /* [-] */ + const double Ki = 0.0; /* [1/s] */ /* #################################################################### */ From 3018823c753b8d21b326c5cd2b702db596a36687 Mon Sep 17 00:00:00 2001 From: Elorza Iker Date: Wed, 3 Jan 2018 17:02:03 +0100 Subject: [PATCH 09/17] fixed bug in ipc saturation --- OpenWitcon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenWitcon b/OpenWitcon index ff09cd6..1c70295 160000 --- a/OpenWitcon +++ b/OpenWitcon @@ -1 +1 @@ -Subproject commit ff09cd61ac1cac776c2cbc2c8d4cdc6ebe6cb60d +Subproject commit 1c702952fedba9ab75205d9d976487499430740f From 028445b99f1709caca0ceeccfb338ba4e7ed8167 Mon Sep 17 00:00:00 2001 From: Elorza Iker Date: Thu, 4 Jan 2018 08:32:09 +0100 Subject: [PATCH 10/17] better ipc gains --- .../CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c b/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c index 4bec942..ac6fd32 100644 --- a/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c +++ b/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c @@ -504,7 +504,7 @@ void ikTuneIpcMyPI(ikConLoopParams *params, double T) { Set parameters here: */ const double Kp = 0.0; /* [deg/kNm] */ - const double Ki = -1.0e-3; /* [deg/kNms] */ + const double Ki = -0.1e-3; /* [deg/kNms] */ /* #################################################################### */ @@ -551,7 +551,7 @@ void ikTuneIpcMzPI(ikConLoopParams *params, double T) { Set parameters here: */ const double Kp = 0.0; /* [deg/kNm] */ - const double Ki = -1.0e-3; /* [deg/kNms] */ + const double Ki = -0.1e-3; /* [deg/kNms] */ /* #################################################################### */ From a5c36364c2089fccdc672c9c355705896b999011 Mon Sep 17 00:00:00 2001 From: Elorza Iker Date: Thu, 4 Jan 2018 10:49:01 +0100 Subject: [PATCH 11/17] fault tolerance compiles --- CONFIGURATION/CL-Windcon/CMakeLists.txt | 4 + .../src/ikClwindconWTCon/ikClwindconWTCon.c | 19 ++- .../src/ikClwindconWTCon/ikClwindconWTCon.h | 6 + .../CL-Windcon/src/ikSpdman/ikSpdman.c | 118 ++++++++++++++ .../CL-Windcon/src/ikSpdman/ikSpdman.h | 149 ++++++++++++++++++ 5 files changed, 292 insertions(+), 4 deletions(-) create mode 100644 CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.c create mode 100644 CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.h diff --git a/CONFIGURATION/CL-Windcon/CMakeLists.txt b/CONFIGURATION/CL-Windcon/CMakeLists.txt index bb9c353..1679e42 100644 --- a/CONFIGURATION/CL-Windcon/CMakeLists.txt +++ b/CONFIGURATION/CL-Windcon/CMakeLists.txt @@ -10,8 +10,10 @@ set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CO set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconWTConfig/) set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikTpman/) set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikPowman/) +set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikSpdman/) # OpenDiscon source files +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikSpdman/ikSpdman.c) set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikTpman/ikTpman.c) set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikPowman/ikPowman.c) set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconWTConfig/ikClwindconWTConfig.c) @@ -29,6 +31,7 @@ set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/Op set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikVfnotch) set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikIpc) set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikVector) +set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikSensorDiagnoser) # OpenWitcon source files set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikConLoop/ikConLoop.c) @@ -42,6 +45,7 @@ set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/s set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikVfnotch/ikVfnotch.c) set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikIpc/ikIpc.c) set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikVector/ikVector.c) +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikSensorDiagnoser/ikSensorDiagnoser.c) # run distribution-specific cmake script include( ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/DISTRIBUTION/${DISTRIBUTION}/CMakeLists.txt ) diff --git a/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.c b/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.c index 433c1f5..b1cfba8 100644 --- a/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.c +++ b/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.c @@ -52,6 +52,8 @@ int ikClwindconWTCon_init(ikClwindconWTCon *self, const ikClwindconWTConParams * if (err) return -7; err = ikConLoop_init(&(self->priv.yawByIpc), &(params_.yawByIpc)); if (err) return -8; + err = ikSpdman_init(&(self->priv.speedSensorManager), &(params_.speedSensorManager)); + if (err) return -9; /* initialise feedback signals */ self->priv.torqueFromTorqueCon = 0.0; @@ -69,13 +71,18 @@ void ikClwindconWTCon_initParams(ikClwindconWTConParams *params) { ikPowman_initParams(&(params->powerManager)); ikIpc_initParams(&(params->individualPitchControl)); ikConLoop_initParams(&(params->yawByIpc)); + ikSpdman_initParams(&(params->speedSensorManager)); } int ikClwindconWTCon_step(ikClwindconWTCon *self) { int i; + /* run speed sensor manager */ + ikSpdman_step(&(self->priv.speedSensorManager), self->in.generatorSpeed, self->in.rotorSpeed, self->in.azimuth); + ikSpdman_getOutput(&(self->priv.speedSensorManager), &(self->priv.generatorSpeedEquivalent), "generator speed equivalent"); + /* run power manager */ - self->priv.maxTorqueFromPowman = ikPowman_step(&(self->priv.powerManager), self->in.deratingRatio, self->in.maximumSpeed, self->in.generatorSpeed); + self->priv.maxTorqueFromPowman = ikPowman_step(&(self->priv.powerManager), self->in.deratingRatio, self->in.maximumSpeed, self->priv.generatorSpeedEquivalent); ikPowman_getOutput(&(self->priv.powerManager), &(self->priv.minPitchFromPowman), "minimum pitch"); ikPowman_getOutput(&(self->priv.powerManager), &(self->priv.belowRatedTorque), "below rated torque"); @@ -91,16 +98,16 @@ int ikClwindconWTCon_step(ikClwindconWTCon *self) { ikTpman_getOutput(&(self->priv.tpManager), &(self->priv.minTorque), "minimum torque"); /* run drivetrain damper */ - self->priv.torqueFromDtdamper = ikConLoop_step(&(self->priv.dtdamper), 0.0, self->in.generatorSpeed, -(self->in.externalMaximumTorque), self->in.externalMaximumTorque); + self->priv.torqueFromDtdamper = ikConLoop_step(&(self->priv.dtdamper), 0.0, self->priv.generatorSpeedEquivalent, -(self->in.externalMaximumTorque), self->in.externalMaximumTorque); /* run torque control */ - self->priv.torqueFromTorqueCon = ikConLoop_step(&(self->priv.torquecon), self->in.maximumSpeed, self->in.generatorSpeed, self->priv.minTorque, self->priv.maxTorque); + self->priv.torqueFromTorqueCon = ikConLoop_step(&(self->priv.torquecon), self->in.maximumSpeed, self->priv.generatorSpeedEquivalent, self->priv.minTorque, self->priv.maxTorque); /* calculate torque demand */ self->out.torqueDemand = self->priv.torqueFromDtdamper + self->priv.torqueFromTorqueCon; /* run collective pitch control */ - self->priv.collectivePitchDemand = ikConLoop_step(&(self->priv.colpitchcon), self->in.maximumSpeed, self->in.generatorSpeed, self->priv.minPitch, self->priv.maxPitch); + self->priv.collectivePitchDemand = ikConLoop_step(&(self->priv.colpitchcon), self->in.maximumSpeed, self->priv.generatorSpeedEquivalent, self->priv.minPitch, self->priv.maxPitch); /* run yaw by ipc */ self->priv.individualPitchForYaw = ikConLoop_step(&(self->priv.yawByIpc), self->in.yawErrorReference, self->in.yawError, -self->in.maximumIndividualPitch, self->in.maximumIndividualPitch); @@ -173,6 +180,10 @@ int ikClwindconWTCon_getOutput(const ikClwindconWTCon *self, double *output, con *output = self->priv.individualPitchForYaw; return 0; } + if (!strcmp(name, "generator speed equivalent")) { + *output = self->priv.generatorSpeedEquivalent; + return 0; + } /* pick up the block names */ sep = strstr(name, ">"); diff --git a/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.h b/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.h index 5a0a5e6..b8d5a8d 100644 --- a/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.h +++ b/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.h @@ -34,6 +34,7 @@ extern "C" { #include "ikTpman.h" #include "ikPowman.h" #include "ikIpc.h" +#include "ikSpdman.h" /** * @struct ikClwindconWTConInputs @@ -46,6 +47,7 @@ extern "C" { double externalMinimumPitch; /**. +*/ + +/** + * @file ikSpdman.c + * + * @brief Class ikSpdman implementation + */ + +/* @cond */ + +#include +#include + +#include "ikSpdman.h" + +int ikSpdman_init(ikSpdman *self, const ikSpdmanParams *params) { + int err; + int err_ = 0; + + /* pass on member parameters */ + err = ikSensorDiagnoser_init(&(self->diagnoser), &(params->diagnoser)); + if (err && !err_) err_ = -1; + + /* register parameter values */ + self->gbratio = params->gearboxRatio; + if (0.0 > params->T) return -2; + self->T = params->T; + if (params->maxAzimuth <= params->minAzimuth) return -3; + self->azimuthRange = params->maxAzimuth - params->minAzimuth; + + return err_; +} + +void ikSpdman_initParams(ikSpdmanParams *params) { + + /* pass on member parameters */ + ikSensorDiagnoser_initParams(&(params->diagnoser)); + + /* set default values */ + params->gearboxRatio = 1.0; + params->T = 1.0; + params->minAzimuth = 0.0; + params->maxAzimuth = 360.0; +} + +int ikSpdman_step(ikSpdman *self, double generatorSpeed, double rotorSpeed, double azimuth) { + int i; + double diff; + + /* prepare signals */ + self->signals[0] = generatorSpeed; + self->signals[1] = self->gbratio*rotorSpeed; + diff = azimuth - self->lastAzimuth; + diff = diff < self->azimuthRange/2 ? diff : diff - self->azimuthRange; + diff = diff > -self->azimuthRange/2 ? diff : diff + self->azimuthRange; + self->signals[3] = self->T * diff / 180.0 * 3.14159265358979; + + /* run diagnoser */ + ikSensorDiagnoser_step(&(self->diagnoser), self->ok, self->signals); + + /* compute status */ + self->status = 0; + for (i = 0; i < 3; i++) { + if (!self->ok[i]) { + if (!self->status) self->status = -1 - i; + else self->status = 4; + } + } + + /* choose the signal to output */ + switch (self->status) { + case -1 : + self->outputSpeed = self->signals[1]; + break; + default : + self->outputSpeed = self->signals[0]; + } + + return self->status; +} + +int ikSpdman_getOutput(const ikSpdman *self, double *output, const char *name) { + const char *sep; + + /* pick up the signal names */ + if (!strcmp(name, "generator speed equivalent")) { + *output = self->outputSpeed; + return 0; + } + + /* pick up the block names */ + sep = strstr(name, ">"); + if (NULL == sep) return -1; + + return -2; +} + +/* @endcond */ + + + diff --git a/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.h b/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.h new file mode 100644 index 0000000..8ee52ae --- /dev/null +++ b/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.h @@ -0,0 +1,149 @@ +/* +Copyright (C) 2017 IK4-IKERLAN + +This file is part of OpenDiscon. + +OpenDiscon is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +OpenDiscon is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenDiscon. If not, see . +*/ + +/** + * @file ikSpdman.h + * + * @brief Class ikSpdman interface + */ + +#ifndef IKSPDMAN_H +#define IKSPDMAN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ikSensorDiagnoser.h" + + /** + * @struct ikSpdman + * @brief Speed sensor manager + * + * This takes the generator speed, rotor speed and azimuth angle measurements, cross-checks them and outputs a usable generator speed signal when possible. + * + * @par Inputs + * @li generator speed: generator speed in rad/s, specify via @link ikSpdman_step @endlink + * @li rotor speed: rotor speed in rad/s, specify via @link ikSpdman_step @endlink + * @li azimuth: rotor azimuth angle in degrees, specify via @link ikSpdman_step @endlink + * + * @par Outputs + * @li generator speed equivalent: generator speed for use by controller, in rad/s, get via @link ikSpdman_getOutput @endlink + * @li status: status code, returned by @link ikSpdman_step @endlink, alternatively get via @link ikSpdman_getOutput @endlink + * + * @par Unit block + * + * @image html ikSpdman_unit_block.svg + * + * @par Block diagram + * + * @image html ikSpdman_block_diagram.svg + * + * @par State machine + * + * @image html ikSpdman_state_machine.svg + * + * @par Methods + * @li @link ikSpdman_initParams @endlink initialise initialisation parameter structure + * @li @link ikSpdman_init @endlink initialise an instance + * @li @link ikSpdman_step @endlink execute periodic calculations + * @li @link ikSpdman_getOutput @endlink get output value + */ + typedef struct ikSpdman { + /** + * Private members + */ + /* @cond */ + ikSensorDiagnoser diagnoser; + double gbratio; + double T; + double azimuthRange; + double lastAzimuth; + double signals[3]; + int ok[3]; + double outputSpeed; + int status; + /* @endcond */ + } ikSpdman; + + /** + * @struct ikSpdmanParams + * @brief Speed sensor manager initialisation parameters + */ + typedef struct ikSpdmanParams { + ikSensorDiagnoserParams diagnoser; /** Date: Thu, 4 Jan 2018 16:43:19 +0100 Subject: [PATCH 12/17] rides through loss of generator speed signal --- CONFIGURATION/CL-Windcon/CMakeLists.txt | 2 + CONFIGURATION/CL-Windcon/src/discon/discon.c | 11 +++++ .../ikClwindconInputMod/ikClwindconInputMod.c | 47 +++++++++++++++++++ .../ikClwindconInputMod/ikClwindconInputMod.h | 43 +++++++++++++++++ .../src/ikClwindconWTCon/ikClwindconWTCon.c | 5 ++ .../ikClwindconWTConfig/ikClwindconWTConfig.c | 13 +++++ .../ikClwindconWTConfig/ikClwindconWTConfig.h | 2 + .../CL-Windcon/src/ikSpdman/ikSpdman.c | 15 +++++- 8 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 CONFIGURATION/CL-Windcon/src/ikClwindconInputMod/ikClwindconInputMod.c create mode 100644 CONFIGURATION/CL-Windcon/src/ikClwindconInputMod/ikClwindconInputMod.h diff --git a/CONFIGURATION/CL-Windcon/CMakeLists.txt b/CONFIGURATION/CL-Windcon/CMakeLists.txt index 1679e42..d6dd943 100644 --- a/CONFIGURATION/CL-Windcon/CMakeLists.txt +++ b/CONFIGURATION/CL-Windcon/CMakeLists.txt @@ -8,6 +8,7 @@ S-Function" ) # OpenDiscon include directories set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconWTCon/) set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconWTConfig/) +set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconInputMod/) set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikTpman/) set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikPowman/) set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikSpdman/) @@ -16,6 +17,7 @@ set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CO set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikSpdman/ikSpdman.c) set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikTpman/ikTpman.c) set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikPowman/ikPowman.c) +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconInputMod/ikClwindconInputMod.c) set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconWTConfig/ikClwindconWTConfig.c) set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconWTCon/ikClwindconWTCon.c) diff --git a/CONFIGURATION/CL-Windcon/src/discon/discon.c b/CONFIGURATION/CL-Windcon/src/discon/discon.c index 6f5036a..afaae27 100644 --- a/CONFIGURATION/CL-Windcon/src/discon/discon.c +++ b/CONFIGURATION/CL-Windcon/src/discon/discon.c @@ -19,6 +19,7 @@ along with OpenDiscon. If not, see . #define NINT(a) ((a) >= 0.0 ? (int) ((a)+0.5) : ((a)-0.5)) +#include "ikClwindconInputMod.h" #include "ikClwindconWTConfig.h" #include "OpenDiscon_EXPORT.h" #include @@ -44,6 +45,7 @@ void OpenDiscon_EXPORT DISCON(float *DATA, int FLAG, const char *INFILE, const c con.in.externalMaximumPitch = 90.0; /* deg */ con.in.externalMinimumPitch = 0.0; /* deg */ con.in.generatorSpeed = (double) DATA[19]; /* rad/s */ + con.in.rotorSpeed = (double) DATA[20]; /* rad/s */ con.in.maximumSpeed = 480.0/30*3.1416; /* rpm to rad/s */ con.in.azimuth = 180.0/3.1416 * (double) DATA[59]; /* rad to deg */ con.in.maximumIndividualPitch = 10.0; /* deg */ @@ -59,6 +61,7 @@ void OpenDiscon_EXPORT DISCON(float *DATA, int FLAG, const char *INFILE, const c con.in.bladeRootMoments[2].c[1] = 1.0e-3 * (double) DATA[31]; /* Nm to kNm */ con.in.bladeRootMoments[2].c[2] = 0.0; /* kNm */ + ikClwindconInputMod(&(con.in)); ikClwindconWTCon_step(&con); DATA[46] = (float) (con.out.torqueDemand*1.0e3); /* kNm to Nm */ @@ -82,4 +85,12 @@ void OpenDiscon_EXPORT DISCON(float *DATA, int FLAG, const char *INFILE, const c fwrite(&(output), 1, sizeof(output), f); err = ikClwindconWTCon_getOutput(&con, &output, "individual pitch control>pitch increment 3"); fwrite(&(output), 1, sizeof(output), f); + err = ikClwindconWTCon_getOutput(&con, &output, "generator speed equivalent"); + fwrite(&(output), 1, sizeof(output), f); + err = ikClwindconWTCon_getOutput(&con, &output, "speed sensor manager>signal 1"); + fwrite(&(output), 1, sizeof(output), f); + err = ikClwindconWTCon_getOutput(&con, &output, "speed sensor manager>signal 2"); + fwrite(&(output), 1, sizeof(output), f); + err = ikClwindconWTCon_getOutput(&con, &output, "speed sensor manager>signal 3"); + fwrite(&(output), 1, sizeof(output), f); } diff --git a/CONFIGURATION/CL-Windcon/src/ikClwindconInputMod/ikClwindconInputMod.c b/CONFIGURATION/CL-Windcon/src/ikClwindconInputMod/ikClwindconInputMod.c new file mode 100644 index 0000000..772bfcb --- /dev/null +++ b/CONFIGURATION/CL-Windcon/src/ikClwindconInputMod/ikClwindconInputMod.c @@ -0,0 +1,47 @@ +/* +Copyright (C) 2017 IK4-IKERLAN + +This file is part of OpenDiscon. + +OpenDiscon is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +OpenDiscon is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenDiscon. If not, see . +*/ + +/** + * @file ikClwindconInputMod.c + * + * @brief CL-Windcon wind turbine controller input modification + */ + +#include "ikClwindconInputMod.h" + +void ikClwindconInputMod(ikClwindconWTConInputs *in) { + + ikGeneratorSpeedSingalFail(in); + +} + +void ikGeneratorSpeedSingalFail(ikClwindconWTConInputs *in) { + static _n = 0; + + const int N = 10000; + const double val = 0.0; + + if (_n < N) { + _n++; + return; + } + + in->generatorSpeed = val; + +} diff --git a/CONFIGURATION/CL-Windcon/src/ikClwindconInputMod/ikClwindconInputMod.h b/CONFIGURATION/CL-Windcon/src/ikClwindconInputMod/ikClwindconInputMod.h new file mode 100644 index 0000000..e2be026 --- /dev/null +++ b/CONFIGURATION/CL-Windcon/src/ikClwindconInputMod/ikClwindconInputMod.h @@ -0,0 +1,43 @@ +/* +Copyright (C) 2017 IK4-IKERLAN + +This file is part of OpenDiscon. + +OpenDiscon is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +OpenDiscon is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenDiscon. If not, see . +*/ + +/** + * @file ikClwindconInputMod.h + * + * @brief CL-Windcon wind turbine controller input modification + */ + +#ifndef IKCLWINDCONINPUTMOD_H +#define IKCLWINDCONINPUTMOD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ikClwindconWTCon.h" + + void ikClwindconInputMod(ikClwindconWTConInputs *in); + void ikGeneratorSpeedSingalFail(ikClwindconWTConInputs *in); + +#ifdef __cplusplus +} +#endif + +#endif /* IKCLWINDCONINPUTMOD_H */ + diff --git a/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.c b/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.c index b1cfba8..c77f576 100644 --- a/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.c +++ b/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.c @@ -223,6 +223,11 @@ int ikClwindconWTCon_getOutput(const ikClwindconWTCon *self, double *output, con if (err) return -1; else return 0; } + if (!strncmp(name, "speed sensor manager", strlen(name) - strlen(sep))) { + err = ikSpdman_getOutput(&(self->priv.speedSensorManager), output, sep + 1); + if (err) return -1; + else return 0; + } return -2; diff --git a/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c b/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c index ac6fd32..269ef89 100644 --- a/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c +++ b/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c @@ -56,6 +56,7 @@ void setParams(ikClwindconWTConParams *param) { ikTuneIpcMzPI(&(param->individualPitchControl.controlMz), T); ikTuneYawByIpc(&(param->yawByIpc), T); ikTuneYawByIpcLowpassFilter(&(param->yawByIpc), T); + ikConfigureSpeedManager(&(param->speedSensorManager), T); } @@ -676,3 +677,15 @@ This is an original implementation of the yaw by IPC strategy in 87e4a2fe8e8ac8f params->linearController.measurementTfs.tfParams[1].b[0] = (0.5*T*w)*(0.5*T*w) / (1 + T*d*w + (0.5*T*w)*(0.5*T*w)); } + +void ikConfigureSpeedManager(ikSpdmanParams *params, double T) { + + params->diagnoser.nStepsToFault = 10; + params->diagnoser.tolerance = 1.0; + + params->gearboxRatio = 50.0; + params->T = T; + params->minAzimuth = 0.0; + params->maxAzimuth = 360.0; + +} diff --git a/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.h b/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.h index 8cbf976..a02a7e9 100644 --- a/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.h +++ b/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.h @@ -68,6 +68,8 @@ extern "C" { void ikTuneYawByIpcLowpassFilter(ikConLoopParams *params, double T); + void ikConfigureSpeedManager(ikSpdmanParams *params, double T); + #ifdef __cplusplus } #endif diff --git a/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.c b/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.c index 9cecc7a..156a7d3 100644 --- a/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.c +++ b/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.c @@ -70,7 +70,8 @@ int ikSpdman_step(ikSpdman *self, double generatorSpeed, double rotorSpeed, doub diff = azimuth - self->lastAzimuth; diff = diff < self->azimuthRange/2 ? diff : diff - self->azimuthRange; diff = diff > -self->azimuthRange/2 ? diff : diff + self->azimuthRange; - self->signals[3] = self->T * diff / 180.0 * 3.14159265358979; + self->signals[2] = self->gbratio * diff / self->T / 180.0 * 3.14159265358979; + self->lastAzimuth = azimuth; /* run diagnoser */ ikSensorDiagnoser_step(&(self->diagnoser), self->ok, self->signals); @@ -104,6 +105,18 @@ int ikSpdman_getOutput(const ikSpdman *self, double *output, const char *name) { *output = self->outputSpeed; return 0; } + if (!strcmp(name, "signal 1")) { + *output = self->signals[0]; + return 0; + } + if (!strcmp(name, "signal 2")) { + *output = self->signals[1]; + return 0; + } + if (!strcmp(name, "signal 3")) { + *output = self->signals[2]; + return 0; + } /* pick up the block names */ sep = strstr(name, ">"); From d161c07e4fe13c87d055c3a7407c3ec63d228db3 Mon Sep 17 00:00:00 2001 From: Elorza Iker Date: Fri, 5 Jan 2018 08:41:51 +0100 Subject: [PATCH 13/17] speed sensor manager doc --- .../src/ikClwindconWTCon/ikClwindconWTCon.h | 1 + .../CL-Windcon/src/ikSpdman/ikSpdman.c | 12 + .../CL-Windcon/src/ikSpdman/ikSpdman.h | 14 +- doc/svg/ikClwindconWTCon_block_diagram.svg | 198 +- doc/svg/ikClwindconWTCon_unit_block.svg | 135 +- doc/svg/ikSpdman_block_diagram.svg | 2194 +++++++++++++++++ doc/svg/ikSpdman_unit_block.svg | 1622 ++++++++++++ 7 files changed, 4100 insertions(+), 76 deletions(-) create mode 100644 doc/svg/ikSpdman_block_diagram.svg create mode 100644 doc/svg/ikSpdman_unit_block.svg diff --git a/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.h b/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.h index b8d5a8d..cc4f4ac 100644 --- a/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.h +++ b/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.h @@ -108,6 +108,7 @@ extern "C" { * @li external minimum pitch: externally set lower pitch limit, in degrees, specify via @link ikClwindconWTConInputs.externalMinimumPitch @endlink at @link in @endlink * @li maximum speed: maximum generator speed setpoint, in rad/s, specify via @link ikClwindconWTConInputs.maximumSpeed @endlink at @link in @endlink * @li generator speed: current generator speed, in rad/s, specify via @link ikClwindconWTConInputs.generatorSpeed @endlink at @link in @endlink + * @li rotor speed: current rotor or low speed shaft speed, in rad/s, specify via @link ikClwindconWTConInputs.rotorSpeed @endlink at @link in @endlink * @li derating ratio: externally set derating ratio, non-dimensional, specify via @link ikClwindconWTConInputs.deratingRatio @endlink at @link in @endlink * @li azimuth: rotor azimuth angle, in degrees, specify via @link ikClwindconWTConInputs.azimuth @endlink at @link in @endlink * @li blade root moments: moments at blade roots, in kNm, specify via @link ikClwindconWTConInputs.bladeRootMoments @endlink at @link in @endlink diff --git a/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.c b/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.c index 156a7d3..439c45f 100644 --- a/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.c +++ b/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.c @@ -117,6 +117,18 @@ int ikSpdman_getOutput(const ikSpdman *self, double *output, const char *name) { *output = self->signals[2]; return 0; } + if (!strcmp(name, "ok 1")) { + *output = self->ok[0]; + return 0; + } + if (!strcmp(name, "ok 2")) { + *output = self->ok[1]; + return 0; + } + if (!strcmp(name, "ok 3")) { + *output = self->ok[2]; + return 0; + } /* pick up the block names */ sep = strstr(name, ">"); diff --git a/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.h b/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.h index 8ee52ae..2cc740c 100644 --- a/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.h +++ b/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.h @@ -55,9 +55,19 @@ extern "C" { * * @image html ikSpdman_block_diagram.svg * - * @par State machine + * @par Map * - * @image html ikSpdman_state_machine.svg + + + + + + + + + + +
ok 1 ok 2 ok 3 status mux
1 1 1 0 1
0 1 1 -1 2
1 0 1 -2 1
1 1 0 -3 1
0 0 1 -4 1
0 1 0 -4 1
1 0 0 -4 1
0 0 0 -4 1
* * @par Methods * @li @link ikSpdman_initParams @endlink initialise initialisation parameter structure diff --git a/doc/svg/ikClwindconWTCon_block_diagram.svg b/doc/svg/ikClwindconWTCon_block_diagram.svg index cad4d7f..1b93350 100644 --- a/doc/svg/ikClwindconWTCon_block_diagram.svg +++ b/doc/svg/ikClwindconWTCon_block_diagram.svg @@ -9,9 +9,9 @@ xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="684.97382mm" + width="857.19366mm" height="440.59653mm" - viewBox="0 0 2427.0723 1561.1687" + viewBox="0 0 3037.3 1561.1687" id="svg2" version="1.1" inkscape:version="0.92.1 r15371" @@ -1914,6 +1914,54 @@ transform="matrix(-0.8,0,0,-0.8,-10,0)" inkscape:connector-curvature="0" /> + + + + + + + + + + transform="translate(492.13748,-48.801925)"> - generator speed @@ -3157,5 +3190,122 @@ cx="1354.4976" cy="1359.53" r="4.999999" /> + generator speed + + speed sensor manager + ikSpdman + rotor speed + azimuth + generator speed equivalent + + + diff --git a/doc/svg/ikClwindconWTCon_unit_block.svg b/doc/svg/ikClwindconWTCon_unit_block.svg index 874589b..78e9f37 100644 --- a/doc/svg/ikClwindconWTCon_unit_block.svg +++ b/doc/svg/ikClwindconWTCon_unit_block.svg @@ -501,6 +501,21 @@ d="M 0,0 5,-5 -12.5,0 5,5 Z" id="path11234-5-0-4-42" /> + + + image/svg+xml - + @@ -545,25 +560,25 @@ xml:space="preserve" style="font-style:normal;font-weight:normal;font-size:15.02537632px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" x="200.73166" - y="388.99149" + y="357.11649" id="text5026">external minimum torque external maximum pitch generator speed external maximum torque maximum speed external minimum pitch derating ratio blade root moments maximum individual pitch yaw error reference yaw error azimuth + + rotor speed diff --git a/doc/svg/ikSpdman_block_diagram.svg b/doc/svg/ikSpdman_block_diagram.svg new file mode 100644 index 0000000..43661b8 --- /dev/null +++ b/doc/svg/ikSpdman_block_diagram.svg @@ -0,0 +1,2194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + generator speed + + diagnoser + ikSensorDiagnoser + rotor speed + azimuth + + + + + + + + + + + + + signal 1 + + + gearboxratio + + signal 2 + + + + gearboxratio + + + + + + + signal 3 + + + ok 1 + ok 2 + ok 3 + + + MUX + + + + + + + + + + map + + + + + generator speed equivalent + status + + diff --git a/doc/svg/ikSpdman_unit_block.svg b/doc/svg/ikSpdman_unit_block.svg new file mode 100644 index 0000000..865d71e --- /dev/null +++ b/doc/svg/ikSpdman_unit_block.svg @@ -0,0 +1,1622 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + generator speed + + speed sensor manager + ikSpdman + rotor speed + azimuth + generator speed equivalent + + + + + + From d7ba881be2958f531393537bb867db248ca8e0cb Mon Sep 17 00:00:00 2001 From: Elorza Iker Date: Fri, 5 Jan 2018 12:19:30 +0100 Subject: [PATCH 14/17] doc fault tolerance --- .../ikClwindconInputMod/ikClwindconInputMod.c | 16 +++- .../ikClwindconWTConfig/ikClwindconWTConfig.c | 26 ++++++- .../CL-Windcon/src/sfunc/OpenDiscon_block.mdl | 78 ++++++++++++------- CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c | 4 +- doc/CL-Windcon.dox | 54 +++++++++---- 5 files changed, 132 insertions(+), 46 deletions(-) diff --git a/CONFIGURATION/CL-Windcon/src/ikClwindconInputMod/ikClwindconInputMod.c b/CONFIGURATION/CL-Windcon/src/ikClwindconInputMod/ikClwindconInputMod.c index 772bfcb..5460c8f 100644 --- a/CONFIGURATION/CL-Windcon/src/ikClwindconInputMod/ikClwindconInputMod.c +++ b/CONFIGURATION/CL-Windcon/src/ikClwindconInputMod/ikClwindconInputMod.c @@ -34,10 +34,24 @@ void ikClwindconInputMod(ikClwindconWTConInputs *in) { void ikGeneratorSpeedSingalFail(ikClwindconWTConInputs *in) { static _n = 0; + /*! [Speed sensor fault] */ + /* + #################################################################### + Speed sensor fault + + A generator speed measurement of val is enforced after N sampling + intervals (N <= 0 to disable). + + Set parameters here: + */ const int N = 10000; const double val = 0.0; + /* + #################################################################### + */ + /*! [Speed sensor fault] */ - if (_n < N) { + if (0 < N && _n < N) { _n++; return; } diff --git a/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c b/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c index 269ef89..bdfe141 100644 --- a/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c +++ b/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c @@ -599,7 +599,6 @@ This is an original implementation of the yaw by IPC strategy in 87e4a2fe8e8ac8f The sampling time is given by function parameter T. - The default values have been kindly provided by TUDelft, who have calculated them to suit the DTU 10MW reference wind turbine from FP7 project INNWIND. Set parameters here: */ const double Kp = 0.0; /* [-] */ @@ -680,10 +679,29 @@ This is an original implementation of the yaw by IPC strategy in 87e4a2fe8e8ac8f void ikConfigureSpeedManager(ikSpdmanParams *params, double T) { - params->diagnoser.nStepsToFault = 10; - params->diagnoser.tolerance = 1.0; + /*! [Speed sensor manager] */ + /* + #################################################################### + Speed sensor management + + Differences between the generator speed, rotor speed and azimuth derivative + (the latter two multiplied by the gearbox ratio) are considered a fault if + they are larger than tol for longer than N sampling intervals T. + + Set parameters here: + */ + const int N = 10; /* [-] */ + const double tol = 1.0; /* [rad/s] */ + const double gbRatio = 50.0; /* [-] */ + /* + #################################################################### + */ + /*! [Speed sensor manager] */ + + params->diagnoser.nStepsToFault = N; + params->diagnoser.tolerance = tol; - params->gearboxRatio = 50.0; + params->gearboxRatio = gbRatio; params->T = T; params->minAzimuth = 0.0; params->maxAzimuth = 360.0; diff --git a/CONFIGURATION/CL-Windcon/src/sfunc/OpenDiscon_block.mdl b/CONFIGURATION/CL-Windcon/src/sfunc/OpenDiscon_block.mdl index bffa8ce..249a943 100644 --- a/CONFIGURATION/CL-Windcon/src/sfunc/OpenDiscon_block.mdl +++ b/CONFIGURATION/CL-Windcon/src/sfunc/OpenDiscon_block.mdl @@ -7,7 +7,7 @@ Model { NumRootInports 0 NumRootOutports 0 ParameterArgumentNames "" - ComputedModelVersion "1.6" + ComputedModelVersion "1.9" NumModelReferences 0 NumTestPointedSignals 0 } @@ -66,9 +66,9 @@ Model { ModifiedByFormat "%" LastModifiedBy "ielorza" ModifiedDateFormat "%" - LastModifiedDate "Mon Dec 18 14:51:22 2017" - RTWModifiedTimeStamp 435509080 - ModelVersionFormat "1.%" + LastModifiedDate "Fri Jan 05 11:00:16 2018" + RTWModifiedTimeStamp 437050811 + ModelVersionFormat "1.%" ConfigurationManager "none" SampleTimeColors off SampleTimeAnnotations off @@ -885,12 +885,12 @@ Model { ShowPageBoundaries off ZoomFactor "100" ReportName "simulink-default.rpt" - SIDHighWatermark "16" + SIDHighWatermark "17" Block { BlockType SubSystem Name "OpenDiscon" SID "2" - Ports [10, 4] + Ports [11, 4] Position [105, 101, 440, 499] ZOrder 2 RequestExecContextInheritance off @@ -926,13 +926,22 @@ Model { Port "2" IconDisplay "Port number" } + Block { + BlockType Inport + Name "rotor speed [rad/s]" + SID "17" + Position [20, 338, 50, 352] + ZOrder 16 + Port "3" + IconDisplay "Port number" + } Block { BlockType Inport Name "azimuth [deg]" SID "5" Position [20, 98, 50, 112] ZOrder 4 - Port "3" + Port "4" IconDisplay "Port number" } Block { @@ -941,7 +950,7 @@ Model { SID "6" Position [20, 128, 50, 142] ZOrder 5 - Port "4" + Port "5" IconDisplay "Port number" } Block { @@ -950,7 +959,7 @@ Model { SID "7" Position [20, 158, 50, 172] ZOrder 6 - Port "5" + Port "6" IconDisplay "Port number" } Block { @@ -959,7 +968,7 @@ Model { SID "8" Position [20, 188, 50, 202] ZOrder 7 - Port "6" + Port "7" IconDisplay "Port number" } Block { @@ -968,7 +977,7 @@ Model { SID "9" Position [20, 218, 50, 232] ZOrder 8 - Port "7" + Port "8" IconDisplay "Port number" } Block { @@ -977,7 +986,7 @@ Model { SID "10" Position [20, 248, 50, 262] ZOrder 9 - Port "8" + Port "9" IconDisplay "Port number" } Block { @@ -986,7 +995,7 @@ Model { SID "11" Position [20, 278, 50, 292] ZOrder 10 - Port "9" + Port "10" IconDisplay "Port number" } Block { @@ -995,15 +1004,15 @@ Model { SID "12" Position [20, 308, 50, 322] ZOrder 11 - Port "10" + Port "11" IconDisplay "Port number" } Block { BlockType S-Function Name "S-Function" SID "1" - Ports [10, 4] - Position [165, 20, 305, 340] + Ports [11, 4] + Position [165, 20, 305, 370] ZOrder 1 FunctionName "OpenDiscon" EnableBusSupport off @@ -1012,7 +1021,7 @@ Model { BlockType Outport Name "generator torque demand [kNm]" SID "13" - Position [395, 53, 425, 67] + Position [395, 63, 425, 77] ZOrder 12 IconDisplay "Port number" } @@ -1020,7 +1029,7 @@ Model { BlockType Outport Name "blade 1 pitch demand [deg]" SID "14" - Position [395, 133, 425, 147] + Position [395, 148, 425, 162] ZOrder 13 Port "2" IconDisplay "Port number" @@ -1029,7 +1038,7 @@ Model { BlockType Outport Name "blade 2 pitch demand [deg]" SID "15" - Position [395, 213, 425, 227] + Position [395, 233, 425, 247] ZOrder 14 Port "3" IconDisplay "Port number" @@ -1038,7 +1047,7 @@ Model { BlockType Outport Name "blade 3 pitch demand [deg]" SID "16" - Position [395, 293, 425, 307] + Position [395, 318, 425, 332] ZOrder 15 Port "4" IconDisplay "Port number" @@ -1047,6 +1056,7 @@ Model { ZOrder 15 SrcBlock "derating ratio [-]" SrcPort 1 + Points [95, 0] DstBlock "S-Function" DstPort 1 } @@ -1054,6 +1064,7 @@ Model { ZOrder 17 SrcBlock "azimuth [deg]" SrcPort 1 + Points [95, 0] DstBlock "S-Function" DstPort 3 } @@ -1061,6 +1072,7 @@ Model { ZOrder 22 SrcBlock "blade 2 root My [kNm]" SrcPort 1 + Points [95, 0] DstBlock "S-Function" DstPort 8 } @@ -1075,6 +1087,7 @@ Model { ZOrder 18 SrcBlock "yaw error [deg]" SrcPort 1 + Points [95, 0] DstBlock "S-Function" DstPort 4 } @@ -1082,6 +1095,7 @@ Model { ZOrder 19 SrcBlock "blade 1 root Mx [kNm]" SrcPort 1 + Points [95, 0] DstBlock "S-Function" DstPort 5 } @@ -1089,6 +1103,7 @@ Model { ZOrder 20 SrcBlock "blade 1 root My [kNm]" SrcPort 1 + Points [95, 0] DstBlock "S-Function" DstPort 6 } @@ -1096,6 +1111,7 @@ Model { ZOrder 21 SrcBlock "blade 2 root Mx [kNm]" SrcPort 1 + Points [95, 0] DstBlock "S-Function" DstPort 7 } @@ -1103,16 +1119,10 @@ Model { ZOrder 16 SrcBlock "generator speed [rad/s]" SrcPort 1 + Points [95, 0] DstBlock "S-Function" DstPort 2 } - Line { - ZOrder 24 - SrcBlock "blade 3 root My [kNm]" - SrcPort 1 - DstBlock "S-Function" - DstPort 10 - } Line { ZOrder 28 SrcBlock "S-Function" @@ -1141,6 +1151,20 @@ Model { DstBlock "generator torque demand [kNm]" DstPort 1 } + Line { + ZOrder 35 + SrcBlock "blade 3 root My [kNm]" + SrcPort 1 + DstBlock "S-Function" + DstPort 10 + } + Line { + ZOrder 36 + SrcBlock "rotor speed [rad/s]" + SrcPort 1 + DstBlock "S-Function" + DstPort 11 + } } } } diff --git a/CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c b/CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c index 453fd20..67969c9 100644 --- a/CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c +++ b/CONFIGURATION/CL-Windcon/src/sfunc/sfunc.c @@ -486,6 +486,7 @@ static void mdlInitializeSizes(SimStruct *S) * 7 - blade 2 root My [kNm] * 8 - blade 3 root Mx [kNm] * 9 - blade 3 root My [kNm] + * 10 - rotor speed [rad/s] * * outputs are: * 0 - generator torque demand [kNm] @@ -493,7 +494,7 @@ static void mdlInitializeSizes(SimStruct *S) * 2 - blade 2 pitch demand [deg] * 3 - blade 3 pitch demand [deg] */ - int_T nInputPorts = 10; /* number of input ports */ + int_T nInputPorts = 11; /* number of input ports */ int_T nOutputPorts = 4; /* number of output ports */ int_T needsInput = 1; /* direct feed through */ @@ -1254,6 +1255,7 @@ static void mdlOutputs(SimStruct *S, int_T tid) con->in.externalMaximumPitch = 90.0; /* deg */ con->in.externalMinimumPitch = 0.0; /* deg */ con->in.generatorSpeed = **(ssGetInputPortRealSignalPtrs(S,1)); /* rad/s */ + con->in.rotorSpeed = **(ssGetInputPortRealSignalPtrs(S,10)); /* rad/s */ con->in.maximumSpeed = 480.0/30*3.1416; /* rpm to rad/s */ con->in.azimuth = **(ssGetInputPortRealSignalPtrs(S,2)); /* deg */ con->in.maximumIndividualPitch = 10.0; /* deg */ diff --git a/doc/CL-Windcon.dox b/doc/CL-Windcon.dox index 5dbeceb..83983ac 100644 --- a/doc/CL-Windcon.dox +++ b/doc/CL-Windcon.dox @@ -34,16 +34,18 @@ along with OpenDiscon. If not, see . * OpenDiscon caters to the needs of H2020 project CL-Windcon, by providing a controller specifically * tuned for compatibility with the Innwind 10 MW reference wind turbine model. * -* @section basic Basic controller +* @section intro Introduction * -* The basic controller provided by OpenDiscon for CL-Windcon is an instance of @link ikClwindconWTCon @endlink, +* The controller provided by OpenDiscon for CL-Windcon is an instance of @link ikClwindconWTCon @endlink, * with the control loop parameters given by @link ikClwindconWTConfig.c @endlink. * * @subsection samplinginterval Sampling interval * -* The basic controller is a discrete-time implementation, with a sampling interval given in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: +* The controller is a discrete-time implementation, with a sampling interval given in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: * @snippet ikClwindconWTConfig.c Sampling interval * +* @section basic Basic controller +* * @subsection dtdamper Drivetrain damper * * The drivetrain damper is an implementation of the following transfer function from [1]: @@ -83,12 +85,6 @@ along with OpenDiscon. If not, see . * The parameters are in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: * @snippet ikClwindconWTConfig.c 1st side-side tower mode filter * -* @subsubsection kopt Optimum torque curve -* -* Below rated wind speed, the torque controller uses a quadratic speed-torque curve, along the lines of that described by [1]. -* The parameters are in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: -* @snippet ikClwindconWTConfig.c Optimum torque -* * @subsection pitchcon Pitch control * * @subsubsection pitchpi PI @@ -125,16 +121,26 @@ along with OpenDiscon. If not, see . * The parameters are in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: * @snippet ikClwindconWTConfig.c Gain schedule * -* @subsubsection minpitch Minimum pitch +* @section derating Derating +* +* @subsection minpitch Minimum pitch * * The minimum pitch is altered depending on the derating ratio. This is implemented as a look-up table. * * The parameters are in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: * @snippet ikClwindconWTConfig.c Minimum pitch * -* @subsection ipc Individual pitch control +* @subsection kopt Optimum torque curve * -* @subsubsection regipc Regular IPC +* Below rated wind speed, the torque controller uses a quadratic speed-torque curve, along the lines of that described by [1]. +* The gain of said curve varies depending on the derating ratio. This is implemented as a look-up table. +* +* The parameters are in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: +* @snippet ikClwindconWTConfig.c Optimum torque +* +* @section ipc Individual pitch control +* +* @subsection regipc Regular IPC * Regular individual pitch control consists of two PI controllers, for moments around axes y and z, respectively. * The gains are in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: * @snippet ikClwindconWTConfig.c IPC My PI @@ -142,7 +148,7 @@ along with OpenDiscon. If not, see . * * Note that regular IPC gains are zero, i.e. regular IPC is disabled, in this configuration. Yaw by IPC is used instead. * -* @subsubsection yawbyipc Yaw by IPC +* @subsection yawbyipc Yaw by IPC * * Yaw by IPC introduces a moment around axis z to make the turbine yaw. It consists of a PI controller, which regulates the yaw error. * Its gains are in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: @@ -156,6 +162,28 @@ along with OpenDiscon. If not, see . * The parameters are in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: * @snippet ikClwindconWTConfig.c Yaw by IPC lowpass filter * +* @section ftc Fault tolerance +* +* @subsection spdman Generator speed sensor redundancy +* +* The controller uses three different generator speed measurements: +* - generator speed +* - rotor speed (approx. generator speed divided by gearbox ratio) +* - azimuth (approx. integral of rotor speed) +* +* If all three measurements are similar, the generator speed is used. +* Dissimilarities are used for sensor failure diagnosis and, if the generator speed sensor is found to have failed, the rotor speed is used instead. +* +* The parameters dictating when the measurements are dissimilar are in @link ikClwindconWTConfig.c @endlink, conveniently commented as follows: +* @snippet ikClwindconWTConfig.c Speed sensor manager +* +* @subsection faults Sensor faults +* +* [Only for DISTRIBUTION = DISCON] A simple generator speed sensor fault introduction facility is provided. +* +* The parameters governing this fault are in @link ikClwindconInputMod.c @endlink, conveniently commented as follows: +* @snippet ikClwindconInputMod.c Speed sensor fault +* * @section references References * * [1] Tony Burton, Nick Jenkins, David Sharpe, Ervin Bossanyi, Wind Energy Handbook , ISBN: 978-0-470-69975-1. From 40fa4dd5ff4ae056e6cdce037f4581ebf99b70fb Mon Sep 17 00:00:00 2001 From: Elorza Iker Date: Wed, 31 Jan 2018 12:54:59 +0100 Subject: [PATCH 15/17] minor fix --- .../CL-Windcon/src/ikClwindconInputMod/ikClwindconInputMod.c | 2 +- OpenWitcon | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CONFIGURATION/CL-Windcon/src/ikClwindconInputMod/ikClwindconInputMod.c b/CONFIGURATION/CL-Windcon/src/ikClwindconInputMod/ikClwindconInputMod.c index 5460c8f..647ab40 100644 --- a/CONFIGURATION/CL-Windcon/src/ikClwindconInputMod/ikClwindconInputMod.c +++ b/CONFIGURATION/CL-Windcon/src/ikClwindconInputMod/ikClwindconInputMod.c @@ -32,7 +32,7 @@ void ikClwindconInputMod(ikClwindconWTConInputs *in) { } void ikGeneratorSpeedSingalFail(ikClwindconWTConInputs *in) { - static _n = 0; + static int _n = 0; /*! [Speed sensor fault] */ /* diff --git a/OpenWitcon b/OpenWitcon index 1c70295..d568e00 160000 --- a/OpenWitcon +++ b/OpenWitcon @@ -1 +1 @@ -Subproject commit 1c702952fedba9ab75205d9d976487499430740f +Subproject commit d568e00edbe5744346982502b5635ce0d9d568ee From 0ec8a606800c01da51a40bf7d59de775440c13c3 Mon Sep 17 00:00:00 2001 From: Inhar Andueza Date: Wed, 21 Mar 2018 16:12:49 +0100 Subject: [PATCH 16/17] merge ftc github --- CONFIGURATION/CL-Windcon/src/discon/discon.c | 4 ++-- .../CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c | 3 +++ OpenWitcon | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CONFIGURATION/CL-Windcon/src/discon/discon.c b/CONFIGURATION/CL-Windcon/src/discon/discon.c index afaae27..36df7e9 100644 --- a/CONFIGURATION/CL-Windcon/src/discon/discon.c +++ b/CONFIGURATION/CL-Windcon/src/discon/discon.c @@ -29,7 +29,7 @@ void OpenDiscon_EXPORT DISCON(float *DATA, int FLAG, const char *INFILE, const c static ikClwindconWTCon con; double output = -12.0; static FILE *f = NULL; - const double deratingRatio = 0.2; /* later to be got via the supercontroller interface */ + const double deratingRatio = 0.0; /* later to be got via the supercontroller interface */ if (NINT(DATA[0]) == 0) { ikClwindconWTConParams param; @@ -48,7 +48,7 @@ void OpenDiscon_EXPORT DISCON(float *DATA, int FLAG, const char *INFILE, const c con.in.rotorSpeed = (double) DATA[20]; /* rad/s */ con.in.maximumSpeed = 480.0/30*3.1416; /* rpm to rad/s */ con.in.azimuth = 180.0/3.1416 * (double) DATA[59]; /* rad to deg */ - con.in.maximumIndividualPitch = 10.0; /* deg */ + con.in.maximumIndividualPitch = 0.0; /* deg */ con.in.yawErrorReference = 0.0; /* deg */ con.in.yawError = 180.0/3.1416 * (double) DATA[23]; /* rad to deg */ con.in.bladeRootMoments[0].c[0] = 1.0e-3 * (double) DATA[68]; /* Nm to kNm */ diff --git a/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c b/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c index bdfe141..9850d7e 100644 --- a/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c +++ b/CONFIGURATION/CL-Windcon/src/ikClwindconWTConfig/ikClwindconWTConfig.c @@ -693,6 +693,7 @@ void ikConfigureSpeedManager(ikSpdmanParams *params, double T) { const int N = 10; /* [-] */ const double tol = 1.0; /* [rad/s] */ const double gbRatio = 50.0; /* [-] */ + const int nSteps = 3000; /* ################################################*/ /* #################################################################### */ @@ -705,5 +706,7 @@ void ikConfigureSpeedManager(ikSpdmanParams *params, double T) { params->T = T; params->minAzimuth = 0.0; params->maxAzimuth = 360.0; + + params->diagnoser.nIgnoredSteps = nSteps; /* ################################################*/ } diff --git a/OpenWitcon b/OpenWitcon index d568e00..9973900 160000 --- a/OpenWitcon +++ b/OpenWitcon @@ -1 +1 @@ -Subproject commit d568e00edbe5744346982502b5635ce0d9d568ee +Subproject commit 9973900313207975f9a57138b86e949c0168d7ce From 4d0892d2453efde01a0bc87f850b5e6913d4fd0c Mon Sep 17 00:00:00 2001 From: Inhar Andueza Date: Wed, 28 Mar 2018 10:39:51 +0200 Subject: [PATCH 17/17] merge-atzeko prest --- CONFIGURATION/CL-Windcon/CMakeLists.txt | 2 + CONFIGURATION/CL-Windcon/src/discon/discon.c | 6 ++- .../ikClwindconResetSensorSignals.c | 53 +++++++++++++++++++ .../ikClwindconResetSensorSignals.h | 44 +++++++++++++++ .../src/ikClwindconWTCon/ikClwindconWTCon.c | 2 +- .../src/ikClwindconWTCon/ikClwindconWTCon.h | 1 + .../ikClwindconWTConfig/ikClwindconWTConfig.c | 7 ++- .../CL-Windcon/src/ikSpdman/ikSpdman.c | 4 +- .../CL-Windcon/src/ikSpdman/ikSpdman.h | 2 +- OpenWitcon | 2 +- 10 files changed, 113 insertions(+), 10 deletions(-) create mode 100644 CONFIGURATION/CL-Windcon/src/ikClwindconResetSensorSignals/ikClwindconResetSensorSignals.c create mode 100644 CONFIGURATION/CL-Windcon/src/ikClwindconResetSensorSignals/ikClwindconResetSensorSignals.h diff --git a/CONFIGURATION/CL-Windcon/CMakeLists.txt b/CONFIGURATION/CL-Windcon/CMakeLists.txt index d6dd943..0fb7937 100644 --- a/CONFIGURATION/CL-Windcon/CMakeLists.txt +++ b/CONFIGURATION/CL-Windcon/CMakeLists.txt @@ -6,6 +6,7 @@ DISCON\n\ S-Function" ) # OpenDiscon include directories +set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconResetSensorSignals/) set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconWTCon/) set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconWTConfig/) set (OPENDISCON_INCLUDE_DIRS ${OPENDISCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconInputMod/) @@ -20,6 +21,7 @@ set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATIO set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconInputMod/ikClwindconInputMod.c) set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconWTConfig/ikClwindconWTConfig.c) set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconWTCon/ikClwindconWTCon.c) +set (OPENDISCON_SOURCES ${OPENDISCON_SOURCES} ${PROJECT_SOURCE_DIR}/CONFIGURATION/${CONFIGURATION}/src/ikClwindconResetSensorSignals/ikClwindconResetSensorSignals.c) # OpenWitcon include directories set (OPENWITCON_INCLUDE_DIRS ${OPENWITCON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/OpenWitcon/src/ikConLoop) diff --git a/CONFIGURATION/CL-Windcon/src/discon/discon.c b/CONFIGURATION/CL-Windcon/src/discon/discon.c index 36df7e9..6c9cb14 100644 --- a/CONFIGURATION/CL-Windcon/src/discon/discon.c +++ b/CONFIGURATION/CL-Windcon/src/discon/discon.c @@ -19,6 +19,7 @@ along with OpenDiscon. If not, see . #define NINT(a) ((a) >= 0.0 ? (int) ((a)+0.5) : ((a)-0.5)) +#include "ikClwindconResetSensorSignals.h" #include "ikClwindconInputMod.h" #include "ikClwindconWTConfig.h" #include "OpenDiscon_EXPORT.h" @@ -62,8 +63,11 @@ void OpenDiscon_EXPORT DISCON(float *DATA, int FLAG, const char *INFILE, const c con.in.bladeRootMoments[2].c[2] = 0.0; /* kNm */ ikClwindconInputMod(&(con.in)); + ikClwindconResetSensorSignals(&(con.in)); ikClwindconWTCon_step(&con); - + + /* ####################################### */ + DATA[46] = (float) (con.out.torqueDemand*1.0e3); /* kNm to Nm */ DATA[41] = (float) (con.out.pitchDemandBlade1/180.0*3.1416); /* deg to rad */ DATA[42] = (float) (con.out.pitchDemandBlade2/180.0*3.1416); /* deg to rad */ diff --git a/CONFIGURATION/CL-Windcon/src/ikClwindconResetSensorSignals/ikClwindconResetSensorSignals.c b/CONFIGURATION/CL-Windcon/src/ikClwindconResetSensorSignals/ikClwindconResetSensorSignals.c new file mode 100644 index 0000000..a323e74 --- /dev/null +++ b/CONFIGURATION/CL-Windcon/src/ikClwindconResetSensorSignals/ikClwindconResetSensorSignals.c @@ -0,0 +1,53 @@ +/* +Copyright (C) 2017 IK4-IKERLAN + +This file is part of OpenDiscon. + +OpenDiscon is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +OpenDiscon is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenDiscon. If not, see . +*/ + +/** + * @file ikClwindconInputMod.c + * + * @brief CL-Windcon wind turbine controller input modification + */ + +#include "ikClwindconResetSensorSignals.h" + +void ikClwindconResetSensorSignals(ikClwindconWTConInputs *in) { + + ikAllOK(in); + +} + +void ikAllOK(ikClwindconWTConInputs *in) { + /*! [Reset Speed sensor fault] */ + /* + #################################################################### + + Set parameters here: + */ + const int nSteps = 3000; + static int _t; + /* + #################################################################### + */ + if (!(_t < nSteps) && !(nSteps < _t)){ + in->ResetSignal = 1; + _t++; + } else { + _t++; + in->ResetSignal = 0; + } +} diff --git a/CONFIGURATION/CL-Windcon/src/ikClwindconResetSensorSignals/ikClwindconResetSensorSignals.h b/CONFIGURATION/CL-Windcon/src/ikClwindconResetSensorSignals/ikClwindconResetSensorSignals.h new file mode 100644 index 0000000..50213e3 --- /dev/null +++ b/CONFIGURATION/CL-Windcon/src/ikClwindconResetSensorSignals/ikClwindconResetSensorSignals.h @@ -0,0 +1,44 @@ +/* +Copyright (C) 2017 IK4-IKERLAN + +This file is part of OpenDiscon. + +OpenDiscon is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +OpenDiscon is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenDiscon. If not, see . +*/ + +/** + * @file ikClwindconInputMod.h + * + * @brief CL-Windcon wind turbine controller input modification + */ + +#ifndef IKCLWINDCONRESETSENSORSIGNALS_H +#define IKCLWINDCONRESETSENSORSIGNALS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ikClwindconWTCon.h" +#include "ikSensorDiagnoser.h" + + void ikClwindconResetSensorSignals(ikClwindconWTConInputs *in); + void ikAllOK(ikClwindconWTConInputs *in); + +#ifdef __cplusplus +} +#endif + +#endif /* IKCLWINDCONINPUTMOD_H */ + diff --git a/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.c b/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.c index c77f576..4287561 100644 --- a/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.c +++ b/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.c @@ -78,7 +78,7 @@ int ikClwindconWTCon_step(ikClwindconWTCon *self) { int i; /* run speed sensor manager */ - ikSpdman_step(&(self->priv.speedSensorManager), self->in.generatorSpeed, self->in.rotorSpeed, self->in.azimuth); + ikSpdman_step(&(self->priv.speedSensorManager), self->in.generatorSpeed, self->in.rotorSpeed, self->in.azimuth, self->in.ResetSignal); ikSpdman_getOutput(&(self->priv.speedSensorManager), &(self->priv.generatorSpeedEquivalent), "generator speed equivalent"); /* run power manager */ diff --git a/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.h b/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.h index cc4f4ac..ceac94c 100644 --- a/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.h +++ b/CONFIGURATION/CL-Windcon/src/ikClwindconWTCon/ikClwindconWTCon.h @@ -54,6 +54,7 @@ extern "C" { double maximumIndividualPitch; /**diagnoser.nStepsToFault = N; params->diagnoser.tolerance = tol; - + params->gearboxRatio = gbRatio; params->T = T; params->minAzimuth = 0.0; params->maxAzimuth = 360.0; - params->diagnoser.nIgnoredSteps = nSteps; /* ################################################*/ + } diff --git a/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.c b/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.c index 439c45f..3bc7500 100644 --- a/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.c +++ b/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.c @@ -60,7 +60,7 @@ void ikSpdman_initParams(ikSpdmanParams *params) { params->maxAzimuth = 360.0; } -int ikSpdman_step(ikSpdman *self, double generatorSpeed, double rotorSpeed, double azimuth) { +int ikSpdman_step(ikSpdman *self, double generatorSpeed, double rotorSpeed, double azimuth, int ResetSignal) { int i; double diff; @@ -72,7 +72,7 @@ int ikSpdman_step(ikSpdman *self, double generatorSpeed, double rotorSpeed, doub diff = diff > -self->azimuthRange/2 ? diff : diff + self->azimuthRange; self->signals[2] = self->gbratio * diff / self->T / 180.0 * 3.14159265358979; self->lastAzimuth = azimuth; - + self->diagnoser.ResetSignal = ResetSignal; /* run diagnoser */ ikSensorDiagnoser_step(&(self->diagnoser), self->ok, self->signals); diff --git a/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.h b/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.h index 2cc740c..94fe24f 100644 --- a/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.h +++ b/CONFIGURATION/CL-Windcon/src/ikSpdman/ikSpdman.h @@ -135,7 +135,7 @@ extern "C" { * @li -3: bad azimuth * @li -4: two or more bad signals */ - int ikSpdman_step(ikSpdman *self, double generatorSpeed, double rotorSpeed, double azimuth); + int ikSpdman_step(ikSpdman *self, double generatorSpeed, double rotorSpeed, double azimuth, int ResetSignal); /** * Get output value by name. All signals named on the block diagram of diff --git a/OpenWitcon b/OpenWitcon index 9973900..c9e5f02 160000 --- a/OpenWitcon +++ b/OpenWitcon @@ -1 +1 @@ -Subproject commit 9973900313207975f9a57138b86e949c0168d7ce +Subproject commit c9e5f024663cbe8f3ddafb7da4d8086991fe9ccb