Source file: /~heha/ewa/Reluktanzmotor/maweig-Motor-200831.zip/trip.cpp

/* Projekt: maweig-Motor mit Delfino-Launchpad
 * Teil: Trip-Steuerung = automatische Abschaltvorkerhungen für PWM
 */
#include "Settings.h"
#include "regdef2.h"

// Define the base quantites
namespace nsBASE{
  //const float VOLTAGE = 236.14;	// Base peak phase voltage (volt), Vdc/sqrt(3)
  const float SHUNT_CURRENT	=9.95;	// Base peak phase current (amp), Max. measurable peak curr.
  const float LEM_CURRENT	=12.0;	//  ----- do -----
  //const float TORQUE =		// Base torque (N.m)
  //const float FLUX =			// Base flux linkage (volt.sec/rad)
}

// ****************************************************************************
// Variables for current measurement
// ****************************************************************************

static const float curLimit = 8.0;

// LEM    1.0pu current ==> 12.0A -> 2048 counts ==> 8A -> 1365
// SHUNT  1.0pu current ==> 9.95A -> 2048 counts ==> 8A -> 1647
inline int LEM(float A)     {return 2048*A/nsBASE::LEM_CURRENT;}
inline int SHUNT(float A)   {return 2048*A/nsBASE::SHUNT_CURRENT;}

// CMPSS parameters for Overcurrent Protection
static const Uint16 
	clkPrescale = 20,
	sampwin     = 30,
	thresh      = 18;
static const Uint16
	LEM_curHi   = 2048 + LEM(curLimit),
	LEM_curLo   = 2048 - LEM(curLimit),
	SHUNT_curHi = 2048 + SHUNT(curLimit),
	SHUNT_curLo = 2048 - SHUNT(curLimit);

// ****************************************************************************
// Flag variables
// ****************************************************************************
MONITOR bool TripFlag;		// PWM trip status
MONITOR bool TripFlagClear;	// PWM trip clear (from debugger)


// Setup OCP limits and digital filter parameters of CMPSS
static void CMPSS_DIG_FILTER(volatile CMPSS_REGS&regs, Uint16 curHi, Uint16 curLo) {
	// comparator references
  regs.DACHVALS.bit.DACVAL = curHi;	// positive max current limit
  regs.DACLVALS.bit.DACVAL = curLo;	// negative max current limit

	// digital filter settings - HIGH side
  regs.CTRIPHFILCLKCTL.bit.CLKPRESCALE = clkPrescale;	// set time between samples, max : 1023
  regs.CTRIPHFILCTL.bit.SAMPWIN        = sampwin;	// # of samples in window, max : 31
  regs.CTRIPHFILCTL.bit.THRESH         = thresh;	// recommended : thresh > sampwin/2

	// digital filter settings - LOW side
  regs.CTRIPLFILCLKCTL.bit.CLKPRESCALE = clkPrescale;	// Max count of 1023 */
  regs.CTRIPLFILCTL.bit.SAMPWIN        = sampwin;	// # of samples in window, max : 31
  regs.CTRIPLFILCTL.bit.THRESH         = thresh;	// recommended : thresh > sampwin/2
}

