/****************************************************************************** * W471to4.cpp: CAN communication to iseg Multi-Channel HV modules: * EHQ200.. * EHQF0.. * EHQ80.. * EHQ82.. * EHQ86.. * EHQF6.. * * written by Jens Roemer */ #include "stdafx.h" #include #include "isegCANHVCon.h" /*============================================================================ * memory reverse copy to change the data format */ void * __cdecl memrcpy ( void * dst, const void * src, size_t count ) { void * ret = dst; /* Low Endian to Big Endian * copy from lower addresses to higher addresses */ src = (char *)src+(count-1); while (count--) { *(char *)dst = *(char *)src; dst = (char *)dst + 1; src = (char *)src - 1; } return(ret); } void CanLogOnOff(uw16 id, uw8 state) { uw8 buff[10]; char tstamp[20]; strcpy(tstamp, SendTime); buff[0]=2; buff[1]=DATA_ID_MOD_LOG_ON; buff[2]=state; Write2Can(id, buff, tstamp); } /************************************************************************************* * check CAN message buffer if an active message has been received from HV module * output an information if it is an active error message * channge the state of HV modules to connect if it is an log on message */ void ScanCanBuff(void) { uw16 ID; uw8 buff[10]; char tstamp[20]; char str[128]; char s[10]; while ( (ReadfBuff(&ID, buff, tstamp)) || (ReadfCan(&ID, buff, tstamp)) //make a blank CAN buffer ) { if ( ((ID&0x200)==0) // active message && (*(buff+1)==0xc0) // status message ) { if ( ( *(buff+2)&1) == 0 ) { strcpy(str, "Sumbit ErrI, ErrV, ErrT or ErrF is occured at CAN device "); strcat(str, itoa(((ID>>3)&0x3f), s,10)); printf("%s\n", str); } if (( *(buff+2)&4) == 0 ) { strcpy(str, "Savetyloop is not closed at CAN device "); strcat(str, itoa(((ID>>3)&0x3f), s,10)); printf("%s\n", str); } if (( *(buff+2)&0x40) == 0 ) { strcpy(str, "Hardware voltage limit to low at CAN device "); strcat(str, itoa(((ID>>3)&0x3f), s,10)); printf("%s\n", str); } if ( ( *(buff+3)&0x40) ) { strcpy(str, "Temperature greater than 55°C at CAN device "); strcat(str, itoa(((ID>>3)&0x3f), s,10)); printf("%s\n", str); } else if ( ( *(buff+2)&0x20) == 0 ) { strcpy(str, "Voltage supplies are out of bounds at CAN device "); strcat(str, itoa(((ID>>3)&0x3f), s,10)); printf("%s\n", str); } } else if (buff[1]==DATA_ID_MOD_LOG_ON) { CanLogOnOff(ID&0x7fe, connect); //HV modules which changed the state back from connect to disconnect are //are switched to connect again } ID=0; } } //---------------------------------------------------------------------------- // THVChannel //------------ THVChannel::THVChannel(uw16 id, uw8 chn) { myIDC=id; myChn=chn; myVset.V = 0; myVset.Q = QUALITY_BAD; myIset.V = 0; myIset.Q = QUALITY_BAD; myItrip.V = 0; myItrip.Q = QUALITY_BAD; myVmeas.V = 0; myVmeas.Q = QUALITY_BAD; myImeas.V = 0; myImeas.Q = QUALITY_BAD; myNominal.V = 0; myNominal.I = 0; myNominal.Q = QUALITY_BAD; myStat.V = 0; myStat.Q = QUALITY_BAD; } THVChannel::~THVChannel(void) { } void THVChannel::SetVset(uw32 vset) { uw8 buff[5]; char tstamp[20]; buff[0]=HVModule->GetDataWhidth()+1; buff[1]=DATA_ID_CHN_SET_VOLTAGE|myChn; memrcpy( buff+2, (uw8 *)&vset, HVModule->GetDataWhidth()); strcpy(tstamp, SendTime); Write2Can(myIDC, buff, tstamp); } TChVal THVChannel::GetVset() { uw8 buff[10]; char tstamp[20]; ScanCanBuff(); buff[0]=1; buff[1]=DATA_ID_CHN_SET_VOLTAGE|myChn; strcpy(tstamp, SendTime); if (WriteReadfCan(myIDC|DATA_DIR, buff, tstamp)) { memrcpy((uw8*)&myVset.V, buff+2, HVModule->GetDataWhidth()); myVset.Q=QUALITY_GOOD; strcpy(myVset.TSt, tstamp); } else myVset.Q=QUALITY_BAD; return myVset; } //==================================================================================================== void THVChannel::SetIset(uw32 Iset) { uw8 buff[5]; char tstamp[20]; buff[0]=HVModule->GetDataWhidth()+1; buff[1]=DATA_EXTID_CHN_SET_CURRENT|myChn; memrcpy(buff+2, (uw8 *)&Iset, HVModule->GetDataWhidth()); strcpy(tstamp, SendTime); Write2Can(myIDC|EXT_INSTR, buff, tstamp); } TChVal THVChannel::GetIset() { uw8 buff[10]; char tstamp[20]; ScanCanBuff(); buff[0]=1; buff[1]=DATA_EXTID_CHN_SET_CURRENT|myChn; strcpy(tstamp, SendTime); if (WriteReadfCan(myIDC|EXT_INSTR|DATA_DIR, buff, tstamp)) { memrcpy((uw8*)&myIset.V, buff+2, HVModule->GetDataWhidth()); myIset.Q=QUALITY_GOOD; strcpy(myIset.TSt, tstamp); } else myIset.Q=QUALITY_BAD; return myIset; } //==================================================================================================== TChVal THVChannel::GetVmeas() { uw8 buff[10]; char tstamp[20]; ScanCanBuff(); buff[0]=1; buff[1]=DATA_ID_CHN_ACTUAL_VOLTAGE|myChn; strcpy(tstamp, SendTime); if (WriteReadfCan(myIDC|DATA_DIR, buff, tstamp)){ memrcpy((uw8*)&myVmeas.V, buff+2, HVModule->GetDataWhidth()); myVmeas.Q=QUALITY_GOOD; strcpy(myVmeas.TSt, tstamp); } else myVmeas.Q=QUALITY_BAD; return myVmeas; } //=================================================================================== TChVal THVChannel::GetImeas() { uw8 buff[10]; char tstamp[20]; ScanCanBuff(); buff[0]=1; buff[1]=DATA_ID_CHN_ACTUAL_CURRENT|myChn; strcpy(tstamp, SendTime); if (WriteReadfCan(myIDC|DATA_DIR, buff, tstamp)) { memrcpy((uw8*)&myImeas.V, buff+2, HVModule->GetDataWhidth()); myImeas.Q=QUALITY_GOOD; strcpy(myImeas.TSt, tstamp); } else myImeas.Q=QUALITY_BAD; return myImeas; } //======================================================================================== TChVal THVChannel::GetStat() { uw8 buff[10]; char tstamp[20]; ScanCanBuff(); buff[0]=1; buff[1]=DATA_ID_CHN_STATUS|myChn; strcpy(tstamp, SendTime); if (WriteReadfCan(myIDC|DATA_DIR, buff, tstamp)) { memrcpy((uw8*)&myStat.V, buff+2, 2); myStat.Q=QUALITY_GOOD; strcpy(myStat.TSt, tstamp); } else myStat.Q=QUALITY_BAD; return myStat; } //============================================================================================================ void THVChannel::SetItrp(uw32 itrp) { uw8 buff[5]; char tstamp[20]; buff[0]=HVModule->GetDataWhidth()+1; buff[1]=DATA_EXTID_CHN_SET_CURRENT_TRIP|myChn; memrcpy(buff+2,(uw8*)&itrp, HVModule->GetDataWhidth()); strcpy(tstamp, SendTime); Write2Can(myIDC|EXT_INSTR, buff, tstamp); } TChVal THVChannel::GetItrp() { uw8 buff[10]; char tstamp[20]; ScanCanBuff(); buff[0]=1; buff[1]=DATA_EXTID_CHN_SET_CURRENT_TRIP|myChn; strcpy(tstamp, SendTime); if (WriteReadfCan(myIDC|EXT_INSTR|DATA_DIR, buff, tstamp)) { memrcpy((uw8*)&myItrip.V, buff+2, HVModule->GetDataWhidth()); myItrip.Q=QUALITY_GOOD; strcpy(myItrip.TSt, SendTime); } else myItrip.Q=QUALITY_BAD; return myItrip; } //==================================================================================================== TNominals THVChannel::GetNominal() { uw8 buff[10]; char tstamp[20]; ScanCanBuff(); buff[0]=1; buff[1]=DATA_EXTID_CHN_NOMINALS|myChn; strcpy(tstamp, SendTime); if (WriteReadfCan(myIDC|EXT_INSTR|DATA_DIR, buff, tstamp)) { myNominal.V=(float)(buff[2]*pow(10, buff[3])); myNominal.I=(float)(buff[4]*pow(10, 3-(0x100-buff[5]))); myNominal.Q=QUALITY_GOOD; strcpy(myNominal.TSt, tstamp); } else myNominal.Q=QUALITY_BAD; return myNominal; } //============================================================================================================== //--------------------------------------------------------------------------- // THVModul //------------ THVModule::THVModule(uw16 id, uw8 maxchn, uw8 dc) { for (uw8 chn=0; chnGID, ""); myDevIDR->Active=false; strcpy(myDevIDR->SID,""); myDevIDR->Q = QUALITY_BAD; myRamp = new Tuw32Val; // Rampspeed myRamp->V = 0; myRamp->Q = QUALITY_BAD; myOnOff = new Tuw16Val; // word with on off flag per channel myOnOff->V = 0; myOnOff->Q = QUALITY_BAD; myNominal = new TNominals; myNominal->V = 0; myNominal->I = 0; myNominal->Q = QUALITY_BAD; myLogOn = new bool; *myLogOn = false; myGenStat = new TGenStat; // word with sum flags myGenStat->V = 0; myGenStat->Q = QUALITY_BAD; } THVModule::~THVModule(void) { if (myIDM) {delete myIDM; myIDM=NULL;} if (myDevClass) {delete myDevClass; myDevClass=NULL;} if (myDevIDR) {delete myDevIDR; myDevIDR=NULL;} if (myRamp) {delete myRamp; myRamp=NULL;} if (myOnOff) {delete myOnOff; myOnOff=NULL;} if (myNominal) {delete myNominal; myNominal=NULL;} if (myLogOn) {delete myLogOn; myLogOn=NULL;} if (myGenStat) {delete myGenStat; myGenStat=NULL;} } uw16 THVModule::GetID() { return *myIDM; // without R/W-bit } uw8 THVModule::GetDevClass() { return *myDevClass; } uw32 THVModule::GetRes() { switch (*myDevClass) { case EHQ200: case EHQ80_6kV: return 50000; case EHQ80_1kV_F: case EHQ82_1kV_F: case EHQ80_MIX_F: case EHQ80_6kV_F: return (uw32)10E6; default: return 50000; } } uw8 THVModule::GetDataWhidth() { switch(*myDevClass){ case EHQ200: case EHQ80_6kV: return 2; case EHQ80_1kV_F: case EHQ82_1kV_F: case EHQ80_MIX_F: case EHQ80_6kV_F: return 3; default: return 4; //all new HV modules will have 4 byte floating point format } } bool THVModule::GetLogOn() { uw8 Stat; char tstamp[20]; strcpy(tstamp, SendTime); *myLogOn=CanLogOnOff(myIDM, &Stat, myDevClass, tstamp); myGenStat->V=Stat; if (*myLogOn) return *myLogOn; //Module was conneted to Client else return false; } void THVModule::SetLogOn(bool logged) { uw8 buff[3]; char tstamp[20]; buff[0] = 0x02; //length buff[1] = DATA_ID_MOD_LOG_ON; buff[2] = logged; strcpy(tstamp, SendTime); Write2Can(*myIDM, buff, tstamp); } //=============================================================================================== void THVModule::SetRamp(uw32 ramp) { uw8 buff[10]; char tstamp[20]; buff[0]=GetDataWhidth()+1; buff[1]=DATA_ID_MOD_RAMP_SPEED; memrcpy(buff+2, (uw8*)&ramp, GetDataWhidth()); strcpy(tstamp, SendTime); Write2Can(*myIDM, buff, tstamp); } Tuw32Val THVModule::GetRamp() { uw8 buff[10]; char tstamp[20]; ScanCanBuff(); buff[0]=1; buff[1]=DATA_ID_MOD_RAMP_SPEED; strcpy(tstamp, SendTime); if (WriteReadfCan(*myIDM|DATA_DIR, buff, tstamp)) { memrcpy((uw8*)&myRamp->V, buff+2, GetDataWhidth()); myRamp->Q = QUALITY_GOOD; strcpy(myRamp->TSt, tstamp); } else myRamp->Q = QUALITY_BAD; return *myRamp; } //==================================================================================================== void THVModule::SetOnOff(uw16 on) { uw8 buff[4]; char tstamp[20]; buff[0]=0x03; buff[1]=DATA_ID_MOD_ON_OFF; memrcpy(buff+2, (uw8*)&on, 2); strcpy(tstamp, SendTime); Write2Can(*myIDM, buff, tstamp); } Tuw16Val THVModule::GetOnOff() { uw8 buff[10]; char tstamp[20]; ScanCanBuff(); buff[0]=1; buff[1]=DATA_ID_MOD_ON_OFF; strcpy(tstamp, SendTime); if (WriteReadfCan(*myIDM|DATA_DIR, buff, tstamp)) { myOnOff->V = (buff[2]<<8)+buff[3]; myOnOff->Q = QUALITY_GOOD; strcpy(myOnOff->TSt, tstamp); } else { myOnOff->Q = QUALITY_BAD; } return *myOnOff; } //================================================================================================================ TGenStat THVModule::GetGenStat() { uw8 buff[10]; char tstamp[20]; ScanCanBuff(); buff[0]=1; buff[1]=DATA_ID_MOD_GENERAL_STATUS; strcpy(tstamp, SendTime); if (WriteReadfCan(*myIDM|DATA_DIR, buff, tstamp)) { myGenStat->V = *(buff+2); myGenStat->Q = QUALITY_GOOD; strcpy(myGenStat->TSt, tstamp); } else myGenStat->Q = QUALITY_BAD; return *myGenStat; } //================================================================================================================ struct TNominals THVModule::GetNominal() { uw8 buff[10]; char tstamp[20]; ScanCanBuff(); buff[0]=1; buff[1]=DATA_ID_MOD_NOMINAL_VALUES; strcpy(tstamp, SendTime); if (WriteReadfCan(*myIDM|DATA_DIR, buff, tstamp)) { myNominal->V=(float)(buff[2]*pow(10,buff[3])); myNominal->I=(float)(buff[4]*pow(10,3-(0x100-buff[5]))); //1 nA Stromauflösung entspr. 10^9-(0x100-0xf7)=1 myNominal->Q=QUALITY_GOOD; strcpy(myNominal->TSt, SendTime); } else myNominal->Q=QUALITY_BAD; return *myNominal; } //================================================================================================================ TDevIDR THVModule::GetDevIDR() { uw8 buff[10]; char tstamp[20]; uw32 l; ScanCanBuff(); buff[0]=1; buff[1]=DATA_ID_MOD_DEVICE_SOFTWARE_ID; strcpy(tstamp, SendTime); if (WriteReadfCan(*myIDM|DATA_DIR, buff, tstamp)) { l=(buff[2]*0x10000)+(buff[3]*0x100)+buff[4]; ltoa(l,myDevIDR->GID,16); if ( (((buff[5]&0xf0)>>4)==4) || (((buff[5]&0xf0)>>4)==1) ) strcat(myDevIDR->GID, " active alarms"); else strcat(myDevIDR->GID, " passive alarms"); myDevIDR->SID[0]=(buff[5]&0xf)+0x30; myDevIDR->SID[1]='.'; myDevIDR->SID[2]=((buff[6]&0xf0)>>4)+0x30; myDevIDR->SID[3]=(buff[6]&0xf)+0x30; myDevIDR->SID[4]=0x00; myDevIDR->ChNb=buff[7]; myDevIDR->Q=QUALITY_GOOD; strcpy(myDevIDR->TSt, tstamp); } else myDevIDR->Q=QUALITY_BAD; return *myDevIDR; } //=============================================================================================================