Robotcontrol groep 2

Dependencies:   Encoder MODSERIAL mbed HIDScope

main.cpp

Committer:
wiesdat
Date:
2014-10-31
Revision:
2:f3e8a27d376c
Parent:
1:a010e434a360
Child:
3:611fd72c9d46

File content as of revision 2:f3e8a27d376c:

#include "mbed.h"
#include "MODSERIAL.h"
#include "HIDScope.h"

#include "encoder.h"
#define K_P (0.1)
#define K_I (0.1)
#define K_D (0.0005 /TSAMP)
#define TSAMP 0.001
#define I_LIMIT 1.

// Outputs van de motor
Encoder encoderA(PTD5,PTA13);
Encoder encoder1(PTD0,PTD2);


// Outputs naar de motor
PwmOut pwm(PTC8);
DigitalOut dir(PTC9);
PwmOut pwm1(PTA5);
DigitalOut dir1(PTA4);

// Vaststellen van het datatype van de outputs naar de motor
float s_speed1;
float s_dir1;
float s_speed2;
float s_dir2;

//lampjes

DigitalOut rood(LED1);
DigitalOut blauw(LED3);
DigitalOut groen(LED2);
// Alle constantes voor de filters definiëren
// Constantes voor de Low Pass filter
#define A1LP    0.018180963222803
#define A0LP     0.016544013176248
#define B1LP    -1.718913340044714
#define B0LP     0.753638316443765

// Constantes voor de High Pass Filter
#define A1HP    -1.999801878951505
#define A0HP   0.999801878951505
#define B1HP   -1.971717601075000
#define B0HP  0.972111984032897

// Constantes voor het Notch Filter
#define A0N 0.99436777112
#define A1N -1.89139989664
#define A2N 0.99436777112
#define B1N 1.89070035439
#define B2N -0.988036

// Sample Time
#define TSAMP 0.001

// EMG Threshold waarde
#define THRESHOLD 0.05

// EMG inputs
AnalogIn    emg1(PTB1);
AnalogIn    emg2(PTB2);

// PC communicatie
MODSERIAL pc(USBTX,USBRX);
HIDScope scope(5);
int set;

// Ticker voor de meetgegevens
Ticker timer;
volatile bool looptimerflag;

// Waardes voor de filters reserveren en als float vaststellen
float emg_value2, ylp2, yhp2, yn2;
float emg_value1, ylp1, yhp1, yn1;

float ysum1 = 0, yave1=0 ;
float ysum2 = 0, yave2=0 ;

// 0 of 1 waardes gedefinieerd uit het EMG, met 0 is te lage activiteit, 1 is hoog genoeg, voor de zekerheid toch als int.
uint8_t y1, y2;
int check = 0;

// integers reserveren voor het deel van het regelsysteem als we de boolean emg waardes hebben: hoek van het badje (0,1, of 2) en de gewenste snelheid (0,1, of 2)
int badjestand;
int badjes=1;
int badjedone=0;
int speeding;
int armstand=0;
int armspeed=0;
bool speeddone=0;
int a; //wordt gebruikt in gotopos
float out1; //pid voor armpositie
// Teller voor hoeveel metingen er zijn gedaan
uint16_t teller=0;

// Random meuk die ik uit batjespositie haal, nog ff opruimen
int32_t enc = 0,enca2 =0,enca1=0, encp=0, counts =0;
float speed = 0.1, out =0;
int pos =0,zero =0, fout;
float v=0;
float out_i = 0;
int y;


// Scopes vaststellen
void viewer()
{
    scope.set(0,y1);
    scope.set(1,y2);
    scope.set(2,badjes);
    scope.set(3,armstand);
    scope.set(4,speeddone);
    scope.send();
}

// EMG 1 uitlezen
float readEMG1()
{

    emg_value1=emg1.read();
    return emg_value1;
}

// EMG 2 uitlezen
float readEMG2()
{

    emg_value2=emg2.read();
    return emg_value2;
}

// Notch Filter voor EMG 1
float notchfilter1(float ylp1)
{
    static float yn1,x1=0,x2=0,y1=0,y2=0,x;
    x = ylp1;
    yn1 = A0N*x + A1N*x1+A2N*x2+B1N*y1+B2N*y2;
    x2 = x1;
    x1 = x;
    y2 = y1;
    y1 = yn1;
    return yn1;
}

// Notch Filter voor EMG 2 (idem aan die voor EMG 1, maar met eigen variabelen)
float notchfilter2(float ylp2)
{
    static float x1=0,x2=0,y1=0,y2=0,x;
    x = ylp2;
    yn2 = A0N*x + A1N*x1+A2N*x2+B1N*y1+B2N*y2;
    x2 = x1;
    x1 = x;
    y2 = y1;
    y1 = yn2;
    return yn2;
}