void Trip::Check() {
	// *******************************************************
	// Current limit setting / tuning in Debug environment
	// *******************************************************
  if (BUILDLEVEL>1) {
    EALLOW;
//    LEM_curHi = 2048 + LEM(curLimit);
//    LEM_curLo = 2048 - LEM(curLimit);
//    SHUNT_curHi = 2048 + SHUNT(curLimit);
//    SHUNT_curLo = 2048 - SHUNT(curLimit);

    if (SENSES & bit(LEM_CURRENT_SENSE)) {
      CMPSS_DIG_FILTER(Cmpss1Regs, LEM_curHi, LEM_curLo);      // LEM - V
      CMPSS_DIG_FILTER(Cmpss3Regs, LEM_curHi, LEM_curLo);      // LEM - W
    }
    if (SENSES & bit(SHUNT_CURRENT_SENSE)) {
      CMPSS_DIG_FILTER(Cmpss2Regs, SHUNT_curHi, SHUNT_curLo);  // SHUNT - V
      CMPSS_DIG_FILTER(Cmpss6Regs, SHUNT_curHi, SHUNT_curLo);  // SHUNT - U
    }
    EDIS;
	// Check for PWM trip due to over current or over speed
    if (!TripFlag) TripFlag = EPwm1Regs.TZFLG.all
     || EPwm2Regs.TZFLG.all
     || EPwm3Regs.TZFLG.all;	// Trip on DMC (halt and IPM fault trip )
  }

  if (TripFlag) {
	// if any EPwm's OST is set, force OST on all three to DISABLE inverter
    EALLOW;
    EPwm1Regs.TZFRC.all = 1<<2;
    EPwm2Regs.TZFRC.all = 1<<2;
    EPwm3Regs.TZFRC.all = 1<<2;
    EDIS;
    RunMotor = false;
  }
	// If clear cmd received, reset PWM trip
  if (TripFlagClear) {
    TripFlag = false;
    TripFlagClear = false;
    EALLOW;
		// clear OST and DCAEVT1 flags
    EPwm1Regs.TZCLR.all = EPwm1Regs.TZFLG.all;
    EPwm2Regs.TZCLR.all = EPwm2Regs.TZFLG.all;
    EPwm3Regs.TZCLR.all = EPwm3Regs.TZFLG.all;
		// clear LLATCH and HLATCH - (not in TRIP gen path)
    Cmpss1Regs.COMPSTSCLR.all = 1<<1 | 1<<9;
    Cmpss3Regs.COMPSTSCLR.all = 1<<1 | 1<<9;
    Cmpss2Regs.COMPSTSCLR.all = 1<<1 | 1<<9;
    Cmpss6Regs.COMPSTSCLR.all = 1<<1 | 1<<9;
    EDIS;
  }
}

// Note that the vectorial sum of d-q PI outputs should be less than 1.0 which
// refers to maximum duty cycle for SVGEN.
// Another duty cycle limiting factor is current sense
// through shunt resistors which depends on hardware/software implementation.
// Depending on the application requirements 3,2 or a single
// shunt resistor can be used for current waveform reconstruction.
// The higher number of shunt resistors allow the higher duty cycle operation
// and better dc bus utilization.
// The users should adjust the PI saturation levels carefully during
// open loop tests (i.e pi_id.Umax, pi_iq.Umax and Umins) as in project manuals.
// Violation of this procedure yields distorted current
// waveforms and unstable closed loop operations which may damage the inverter.

