J L
/
Neptune_170620
Neptune_170620
Diff: Functions.cpp
- Revision:
- 0:20b4b057fa7f
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Functions.cpp Wed Jun 17 10:11:19 2020 +0000 @@ -0,0 +1,1030 @@ +#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 "Threads.h" +#include "ISR.h" +#include "FastPWM.h" + +/////////////////////////////////////////////////////////////////////////////// +// MBED OBJECTS +/////////////////////////////////////////////////////////////////////////////// +extern NextionLCD lcd;//Tx, Rx, Nextion Port + +Thread thread; +volatile uint16_t loopTime = 0; +volatile bool loopTimeFlag = false; +volatile bool readFlag = false; + +/////////////////////////////////////////////////////////////////////////////// +// VARIABLES +/////////////////////////////////////////////////////////////////////////////// +bool incFlag = false; +bool decFlag = false; +bool okFlag = false; +bool manFlag = false; + +uint8_t pumpType = QDOS_30; +uint8_t calState = ZERO; + +/////////////////////////////////////////////////////////////////////////////// +// THREADS +/////////////////////////////////////////////////////////////////////////////// +void loopTime_thread(){ + + while(1){ + #ifdef LOOP_TIME + if(readFlag){ + pc.printf("\r\n\r\n Loop Time \t= %d us",loopTime); + readFlag = false; + loopTimeFlag = true; + } + #endif + } +} + +void loopTimeMeasure(void){ + + #ifdef LOOP_TIME + if(!loopTimeFlag){ + //wait_us(20);//add a known time to verify the accuracy of the loop timer + tSec.stop(); + loopTime = tSec.read_us(); + //run_stat_out_oc = 1; + readFlag = true; + } + else{ + tSec.reset(); + tSec.start(); + loopTimeFlag = false; + //run_stat_out_oc = 0; + } + #endif +} + +/////////////////////////////////////////////////////////////////////////////// +// ARRAYS +/////////////////////////////////////////////////////////////////////////////// +char buffer[20]; + +const uint8_t uOutPut1_ID[7] = { + OUT1_GENERAL_ALARM, + OUT1_RUN_STATUS, + OUT1_MANUAL_MODE, + OUT1_ANALOGUE_MODE, + OUT1_CONTACT_MODE, + OUT1_FLUID_LEVEL, + OUT1_LEAK_DETECT +}; + +const uint8_t uOutPut2_ID[7] = { + OUT2_GENERAL_ALARM, + OUT2_RUN_STATUS, + OUT2_MANUAL_MODE, + OUT2_ANALOGUE_MODE, + OUT2_CONTACT_MODE, + OUT2_FLUID_LEVEL, + OUT2_LEAK_DETECT +}; + +const uint8_t uFlowUnitID[10] = { + PERCENT, + GPD, + GPH, + ML_HR, + ML_MIN, + L_DAY, + L_HR, + L_MIN, + OZ_MIN, + RPM +}; + +const string menuStringArray[3][10] = {//[Group][Item], 2 groups, 10 items in each group i.e menuItems[1][6]= "Leak Detect" + "%\0", //0x10 + "gpd\0", //0x11 + "gph\0", //0x12 + "ml/hr\0", //0x13 + "ml/min\0", //0x14 + "l/day\0", //0x15 + "l/hr\0", //0x16 + "l/min\0", //0x17 + "oz/min\0", //0x18 + "RPM\0", //0x19 + + "General Alarm\0", + "Run Status\0", + "Manual Mode\0", + "Analogue Mode\0", + "Contact Mode\0", + "Fluid Level\0", + "Leak Detect\0", + "A1\0", + "B1\0", + "C1\0", + + "General Alarm\0", + "Run Status\0", + "Manual Mode\0", + "Analogue Mode\0", + "Contact Mode\0", + "Fluid Level\0", + "Leak Detect\0", + "A2\0", + "B2\0", + "C2\0" +}; + +const float fMaxFlowUnits[5][10] = { + + //QDOS 30 + 100.0,//% + 190.2,//gpd + 7.925,//gph + 30.00,//l/hr + 500.0,//ml/min + 720.0,//l/day + 30.00,//l/hr + 0.500,//l/min + 17.6,//oz + 125.0,//rpm + + //VDOS 20 + 100.0, + 131.06, + 5.46, + 20670.00, + 344.50, + 496.08, + 20.67, + 0.34, + 12.15, + 65.0, + + //VDOS 30 + 100.0, + 191.56, + 7.98, + 30210.00, + 503.50, + 725.04, + 30.21, + 0.50, + 17.76, + 95.00, + + //VDOS 60 + 100.0, + 380.83, + 15.87, + 60060.00, + 1001.00, + 1441.44, + 60.06, + 1.00, + 35.31, + 110.00, + + //VDOS 120 + 100.0, + 765.62, + 31.90, + 120744.00, + 2012.40, + 2897.86, + 120.74, + 2.01, + 70.98, + 129.00 +}; + +const float fMinFlowUnits[5][10] = { + + //QDOS 30 + 0.1,//% + 0.1,//gpd + 0.001,//gph + 1.0,//ml/hr + 0.1,//ml/min + 0.1,//l/day + 0.01,//l/hr + 0.001,//l/min + 0.1,//oz + 0.1,//rpm + + //VDOS 20 + 0.2, + 0.26, + 0.01, + 41.34, + 0.87, + 0.99, + 0.04, + 0.00, + 0.02, + 5.0, + + //VDOS 30 + 0.2, + 0.38, + 0.02, + 60.42, + 1.01, + 1.45, + 0.06, + 0.00, + 0.04, + 5.0, + + //VDOS 60 + 0.2, + 0.76, + 0.03, + 120.12, + 2.0, + 2.88, + 0.16, + 0.00, + 0.07, + 5.0, + + //VDOS 120 + 0.2, + 1.53, + 0.06, + 241.49, + 4.02, + 5.80, + 0.24, + 0.00, + 0.14, + 5.0 +}; + + +/////////////////////////////////////////////////////////////////////////////// +// FUNCTIONS +/////////////////////////////////////////////////////////////////////////////// +void sysInit(void){ + + wait(0.250);//settle time + + pc.baud(MED_BAUD);//Debug Port + usart6.baud(MED_BAUD);//Motor Controller Port + + led1=ON; + led2=ON; + led3=ON; + wait(2.00); + led1=OFF; + led2=OFF; + led3=OFF; + + nexInit(MED_BAUD); + reset(); + + //4-20mA Control Outputs + alarmOut1 = OFF; + alarmOut2 = OFF; + + initNVM();//Initialise the NVM memory + loadNVM(&nvm,0);//loads EEPROM content to nvm data structure + + nvm.pumpOnOff = PUMP_OFF; + writeNVMByte(PUMP_ON_OFF,nvm.pumpOnOff); + + nvm.speedLimit = 125.0; + writeNVMfloat(NVM_SPEED_LIMIT,nvm.speedLimit); + + #ifdef DEBUG_NVM + + pc.printf("\r\n\r\n HARDWARE \t\t= %s", HARDWARE.c_str()); + pc.printf("\r\n\r\n SOFTWARE \t\t= %s",SOFTWARE.c_str()); + pc.printf("\r\n\r\n AUTHOR \t\t= %s",AUTHOR.c_str()); + pc.printf("\r\n\r\n DATE \t\t\t= %s",__DATE__); + pc.printf("\r\n\r\n TIME \t\t\t= %s",__TIME__); + pc.printf("\r\n\r\n ADC Samples \t\t= %d", ADC_SAMPLES); + pc.printf("\r\n\r\n SPI Freq \t\t= %d(Hz)", SPI_FREQ); + pc.printf("\r\n\r\n Watchdog \t\t= %.1f(Seconds)", WDT); + pc.printf("\r\n\r\n Flow Unit\t\t= 0x%X", nvm.flowUnits); + pc.printf("\r\n\r\n Run Mode\t\t= 0x%X", nvm.runMode); + pc.printf("\r\n\r\n Auto Restart\t\t= 0x%X", nvm.autoRestart); + pc.printf("\r\n\r\n Pump Head\t\t= 0x%X", nvm.pumpHeadStatus); + pc.printf("\r\n\r\n Alarm\t\t\t= 0x%X", nvm.alarm); + pc.printf("\r\n\r\n Head Side\t\t= 0x%X", nvm.headSide); + pc.printf("\r\n\r\n Pump On/Off\t\t= 0x%X", nvm.pumpOnOff); + pc.printf("\r\n\r\n Speed Limit Val\t= %.2f", nvm.speedLimit); + pc.printf("\r\n\r\n Flow Unit Val\t\t= %.2f", nvm.flowUnitVal); + pc.printf("\r\n\r\n Analogue Cal mA Low\t= %.2f(mA)", nvm.mA_low); + pc.printf("\r\n\r\n Analogue Cal mA High\t= %.2f(mA)", nvm.mA_high); + pc.printf("\r\n\r\n Analogue Cal Flow Low\t= %.2f(%%)", nvm.flow_low); + pc.printf("\r\n\r\n Analogue Cal Flow High\t= %.2f(%%)", nvm.flow_high); + pc.printf("\r\n\r\n ADC min V\t\t= %.2f(V)", nvm.adc_min_v); + pc.printf("\r\n\r\n ADC max V\t\t= %.2f(V)", nvm.adc_max_v); + pc.printf("\r\n\r\n DAC V low factor\t= %f", nvm.dac_v_low); + pc.printf("\r\n\r\n DAC V high factor\t= %f", nvm.dac_v_high); + pc.printf("\r\n\r\n DAC V low \t\t= %.2f(V)", nvm.dac_v_low*VDD); + pc.printf("\r\n\r\n DAC V high \t\t= %.2f(V)", nvm.dac_v_high*VDD); + pc.printf("\r\n\r\n Remote Stop Pump Input = 0x%X", nvm.rmtStopPump); + pc.printf("\r\n\r\n Output 1\t\t= 0x%X", nvm.outPut1); + pc.printf("\r\n\r\n Output 1 Logic \t= 0x%X", nvm.outPut1Logic); + pc.printf("\r\n\r\n Output 2\t\t= 0x%X", nvm.outPut2); + pc.printf("\r\n\r\n Output 2 Logic \t= 0x%X", nvm.outPut2Logic); + pc.printf("\r\n\r\n 4-20mA Output\t\t= 0x%X", nvm._4_20mAoutPut); + + usart6.printf("\r\n\r\n Motor Controller Active"); + + #endif + + //pumpType = VDOS_120; + pumpType = QDOS_30; + + //tachoIn.rise(&isr1); + + motor(MOTOR_RPM_MIN, CW, BRAKE_OFF, MOTOR_DISABLE, 100); + + anaOut_mA(I_3MA);//analogue output forced to 3mA + + wd.Configure(WDT); // sets the timeout + + thread.start(callback(loopTime_thread)); +} + +void nexInit(uint32_t baud){ + + /* Set the baudrate which is for debug and communicate with Nextion screen. */ + + nexPwrCont = ON;//Nextion power is on + wait(0.25); + lcd.nexSetBaud(baud);//Set Nextion baud + lcd.nexSetBckLite(100);//program backlight to be off at power up +} + +float motorRPM(void){ + static float rpm = 0.1; + //static float flowUnits = 0.1; + + rpm = mapF(nvm.flowUnitVal, minScale, maxScale, 0, fMaxFlowUnits[pumpType][9]); + + //flowUnits = mapF(rpm,0.1,125.0,minScale,maxScale); + + //return(flowUnits); + return(rpm); +} + +float incDecControl(float *val, float precision, float min, float max, float speedLimit){ + + static bool incMode = false; + static bool decMode = false; + static float speed = SLOW_SPEED; + + if(motorRPM() < speedLimit){ + + if(*val < max){ + if((tPush.read() > START_DELAY)&&(incMode)){//INC button pressed > 0.5 seconds, speed set to fast update + + if(tSpeed.read() > speed){//fast and then slow after 4 seconds + tSpeed.reset(); + + if(tPush.read() > DELAY_LONG){//INC button pressed > 4 seconds, now set speed to slow update + tPush.stop(); + speed = FAST_SPEED; + } + *val+=flowUnitPrec(precision-1); + } + } + else//INC button released + if(incFlag){ + incFlag = false; + incMode = true; + decMode = false; + speed = SLOW_SPEED; + *val+=flowUnitPrec(precision);//Inc 0.1 + } + if(*val > max) + *val = max; + } + } + else + if(motorRPM() > speedLimit) + *val-=0.1; + + if(*val > min){ + + if((tPush.read() > START_DELAY)&&(decMode)){ + + if(tSpeed.read() > speed){//fast and then slow after 4 seconds + tSpeed.reset(); + + if(tPush.read() > DELAY_LONG){//INC button pressed > 4 seconds, now set speed to slow update + tPush.stop(); + speed = FAST_SPEED; + } + *val-=flowUnitPrec(precision-1); + } + } + else + if(decFlag){ + decFlag = false; + decMode = true; + incMode = false; + speed = SLOW_SPEED; + *val-=flowUnitPrec(precision);//Dec 0.1 + } + if(*val < min)//catch fix + *val = min; + + } + return(mapF(*val, 0.0, max, 0.0, 100.0));//return percentage multiplier +} + +long mapI(long x, long in_min, long in_max, long out_min, long out_max){ + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + +float mapF(float in, float inMin, float inMax, float outMin, float outMax) { + // check it's within the range + if (inMin<inMax) { + if (in <= inMin) + return outMin; + if (in >= inMax) + return outMax; + } else { // cope with input range being backwards. + if (in >= inMin) + return outMin; + if (in <= inMax) + return outMax; + } + // calculate how far into the range we are + float scale = (in-inMin)/(inMax-inMin); + // calculate the output. + return outMin + scale*(outMax-outMin); +} + +void diags(void){ + pc.printf("////////////////////////////////////////////////////////////////////////////////\r\n"); + pc.printf("//Neptune Diagnostics\r\n"); + pc.printf("////////////////////////////////////////////////////////////////////////////////\r\n"); +} + +uint8_t decodeByteNVM(uint8_t nvmByte, uint8_t *prec){ +/* + Decode Byte from NVM + + Function decodes nvm byte and displays and:- + * Displays the approriate string for the passed nvm byte + * Sets the flow unit precision when nvm byte is a flow unit + * Sets the min and max scale when nvm bytes is a flow unit + */ + uint8_t list = 0; + uint8_t i = ZERO; + bool error = false; + + switch(nvmByte){ + + case OUT1_GENERAL_ALARM: + case OUT1_RUN_STATUS: + case OUT1_MANUAL_MODE: + case OUT1_ANALOGUE_MODE: + case OUT1_CONTACT_MODE: + case OUT1_FLUID_LEVEL: + case OUT1_LEAK_DETECT: list = OUTPUT1_LIST; break; + + case OUT2_GENERAL_ALARM: + case OUT2_RUN_STATUS: + case OUT2_MANUAL_MODE: + case OUT2_ANALOGUE_MODE: + case OUT2_CONTACT_MODE: + case OUT2_FLUID_LEVEL: + case OUT2_LEAK_DETECT: list = OUTPUT2_LIST; break; + + case PERCENT: + case GPD: + case ML_MIN: + case L_DAY: + case OZ_MIN: + case RPM: *prec = 1; break; + + case ML_HR: + case L_HR: *prec = 2; break; + + case GPH: + case L_MIN: *prec = 3; break; + + default: pc.printf("Error flowUnitsNVM : Last case %d", nvmByte); + error = true; + } + + if(!error){ + i = ReadListIndexNVM(nvmByte); + + minScale = fMinFlowUnits[pumpType][i]; + maxScale = fMaxFlowUnits[pumpType][i];//float, max flow unit range + + lcd.nexSendFloat("p1right",maxScale, 2);//page 1 right text box + lcd.nexSendTxt("units", menuStringArray[list][i]); + } + + return(i); +} + +uint8_t ReadListIndexNVM(uint8_t nvm){ +/* + return the list item index +*/ + return(0x0f&nvm); +} + +float flowUnitPrec(int8_t precision){ +/* +precision = number of decimal places, 1, 2 & 3 +returns a float used to Inc/Dec flow units + + 100.0, + 139.6, + 5.815, + 22.01, + 366.9, + 528.2, + 22.01, + 0.367, + 12.9, + 55.0, +*/ + + float precisionVal; + + switch(precision){ + case -1: precisionVal = 10; break; + case 0: precisionVal = 1; break; + case 1: precisionVal = 0.1; break; + case 2: precisionVal = 0.01; break; + case 3: precisionVal = 0.001; break; + default:pc.printf("Error incDec : Last case %d",precision); + } + return(precisionVal); +} + +float low_pass_filterF(float x) { + + //https://www.eevblog.com/forum/beginners/averaging-or-smoothing-adc-values/ + + static float samples[ADC_SAMPLES]; + static int i = ZERO; + static float total = ZERO; + + /* Update the moving average */ + total += x - samples[i]; + samples[i] = x; + + /* Update the index */ + i = (i==(ADC_SAMPLES-1) ? 0 : i+1); + + return total/ADC_SAMPLES; +} + +uint8_t runModeNVM(uint8_t settingIndex){ + uint8_t task; +/* + Converts EEPROM setting to state machine case setting + + */ + switch(settingIndex) + { + case MANUAL: task = MANUAL_SET; break; + case ANALOGUE: task = ANALOGUE_SET; break; + case CONTACT: task = CONTACT_SET; break; + case FLUID_REC: task = FLUIDREC_SET; break; + case FLOW_CAL: task = FLOW_CAL_SET; break; + default: pc.printf("Error runModeNVM : Last case %d",settingIndex); + } + return(task); +} + +void dbgStates(uint8_t state){ + + #ifdef DEBUG_STATES + + static uint8_t lastState = INITIALISE; + + if(state != lastState){ + switch(state){ + case INITIALISE: pc.printf("\r\nSTATE = INITIALISE"); break; + case START: pc.printf("\r\nSTATE = START"); break; + case STOP: pc.printf("\r\nSTATE = STOP"); break; + case STOP_SCRN: pc.printf("\r\nSTATE = STOP_SCRN"); break; + case RUNNING: pc.printf("\r\nSTATE = RUNNING"); break; + case ANALOGUE_SET: pc.printf("\r\nSTATE = ANALOGUE_SET"); break; + case DOSE: pc.printf("\r\nSTATE = DOSE"); break; + case MANUAL_SET: pc.printf("\r\nSTATE = MANUAL_SET"); break; + case PROFIBUS: pc.printf("\r\nSTATE = PROFIBUS"); break; + case STALL: pc.printf("\r\nSTATE = STALL"); break; + case DEBUG: pc.printf("\r\nSTATE = DEBUG"); break; + case DIAGS: pc.printf("\r\nSTATE = DIAGS"); break; + case ALARM: pc.printf("\r\nSTATE = ALARM"); break; + case FAULT: pc.printf("\r\nSTATE = FAULT"); break; + case READ_KEYS: pc.printf("\r\nSTATE = READ_KEYS"); break; + case MANUAL_MODE: pc.printf("\r\nSTATE = MANUAL_MODE"); break; + case ANALOGUE_MODE: pc.printf("\r\nSTATE = ANALOGUE_MODE"); break; + case PROFIBUS_MODE: pc.printf("\r\nSTATE = PROFIBUS_MODE"); break; + case CONTACT_SET: pc.printf("\r\nSTATE = CONTACT_SET"); break; + case FLUIDREC_SET: pc.printf("\r\nSTATE = FLUIDREC_SET"); break; + case READ_NVM: pc.printf("\r\nSTATE = READ_NVM"); break; + case RESET_VARS: pc.printf("\r\nSTATE = RESET_VARS"); break; + case ANA_CAL: pc.printf("\r\nSTATE = ANA_CAL"); break; + case REMOTE_IN: pc.printf("\r\nSTATE = REMOTE_IN"); break; + + default: pc.printf("\r\nSTATE = UNDEFINED"); + } + + lastState = state; + } + + #endif +} + +uint8_t touchBtn(uint8_t nexPage, uint8_t nexBtn, uint8_t nexPushPop){ + /* + Function returns true if the button matches input parameters + */ + + uint8_t state = false; + + if((page == nexPage)&&(id == nexBtn)&&(pushPop == nexPushPop)) + state = true; + + return(state); +} + +uint8_t anaCal(void){ + + char* buffer; + float tmp; + bool drawCompleted = false; + uint8_t task = ANA_CAL; + + switch(calState){ + + case CAL1_SCRN: + if(scrnUpdate){ + scrnUpdate = false; + + lcd.nexSendTxt("title","4-20mA Calibration 1/4"); + lcd.nexSendTxt("info2","signal"); + lcd.nexSendTxt("sigName","Signal High"); + lcd.nexSendTxt("t1","mA"); + + if(manFlag){ + lcd.nexSendTxt("info1","Enter HIGH"); + lcd.nexSendTxt("info2","signal"); + lcd.nexSendTxt("info3","using +/- keys"); + } + else + { + lcd.nexSendTxt("info1","Apply HIGH"); + lcd.nexSendTxt("info2","signal"); + } + + lcd.nexSendTxt("info4","then press OK"); + lcd.nexSendTxt("info5",""); + } + + if(manFlag) + incDecControl(&nvm.mA_high, 2, LOW_CAL_MIN, HIGH_CAL_MAX, nvm.speedLimit);//2 decimal places for mA + else + nvm.mA_high = anaIn_mA(); + + lcd.nexSendFloat("anaVal", nvm.mA_high, 2); + tmp = nvm.mA_high;//make a copy of the data to be + + drawCompleted = drawCalGraph(X1,Y1,mapF(nvm.mA_high, I_0MA, I_21MA,X1,X2),Y2,DRAW);//wait for graph to complete + + if(okFlag && drawCompleted){ + drawCompleted = okFlag = false; + scrnUpdate = true; + calState++; + + if(writeNVMfloat(NVM_ANA_MA_CAL_HIGH, nvm.mA_high)) + lcd.nexSendTxt("info5","Data Varified"); + else + { + lcd.nexSendTxt("info5","Varify Failed"); + while(1); + } + + wait(1.0); + lcd.nexSendTxt("info5",""); + } + break; + + case CAL2_SCRN: + if(scrnUpdate){ + scrnUpdate = false; + + lcd.nexSendTxt("title","4-20mA Calibration 2/4"); + lcd.nexSendTxt("info1","Enter MAX"); + lcd.nexSendTxt("info2","flow signal"); + lcd.nexSendTxt("info3","using +/- keys"); + lcd.nexSendTxt("info4","then press OK"); + lcd.nexSendTxt("flowName","Flow High"); + lcd.nexSendTxt("t0","%"); + drawCalGraph(X1,Y1,mapF(nvm.mA_high, I_0MA, I_21MA,X1,X2),Y2,ERASE);//mA high, now erase the line read for next cal screen + } + + incDecControl(&nvm.flow_high, 1, 0.0, 100.0, nvm.speedLimit);//2 decimal places for mA + lcd.nexSendFloat("flowVal", nvm.flow_high, 1); + drawCompleted = drawCalGraph(X1,Y1,mapF(nvm.mA_high, I_0MA, I_21MA,X1,X2),mapF(nvm.flow_high, 0.0, 100.0,Y1,Y2),DRAW);//%, draw the line + + if(okFlag && drawCompleted){ + drawCompleted = okFlag = false; + scrnUpdate = true; + calState++; + + if(writeNVMfloat(NVM_ANA_FLOW_CAL_HIGH, nvm.flow_high)) + lcd.nexSendTxt("info5","Data Varified"); + else + { + lcd.nexSendTxt("info5","Varify Failed"); + while(1); + } + + wait(1.0); + lcd.nexSendTxt("info5",""); + } + break; + + case CAL3_SCRN: + if(scrnUpdate){ + scrnUpdate = false; + + lcd.nexSendTxt("title","4-20mA Calibration 3/4"); + lcd.nexSendTxt("info2","signal"); + lcd.nexSendTxt("sigName","Signal Low"); + + lcd.nexSendTxt("flowName","");//Clear these displays + lcd.nexSendTxt("flowVal",""); + lcd.nexSendTxt("t0",""); + + if(manFlag){ + lcd.nexSendTxt("info1","Enter LOW"); + lcd.nexSendTxt("info2","signal"); + lcd.nexSendTxt("info3","using +/- keys"); + } + else + { + lcd.nexSendTxt("info1","Apply LOW"); + lcd.nexSendTxt("info2","signal"); + } + + lcd.nexSendTxt("info4","then press OK"); + + drawCalGraph(X1,Y1,mapF(nvm.mA_high, I_0MA, I_21MA,X1,X2),mapF(nvm.flow_high, 0.0, 100.0,Y1,Y2),ERASE);//%, now erase the line read for next cal screen + } + + if(manFlag) + incDecControl(&nvm.mA_low, 2, LOW_CAL_MIN, HIGH_CAL_MAX, nvm.speedLimit);//2 decimal places for mA + else + nvm.mA_low = anaIn_mA(); + + lcd.nexSendFloat("anaVal", nvm.mA_low, 2); + drawCompleted = drawCalGraph(X1,Y1,mapF(nvm.mA_low, I_0MA, I_21MA,X1,X2),Y2,DRAW);//mA low, draw the line + + if(okFlag && drawCompleted){ + drawCompleted = okFlag = false; + scrnUpdate = true; + calState++; + + if(writeNVMfloat(NVM_ANA_MA_CAL_LOW, nvm.mA_low)) + lcd.nexSendTxt("info5","Data Varified"); + else + { + lcd.nexSendTxt("info5","Varify Failed"); + while(1); + } + + wait(1.0); + lcd.nexSendTxt("info5",""); + } + break; + + case CAL4_SCRN: + if(scrnUpdate){ + scrnUpdate = false; + + lcd.nexSendTxt("title","4-20mA Calibration 4/4"); + lcd.nexSendTxt("info1","Enter MIN"); + lcd.nexSendTxt("info2","flow signal"); + lcd.nexSendTxt("info3","using +/- keys"); + lcd.nexSendTxt("info4","then press OK"); + lcd.nexSendTxt("flowName","Flow Low"); + lcd.nexSendTxt("t0","%"); + drawCalGraph(X1,Y1,mapF(nvm.mA_low, I_0MA, I_21MA,X1,X2),Y2,ERASE);//mA low, now erase the line read for next cal screen + } + + incDecControl(&nvm.flow_low, 1, 0.0, 100.0, nvm.speedLimit);//2 decimal places for mA + lcd.nexSendFloat("flowVal", nvm.flow_low, 1); + drawCompleted = drawCalGraph(X1,Y1,mapF(nvm.mA_low, I_0MA, I_21MA,X1,X2),mapF(nvm.flow_low, 0.0, 100.0,Y1,Y2),DRAW);//%, draw the line + + if(okFlag && drawCompleted){ + drawCompleted = okFlag = false; + scrnUpdate = true; + calState++; + + if(writeNVMfloat(NVM_ANA_FLOW_CAL_LOW, nvm.flow_low)) + lcd.nexSendTxt("info5","Data Varified"); + else + { + lcd.nexSendTxt("info5","Varify Failed"); + while(1); + } + + wait(1.0); + lcd.nexSendTxt("info5",""); + } + break; + + case COMPLETE_SCRN: + if(scrnUpdate){ + scrnUpdate = false; + + calComplete = true; + + lcd.nexChgPage(PAGE_18_ANA_CAL_MODE); + //lcd.nexSendTxt("title","4 - 20mA Calibration completed"); + //lcd.nexSendTxt("info2","Analogue = Starts in 4-20mA mode"); + //lcd.nexSendTxt("info4","Manual = Starts in Manual mode"); + //lcd.nexSendTxt("btnRight","Manual"); + //lcd.nexSendTxt("btnLeft","Analogue"); + + stopLED = 0;//turn off the stop LED + drawCalGraph(X1,Y1,mapF(nvm.mA_low, I_0MA, I_21MA,X1,X2),mapF(nvm.flow_low, 0.0, 100.0,Y1,Y2),ERASE);//%, now erase the line read for next cal screen + } + break; + + } + + return(task); +} + +bool drawCalGraph(float x1, float y1, float x2, float y2,bool draw){ + + static uint16_t cntr = ZERO; + static float lastX1 = X1; + static float lastY1 = Y1; + static float lastX2 = X2; + static float lastY2 = Y2; + bool updated = false; + + if(draw){ + + if(cntr < DRAW_SPEED){ + cntr++; + updated = false; + } + else + { + cntr=ZERO; + + stopLED = !stopLED; + + lcd.nexDrawLine (lastX1, lastY1, lastX2, lastY2, WHITE);//Erase the previous red line calibration posotion + wait(0.001); + lcd.nexDrawLine (x1, y1, x2, y2, RED);//draw the new red line calibration position + + lastX1 = x1; + lastY1 = y1; + lastX2 = x2; + lastY2 = y2; + updated = true; + } + } + else + lcd.nexDrawLine (x1, y1, x2, y2, WHITE);//erase the new red line calibration position + + return(updated); +} + +uint8_t retLastStoredTask(uint8_t storedTask){ +/* + Returns to the last stored task +*/ + + uint8_t task; + + switch(storedTask){ + case STOP_SCRN: task = STOP_SCRN;//refresh stop screen + break; + + case ANALOGUE_SET: task = ANALOGUE_SET;//refresh + break; + + case MANUAL_SET: task = MANUAL_SET;//refresh + break; + default:; + } + return(task); +} + +void flowUnitInc(uint8_t *fUx, uint8_t *fUy, uint8_t *fUz){ + + if(*fUx > ZERO) + *fUx-=1; + else + *fUx = P8_MENU_ITEMS; + + if(*fUy > ZERO) + *fUy-=1; + else + *fUy = P8_MENU_ITEMS; + + if(*fUz > ZERO) + *fUz-=1; + else + *fUz = P8_MENU_ITEMS; + + lcd.nexSendTxt("top", menuStringArray[0][*fUx]); + lcd.nexSendTxt("data", menuStringArray[0][*fUy]); + lcd.nexSendTxt("bot", menuStringArray[0][*fUz]); + + nvm.flowUnits = uFlowUnitID[*fUy]; +} + +void flowUnitDec(uint8_t *fUx, uint8_t *fUy, uint8_t *fUz){ + + if(*fUx < P8_MENU_ITEMS) + *fUx+=1; + else + *fUx = ZERO; + + if(*fUy < P8_MENU_ITEMS) + *fUy+=1; + else + *fUy = ZERO; + + if(*fUz < P8_MENU_ITEMS) + *fUz+=1; + else + *fUz = ZERO; + + lcd.nexSendTxt("top", menuStringArray[0][*fUx]); + lcd.nexSendTxt("data", menuStringArray[0][*fUy]); + lcd.nexSendTxt("bot", menuStringArray[0][*fUz]); + + nvm.flowUnits = uFlowUnitID[*fUy]; +} + +void dispList(uint8_t i[3], uint8_t incDec, uint8_t stringList, const string sArray[2][10], uint8_t maxListStrings){ + + const uint8_t x=0,y=1,z=2; + + if(incDec){ + if(i[x] < maxListStrings) + i[x]+=1; + else + i[x] = ZERO; + + if(i[y] < maxListStrings) + i[y]+=1; + else + i[y] = ZERO; + + if(i[z] < maxListStrings) + i[z]+=1; + else + i[z] = ZERO; + }else{ + if(i[x] > ZERO) + i[x]-=1; + else + i[x] = maxListStrings; + + if(i[y] > ZERO) + i[y]-=1; + else + i[y] = maxListStrings; + + if(i[z] > ZERO) + i[z]-=1; + else + i[z] = maxListStrings; + } + + lcd.nexSetFontCol("data", RED); + lcd.nexSendTxt("top", sArray[stringList][i[x]]); + lcd.nexSendTxt("data", sArray[stringList][i[y]]); + lcd.nexSendTxt("bot", sArray[stringList][i[z]]); +} + + + +