Neptune_170620

Dependencies:   mbed

Revision:
0:20b4b057fa7f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Controls.cpp	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,600 @@
+#include <string> 
+#include "main.h"
+#include "Functions.h"
+#include "Definitions.h"
+#include "Boolean.h"
+#include "NextionLCD.h"
+#include "mbed_debug.h"
+#include "mbed.h"
+#include "Languages.h"
+#include "Ser25lcxxx.h"
+#include "NVM.h"
+#include "Watchdog.h"
+#include "NextionPages.h"
+#include "Controls.h"
+#include "ISR.h"
+#include "FastPWM.h"
+
+/*
+    CONTROLS
+
+    Start Button
+    Stop Button
+    Analogue Input
+    Analogue Output
+    Motor Control
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// MBED OBJECTS
+///////////////////////////////////////////////////////////////////////////////
+extern NextionLCD lcd;//Tx, Rx, Nextion Port
+
+//ADC/DAC
+AnalogIn ain(ANA_IN_A0);
+AnalogOut aout(ANA_OUT_DAC1);
+
+//Button Membrane 
+DigitalOut startLED(START_LED);
+DigitalOut stopLED(STOP_LED);
+DigitalIn startButton(START_BTN);
+DigitalIn stopButton(STOP_BTN);
+
+//4-20mA Control Inputs
+DigitalIn rmtRunStop(RUN_STOP);// Run / Stop Input
+DigitalIn rmtExtCont(EXT_CONT);//External Contact Input
+DigitalIn rmtFldRec(RMT_FLD_REC);//Remote Fluid Recovery Input
+
+//Leak detection
+DigitalIn leakIn(LEAK_DETECT_INPUT);//Pump head leak detection
+
+//4-20mA Control Outputs
+DigitalOut alarmOut1(ALARM_OUT1);
+DigitalOut alarmOut2(ALARM_OUT2);
+
+//Nucleo Debug LEDs
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3); 
+
+//DVR8603 BLDC Motor Controller
+DigitalOut motEnable(MOT_EN);
+DigitalOut motDir(MOT_DIR);
+DigitalOut nBrake(N_BRK);
+DigitalIn nFault(N_FAULT);
+
+//Netxion Power Control
+DigitalOut nexPwrCont(NEX_PWR);
+
+//3V3 Power Good signal from power supply
+DigitalIn pwrGood(PWR_GOOD);
+
+FastPWM pwm(PWM, PWM_PRESCALER);//leave prescaler at 1 so that that the smallest speed inc/dec results in a measureable PWM change, resolution is ~20ns/bit
+
+float motorSpeed = ZERO;
+float motSpeedSetPoint = ZERO;
+float flowPercent = ZERO;
+float lastMaxScale = maxScale;
+
+bool leakDetect(bool leakInput){
+    bool leak = false;    
+
+    if(leakInput == true){
+        leak = true;
+    }   
+
+    return(leak);    
+}
+
+bool outputFluidLevMon(void){
+
+    return(0);
+}
+
+bool outputContactMode(void){
+
+    /*
+    
+     need debouce routine 
+     measure pulse time, 40 - 1000ms
+
+     if valid do stuff, if pulse not valid ignore
+
+     count the pulses also
+    
+     */
+    return(0);
+}
+
+bool startBtn(bool byPassPress){//Interrupt pin
+/*
+    byPassPress if true allows the fucntion to be used for LED indicators without pressing the start button
+*/
+    bool state = OFF;
+
+    if((startButton == _ON)||(byPassPress == true)){    
+        startLED = ON;//Keypad LEDs OFF ta power up
+        stopLED = OFF;          
+        state = ON;
+    }
+    return(state);
+}
+
+bool stopBtn(bool byPassPress){//Interrupt pin
+/*
+    byPassPress if true allows the fucntion to be used  for LED indicators without pressing the stop button
+*/
+    bool state = OFF;
+
+    if((stopButton == _ON)||(byPassPress  == true)){
+        startLED = OFF;//Keypad LEDs OFF ta power up
+        stopLED = ON;             
+        state = ON;
+    }
+    return(state);
+}
+
+void reset(void){
+    ml=ZERO;
+    arrowFlag = false;
+    motorSpeed = ZERO;
+    motSpeedSetPoint = ZERO;
+    ConfInputSw();
+    confBtn();
+    confMotor();//turn motor off    
+    confPWM();//Reset      
+}
+
+void confBtn(void){
+    startLED = OFF;//Keypad LEDs OFF ta power up
+    stopLED = OFF;
+    startButton.mode(PullUp);//Enable pull up resistors to 3V3
+    stopButton.mode(PullUp);
+}
+
+void ConfInputSw(void){
+    rmtFldRec.mode(PullDown);
+    rmtExtCont.mode(PullDown);
+    rmtRunStop.mode(PullDown);
+}
+
+void confMotor(void){
+    motEnable = OFF;
+    motDir = CCW;//Default motor direction
+    nBrake = _OFF;
+    tachoIn.mode(PullUp);//Speed feedback, OD Output from motor controller
+    nFault.mode(PullUp);
+}
+
+uint8_t fluidRecMode(void){
+    
+ return(0);     
+}
+
+uint8_t flowCalMode(void){
+
+ return(0); 
+}
+
+uint8_t contactMode(void){
+
+ return(0); 
+}
+
+void anaOutScale(float mA_FullScale, float mA_MatchScale){
+    
+    if(nvm._4_20mAoutPut == _4_20MA_OUT_FULL_SCALE)
+        anaOut_mA(mA_FullScale);    
+    else
+        if(nvm._4_20mAoutPut == _4_20MA_OUT_MATCH_INPUT_SCALE)
+            anaOut_mA(mA_MatchScale);
+}
+
+void anaOut_mA(float mA){
+/*
+    Current to DAC Voltage converter
+    aout.write() has range 0.0 - 1.0
+*/    
+
+    float rawDAC_V = ZERO;
+    float lpfDAC_V = ZERO;
+   
+    rawDAC_V = mapF(mA, I_3MA, I_20MA, DAC_V_LOW, DAC_V_HIGH);        
+    aout.write(rawDAC_V);         
+}
+
+float anaIn_mA(void){
+/*
+    Low Pass Filtered analogue signal
+*/
+    float rawADC_V = ZERO;//Raw ADC voltage
+    float lpfADC_V = ZERO;//Low Pass Filtered ADC Voltage    
+    float ana_mA = ZERO; //ADC Voltage convered to mA 
+
+    rawADC_V = (ain.read() * VDD);//Output in V  
+    lpfADC_V = low_pass_filterF(rawADC_V);
+    ana_mA = mapF(lpfADC_V, ADC_MIN_V, ADC_MAX_V, I_0MA, I_22_4MA);
+
+    return(ana_mA);    
+}
+ 
+uint8_t anaIn(void){
+/*
+    Convert analogue signal to mA output and control motor speed
+    Measured Hyteresis band is approx 50uA on QDOS 30
+*/
+
+    float lpfADC_V = ZERO;//ADC variable from Low Pass Filter 
+    float ana_mA = ZERO;
+    static float flowPercent;//flow rate percentage, used for map calculations
+    static float hyst_mA = ZERO;//
+    static bool pumpMotor =  OFF;//make sure the motor is off by default
+ 
+    uint8_t task = RUNNING;//next normal task
+
+    ana_mA = anaIn_mA();//get the analogue current from external equipment 
+
+    //lcd.nexSendFloat("p1left",ana_mA,2);//update
+         
+    if(ana_mA >= (nvm.mA_low - hyst_mA)){//hysteresis to stop noise triggering motor control    
+        hyst_mA = HYST_MA;
+        pumpMotor = ON;       
+        startBtn(ON);              
+    }          
+    else{
+        hyst_mA = ZERO;  
+        pumpMotor = OFF; 
+        stopBtn(ON);              
+    }
+                
+      if((runStopSignal(rmtRunStop, &nvm) == false)&&(pumpMotor == ON)){//Pump is ON
+        lcd.nexRotArrow(ON);
+        lcd.nexSetFontCol("p1mid",BLACK);       
+        lcd.nexSendTxt("p1mid","4-20mA Input Mode");//page 1 middle text box   
+ 
+        flowPercent = mapF(ana_mA, nvm.mA_low, nvm.mA_high, nvm.flow_low, nvm.flow_high);//this outputs flow rate % used in map calculations     
+
+        nvm.flowUnitVal = mapF(flowPercent, 0.0, 100.0, minScale, maxScale);
+
+        lcd.nexSendFloat("meter", nvm.flowUnitVal, precision);//display the flow units                                           
+
+        motor(flowPercent, CCW, BRAKE_OFF, MOTOR_ENABLE, 1);
+
+        anaOutScale((mapF(nvm.flowUnitVal, minScale, maxScale, I_4MA, I_20MA)), (mapF(nvm.flowUnitVal, minScale, nvm.flow_high, I_4MA, I_20MA)));
+ 
+    }
+    else
+    {//Pump is OFF     
+        //lcd.nexDispSymbol("stop", OFF);          
+        lcd.nexRotArrow(OFF);
+        lcd.nexSetFontCol("p1mid",RED);     
+        lcd.nexSendTxt("p1mid","4-20mA Input Mode");//page 1 middle text box    
+        lcd.nexSendFloat("meter", METER_ZERO, precision);//bug warning: writting 0.00 result in blank writted to meter, writing 0.00001 to the meter then displays 0.0        
+        motor(ZERO, CCW, BRAKE_OFF, MOTOR_DISABLE, 1);   
+        anaOut_mA(I_3MA);//analogue output forced to 3mA 
+    }      
+    return(task);           
+}
+
+uint8_t manual(void){
+
+    float ana_mA = 0;    
+    static float lastFlowUnitVal = nvm.flowUnitVal;
+    uint8_t task = RUNNING;
+
+    if(runStopSignal(rmtRunStop, &nvm) == false){//Run/Stop signal logic                   
+
+        flowPercent = incDecControl(&nvm.flowUnitVal, precision, minScale, maxScale, nvm.speedLimit);
+
+            if((tPop.read() > 1.0)&&(lastFlowUnitVal == nvm.flowUnitVal)){//x seconds has expired save the updated  flowUnitVal to NVM memory and reload NVM
+                tPop.stop();
+                tPop.reset();
+                stopLED = ON;
+                wait(0.01);
+                stopLED = OFF;  
+                writeNVMfloat(NVM_FLOWU_VAL,nvm.flowUnitVal);        
+            }
+
+            lcd.nexRotArrow(ON);
+            lcd.nexSetFontCol("p1mid",BLACK);                                                                                           
+            lcd.nexSendTxt("p1mid","Manual Mode");//page 1 middle text box       
+
+            nvm.flowUnitVal = ((flowPercent/100)*maxScale);
+            lcd.nexSendFloat("meter", nvm.flowUnitVal, precision);//display the flow units   
+                
+            motor(flowPercent, CCW, BRAKE_OFF, MOTOR_ENABLE, 1);    
+
+            anaOut_mA(mapF(nvm.flowUnitVal, minScale, maxScale, I_4MA, I_20MA));//convert flow rate % to analogue output current    
+
+            lastFlowUnitVal = nvm.flowUnitVal;//update
+        //}
+    }
+    else{   
+        //lcd.nexDispSymbol("stop", OFF);   
+        lcd.nexRotArrow(OFF); 
+        lcd.nexSetFontCol("p1mid",RED);                                                                                           
+        lcd.nexSendTxt("p1mid","Manual Mode");//page 1 middle text box           
+        motor(flowPercent, CCW, BRAKE_OFF, MOTOR_DISABLE, 1);    
+    }
+    
+    return(task); 
+}
+ 
+uint8_t motor(float rpmSetPoint, bool dir, bool brake, bool enable, float rampTime){
+
+    uint8_t task = RUNNING;//next normal task
+
+    static float rpmRamp = ZERO;
+    
+    motEnable = enable;
+    motDir = dir;
+    nBrake = brake;
+    
+    if((motEnable == MOTOR_DISABLE)||(nBrake == BRAKE_ON))    
+        rpmRamp = ZERO;
+    else{
+
+        if(rpmRamp > rpmSetPoint){    
+
+            pwm.pulsewidth_us(rpmRamp);            
+
+            if(rpmRamp > MOTOR_PWM_MIN)
+                rpmRamp-=0.1;
+            else
+                rpmRamp = MOTOR_RPM_MIN;                                       
+        }
+
+        if(rpmRamp < rpmSetPoint){
+        
+            pwm.pulsewidth_us(rpmRamp);        
+        
+            if(rpmRamp < MOTOR_PWM_MAX)
+                rpmRamp+=0.1;
+            else  
+                rpmRamp = MOTOR_PWM_MAX;                                 
+        }                      
+    }
+
+    lcd.nexSetPrgBar("progBar",rpmRamp);  
+
+    return(task);
+}
+
+void confPWM(void){    
+    pwm.period_us(PWM_PERIOD);
+    pwm.pulsewidth_us(ZERO);      
+}
+
+void ledClr(void){
+    led1=OFF; 
+    led2=OFF; 
+    led3=OFF; 
+}
+
+uint8_t startUpMode(uint8_t runMode){
+    uint8_t task = START;         
+    uint8_t setRunMode;    
+
+    setRunMode = runModeNVM(runMode);//retreive the run mode stored in NVM    
+
+    if(setRunMode == ANALOGUE_SET)//if set for analogue start 
+        task = ANALOGUE_SET;                                                  
+    else
+    {  
+        if((startBtn(BTN_AND_IND))&&(setRunMode == MANUAL_SET))//if set for manual bypass start button and start                                                                                                              
+            task = MANUAL_SET;                                                                                                                                                                                                                                                     
+    }                                                                                                                                                                            
+    return(task);
+}
+ 
+bool runStopSignal(bool runStopSig, struct settingsNVM *nvm){    
+
+    //#define DEBUG_LOCAL
+
+    #ifdef DEBUG_LOCAL
+        uint8_t selected=0;
+    #endif
+
+    bool pumpPause = false;
+
+
+    if((nvm->rmtStopPump == RMT_STOP_PUMP_HIGH)&&(runStopSig == HI)){  
+
+        #ifdef DEBUG_LOCAL
+            selected=1;    
+        #endif 
+
+        lcd.nexDispSymbol("pause", ON);         
+        nvm->pumpOnOff = PUMP_OFF;                  
+        writeNVMByte(PUMP_ON_OFF,nvm->pumpOnOff);          
+        pumpPause = true;        
+    }
+    else
+    if((nvm->rmtStopPump == RMT_STOP_PUMP_HIGH)&&(runStopSig == LO)){  
+
+        #ifdef DEBUG_LOCAL
+            selected=2;                
+        #endif
+
+        lcd.nexDispSymbol("pause", OFF);      
+        nvm->pumpOnOff = PUMP_ON;  
+        writeNVMByte(PUMP_ON_OFF,nvm->pumpOnOff);                           
+        pumpPause = false;                  
+    }    
+    else       
+    if((nvm->rmtStopPump == RMT_STOP_PUMP_LOW)&&(runStopSig == HI)){        
+
+        #ifdef DEBUG_LOCAL        
+            selected=3;          
+        #endif
+
+        lcd.nexDispSymbol("pause", OFF);  
+        nvm->pumpOnOff = PUMP_ON;                
+        writeNVMByte(PUMP_ON_OFF,nvm->pumpOnOff);                     
+        pumpPause = false;                
+    }
+    else
+    if((nvm->rmtStopPump == RMT_STOP_PUMP_LOW)&&(runStopSig == LO)){    
+
+        #ifdef DEBUG_LOCAL        
+            selected=4;          
+        #endif    
+
+        lcd.nexDispSymbol("pause", ON);   
+        nvm->pumpOnOff = PUMP_OFF;                     
+        writeNVMByte(PUMP_ON_OFF,nvm->pumpOnOff);                 
+        pumpPause = true;                         
+    }        
+ 
+    #ifdef DEBUG_LOCAL
+        pc.printf("\r\n\nPump On/Off = 0x%02X, Selected = %d",nvm->pumpOnOff, selected); 
+    #endif        
+    
+
+    return(pumpPause);
+}
+ 
+void outPuts(bool leakDetection, struct settingsNVM *nvm){
+
+        if((nvm->outPut1 ==  OUT1_RUN_STATUS)&&(nvm->outPut1Logic == OUT1_LOGIC_LO)&&(nvm->pumpOnOff == PUMP_ON)){
+        // Run status ok for manual and analogue            
+        
+            alarmOut1 = OFF;
+        }
+        else   
+        if((nvm->outPut1 ==  OUT1_RUN_STATUS)&&(nvm->outPut1Logic == OUT1_LOGIC_LO)&&(nvm->pumpOnOff == PUMP_OFF)){
+            alarmOut1 = ON;
+        }   
+        else
+        if((nvm->outPut1 ==  OUT1_RUN_STATUS)&&(nvm->outPut1Logic == OUT1_LOGIC_HI)&&(nvm->pumpOnOff == PUMP_ON)){
+            alarmOut1 = ON;
+        }
+        else   
+        if((nvm->outPut1 ==  OUT1_RUN_STATUS)&&(nvm->outPut1Logic == OUT1_LOGIC_HI)&&(nvm->pumpOnOff == PUMP_OFF)){
+            alarmOut1 = OFF;
+        }         
+        else
+        if((nvm->outPut1 ==  OUT1_MANUAL_MODE)&&(nvm->outPut1Logic == OUT1_LOGIC_HI)&&(nvm->runMode == MANUAL)){
+            alarmOut1 = ON;
+        }    
+        else
+        if((nvm->outPut1 ==  OUT1_MANUAL_MODE)&&(nvm->outPut1Logic == OUT1_LOGIC_LO)&&(nvm->runMode == MANUAL)){
+            alarmOut1 = OFF;
+        }  
+        else
+        if((nvm->outPut1 ==  OUT1_ANALOGUE_MODE)&&(nvm->outPut1Logic == OUT1_LOGIC_HI)&&(nvm->runMode == ANALOGUE)){
+            alarmOut1 = ON;
+        }    
+        else
+        if((nvm->outPut1 ==  OUT1_ANALOGUE_MODE)&&(nvm->outPut1Logic == OUT1_LOGIC_LO)&&(nvm->runMode == ANALOGUE)){
+            alarmOut1 = OFF;
+        }     
+        else
+        if((nvm->outPut1 ==  OUT1_CONTACT_MODE)&&(nvm->outPut1Logic == OUT1_LOGIC_HI)){
+            alarmOut1 = ON;
+        }    
+        else
+        if((nvm->outPut1 ==  OUT1_CONTACT_MODE)&&(nvm->outPut1Logic == OUT1_LOGIC_LO)){
+            alarmOut1 = OFF;
+        }     
+        else
+        if((nvm->outPut1 ==  OUT1_FLUID_LEVEL)&&(nvm->outPut1Logic == OUT1_LOGIC_HI)){
+            alarmOut1 = ON;
+        }    
+        else
+        if((nvm->outPut1 ==  OUT1_FLUID_LEVEL)&&(nvm->outPut1Logic == OUT1_LOGIC_LO)){
+            alarmOut1 = OFF;
+        }          
+        else
+        if((nvm->outPut1 ==  OUT1_LEAK_DETECT)&&(nvm->outPut1Logic == OUT1_LOGIC_HI)){            
+            alarmOut1 = ~leakDetect(leakDetection);
+        }    
+        else
+        if((nvm->outPut1 ==  OUT1_LEAK_DETECT)&&(nvm->outPut1Logic == OUT1_LOGIC_LO)){
+            alarmOut1 = leakDetect(leakDetection);
+        }                
+        else
+        if((nvm->outPut1 ==  OUT1_GENERAL_ALARM)&&(nvm->outPut1Logic == OUT1_LOGIC_HI)){
+        /*  Not defined in QDOS documents, I know leak detect triggers this there will be 
+            others faults tha trigger this but at this time they are not known.
+            
+        */
+            alarmOut1 = ~leakDetect(leakDetection);
+        }    
+        else
+        if((nvm->outPut1 ==  OUT1_GENERAL_ALARM)&&(nvm->outPut1Logic == OUT1_LOGIC_LO)){
+            alarmOut1 = leakDetect(leakDetection);
+        }                
+
+
+
+        if((nvm->outPut2 ==  OUT2_RUN_STATUS)&&(nvm->outPut2Logic == OUT2_LOGIC_LO)&&(nvm->pumpOnOff == PUMP_ON)){
+            alarmOut2 = OFF;
+        }
+        else   
+        if((nvm->outPut2 ==  OUT2_RUN_STATUS)&&(nvm->outPut2Logic == OUT2_LOGIC_LO)&&(nvm->pumpOnOff == PUMP_OFF)){
+            alarmOut2 = ON;
+        }   
+        else
+        if((nvm->outPut2 ==  OUT2_RUN_STATUS)&&(nvm->outPut2Logic == OUT2_LOGIC_HI)&&(nvm->pumpOnOff == PUMP_ON)){
+            alarmOut2 = ON;
+        }
+        else   
+        if((nvm->outPut2 ==  OUT2_RUN_STATUS)&&(nvm->outPut2Logic == OUT2_LOGIC_HI)&&(nvm->pumpOnOff == PUMP_OFF)){
+            alarmOut2 = OFF;
+        }     
+        else
+        if((nvm->outPut2 ==  OUT2_MANUAL_MODE)&&(nvm->outPut2Logic == OUT2_LOGIC_HI)&&(nvm->runMode == MANUAL)){
+            alarmOut2 = ON;
+        }    
+        else
+        if((nvm->outPut2 ==  OUT2_MANUAL_MODE)&&(nvm->outPut2Logic == OUT2_LOGIC_LO)&&(nvm->runMode == MANUAL)){
+            alarmOut2 = OFF;
+        }    
+        else
+        if((nvm->outPut2 ==  OUT2_ANALOGUE_MODE)&&(nvm->outPut2Logic == OUT2_LOGIC_HI)&&(nvm->runMode == ANALOGUE)){
+            alarmOut2 = ON;
+        }    
+        else
+        if((nvm->outPut2 ==  OUT2_ANALOGUE_MODE)&&(nvm->outPut2Logic == OUT2_LOGIC_LO)&&(nvm->runMode == ANALOGUE)){
+            alarmOut2 = OFF;
+        }             
+        else
+        if((nvm->outPut2 ==  OUT2_CONTACT_MODE)&&(nvm->outPut2Logic == OUT2_LOGIC_HI)){
+            alarmOut2 = ON;
+        }    
+        else
+        if((nvm->outPut2 ==  OUT2_CONTACT_MODE)&&(nvm->outPut2Logic == OUT2_LOGIC_LO)){
+            alarmOut2 = OFF;
+        }             
+        else
+        if((nvm->outPut1 ==  OUT1_FLUID_LEVEL)&&(nvm->outPut1Logic == OUT1_LOGIC_HI)){
+            alarmOut1 = ON;
+        }    
+        else
+        if((nvm->outPut2 ==  OUT2_FLUID_LEVEL)&&(nvm->outPut2Logic == OUT2_LOGIC_LO)){
+            alarmOut2 = OFF;
+        }          
+        else
+        if((nvm->outPut2 ==  OUT2_LEAK_DETECT)&&(nvm->outPut2Logic == OUT2_LOGIC_HI)){            
+            alarmOut2 = ~leakDetect(leakDetection);
+        }    
+        else
+        if((nvm->outPut2 ==  OUT2_LEAK_DETECT)&&(nvm->outPut2Logic == OUT2_LOGIC_LO)){
+            alarmOut2 = leakDetect(leakDetection);
+        }                
+        else
+        if((nvm->outPut2 ==  OUT2_GENERAL_ALARM)&&(nvm->outPut2Logic == OUT2_LOGIC_HI)){
+        /*  Not defined in QDOS documents, I know leak detect triggers this there will be 
+            others faults tha trigger this but at this time they are not known.
+            
+        */
+            alarmOut2 = ~leakDetect(leakDetection);
+        }    
+        else
+        if((nvm->outPut2 ==  OUT2_GENERAL_ALARM)&&(nvm->outPut2Logic == OUT2_LOGIC_LO)){
+            alarmOut2 = leakDetect(leakDetection);
+        }           
+}     
+
+