// High Pass Filter voor EMG 1
float hpfilter1(float yn1)
{
    static float x1=0,y1=0,x2=0, y2=0,x;
    x = yn1;
    yhp1 = x + A1HP*x1 + A0HP*x2 - B1HP*y1 - B0HP*y2;
    x2 = x1;
    x1 = x;
    y2 = y1;
    y1 = yhp1;
    return yhp1;
}

// High Pass Filter voor EMG 2 (idem aan die voor EMG 1, maar met eigen variabelen)
float hpfilter2(float yn2)
{
    static float x1=0,y1=0,x2=0, y2=0,x;
    x = yn2;
    yhp2 = x + A1HP*x1 + A0HP*x2 - B1HP*y1 - B0HP*y2;
    x2 = x1;
    x1 = x;
    y2 = y1;
    y1 = yhp2;
    return yhp2;
}

// Low Pass Filter voor EMG 1
float lpfilter1(float yhp1)
{
    static float x1=0,y1=0,x2=0, y2=0,x;
    x = yhp1;
    ylp1 = A1LP*x1-B1LP*y1+A0LP*x2-B0LP*y2;
    x2 = x1;
    x1 = x;
    y2 = y1;
    y1 = ylp1;
    return ylp1;
}

// Low Pass Filter voor EMG 2 (idem aan die voor EMG 1, maar met eigen variabelen)
float lpfilter2(float yhp2)
{
    static float x1=0,y1=0,x2=0, y2=0,x;
    x = yhp2;
    ylp2 = A1LP*x1-B1LP*y1+A0LP*x2-B0LP*y2;
    x2 = x1;
    x1 = x;
    y2 = y1;
    y1 = ylp2;
    return ylp2;
}

// Stukje nodig voor de ticker
void setlooptimerflag(void)
{
    looptimerflag = true;
}

// Combinatie van de drie bovengenoemde filters voor EMG 1, en de middeling van 500 dataputen (nieuwe data 2 keer per seconde)
float filter1(float emg_value1)
{
    static uint16_t n;
    yn1 = notchfilter1(emg_value1);
    yhp1 = hpfilter1(yn1);
    ylp1 = lpfilter1(yhp1);
    ylp1 = fabs(ylp1);
    ysum1 = ysum1+ylp1;
    n++;
    if(n==500) {
        yave1 = ysum1/500;
        ysum1 = 0;
        n = 0;
    }
    return yave1;
}

// Idem voor EMG 2
float filter2(float emg_value2)
{
    static uint16_t n;
    yn2 = notchfilter2(emg_value2);
    yhp2 = hpfilter2(yn2);
    ylp2 = lpfilter2(yhp2);
    ylp2 = fabs(ylp2);
    ysum2 = ysum2 + ylp2;
    n++;

    if(n==500) {
        yave2 = ysum2/500;
        ysum2 = 0;
        n = 0;
    }
    return yave2;
}

// Check of de waarde van het EMG boven de gedefinieerde threshold waarde uitkomt voor EMG 1
float threshold1 (float yave1)
{
    if(yave1>THRESHOLD) {
        y1 = 1;
    } else {
        y1 = 0;
    }
    return y1;
}

//Idem voor EMG 2
float threshold2 (float yave2)
{
    if(yave2>THRESHOLD) {
        y2 = 1;
    } else {
        y2 = 0;
    }
    return y2;
}

// Hoek van het badje vaststelen: begint met waarde 1, als EMG 1 alleen gebruikt wordt, gaat er 1 vanaf (maximaal 0), wordt EMG 2 alleen gebruikt, dan gaat er 1 bij (maximaal 2).
// Als beide tegelijkertijd 2 maal achter elkaar gebruikt worden, dan wordt de hoek vastgezet (kan niet meer verandert worden tot de reset).
uint8_t badje (uint8_t y1, uint8_t y2)
{
    if (y1>0 && y2>0 && check>0) {
        badjedone=1;
        check=0;
        rood = 1;
        groen = 0;
    } else if (y1>0 && y2>0) {
        check=1;
    } else if (y1>0) {
        badjes=0;
        check=0;
    } else if (y2>0 ) {
        badjes=1;
        check=0;
    }
    else {
        check=0;
        badjes = 2;
    }
    return badjes;
}

