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.

Files at this revision

API Documentation at this revision

Comitter:
humlet
Date:
Thu Mar 14 18:27:24 2013 +0000
Child:
1:9e595056c3da
Commit message:
initial;

Changed in this revision

FtEncoder.cpp Show annotated file Show diff for this revision Revisions of this file
FtEncoder.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FtEncoder.cpp	Thu Mar 14 18:27:24 2013 +0000
@@ -0,0 +1,44 @@
+#include "FtEncoder.h"
+
+FtEncoder::FtEncoder(PinName pwm, unsigned int standStillTimeout)
+    :m_encIRQ(pwm), m_cnt(0), m_standStillTimeout(standStillTimeout), m_cursor(0), m_ready(false)
+{
+    unsigned int tmStmp = getCurrentTimeStamp() - c_nTmStmps * m_standStillTimeout;
+    for(int i=0; i<c_nTmStmps-1; ++i)
+        m_timeStamps[i] = tmStmp + i*m_standStillTimeout;
+    m_cursor = c_nTmStmps-1;
+
+    m_encIRQ.rise(this, &FtEncoder::encoderISR);
+    m_encIRQ.fall(this, &FtEncoder::encoderISR);
+    m_tmOut.attach_us(this, &FtEncoder::encoderISR, 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 an 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();
+    m_tmOut.detach();
+    m_tmOut.attach_us(this, &FtEncoder::encoderISR, m_standStillTimeout);
+    m_callBack.call();
+    ++m_cnt;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FtEncoder.h	Thu Mar 14 18:27:24 2013 +0000
@@ -0,0 +1,76 @@
+#ifndef FTENCODER_H
+#define FTENCODER_H
+
+#include "InterruptIn.h"
+#include "us_ticker_api.h"
+#include "FunctionPointer.h"
+#include "Timeout.h"
+
+using namespace mbed;
+
+/// Simple Interface for the encoder of the red fischertechnik motors
+/// @note 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.
+/// 
+class FtEncoder
+{
+    static const float c_speedFactor = 1e6/75.0; // 1/(µs * 150/2) edges per revolution)
+    static const int c_nTmStmps = 1<<2;
+
+    InterruptIn m_encIRQ;
+    Timeout m_tmOut;
+
+    volatile unsigned int m_cnt;
+    unsigned int m_standStillTimeout;
+    volatile unsigned int m_cursor;
+    unsigned int m_timeStamps[c_nTmStmps];
+    bool m_ready;
+
+    FunctionPointer m_callBack;
+
+    /// ISR called on rising and falling encoder edges
+    void encoderISR();
+
+public:
+
+    /// create a simple interface to the encoder connected to the given pin
+    /// @param name of the pin the black encoder signl wire is connected to
+    /// @param standStillTimeout After this time [µs] without any encoder edge getSpeed() returns zero
+    FtEncoder(PinName pwm, unsigned int standStillTimeout=50000);
+
+    /// get number of falling and rising encoder edges
+    inline unsigned int getCounter() const {
+        return m_cnt;
+    };
+
+    /// reset the encoder edge counter to the given value (default is 0)
+    inline void resetCounter(unsigned int cnt=0) {
+        m_cnt=cnt;
+    };
+
+    /// get period [µs] between the two latest edges of same direction (rising or falling)
+    /// @note Returns standStillTimeout if motor stands still or no edges have been detected yet
+    unsigned int getLastPeriod() const;
+
+    /// get time stamp [µs] of last update i.e. encoder edge or timeout
+    unsigned int getTimeStampOfLastUpdate() const {
+        return m_timeStamps[m_cursor];
+    };
+
+    /// returns current time stamp [µs]
+    /// @note simply calls us_ticker_read() from mbed's C-API (capi/us_ticker_api.h)
+    inline unsigned int  getCurrentTimeStamp() const {
+        return us_ticker_read();
+    }
+
+    /// get speed in revolutions per second (Hz)
+    float getSpeed() const;
+
+    /// hook in a call back to the encoder ISR e.g. for sending a RTOS signal
+    void setCallBack(FunctionPointer callBack) {
+        m_callBack=callBack;
+    };
+};
+
+#endif
\ No newline at end of file