#include "shaftencoder.h" #include "timer.h" #include "network.h" #include // cout #include // setw, setfill #include // gSystem #include // TGLabel->SetText #include #include // PRIO_PROCESS ShaftEncoder::ShaftEncoder(BYTE_t nodeid, ostream &out=cout) : NodeDrv(nodeid, out), fLabel(NULL) { // // Show information // pthread_create(&fThread, NULL, MapUpdateThread, this); } ShaftEncoder::~ShaftEncoder() { pthread_cancel(fThread); } void ShaftEncoder::HandleSDO(WORD_t idx, BYTE_t subidx, LWORD_t val, struct timeval *tv) { switch (idx) { case 0x1000: cout << "Model: "; switch (val&0xffff) { case 0x0196: cout << "Shaft Encoder Type: "; switch ((val>>16)&0xff) { case 0x01: cout << "Singleturn" << endl; return; case 0x02: cout << "Multiturn" << endl; return; default: cout << "?" << endl; return; } default: cout << "???" << endl; return; } case 0x100b: cout << "Node ID: " << dec << val << endl; return; case 0x6000: case 0x6500: cout << "Counting: " << (val&1 ?"anti-clockwise":"clockwise") << " "; cout << "HwTest: " << (val&2 ?"on":"off") << " "; cout << "Scaling: " << (val&4 ?"on":"off") << " "; cout << "Modulo: " << (val&4096?"on":"off") << endl; case 0x6001: cout << "Logical Ticks/Turn: " << dec << val << endl; return; case 0x6004: cout << "Position: " << dec << val << endl; fPos = val; fTurn = 0; return; case 0x6501: cout << "Phys. Ticks/Turn: " << dec << val << endl; fTicks = val; return; case 0x6502: cout << "Possible Turns: " << dec << val << endl; fTurns = val ? val : 1; // Single Turn = Multiturn with one turn return; } cout << hex << setfill('0'); cout << "Sdo=" << idx << "/" << (int)subidx << ": 0x" << setw(8) << val; cout << endl; } void *ShaftEncoder::MapUpdateThread(void *data) { ShaftEncoder *se = (ShaftEncoder*) data; // // Detach thread (make sure that it is really removed from memory) // pthread_detach(pthread_self()); setpriority(PRIO_PROCESS, 0, 5); se->UpdateThread(); return NULL; } void ShaftEncoder::UpdateThread() { // // check for a running thread and lock mutex // char text[21]; // // Wait until the network and the output widget is initialized // while (!GetNetwork() || !fLabel) usleep(1); while (1) { WaitForNextPdo1(); // // Update information // sprintf(text, "%ld", fPos); fLabel[0]->SetText(new TGString(text)); sprintf(text, "%d", fVel); fLabel[1]->SetText(new TGString(text)); sprintf(text, "%d", fAcc); fLabel[2]->SetText(new TGString(text)); // // make updated information visible // gSystem->ProcessEvents(); } } void ShaftEncoder::HandlePDOType0(BYTE_t *data) { // // Decode information, we have a 14bit only // fPos = data[0] | (data[1]<<8) | (data[2]<<16); // | (data[3]<<24); } void ShaftEncoder::HandlePDOType1(BYTE_t *data) { // // 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]; pos=pos; flag=flag; } void ShaftEncoder::HandlePDOType2(BYTE_t *data, struct timeval *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); fTime.SetTimer(tv); const int uplim = 9*fTicks/10; const int dnlim = 1*fTicks/10; if (fPos > uplim && pos < dnlim) fTurn++; if (fPos < dnlim && pos > uplim) fTurn--; fPos = pos; } double ShaftEncoder::GetTime() { return fTime.GetTime(); } double ShaftEncoder::GetMjd() { return fTime.GetMjd(); } void ShaftEncoder::InitDevice(Network *net) { NodeDrv::InitDevice(net); //----------------------------------------------------------------------- // Start Setup of the Shaft Encoder //----------------------------------------------------------------------- // // Requesting and checking (FIXME) type of encoder // lout << "- Requesting SDO 0x1000 of " << (int)GetId() << endl; RequestSDO(0x1000); WaitForSdo(0x1000); // // Read physical ticks per turn // lout << "- Requesting SDO 0x6501 of " << (int)GetId() << endl; RequestSDO(0x6501); WaitForSdo(0x6501); // // Read number of possible ticks per turn // lout << "- Requesting SDO 0x6502 of " << (int)GetId() << endl; RequestSDO(0x6502); WaitForSdo(0x6502); // // Set logic ticks per turn = physical ticks per turn => scale factor = 1 // lout << "- Configuring SDO 0x6001 of " << (int)GetId() << endl; SendSDO(0x6001, fTicks); WaitForSdo(0x6001); // // Set maximum number of ticks (ticks * turns) // lout << "- Configuring SDO 0x6002 of " << (int)GetId() << endl; SendSDO(0x6002, (LWORD_t)(fTicks*fTurns)); WaitForSdo(0x6002); // // Configure PDOs // lout << "- Configuring SDO 0x1802 of " << (int)GetId() << endl; SendSDO(0x1802, 1, (LWORD_t)0x281); WaitForSdo(0x1802, 1); // // Delete preset Value // lout << "- Configuring SDO 0x6003 of " << (int)GetId() << endl; SendSDO(0x6003, (LWORD_t)0xffffffff); WaitForSdo(0x6003); // // Request Parameter // lout << "- Requesting SDO 0x6000 of " << (int)GetId() << endl; RequestSDO(0x6000); WaitForSdo(0x6000); ReqPos(); lout << "- Start Node " << (int)GetId() << endl; SendNMT(kNMT_START); } void ShaftEncoder::ReqPos() { // // Request Position // lout << "- Requesting Position of #" << (int)GetId() << endl; RequestSDO(0x6004); WaitForSdo(0x6004); } void ShaftEncoder::SetPreset(LWORD_t pre) { fPos = pre%16384; fTurn = pre/16384; lout << " - Setting Preset #" << (int)GetId() << endl; SendSDO(0x6003, (LWORD_t)fPos); WaitForSdo(0x6003); } void ShaftEncoder::StopDevice() { lout << "- Start Node " << (int)GetId() << endl; SendNMT(kNMT_STOP); }