//  DMC Protection Against Over Current Protection
static void cmpssConfig(volatile CMPSS_REGS&regs, int16 Hi, int16 Lo) {
	// Set up COMPCTL register
  regs.COMPCTL.bit.COMPDACE    = 1;	// Enable CMPSS
  regs.COMPCTL.bit.COMPLSOURCE = 0;	// NEG signal from DAC for COMP-L
  regs.COMPCTL.bit.COMPHSOURCE = 0;	// NEG signal from DAC for COMP-H
  regs.COMPCTL.bit.COMPHINV    = 0;	// COMP-H output is NOT inverted
  regs.COMPCTL.bit.COMPLINV    = 1;	// COMP-L output is inverted
  regs.COMPCTL.bit.ASYNCHEN    = 0;	// Disable aynch COMP-H ouput
  regs.COMPCTL.bit.ASYNCLEN    = 0;	// Disable aynch COMP-L ouput
  regs.COMPCTL.bit.CTRIPHSEL    = 2;	// Dig filter output ==> CTRIPH
  regs.COMPCTL.bit.CTRIPOUTHSEL = 2;	// Dig filter output ==> CTRIPOUTH
  regs.COMPCTL.bit.CTRIPLSEL    = 2;	// Dig filter output ==> CTRIPL
  regs.COMPCTL.bit.CTRIPOUTLSEL = 2;	// Dig filter output ==> CTRIPOUTL
	// Set up COMPHYSCTL register
  regs.COMPHYSCTL.bit.COMPHYS   = 2;	// COMP hysteresis set to 2x typical value
	// set up COMPDACCTL register
  regs.COMPDACCTL.bit.SELREF    = 0;	// VDDA is REF for CMPSS DACs
  regs.COMPDACCTL.bit.SWLOADSEL = 0;	// DAC updated on sysclock
  regs.COMPDACCTL.bit.DACSOURCE = 0;	// Ramp bypassed
	// Load DACs - High and Low
  regs.DACHVALS.bit.DACVAL = Hi;	// Set DAC-H to allowed MAX +ve current
  regs.DACLVALS.bit.DACVAL = Lo;	// Set DAC-L to allowed MAX -ve current
	// digital filter settings - HIGH side
  regs.CTRIPHFILCLKCTL.bit.CLKPRESCALE = clkPrescale;	// set time between samples, max : 1023
  regs.CTRIPHFILCTL.bit.SAMPWIN        = sampwin;	// # of samples in window, max : 31
  regs.CTRIPHFILCTL.bit.THRESH         = thresh;	// recommended : thresh > sampwin/2
  regs.CTRIPHFILCTL.bit.FILINIT        = 1;		// Init samples to filter input value
	// digital filter settings - LOW side
  regs.CTRIPLFILCLKCTL.bit.CLKPRESCALE = clkPrescale;	// set time between samples, max : 1023
  regs.CTRIPLFILCTL.bit.SAMPWIN        = sampwin;	// # of samples in window, max : 31
  regs.CTRIPLFILCTL.bit.THRESH         = thresh;	// recommended : thresh > sampwin/2
  regs.CTRIPLFILCTL.bit.FILINIT        = 1;		// Init samples to filter input value
	// Clear the status register for latched comparator events
  regs.COMPSTSCLR.bit.HLATCHCLR = 1;
  regs.COMPSTSCLR.bit.LLATCHCLR = 1;
}

static void InitPwmTrip(volatile EPWM_REGS&regs,Uint16 tzsel) {
  regs.DCTRIPSEL.all = 3<<0;		// Digital Comparator A High Input kommt von TripIn 4
  regs.TZDCSEL.all = TZ_DCAH_HI<<0;	// Digital Comparator A Event 1 Select: DCAH==H && DCAL=x
  regs.DCACTL.all = DC_EVT_ASYNC<<1;	// asynchron
  regs.TZSEL.all = tzsel;
  regs.TZCTL.all= TZ_FORCE_HI<<0 | TZ_FORCE_HI<<2;	// Ausgang A und B auf HIGH wenn One-Shot-Trip kommt
  regs.TZCLR.all = 1<<2 | 1<<3;		// Clear any spurious OV trip
}

