Script 15-10-2019

Dependencies:   Servoaansturing mbed QEI HIDScope biquadFilter MODSERIAL FastPWM

main.cpp.orig

Committer:
Renate
Date:
2019-11-05
Revision:
43:2f946b617d62
Parent:
19:1fd39a2afc30

File content as of revision 43:2f946b617d62:

#include "mbed.h"
#include "HIDScope.h"
#include "QEI.h"
#include "MODSERIAL.h"
#include "BiQuad.h"
#include "FastPWM.h"
#include <math.h>
#include "Servo.h"

// Definieer objecten
Serial pc(USBTX, USBRX);

PwmOut motor1(D6);  // Misschien moeten we hiervoor DigitalOut gebruiken, moet 
PwmOut motor2(D5);  // samen kunnen gaan met de servo motor

DigitalOut motor1_dir(D7);
DigitalOut motor2_dir(D4);
  
DigitalIn Power_button_pressed(D1); // Geen InterruptIn gebruiken!
DigitalIn Emergency_button_pressed(D2);  

AnalogIn EMG_biceps_right_raw (A0);
AnalogIn EMG_biceps_left_raw (A1);
AnalogIn EMG_calf_raw (A2);

Ticker loop_ticker;
Ticker HIDScope_ticker;
Ticker emgSampleTicker;

HIDScope scope(3);

BiQuadChain bqc; // Let op !!! Deze coëfficiënten moeten nog worden veranderd
BiQuad bq1(0.0030, 0.0059, 0.0030, -1.8404,0.8522); //voor low-pass
BiQuad bq2(0.9737, -1.9474, 0.9737, -1.9467, 0.9481); //voor high-pass
BiQuad bq3(0.9912, -1.9823,0.9912, -1.9822, 0.9824); //lage piek eruit-> voor coëfficienten, zie matlab

bool calib = false; // MOGELIJK GAAT HET HIER FOUT
int i_calib = 0;

void emgSampleFilter() // Deze functie wordt aangeroepen dmv een ticker. Het sampled 
                       // hierdoor het EMG signaal en het haalt er een filter overheen
{   
    float filtered_EMG_biceps_right=bqc.step(EMG_biceps_right_raw.read());
    float filtered_EMG_biceps_left=bqc.step(EMG_biceps_left_raw.read());
    float filtered_EMG_calf=bqc.step(EMG_calf_raw.read());
    
    float filtered_EMG_biceps_right_total=filtered_EMG_biceps_right;
    float filtered_EMG_biceps_left_total=filtered_EMG_biceps_left;
    float filtered_EMG_calf_total=filtered_EMG_calf;
    
    if (calib)
        {   
            if (i_calib < 500)
                {
                    filtered_EMG_biceps_right_total=filtered_EMG_biceps_right+filtered_EMG_biceps_right_total;
                    filtered_EMG_biceps_left_total=filtered_EMG_biceps_left+filtered_EMG_biceps_left_total;
                    filtered_EMG_calf_total=filtered_EMG_calf+filtered_EMG_calf_total;
                    i_calib++;
                }
            if (i_calib >= 500)
                {   
                    mean_EMG_biceps_right=filtered_EMG_biceps_right_total/500;
                    mean_EMG_biceps_left=filtered_EMG_biceps_left_total/500;
                    mean_EMG_calf=filtered_EMG_calf_total/500;
                    calib = false; 
                }
         }
}

void sendHIDScope() // Deze functie geeft de gefilterde EMG-signalen weer in de HIDScope
                    // Wordt eveneens gerund dmv een ticker
{
    /* Set the sampled emg values in channel 0 (the first channel) and 1 (the second channel) in the 'HIDScope' instance named 'scope' */
    scope.set(0, filtered_EMG_biceps_right() ); // Werkt dit zo? Of nog met .read?
    scope.set(1, filtered_EMG_biceps_left() );
    scope.set(2, filtered_EMG_calf() );
    /* Repeat the step above if required for more channels of required (channel 0 up to 5 = 6 channels) 
    *  Ensure that enough channels are available (HIDScope scope( 2 ))
    *  Finally, send all channels to the PC at once */
    scope.send();
    // Eventueel nog een ledje laten branden
}

// Emergency    
void emergency()
    {
        loop_ticker.detach(); 
        motor1.write(0);
        motor2.write(0);
        pc.printf("Ik ga exploderen!!!\r\n");
        // Alles moet uitgaan (evt. een rood LEDje laten branden), moet 
        // opnieuw worden opgestart. Mogelijk kan dit door de ticker te 
        // detachen
    }    

// Motoren uitzetten    
void motors_off()
    {
        motor1.write(0);
        motor2.write(0);
        pc.printf("Motoren uit functie\r\n");
    }  
    
