J L
/
Neptune_170620
Neptune_170620
Diff: Controls.cpp
- Revision:
- 0:20b4b057fa7f
diff -r 000000000000 -r 20b4b057fa7f Controls.cpp --- /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); + } +} + +