Control project for the Lift-arm. Works with ROS Melodic
Dependencies: mbed Servo ros_lib_melodic ULN2003_StepperDriver Async_4pin_Stepper
Diff: src/encoder.cpp
- Revision:
- 5:71c2f193a7f9
- Parent:
- 4:9edb248c6431
--- a/src/encoder.cpp Mon May 31 16:47:02 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,198 +0,0 @@ -#ifndef ENCODER_H -#define ENCODER_H - -/* Karbot encoder class - * - * This class is based upon the QEI class by Aaron Berk and the encoder class - * I wrote during ESP in 2nd year - * - * Written by Simon Krogedal - * 27/05/21 - * Team 9 4th Year project - * - * for NUCLEO-F401RE - * - */ - -#include "encoder.h" - - -encoder::encoder( - PinName chanA, - PinName chanB, - int CPR, - bool c, - double p, - double ec - ) : channelA_(chanA, PullUp), - channelB_(chanB, PullUp), - c_d(c), - period(p), - enc_const(ec) { - - pulses_ = 0; - pulsesPerRev_ = CPR; - tot_clicks = 0; - click_rate = 0; - temp_tot = 0; - - //Workout what the current state is. - int channA = channelA_.read(); - int channB = channelB_.read(); - - //2-bit state. - currState_ = (channA << 1) | (channB); - prevState_ = currState_; - - //X4 encoding uses interrupts on channel A, - //and on channel B. - channelA_.rise(callback(this, &encoder::encode)); - channelA_.fall(callback(this, &encoder::encode)); - channelB_.rise(callback(this, &encoder::encode)); - channelB_.fall(callback(this, &encoder::encode)); -} - -void encoder::reset(void) { - pulses_ = 0; -} - -int encoder::getCurrentState(void) { - - return currState_; - -} - -int encoder::getPulses(void) { - - return pulses_; - -} - -// +-------------+ -// | X2 Encoding | -// +-------------+ -// -// When observing states two patterns will appear: -// -// Counter clockwise rotation: -// -// 10 -> 01 -> 10 -> 01 -> ... -// -// Clockwise rotation: -// -// 11 -> 00 -> 11 -> 00 -> ... -// -// We consider counter clockwise rotation to be "forward" and -// counter clockwise to be "backward". Therefore pulse count will increase -// during counter clockwise rotation and decrease during clockwise rotation. -// -// +-------------+ -// | X4 Encoding | -// +-------------+ -// -// There are four possible states for a quadrature encoder which correspond to -// 2-bit gray code. -// -// A state change is only valid if of only one bit has changed. -// A state change is invalid if both bits have changed. -// -// Clockwise Rotation -> -// -// 00 01 11 10 00 -// -// <- Counter Clockwise Rotation -// -// If we observe any valid state changes going from left to right, we have -// moved one pulse clockwise [we will consider this "backward" or "negative"]. -// -// If we observe any valid state changes going from right to left we have -// moved one pulse counter clockwise [we will consider this "forward" or -// "positive"]. -// -// We might enter an invalid state for a number of reasons which are hard to -// predict - if this is the case, it is generally safe to ignore it, update -// the state and carry on, with the error correcting itself shortly after. -void encoder::encode(void) { - - int change = 0; - int chanA = channelA_.read(); - int chanB = channelB_.read(); - - //2-bit state. - currState_ = (chanA << 1) | (chanB); - - //Entered a new valid state. - if (((currState_ ^ prevState_) != INVALID) && (currState_ != prevState_)) { - //2 bit state. Right hand bit of prev XOR left hand bit of current - //gives 0 if clockwise rotation and 1 if counter clockwise rotation. - change = (prevState_ & PREV_MASK) ^ ((currState_ & CURR_MASK) >> 1); - - if (change == 0) { - change = -1; - } - - pulses_ -= change; - } - - prevState_ = currState_; - -} - -void encoder::sample_func(void) { - int clicks = getPulses(); - click_rate = ((double)clicks / period); - reset(); //reset clicks - tot_clicks += clicks; - temp_tot += clicks; -} - -double encoder::getClicks(void) { -// test_sample(); - if(c_d) - return click_rate; - else - return -click_rate; -} - -double encoder::getSpeed(void) { - double s = click_rate * enc_const; //angular frequency = 2pi*CPS/CPR and v = omega*r - if(c_d) - return s; - else - return -s; -} - -double encoder::getDistance(void) { //calculates total distance and returns it -// test_sample(); - double d = ((double)click_store * enc_const); - if(c_d) - return d; - else - return -d; -} - -double encoder::tempDist(void) { //calculates total distance and returns it -// test_sample(); - double d = ((double)temp_tot * enc_const); - if(c_d) - return d; - else - return -d; -} - -void encoder::distRst(void) { - int temp; - if(c_d) - temp = tot_clicks; - else - temp = -tot_clicks; - if(temp > click_store) - click_store = temp; - tot_clicks = 0; -} - -void encoder::tempRst(void) {temp_tot = 0;} - -void encoder::start(void) {sampler.attach(callback(this, &encoder::sample_func), period);} - -#endif \ No newline at end of file