Interface for the encoder of the red fischertechnik motors

Dependencies:   NeedfulThings

Simple Interface for the simple encoder of the red fischertechnik motors.

The interface counts both, rising and falling edges, resulting in 150 counts per revolution. The interface also provides a speed measurement updated with each edge.

Connect the green wire to GND, the red one to +3.3V and the black signal line to any of mbed numbered pins. Additionally connect the signal line via a pullup resitor to +3.3V. A 10K resistor works fine.

FtEncoder.cpp

Committer:
humlet
Date:
2013-03-25
Revision:
2:1bf9f7b6bf29
Parent:
1:9e595056c3da

File content as of revision 2:1bf9f7b6bf29:

#include "FtEncoder.h"

FtEncoder::FtEncoder(PinName pwm, unsigned int standStillTimeout)
    :m_encIRQ(pwm),
     m_cnt(0),
     m_standStillTimeout(standStillTimeout),
     m_cursor(0)
{
    // initialize the edge timestamp ringbuffer
    unsigned int tmStmp = getCurrentTimeStamp() - c_nTmStmps * m_standStillTimeout;
    for(int i=0; i<c_nTmStmps; ++i)
        m_timeStamps[i] = tmStmp + i*m_standStillTimeout;
    m_cursor = c_nTmStmps-1;

    m_encIRQ.mode(PullUp); // set it to pullup, but an external pullup is needed, the internal isn't sufficient
    m_encIRQ.rise(this, &FtEncoder::encoderISR);
    m_encIRQ.fall(this, &FtEncoder::encoderISR);
    m_tmOut.attach_us(this, &FtEncoder::timeoutISR, m_standStillTimeout);
}

unsigned int FtEncoder::getLastPeriod() const
{
    unsigned int period = 0;
    unsigned int cursor, cnt;
    do {
        cursor = m_cursor;
        cnt = m_cnt;
        period = m_timeStamps[m_cursor] - m_timeStamps[(m_cursor-2)&(c_nTmStmps-1)];
    } while(cursor!=m_cursor || cnt!=m_cnt); // stay in loop until we have a non intrrupted reading
    return period;
}

float FtEncoder::getSpeed() const
{
    unsigned int period = getLastPeriod();
    return (period!=0 && period<m_standStillTimeout) ?
           c_speedFactor/period : 0.0;
}

void FtEncoder::encoderISR()
{
    ++m_cursor;
    m_cursor &= c_nTmStmps-1;
    m_timeStamps[m_cursor] = getCurrentTimeStamp();
    // restart the timeout
    m_tmOut.remove();
    m_tmOut.insert(m_timeStamps[m_cursor]+m_standStillTimeout);
    ++m_cnt;
    m_callBack.call();
}

void FtEncoder::timeoutISR(){
    --m_cnt;
    encoderISR();
}