sfbsg

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
borlanic
Date:
Tue Apr 03 15:17:11 2018 +0000
Commit message:
fg

Changed in this revision

DiffCounter.cpp Show annotated file Show diff for this revision Revisions of this file
DiffCounter.h Show annotated file Show diff for this revision Revisions of this file
EncoderCounter.cpp Show annotated file Show diff for this revision Revisions of this file
EncoderCounter.h Show annotated file Show diff for this revision Revisions of this file
GPA.cpp Show annotated file Show diff for this revision Revisions of this file
GPA.h Show annotated file Show diff for this revision Revisions of this file
IIR_filter.cpp Show annotated file Show diff for this revision Revisions of this file
IIR_filter.h Show annotated file Show diff for this revision Revisions of this file
LinearCharacteristics.cpp Show annotated file Show diff for this revision Revisions of this file
LinearCharacteristics.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DiffCounter.cpp	Tue Apr 03 15:17:11 2018 +0000
@@ -0,0 +1,35 @@
+#include "DiffCounter.h"
+
+using namespace std;
+/*      1/tau*(z-1)        
+G(z) = ------------
+         z - a0
+*/
+
+DiffCounter::DiffCounter(float time_constant, float SampleTime){
+    Ts = SampleTime;
+    alpha = 1/time_constant;            // scaling
+    a0 = -(1-Ts/time_constant);         // a0=-exp(-Ts/tau) ~= -(1-Ts/tau) 
+    inc_old = 0;                        // old values
+    v_old = 0;                          //   "  "
+    inc2rad = 2.0f*3.1415927f/(4.0f*6400.0);   // incr encoder with 6400inc/rev
+    }
+
+DiffCounter::~DiffCounter() {} 
+    
+void DiffCounter::reset(float initValue,short inc) {
+    v_old = initValue;
+    inc_old = inc;
+}
+
+float DiffCounter::doStep(short inc){
+    del = (long)(inc - inc_old);
+    if(del < -16000)
+        del += 0xFFFF;
+    if(del > 16000)
+        del -= 0xFFFF;
+    float vel = alpha * (float)del * inc2rad - a0 * v_old;
+    v_old = vel;
+    inc_old = inc;
+    return vel;
+    }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DiffCounter.h	Tue Apr 03 15:17:11 2018 +0000
@@ -0,0 +1,28 @@
+/*  DiffCounter Class, differentiate encoder counts for cuboid based on LP filter
+    and unwrapping
+    
+        1/tau*(z-1)        
+G(z) = ------------
+         z - a0
+*/
+
+class DiffCounter{
+     public:
+                    DiffCounter(float a,float b);
+        float operator()(short inc){
+         return doStep(inc);
+         }
+        virtual     ~DiffCounter();
+        void        reset(float,short);
+        float       doStep(short inc);
+        float       Ts;
+    
+    private:
+    
+        float alpha;
+        float a0;
+        short inc_old;
+        float v_old;
+        long del;
+        float inc2rad;
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EncoderCounter.cpp	Tue Apr 03 15:17:11 2018 +0000
@@ -0,0 +1,139 @@
+/*
+ * EncoderCounter.cpp
+ * Copyright (c) 2017, ZHAW
+ * All rights reserved.
+ */
+
+#include "EncoderCounter.h"
+
+using namespace std;
+
+/**
+ * Creates and initializes the driver to read the quadrature
+ * encoder counter of the STM32 microcontroller.
+ * @param a the input pin for the channel A.
+ * @param b the input pin for the channel B.
+ */
+EncoderCounter::EncoderCounter(PinName a, PinName b) {
+    
+    // check pins
+    
+    if ((a == PA_6) && (b == PC_7)) {
+        
+        // pinmap OK for TIM3 CH1 and CH2
+        
+        TIM = TIM3;
+        
+        // configure reset and clock control registers
+        
+        RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;    // manually enable port C (port A enabled by mbed library)
+        
+        // configure general purpose I/O registers
+        
+        GPIOA->MODER &= ~GPIO_MODER_MODER6;     // reset port A6
+        GPIOA->MODER |= GPIO_MODER_MODER6_1;    // set alternate mode of port A6
+        GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR6;     // reset pull-up/pull-down on port A6
+        GPIOA->PUPDR |= GPIO_PUPDR_PUPDR6_1;    // set input as pull-down
+        GPIOA->AFR[0] &= ~(0xF << 4*6);         // reset alternate function of port A6
+        GPIOA->AFR[0] |= 2 << 4*6;              // set alternate funtion 2 of port A6
+        
+        GPIOC->MODER &= ~GPIO_MODER_MODER7;     // reset port C7
+        GPIOC->MODER |= GPIO_MODER_MODER7_1;    // set alternate mode of port C7
+        GPIOC->PUPDR &= ~GPIO_PUPDR_PUPDR7;     // reset pull-up/pull-down on port C7
+        GPIOC->PUPDR |= GPIO_PUPDR_PUPDR7_1;    // set input as pull-down
+        GPIOC->AFR[0] &= ~0xF0000000;           // reset alternate function of port C7
+        GPIOC->AFR[0] |= 2 << 4*7;              // set alternate funtion 2 of port C7
+        
+        // configure reset and clock control registers
+        
+        RCC->APB1RSTR |= RCC_APB1RSTR_TIM3RST;  //reset TIM3 controller
+        RCC->APB1RSTR &= ~RCC_APB1RSTR_TIM3RST;
+        
+        RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;     // TIM3 clock enable
+        
+    } else if ((a == PB_6) && (b == PB_7)) {
+        
+        // pinmap OK for TIM4 CH1 and CH2
+        
+        TIM = TIM4;
+        
+        // configure reset and clock control registers
+        
+        RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;    // manually enable port B (port A enabled by mbed library)
+        
+        // configure general purpose I/O registers
+        
+        GPIOB->MODER &= ~GPIO_MODER_MODER6;     // reset port B6
+        GPIOB->MODER |= GPIO_MODER_MODER6_1;    // set alternate mode of port B6
+        GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR6;     // reset pull-up/pull-down on port B6
+        GPIOB->PUPDR |= GPIO_PUPDR_PUPDR6_1;    // set input as pull-down
+        GPIOB->AFR[0] &= ~(0xF << 4*6);         // reset alternate function of port B6
+        GPIOB->AFR[0] |= 2 << 4*6;              // set alternate funtion 2 of port B6
+        
+        GPIOB->MODER &= ~GPIO_MODER_MODER7;     // reset port B7
+        GPIOB->MODER |= GPIO_MODER_MODER7_1;    // set alternate mode of port B7
+        GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR7;     // reset pull-up/pull-down on port B7
+        GPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_1;    // set input as pull-down
+        GPIOB->AFR[0] &= ~0xF0000000;           // reset alternate function of port B7
+        GPIOB->AFR[0] |= 2 << 4*7;              // set alternate funtion 2 of port B7
+        
+        // configure reset and clock control registers
+        
+        RCC->APB1RSTR |= RCC_APB1RSTR_TIM4RST;  //reset TIM4 controller
+        RCC->APB1RSTR &= ~RCC_APB1RSTR_TIM4RST;
+        
+        RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;     // TIM4 clock enable
+        
+    } else {
+        
+        printf("pinmap not found for peripheral\n");
+    }
+    
+    // configure general purpose timer 3 or 4
+    
+    TIM->CR1 = 0x0000;          // counter disable
+    TIM->CR2 = 0x0000;          // reset master mode selection
+    TIM->SMCR = TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0; // counting on both TI1 & TI2 edges
+    TIM->CCMR1 = TIM_CCMR1_CC2S_0 | TIM_CCMR1_CC1S_0;
+    TIM->CCMR2 = 0x0000;        // reset capture mode register 2
+    TIM->CCER = TIM_CCER_CC2E | TIM_CCER_CC1E;
+    TIM->CNT = 0x0000;          // reset counter value
+    TIM->ARR = 0xFFFF;          // auto reload register
+    TIM->CR1 = TIM_CR1_CEN;     // counter enable
+}
+
+EncoderCounter::~EncoderCounter() {}
+
+/**
+ * Resets the counter value to zero.
+ */
+void EncoderCounter::reset() {
+    
+    TIM->CNT = 0x0000;
+}
+
+/**
+ * Resets the counter value to a given offset value.
+ * @param offset the offset value to reset the counter to.
+ */
+void EncoderCounter::reset(short offset) {
+    
+    TIM->CNT = -offset;
+}
+
+/**
+ * Reads the quadrature encoder counter value.
+ * @return the quadrature encoder counter as a signed 16-bit integer value.
+ */
+short EncoderCounter::read() {
+    
+    return (short)(-TIM->CNT);
+}
+
+/**
+ * The empty operator is a shorthand notation of the <code>read()</code> method.
+ */
+EncoderCounter::operator short() {
+    
+    return read();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EncoderCounter.h	Tue Apr 03 15:17:11 2018 +0000
@@ -0,0 +1,33 @@
+/*
+ * EncoderCounter.h
+ * Copyright (c) 2017, ZHAW
+ * All rights reserved.
+ */
+
+#ifndef ENCODER_COUNTER_H_
+#define ENCODER_COUNTER_H_
+
+#include <cstdlib>
+#include <mbed.h>
+
+/**
+ * This class implements a driver to read the quadrature
+ * encoder counter of the STM32 microcontroller.
+ */
+class EncoderCounter {
+    
+    public:
+        
+                    EncoderCounter(PinName a, PinName b);
+        virtual     ~EncoderCounter();
+        void        reset();
+        void        reset(short offset);
+        short       read();
+                    operator short();
+        
+    private:
+        
+        TIM_TypeDef*    TIM;
+};
+
+#endif /* ENCODER_COUNTER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GPA.cpp	Tue Apr 03 15:17:11 2018 +0000
@@ -0,0 +1,267 @@
+/*
+    GPA: frequency point wise gain and phase analyser to measure the frequency
+         respone of dynamical system
+    
+        hint:       the measurements should only be perfomed in closed loop
+        assumption: the system is at the desired steady state of interest when
+                    the measurment starts
+    
+                             exc(2)                 C: controller
+                               |                    P: plant
+                               v                     
+     exc(1) --> o   ->| C |--->o------->| P |----------> out
+                ^                  |             |
+                |                   --> inp      |  exc: excitation signal (E)
+                |                                |  inp: input plant (U)
+                 --------------------------------   out: output plant (Y)
+  
+    instantiate option 1:
+    GPA(float fMin, float fMax, int NfexcDes, int NperMin, int NmeasMin, float Ts, float Aexc0, float Aexc1)
+    
+        fMin:     minimal desired frequency that should be measured in Hz
+        fMax:     maximal desired frequency that should be measured in Hz
+        NfexcDes: number of logarithmic equaly spaced frequency points
+        NperMin:  minimal number of periods that are used for each frequency point
+        NmeasMin: maximal number of samples that are used for each frequency point
+        Ts:       sampling time
+        Aexc0:    excitation amplitude at fMin 
+        Aexc1:    excitation amplitude at fMax
+    
+        hints:    the amplitude drops with 1/fexc, if you're using
+                  Axc1 = Aexc0/fMax the d/dt exc = const., this is recommended
+                  if your controller does not have a rolloff.
+                  if a desired frequency point is not measured try to increase Nmeas.
+    
+    pseudo code for a closed loop measurement with a proportional controller Kp:
+    
+        float inp = "measurement of inputsignal";
+        float out = "mesurement of outputsignal";
+        float exc = myGPA(inp, out);
+        float off = "desired steady state off the system";
+        
+        excitation input at (1):
+        inp = Kp*(exc + off - out);
+        
+        excitation input at (2):
+        inp = Kp*(off - out) + exc;
+        
+    usage:
+        exc = myGPA(inp, out) does update the internal states of the gpa at the
+        timestep k and returns the excitation signal for the timestep k+1. the 
+        results are plotted to a terminal (putty) over serial cennection and look
+        as follows:
+ -----------------------------------------------------------------------------------------
+   fexc[Hz]    |Gyu|     ang(Gyu)    |Gye|     ang(Gye)     |E|        |U|        |Y|
+ -----------------------------------------------------------------------------------------
+   7.01e-01   1.08e+01  -7.45e-02   1.08e+01  -7.38e-02   9.99e-01   9.99e-01   1.08e+01
+        
+    in matlab you can use:
+        dataNucleo = [... insert measurement data here ...];
+        g = frd(dataNucleo(:,2).*exp(1i*dataNucleo(:,3)), dataNucleo(:,1), Ts, 'Units', 'Hz');
+        gcl = frd(dataNucleo(:,4).*exp(1i*dataNucleo(:,5)), dataNucleo(:,1), Ts, 'Units', 'Hz');
+        
+    if you're evaluating more than one measurement which contain equal frequency points try:
+        dataNucleo = [dataNucleo1; dataNucleo2];
+        [~, ind] = unique(dataNucleo(:,1),'stable');
+        dataNucleo = dataNucleo(ind,:);
+         
+        autor: M.E. Peter
+*/ 
+
+#include "GPA.h"
+#include "mbed.h"
+#include "math.h"
+#define   pi 3.1415927f
+
+using namespace std;
+
+GPA::GPA(float fMin, float fMax, int NfexcDes, int NperMin, int NmeasMin, float Ts, float Aexc0, float Aexc1)
+{
+    this->NfexcDes = NfexcDes;
+    this->NperMin = NperMin;
+    this->NmeasMin = NmeasMin;
+    this->Ts = Ts;
+
+    // calculate logarithmic spaced frequency points
+    fexcDes = (float*)malloc(NfexcDes*sizeof(float));
+    fexcDesLogspace(fMin, fMax, NfexcDes);
+
+    // calculate coefficients for decreasing amplitude (1/fexc)
+    this->aAexcDes = (Aexc1 - Aexc0)/(1.0f/fexcDes[NfexcDes-1] - 1.0f/fexcDes[0]);
+    this->bAexcDes = Aexc0 - aAexcDes/fexcDes[0];
+
+    fnyq = 1/2.0f/Ts;
+    pi2 = 2.0f*pi;
+    pi2Ts = pi2*Ts;
+    piDiv2 = pi/2.0f;
+
+    sU = (float*)malloc(3*sizeof(float));
+    sY = (float*)malloc(3*sizeof(float));
+    reset();
+}
+
+GPA::~GPA() {}
+
+void GPA::reset()
+{
+    Nmeas = 0;
+    Nper = 0;
+    fexc = 0.0f;
+    fexcPast = 0.0f;
+    ii = 1; // iterating through desired frequency points
+    jj = 1; // iterating through measurement points w.r.t. reachable frequency
+    scaleG = 0.0f;
+    cr = 0.0f;
+    ci = 0.0f;
+    for(int i = 0; i < 3; i++) {
+        sU[i] = 0.0f;
+        sY[i] = 0.0f;
+    }
+    sinarg = 0.0f;
+    NmeasTotal = 0;
+    Aexc = 0.0f;
+    pi2Tsfexc = 0.0f;
+}
+
+float GPA::update(float inp, float out)
+{
+    // a new frequency point has been reached
+    if(jj == 1) {
+        // get a new unique frequency point
+        while(fexc == fexcPast) {
+            // measurement finished
+            if(ii > NfexcDes) {
+                return 0.0f;
+            }
+            calcGPAmeasPara(fexcDes[ii - 1]);
+            // secure fexc is not higher or equal to nyquist frequency
+            if(fexc >= fnyq) {
+                fexc = fexcPast;
+            }
+            // no frequency found
+            if(fexc == fexcPast) {
+                ii += 1;
+            } else {
+                Aexc = aAexcDes/fexc + bAexcDes;
+                pi2Tsfexc = pi2Ts*fexc;
+            }
+        }
+        fexcPast = fexc;
+        // filter scaling
+        scaleG = 1.0f/sqrt((float)Nmeas);
+        // filter coefficients
+        cr = cos(pi2Tsfexc);
+        ci = sin(pi2Tsfexc);
+        // filter storage
+        for(int i = 0; i < 3; i++) {
+            sU[i] = 0.0f;
+            sY[i] = 0.0f;
+        }
+    }
+    // filter step for signal su
+    sU[0] = scaleG*inp + 2.0f*cr*sU[1] - sU[2];
+    sU[2] = sU[1];
+    sU[1] = sU[0];
+    // filter step for signal sy
+    sY[0] = scaleG*out + 2.0f*cr*sY[1] - sY[2];
+    sY[2] = sY[1];
+    sY[1] = sY[0];
+    // measurement of frequencypoint is finished
+    if(jj == Nmeas) {
+        jj = 1;
+        ii += 1;
+        // calculate the one point dft
+        float Ureal = 2.0f*scaleG*(cr*sU[1] - sU[2]);
+        float Uimag = 2.0f*scaleG*ci*sU[1];
+        float Yreal = 2.0f*scaleG*(cr*sY[1] - sY[2]);
+        float Yimag = 2.0f*scaleG*ci*sY[1];
+        // calculate magnitude and angle
+        float Umag = sqrt(Ureal*Ureal + Uimag*Uimag);
+        float Ymag = sqrt(Yreal*Yreal + Yimag*Yimag);
+        float absGyu = Ymag/Umag;
+        float angGyu = atan2(Yimag, Yreal) - atan2(Uimag, Ureal);
+        float absGye = Ymag/Aexc;
+        float angGye = (atan2(Yimag, Yreal) + piDiv2);
+        // user info
+        if(ii == 1) {
+            printLine();
+            printf("   fexc[Hz]    |Gyu|     ang(Gyu)    |Gye|     ang(Gye)     |E|        |U|        |Y|\r\n");
+            printLine();
+        }
+        printf("%11.2e %10.2e %10.2e %10.2e %10.2e %10.2e %10.2e %10.2e\r\n", fexc, absGyu, angGyu, absGye, angGye, Aexc, Umag, Ymag);
+    } else {
+        jj += 1;
+    }
+    sinarg = fmod(sinarg + pi2Tsfexc, pi2);
+    NmeasTotal += 1;
+    return Aexc*sin(sinarg);
+}
+
+void GPA::fexcDesLogspace(float fMin, float fMax, int NfexcDes)
+{
+    // calculate logarithmic spaced frequency points
+    float Gain = log10(fMax/fMin)/((float)NfexcDes - 1.0f);
+    float expon = 0.0f;
+    for(int i = 0; i < NfexcDes; i++) {
+        fexcDes[i] = fMin*pow(10.0f, expon);
+        expon += Gain;
+    }
+}
+
+void GPA::calcGPAmeasPara(float fexcDes_i)
+{
+    // Nmeas has to be an integer
+    Nper = NperMin;
+    Nmeas = (int)floor((float)Nper/fexcDes_i/Ts + 0.5f);
+    //  secure that the minimal number of measurements is fullfilled
+    int Ndelta = NmeasMin - Nmeas;
+    if(Ndelta > 0) {
+        Nper = (int)ceil((float)NmeasMin*fexcDes_i*Ts);
+        Nmeas = (int)floor((float)Nper/fexcDes_i/Ts + 0.5f);
+    }
+    // evaluating reachable frequency
+    fexc = (float)Nper/(float)Nmeas/Ts;
+}
+
+void GPA::printLine()
+{
+    printf("-----------------------------------------------------------------------------------------\r\n");
+}
+
+void GPA::printGPAfexcDes()
+{
+    printLine();
+    for(int i = 0; i < NfexcDes; i++) {
+        printf("%9.4f\r\n", fexcDes[i]);
+    }
+}
+
+void GPA::printGPAmeasPara()
+{
+    printLine();
+    printf(" fexcDes[Hz]  fexc[Hz]       Aexc   Nmeas   Nper\r\n");
+    printLine();
+    for(int i = 0; i < NfexcDes; i++) {
+        calcGPAmeasPara(fexcDes[i]);
+        if(fexc == fexcPast || fexc >= fnyq) {
+            fexc = 0.0f;
+            Nmeas = 0;
+            Nper = 0;
+            Aexc = 0;
+        } else {
+            Aexc = aAexcDes/fexc + bAexcDes;
+            fexcPast = fexc;
+        }
+        NmeasTotal += Nmeas;
+        printf("%12.2e %9.2e %10.2e %7i %6i \r\n", fexcDes[i], fexc, Aexc, Nmeas, Nper);
+    }
+    printGPAmeasTime();
+    reset();
+}
+
+void GPA::printGPAmeasTime()
+{
+    printLine();
+    printf(" number of data points:  %9i\r\n", NmeasTotal);
+    printf(" measurment time in sec: %9.2f\r\n", (float)NmeasTotal*Ts);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GPA.h	Tue Apr 03 15:17:11 2018 +0000
@@ -0,0 +1,55 @@
+class GPA
+{
+public:
+
+    GPA(float fMin, float fMax, int NfexcDes, int NperMin, int NmeasMin, float Ts, float Aexc0, float Aexc1);
+
+    float operator()(float inp, float out) {
+        return update(inp, out);
+    }
+
+    virtual ~GPA();
+
+    void     reset();
+    float    update(float inp, float out);
+
+    void     printGPAfexcDes();
+    void     printGPAmeasPara();
+    void     printGPAmeasTime();
+
+private:
+
+    int    NfexcDes;
+    int    NperMin;
+    int    NmeasMin;
+    float  Ts;
+    float *fexcDes;
+    float  aAexcDes;
+    float  bAexcDes;
+
+    float  fnyq;
+    float  pi2;
+    float  pi2Ts;
+    float  piDiv2;
+
+    int    Nmeas;
+    int    Nper;
+    float  fexc;
+    float  fexcPast;
+    int    ii;
+    int    jj;
+    float  scaleG;
+    float  cr;
+    float  ci;
+    float *sU;
+    float *sY;
+    float  sinarg;
+    int    NmeasTotal;
+    float  Aexc;
+    float  pi2Tsfexc;
+
+    void   fexcDesLogspace(float fMin, float fMax, int NfexcDes);
+    void   calcGPAmeasPara(float fexcDes_i);
+    void   printLine();
+
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IIR_filter.cpp	Tue Apr 03 15:17:11 2018 +0000
@@ -0,0 +1,171 @@
+#include "IIR_filter.h"
+#include "mbed.h"
+using namespace std;
+
+/*
+  IIR filter implemention for the following filter types:
+  init for: first order differentiatior:   G(s) = s/(T*s + 1)
+            first order lowpass with gain  G(s) = K/(T*s + 1)
+            second order lowpass with gain G(s) = K*w0^2/(s^2 + 2*D*w0*s + w0*w0)        
+            nth order, with arbitrary values
+  the billinear transformation is used for s -> z
+  reseting the filter only makes sence for static signals, whatch out if you're using the differnetiator
+*/
+
+// G(s) = s/(T*s + 1)
+IIR_filter::IIR_filter(float T,float Ts){
+           
+    // filter orders
+    nb = 1; // Filter Order
+    na = 1; // Filter Order
+    
+    // filter coefficients
+    B = (float*)malloc((nb+1)*sizeof(float));
+    A = (float*)malloc(na*sizeof(float));    
+    B[0] = 2.0f/(2.0f*T + Ts);
+    B[1] = -B[0];
+    A[0] = -(2.0f*T - Ts)/(2.0f*T + Ts);
+    
+    // signal arrays
+    uk = (float*)malloc((nb+1)*sizeof(float));
+    yk = (float*)malloc(na*sizeof(float));
+    uk[0]= uk[1] = 0.0f;
+    yk[0] = 0.0f;
+    
+    // dc-gain
+    this->K = 0.0f;
+}
+
+// G(s) = K/(T*s + 1)
+IIR_filter::IIR_filter(float T,float Ts,float K){
+    
+    // filter orders
+    nb = 1; // Filter Order
+    na = 1; // Filter Order
+    
+    // filter coefficients
+    B = (float*)malloc((nb+1)*sizeof(float));
+    A = (float*)malloc(na*sizeof(float));      
+    B[0] = Ts/(Ts + 2.0f*T);
+    B[1] = B[0];
+    A[0] = (Ts - 2.0f*T)/(Ts + 2.0f*T); 
+    
+    // signal arrays
+    uk = (float*)malloc((nb+1)*sizeof(float));
+    yk = (float*)malloc(na*sizeof(float));
+    uk[0]= uk[1] = 0.0f;
+    yk[0] = 0.0f;
+    
+    // dc-gain
+    this->K = K;
+}
+
+// G(s) = K*w0^2/(s^2 + 2*D*w0*s + w0^2) 
+IIR_filter::IIR_filter(float w0,float D, float Ts, float K){
+    
+    // filter orders
+    nb = 2; // Filter Order
+    na = 2; // Filter Order
+    
+    // filter coefficients
+    B = (float*)malloc((nb+1)*sizeof(float));
+    A = (float*)malloc(na*sizeof(float));
+    float k0 = Ts*Ts*w0*w0;
+    float k1 = 4.0f*D*Ts*w0;
+    float k2 = k0 + k1 + 4.0f;    
+    B[0] = K*k0/k2;
+    B[1] = 2.0f*B[0];
+    B[2] = B[0]; 
+    A[0] = (2.0f*k0 - 8.0f)/k2;
+    A[1] = (k0 - k1 + 4.0f)/k2;
+    
+    // signal arrays
+    uk = (float*)malloc((nb+1)*sizeof(float));
+    yk = (float*)malloc(na*sizeof(float));
+    uk[0]= uk[1] = uk[2] = 0.0f;
+    yk[0] = yk[1] = 0.0f;
+    
+    // dc-gain
+    this->K = K;
+}
+
+IIR_filter::IIR_filter(float *b,float *a,int nb_, int na_){
+    
+    // filter orders
+    this->nb = nb_-1;    // Filter Order
+    this->na = na_;      // Filter Order
+    
+    // filter coefficients
+    B = (float*)malloc((nb+1)*sizeof(float));
+    A = (float*)malloc(na*sizeof(float));
+    uk = (float*)malloc((nb+1)*sizeof(float));
+    yk = (float*)malloc(na*sizeof(float));
+    
+    for(int k=0;k<=nb;k++){
+        B[k]=b[k];
+        uk[k]=0.0f;
+        }
+    for(int k=0;k<na;k++){
+        A[k] = a[k];
+        yk[k] = 0.0f;
+        }
+    //B[0] = K*k0/k2;
+    //B[1] = 2.0f*B[0];
+    //B[2] = B[0]; 
+    //A[0] = (2.0f*k0 - 8.0f)/k2;
+    //A[1] = (k0 - k1 + 4.0f)/k2;
+    
+    // dc-gain
+    this->K = 1.0f;
+}
+
+    
+IIR_filter::~IIR_filter() {} 
+    
+void IIR_filter::reset(float val) {
+    for(int k=0;k < nb;k++)
+        uk[k] = val;
+    for(int k=0;k < na;k++)
+        yk[k] = val*K;
+        
+}
+
+/* 
+    the filter is operating as follows: 
+    (B[0] + B[1]*z^-1 + ... + B[nb]*z^-nb)*U(z) = (1 + A[0]*z^-1 + ... + A[na-1]*z^-na))*Y(z)
+    y(n) =  B[0]*u(k)   + B[1]*u(k-1) + ... + B[nb]*u(k-nb) + ...
+          - A[0]*y(k-1) - A[1]*y(k-2) - ... - A[na]*y(n-na)
+*/
+float IIR_filter::filter(float input){
+    for(int k = nb;k > 0;k--)    // shift input values back
+        uk[k] = uk[k-1];
+    uk[0] = input;
+    float ret = 0.0f;
+    for(int k = 0;k <= nb;k++)
+        ret += B[k] * uk[k];
+    for(int k = 0;k < na;k++)
+        ret -= A[k] * yk[k];
+    for(int k = na;k > 1;k--)
+        yk[k-1] = yk[k-2];
+    yk[0] = ret;
+    return ret;
+}
+
+// (B[0] + B[1]*z^-1 + ... + B[nb]*z^-nb)*U(z) = (1 + A[0]*z^-1 + ... + A[na-1]*z^-na))*Y(z)
+/*
+IIR_filter::IIR_filter(float *a[], float *b[], float K){
+    
+    this->A = A[0];
+    this->B = B[0];   
+    nb = sizeof(B)/sizeof(B[0]);
+    na = sizeof(A)/sizeof(A[0]);
+    uk = (float*)malloc((nb+1)*sizeof(float));
+    yk = (float*)malloc(na*sizeof(float));
+    for(int ii=0; ii<nb; ii++){
+        uk[ii] = 0.0f;
+    }
+    for(int ii=0; ii<na; ii++){
+        yk[ii] = 0.0f;
+    }
+    this->K = K;       %%% THIS IMPLEMENTATION SUITS NOT THE RESET PROCESS %%%
+}*/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IIR_filter.h	Tue Apr 03 15:17:11 2018 +0000
@@ -0,0 +1,26 @@
+class IIR_filter{
+     public:
+     
+        //IIR_filter(float *A[],float *B[]);       
+        IIR_filter(float T,float Ts);
+        IIR_filter(float T,float Ts,float K);
+        IIR_filter(float w0,float D, float Ts, float K);
+        IIR_filter(float *,float *, int,int);
+                    
+        float operator()(float u){
+            return filter(u);
+         }
+        virtual     ~IIR_filter();
+        void        reset(float);
+        float       filter(float);
+    
+    private:
+
+        unsigned int nb;
+        unsigned int na;
+        float *B;
+        float *A;
+        float *uk;
+        float *yk;
+        float K;
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LinearCharacteristics.cpp	Tue Apr 03 15:17:11 2018 +0000
@@ -0,0 +1,29 @@
+#include "LinearCharacteristics.h"
+
+using namespace std;
+
+LinearCharacteristics::LinearCharacteristics(float k, float offset, float min, float max)     // standard lin characteristics
+{
+    this -> k = k;
+    this -> offset = offset;
+    this -> min = min;
+    this -> max = max;
+// ...
+}
+
+LinearCharacteristics::~LinearCharacteristics(){}
+
+float LinearCharacteristics::trans(float input)
+{
+
+    output = k*input + offset;
+
+    if(output >= max) {
+        output = max;
+    }
+    if(output <= min) {
+        output = min;
+    }
+    return output;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LinearCharacteristics.h	Tue Apr 03 15:17:11 2018 +0000
@@ -0,0 +1,34 @@
+#ifndef LINEAR_CHARACTERISTICS_H_
+#define LINEAR_CHARACTERISTICS_H_
+
+#include <cstdlib>
+#include <mbed.h>
+
+// Linear Characteristics for different purposes (map Voltage to acc etc.)
+class LinearCharacteristics
+{
+public:
+
+    LinearCharacteristics(float k, float offset, float min, float max);
+    float trans(float input);
+
+//    float operator()(float input) {
+//        return trans(input);
+//    }
+    //...
+    //...
+    virtual     ~LinearCharacteristics();
+    // here: the calculation function
+
+
+private:
+    // here: private functions and values...
+    float k;
+    float offset;
+    float output;
+    float min;
+    float max;
+
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Apr 03 15:17:11 2018 +0000
@@ -0,0 +1,34 @@
+#include "mbed.h"
+#include "math.h"
+//------------------------------------------
+#define PI 3.1415927f
+//------------------------------------------
+#include "EncoderCounter.h"
+#include "DiffCounter.h"
+#include "IIR_filter.h"
+#include "LinearCharacteristics.h"
+
+PwmOut pwm1(PA_5);
+
+float inc2rad = 2.0f*3.1415927f/(4.0f*6400.0);
+
+int main()
+{
+
+    EncoderCounter counter1(PB_6, PB_7);
+    DiffCounter diffc(0.9f,0.05f);
+
+
+    pwm1.period(0.00005f);
+
+    while(1) {
+        short inc = counter1.read();
+        float velocity = diffc(inc);
+        printf("angle = %.2f velocity = %.2f\r\n",inc*inc2rad,velocity);
+
+        pwm1.write(0.5f);
+        wait(0.05f);
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Tue Apr 03 15:17:11 2018 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/994bdf8177cb
\ No newline at end of file