#pragma once
// Include "Settings.h" first
inline float frac(float x) {return x-int(x);}
class QEP{ // Quadrature Encoder Driver object
public:
inline float getElecTheta() const{ // Output: Motor Electrical Angle (0..<1)
return frac(PolePairs*MechTheta);
}
inline float getMechTheta() const{ // Output: Motor Mechanical Angle (0..<1)
return MechTheta;
}
inline bool getDirection() const{ // Output: Motor rotation direction
return regs.QEPSTS.bit.QDF;
}
private:
// Uint16 QepPeriod; // Output: Capture period of QEP signal in number of EQEP capture timer (QCTMR) period
// Uint32 QepCountIndex; // Variable: Encoder counter index
float MechScaler; // Parameter: 1/lines
int32_t LineEncoder; // Constant: Lines of encoder × 4
uint16_t PolePairs; // Parameter: Number of pole pairs
float MechTheta; // Output: Motor Mechanical Angle
volatile EQEP_REGS®s;
public:
inline void init(int32_t a4i=0, bool invert=false) { // was QEP_INIT_MACRO(m,v)
regs.QEPCTL.all = 0x821E; // FREE_SOFT[1]|IEI[1]|IEL[0]|QPEM|QLCM|UTE
regs.QUPRD = F_CPU/100; // Unit Timer for 100 Hz
regs.QCAPCTL.all = 0x8075; // CEN|CCPS[2:0]|UPPS[2,0]
regs.QPOSINIT = a4i; // set index marker's angle (for rising edge)
if (invert) regs.QDECCTL.bit.SWAP = 1;
// Unit Position Event Prescaler = 32,
// capture timer clock prescaler = 128
regs.QPOSMAX = LineEncoder-1;
}
inline void resetPos() {
regs.QCLR.bit.IEL = 1; // Absolute position is now unknown
//setPos();
}
inline int32_t getPos() const {return regs.QPOSCNT;}
inline void setPos(int32_t newpos=0, bool relative=false, bool moveReference=false) {
regs.QEPCTL.bit.QPEN = 0; // don't count while twiddeling on position
int32_t diff = newpos;
if (relative) newpos+=regs.QPOSCNT;
else diff-=regs.QPOSCNT;
regs.QPOSCNT = newpos;
regs.QEPCTL.bit.QPEN = 1; // now continue counting
if (moveReference) {
int32_t n = regs.QPOSINIT + diff;
int32_t lines = regs.QPOSMAX+1;
while (n<0) n+=lines;
while (n>=lines) n-=lines;
regs.QPOSINIT = n;
}
}
inline bool isAbsolute() const {return regs.QFLG.bit.IEL;}
inline void operator() () { // was QEP_MACRO(m,v)
// Compute the mechanical angle
MechTheta = MechScaler*regs.QPOSCNT;
// Check unit Time out-event for speed calculation:
// Unit Timer is configured for 100Hz in INIT function
if (regs.QFLG.bit.UTO) {
// Low Speed Calculation — Capture Counter overflowed, hence do no compute speed
if (regs.QEPSTS.bit.COEF || regs.QEPSTS.bit.CDEF) regs.QEPSTS.all = 0x000C;
// else if (regs.QCPRDLAT!=0xffff) QepPeriod = regs.QCPRDLAT;
} // Compute lowspeed using capture counter value
}
QEP(volatile EQEP_REGS&r,Uint16 polepairs,Uint16 lines,float gear=1):
regs(r),
PolePairs(polepairs),
LineEncoder(lines<<2),
MechScaler(gear/(lines<<2)) // gear = (optionales) Getriebe
{}
};
Detected encoding: ASCII (7 bit) | 8
|