Flow measurement

Dependencies:   mbed PID FastPWM

main.cpp

Committer:
renemagrit
Date:
2020-05-04
Revision:
0:638eb51d9082

File content as of revision 0:638eb51d9082:

/*
 * Date: march 2020.
 * Decription: Bilo je potrebno napraviti sistem PID regulatora ciji je osnovni
    zadatak odrzavanja pritiska vrednosti 0 Bara. 
    Sistem se sastoji iz: 
        1.Senzora pritiska
        2.Step motora koji pogoni elektricnu pumpu
    Izlaz PID regulatira je frekvencija obrtanja step motora koji tera pumpu. 
    Sto se motor brze okrece to pumpa vise kolicine izvlaci.
    Na ovaj nacin obezbedjeno je precizno protocno merenje kolicine u ispitivanju
    injekotra.
    Sistem tokom celokupnog rada zeli da stabilise pritisak od 0 Bari i time
    ponisti razliku pritisaka koja se javlja usled odredjene kolicine goriva u 
    sistemu.
 
    - Dugorocnim testiranjem utvrdjeni su parametri PID kontrolera.
    - Senzor pritiska se filtira sa MID7 filterom
    - Izmerena kolicina se filtrira sa MID7 filterom
    - PID procesuira zahteve svakih 100ms
*/
#include "mbed.h"
#include "AsynchSerial.h"
#include "PID.h"
#include "FastPWM.h"

#define RATE 0.1
#define ZERO 2.33
AsynchSerial pc(USBTX, USBRX, 115200);

EventQueue queue;
Ticker tick;

//Kc, Ti, Td, interval
PID controller(2.5, 1, 0.0, RATE);
AnalogIn pv(PA_0);
FastPWM   co(PA_1,2);

//mm u opsegu od 0 do 100

float reff; 
float value;
float inValue;

float analogInValues[7];
float freqValues[7];
volatile int cntFreq = 0;
int n = 7;
int enable = 0;
int width = 0;

void getData() {
/*Citanje podatka iz Buffera Serijske komunikacije -uz resnje GRESKE citanja*/
    
    unsigned char buffer[20];
    int16_t len = pc.read(buffer, sizeof(buffer));

    if (len > 0) {
       
        int kom = sscanf((const char *)buffer,"%f",&reff);
       
        if(kom==1){ 
            if(reff > 100.0){
                controller.setSetPoint(0);
                printf("Greska! Referenca veca od 100 mm");
            }else 
                controller.setSetPoint(reff);
        }
    }
}

void rxCb() {
    
    queue.call(getData);  // can't read data in callback
    
}
void printuj(void){
    freqValues[cntFreq++] = value/2.0;
    if(cntFreq == 7){
        cntFreq = 0;
         for (int i = 0; i < n; i++)
            // Last i elements are already in place
            for (int j = 0; j < n-i-1; j++)
                if (freqValues[j] > freqValues[j+1]){
                    float temp = freqValues[j];
                    freqValues[j]=freqValues[j+1];
                    freqValues[j+1]=temp;
                }
                
        printf("Ref: %.1f \n",reff);
        printf("Input Analog High: %.1f mm \n", inValue);
        printf("F: %.1f Hz\n",freqValues[4]);
        printf("Q: %.1f ml\n",freqValues[4]*0.045);
         
    } 
}
void setData(void){
    
    queue.call(printuj);
    
}
 
int main(){
        
      Thread eventThread;
      eventThread.start(callback(&queue, &EventQueue::dispatch_forever));
      pc.attach(callback(rxCb), AsynchSerial::RX); 
      pc.init(); //Serial buffer interrupt
      tick.attach(&setData, 0.3);
        
      //Set the period to 1ms = 1kHz
      co.pulsewidth_ms(0);     
      co.prescaler(2);
      
      controller.setInputLimits(-100.0, 100.0);
      //Pwm output from 0.0 to 1.0
      controller.setOutputLimits(4, 3200);
      //If there's a bias.
      controller.setBias(0);
      controller.setMode(1); //not null value is AUTO MODE
      //We want the process variable to be 1.7V
      controller.setSetPoint(0.0);
     
      while(1){
        
        for(int i=0;i<n;i++){
            analogInValues[i] = pv.read();
            wait_ms(10);
        }
        // sort . . .
        for (int i = 0; i < n; i++)
            // Last i elements are already in place
            for (int j = 0; j < n-i-1; j++)
                if (analogInValues[j] > analogInValues[j+1]){
                    float temp = analogInValues[j];
                    analogInValues[j]=analogInValues[j+1];
                    analogInValues[j+1]=temp;
                }
        
        //Update the process variable.
        //input u mm
        inValue = (float)(((ZERO - analogInValues[4] * (float)3.29) * 100.0)/1.59)*(-1.0);
        //inValue = (float)(((ZERO - pv.read() * (float)3.29) * 100.0)/1.59);
        controller.setProcessValue(inValue);
        
        //Set the new output.
        value = controller.compute();
        
        if(value == 0){
            enable = 0;
            printf("Greska! Value = 0");
        }else{
            int period = (int)(1.0/value * 1000000);
            co.period_us(period); 
            enable = 1;
        }   
        if(enable == 1){
            if(value > 100)
                co.pulsewidth_us(25);
            else
                co.pulsewidth_ms(2);
        }else{
            co.pulsewidth_us(0);
        }         
        wait_ms(100 - 10*n);
        
      }
}