My modifications/additions to the code

Dependencies:   ADXL345 ADXL345_I2C IMUfilter ITG3200 Servo fishgait mbed-rtos mbed pixy_cam

Fork of robotic_fish_ver_4_8 by jetfishteam

MainController.cpp

Committer:
sandwich
Date:
2014-06-03
Revision:
21:835fd919b4bd
Parent:
20:6ae16da1492a
Child:
22:807d5467fbf6

File content as of revision 21:835fd919b4bd:

#include "MainController.h"

MainController::MainController()
    :ch1(p18,0.056,0.090), // yaw
     ch2(p17,0.054,0.092), // pitch
     ch3(p15,0.054,0.092), // amplitude
     ch4(p30,0.055,0.092), // adj
     ch6(p16,0.053,0.092), // frequency
     mcon(p22, p6, p7), // change pin p5 to p7, because p5 is burned through
     //ap(p25, p26)//,
     leftservo(p21),
     rightservo(p23)
     
{
    wait_ms(50);
    amp = 0.0;
    frq = 1.0;
    frqCmd = frq;
    yaw = 0.5;
    pitch = 0.5;
    adj = 0.5;
    frqMin = 0.8; //hardcoded
    frqMax = 2.9; //hardcoded
    //change = 0;
    //state = 0;
    fullCycle = true;
    volume = 0.0;
    volMax = 0.1;
    volChg = 0.0;
    raiser = 0.0;
    pitAvg = 0.0;
    alPi = 0.2/(0.2+0.001);//tf/(tf+Ts);
    
    //leftservo.calibrate(0.0008, 45); 
    //rightservo.calibrate(-0.0001, 45); 

}

void MainController::control()
{
    curTime = timer1.read();
    
    // check every half cycle
    if(curTime > 1/(2*frqCmd) ) {
        
        // read new yaw value every half cycle
        yaw = this->calculateYaw(); // a value from -1 to 1
        
        if(yaw < 0.1 && yaw > -0.1){
            yaw =0.0;
        }
        // calculate liquid volume change in the chambers
        volChg = volMax * yaw;
        volChg = 0.0;
        
        timeAdd = 0.0;
        
        // Read volume and frequency only every full cycle
        if( fullCycle ) {
            //read other new inputs
            amp = this->calculateAmplitude(); // a value from 0 to 1
            frq = this->calculateFrequency(); // a value from frqmin to frqmax

            if(volChg > 0.0) {
                // adjust frequency to add additional volume
                if( amp < 0.0001 ) {
                    amp = 0.0001;  
                } 
                timeAdd = volChg/amp;

                if( timeAdd > 0.5/frq ) {
                    timeAdd = 0.5/frq;
                    volChg = timeAdd * amp;
                }
            }
            ampNew = amp;
            
            if(yaw < 0.0)
            {
                ampNew = (1.0+0.7*yaw)*amp;
            }
  
            fullCycle = false;

        } else {
            // reverse for the downward slope
            amp = -amp;

            if(volChg < 0.0) {
                // adjust frequency to add additional volume
                if( amp > -0.0001 ) {
                    amp = -0.0001;
                }
                timeAdd = volChg/amp;
                
                if( timeAdd > 0.5/frq ) {
                    timeAdd = 0.5/frq;
                    volChg = timeAdd * amp;
                }
            }
            
            ampNew = amp;
            
            if(yaw > 0.0)
            {
                ampNew = (1.0-0.7*yaw)*amp;
            }
            
            // use amp and frq from last cycle in order to make sure it is equalized
            fullCycle = true;
        }
        // update the frequency that actually needs to be commanded
        frqCmd = 1.0/( 2.0*( timeAdd + 1/( 2* frq) ) );

        // read new yaw value every half cycle
        adj = this->calculateAdj(); // a value from 0 to 1
    
        // for keeping track, calculate current volume storage, positive means on side is fuller, negative means other side is fuller
        //volume = volChg + volume;            
        // rudder value used to define the trapezoid shape
        raiser = ( 5 * adj + 1.0); // varied from 1 to 5      
        
        //reset timer
        timer1.reset();
        curTime = 0.0;
    }
        
      
    //Set Servo Values
    pitch = this->calculatePitch();
    leftservo = pitch+0.03;
    rightservo = 1.0 - pitch;
    if (rightservo<0.03){
        rightservo = 0.03;
    }
        
    dutyCycle = ampNew * saturate(raiser * sin( 2.0 * MATH_PI * frqCmd * curTime )); // add factor 4.0 to get a cut off sinus
            
    mcon.setpolarspeed(dutyCycle);
}

float MainController::calculateFrequency()
{
    return ((frqMax - frqMin) * ch6.dutycyclescaledup() + frqMin);    
}

float MainController::calculateAmplitude()
{
    return (ch3.dutycyclescaledup());
}

float MainController::calculateYaw()
{
    return (2.0*ch1.dutycyclescaledup() - 1.0); 
}

float MainController::calculatePitch()
{
    pitAvg = alPi * pitAvg+ (1.0 - alPi)*(ch2.dutycyclescaledup());
    return pitAvg;
}

float MainController::calculateAdj()
{
    return (ch4.dutycyclescaledup());
}

void MainController::start()
{
    timer1.start();
    
    ticker1.attach(this, &MainController::control,0.001);
    //Autopilot guardian
    //ap.calibrate();
    //ap.set2D();
    //ap.setoff();
    
}

void MainController::stop()
{
    timer1.stop();
    ticker1.detach();
    mcon.setpolarspeed(0.0);
}

float MainController::getDutyCycle()
{
    return dutyCycle;
}

float MainController::getAmplitude()
{
    return amp;
}


float MainController::getFrequency()
{
    return frq;
}

float MainController::getVolume()
{
    return volume;
}

float MainController::getYaw()
{
    return yaw;
}

float MainController::getPitch()
{
    return pitch;
}

float MainController::getAdj()
{
    return adj;
}

float MainController::getTimeAdd()
{
    return timeAdd;
}

//signum function
float MainController::signum(float input)
{
    if (input>0.0)
        return 1.0;
    else if (input<0.0)
        return (-1.0);
    else
        return 0.0;
}

//saturate function
float MainController::saturate(float input)
{
    if (input > 1.0)
        return (1.0);
    else if (input < -1.0)
        return (-1.0);
    else
        return input;
}