Test the speed of sensor module PID controlled speed. When note is passed the optical sensors data is collected and shared via SWO

Dependencies:   mbed PID SWO

main.cpp

Committer:
andjoh
Date:
2018-11-30
Revision:
0:fc81857d8067

File content as of revision 0:fc81857d8067:

#include "mbed.h"
#include "SWO.h"
#include "PID.h"

#define RATE 5 //interval PID calculation performed every 5th milliseconds.



DigitalOut LED_GREEN(PA_4);
DigitalOut LED_RED(PA_5);
DigitalOut LED_ENABLE(PB_5);

//optical sensors
DigitalIn SCANNER_INPUT(PC_10);
DigitalIn SCANNER_OUTPUT(PC_1);
DigitalIn SWITCH_INPUT(PC_2);
DigitalIn REJECT_INPUT(PA_7);
DigitalIn REJECT_OUTPUT(PA_6);
DigitalIn STORAGE_INPUT(PC_3);

int opticalSensors[6] = {0};    //list to store the values from optical sensors
int lastValueOpticalSensors[6] = {0};    //list to store the previous values from optical sensors
float sensorNoteRunningTimes[10] = {0};  //The times (in us) when note hit the sensors are stored in this array
int pulseCountBetweenSensors[10] = {0};  //The counted number encoder pulses between sensors
int noteInSystem = 0;
long lastPulseTime = 0;
long maxTimeBetweenPulses = 0;
long minTimeBetweenPulses = 10000000;
long timeBetweenPulses = 0;
double currentSpeed = 0; //speed in mm/ms
long lastControl = 0;

PID controller(4.0, 0.0, 0.0, RATE);


int AtoB_dist = 357;    //distance from SCANNER_INPUT to SCANNER_OUTPUT     counted pulses: 372
int BtoC_dist = 81;     //distance from SCANNER_OUTPUT to SWITCH_INPUT      counted pulses: 82
int CtoD_dist = 201;    //distance from SWITCH_INPUT to REJECT_INPUT        counted pulses: 203
int DtoE_dist = 158;    //distance from REJECT_INPUT to REJECT_OUTPUT       counted pulses: 156
int Tot_dist = 797;     //distance from SCANNER_INPUT to REJECT_OUTPUT      counted pulses: 813

int TenEURnoteLength = 127;
int FiftyEURnoteLength = 140;
int TwentyEURnoteLength = 120;

//encoders
InterruptIn MAIN_ENC(PA_8);
//InterruptIn STORAGE_ENC(PA_15);
//InterruptIn SWITCH_ENC(PB_4);
//InterruptIn ROUTER_ENC(PB_6);


//Motors
PwmOut MAIN_PWM(PC_7);   //PWM to Main Drive
DigitalOut MAIN_DIR(PC_0);   //Direction of main drive

PwmOut SWITCH_PWM(PB_14);   //PWM to Switch
DigitalOut SWITCH_DIR(PB_15);   //Direction of Switch

PwmOut ROUTER_PWM(PC_8);   //PWM to Router
DigitalOut ROUTER_DIR(PB_7);   //Direction of Router

PwmOut STORAGE_PWM(PC_6);   //PWM to Storage
DigitalOut STORAGE_DIR(PC_9);   //Direction of Storage



uint32_t blinkTime_ms = 0;
uint32_t reportTimer = 0;
uint32_t pulses = 0;


Timer t;
//PID controller(1, 0, 0, RATE);    //Kc, Ti, Td, interval


Serial pc(USBTX, USBRX);
SWO_Channel swo("channel");

void green_blink(void)
{
    if(t.read_ms() - blinkTime_ms > 200) {
        LED_RED = 0;
        LED_GREEN = !LED_GREEN;
        blinkTime_ms = t.read_ms();
    }
}
void red_blink(void)
{
    if(t.read_ms() - blinkTime_ms > 200) {
        LED_GREEN = 0;
        LED_RED = !LED_RED;
        blinkTime_ms = t.read_ms();
    }
}