// Motoren aanzetten
void motors_on()
    {
        motor1.write(0.9);
        motor1_dir.write(1);
        motor2.write(0.1);
        motor1_dir.write(1);
        pc.printf("Motoren aan functie\r\n");
    }
        
// EMG kalibreren        
void  emg_calibration()   
     {
        // Gedurende bijv. 5 seconden EMG meten, wanneer de spieren maximaal
        // worden aangespannen -> maximaal potentiaal verkrijgen. Een fractie 
        // hiervan kan als drempel worden gebruikt voor beweging
        
        // *Tijd instellen* 
        // Iets met DOUBLE_MAX? https://docs.microsoft.com/en-us/cpp/c-language/cpp-integer-limits?view=vs-2019
        
        // Ledje van kleur laten veranderen
        
        // MOGELIJK NIET MEER NODIG???
       
     }

// Finite state machine programming (calibration servo motor?)
enum states {Motors_off, Calib_motor, Calib_EMG, Homing, Operation_mode};

states currentState = Motors_off; 
bool stateChanged = true; // Make sure the initialization of first state is executed

void ProcessStateMachine(void) 
{   
    switch (currentState) 
    { 
        case Motors_off:
        
            if (stateChanged) 
            {
                motors_off(); // functie waarbij motoren uitgaan
                stateChanged = false;
                pc.printf("Motors off state\r\n");
            }          
            if  (Power_button_pressed.read() == false) // Normaal waarde 1 bij indrukken, nu nul -> false
            {      
                motors_on();
                currentState = Calib_motor;
                stateChanged = true;
                pc.printf("Moving to Calib_motor state\r\n");
            }
            if  (Emergency_button_pressed.read() == false) // Normaal waarde 1 bij indrukken, nu nul -> false
            { 
                emergency();
            } 
            break;
            
        case Calib_motor:
            
            if (stateChanged)
            {       
                // Hier wordt een kalibratie uitgevoerd, waarbij de motorhoeken worden bepaald
                currentState = Calib_EMG;
                stateChanged = true;
                pc.printf("Moving to Calib_EMG state\r\n");
            }    
            if  (Emergency_button_pressed.read() == false) 
            { 
                emergency();
            } 
            break;
            
         case Calib_EMG:
            
            motors_off();
            if (stateChanged)
            {
                // Hierbij wordt een een kalibratie uitgevoerd, waarbij de maximale EMG-amplitude waarde wordt bepaald
                calib = true;
                emgSampleFilter() // Gaat dit nu goed? -> moet sws worden toegevoegd bij relevante onderdelen?
                if (i_calib >= 500) // of wait(10);?
                {
                    currentState = Homing;
                    stateChanged = true;
                    pc.printf("Moving to Homing state\r\n");
                }
            if  (Emergency_button_pressed.read() == false) 
            { 
                emergency();
            } 
            break; 
            
         case Homing:
            
            motors_on();
            if (stateChanged)
            {   
                // Ervoor zorgen dat de motoren zo bewegen dat de robotarm 
                // (inclusief de end-effector) in de juiste home positie wordt gezet
                currentState = Operation_mode;
                stateChanged = true;
                pc.printf("Moving to operation mode \r\n");
            }
            if  (Emergency_button_pressed.read() == false) 
            { 
                emergency();
            } 
            break; 
            
         case Operation_mode: // Overgaan tot emergency wanneer referentie niet 
                              // overeenkomt met werkelijkheid
        
            if (stateChanged)
             
                // Hier moet een functie worden aangeroepen die ervoor zorgt dat 
                // aan de hand van EMG-signalen de motoren kunnen worden aangestuurd, 
                // zodat de robotarm kan bewegen   
                
                if (Power_button_pressed.read() == false) // Normaal waarde 1 bij indrukken, nu nul -> false
                {
                    motors_off();
                    currentState = Motors_off;
                    stateChanged = true;
                    pc.printf("Terug naar de state Motors_off\r\n");
                }
                if  (Emergency_button_pressed.read() == false) 
                { 
                    emergency();
                } 
                // wait(5);
                else 
                { 
                    currentState = Homing; 
                    stateChanged = true; 
                    pc.printf("Terug naar de state Homing\r\n");
                }
                break;
                     
        default:
            // Zelfde functie als die eerder is toegepast om motoren uit te schakelen -> safety!
            motors_off();
            pc.printf("Unknown or uninplemented state reached!\r\n");
            
    }
}

int main(void)
    {
        pc.printf("Opstarten\r\n");
        bqc.add(&bq1).add(&bq2).add(&bq3);
        emgSampleTicker.attach(&emgSampleFilter, 0.01f);
        HIDScope_ticker.attach(&sendHIDScope, 0.01f);
        loop_ticker.attach(&ProcessStateMachine, 5.0f);  
        while(true) 
        { /* do nothing */}
    }