#include "shaftencoder.h" #include // TGLabel->SetText #include "MLog.h" #include "MLogManip.h" #include "macs.h" #include "network.h" ClassImp(ShaftEncoder); using namespace std; ShaftEncoder::ShaftEncoder(const BYTE_t nodeid, const char *name) : NodeDrv(nodeid, name), fPos(0), fVel(0), fAcc(0), fTurn(0), fTicks(0), fTurns(0), fDirection(kUndefined), fHysteresisPos(0), fHysteresisNeg(0), fLabel(NULL), fUpdPos(0), fPosHasChanged(false), fDirHasChanged(false), fReport(NULL), fMotor(NULL), fOffset(0), fDirChangedPos(0), fDirChangedOffset(0) { } /* void ShaftEncoder::CheckTwin(Int_t diff) const { if (!fTwin) return; if (fTwin->fIsUpdated) fTwin->fIsUpdated = kFALSE; else fTwin->fOffset += diff; } */ void ShaftEncoder::HandleSDO(WORD_t idx, BYTE_t subidx, LWORD_t val, const timeval_t &tv) { switch (idx) { case 0x1000: gLog << inf2 << "- Model: "; switch (val&0xffff) { case 0x0196: gLog << inf2 << "Shaft Encoder Type: "; switch ((val>>16)&0xff) { case 0x01: gLog << "Singleturn" << endl; return; case 0x02: gLog << "Multiturn" << endl; return; default: gLog << err << "?" << endl; SetZombie(); return; } default: gLog << err << "???" << endl; SetZombie(); return; } case 0x100b: // Do not display, this is used for CheckConnection // lout << "Node ID: " << dec << val << endl; return; case 0x100c: gLog << inf2 << "- Guardtime: " << dec << val << "ms" << endl; return; case 0x100d: gLog << inf2 << "- Lifetimefactor: " << dec << val << endl; return; case 0x100e: gLog << inf2 << "- CobId for guarding: 0x" << hex << val << endl; return; case 0x6000: case 0x6500: gLog << inf2 << "- Counting: " << (val&1 ?"anti-clockwise":"clockwise") << " "; gLog << "HwTest: " << (val&2 ?"on":"off") << " "; gLog << "Scaling: " << (val&4 ?"on":"off") << " "; gLog << "Modulo: " << (val&4096?"on":"off") << endl; return; case 0x6001: gLog << inf2 << "- Logical Ticks/Revolution: " << dec << val << endl; return; case 0x6004: gLog << inf2 << "- Reported position: " << dec << (Int_t)val << endl; fPos = val; fTurn = 0; fDirChangedPos = val; fOffset = fMotor ? fMotor->GetPdoPos() : 0; fPosHasChanged = true; fDirHasChanged = true; fDirection = kUndefined; //fIsUpdated=kTRUE; //fOffset = 0; return; case 0x6501: gLog << inf2 << "- Phys. Ticks/Revolution: " << dec << val << endl; fTicks = val; return; case 0x6502: //if (val==0) // val = 1; // Single Turn = Multiturn with one turn gLog << inf2 << "- Number of Revolutions: " << dec << val << endl; fTurns = val; return; } NodeDrv::HandleSDO(idx, subidx, val, tv); // gLog << err << hex << setfill('0'); // gLog << "Sdo=" << idx << "/" << (int)subidx << ": 0x" << setw(8) << val; // gLog << endl; } void ShaftEncoder::HandleSDOOK(WORD_t idx, BYTE_t subidx, LWORD_t data, const timeval_t &tv) { switch (idx) { case 0x1802: switch (subidx) { case 1: //lout << ddev(MLog::eGui); gLog << inf2 << "- " << GetNodeName() << ": PDOs configured." << endl; //lout << edev(MLog::eGui); return; } break; case 0x6001: switch (subidx) { case 0: //lout << ddev(MLog::eGui); gLog << inf2 << "- " << GetNodeName() << ": Log.ticks/revolution set." << endl; //lout << edev(MLog::eGui); return; } break; case 0x6002: switch (subidx) { case 0: //lout << ddev(MLog::eGui); gLog << inf2 << "- " << GetNodeName() << ": Max number of ticks set." << endl; //lout << edev(MLog::eGui); return; } break; case 0x6003: switch (subidx) { case 0: //lout << ddev(MLog::eGui); gLog << inf2 << "- " << GetNodeName() << ": Preset value set." << endl; //lout << edev(MLog::eGui); return; } break; } NodeDrv::HandleSDOOK(idx, subidx, data, tv); } void ShaftEncoder::DisplayVal() { const LWORDS_t pos = GetPos(); if (IsZombieNode()) { fLabel->SetText(new TGString("")); fUpdPos = ~pos; return; } char text[21]=""; if (pos!=fUpdPos && fLabel) { sprintf(text, "%ld", pos); fLabel->SetText(new TGString(text)); fUpdPos = pos; } } void ShaftEncoder::HandlePDOType0(const BYTE_t *data, const timeval_t &tv) { // // Decode information, we have a 14bit only // LWORDS_t pos = data[0] | (data[1]<<8) | (data[2]<<16); // | (data[3]<<24); //if (pos==fPos) // return; // Warning: A multiturn shaftencoder is assumed! if ((pos>fDirChangedPos && posfPos)) { fDirChangedPos = pos; fDirHasChanged = true; } else fOffset = fMotor ? fMotor->GetPdoPos() : 0; fPos = pos; fTime.Set(tv); fPosHasChanged = true; //CheckTwin(fPos-pos); //fIsUpdated=kTRUE; if (fReport) { fReport->Lock("ShaftEncoder::HandlePDOType0"); *fReport << "SE-REPORT " << (int)GetId() << " " << fTime << " PDO0 " << pos << " " << GetNodeName() << endl; fReport->UnLock("ShaftEncoder::HandlePDOType0"); } } void ShaftEncoder::HandlePDOType1(const BYTE_t *data, const timeval_t &tv) { // // Decode information, we have a 14bit only // LWORDS_t pos = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24); BYTE_t flag = data[4]; //if (fPos==pos) // return; // Warning: A multiturn shaftencoder is assumed! if ((pos>fDirChangedPos && posfPos)) { fDirChangedPos = pos; fDirHasChanged = true; } else fOffset = fMotor ? fMotor->GetPdoPos() : 0; //CheckTwin(fPos-pos); fPos=pos; fTime.Set(tv); fPosHasChanged=true; //fIsUpdated=kTRUE; //fOffset = 0; flag=flag; if (fReport) { fReport->Lock("ShaftEncoder::HandlePDOType1"); *fReport << "SE-REPORT " << (int)GetId() << " " << fTime << " PDO1 " << pos << " " << (int)flag << " " << GetNodeName() << endl; fReport->UnLock("ShaftEncoder::HandlePDOType1"); } } //#include //ofstream fout("log/shaftencoder.log"); void ShaftEncoder::HandlePDOType2(const BYTE_t *data, const timeval_t &tv) { // // Decode information, we have a 14bit only // LWORDS_t pos = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24); fVel = data[4] | (data[5]<<8); fAcc = data[6] | (data[7]<<8); const int dnlim = fTicks/10; const int uplim = fTurns*fTicks-dnlim; int turn = fTurn; if (fPos > uplim && pos < dnlim) turn++; if (fPos < dnlim && pos > uplim) turn--; LWORDS_t multipos = pos+turn*fTicks; // SE position of multiturn shaftencoder //if (fPos==pos && fTurn==fTurn) // return; //CheckTwin(fPos-pos); fOffset = fMotor ? fMotor->GetPdoPos() : 0; // Warning: A multiturn shaftencoder is assumed! if ((multipos>fDirChangedPos && multiposfPos)) { fDirChangedPos = GetPos(); fDirHasChanged = true; fDirChangedOffset = fOffset; } else { fDirHasChanged = false; } if (multipos>GetPos()) fDirection = kForward; else if (multiposLock("ShaftEncoder::HandlePDOType2"); *fReport << "SE-REPORT " << (int)GetId() << " " << fTime << " PDO2 " << pos << " " << fVel << " " << fAcc << " " << GetNodeName() << endl; *fReport << "DIR-REPORT " << (int)GetId() << " " << (Int_t)fDirHasChanged << " " << (Int_t)fDirChangedPos << endl; fReport->UnLock("ShaftEncoder::HandlePDOType2"); } } double ShaftEncoder::GetMjd() { return fTime.GetMjd(); } void ShaftEncoder::Init() { //----------------------------------------------------------------------- // Start Setup of the Shaft Encoder //----------------------------------------------------------------------- StopGuarding(); // // Requesting and checking (FIXME) type of encoder // gLog << inf2 << "- " << GetNodeName() << ": Requesting Hardware Type (0x1000)." << endl; RequestSDO(0x1000); WaitForSdo(0x1000); if (IsZombieNode()) return; // // Read physical ticks per revolution // gLog << inf2 << "- " << GetNodeName() << ": Requesting physical ticks/revolution (SDO 0x6501)." << endl; RequestSDO(0x6501); WaitForSdo(0x6501); // // Read number of possible ticks per revolution // gLog << inf2 << "- " << GetNodeName() << ": Requesting possible ticks/revolution (SDO 0x6502)." << endl; RequestSDO(0x6502); WaitForSdo(0x6502); // // Request Lifetimefactor for unknown reason to make guarding // working in SE/Az... (FIXME) // // lout << "- " << GetNodeName() << ": Requesting Lifetimefactor (Workaround, FIXME!) (SDO 0x100d)." << endl; // RequestSDO(0x100c); // WaitForSdo(0x100c); // RequestSDO(0x100d); // WaitForSdo(0x100d); // // Set logic ticks/revolution = physical ticks/revolution => scale factor = 1 // gLog << inf2 << "- " << GetNodeName() << ": Configuring log. tick/rev (0x6001)." << endl; SendSDO(0x6001, fTicks); WaitForSdo(0x6001); // // Set maximum number of ticks (ticks * turns) // gLog << inf2 << "- " << GetNodeName() << ": Configuring max number of ticks (0x6002)." << endl; SendSDO(0x6002, (LWORD_t)(fTicks*fTurns)); WaitForSdo(0x6002); // // Delete preset Value // gLog << inf2 << "- " << GetNodeName() << ": Delete preset value (0x6003)." << endl; SendSDO(0x6003, (LWORD_t)0xffffffff); WaitForSdo(0x6003); // // Configure PDOs // gLog << inf2 << "- " << GetNodeName() << ": Configuring PDOs (0x1802)." << endl; SendSDO(0x1802, 1, (LWORD_t)0x281); WaitForSdo(0x1802, 1); // // Request Parameter // gLog << inf2 << "- " << GetNodeName() << ": Requesting SDO 0x6000." << endl; RequestSDO(0x6000); WaitForSdo(0x6000); ReqPos(); gLog << inf2 << "- " << GetNodeName() << ": Start Node (NMT)." << endl; SendNMT(kNMT_START); /* cout << "---1---" << endl; MTimeout t(1000); while (!t.HasTimedOut()) usleep(1); cout << "---2---" << endl; */ // StartGuarding(200, 1, kTRUE); // 175 // StartGuarding(10*GetId(), 2); // 175 } void ShaftEncoder::CheckConnection() { // Request Node number RequestSDO(0x100b); WaitForSdo(0x100b); } void ShaftEncoder::ReqPos() { // // Request Position // gLog << inf2 << "- " << GetNodeName() << ": Requesting Position." << endl; RequestSDO(0x6004); WaitForSdo(0x6004); } void ShaftEncoder::SetPreset(LWORD_t pre) { gLog << inf2 << "- " << GetNodeName() << ": Setting Preset." << endl; SendSDO(0x6003, (LWORD_t)pre); if (!WaitForSdo(0x6003)) return; fPos = pre%fTicks; fTurn = pre/fTicks; fDirChangedPos = fPos; fOffset = fMotor ? fMotor->GetPdoPos() : 0; fPosHasChanged = true; fDirHasChanged = true; fDirection = kUndefined; } void ShaftEncoder::StopDevice() { gLog << inf2 << "- " << GetNodeName() << ": Stop Node (NMT)." << endl; SendNMT(kNMT_STOP); }