void reportNoteThroughSensorLengths()
{

    swo.printf("\n");

    //Time for note to travel through first sensor
    long time = (sensorNoteRunningTimes[1] - sensorNoteRunningTimes[0]); //us
    swo.printf("Time for note to pass 1th sensor (us): %d\r", time);
    //int length = TwentyEURnoteLength;
    int countedPulses = pulseCountBetweenSensors[1] - pulseCountBetweenSensors[0];
    swo.printf("  Counted pulses: %d\r\n", countedPulses);

    //Time for note to travel through second sensor
    time = (sensorNoteRunningTimes[3] - sensorNoteRunningTimes[2]); //us
    swo.printf("Time for note to pass 2th sensor (us): %d\r\n", time);
    countedPulses = pulseCountBetweenSensors[3] - pulseCountBetweenSensors[2];
    swo.printf("  Counted pulses: %d\r\n", countedPulses);

    //Time for note to travel through third sensor
    time = (sensorNoteRunningTimes[5] - sensorNoteRunningTimes[4]); //us
    swo.printf("Time for note to pass 3th sensor (us): %d\r\n", time);
    countedPulses = pulseCountBetweenSensors[5] - pulseCountBetweenSensors[4];
    swo.printf("  Counted pulses: %d\r\n", countedPulses);

    //Time for note to travel through fourth sensor
    time = (sensorNoteRunningTimes[7] - sensorNoteRunningTimes[6]); //us
    swo.printf("Time for note to pass 4th sensor (us): %d\r\n", time);
    countedPulses = pulseCountBetweenSensors[7] - pulseCountBetweenSensors[6];
    swo.printf("  Counted pulses: %d\r\n", countedPulses);

    //Time for note to travel through fifth sensor
    time = (sensorNoteRunningTimes[9] - sensorNoteRunningTimes[8]); //us
    swo.printf("Time for note to pass 5th sensor (us): %d\r\n", time);
    countedPulses = pulseCountBetweenSensors[9] - pulseCountBetweenSensors[8];
    swo.printf("  Counted pulses: %d\r\n", countedPulses);

    swo.printf("\n");
    swo.printf("\n");

}

void report(void)
{
    //uint32_t now = t.read_ms();

    /*
    swo.printf("Optical sensor status: ");
    for(int j = 0; j <=5 ; j++) {
        swo.printf("%d ", opticalSensors[j]);
    }
    swo.printf("\n");
    */

    long time = (sensorNoteRunningTimes[2] - sensorNoteRunningTimes[0]) / 1000; //ms

    //swo.printf("Time between first two sensors (ms): ");
    //swo.printf("%d ", time);
    //swo.printf("\n");

    //V = S / T
    float V = 1000 * AtoB_dist / time; //(mm/s)

    swo.printf("Speed between first two sensors (mm/s): ");
    swo.printf("%f ", V);
    swo.printf("  Counted encoder pulses: ");
    uint32_t countedPulses = pulseCountBetweenSensors[2] - pulseCountBetweenSensors[0];
    swo.printf("%d ", countedPulses);
    swo.printf("  ->Encoder speed (mm/s): ");
    float countedSpeed = 1000 * countedPulses / time;
    swo.printf("%f ", countedSpeed);
    swo.printf("  ->Speed difference (percentage): ");
    double difference = (100 * V / countedSpeed) - 100;
    swo.printf("%f ", difference);

    swo.printf("\n");

    time = (sensorNoteRunningTimes[4] - sensorNoteRunningTimes[2]) / 1000; //ms
    V = 1000 * BtoC_dist / time; //(mm/s)

    swo.printf("Speed between second and third sensor (mm/s): ");
    swo.printf("%f ", V);
    swo.printf("  Counted encoder pulses: ");
    countedPulses = pulseCountBetweenSensors[4] - pulseCountBetweenSensors[2];
    swo.printf("%d ", countedPulses);
    swo.printf("  ->Encoder speed (mm/s): ");
    countedSpeed = 1000 * countedPulses / time;
    swo.printf("%f ", countedSpeed);
    swo.printf("  ->Speed difference (percentage): ");
    difference = (100 * V / countedSpeed) - 100;
    swo.printf("%f ", difference);

    swo.printf("\n");

    time = (sensorNoteRunningTimes[6] - sensorNoteRunningTimes[4]) / 1000; //ms
    V = 1000 * CtoD_dist / time; //(mm/s)

    swo.printf("Speed between third and fourth sensor (mm/s): ");
    swo.printf("%f ", V);
    swo.printf("  Counted encoder pulses: ");
    countedPulses = pulseCountBetweenSensors[6] - pulseCountBetweenSensors[4];
    swo.printf("%d ", countedPulses);
    swo.printf("  ->Encoder speed (mm/s): ");
    countedSpeed = 1000 * countedPulses / time;
    swo.printf("%f ", countedSpeed);
    swo.printf("  ->Speed difference (percentage): ");
    difference = (100 * V / countedSpeed) - 100;
    swo.printf("%f ", difference);

    swo.printf("\n");

    time = (sensorNoteRunningTimes[8] - sensorNoteRunningTimes[6]) / 1000; //ms
    V = 1000 * DtoE_dist / time; //(mm/s)

    swo.printf("Speed between fourth and fifth sensor (mm/s): ");
    swo.printf("%f ", V);
    swo.printf("  Counted encoder pulses: ");
    countedPulses = pulseCountBetweenSensors[8] - pulseCountBetweenSensors[6];
    swo.printf("%d ", countedPulses);
    swo.printf("  ->Encoder speed (mm/s): ");
    countedSpeed = 1000 * countedPulses / time;
    swo.printf("%f ", countedSpeed);
    swo.printf("  ->Speed difference (percentage): ");
    difference = (100 * V / countedSpeed) - 100;
    swo.printf("%f ", difference);

    swo.printf("\n");
    swo.printf("\n");

    time = (sensorNoteRunningTimes[8] - sensorNoteRunningTimes[0]) / 1000; //ms
    V = 1000 * Tot_dist / time; //(mm/s)

    swo.printf("Total mean speed between first and last sensor (mm/s): ");
    swo.printf("%f ", V);
    swo.printf("  Total counted encoder pulses: ");
    countedPulses = pulseCountBetweenSensors[8] - pulseCountBetweenSensors[0];
    swo.printf("%d ", countedPulses);
    swo.printf("  ->Encoder speed (mm/s): ");
    countedSpeed = 1000 * countedPulses / time;
    swo.printf("%f ", countedSpeed);
    swo.printf("  ->Total speed difference (percentage): ");
    difference = (100 * V / countedSpeed) - 100;
    swo.printf("%f ", difference);

    swo.printf("\n");
    swo.printf("\n");

    swo.printf("Maximum time between pulses (us): %d\r\n", maxTimeBetweenPulses);
    swo.printf("Minimum time between pulses (us): %d\r\n", minTimeBetweenPulses);

    swo.printf("\n");
    swo.printf("Filtered speed value to PID (mm/s): ");
    swo.printf("%f ", currentSpeed);
    

    swo.printf("\n");
    swo.printf("\n");


    reportNoteThroughSensorLengths();
    
    maxTimeBetweenPulses = 0;
    minTimeBetweenPulses = 10000000;
    pulses = 0;

    reportTimer = t.read_ms();
}