void Trip::InitAll() {
// Digitale Eingänge für das Abschalten der PWM bereitstellen
  configGpioIn(14,false);		// mit Eingangsinvertierung und Pullup
  configGpioIn(24,false);		// TODO: Erst mal low-aktiver Trip damit der Eingang offen bleiben kann
//  GpioCtrlRegs.GPAINV.all |=  bit(14)|bit(24);	// High = PWM Stop
//  GpioCtrlRegs.GPAPUD.all &=~(bit(14)|bit(24));	// offener Eingang = PWM Stop
  InputXbarRegs.INPUT1SELECT = 24;	// Select GPIO24 as INPUTXBAR1 = !TZ1 for tripping PWM1..3
  InputXbarRegs.INPUT2SELECT = 14;	// Select GPIO14 as INPUTXBAR2 = !TZ2 for tripping PWM4..6
  if (BUILDLEVEL>1) {
	//Clearing the Fault(active low), GPIO41,
	// Configure as Output
//  GpioCtrlRegs.GPBPUD.bit.GPIO41  = 1; // disable pull ups
//  GpioCtrlRegs.GPBMUX1.bit.GPIO41 = 0; // choose GPIO for mux option
    configGpioOut(41);
    GpioDataRegsA.doSET(41);
//    GpioCtrlRegs.GPBDIR.bit.GPIO41  = 1; // set as output
//    GpioDataRegs.GPBSET.bit.GPIO41  = 1;

	// LEM Current phase V(ADC A2, COMP1) and W(ADC B2, COMP3), High Low Compare event trips
    if (SENSES & bit(LEM_CURRENT_SENSE)) {
//  LEM_curHi = 2048 + LEM(curLimit);
//  LEM_curLo = 2048 - LEM(curLimit);
      cmpssConfig(Cmpss1Regs, LEM_curHi, LEM_curLo);  //Enable CMPSS1 - LEM V
      cmpssConfig(Cmpss3Regs, LEM_curHi, LEM_curLo);  //Enable CMPSS3 - LEM W
    }

    if (SENSES & bit(SHUNT_CURRENT_SENSE)) {
	// Shunt Current phase V(ADC A4, COMP2) and W(ADC C2, COMP6), High Low Compare event trips
//    SHUNT_curHi = 2048 + SHUNT(curLimit);
//    SHUNT_curLo = 2048 - SHUNT(curLimit);
      cmpssConfig(Cmpss2Regs, SHUNT_curHi, SHUNT_curLo);  //Enable CMPSS2 - Shunt V
      cmpssConfig(Cmpss6Regs, SHUNT_curHi, SHUNT_curLo);  //Enable CMPSS6 - Shunt U
    }

	// Configure TRIP 4 to OR the High and Low trips from both comparator 1 & 3
    EPwmXbarRegs.TRIP4MUX0TO15CFG.all  = bit(0) | bit(4) | bit(2) | bit(10) | bit(3);
    EPwmXbarRegs.TRIP4MUX16TO31CFG.all = 0;
	// Enable Muxes for ored input of CMPSS1H and 1L, i.e. .1 mux for Mux0
//  MUX0  = 1;  //cmpss1 - tripH or tripL
//  MUX4  = 1;  //cmpss3 - tripH or tripL
//  MUX2  = 1;  //cmpss2 - tripH or tripL
//  MUX10 = 1;  //cmpss6 - tripH or tripL
//  MUX3  = 1;  //inputxbar2 trip

	// Enable Mux 0 OR Mux 4 to generate TRIP4
    EPwmXbarRegs.TRIP4MUXENABLE.all = bit(0) | bit(4) | bit(2) | bit(10) | bit(1);
  }
  InitPwmTrip(EPwm1Regs,1<<14 | 1<<0 | 1<<5);	// Bit 14: DCAEVT1 = Quelle für Dauer-Aus
  InitPwmTrip(EPwm2Regs,1<<14 | 1<<0 | 1<<5);	// Bit 8: TZ1 (GPIO24) = Quelle für Dauer-Aus
  InitPwmTrip(EPwm3Regs,1<<14 | 1<<0 | 1<<5);	// Bit 5: TZ6 = Quelle für Zyklus-Aus
  InitPwmTrip(EPwm4Regs,1<<14 | 1<<1 | 1<<5);	// Bit 14: DCAEVT1 = Quelle für Dauer-Aus
  InitPwmTrip(EPwm5Regs,1<<14 | 1<<1 | 1<<5);	// Bit 9: TZ2 (GPIO14) = Quelle für Dauer-Aus
  InitPwmTrip(EPwm6Regs,1<<14 | 1<<1 | 1<<5);	// Bit 5: TZ6 = Quelle für Zyklus-Aus
	// What do we want the OST/CBC events to do?
	// TZA events can force EPWMxA
	// TZB events can force EPWMxB
}
Detected encoding: ASCII (7 bit)8