// Stukje dat hetzelfde als bij de hoek van het badje regelt, maar dan voor de snelheid waarmee de arm moet bewegen. Heeft ook de waardes 0,1, of 2.
// Bij 2 maal achter elkaar EMG 1 en EMG 2 gebruikt, wordt de snelheid vastgezet.
uint8_t velocity (uint8_t y1, uint8_t y2)
{
    if (y1>0 && y2>0 && check>0) {
        speeddone=1;
        check=0;
        rood = 0;
        groen = 1;
    } else if (y1>0 && y2>0) {
        check=1;
    } else if (y1>0) {
        if (speed>0) {
            speed+=1;
        } else {
            check=0;
        }
    } else if (y2>0 ) {
        if (speed<2) {
            speed-=1;
        } else {
            check=0;
        }
    } else {
        check=0;
        
    }
    return speed;
}

void batposition(int y)
{
    switch(y) {
        case 0:
          
            dir = 1;
            pwm.write(0.4);
            wait(0.02);
            pwm.write(0);
            break;
        case 1:
            
            dir = 0;
            pwm.write(0.4);
            wait(0.02);
            pwm.write(0);
            break;
        case 2:
            
            pwm.write(0);
            break;

    }

}

void clamp(float * in, float min, float max)
{
*in > min ? *in < max? : *in = max: *in = min;
}

float pid1(float setpoint, float measurement)
{
    float error;
    static float prev_error = 0;
    float           out_p = 0;

    float           out_d = 0;
    error  = setpoint-measurement;
    out_p  = error*K_P;
    out_i += error*K_I;
    out_d  = (error-prev_error)*K_D;
    clamp(&out_i,-I_LIMIT,I_LIMIT);
    prev_error = error;
    out1  = out_i+out_p+out_d;
    return out1;
}

float getv(float delta_t)
{
    int n =0 ;
    while(n<3) {
        wait(delta_t);
        enc = encoderA.getPosition();
        enca2 = enca1;
        enca1 = enc;
        n++;

    }

    counts = (enca1 - enca2)/delta_t;
    v = (counts)*((2*3.14159265359)/1550);
    return v;
}


float gotopos(float pos)
{
    switch(a) {
        case 1:
            pos = 100;
            break;

        case 2:
            pos = 200;
            break;

        case 3:
            pos = 250;
            break;
    }
    enc = encoder1.getPosition();
    while((abs(pos-encoder1.getPosition()) >6)|| (v!= 0)) {

        while(!looptimerflag);
        looptimerflag = false;
        out1 = pid1(pos,encoder1.getPosition());

        if(out>0) {
            dir1 = 1;

        } else if(out<0) {
            dir1 = 0;
        }
        pwm1 = fabs(out);
        v = getv(0.001);
    }
    pwm1 =0;

    return pwm1;
}

float reset()
{
    v = 1;
    while(v !=0) {

        dir = 0;
        speed = 0.1;
        pwm = speed;
        v =getv(0.1);
    }
    pwm = 0;
    dir =1;
    encoderA.setPosition(0);
    zero = encoderA.getPosition();

    return pwm;
}

// Main code
int main()
{
     v = 1;
    rood = 0;
    blauw = 1;
    groen = 1;
    // Startcondities
    pc.baud(115200);
    timer.attach(setlooptimerflag,TSAMP);
    // 20 secondes wachten, zodat er geen effecten van het opstarten van het bordje, alvast waardes voor het badje of de arm vastzetten.
    wait(2);

    while(1) {

        // Ticker
        while(!looptimerflag);

        looptimerflag = false;

        // EMG uitlezen
        emg_value1 =  readEMG1();
        emg_value2 =  readEMG2();

        // Filters gebruiken
        yave1 = filter1(emg_value1);
        yave2 = filter2(emg_value2);

        // Checken of de waardes boven de threshold uitkomen
        y1=threshold1(yave1);
        y2=threshold2(yave2);

        // Aantal metingen tellen
        teller++;

        // Om de 500 metingen controleren
        if (teller==500) {

            teller=0;
            // Als de hoek voor het badje nog niet klaar is, zet badje in de huidig aangegeven stand
            if (badjedone==0) {
                badjestand=badje(y1,y2);
                
                batposition(badjestand);
              
                // Als de hoek voor het badje wel klaar is:
            } else if (badjedone==1) {
                // Als de snelheid van de arm ook al klaar is, zorg ervoor dat de rest iet meer gebeurt
                if (speeddone==1) {
                    
                    badjedone=0;
                    speeddone=0;
                    badjestand=1;
                    armstand=0;
                    // Anders, pas de hoek van de arm aan naar de stand die hoort bij de huidig geselecteerde snelheid
                } else {
                    armstand=velocity(y1,y2);
                    gotopos(armstand);
                }

            }
        }
        // Verzend data naar de scopes

        viewer();
        reset();
        

    }

}