void encTick(void)
{
    long now = t.read_us();
    timeBetweenPulses = now - lastPulseTime;

    if(noteInSystem) {
        if(timeBetweenPulses > maxTimeBetweenPulses) maxTimeBetweenPulses = timeBetweenPulses;  //storing maximum time between pulses
        if(timeBetweenPulses < minTimeBetweenPulses) minTimeBetweenPulses = timeBetweenPulses;  //storing minimum time between pulses
    }

    lastPulseTime = now;

    pulses++;

    //filtered 10%
    currentSpeed = 0.05 * (1000000/timeBetweenPulses) + 0.95 * currentSpeed;  //mm/s
    //currentSpeed = 1000000/timeBetweenPulses;  //mm/s
}

void checkOpticalSensors(void)
{

    for(int i=0; i<=5; i++) {
        opticalSensors[i]=0;
    }

    if(SCANNER_INPUT) {
        opticalSensors[0]=1;
        if(lastValueOpticalSensors[0] == 0) {
            sensorNoteRunningTimes[0] = t.read_us();    //leading edge of note detected on first optical sensor - storing time
            noteInSystem = 1;   //note entered the system
            pulseCountBetweenSensors[0] = pulses;
        }
    } else {
        if(lastValueOpticalSensors[0] == 1) {
            sensorNoteRunningTimes[1] = t.read_us();    //leaving edge of note detected on first optical sensor - storing time
            pulseCountBetweenSensors[1] = pulses;
        }
    }

    if(SCANNER_OUTPUT) {
        opticalSensors[1]=1;
        if(lastValueOpticalSensors[1] == 0) {
            sensorNoteRunningTimes[2] = t.read_us();    //note detected on second optical sensor - storing time
            pulseCountBetweenSensors[2] = pulses;
        }
    } else {
        if(lastValueOpticalSensors[1] == 1) {
            sensorNoteRunningTimes[3] = t.read_us();    //leaving edge of note detected on first optical sensor - storing time
            pulseCountBetweenSensors[3] = pulses;
        }
    }

    if(SWITCH_INPUT) {
        opticalSensors[2]=1;
        if(lastValueOpticalSensors[2] == 0) {
            sensorNoteRunningTimes[4] = t.read_us();    //note detected on second optical sensor - storing time
            pulseCountBetweenSensors[4] = pulses;
        }
    } else {
        if(lastValueOpticalSensors[2] == 1) {
            sensorNoteRunningTimes[5] = t.read_us();    //leaving edge of note detected on first optical sensor - storing time
            pulseCountBetweenSensors[5] = pulses;
        }
    }

    if(REJECT_INPUT) {
        opticalSensors[3]=1;
        if(lastValueOpticalSensors[3] == 0) {
            sensorNoteRunningTimes[6] = t.read_us();    //note detected on second optical sensor - storing time
            pulseCountBetweenSensors[6] = pulses;
        }
    } else {
        if(lastValueOpticalSensors[3] == 1) {
            sensorNoteRunningTimes[7] = t.read_us();    //leaving edge of note detected on first optical sensor - storing time
            pulseCountBetweenSensors[7] = pulses;
        }
    }

    if(REJECT_OUTPUT) {
        opticalSensors[4]=1;
        if(lastValueOpticalSensors[4] == 0) {
            sensorNoteRunningTimes[8] = t.read_us();    //note detected on second optical sensor - storing time
            pulseCountBetweenSensors[8] = pulses;
        }
    } else {
        if(lastValueOpticalSensors[4] == 1) {
            sensorNoteRunningTimes[9] = t.read_us();    //leaving edge of note detected on first optical sensor - storing time
            pulseCountBetweenSensors[9] = pulses;
            noteInSystem = 0;   //note left the system
            report();
        }
    }

    if(STORAGE_INPUT) opticalSensors[5]=1;

    //storing sensor state in previous value array
    for(int i=0; i<=5; i++) {
        lastValueOpticalSensors[i] = opticalSensors[i];
    }

}

void tunePID()
{

    swo.printf("setting 60percent output %\n");
    MAIN_PWM.write(0.6f);
    swo.printf("waiting for speedup... %\n");
    wait(2);    //waiting 2 sec
    swo.printf("Current speed (mm/s): %f\n", currentSpeed);
    double beforeSpeed = currentSpeed;
    swo.printf("setting 70percent output %\n");
    MAIN_PWM.write(0.7f);   //10% more output
    swo.printf("waiting for speedup... %\n");
    wait(2);    //waiting 2 sec
    swo.printf("Current speed (mm/s): %f\n", currentSpeed);
    double deltaSpeed = currentSpeed - beforeSpeed;
    swo.printf("delta Speed (mm/s): %f\n", deltaSpeed);
    double K = deltaSpeed / 10;
    swo.printf("PID K-factor (deltaSpeed/10): %f\n", K);

    controller.setTunings(K/2, 0, 0); //K/2?

    controller.setInputLimits(0.0, 600);

    //Pwm output from 0.0 to 1.0
    controller.setOutputLimits(0.0, 1.0);

    controller.setMode(AUTO_MODE);

    controller.setSetPoint(600);

    swo.printf("\n");
    swo.printf("\n");
    swo.printf("\n");

}


int main()
{
    LED_ENABLE = 1; //turning leds on
    LED_GREEN = 0;
    LED_RED = 0;

    //Setting motors off
    MAIN_PWM.write(0.00f);
    SWITCH_PWM.write(0.00f);
    ROUTER_PWM.write(0.00f);
    STORAGE_PWM.write(0.00f);
    MAIN_PWM.period(0.00005);  //Set motor PWM periods to 20KHz.
    SWITCH_PWM.period(0.00005);  //Set motor PWM periods to 20KHz.
    ROUTER_PWM.period(0.00005);  //Set motor PWM periods to 20KHz.
    STORAGE_PWM.period(0.00005);  //Set motor PWM periods to 20KHz.


    swo.printf("STARTED %\n");
    swo.printf("CPU SystemCoreClock is %d Hz\r\n", SystemCoreClock);    //SYTEM CLOCK 72MHz
    MAIN_ENC.rise(&encTick);  // attach the address of the encTick function to the rising edge

    t.start();

    //MAIN_PWM.write(0.7f); //40% works 0.4f

    tunePID();


    while(1) {


        checkOpticalSensors();  //updating opticalSensors array

        //if(t.read_ms() - reportTimer > 1000 && noteInSystem == 0) report();  //reporting every second

        if(t.read_ms() -  lastControl > RATE) {
            //Update the process variable.
            controller.setProcessValue(currentSpeed);
            //Set the new output.
            double output = controller.compute();
            MAIN_PWM.write(output);
            //swo.printf("sent to controller: %f\n", output);
            lastControl = t.read_ms();
        }

    }


}