Per Mårtensson 2 ay önce
ebeveyn
işleme
a5dc31ecd2

BIN
docs/DC_Load_LCD_wiring.pdf


BIN
docs/DC_Load_PCB_heatsink_spacing.pdf


BIN
docs/DC_Load_Rotary_Encoder_wiring.pdf


BIN
docs/DC_Load_Ver9_3_KiCad_Files.zip


BIN
docs/DC_Load_update_files.zip


BIN
docs/DC_Load_ver9_2_gerbers.zip


BIN
docs/DC_Load_ver9_3_gerber_files.zip


+ 1390 - 0
docs/Electronic_Load_software_V35.ino

@@ -0,0 +1,1390 @@
+//SCULLCOM HOBBY ELECTRONICS
+//ELECTRONIC DC LOAD PROJECT
+//Software Version 35 (4x5 Matrix Keypad Version - modified key layout)
+//14th April 2018
+
+#include <SPI.h>                              //include SPI library (Serial Peripheral Interface)
+#include <Wire.h>                             //include I2C library
+#include <LiquidCrystal_I2C.h>                // F Malpartida's NewLiquidCrystal library
+                                              // https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads/NewliquidCrystal_1.3.4.zip
+#include <math.h>                             //
+#include <Adafruit_MCP4725.h>                 //Adafruit DAC library  https://github.com/adafruit/Adafruit_MCP4725
+#include <MCP342x.h>                          //Steve Marple library avaiable from    https://github.com/stevemarple/MCP342x
+#include <MCP79410_Timer.h>                   //Scullcom Hobby Electronics library  http://www.scullcom.com/MCP79410Timer-master.zip
+#include <EEPROM.h>                           //include EEPROM library used for storing setup data
+
+#include <Keypad.h>                           //http://playground.arduino.cc/Code/Keypad
+
+const byte ROWS = 5;                          //five rows
+const byte COLS = 4;                          //four columns
+
+//define the symbols on the buttons of the keypads
+char hexaKeys[ROWS][COLS] = {
+  {'<','0','>','F'},
+  {'7','8','9','E'},
+  {'4','5','6','D'},
+  {'1','2','3','C'},
+  {'A','B','#','*'}
+};
+
+byte rowPins[ROWS] = {9, 10, 11, 12, 14}; //connect to the row pin outs of the keypad
+byte colPins[COLS] = {5, 6, 7, 8}; //connect to the column pin outs of the keypad
+
+//initialize an instance of class NewKeypad
+Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
+char customKey;
+
+char decimalPoint;                            //used to test for more than one press of * key (decimal point)
+
+Adafruit_MCP4725 dac;                         //constructor
+
+uint8_t address = 0x68;                       //0x68 is the default address for the MCP3426 device
+MCP342x adc = MCP342x(address);
+
+const byte MCP79410_ADDRESS = 0x6f;           //0x6f is the default address for the MCP79410 Real Time Clock IC
+MCP79410_Timer timer = MCP79410_Timer(MCP79410_ADDRESS);
+
+//Set the pins on the I2C chip used for LCD connections
+//ADDR,EN,R/W,RS,D4,D5,D6,D7
+LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7);    //0x27 is the default address of the LCD with I2C bus module
+
+const byte pinA = 2;                          //digital pin (also interrupt pin) for the A pin of the Rotary Encoder (changed to digital pin 2)
+const byte pinB = 4;                          //digital pin for the B pin of the Rotary Encoder
+
+const byte CursorPos = 17;                    //analog pin A3 used as a digital pin to set cursor position (rotary encoder push button)
+const byte LoadOnOff = 15;                    //analog pin A1 used as a digital pin to set Load ON/OFF
+
+const byte TriggerPulse = 16;                 //analog pin A2 used as a digital pin for trigger pulse input in transient mode
+
+const byte fan = 3;                           //digital pin 3 for fan control output (changed to Digital pin 3)
+const byte temperature = A6;                  //analog pin used for temperature output from LM35 (was A0 previously but changed)
+int temp;                                     //
+
+float BatteryLife = 0;                        //
+float BatteryLifePrevious = 0;                //
+float Seconds = 0;                            //time variable used in Battery Capacity Mode (BC)
+float SecondsLog = 0;                         //variable used for data logging of the time in seconds
+float BatteryCutoffVolts;                     //used to set battery discharge cut-off voltage
+float MaxBatteryCurrent = 1.0;                //maximum battery current allowed for Battery Capacity Testing
+
+int stopSeconds;                              //store for seconds when timer stopped
+
+int CP = 8;                                   //cursor start position
+
+boolean toggle = false;                       //used for toggle of Load On/Off button
+
+unsigned long controlVoltage = 0;             //used for DAC to control MOSFET
+
+long current = 0;                             //variable used by ADC for measuring the current
+long voltage = 0;                             //variable used by ADC for measuring the voltage
+
+float reading = 0;                            //variable for Rotary Encoder value divided by 1000
+
+float setCurrent = 0;                         //variable used for the set current of the load
+float setPower = 0;                           //variable used for the set power of the load
+float setResistance = 0;                      //variable used for the set resistance of the load
+float setCurrentCalibrationFactor = 0.980;    //calibration adjustment - set as required if needed (was 1.000)
+
+float displayCurrentCal = 0.000;              //calibration correction for LCD current display (was 0.040)
+int Load = 0;                                 //Load On/Off flag
+
+float setControlCurrent = 0;                  //variable used to set the temporary store for control current required
+
+int VoltsDecimalPlaces = 3;                   //number of decimal places used for Voltage display on LCD
+
+float ActualVoltage = 0;                      //variable used for Actual Voltage reading of Load
+float ActualCurrent = 0;                      //variable used for Actual Current reading of Load
+float ActualPower = 0;                        //variable used for Actual Power reading of Load
+
+float ResistorCutOff = 999;                   //maximum Resistor we want to deal with in software
+float BatteryCurrent;                         //
+float LoadCurrent;                            //
+
+int CurrentCutOff = EEPROM.read(0x00);
+int PowerCutOff = EEPROM.read(0x20);
+int tempCutOff = EEPROM.read(0x40);
+
+int setReading = 0;                           //
+
+int ControlVolts = 0;                         //used to set output current
+float OutputVoltage = 0;                      //
+
+String Mode ="  ";                            //used to identify which mode
+
+int modeSelected = 0;                         //Mode status flag
+
+int lastCount = 50;                           //
+volatile float encoderPosition = 0;           //
+volatile unsigned long factor= 0;             //number of steps to jump
+volatile unsigned long encoderMax = 999000;   //sets maximum Rotary Encoder value allowed CAN BE CHANGED AS REQUIRED (was 50000)
+
+float LiPoCutOffVoltage = 3.0;                //set cutoff voltage for LiPo battery
+float LiFeCutOffVoltage = 2.8;                //set cutoff voltage for LiFe battery
+float NiCdCutOffVoltage = 1.0;                //set cutoff voltage for NiCd battery
+float ZiZnCutOffVoltage = 1.0;                //set cutoff voltage for ZiZn battery
+float PbAcCutOffVoltage = 1.75;               //set cutoff voltage for PbAc battery
+String BatteryType ="    ";
+
+byte exitMode = 0;                           //used to exit battery selection menu and return to CC Mode
+
+char numbers[10];                            //keypad number entry - Plenty to store a representation of a float
+byte index = 0;
+int z = 1;                                   //was previously 0
+float x = 0;
+int y = 0;
+int r = 0;
+
+float LowCurrent = 0;               //the low current setting for transcient mode
+float HighCurrent = 0;              //the high current setting for transcient mode
+unsigned long transientPeriod;      //used to store pulse time period in transcient pulse mode
+unsigned long current_time;         //used to store the current time in microseconds
+unsigned long last_time;            //used to store the time of the last transient switch in micro seconds
+boolean transient_mode_status;      //used to maintain the state of the trascient mode (false = low current, true = high current)
+
+float transientList [10][2];        //array to store Transient List data
+int total_instructions;             //used in Transient List Mode
+int current_instruction;            //used in Transient List Mode
+
+//--------------------------------Interrupt Routine for Rotary Encoder------------------------
+void isr()
+{
+  static unsigned long lastInterruptTime = 0;
+  unsigned long interruptTime = millis();
+
+  if (interruptTime - lastInterruptTime > 5) {  //
+    if (digitalRead(pinB) == LOW)
+    {
+      encoderPosition = encoderPosition - factor;
+    }else{
+      encoderPosition = encoderPosition + factor;
+    }
+    encoderPosition = min(encoderMax, max(0, encoderPosition));  // sets maximum range of rotary encoder
+    lastInterruptTime = interruptTime;
+  }
+    }
+//---------------------------------Initial Set up---------------------------------------
+void setup() {
+  Serial.begin(9600);                                      //used for testing only
+ 
+  Wire.begin();                                            //join i2c bus (address optional for master)
+  Wire.setClock(400000L);                                  //sets bit rate to 400KHz
+
+  MCP342x::generalCallReset();                             //Reset devices
+  delay(1);                                                //MC342x needs 300us to settle, wait 1ms - (may not be required)
+
+  pinMode (pinA, INPUT);
+  pinMode (pinB, INPUT);
+
+  pinMode (CursorPos, INPUT_PULLUP);
+  pinMode (LoadOnOff, INPUT_PULLUP);
+ 
+  pinMode (TriggerPulse, INPUT_PULLUP);
+
+  pinMode (fan, OUTPUT);
+  TCCR2B = (TCCR2B & 0b11111000) | 1;                      //change PWM to above hearing (Kenneth Larvsen recommendation)
+  pinMode (temperature, INPUT);
+ 
+  analogReference(INTERNAL);                               //use Arduino internal reference for tempurature monitoring
+
+  attachInterrupt(digitalPinToInterrupt(pinA), isr, LOW);
+
+  dac.begin(0x61);                                         //the DAC I2C address with MCP4725 pin A0 set high
+  dac.setVoltage(0,false);                                 //reset DAC to zero for no output current set at Switch On
+
+  lcd.begin(20, 4);                                        //set up the LCD's number of columns and rows 
+  lcd.setBacklightPin(3,POSITIVE);                         // BL, BL_POL
+  lcd.setBacklight(HIGH);                                  //set LCD backlight on
+ 
+  lcd.clear();                                             //clear LCD display
+  lcd.setCursor(6,0);                                      //set LCD cursor to column 0, row 4
+  lcd.print("SCULLCOM");                                   //print SCULLCOM to display with 5 leading spaces (you can change to your own)
+  lcd.setCursor(1,1);                                      //set LCD cursor to column 0, row 1 (start of second line)
+  lcd.print("Hobby Electronics");                          //print Hobby Electronics to display (you can change to your own)
+  lcd.setCursor(1,2);
+  lcd.print("DC Electronic Load"); //
+  lcd.setCursor(0,3);
+  lcd.print("Ver. 35 (5x4 Keypad)"); //
+  delay(2000);                                             //3000 mSec delay for intro display
+  lcd.clear();                                             //clear dislay
+  setupLimits();
+  delay(3000);
+  lcd.clear();
+
+  last_time = 0;                                           //set the last_time to 0 at the start (Transicent Mode)
+  transient_mode_status = false;                           //set the initial transient mode status (false = low, true = high);
+  setCurrent = LowCurrent;                                 //first set the current to the low current value (Transicent Mode)
+ 
+  lcd.setCursor(8,0);
+  lcd.print("OFF");                                        //indicate that LOAD is off at start up
+  Current();                                               //sets initial mode to be CC (Constant Current) at Power Up
+  
+  customKey = customKeypad.getKey();
+  
+}
+
+//------------------------------------------Main Program Loop---------------------------------
+void loop() {
+
+ if(CurrentCutOff > 5){                                 //Test and go to user set limits if required
+    userSetUp();
+     }else{
+  
+  readKeypadInput();                                     //read Keypad entry
+  
+  if (digitalRead(LoadOnOff) == LOW) {
+    LoadSwitch();                                          //Load on/off
+  }
+  
+  transient();                                           //test for Transient Mode
+  
+  lcd.setCursor(18,3);                                   //sets display of Mode indicator at bottom right of LCD
+  lcd.print(Mode);                                       //display mode selected on LCD (CC, CP, CR or BC)
+
+  if(Mode != "TC" && Mode != "TP" && Mode != "TT" && Mode != "TL"){      //if NOT transient mode then Normal Operation
+    reading = encoderPosition/1000;                        //read input from rotary encoder 
+    maxConstantCurrentSetting();                           //set maxiumum Current allowed in Constant Current Mode (CC)
+    powerLevelCutOff();                                    //Check if Power Limit has been exceeded
+  
+    temperatureCutOff();                                   //check if Maximum Temperature is exceeded
+  
+    batteryCurrentLimitValue();                            //Battery Discharge Constant Current Limit Value in BC Mode
+    displayEncoderReading();                               //display rotary encoder input reading on LCD
+    lastCount = encoderPosition;                           //store rotary encoder current position
+    CursorPosition();                                      //check and change the cursor position if cursor button pressed
+  }else{
+    transientLoadToggle();                                  //Start Transient Mode
+  }
+    
+  readVoltageCurrent();                                  //routine for ADC's to read actual Voltage and Current
+  ActualReading();                                       //Display actual Voltage, Current readings and Actual Wattage
+  
+  dacControl();
+  dacControlVoltage();                                   //sets the drive voltage to control the MOSFET
+
+  batteryCapacity();                                     //test if Battery Capacity (BC) mode is selected - if so action
+  fanControl();                                          //call heatsink fan control
+  }
+}
+//------------------------------------------------Read Keypad Input-----------------------------------------------------
+void readKeypadInput (void) {
+  customKey = customKeypad.getKey();
+  
+//  if (customKey != NO_KEY){                             //only used for testing keypad (uncomment if required for testing keypad)
+// Serial.print("customKey = ");                          //only used for testing keypad (uncomment if required for testing keypad)
+// Serial.println(customKey);                             //only used for testing keypad (uncomment if required for testing keypad)
+//  }                                                     //only used for testing keypad (uncomment if required for testing keypad)
+
+if(customKey == 'E'){                                     //check for Load on/off
+  LoadSwitch();
+}
+
+  if(customKey == 'D'){                                   //check if Set-Up Mode Selected 
+  delay(200);
+  toggle = false;                                         //switch Load OFF
+  userSetUp();
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point text character reset
+}
+ 
+  if(customKey == 'C'){                                   //check if Transient Mode Selected
+  toggle = false;                                         //switch Load OFF
+  transientType();
+ 
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point text character reset
+  }
+               
+  if(customKey == 'A'){                                   //check if Constant Current button pressed
+  toggle = false;                                         //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");
+  Current();                                              //if selected go to Constant Current Selected routine
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point test character reset
+  }
+         
+  if(customKey == 'B'){                                   //check if Constant Power button pressed
+  toggle = false;                                         //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF"); 
+  Power();                                                //if selected go to Constant Power Selected routine
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point test character reset
+  }
+          
+  if(customKey == '#'){                                   //check if Constant Resistance button pressed  
+  toggle = false;                                         //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");  
+  Resistance();                                           //if selected go to Constant Resistance Selected routine
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point test character reset
+  }
+
+  if(customKey == '*'){                                   //check if Battery Capacity button pressed
+  dac.setVoltage(0,false);                                //Ensures Load is OFF - sets DAC output voltage to 0
+  toggle = false;                                         //switch Load OFF
+  batteryType();                                          //select battery type
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point test character reset
+
+    if (exitMode == 1){                                   //if NO battery type selected revert to CC Mode
+    lcd.setCursor(8,0);
+    lcd.print("OFF");
+    Current();                                            //if selected go to Constant Current Selected routine
+    encoderPosition = 0;                                  //reset encoder reading to zero
+    customKey = 'A';
+    }
+    else
+    {
+    lcd.setCursor(16,2);
+    lcd.print(BatteryType);                               //print battery type on LCD 
+    lcd.setCursor(8,0);
+    lcd.print("OFF");
+    timer.reset();                                        //reset timer
+    BatteryLifePrevious = 0;
+    CP = 9;                                               //set cursor position
+    BatteryCapacity();                                    //go to Battery Capacity Routine
+    }
+  }
+
+if (Mode != "BC"){
+
+  if(customKey >= '0' && customKey <= '9'){               //check for keypad number input
+       numbers[index++] = customKey;
+       numbers[index] = '\0';
+       lcd.setCursor(z,3);                                //                   
+       lcd.print(customKey);                              //show number input on LCD
+       z = z+1;
+     }
+  
+  if(customKey == '>'){                                   //check if decimal button key pressed
+      if (decimalPoint != ('>')){                         //test if decimal point entered twice - if so skip 
+      numbers[index++] = '.';
+      numbers[index] = '\0';
+      lcd.setCursor(z,3);
+      lcd.print(".");
+      z = z+1;
+      decimalPoint = ('>');                             //used to indicate decimal point has been input
+        }
+      }
+
+  if(customKey == '<'){                                 //clear input entry
+     index = 0;
+     z = 1;                                             //sets column position for LCD displayed character
+     lcd.setCursor(z,3);
+     lcd.print("     ");
+     numbers[index] = '\0';                             //
+     decimalPoint = (' ');                              //clear decimal point test character reset
+    }
+
+  if(customKey == 'F') {                                //use entered number
+    x = atof(numbers);     
+         reading = x;
+         encoderPosition = reading*1000;
+         index = 0;
+         numbers[index] = '\0';
+         z = 1;                                         //sets column position for LCD displayed character
+         lcd.setCursor(0,3);
+         lcd.print("        ");
+         decimalPoint = (' ');                          //clear decimal point test character reset
+          }
+    }
+  
+}
+
+//----------------------Limit Maximum Current Setting-----------------------------------------
+void maxConstantCurrentSetting (void) {
+  if (Mode == "CC" && reading > CurrentCutOff){           //Limit maximum Current Setting
+  reading = CurrentCutOff;
+  encoderPosition = (CurrentCutOff * 1000);               //keep encoder position value at maximum Current Limit
+  lcd.setCursor(0,3);
+  lcd.print("                    ");                      //20 spaces to clear last line of LCD 
+  }
+
+  if (Mode == "CP" && reading > PowerCutOff) {             //Limit maximum Current Setting
+        reading = PowerCutOff;
+        encoderPosition = (PowerCutOff * 1000);            //keep encoder position value at maximum Current Limit
+        lcd.setCursor(0,3);
+        lcd.print("                    ");                   //20 spaces to clear last line of LCD 
+    }
+
+   if (Mode == "CR" && reading > ResistorCutOff ) {             //Limit maximum Current Setting
+        reading = ResistorCutOff;
+        encoderPosition = (ResistorCutOff * 1000);            //keep encoder position value at maximum Current Limit
+        lcd.setCursor(0,3);
+        lcd.print("                    ");                   //20 spaces to clear last line of LCD 
+    }
+
+}
+
+//----------------------Power Level Cutoff Routine-------------------------------------------
+void powerLevelCutOff (void) {
+  if (ActualPower  > PowerCutOff){                        //Check if Power Limit has been exceed
+  reading = 0;
+  encoderPosition = 0; 
+  lcd.setCursor(0,3);
+  lcd.print("                    ");
+  lcd.setCursor(0,3);
+  lcd.print("Exceeded Power");
+  lcd.setCursor(8,0);
+  lcd.print("OFF");
+  toggle = false;                                         //switch Load Off
+  }
+}
+
+//----------------------Battery Constant Current Limit Value------------------------------------------
+void batteryCurrentLimitValue (void) {
+  if (Mode == "BC" && reading > MaxBatteryCurrent){
+  reading = MaxBatteryCurrent;
+  encoderPosition = (MaxBatteryCurrent*1000);            //keep encoder position value at 1000mA
+  }
+}
+
+//----------------------Display Rotary Encoder Input Reading on LCD---------------------------
+void displayEncoderReading (void) {
+
+    lcd.setCursor(8,2);                                      //start position of setting entry
+
+    if ( ( Mode == "CP" || Mode == "CR" ) && reading < 100 ) {
+        lcd.print("0");
+    }
+    
+    if (reading < 10) {                                      //add a leading zero to display if reading less than 10
+        lcd.print("0"); 
+    }
+
+    if ( Mode == "CP" || Mode == "CR" ) {
+        lcd.print (reading, 2);                              //show input reading from Rotary Encoder on LCD
+    } else {
+        lcd.print (reading, 3);
+    }
+    lcd.setCursor (CP, 2);                                   //sets cursor position
+    lcd.cursor();                                            //show cursor on LCD
+}
+
+//--------------------------Cursor Position-------------------------------------------------------
+//Change cursor the position routine
+void CursorPosition(void) {
+
+    // Defaults for two digits before decimal and 3 after decimal point
+    int unitPosition = 9;
+
+    //Power and Resistance modes can be 3 digit before decimal but only 2 decimals
+    if ( Mode == "CP" || Mode == "CR" ) {
+        unitPosition = 10;        
+    }
+
+    if (digitalRead(CursorPos) == LOW) {
+    
+        delay(200);                                          //simple key bounce delay  
+        CP = CP + 1;
+        if (CP == unitPosition + 1 ) {
+            CP = CP + 1;
+        }
+    }
+    
+    if (CP > 13)  { CP = unitPosition; }                     //No point in turning tens and hundreds
+    if (CP == unitPosition +4 ) { factor = 1; }
+    if (CP == unitPosition +3 ) { factor = 10; }
+    if (CP == unitPosition +2 ) { factor = 100; }
+    if (CP == unitPosition )    { factor = 1000; }
+}
+
+//---------------------------------------------Read Voltage and Current--------------------------------------------------------------
+void readVoltageCurrent (void) {
+  
+  MCP342x::Config status;
+// Initiate a conversion; convertAndRead() will wait until it can be read
+  adc.convertAndRead(MCP342x::channel1, MCP342x::oneShot,
+           MCP342x::resolution16, MCP342x::gain1,                         //"gain1" means we have select the input amp of the ADC to x1
+           1000000, voltage, status);
+  
+// Initiate a conversion; convertAndRead() will wait until it can be read
+  adc.convertAndRead(MCP342x::channel2, MCP342x::oneShot,
+           MCP342x::resolution16, MCP342x::gain4,                         //"gain4" means we have select the input amp of the ADC to x4
+           1000000, current, status);
+  
+}
+
+//-----------------------------------Calculate Actual Voltage and Current and display on LCD-----------------------------------------
+void ActualReading(void) {
+
+  ActualCurrent = (((current*2.048)/32767) * 2.5);        //calculate load current
+  currentDisplayCal();                                    //LCD display current calibration correction
+  ActualVoltage = (((voltage*2.048)/32767) * 50.4);       //calculate load voltage upto 100v (was 50)
+  ActualPower = ActualVoltage*ActualCurrent;
+
+  if (ActualPower <=0){
+    ActualPower = 0;
+  }
+
+ if (ActualVoltage <=0.0){                              //added to prevent negative readings on LCD due to error
+  ActualVoltage = 0.0;
+ }
+ if (ActualCurrent <= 0.0){                             //added to prevent negative readings on LCD due to error
+  ActualCurrent = 0.0;
+ }
+ 
+ lcd.setCursor(0,1);
+    
+    if ( ActualCurrent < 10.0 ) {
+        lcd.print(ActualCurrent,3);
+    } else {
+        lcd.print(ActualCurrent,2);
+    }
+    
+    lcd.print("A");
+    lcd.print(" ");
+    
+    if (ActualVoltage < 10.0) {
+        lcd.print(ActualVoltage, 3);
+    } else {
+        lcd.print(ActualVoltage, 2);
+    }    
+
+    lcd.print("V");
+    lcd.print(" ");
+     
+    if (ActualPower < 100 ) {
+        lcd.print(ActualPower,2);
+    } else {
+        lcd.print(ActualPower,1);
+    }
+    lcd.print("W");
+    lcd.print(" ");
+}
+
+//-----------------------DAC Control Voltage for Mosfet---------------------------------------
+void dacControlVoltage (void) {
+  if (Mode == "CC"){
+  setCurrent = reading*1000;                                //set current is equal to input value in Amps
+  setReading = setCurrent;                                  //show the set current reading being used
+  setControlCurrent = setCurrent * setCurrentCalibrationFactor;
+  controlVoltage = setControlCurrent; 
+  }
+
+  if (Mode == "CP"){
+  setPower = reading*1000;                                  //in Watts
+  setReading = setPower;
+  setCurrent = setPower/ActualVoltage;
+  setControlCurrent = setCurrent * setCurrentCalibrationFactor;
+  controlVoltage = setControlCurrent;                       //
+  }
+
+  if (Mode == "CR"){
+  setResistance = reading;                                  //in ohms
+  setReading = setResistance;
+  setCurrent = (ActualVoltage)/setResistance*1000;
+  setControlCurrent = setCurrent * setCurrentCalibrationFactor;
+  controlVoltage = setControlCurrent; 
+  }
+
+if (Mode == "TC" || Mode == "TP" || Mode == "TT" || Mode == "TL"){                            //Transient Modes
+  setControlCurrent = (setCurrent * 1000) * setCurrentCalibrationFactor;
+  controlVoltage = setControlCurrent; 
+  }
+
+}
+
+//-------------------------------------Battery Capacity Discharge Routine----------------------------------------------------
+void batteryCapacity (void) {
+  if (Mode == "BC"){
+    
+    setCurrent = reading*1000;                             //set current is equal to input value in Amps
+    setReading = setCurrent;                               //show the set current reading being used
+    setControlCurrent = setCurrent * setCurrentCalibrationFactor;
+    controlVoltage = setControlCurrent;
+
+    lcd.setCursor(0,3);
+    lcd.print (timer.getTime());                           //start clock and print clock time
+
+    Seconds = timer.getTotalSeconds();                     //get totals seconds
+  
+    LoadCurrent = ActualCurrent;                           //if timer still running use present Actual Current reading
+    if (timer.status() == 2){                              //if timer is halted then use last Actual Current reading before timer stopped
+      LoadCurrent = BatteryCurrent;
+      }
+ 
+    BatteryLife = (LoadCurrent*1000)*(Seconds/3600);       //calculate battery capacity in mAh
+    lcd.setCursor(9,3);
+    BatteryLife = round(BatteryLife);
+
+    if(BatteryLife >= BatteryLifePrevious){                //only update LCD (mAh) if BatteryLife has increased
+  
+      if (BatteryLife < 10) {                              //add a 3 leading zero to display if reading less than 10
+      lcd.print("000");
+      }
+
+      if (BatteryLife >= 10 && BatteryLife <100){          //add a 2 leading zero to display
+      lcd.print("00");  
+      }
+
+      if (BatteryLife >= 100 && BatteryLife <1000){        //add a 1 leading zero to display
+      lcd.print("0"); 
+      }
+  
+    lcd.print(BatteryLife,0);
+    lcd.setCursor(13,3);
+    lcd.print("mAh");
+    BatteryLifePrevious = BatteryLife;                      //update displayed battery capacity on LCD
+    } 
+  }
+
+
+  if (Mode == "BC" && ActualVoltage <= BatteryCutoffVolts){ //stops clock if battery reached cutoff level and switch load off
+
+  BatteryCurrent = ActualCurrent;
+  dac.setVoltage(0,false);                                  //reset DAC to zero for no output current set at switch on                                             
+  toggle = false;                                           //Load is toggled OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");                                         //indicate that LOAD is off at start up
+  timer.stop();
+  }
+
+      if (Mode == "BC" && Load == 1){                       //Routine used for data logging in Battery Capacity Mode
+          if (Seconds != SecondsLog){                       //only send serial data if time has changed
+            SecondsLog = Seconds;
+            Serial.print (SecondsLog);                    //sends serial data of time in seconds
+            Serial.print (",");                             //sends a comma as delimiter for logged data
+            Serial.println (ActualVoltage);                   //sends serial data of Voltage reading         
+              }
+          }
+
+}
+
+//--------------------------------------------------Fan Control----------------------------------------------------------
+void fanControl (void) {
+  temp = analogRead(temperature);
+  temp = temp * 0.107421875;                                // convert to Celsius
+  
+  if (temp >= 40){                                        //if temperature 40 degree C or above turn fan on.
+    digitalWrite(fan, HIGH); 
+  }  else {
+    digitalWrite(fan, LOW);                               //otherwise turn fan turned off
+  }
+  
+  lcd.setCursor(16,0);
+  lcd.print(temp);                                        //display temperature of heatsink on LCD
+  lcd.print((char)0xDF);
+  lcd.print("C");
+
+}
+
+  
+//-----------------------Toggle Current Load ON or OFF------------------------------
+void LoadSwitch(void) {
+  
+  delay(200);                                              //simple key bounce delay 
+ 
+    if(toggle)
+    {
+      lcd.setCursor(8,0);
+      lcd.print("OFF");
+      current_instruction = 0;                            //reset current instruction for Transient List Mode to zero
+      last_time = 0;                                      //reset last time to zero
+      transientPeriod = 0;                                //reset transient period time to zero
+      setCurrent = 0;                                     //reset setCurrent to zero
+      toggle = !toggle;
+      Load = 0;        
+    }
+    else
+    {
+      lcd.setCursor(8,0);
+      lcd.print("ON ");
+      lcd.setCursor(0,3);
+      lcd.print("                    ");                 //clear bottom line of LCD
+      toggle = !toggle;
+      Load = 1;
+    }
+}
+
+//-----------------------Select Constant Current LCD set up--------------------------------
+void Current(void) {
+  Mode = ("CC");
+  lcd.setCursor(0,0);
+  lcd.print("DC LOAD");  
+  lcd.setCursor(0,2);
+  lcd.print("                ");
+  lcd.setCursor(0,2);
+  lcd.print("Set I = ");
+  lcd.setCursor(16,2);
+  lcd.print("    ");
+  lcd.setCursor(14,2);
+  lcd.print("A");
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("                    ");                    //20 spaces so as to allow for Load ON/OFF to still show
+  CP = 9;                                               //sets cursor starting position to units.
+}
+
+//----------------------Select Constant Power LCD set up------------------------------------
+void Power(void) {
+  Mode = ("CP");
+  lcd.setCursor(0,0);
+  lcd.print("DC LOAD");
+  lcd.setCursor(0,2);
+  lcd.print("                ");
+  lcd.setCursor(0,2);
+  lcd.print("Set W = ");
+  lcd.setCursor(16,2);
+  lcd.print("    ");
+  lcd.setCursor(14,2);
+  lcd.print("W");
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("                    ");                    //20 spaces so as to allow for Load ON/OFF to still show
+  CP = 10;                                               //sets cursor starting position to units.
+}
+
+//----------------------- Select Constant Resistance LCD set up---------------------------------------
+void Resistance(void) {
+  Mode = ("CR");
+  lcd.setCursor(0,0);
+  lcd.print("DC LOAD");  
+  lcd.setCursor(0,2);
+  lcd.print("                ");
+  lcd.setCursor(0,2);
+  lcd.print("Set R = ");
+  lcd.setCursor(16,2);
+  lcd.print("    ");
+  lcd.setCursor(14,2);
+  lcd.print((char)0xF4);
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("                    ");                    //20 spaces so as to allow for Load ON/OFF to still show
+  CP = 10;                                               //sets cursor starting position to units.
+}
+
+//----------------------- Select Battery Capacity Testing LCD set up---------------------------------------
+void BatteryCapacity(void) {
+  Mode = ("BC");
+  lcd.setCursor(0,0);
+  lcd.print("BATTERY");
+  lcd.setCursor(0,2);
+  lcd.print("                ");
+  lcd.setCursor(0,2);
+  lcd.print("Set I = ");
+  lcd.setCursor(14,2);
+  lcd.print("A");
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("                    ");                    //20 spaces so as to allow for Load ON/OFF to still show
+}
+
+//----------------------Battery Type Selection Routine------------------------------------------------
+void batteryType (void) {
+  exitMode = 0;                                         //reset EXIT mode
+  lcd.noCursor();                                       //switch Cursor OFF for this menu               
+  lcd.clear();
+  lcd.setCursor(0,0);
+  lcd.print("Select Battery Type");  
+  lcd.setCursor(0,1);
+  lcd.print("1=LiPo/Li-Ion 2=LiFe");
+  lcd.setCursor(0,2);
+  lcd.print("3=NiCd/NiMH   4=ZiZn");
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("5=Set Voltage 6=Exit");                    //20 spaces so as to allow for Load ON/OFF to still show
+
+  customKey = customKeypad.waitForKey();                //stop everything till the user press a key.
+
+  if (customKey == '1'){
+  BatteryCutoffVolts = LiPoCutOffVoltage;
+  BatteryType = ("LiPo");
+    }
+
+  if (customKey == '2'){
+  BatteryCutoffVolts = LiFeCutOffVoltage;
+  BatteryType = ("LiFe");
+    }
+
+  if (customKey == '3'){
+  BatteryCutoffVolts = NiCdCutOffVoltage;
+  BatteryType = ("NiCd");  
+    }
+
+  if (customKey == '4'){
+  BatteryCutoffVolts = ZiZnCutOffVoltage;
+  BatteryType = ("ZiZn"); 
+    }
+
+  if (customKey == '5'){ 
+  BatteryType = ("SetV");
+    }
+
+  if (customKey == '6'){                                  //Exit selection screen
+  exitMode = 1;
+    }
+
+  if (customKey == '7' || customKey == '8' || customKey == '9' || customKey == '0' || customKey == 'A' || customKey == 'B' || customKey == 'C' || customKey == 'D' || customKey == '*' || customKey == '#' || customKey == 'E' || customKey == 'F' || customKey == '<' || customKey == '>' ){
+  batteryType();                                                      //ignore other keys
+    }
+
+  if(BatteryType == "SetV" && exitMode != 1){
+  setBatteryCutOff();
+    }
+
+  batteryTypeSelected();                                    //briefly display battery type selected and discharge cut off voltage
+
+  lcd.clear();
+
+}
+
+//--------------------------Set DAC Voltage--------------------------------------------
+void dacControl (void) {
+  if (!toggle){
+  dac.setVoltage(0,false);                                 //set DAC output voltage to 0 if Load Off selected
+    if(Mode == "BC" && ActualVoltage >= BatteryCutoffVolts && timer.status() == 1){
+    timer.stop();
+    }
+  
+  }else{
+  //Serial.println("Control Voltage");                    //used for testing only
+  //Serial.println(controlVoltage);                       //used for testing only
+  dac.setVoltage(controlVoltage,false);                   //set DAC output voltage for Range selected
+    if(Mode == "BC" && ActualVoltage >= BatteryCutoffVolts && timer.status() != 1){
+    timer.start();
+    }
+  }
+}
+
+//--------------------------Battery Selected Information--------------------------------------------
+void batteryTypeSelected (void) {
+  if (exitMode !=1){                                      //if battery selection was EXIT then skip this routine
+  lcd.clear();
+  lcd.setCursor(2,0);
+  lcd.print("Battery Selected");
+  lcd.setCursor(8,1);
+  lcd.print(BatteryType);                                 //display battery type selected
+  lcd.setCursor(2,2);
+  lcd.print("Discharge Cutoff");
+  lcd.setCursor(6,3);
+  lcd.print(BatteryCutoffVolts);                          //display battery discharge cut off voltage
+  lcd.print(" volts");                                    
+  delay(3000);
+  }
+}
+
+//--------------------------Set Battery Cut-Off Voltage--------------------------------------------
+void setBatteryCutOff (void) {
+
+  lcd.clear();
+  lcd.setCursor(4,0);
+  lcd.print("Enter Battery");
+  lcd.setCursor(3,1);
+  lcd.print("Cut-Off Voltage");
+  y = 8;
+  z = 8;
+  r = 2;
+
+  inputValue();
+  BatteryCutoffVolts = x;
+
+  lcd.clear();
+}
+
+//------------------------Key input used for Battery Cut-Off and Transient Mode------------------------
+void inputValue (void){
+
+ while(customKey != 'F'){               //check if enter pressed (was previously #)
+  
+  customKey = customKeypad.getKey();
+  if(customKey >= '0' && customKey <= '9'){               //check for keypad number input
+       numbers[index++] = customKey;
+       numbers[index] = '\0';
+       lcd.setCursor(z,r);                              
+       lcd.print(customKey);                              //show number input on LCD
+       z = z+1;
+     }
+  
+  if(customKey == '>'){                                   //Decimal point
+      if (decimalPoint != ('>')){                         //test if decimal point entered twice - if so ski
+      numbers[index++] = '.';
+      numbers[index] = '\0';
+      lcd.setCursor(z,r);
+      lcd.print(".");
+      z = z+1;
+      decimalPoint = ('>');                               //used to indicate decimal point has been input
+        }
+      }
+
+ if(customKey == '<'){                                    //clear entry
+    index = 0;
+    z = y;
+    lcd.setCursor(y,r);
+    lcd.print("     ");
+    numbers[index] = '\0';                                //
+    decimalPoint = (' ');                                 //clear decimal point test character reset
+  }
+
+ }
+ 
+  if(customKey == 'F') {                                  //enter value 
+    x = atof(numbers);     
+    index = 0;
+    numbers[index] = '\0';
+    decimalPoint = (' ');                                 //clear decimal point test character reset
+  }
+}
+
+//----------------------------------------Transient Mode--------------------------------------------
+void transientMode (void) {
+
+if(Mode != "TL"){
+
+  y = 11;
+  z = 11;
+  
+  lcd.noCursor();                                       //switch Cursor OFF for this menu               
+  lcd.clear();
+  lcd.setCursor(3,0);
+  lcd.print("Transient Mode");  
+  lcd.setCursor(0,1);
+  lcd.print("Set Low  I=");
+  lcd.setCursor(19,1);
+  lcd.print("A");
+  r = 1;
+  inputValue();
+  
+  if(x >= CurrentCutOff){
+    LowCurrent = CurrentCutOff;
+  }else{
+    LowCurrent = x;
+  }
+  lcd.setCursor(11,r);
+  lcd.print(LowCurrent,3);
+  
+  customKey = '0';
+
+  z = 11;
+
+  lcd.setCursor(0,2);
+  lcd.print("Set High I=");
+  lcd.setCursor(19,2);
+  lcd.print("A");
+  r = 2;
+  inputValue();
+  if(x >= CurrentCutOff){
+    HighCurrent = CurrentCutOff;
+  }else{
+    HighCurrent = x;
+  }
+  lcd.setCursor(11,r);
+  lcd.print(HighCurrent,3);
+
+  customKey = '0';
+
+  if(Mode == "TC" || Mode == "TP"){
+  z = 11;
+
+  lcd.setCursor(0,3);
+  lcd.print("Set Time  = ");
+  lcd.setCursor(16,3);
+  lcd.print("mSec");
+  r = 3;
+  inputValue();
+  transientPeriod = x;
+  lcd.setCursor(11,r);
+  lcd.print(transientPeriod);
+  }else{
+  lcd.setCursor(0,3);
+  lcd.print("                    ");
+  }
+
+  lcd.clear();
+
+  toggle = false;                                           //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");                                         //print on display OFF
+    }else{  
+  transientListSetup();
+  lcd.clear();
+ 
+  toggle = false;                                           //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");                                         //print on display OFF
+  }
+}
+
+//----------------------------------------Transient Type Selection--------------------------------------------
+void transientType (void) {
+  toggle = false;                                         //switch Load OFF
+  exitMode = 0;                                           //reset EXIT mode
+  lcd.noCursor();                                         //switch Cursor OFF for this menu               
+  lcd.clear();
+  lcd.setCursor(3,0);
+  lcd.print("Transient Mode");  
+  lcd.setCursor(0,1);
+  lcd.print("1 = Continuous");
+  lcd.setCursor(0,2);
+  lcd.print("2 = Toggle");
+  lcd.setCursor(11,2);                                    //
+  lcd.print("3 = Pulse");                                 //
+  lcd.setCursor(0,3);                                     //
+  lcd.print("4 = List");                                  //
+  lcd.setCursor(11,3);                                    //
+  lcd.print("5 = Exit");                                  //
+
+  customKey = customKeypad.waitForKey();                  //stop everything till the user press a key.
+
+  if (customKey == '1'){
+  Mode = ("TC"); 
+    }
+
+  if (customKey == '2'){
+   Mode = ("TT");
+    }
+
+  if (customKey == '3'){
+  Mode = ("TP");  
+    }
+
+  if (customKey == '4'){
+  Mode = ("TL");  
+    }
+
+  if (customKey == '5'){                                  //Exit selection screen
+  exitMode = 1;
+    }
+
+  if (customKey == '6' || customKey == '7' || customKey == '8' || customKey == '9' || customKey == '0' || customKey == 'A' || customKey == 'B' || customKey == 'C' || customKey == 'D' || customKey == '*' || customKey == '#' || customKey == 'E' || customKey == 'F' || customKey == '<' || customKey == '>' ){
+  transientType();                                                      //ignore other keys
+  
+    }
+lcd.clear();
+
+if (exitMode == 1){                                       //if NO Transient Mode type selected revert to CC Mode
+    lcd.setCursor(8,0);
+    lcd.print("OFF");
+    Current();                                            //if selected go to Constant Current Selected routine
+    encoderPosition = 0;                                  //reset encoder reading to zero
+    customKey = 'A';
+      }else{
+    transientMode();
+      }
+ }
+ 
+//----------------------------------------Transient--------------------------------------------
+void transient (void) {
+  
+  if(Mode == "TC" || Mode == "TP" || Mode == "TT" || Mode == "TL"){
+  lcd.noCursor();                                         //switch Cursor OFF for this menu 
+  lcd.setCursor(0,0);
+  lcd.print("DC LOAD");
+  
+  if(Mode != "TL"){
+  lcd.setCursor(0,2);
+  lcd.print("Lo=");
+  lcd.setCursor(3,2);
+  lcd.print(LowCurrent,3);
+  lcd.setCursor(8,2);
+  lcd.print("A");
+  lcd.setCursor(11,2);
+  lcd.print("Hi=");
+  lcd.setCursor(14,2);                                    //
+  lcd.print(HighCurrent,3);
+  lcd.setCursor(19,2);
+  lcd.print("A");
+  }else{
+    delay(1);
+  }
+
+
+  if(Mode == "TC" || Mode == "TP" || Mode == "TL"){
+  lcd.setCursor(0,3);                                     //
+  lcd.print("Time = ");
+  lcd.setCursor(7,3);
+  lcd.print(transientPeriod);
+  lcd.setCursor(12,3);                                    //
+  lcd.print("mSecs");
+    }else{
+     lcd.setCursor(0,3);
+     lcd.print("  ");
+    }
+  }
+delay(1);
+}
+
+//-------------------------------------Transcient List Setup-------------------------------------------
+void transientListSetup(){
+
+  lcd.noCursor();                                                 
+  lcd.clear();
+  lcd.setCursor(0,0);
+  lcd.print("Setup Transient List");
+  lcd.setCursor(0,1);
+  lcd.print("Enter Number in List");
+  lcd.setCursor(0,2);
+  lcd.print("(between 2 to 10 max"); 
+  y = 0;
+  z = 0;
+  r = 3;
+  inputValue();
+  total_instructions = int(x-1);
+  customKey = '0';
+  lcd.clear();
+  
+    for(int i=0; i<=(total_instructions); i++){
+      lcd.setCursor(0,0);
+      lcd.print("Set Current ");
+      lcd.print(i+1);
+      lcd.setCursor(16,1);
+      lcd.print("A");
+      y = 0;
+      z = 0;
+      r = 1;
+      inputValue();            //get the users input value
+      transientList[i][0] = x; //store the users entered value in the transient list 
+      customKey = '0';
+      lcd.setCursor(0,2);
+      lcd.print("Set Time ");
+      lcd.print(i+1);
+      lcd.setCursor(16,3);
+      lcd.print("mSec");
+      y = 0;
+      z = 0;
+      r = 3;
+      inputValue();            //get the users input value
+      transientList[i][1] = x; //store the users entered value in the transient list
+      customKey = '0';
+      lcd.clear();   
+  }
+  current_instruction = 0;      //start at first instrution
+}
+
+//-------------------------------------Transcient Load Toggel-------------------------------------------
+void transientLoadToggle(){
+
+  if(Mode == "TC"){
+  current_time = micros();                              //get the current time in micro seconds()
+  if (last_time == 0){
+    last_time = current_time;
+  } else {
+    switch (transient_mode_status){
+      case (false):
+          // we are in the low current setting
+          if ((current_time - last_time) >= (transientPeriod * 1000.0)){
+             transientSwitch(LowCurrent, true);  
+          }
+        break;
+      case (true):
+          // we are in the high current setting 
+          if ((current_time - last_time) >= (transientPeriod * 1000.0)){
+            transientSwitch(HighCurrent, true);            
+          }
+        break; 
+      } 
+     }
+    }
+
+
+  if(Mode == "TP"){
+    current_time = micros();                            //get the current time in micro seconds()
+    if (last_time == 0){
+        last_time = current_time;
+        transientSwitch(LowCurrent, true);
+    }
+    if (digitalRead(TriggerPulse) == LOW){
+      // a trigger pluse is received
+      // set to the high current
+      transientSwitch(HighCurrent, true); 
+    } else {
+        if ((current_time - last_time) >= (transientPeriod * 1000.0)){
+            transientSwitch(LowCurrent, true);            
+        }
+      }  
+  }
+
+
+ if(Mode == "TT"){          // this function will toggle between high and low current when the trigger pin is taken low
+  if (digitalRead(TriggerPulse) == LOW){
+    switch (transient_mode_status){
+      case (false):
+        transientSwitch(LowCurrent, true);
+        delay(200);         //added to prevent key bounce when transient button used (date of addition 31-03-2018)
+        break;
+      case (true):
+        transientSwitch(HighCurrent, true);
+        delay(200);         //added to prevent key bounce when transient button used (date of addition 31-03-2018)   
+        break;
+      }
+    }
+  }
+
+
+if(Mode == "TL"){
+  if (Load == 1){                                                 //Only perform Transient List if Load is ON
+   current_time = micros();                                       //get the current time in micro seconds()
+    if (last_time == 0){
+      last_time = current_time;
+      transientPeriod = transientList[current_instruction][1];    //Time data for LCD display
+      transientSwitch(transientList[current_instruction][0], false);
+    }
+    if((current_time - last_time) >= transientList[current_instruction][1] * 1000){     //move to next list instruction
+        current_instruction++;
+        if(current_instruction > total_instructions){
+          current_instruction = 0;
+        }
+      transientPeriod = transientList[current_instruction][1];   //Time data for LCD display
+      transientSwitch(transientList[current_instruction][0], false);
+      }
+    }
+  }
+
+}
+
+//-------------------------------------Transcient Switch-------------------------------------------
+void transientSwitch(float current_setting, boolean toggle_status){
+  if (toggle_status){
+  transient_mode_status = !transient_mode_status;
+  }
+  setCurrent = current_setting;
+  //Serial.print("set current = ");                     //used for testing only
+  //Serial.println(setCurrent);                         //used for testing only
+  last_time = current_time;
+}
+
+//-------------------------------------User set up for limits-------------------------------------------------
+void userSetUp (void) {
+  y = 14;
+  z = 14;
+  
+  lcd.noCursor();                                       //switch Cursor OFF for this menu               
+  lcd.clear();
+  lcd.setCursor(4,0);
+  lcd.print("User Set-Up");
+  lcd.setCursor(0,1);
+  lcd.print("Current Limit=");
+  lcd.setCursor(19,1);
+  lcd.print("A");
+  r = 1;
+  inputValue();
+  CurrentCutOff = x;
+  EEPROM.write(0x00, CurrentCutOff);
+  lcd.setCursor(14,r);
+  lcd.print(CurrentCutOff);
+  
+  customKey = '0';
+
+  z = 14;
+
+  lcd.setCursor(0,2);
+  lcd.print("Power Limit  =");
+  lcd.setCursor(19,2);
+  lcd.print("W");
+  r = 2;
+  inputValue();
+  PowerCutOff = x;
+  EEPROM.write(0x20, PowerCutOff);              //
+  lcd.setCursor(14,r);
+  lcd.print(PowerCutOff);
+
+  customKey = '0';
+
+  z = 14;
+
+  lcd.setCursor(0,3);
+  lcd.print("Temp. Limit  =");
+  lcd.setCursor(18,3);
+  lcd.print((char)0xDF);
+  lcd.print("C");
+  r = 3;
+  inputValue();
+  tempCutOff = x;
+  EEPROM.write(0x40, tempCutOff);
+  lcd.setCursor(14,r);
+  lcd.print(tempCutOff);
+
+    lcd.clear();
+
+    lcd.setCursor(8,0);
+    lcd.print("OFF");
+    Current();                                            //if selected go to Constant Current Selected routine
+    encoderPosition = 0;                                  //reset encoder reading to zero
+    customKey = 'A';
+}
+
+//------------------------------------------High Temperature Cut-Off--------------------------------------------------------------
+void temperatureCutOff (void){
+  if (temp >= tempCutOff){                                 //if Maximum temperature is exceeded
+  reading = 0;
+  encoderPosition = 0; 
+  lcd.setCursor(0,3);
+  lcd.print("                    ");
+  lcd.setCursor(0,3);
+  lcd.print("Over Temperature");
+  lcd.setCursor(8,0);
+  lcd.print("OFF");
+  toggle = false;                                         //switch Load Off
+  }
+}
+
+//-----------------------------------------Current Read Calibration for LCD Display --------------------------------------------
+void currentDisplayCal (void){
+
+  if(ActualCurrent <= 0){
+    ActualCurrent = 0;
+  }else if(Load == 0){
+    ActualCurrent = 0;
+  }else{
+  ActualCurrent = ActualCurrent + displayCurrentCal;
+  }
+
+/*  if (ActualCurrent <= 0.5)
+    {
+    ActualCurrent = (ActualCurrent +(displayCurrentCal * 3));
+    }
+    else if (ActualCurrent >= 0.5 && ActualCurrent <1.0)
+    {
+    ActualCurrent = (ActualCurrent + (displayCurrentCal * 2));
+    }
+    else if (ActualCurrent >= 1.0 && ActualCurrent <= 1.4)
+    {
+    ActualCurrent = (ActualCurrent + (displayCurrentCal));
+    }
+    else 
+    {
+    ActualCurrent = ActualCurrent;
+    }
+*/
+}
+  
+//-----------------------------Show limits Stored Data for Current, Power and Temp-----------------------------
+  void setupLimits (void){
+  lcd.clear();
+  lcd.setCursor(1,0);
+  lcd.print("Maximum Limits Set");
+  lcd.setCursor(0,1);
+  lcd.print("Current Limit=");
+  lcd.setCursor(17,1);
+  lcd.print("A");
+  lcd.setCursor(15,1);
+  CurrentCutOff = EEPROM.read(0x00);
+  lcd.print(CurrentCutOff);
+
+  lcd.setCursor(0,2);
+  lcd.print("Power Limit  =");
+  lcd.setCursor(17,2);
+  lcd.print("W");
+  lcd.setCursor(15,2);
+  PowerCutOff = EEPROM.read(0x20);
+  lcd.print(PowerCutOff);
+
+  lcd.setCursor(0,3);
+  lcd.print("Temp. Limit  =");
+  lcd.setCursor(17,3);
+  lcd.print((char)0xDF);
+  lcd.print("C");
+  tempCutOff = EEPROM.read(0x40);
+  lcd.setCursor(15,3);
+  lcd.print(tempCutOff);
+  }
+  
+  //---------------------------------------------------------------------------------------------------------

+ 1375 - 0
docs/Electronic_Load_software_V35B.ino

@@ -0,0 +1,1375 @@
+//SCULLCOM HOBBY ELECTRONICS
+//ELECTRONIC DC LOAD PROJECT
+//Software Version 35B (4x4 Matrix Keypad Version)
+//14th April 2018
+
+#include <SPI.h>                              //include SPI library (Serial Peripheral Interface)
+#include <Wire.h>                             //include I2C library
+#include <LiquidCrystal_I2C.h>                // F Malpartida's NewLiquidCrystal library
+                                              // https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads/NewliquidCrystal_1.3.4.zip
+#include <math.h>                             //
+#include <Adafruit_MCP4725.h>                 //Adafruit DAC library  https://github.com/adafruit/Adafruit_MCP4725
+#include <MCP342x.h>                          //Steve Marple library avaiable from    https://github.com/stevemarple/MCP342x
+#include <MCP79410_Timer.h>                   //Scullcom Hobby Electronics library  http://www.scullcom.com/MCP79410Timer-master.zip
+#include <EEPROM.h>                           //include EEPROM library used for storing setup data
+
+#include <Keypad.h>                           //http://playground.arduino.cc/Code/Keypad
+
+const byte ROWS = 4;                          //four rows
+const byte COLS = 4;                          //four columns
+
+//define the symbols on the buttons of the keypads
+char hexaKeys[ROWS][COLS] = {
+  {'1','2','3','A'},
+  {'4','5','6','B'},
+  {'7','8','9','C'},
+  {'*','0','#','D'}
+};
+
+byte rowPins[ROWS] = {5, 6, 7, 8}; //connect to the row pin outs of the keypad
+byte colPins[COLS] = {9, 10, 11, 12}; //connect to the column pin outs of the keypad
+
+//initialize an instance of class NewKeypad
+Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
+char customKey;
+
+char decimalPoint;                            //used to test for more than one press of * key (decimal point)
+
+Adafruit_MCP4725 dac;                         //constructor
+
+uint8_t address = 0x68;                       //0x68 is the default address for the MCP3426 device
+MCP342x adc = MCP342x(address);
+
+const byte MCP79410_ADDRESS = 0x6f;           //0x6f is the default address for the MCP79410 Real Time Clock IC
+MCP79410_Timer timer = MCP79410_Timer(MCP79410_ADDRESS);
+
+//Set the pins on the I2C chip used for LCD connections
+//ADDR,EN,R/W,RS,D4,D5,D6,D7
+LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7);    //0x27 is the default address of the LCD with I2C bus module
+
+const byte pinA = 2;                          //digital pin (also interrupt pin) for the A pin of the Rotary Encoder (changed to digital pin 2)
+const byte pinB = 4;                          //digital pin for the B pin of the Rotary Encoder
+
+const byte CursorPos = 17;                    //analog pin A3 used as a digital pin to set cursor position (rotary encoder push button)
+const byte LoadOnOff = 15;                    //analog pin A1 used as a digital pin to set Load ON/OFF
+
+const byte TriggerPulse = 16;                 //analog pin A2 used as a digital pin for trigger pulse input in transient mode
+
+const byte fan = 3;                           //digital pin 3 for fan control output (changed to Digital pin 3)
+const byte temperature = A6;                  //analog pin used for temperature output from LM35 (was A0 previously but changed)
+int temp;                                     //
+
+float BatteryLife = 0;                        //
+float BatteryLifePrevious = 0;                //
+float Seconds = 0;                            //time variable used in Battery Capacity Mode (BC)
+float SecondsLog = 0;                         //variable used for data logging of the time in seconds
+float BatteryCutoffVolts;                     //used to set battery discharge cut-off voltage
+float MaxBatteryCurrent = 1.0;                //maximum battery current allowed for Battery Capacity Testing
+
+int stopSeconds;                              //store for seconds when timer stopped
+
+int CP = 8;                                   //cursor start position
+
+boolean toggle = false;                       //used for toggle of Load On/Off button
+
+unsigned long controlVoltage = 0;             //used for DAC to control MOSFET
+
+long current = 0;                             //variable used by ADC for measuring the current
+long voltage = 0;                             //variable used by ADC for measuring the voltage
+
+float reading = 0;                            //variable for Rotary Encoder value divided by 1000
+
+float setCurrent = 0;                         //variable used for the set current of the load
+float setPower = 0;                           //variable used for the set power of the load
+float setResistance = 0;                      //variable used for the set resistance of the load
+float setCurrentCalibrationFactor = 0.980;    //calibration adjustment - set as required if needed (was 1.000)
+
+float displayCurrentCal = 0.040;              //calibration correction for LCD current display
+int Load = 0;                                 //Load On/Off flag
+
+float setControlCurrent = 0;                  //variable used to set the temporary store for control current required
+
+int VoltsDecimalPlaces = 3;                   //number of decimal places used for Voltage display on LCD
+
+float ActualVoltage = 0;                      //variable used for Actual Voltage reading of Load
+float ActualCurrent = 0;                      //variable used for Actual Current reading of Load
+float ActualPower = 0;                        //variable used for Actual Power reading of Load
+
+float ResistorCutOff = 999;                   //maximum Resistor we want to deal with in software
+float BatteryCurrent;                         //
+float LoadCurrent;                            //
+
+//int CurrentCutOff = eeprom_read_dword(0x00);
+int CurrentCutOff = EEPROM.read(0x00);
+int PowerCutOff = EEPROM.read(0x20);
+int tempCutOff = EEPROM.read(0x40);
+
+int setReading = 0;                           //
+
+int ControlVolts = 0;                         //used to set output current
+float OutputVoltage = 0;                      //
+
+String Mode ="  ";                            //used to identify which mode
+
+int modeSelected = 0;                         //Mode status flag
+
+int lastCount = 50;                           //
+volatile float encoderPosition = 0;           //
+volatile unsigned long factor= 0;             //number of steps to jump
+volatile unsigned long encoderMax = 999000;   //sets maximum Rotary Encoder value allowed CAN BE CHANGED AS REQUIRED (was 50000)
+
+float LiPoCutOffVoltage = 3.0;                //set cutoff voltage for LiPo battery
+float LiFeCutOffVoltage = 2.8;                //set cutoff voltage for LiFe battery
+float NiCdCutOffVoltage = 1.0;                //set cutoff voltage for NiCd battery
+float ZiZnCutOffVoltage = 1.0;                //set cutoff voltage for ZiZn battery
+float PbAcCutOffVoltage = 1.75;               //set cutoff voltage for PbAc battery
+String BatteryType ="    ";
+
+byte exitMode = 0;                           //used to exit battery selection menu and return to CC Mode
+
+char numbers[10];                            //keypad number entry - Plenty to store a representation of a float
+byte index = 0;
+int z = 1;                                   //was 0
+float x = 0;
+int y = 0;
+int r = 0;
+
+float LowCurrent = 0;               //the low current setting for transcient mode
+float HighCurrent = 0;              //the high current setting for transcient mode
+unsigned long transientPeriod;      //used to store pulse time period in transcient pulse mode
+unsigned long current_time;         //used to store the current time in microseconds
+unsigned long last_time;            //used to store the time of the last transient switch in micro seconds
+boolean transient_mode_status;      //used to maintain the state of the trascient mode (false = low current, true = high current)
+
+float transientList [10][2];        //array to store Transient List data
+int total_instructions;             //used in Transient List Mode
+int current_instruction;            //used in Transient List Mode
+
+//--------------------------------Interrupt Routine for Rotary Encoder------------------------
+void isr()
+{
+  static unsigned long lastInterruptTime = 0;
+  unsigned long interruptTime = millis();
+
+  if (interruptTime - lastInterruptTime > 5) {  //
+    if (digitalRead(pinB) == LOW)
+    {
+      encoderPosition = encoderPosition - factor;
+    }else{
+      encoderPosition = encoderPosition + factor;
+    }
+    encoderPosition = min(encoderMax, max(0, encoderPosition));  // sets maximum range of rotary encoder
+    lastInterruptTime = interruptTime;
+  }
+    }
+//---------------------------------Initial Set up---------------------------------------
+void setup() {
+  Serial.begin(9600);                                      //used for testing only
+ 
+  Wire.begin();                                            //join i2c bus (address optional for master)
+  Wire.setClock(400000L);                                  //sets bit rate to 400KHz
+
+  MCP342x::generalCallReset();                             //Reset devices
+  delay(1);                                                //MC342x needs 300us to settle, wait 1ms - (may not be required)
+
+  pinMode (pinA, INPUT);
+  pinMode (pinB, INPUT);
+
+  pinMode (CursorPos, INPUT_PULLUP);
+  pinMode (LoadOnOff, INPUT_PULLUP);
+ 
+  pinMode (TriggerPulse, INPUT_PULLUP);
+
+  pinMode (fan, OUTPUT);
+  TCCR2B = (TCCR2B & 0b11111000) | 1;                      //change PWM to above hearing (Kenneth Larvsen recommendation)
+  pinMode (temperature, INPUT);
+ 
+  analogReference(INTERNAL);                               //use Arduino internal reference for tempurature monitoring
+
+  attachInterrupt(digitalPinToInterrupt(pinA), isr, LOW);
+
+  dac.begin(0x61);                                         //the DAC I2C address with MCP4725 pin A0 set high
+  dac.setVoltage(0,false);                                 //reset DAC to zero for no output current set at Switch On
+
+  lcd.begin(20, 4);                                        //set up the LCD's number of columns and rows 
+  lcd.setBacklightPin(3,POSITIVE);                         // BL, BL_POL
+  lcd.setBacklight(HIGH);                                  //set LCD backlight on
+ 
+  lcd.clear();                                             //clear LCD display
+  lcd.setCursor(6,0);                                      //set LCD cursor to column 0, row 4
+  lcd.print("SCULLCOM");                                   //print SCULLCOM to display with 5 leading spaces (you can change to your own)
+  lcd.setCursor(1,1);                                      //set LCD cursor to column 0, row 1 (start of second line)
+  lcd.print("Hobby Electronics");                          //print Hobby Electronics to display (you can change to your own)
+  lcd.setCursor(1,2);
+  lcd.print("DC Electronic Load"); //
+  lcd.setCursor(0,3);
+  lcd.print("Ver. 35B(4x4 Keypad)"); //
+  delay(2000);                                             //3000 mSec delay for intro display
+  lcd.clear();                                             //clear dislay
+  setupLimits();
+  delay(3000);
+  lcd.clear();
+
+  last_time = 0;                                           //set the last_time to 0 at the start (Transicent Mode)
+  transient_mode_status = false;                           //set the initial transient mode status (false = low, true = high);
+  setCurrent = LowCurrent;                                 //first set the current to the low current value (Transicent Mode)
+ 
+  lcd.setCursor(8,0);
+  lcd.print("OFF");                                        //indicate that LOAD is off at start up
+  Current();                                               //sets initial mode to be CC (Constant Current) at Power Up
+  
+  customKey = customKeypad.getKey();
+  
+}
+
+//------------------------------------------Main Program Loop---------------------------------
+void loop() {
+
+ if(CurrentCutOff > 5){                                 //Test and go to user set limits if required
+    userSetUp();
+     }else{
+  
+  readKeypadInput();                                     //read Keypad entry
+  
+  if (digitalRead(LoadOnOff) == LOW) {
+    LoadSwitch();                                          //Load on/off
+  }
+  
+  transient();                                           //test for Transient Mode
+  
+  lcd.setCursor(18,3);                                   //sets display of Mode indicator at bottom right of LCD
+  lcd.print(Mode);                                       //display mode selected on LCD (CC, CP, CR or BC)
+
+  if(Mode != "TC" && Mode != "TP" && Mode != "TT" && Mode != "TL"){      //if NOT transient mode then Normal Operation
+    reading = encoderPosition/1000;                        //read input from rotary encoder 
+    maxConstantCurrentSetting();                           //set maxiumum Current allowed in Constant Current Mode (CC)
+    powerLevelCutOff();                                    //Check if Power Limit has been exceeded
+  
+    temperatureCutOff();                                   //check if Maximum Temperature is exceeded
+  
+    batteryCurrentLimitValue();                            //Battery Discharge Constant Current Limit Value in BC Mode
+    displayEncoderReading();                               //display rotary encoder input reading on LCD
+    lastCount = encoderPosition;                           //store rotary encoder current position
+    CursorPosition();                                      //check and change the cursor position if cursor button pressed
+  }else{
+    transientLoadToggle();                                  //Start Transient Mode
+  }
+    
+  readVoltageCurrent();                                  //routine for ADC's to read actual Voltage and Current
+  ActualReading();                                       //Display actual Voltage, Current readings and Actual Wattage
+  
+  dacControl();
+  dacControlVoltage();                                   //sets the drive voltage to control the MOSFET
+
+  batteryCapacity();                                     //test if Battery Capacity (BC) mode is selected - if so action
+  fanControl();                                          //call heatsink fan control
+  }
+}
+//------------------------------------------------Read Keypad Input-----------------------------------------------------
+void readKeypadInput (void) {
+  customKey = customKeypad.getKey();
+  
+ //if (customKey != NO_KEY){                             //only used for testing keypad
+ //Serial.print("customKey = ");                          //only used for testing keypad
+ //Serial.println(customKey);                             //only used for testing keypad
+ //}                                                     //only used for testing keypad
+
+if(customKey == '*' && digitalRead(CursorPos) == LOW){    //check if Set-Up Mode Selected (press * and Cursor Button together)
+  delay(200);
+  toggle = false;                                         //switch Load OFF
+  userSetUp();
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point text character reset
+}
+
+if(customKey == 'A' && digitalRead(CursorPos) == LOW){    //check if Transient Mode Selected (press A and Cursor Button together)
+  toggle = false;                                         //switch Load OFF
+  transientType();
+ 
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point text character reset
+  }
+               
+  if(customKey == 'A'){                                   //check if Constant Current button pressed
+  toggle = false;                                         //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");
+  Current();                                              //if selected go to Constant Current Selected routine
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point test character reset
+  }
+         
+  if(customKey == 'B'){                                   //check if Constant Power button pressed
+  toggle = false;                                         //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF"); 
+  Power();                                                //if selected go to Constant Power Selected routine
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point test character reset
+  }
+          
+  if(customKey == 'C'){                                   //check if Constant Resistance button pressed  
+  toggle = false;                                         //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");  
+  Resistance();                                           //if selected go to Constant Resistance Selected routine
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point test character reset
+  }
+
+  if(customKey == 'D'){                                   //check if Battery Capacity button pressed
+  dac.setVoltage(0,false);                                //Ensures Load is OFF - sets DAC output voltage to 0
+  toggle = false;                                         //switch Load OFF
+  batteryType();                                          //select battery type
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point test character reset
+
+    if (exitMode == 1){                                   //if NO battery type selected revert to CC Mode
+    lcd.setCursor(8,0);
+    lcd.print("OFF");
+    Current();                                            //if selected go to Constant Current Selected routine
+    encoderPosition = 0;                                  //reset encoder reading to zero
+    customKey = 'A';
+    }
+    else
+    {
+    lcd.setCursor(16,2);
+    lcd.print(BatteryType);                               //print battery type on LCD 
+    lcd.setCursor(8,0);
+    lcd.print("OFF");
+    timer.reset();                                        //reset timer
+    BatteryLifePrevious = 0;
+    CP = 9;                                               //set cursor position
+    BatteryCapacity();                                    //go to Battery Capacity Routine
+    }
+  }
+
+if (Mode != "BC"){
+
+  if(customKey >= '0' && customKey <= '9'){               //check for keypad number input
+       numbers[index++] = customKey;
+       numbers[index] = '\0';
+       lcd.setCursor(z,3);                              
+       lcd.print(customKey);                              //show number input on LCD
+       z = z+1;
+     }
+  
+  if(customKey == '*'){                                   //check if decimal button key pressed
+      if (decimalPoint != ('*')){                         //test if decimal point entered twice - if so skip 
+      numbers[index++] = '.';
+      numbers[index] = '\0';
+      lcd.setCursor(z,3);
+      lcd.print(".");
+      z = z+1;
+      decimalPoint = ('*');                             //used to indicate decimal point has been input
+        }
+      }
+
+
+  if(customKey == '#') {                                //check if Load ON/OFF button pressed
+    x = atof(numbers);     
+         reading = x;
+         encoderPosition = reading*1000;
+         index = 0;
+         numbers[index] = '\0';
+         z = 1;                                             //sets column position for LCD displayed character
+         lcd.setCursor(0,3);
+         lcd.print("        ");
+         decimalPoint = (' ');                          //clear decimal point test character reset
+          }
+    }
+  
+}
+
+//----------------------Limit Maximum Current Setting-----------------------------------------
+void maxConstantCurrentSetting (void) {
+  if (Mode == "CC" && reading > CurrentCutOff){           //Limit maximum Current Setting
+  reading = CurrentCutOff;
+  encoderPosition = (CurrentCutOff * 1000);               //keep encoder position value at maximum Current Limit
+  lcd.setCursor(0,3);
+  lcd.print("                    ");                      //20 spaces to clear last line of LCD 
+  }
+
+  if (Mode == "CP" && reading > PowerCutOff) {             //Limit maximum Current Setting
+        reading = PowerCutOff;
+        encoderPosition = (PowerCutOff * 1000);            //keep encoder position value at maximum Current Limit
+        lcd.setCursor(0,3);
+        lcd.print("                    ");                   //20 spaces to clear last line of LCD 
+    }
+
+   if (Mode == "CR" && reading > ResistorCutOff ) {             //Limit maximum Current Setting
+        reading = ResistorCutOff;
+        encoderPosition = (ResistorCutOff * 1000);            //keep encoder position value at maximum Current Limit
+        lcd.setCursor(0,3);
+        lcd.print("                    ");                   //20 spaces to clear last line of LCD 
+    }
+
+}
+
+//----------------------Power Level Cutoff Routine-------------------------------------------
+void powerLevelCutOff (void) {
+  if (ActualPower  > PowerCutOff){                        //Check if Power Limit has been exceed
+  reading = 0;
+  encoderPosition = 0; 
+  lcd.setCursor(0,3);
+  lcd.print("                    ");
+  lcd.setCursor(0,3);
+  lcd.print("Exceeded Power");
+  lcd.setCursor(8,0);
+  lcd.print("OFF");
+  toggle = false;                                         //switch Load Off
+  }
+}
+
+//----------------------Battery Constant Current Limit Value------------------------------------------
+void batteryCurrentLimitValue (void) {
+  if (Mode == "BC" && reading > MaxBatteryCurrent){
+  reading = MaxBatteryCurrent;
+  encoderPosition = (MaxBatteryCurrent*1000);            //keep encoder position value at 1000mA
+  }
+}
+
+//----------------------Display Rotary Encoder Input Reading on LCD---------------------------
+void displayEncoderReading (void) {
+
+    lcd.setCursor(8,2);                                      //start position of setting entry
+
+    if ( ( Mode == "CP" || Mode == "CR" ) && reading < 100 ) {
+        lcd.print("0");
+    }
+    
+    if (reading < 10) {                                      //add a leading zero to display if reading less than 10
+        lcd.print("0"); 
+    }
+
+    if ( Mode == "CP" || Mode == "CR" ) {
+        lcd.print (reading, 2);                              //show input reading from Rotary Encoder on LCD
+    } else {
+        lcd.print (reading, 3);
+    }
+    lcd.setCursor (CP, 2);                                   //sets cursor position
+    lcd.cursor();                                            //show cursor on LCD
+}
+
+//--------------------------Cursor Position-------------------------------------------------------
+//Change cursor the position routine
+void CursorPosition(void) {
+
+    // Defaults for two digits before decimal and 3 after decimal point
+    int unitPosition = 9;
+
+    //Power and Resistance modes can be 3 digit before decimal but only 2 decimals
+    if ( Mode == "CP" || Mode == "CR" ) {
+        unitPosition = 10;        
+    }
+
+    if (digitalRead(CursorPos) == LOW) {
+    
+        delay(200);                                          //simple key bounce delay  
+        CP = CP + 1;
+        if (CP == unitPosition + 1 ) {
+            CP = CP + 1;
+        }
+    }
+    
+    if (CP > 13)  { CP = unitPosition; }                     //No point in turning tens and hundreds
+    if (CP == unitPosition +4 ) { factor = 1; }
+    if (CP == unitPosition +3 ) { factor = 10; }
+    if (CP == unitPosition +2 ) { factor = 100; }
+    if (CP == unitPosition )    { factor = 1000; }
+}
+
+//---------------------------------------------Read Voltage and Current--------------------------------------------------------------
+void readVoltageCurrent (void) {
+  
+  MCP342x::Config status;
+// Initiate a conversion; convertAndRead() will wait until it can be read
+  adc.convertAndRead(MCP342x::channel1, MCP342x::oneShot,
+           MCP342x::resolution16, MCP342x::gain1,                         //"gain1" means we have select the input amp of the ADC to x1
+           1000000, voltage, status);
+  
+// Initiate a conversion; convertAndRead() will wait until it can be read
+  adc.convertAndRead(MCP342x::channel2, MCP342x::oneShot,
+           MCP342x::resolution16, MCP342x::gain4,                         //"gain4" means we have select the input amp of the ADC to x4
+           1000000, current, status);
+  
+}
+
+//-----------------------------------Calculate Actual Voltage and Current and display on LCD-----------------------------------------
+void ActualReading(void) {
+
+  ActualCurrent = (((current*2.048)/32767) * 2.5);        //calculate load current
+  currentDisplayCal();                                    //LCD display current calibration correction
+  ActualVoltage = (((voltage*2.048)/32767) * 50.4);       //calculate load voltage upto 100v (was 50)
+  ActualPower = ActualVoltage*ActualCurrent;
+
+  if (ActualPower <=0){
+    ActualPower = 0;
+  }
+
+ if (ActualVoltage <=0.0){                              //added to prevent negative readings on LCD due to error
+  ActualVoltage = 0.0;
+ }
+ if (ActualCurrent <= 0.0){                             //added to prevent negative readings on LCD due to error
+  ActualCurrent = 0.0;
+ }
+ 
+ lcd.setCursor(0,1);
+    
+    if ( ActualCurrent < 10.0 ) {
+        lcd.print(ActualCurrent,3);
+    } else {
+        lcd.print(ActualCurrent,2);
+    }
+    
+    lcd.print("A");
+    lcd.print(" ");
+    
+    if (ActualVoltage < 10.0) {
+        lcd.print(ActualVoltage, 3);
+    } else {
+        lcd.print(ActualVoltage, 2);
+    }    
+
+    lcd.print("V");
+    lcd.print(" ");
+     
+    if (ActualPower < 100 ) {
+        lcd.print(ActualPower,2);
+    } else {
+        lcd.print(ActualPower,1);
+    }
+    lcd.print("W");
+    lcd.print(" ");
+}
+
+//-----------------------DAC Control Voltage for Mosfet---------------------------------------
+void dacControlVoltage (void) {
+  if (Mode == "CC"){
+  setCurrent = reading*1000;                                //set current is equal to input value in Amps
+  setReading = setCurrent;                                  //show the set current reading being used
+  setControlCurrent = setCurrent * setCurrentCalibrationFactor;
+  controlVoltage = setControlCurrent; 
+  }
+
+  if (Mode == "CP"){
+  setPower = reading*1000;                                  //in Watts
+  setReading = setPower;
+  setCurrent = setPower/ActualVoltage;
+  setControlCurrent = setCurrent * setCurrentCalibrationFactor;
+  controlVoltage = setControlCurrent;                       //
+  }
+
+  if (Mode == "CR"){
+  setResistance = reading;                                  //in ohms
+  setReading = setResistance;
+  setCurrent = (ActualVoltage)/setResistance*1000;
+  setControlCurrent = setCurrent * setCurrentCalibrationFactor;
+  controlVoltage = setControlCurrent; 
+  }
+
+if (Mode == "TC" || Mode == "TP" || Mode == "TT" || Mode == "TL"){                            //Transient Modes
+  setControlCurrent = (setCurrent * 1000) * setCurrentCalibrationFactor;
+  controlVoltage = setControlCurrent; 
+  }
+
+}
+
+//-------------------------------------Battery Capacity Discharge Routine----------------------------------------------------
+void batteryCapacity (void) {
+  if (Mode == "BC"){
+    
+    setCurrent = reading*1000;                             //set current is equal to input value in Amps
+    setReading = setCurrent;                               //show the set current reading being used
+    setControlCurrent = setCurrent * setCurrentCalibrationFactor;
+    controlVoltage = setControlCurrent;
+
+    lcd.setCursor(0,3);
+    lcd.print (timer.getTime());                           //start clock and print clock time
+
+    Seconds = timer.getTotalSeconds();                     //get totals seconds
+  
+    LoadCurrent = ActualCurrent;                           //if timer still running use present Actual Current reading
+    if (timer.status() == 2){                              //if timer is halted then use last Actual Current reading before timer stopped
+      LoadCurrent = BatteryCurrent;
+      }
+ 
+    BatteryLife = (LoadCurrent*1000)*(Seconds/3600);       //calculate battery capacity in mAh
+    lcd.setCursor(9,3);
+    BatteryLife = round(BatteryLife);
+
+    if(BatteryLife >= BatteryLifePrevious){                //only update LCD (mAh) if BatteryLife has increased
+  
+      if (BatteryLife < 10) {                              //add a 3 leading zero to display if reading less than 10
+      lcd.print("000");
+      }
+
+      if (BatteryLife >= 10 && BatteryLife <100){          //add a 2 leading zero to display
+      lcd.print("00");  
+      }
+
+      if (BatteryLife >= 100 && BatteryLife <1000){        //add a 1 leading zero to display
+      lcd.print("0"); 
+      }
+  
+    lcd.print(BatteryLife,0);
+    lcd.setCursor(13,3);
+    lcd.print("mAh");
+    BatteryLifePrevious = BatteryLife;                      //update displayed battery capacity on LCD
+    } 
+  }
+
+
+  if (Mode == "BC" && ActualVoltage <= BatteryCutoffVolts){ //stops clock if battery reached cutoff level and switch load off
+
+  BatteryCurrent = ActualCurrent;
+  dac.setVoltage(0,false);                                  //reset DAC to zero for no output current set at switch on                                             
+  toggle = false;                                           //Load is toggled OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");                                         //indicate that LOAD is off at start up
+  timer.stop();
+  }
+      if (Mode == "BC" && Load == 1){                       //Routine used for data logging in Battery Capacity Mode
+          if (Seconds != SecondsLog){                       //only send serial data if time has changed
+            SecondsLog = Seconds;
+            Serial.print (SecondsLog);                    //sends serial data of time in seconds
+            Serial.print (",");                             //sends a comma as delimiter for logged data
+            Serial.println (ActualVoltage);                   //sends serial data of Voltage reading         
+              }
+          }
+  
+}
+
+//--------------------------------------------------Fan Control----------------------------------------------------------
+void fanControl (void) {
+  temp = analogRead(temperature);
+  temp = temp * 0.107421875;                                // convert to Celsius
+  
+  if (temp >= 40){                                        //if temperature 40 degree C or above turn fan on.
+    digitalWrite(fan, HIGH); 
+  }  else {
+    digitalWrite(fan, LOW);                               //otherwise turn fan turned off
+  }
+  
+  lcd.setCursor(16,0);
+  lcd.print(temp);                                        //display temperature of heatsink on LCD
+  lcd.print((char)0xDF);
+  lcd.print("C");
+
+}
+
+  
+//-----------------------Toggle Current Load ON or OFF------------------------------
+void LoadSwitch(void) {
+  
+  delay(200);                                              //simple key bounce delay 
+ 
+    if(toggle)
+    {
+      lcd.setCursor(8,0);
+      lcd.print("OFF");
+      current_instruction = 0;                            //reset current instruction for Transient List Mode to zero
+      last_time = 0;                                      //reset last time to zero
+      transientPeriod = 0;                                //reset transient period time to zero
+      setCurrent = 0;                                     //reset setCurrent to zero
+      toggle = !toggle;
+      Load = 0;        
+    }
+    else
+    {
+      lcd.setCursor(8,0);
+      lcd.print("ON ");
+      lcd.setCursor(0,3);
+      lcd.print("                    ");                 //clear bottom line of LCD
+      toggle = !toggle;
+      Load = 1;
+    }
+}
+
+//-----------------------Select Constant Current LCD set up--------------------------------
+void Current(void) {
+  Mode = ("CC");
+  lcd.setCursor(0,0);
+  lcd.print("DC LOAD");  
+  lcd.setCursor(0,2);
+  lcd.print("                ");
+  lcd.setCursor(0,2);
+  lcd.print("Set I = ");
+  lcd.setCursor(16,2);
+  lcd.print("    ");
+  lcd.setCursor(14,2);
+  lcd.print("A");
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("                    ");                    //20 spaces so as to allow for Load ON/OFF to still show
+  CP = 9;                                               //sets cursor starting position to units.
+}
+
+//----------------------Select Constant Power LCD set up------------------------------------
+void Power(void) {
+  Mode = ("CP");
+  lcd.setCursor(0,0);
+  lcd.print("DC LOAD");
+  lcd.setCursor(0,2);
+  lcd.print("                ");
+  lcd.setCursor(0,2);
+  lcd.print("Set W = ");
+  lcd.setCursor(16,2);
+  lcd.print("    ");
+  lcd.setCursor(14,2);
+  lcd.print("W");
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("                    ");                    //20 spaces so as to allow for Load ON/OFF to still show
+  CP = 10;                                               //sets cursor starting position to units.
+}
+
+//----------------------- Select Constant Resistance LCD set up---------------------------------------
+void Resistance(void) {
+  Mode = ("CR");
+  lcd.setCursor(0,0);
+  lcd.print("DC LOAD");  
+  lcd.setCursor(0,2);
+  lcd.print("                ");
+  lcd.setCursor(0,2);
+  lcd.print("Set R = ");
+  lcd.setCursor(16,2);
+  lcd.print("    ");
+  lcd.setCursor(14,2);
+  lcd.print((char)0xF4);
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("                    ");                    //20 spaces so as to allow for Load ON/OFF to still show
+  CP = 10;                                               //sets cursor starting position to units.
+}
+
+//----------------------- Select Battery Capacity Testing LCD set up---------------------------------------
+void BatteryCapacity(void) {
+  Mode = ("BC");
+  lcd.setCursor(0,0);
+  lcd.print("BATTERY");
+  lcd.setCursor(0,2);
+  lcd.print("                ");
+  lcd.setCursor(0,2);
+  lcd.print("Set I = ");
+  lcd.setCursor(14,2);
+  lcd.print("A");
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("                    ");                    //20 spaces so as to allow for Load ON/OFF to still show
+}
+
+//----------------------Battery Type Selection Routine------------------------------------------------
+void batteryType (void) {
+  exitMode = 0;                                         //reset EXIT mode
+  lcd.noCursor();                                       //switch Cursor OFF for this menu               
+  lcd.clear();
+  lcd.setCursor(0,0);
+  lcd.print("Select Battery Type");  
+  lcd.setCursor(0,1);
+  lcd.print("1=LiPo/Li-Ion 2=LiFe");
+  lcd.setCursor(0,2);
+  lcd.print("3=NiCd/NiMH   4=ZiZn");
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("5=Set Voltage 6=Exit");                    //20 spaces so as to allow for Load ON/OFF to still show
+
+  customKey = customKeypad.waitForKey();                //stop everything till the user press a key.
+
+  if (customKey == '1'){
+  BatteryCutoffVolts = LiPoCutOffVoltage;
+  BatteryType = ("LiPo");
+    }
+
+  if (customKey == '2'){
+  BatteryCutoffVolts = LiFeCutOffVoltage;
+  BatteryType = ("LiFe");
+    }
+
+  if (customKey == '3'){
+  BatteryCutoffVolts = NiCdCutOffVoltage;
+  BatteryType = ("NiCd");  
+    }
+
+  if (customKey == '4'){
+  BatteryCutoffVolts = ZiZnCutOffVoltage;
+  BatteryType = ("ZiZn"); 
+    }
+
+  if (customKey == '5'){ 
+  BatteryType = ("SetV");
+    }
+
+  if (customKey == '6'){                                  //Exit selection screen
+  exitMode = 1;
+    }
+
+  if (customKey == '7' || customKey == '8' || customKey == '9' || customKey == '0' || customKey == 'A' || customKey == 'B' || customKey == 'C' || customKey == 'D' || customKey == '*' || customKey == '#'){
+  batteryType();                                                        //ignore other keys
+    }
+
+  if(BatteryType == "SetV" && exitMode != 1){
+  setBatteryCutOff();
+    }
+
+  batteryTypeSelected();                                    //briefly display battery type selected and discharge cut off voltage
+
+  lcd.clear();
+
+}
+
+//--------------------------Set DAC Voltage--------------------------------------------
+void dacControl (void) {
+  if (!toggle){
+  dac.setVoltage(0,false);                                 //set DAC output voltage to 0 if Load Off selected
+    if(Mode == "BC" && ActualVoltage >= BatteryCutoffVolts && timer.status() == 1){
+    timer.stop();
+    }
+  
+  }else{
+  //Serial.println("Control Voltage");                    //used for testing only
+  //Serial.println(controlVoltage);                       //used for testing only
+  dac.setVoltage(controlVoltage,false);                   //set DAC output voltage for Range selected
+    if(Mode == "BC" && ActualVoltage >= BatteryCutoffVolts && timer.status() != 1){
+    timer.start();
+    }
+  }
+}
+
+//--------------------------Battery Selected Information--------------------------------------------
+void batteryTypeSelected (void) {
+  if (exitMode !=1){                                      //if battery selection was EXIT then skip this routine
+  lcd.clear();
+  lcd.setCursor(2,0);
+  lcd.print("Battery Selected");
+  lcd.setCursor(8,1);
+  lcd.print(BatteryType);                                 //display battery type selected
+  lcd.setCursor(2,2);
+  lcd.print("Discharge Cutoff");
+  lcd.setCursor(6,3);
+  lcd.print(BatteryCutoffVolts);                          //display battery discharge cut off voltage
+  lcd.print(" volts");                                    
+  delay(3000);
+  }
+}
+
+//--------------------------Set Battery Cut-Off Voltage--------------------------------------------
+void setBatteryCutOff (void) {
+
+  lcd.clear();
+  lcd.setCursor(4,0);
+  lcd.print("Enter Battery");
+  lcd.setCursor(3,1);
+  lcd.print("Cut-Off Voltage");
+  y = 8;
+  z = 8;
+  r = 2;
+
+  inputValue();
+  BatteryCutoffVolts = x;
+
+  lcd.clear();
+}
+
+//------------------------Key input used for Battery Cut-Off and Transient Mode------------------------
+void inputValue (void){
+
+ while(customKey != '#'){               //check if enter pressed (was previously #)
+  
+  customKey = customKeypad.getKey();
+  if(customKey >= '0' && customKey <= '9'){               //check for keypad number input
+       numbers[index++] = customKey;
+       numbers[index] = '\0';
+       lcd.setCursor(z,r);                              
+       lcd.print(customKey);                              //show number input on LCD
+       z = z+1;
+     }
+  
+  if(customKey == '*'){                                   //Decimal point
+      if (decimalPoint != ('*')){                         //test if decimal point entered twice - if so ski
+      numbers[index++] = '.';
+      numbers[index] = '\0';
+      lcd.setCursor(z,r);
+      lcd.print(".");
+      z = z+1;
+      decimalPoint = ('*');                               //used to indicate decimal point has been input
+        }
+      }
+
+ if(customKey == 'C'){                                    //clear entry
+    index = 0;
+    z = y;
+    lcd.setCursor(y,r);
+    lcd.print("     ");
+    numbers[index] = '\0';                                //
+    decimalPoint = (' ');                                 //clear decimal point test character reset
+  }
+
+ }
+ 
+  if(customKey == '#') {                                  //enter value 
+    x = atof(numbers);     
+    index = 0;
+    numbers[index] = '\0';
+    decimalPoint = (' ');                                 //clear decimal point test character reset
+  }
+}
+
+//----------------------------------------Transient Mode--------------------------------------------
+void transientMode (void) {
+
+if(Mode != "TL"){
+
+  y = 11;
+  z = 11;
+  
+  lcd.noCursor();                                       //switch Cursor OFF for this menu               
+  lcd.clear();
+  lcd.setCursor(3,0);
+  lcd.print("Transient Mode");  
+  lcd.setCursor(0,1);
+  lcd.print("Set Low  I=");
+  lcd.setCursor(19,1);
+  lcd.print("A");
+  r = 1;
+  inputValue();
+  
+  if(x >= CurrentCutOff){
+    LowCurrent = CurrentCutOff;
+  }else{
+    LowCurrent = x;
+  }
+  lcd.setCursor(11,r);
+  lcd.print(LowCurrent,3);
+  
+  customKey = '0';
+
+  z = 11;
+
+  lcd.setCursor(0,2);
+  lcd.print("Set High I=");
+  lcd.setCursor(19,2);
+  lcd.print("A");
+  r = 2;
+  inputValue();
+  if(x >= CurrentCutOff){
+    HighCurrent = CurrentCutOff;
+  }else{
+    HighCurrent = x;
+  }
+  lcd.setCursor(11,r);
+  lcd.print(HighCurrent,3);
+
+  customKey = '0';
+
+  if(Mode == "TC" || Mode == "TP"){
+  z = 11;
+
+  lcd.setCursor(0,3);
+  lcd.print("Set Time  = ");
+  lcd.setCursor(16,3);
+  lcd.print("mSec");
+  r = 3;
+  inputValue();
+  transientPeriod = x;
+  lcd.setCursor(11,r);
+  lcd.print(transientPeriod);
+  }else{
+  lcd.setCursor(0,3);
+  lcd.print("                    ");
+  }
+
+  lcd.clear();
+
+  toggle = false;                                           //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");                                         //print on display OFF
+    }else{  
+  transientListSetup();
+  lcd.clear();
+ 
+  toggle = false;                                           //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");                                         //print on display OFF
+  }
+}
+
+//----------------------------------------Transient Type Selection--------------------------------------------
+void transientType (void) {
+  toggle = false;                                         //switch Load OFF
+  exitMode = 0;                                           //reset EXIT mode
+  lcd.noCursor();                                         //switch Cursor OFF for this menu               
+  lcd.clear();
+  lcd.setCursor(3,0);
+  lcd.print("Transient Mode");  
+  lcd.setCursor(0,1);
+  lcd.print("1 = Continuous");
+  lcd.setCursor(0,2);
+  lcd.print("2 = Toggle");
+  lcd.setCursor(11,2);                                    //
+  lcd.print("3 = Pulse");                                 //
+  lcd.setCursor(0,3);                                     //
+  lcd.print("4 = List");                                  //
+  lcd.setCursor(11,3);                                    //
+  lcd.print("5 = Exit");                                  //
+
+  customKey = customKeypad.waitForKey();                  //stop everything till the user press a key.
+
+  if (customKey == '1'){
+  Mode = ("TC"); 
+    }
+
+  if (customKey == '2'){
+   Mode = ("TT");
+    }
+
+  if (customKey == '3'){
+  Mode = ("TP");  
+    }
+
+  if (customKey == '4'){
+  Mode = ("TL");  
+    }
+
+  if (customKey == '5'){                                  //Exit selection screen
+  exitMode = 1;
+    }
+
+  if (customKey == '6' || customKey == '7' || customKey == '8' || customKey == '9' || customKey == '0' || customKey == 'A' || customKey == 'B' || customKey == 'C' || customKey == 'D' || customKey == '*' || customKey == '#'){
+  transientType();                                                      //ignore other keys
+  
+    }
+lcd.clear();
+
+if (exitMode == 1){                                       //if NO Transient Mode type selected revert to CC Mode
+    lcd.setCursor(8,0);
+    lcd.print("OFF");
+    Current();                                            //if selected go to Constant Current Selected routine
+    encoderPosition = 0;                                  //reset encoder reading to zero
+    customKey = 'A';
+      }else{
+    transientMode();
+      }
+ }
+ 
+//----------------------------------------Transient--------------------------------------------
+void transient (void) {
+  
+  if(Mode == "TC" || Mode == "TP" || Mode == "TT" || Mode == "TL"){
+  lcd.noCursor();                                         //switch Cursor OFF for this menu 
+  lcd.setCursor(0,0);
+  lcd.print("DC LOAD");
+  
+  if(Mode != "TL"){
+  lcd.setCursor(0,2);
+  lcd.print("Lo=");
+  lcd.setCursor(3,2);
+  lcd.print(LowCurrent,3);
+  lcd.setCursor(8,2);
+  lcd.print("A");
+  lcd.setCursor(11,2);
+  lcd.print("Hi=");
+  lcd.setCursor(14,2);                                    //
+  lcd.print(HighCurrent,3);
+  lcd.setCursor(19,2);
+  lcd.print("A");
+  }else{
+    delay(1);
+  }
+
+
+  if(Mode == "TC" || Mode == "TP" || Mode == "TL"){
+  lcd.setCursor(0,3);                                     //
+  lcd.print("Time = ");
+  lcd.setCursor(7,3);
+  lcd.print(transientPeriod);
+  lcd.setCursor(12,3);                                    //
+  lcd.print("mSecs");
+    }else{
+     lcd.setCursor(0,3);
+     lcd.print("  ");
+    }
+  }
+delay(1);
+}
+
+//-------------------------------------Transcient List Setup-------------------------------------------
+void transientListSetup(){
+
+  lcd.noCursor();                                                 
+  lcd.clear();
+  lcd.setCursor(0,0);
+  lcd.print("Setup Transient List");
+  lcd.setCursor(0,1);
+  lcd.print("Enter Number in List");
+  lcd.setCursor(0,2);
+  lcd.print("(between 2 to 10 max"); 
+  y = 0;
+  z = 0;
+  r = 3;
+  inputValue();
+  total_instructions = int(x-1);
+  customKey = '0';
+  lcd.clear();
+  
+    for(int i=0; i<=(total_instructions); i++){
+      lcd.setCursor(0,0);
+      lcd.print("Set Current ");
+      lcd.print(i+1);
+      lcd.setCursor(16,1);
+      lcd.print("A");
+      y = 0;
+      z = 0;
+      r = 1;
+      inputValue();            //get the users input value
+      transientList[i][0] = x; //store the users entered value in the transient list 
+      customKey = '0';
+      lcd.setCursor(0,2);
+      lcd.print("Set Time ");
+      lcd.print(i+1);
+      lcd.setCursor(16,3);
+      lcd.print("mSec");
+      y = 0;
+      z = 0;
+      r = 3;
+      inputValue();            //get the users input value
+      transientList[i][1] = x; //store the users entered value in the transient list
+      customKey = '0';
+      lcd.clear();   
+  }
+  current_instruction = 0;      //start at first instrution
+}
+
+//-------------------------------------Transcient Load Toggel-------------------------------------------
+void transientLoadToggle(){
+
+  if(Mode == "TC"){
+  current_time = micros();                              //get the current time in micro seconds()
+  if (last_time == 0){
+    last_time = current_time;
+  } else {
+    switch (transient_mode_status){
+      case (false):
+          // we are in the low current setting
+          if ((current_time - last_time) >= (transientPeriod * 1000.0)){
+             transientSwitch(LowCurrent, true);  
+          }
+        break;
+      case (true):
+          // we are in the high current setting 
+          if ((current_time - last_time) >= (transientPeriod * 1000.0)){
+            transientSwitch(HighCurrent, true);            
+          }
+        break; 
+      } 
+     }
+    }
+
+
+  if(Mode == "TP"){
+    current_time = micros();                            //get the current time in micro seconds()
+    if (last_time == 0){
+        last_time = current_time;
+        transientSwitch(LowCurrent, true);
+    }
+    if (digitalRead(TriggerPulse) == LOW){
+      // a trigger pluse is received
+      // set to the high current
+      transientSwitch(HighCurrent, true); 
+    } else {
+        if ((current_time - last_time) >= (transientPeriod * 1000.0)){
+            transientSwitch(LowCurrent, true);            
+        }
+      }  
+  }
+
+
+ if(Mode == "TT"){          // this function will toggle between high and low current when the trigger pin is taken low
+  if (digitalRead(TriggerPulse) == LOW){
+    switch (transient_mode_status){
+      case (false):
+        transientSwitch(LowCurrent, true); 
+        break;
+      case (true):
+        transientSwitch(HighCurrent, true);   
+        break;
+      }
+    }
+  }
+
+
+if(Mode == "TL"){
+  if (Load == 1){                                           // Only perform Transient List if Load is ON
+   current_time = micros();                              //get the current time in micro seconds()
+    if (last_time == 0){
+      last_time = current_time;
+      transientPeriod = transientList[current_instruction][1];   //Time data for LCD display
+      transientSwitch(transientList[current_instruction][0], false);
+    }
+    if((current_time - last_time) >= transientList[current_instruction][1] * 1000){     //move to next list instruction
+        current_instruction++;
+        if(current_instruction > total_instructions){
+          current_instruction = 0;
+        }
+      transientPeriod = transientList[current_instruction][1];   //Time data for LCD display
+      transientSwitch(transientList[current_instruction][0], false);
+      }
+    }
+  }
+
+}
+
+//-------------------------------------Transcient Switch-------------------------------------------
+void transientSwitch(float current_setting, boolean toggle_status){
+  if (toggle_status){
+  transient_mode_status = !transient_mode_status;
+  }
+  setCurrent = current_setting;
+  //Serial.print("set current = ");                     //used for testing only
+  //Serial.println(setCurrent);                         //used for testing only
+  last_time = current_time;
+}
+
+//-------------------------------------User set up for limits-------------------------------------------------
+void userSetUp (void) {
+  y = 14;
+  z = 14;
+  
+  lcd.noCursor();                                       //switch Cursor OFF for this menu               
+  lcd.clear();
+  lcd.setCursor(4,0);
+  lcd.print("User Set-Up");
+  lcd.setCursor(0,1);
+  lcd.print("Current Limit=");
+  lcd.setCursor(19,1);
+  lcd.print("A");
+  r = 1;
+  inputValue();
+  CurrentCutOff = x;
+  EEPROM.write(0x00, CurrentCutOff);
+  lcd.setCursor(14,r);
+  lcd.print(CurrentCutOff);
+  
+  customKey = '0';
+
+  z = 14;
+
+  lcd.setCursor(0,2);
+  lcd.print("Power Limit  =");
+  lcd.setCursor(19,2);
+  lcd.print("W");
+  r = 2;
+  inputValue();
+  PowerCutOff = x;
+  EEPROM.write(0x20, PowerCutOff);              //
+  lcd.setCursor(14,r);
+  lcd.print(PowerCutOff);
+
+  customKey = '0';
+
+  z = 14;
+
+  lcd.setCursor(0,3);
+  lcd.print("Temp. Limit  =");
+  lcd.setCursor(18,3);
+  lcd.print((char)0xDF);
+  lcd.print("C");
+  r = 3;
+  inputValue();
+  tempCutOff = x;
+  EEPROM.write(0x40, tempCutOff);
+  lcd.setCursor(14,r);
+  lcd.print(tempCutOff);
+
+    lcd.clear();
+
+    lcd.setCursor(8,0);
+    lcd.print("OFF");
+    Current();                                            //if selected go to Constant Current Selected routine
+    encoderPosition = 0;                                  //reset encoder reading to zero
+    customKey = 'A';
+}
+
+//------------------------------------------High Temperature Cut-Off--------------------------------------------------------------
+void temperatureCutOff (void){
+  if (temp >= tempCutOff){                                 //if Maximum temperature is exceeded
+  reading = 0;
+  encoderPosition = 0; 
+  lcd.setCursor(0,3);
+  lcd.print("                    ");
+  lcd.setCursor(0,3);
+  lcd.print("Over Temperature");
+  lcd.setCursor(8,0);
+  lcd.print("OFF");
+  toggle = false;                                         //switch Load Off
+  }
+}
+
+//-----------------------------------------Current Read Calibration for LCD Display --------------------------------------------
+void currentDisplayCal (void){
+
+  if(ActualCurrent <= 0){
+    ActualCurrent = 0;
+  }else if(Load == 0){
+    ActualCurrent = 0;
+  }else{
+  ActualCurrent = ActualCurrent + displayCurrentCal;
+  }
+
+/*  if (ActualCurrent <= 0.5)
+    {
+    ActualCurrent = (ActualCurrent +(displayCurrentCal * 3));
+    }
+    else if (ActualCurrent >= 0.5 && ActualCurrent <1.0)
+    {
+    ActualCurrent = (ActualCurrent + (displayCurrentCal * 2));
+    }
+    else if (ActualCurrent >= 1.0 && ActualCurrent <= 1.4)
+    {
+    ActualCurrent = (ActualCurrent + (displayCurrentCal));
+    }
+    else 
+    {
+    ActualCurrent = ActualCurrent;
+    }
+*/
+}
+  
+//-----------------------------Show limits Stored Data for Current, Power and Temp-----------------------------
+  void setupLimits (void){
+  lcd.clear();
+  lcd.setCursor(1,0);
+  lcd.print("Maximum Limits Set");
+  lcd.setCursor(0,1);
+  lcd.print("Current Limit=");
+  lcd.setCursor(17,1);
+  lcd.print("A");
+  lcd.setCursor(15,1);
+  CurrentCutOff = EEPROM.read(0x00);
+  lcd.print(CurrentCutOff);
+
+  lcd.setCursor(0,2);
+  lcd.print("Power Limit  =");
+  lcd.setCursor(17,2);
+  lcd.print("W");
+  lcd.setCursor(15,2);
+  PowerCutOff = EEPROM.read(0x20);
+  lcd.print(PowerCutOff);
+
+  lcd.setCursor(0,3);
+  lcd.print("Temp. Limit  =");
+  lcd.setCursor(17,3);
+  lcd.print((char)0xDF);
+  lcd.print("C");
+  tempCutOff = EEPROM.read(0x40);
+  lcd.setCursor(15,3);
+  lcd.print(tempCutOff);
+  }
+  
+  //---------------------------------------------------------------------------------------------------------

BIN
docs/IýC Interface Module for LCD Displays.pdf


BIN
docs/MCP79410Timer-master.zip


+ 35 - 0
sw/DC_LOAD/include/MCP79410_Timer.h

@@ -0,0 +1,35 @@
+#ifndef MCP79410_Timer_h
+#define MCP79410_Timer_h
+
+#include <Arduino.h>
+#include <Wire.h>
+
+class MCP79410_Timer {
+  public:
+    MCP79410_Timer(byte rtcAddress);
+    MCP79410_Timer(void);
+    void start();
+    void stop();
+    void reset();
+    int status();
+    uint8_t hours();
+    uint8_t minutes();
+    uint8_t seconds();
+    String getTime();
+    uint32_t getTotalSeconds();
+
+  private:
+    // private methods
+    unsigned char _readRtcByte(const unsigned char adr);
+    void _writeRtcByte(const unsigned char adr, const unsigned char data);
+    uint8_t _makeDec(uint8_t num);
+    uint8_t _makeHex(uint8_t num);
+    unsigned char _getRtcData(const unsigned char adr, const unsigned char validbits);
+    String _format2digit(const unsigned char data);
+    // private variables
+    byte _rtcAddress;
+    int _rtcState;
+
+};
+
+#endif

+ 39 - 0
sw/DC_LOAD/include/README

@@ -0,0 +1,39 @@
+
+This directory is intended for project header files.
+
+A header file is a file containing C declarations and macro definitions
+to be shared between several project source files. You request the use of a
+header file in your project source file (C, C++, etc) located in `src` folder
+by including it, with the C preprocessing directive `#include'.
+
+```src/main.c
+
+#include "header.h"
+
+int main (void)
+{
+ ...
+}
+```
+
+Including a header file produces the same results as copying the header file
+into each source file that needs it. Such copying would be time-consuming
+and error-prone. With a header file, the related declarations appear
+in only one place. If they need to be changed, they can be changed in one
+place, and programs that include the header file will automatically use the
+new version when next recompiled. The header file eliminates the labor of
+finding and changing all the copies as well as the risk that a failure to
+find one copy will result in inconsistencies within a program.
+
+In C, the usual convention is to give header files names that end with `.h'.
+It is most portable to use only letters, digits, dashes, and underscores in
+header file names, and at most one dot.
+
+Read more about using header files in official GCC documentation:
+
+* Include Syntax
+* Include Operation
+* Once-Only Headers
+* Computed Includes
+
+https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

+ 46 - 0
sw/DC_LOAD/lib/README

@@ -0,0 +1,46 @@
+
+This directory is intended for project specific (private) libraries.
+PlatformIO will compile them to static libraries and link into executable file.
+
+The source code of each library should be placed in a an own separate directory
+("lib/your_library_name/[here are source files]").
+
+For example, see a structure of the following two libraries `Foo` and `Bar`:
+
+|--lib
+|  |
+|  |--Bar
+|  |  |--docs
+|  |  |--examples
+|  |  |--src
+|  |     |- Bar.c
+|  |     |- Bar.h
+|  |  |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
+|  |
+|  |--Foo
+|  |  |- Foo.c
+|  |  |- Foo.h
+|  |
+|  |- README --> THIS FILE
+|
+|- platformio.ini
+|--src
+   |- main.c
+
+and a contents of `src/main.c`:
+```
+#include <Foo.h>
+#include <Bar.h>
+
+int main (void)
+{
+  ...
+}
+
+```
+
+PlatformIO Library Dependency Finder will find automatically dependent
+libraries scanning project source files.
+
+More information about PlatformIO Library Dependency Finder
+- https://docs.platformio.org/page/librarymanager/ldf.html

+ 19 - 0
sw/DC_LOAD/platformio.ini

@@ -0,0 +1,19 @@
+; PlatformIO Project Configuration File
+;
+;   Build options: build flags, source filter
+;   Upload options: custom upload port, speed and extra flags
+;   Library options: dependencies, extra library storages
+;   Advanced options: extra scripting
+;
+; Please visit documentation for the other options and examples
+; https://docs.platformio.org/page/projectconf.html
+
+[env:nanoatmega328]
+platform = atmelavr
+board = nanoatmega328
+
+framework = arduino
+lib_deps =  https://github.com/cyberang3l/NewLiquidCrystal
+            https://github.com/adafruit/Adafruit_MCP4725
+            https://github.com/stevemarple/MCP342x
+            https://github.com/Chris--A/Keypad

+ 121 - 0
sw/DC_LOAD/src/MCP79410_Timer.cpp

@@ -0,0 +1,121 @@
+#include "MCP79410_Timer.h"
+
+// constructor
+MCP79410_Timer::MCP79410_Timer(byte rtcAddress){
+  _rtcAddress = rtcAddress;
+  Wire.begin();
+}
+
+MCP79410_Timer::MCP79410_Timer(void){
+  _rtcAddress = 0x6f;
+  Wire.begin();
+}
+
+
+void MCP79410_Timer::start(){
+  // get the seconds byte form RTC
+  byte secondsByte = _getRtcData(0, 8);
+  // bitwise OR between seconds byte and 1000 0000
+  // sets the first bit to 1 and leave the remaining 7 bits untouched
+  secondsByte = secondsByte | 0x80;
+  // write the updated byte back to the RTC
+  _writeRtcByte(0, secondsByte);
+  // set the state = 1 to indicate the clock is running
+  _rtcState = 1;
+}
+
+void MCP79410_Timer::stop(){
+  // get the seconds byte form RTC
+  byte secondsByte = _getRtcData(0, 8); // get the seconds byte form RTC
+  // bitwise AND between seconds byte and 0111 1111
+  // sets the first bit to 0 and leave the remaining 7 bits untouched
+  secondsByte = secondsByte & 0x7f;
+  _writeRtcByte(0, secondsByte);
+  // set the state = 2 to indicate the clock is stopped
+  _rtcState = 2;
+}
+
+void MCP79410_Timer::reset(){
+  // always force a the timer to stop before a reset
+  _writeRtcByte(0,0x00);     //SECOND=0 and Clock Stopped
+  _writeRtcByte(1,0x00);    //MINUTE=00
+  _writeRtcByte(2,0x00);    //HOUR=00
+  // set the state = 2 to indicate the clock is reset & stopped
+  _rtcState = 0;
+}
+
+int MCP79410_Timer::status(){
+  return _rtcState;
+}
+
+uint32_t MCP79410_Timer::getTotalSeconds(){
+  uint32_t hours = _makeDec(_getRtcData(2, 6)) * 60 * 60;   //convert hours to seconds
+  uint16_t mins = _makeDec(_getRtcData(1, 7)) * 60;         //convert minutes to seconds
+  uint8_t secs = _makeDec(_getRtcData(0,7));                //seconds
+  uint32_t dateAsSeconds = hours + mins + secs;             //calculate total seconds
+  return dateAsSeconds;                                     //return with total seconds
+}
+
+uint8_t MCP79410_Timer::hours() {
+    return _makeDec(_getRtcData(2,6));
+}
+
+uint8_t MCP79410_Timer::minutes() {
+  return _makeDec(_getRtcData(1,7));
+}
+
+uint8_t MCP79410_Timer::seconds(){
+  return _makeDec(_getRtcData(0,7));
+}
+
+String MCP79410_Timer::getTime(){
+  return _format2digit(_getRtcData(2,6)) + ":" +
+         _format2digit(_getRtcData(1,7)) + ":" +
+         _format2digit(_getRtcData(0,7));
+}
+
+
+//Read RTC Byte
+unsigned char MCP79410_Timer::_readRtcByte(const unsigned char adr){
+  unsigned char data;
+  Wire.beginTransmission(0x6f);
+  Wire.write(adr);
+  Wire.endTransmission();
+  Wire.requestFrom(0x6f,1);
+  while (Wire.available()) data=Wire.read();
+  return data;
+}
+
+//Write to RTC
+void MCP79410_Timer::_writeRtcByte(const unsigned char adr, const unsigned char data){
+  Wire.beginTransmission(0x6f);
+  Wire.write(adr);
+  Wire.write(data);
+  Wire.endTransmission();
+}
+
+//convert to decimal
+uint8_t MCP79410_Timer::_makeDec(uint8_t num){
+    uint8_t units = num & 0x0F;
+    uint8_t tens = num >> 4;
+    return tens*10 + units;
+}
+
+uint8_t MCP79410_Timer::_makeHex(uint8_t num){
+  uint8_t units = num % 10;
+  uint8_t tens = num / 10;
+  return (tens << 4) | units;
+}
+
+unsigned char MCP79410_Timer::_getRtcData(const unsigned char adr, const unsigned char validbits){
+  unsigned char data;
+  data=_readRtcByte(adr);
+  data=data & 0xff>>(8-validbits);
+  return data;
+}
+
+String MCP79410_Timer::_format2digit(unsigned char data){
+  uint8_t units = data & 0x0f;
+  uint8_t tens = data >> 4;
+  return String(tens) + String(units);
+}

+ 1423 - 0
sw/DC_LOAD/src/main.cpp

@@ -0,0 +1,1423 @@
+
+
+//SCULLCOM HOBBY ELECTRONICS
+//ELECTRONIC DC LOAD PROJECT
+//Software Version 35 (4x5 Matrix Keypad Version - modified key layout)
+//14th April 2018
+#include <Arduino.h>
+#include <SPI.h>                              //include SPI library (Serial Peripheral Interface)
+#include <Wire.h>                             //include I2C library
+#include <LiquidCrystal_I2C.h>                // F Malpartida's NewLiquidCrystal library
+                                              // https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads/NewliquidCrystal_1.3.4.zip
+#include <math.h>                             //
+#include <Adafruit_MCP4725.h>                 //Adafruit DAC library  https://github.com/adafruit/Adafruit_MCP4725
+#include <MCP342x.h>                          //Steve Marple library avaiable from    https://github.com/stevemarple/MCP342x
+#include <MCP79410_Timer.h>                   //Scullcom Hobby Electronics library  http://www.scullcom.com/MCP79410Timer-master.zip
+#include <EEPROM.h>                           //include EEPROM library used for storing setup data
+
+#include <Keypad.h>                           //http://playground.arduino.cc/Code/Keypad
+
+const byte ROWS = 5;                          //five rows
+const byte COLS = 4;                          //four columns
+
+void setupLimits (void);
+void transientSwitch(float current_setting, boolean toggle_status);
+void transientListSetup();
+void batteryType (void);
+void setBatteryCutOff (void);
+void setBatteryCutOff (void);
+void inputValue (void);
+void batteryTypeSelected (void);
+void currentDisplayCal (void);
+void BatteryCapacity(void);
+void Current(void);
+void Resistance(void);
+void Power(void);
+void transientType(void);
+void userSetUp (void);
+void fanControl (void);
+void batteryCapacity (void);
+void LoadSwitch(void);
+void dacControlVoltage (void);
+void dacControl (void);
+void ActualReading(void);
+void readVoltageCurrent (void);
+void displayEncoderReading (void);
+void transientLoadToggle();
+void CursorPosition(void);
+void batteryCurrentLimitValue(void);
+void temperatureCutOff(void);
+void maxConstantCurrentSetting (void) ;
+void transient (void);
+void readKeypadInput (void);
+void powerLevelCutOff (void) ;
+//define the symbols on the buttons of the keypads
+char hexaKeys[ROWS][COLS] = {
+  {'<','0','>','F'},
+  {'7','8','9','E'},
+  {'4','5','6','D'},
+  {'1','2','3','C'},
+  {'A','B','#','*'}
+};
+
+byte rowPins[ROWS] = {9, 10, 11, 12, 14}; //connect to the row pin outs of the keypad
+byte colPins[COLS] = {5, 6, 7, 8}; //connect to the column pin outs of the keypad
+
+//initialize an instance of class NewKeypad
+Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
+char customKey;
+
+char decimalPoint;                            //used to test for more than one press of * key (decimal point)
+
+Adafruit_MCP4725 dac;                         //constructor
+
+uint8_t address = 0x68;                       //0x68 is the default address for the MCP3426 device
+MCP342x adc = MCP342x(address);
+
+const byte MCP79410_ADDRESS = 0x6f;           //0x6f is the default address for the MCP79410 Real Time Clock IC
+MCP79410_Timer timer = MCP79410_Timer(MCP79410_ADDRESS);
+
+//Set the pins on the I2C chip used for LCD connections
+//ADDR,EN,R/W,RS,D4,D5,D6,D7
+LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7);    //0x27 is the default address of the LCD with I2C bus module
+
+const byte pinA = 2;                          //digital pin (also interrupt pin) for the A pin of the Rotary Encoder (changed to digital pin 2)
+const byte pinB = 4;                          //digital pin for the B pin of the Rotary Encoder
+
+const byte CursorPos = 17;                    //analog pin A3 used as a digital pin to set cursor position (rotary encoder push button)
+const byte LoadOnOff = 15;                    //analog pin A1 used as a digital pin to set Load ON/OFF
+
+const byte TriggerPulse = 16;                 //analog pin A2 used as a digital pin for trigger pulse input in transient mode
+
+const byte fan = 3;                           //digital pin 3 for fan control output (changed to Digital pin 3)
+const byte temperature = A6;                  //analog pin used for temperature output from LM35 (was A0 previously but changed)
+int temp;                                     //
+
+float BatteryLife = 0;                        //
+float BatteryLifePrevious = 0;                //
+float Seconds = 0;                            //time variable used in Battery Capacity Mode (BC)
+float SecondsLog = 0;                         //variable used for data logging of the time in seconds
+float BatteryCutoffVolts;                     //used to set battery discharge cut-off voltage
+float MaxBatteryCurrent = 1.0;                //maximum battery current allowed for Battery Capacity Testing
+
+int stopSeconds;                              //store for seconds when timer stopped
+
+int CP = 8;                                   //cursor start position
+
+boolean toggle = false;                       //used for toggle of Load On/Off button
+
+unsigned long controlVoltage = 0;             //used for DAC to control MOSFET
+
+long current = 0;                             //variable used by ADC for measuring the current
+long voltage = 0;                             //variable used by ADC for measuring the voltage
+
+float reading = 0;                            //variable for Rotary Encoder value divided by 1000
+
+float setCurrent = 0;                         //variable used for the set current of the load
+float setPower = 0;                           //variable used for the set power of the load
+float setResistance = 0;                      //variable used for the set resistance of the load
+float setCurrentCalibrationFactor = 0.980;    //calibration adjustment - set as required if needed (was 1.000)
+
+float displayCurrentCal = 0.000;              //calibration correction for LCD current display (was 0.040)
+int Load = 0;                                 //Load On/Off flag
+
+float setControlCurrent = 0;                  //variable used to set the temporary store for control current required
+
+int VoltsDecimalPlaces = 3;                   //number of decimal places used for Voltage display on LCD
+
+float ActualVoltage = 0;                      //variable used for Actual Voltage reading of Load
+float ActualCurrent = 0;                      //variable used for Actual Current reading of Load
+float ActualPower = 0;                        //variable used for Actual Power reading of Load
+
+float ResistorCutOff = 999;                   //maximum Resistor we want to deal with in software
+float BatteryCurrent;                         //
+float LoadCurrent;                            //
+
+int CurrentCutOff = EEPROM.read(0x00);
+int PowerCutOff = EEPROM.read(0x20);
+int tempCutOff = EEPROM.read(0x40);
+
+int setReading = 0;                           //
+
+int ControlVolts = 0;                         //used to set output current
+float OutputVoltage = 0;                      //
+
+String Mode ="  ";                            //used to identify which mode
+
+int modeSelected = 0;                         //Mode status flag
+
+int lastCount = 50;                           //
+volatile float encoderPosition = 0;           //
+volatile unsigned long factor= 0;             //number of steps to jump
+volatile unsigned long encoderMax = 999000;   //sets maximum Rotary Encoder value allowed CAN BE CHANGED AS REQUIRED (was 50000)
+
+float LiPoCutOffVoltage = 3.0;                //set cutoff voltage for LiPo battery
+float LiFeCutOffVoltage = 2.8;                //set cutoff voltage for LiFe battery
+float NiCdCutOffVoltage = 1.0;                //set cutoff voltage for NiCd battery
+float ZiZnCutOffVoltage = 1.0;                //set cutoff voltage for ZiZn battery
+float PbAcCutOffVoltage = 1.75;               //set cutoff voltage for PbAc battery
+String BatteryType ="    ";
+
+byte exitMode = 0;                           //used to exit battery selection menu and return to CC Mode
+
+char numbers[10];                            //keypad number entry - Plenty to store a representation of a float
+byte index = 0;
+int z = 1;                                   //was previously 0
+float x = 0;
+int y = 0;
+int r = 0;
+
+float LowCurrent = 0;               //the low current setting for transcient mode
+float HighCurrent = 0;              //the high current setting for transcient mode
+unsigned long transientPeriod;      //used to store pulse time period in transcient pulse mode
+unsigned long current_time;         //used to store the current time in microseconds
+unsigned long last_time;            //used to store the time of the last transient switch in micro seconds
+boolean transient_mode_status;      //used to maintain the state of the trascient mode (false = low current, true = high current)
+
+float transientList [10][2];        //array to store Transient List data
+int total_instructions;             //used in Transient List Mode
+int current_instruction;            //used in Transient List Mode
+
+//--------------------------------Interrupt Routine for Rotary Encoder------------------------
+void isr()
+{
+  static unsigned long lastInterruptTime = 0;
+  unsigned long interruptTime = millis();
+
+  if (interruptTime - lastInterruptTime > 5) {  //
+    if (digitalRead(pinB) == LOW)
+    {
+      encoderPosition = encoderPosition - factor;
+    }else{
+      encoderPosition = encoderPosition + factor;
+    }
+    encoderPosition = min(encoderMax, max(0, encoderPosition));  // sets maximum range of rotary encoder
+    lastInterruptTime = interruptTime;
+  }
+    }
+//---------------------------------Initial Set up---------------------------------------
+void setup() {
+  Serial.begin(9600);                                      //used for testing only
+ 
+  Wire.begin();                                            //join i2c bus (address optional for master)
+  Wire.setClock(400000L);                                  //sets bit rate to 400KHz
+
+  MCP342x::generalCallReset();                             //Reset devices
+  delay(1);                                                //MC342x needs 300us to settle, wait 1ms - (may not be required)
+
+  pinMode (pinA, INPUT);
+  pinMode (pinB, INPUT);
+
+  pinMode (CursorPos, INPUT_PULLUP);
+  pinMode (LoadOnOff, INPUT_PULLUP);
+ 
+  pinMode (TriggerPulse, INPUT_PULLUP);
+
+  pinMode (fan, OUTPUT);
+  TCCR2B = (TCCR2B & 0b11111000) | 1;                      //change PWM to above hearing (Kenneth Larvsen recommendation)
+  pinMode (temperature, INPUT);
+ 
+  analogReference(INTERNAL);                               //use Arduino internal reference for tempurature monitoring
+
+  attachInterrupt(digitalPinToInterrupt(pinA), isr, LOW);
+
+  dac.begin(0x61);                                         //the DAC I2C address with MCP4725 pin A0 set high
+  dac.setVoltage(0,false);                                 //reset DAC to zero for no output current set at Switch On
+
+  lcd.begin(20, 4);                                        //set up the LCD's number of columns and rows 
+  lcd.setBacklightPin(3,POSITIVE);                         // BL, BL_POL
+  lcd.setBacklight(HIGH);                                  //set LCD backlight on
+ 
+  lcd.clear();                                             //clear LCD display
+  lcd.setCursor(6,0);                                      //set LCD cursor to column 0, row 4
+  lcd.print("SCULLCOM");                                   //print SCULLCOM to display with 5 leading spaces (you can change to your own)
+  lcd.setCursor(1,1);                                      //set LCD cursor to column 0, row 1 (start of second line)
+  lcd.print("Hobby Electronics");                          //print Hobby Electronics to display (you can change to your own)
+  lcd.setCursor(1,2);
+  lcd.print("DC Electronic Load"); //
+  lcd.setCursor(0,3);
+  lcd.print("Ver. 35 (5x4 Keypad)"); //
+  delay(2000);                                             //3000 mSec delay for intro display
+  lcd.clear();                                             //clear dislay
+  setupLimits();
+  delay(3000);
+  lcd.clear();
+
+  last_time = 0;                                           //set the last_time to 0 at the start (Transicent Mode)
+  transient_mode_status = false;                           //set the initial transient mode status (false = low, true = high);
+  setCurrent = LowCurrent;                                 //first set the current to the low current value (Transicent Mode)
+ 
+  lcd.setCursor(8,0);
+  lcd.print("OFF");                                        //indicate that LOAD is off at start up
+  Current();                                               //sets initial mode to be CC (Constant Current) at Power Up
+  
+  customKey = customKeypad.getKey();
+  
+}
+
+//------------------------------------------Main Program Loop---------------------------------
+void loop() {
+
+ if(CurrentCutOff > 5){                                 //Test and go to user set limits if required
+    userSetUp();
+     }else{
+  
+  readKeypadInput();                                     //read Keypad entry
+  
+  if (digitalRead(LoadOnOff) == LOW) {
+    LoadSwitch();                                          //Load on/off
+  }
+  
+  transient();                                           //test for Transient Mode
+  
+  lcd.setCursor(18,3);                                   //sets display of Mode indicator at bottom right of LCD
+  lcd.print(Mode);                                       //display mode selected on LCD (CC, CP, CR or BC)
+
+  if(Mode != "TC" && Mode != "TP" && Mode != "TT" && Mode != "TL"){      //if NOT transient mode then Normal Operation
+    reading = encoderPosition/1000;                        //read input from rotary encoder 
+    maxConstantCurrentSetting();                           //set maxiumum Current allowed in Constant Current Mode (CC)
+    powerLevelCutOff();                                    //Check if Power Limit has been exceeded
+  
+    temperatureCutOff();                                   //check if Maximum Temperature is exceeded
+  
+    batteryCurrentLimitValue();                            //Battery Discharge Constant Current Limit Value in BC Mode
+    displayEncoderReading();                               //display rotary encoder input reading on LCD
+    lastCount = encoderPosition;                           //store rotary encoder current position
+    CursorPosition();                                      //check and change the cursor position if cursor button pressed
+  }else{
+    transientLoadToggle();                                  //Start Transient Mode
+  }
+    
+  readVoltageCurrent();                                  //routine for ADC's to read actual Voltage and Current
+  ActualReading();                                       //Display actual Voltage, Current readings and Actual Wattage
+  
+  dacControl();
+  dacControlVoltage();                                   //sets the drive voltage to control the MOSFET
+
+  batteryCapacity();                                     //test if Battery Capacity (BC) mode is selected - if so action
+  fanControl();                                          //call heatsink fan control
+  }
+}
+//------------------------------------------------Read Keypad Input-----------------------------------------------------
+void readKeypadInput (void) {
+  customKey = customKeypad.getKey();
+  
+//  if (customKey != NO_KEY){                             //only used for testing keypad (uncomment if required for testing keypad)
+// Serial.print("customKey = ");                          //only used for testing keypad (uncomment if required for testing keypad)
+// Serial.println(customKey);                             //only used for testing keypad (uncomment if required for testing keypad)
+//  }                                                     //only used for testing keypad (uncomment if required for testing keypad)
+
+if(customKey == 'E'){                                     //check for Load on/off
+  LoadSwitch();
+}
+
+  if(customKey == 'D'){                                   //check if Set-Up Mode Selected 
+  delay(200);
+  toggle = false;                                         //switch Load OFF
+  userSetUp();
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point text character reset
+}
+ 
+  if(customKey == 'C'){                                   //check if Transient Mode Selected
+  toggle = false;                                         //switch Load OFF
+  transientType();
+ 
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point text character reset
+  }
+               
+  if(customKey == 'A'){                                   //check if Constant Current button pressed
+  toggle = false;                                         //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");
+  Current();                                              //if selected go to Constant Current Selected routine
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point test character reset
+  }
+         
+  if(customKey == 'B'){                                   //check if Constant Power button pressed
+  toggle = false;                                         //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF"); 
+  Power();                                                //if selected go to Constant Power Selected routine
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point test character reset
+  }
+          
+  if(customKey == '#'){                                   //check if Constant Resistance button pressed  
+  toggle = false;                                         //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");  
+  Resistance();                                           //if selected go to Constant Resistance Selected routine
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point test character reset
+  }
+
+  if(customKey == '*'){                                   //check if Battery Capacity button pressed
+  dac.setVoltage(0,false);                                //Ensures Load is OFF - sets DAC output voltage to 0
+  toggle = false;                                         //switch Load OFF
+  batteryType();                                          //select battery type
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point test character reset
+
+    if (exitMode == 1){                                   //if NO battery type selected revert to CC Mode
+    lcd.setCursor(8,0);
+    lcd.print("OFF");
+    Current();                                            //if selected go to Constant Current Selected routine
+    encoderPosition = 0;                                  //reset encoder reading to zero
+    customKey = 'A';
+    }
+    else
+    {
+    lcd.setCursor(16,2);
+    lcd.print(BatteryType);                               //print battery type on LCD 
+    lcd.setCursor(8,0);
+    lcd.print("OFF");
+    timer.reset();                                        //reset timer
+    BatteryLifePrevious = 0;
+    CP = 9;                                               //set cursor position
+    BatteryCapacity();                                    //go to Battery Capacity Routine
+    }
+  }
+
+if (Mode != "BC"){
+
+  if(customKey >= '0' && customKey <= '9'){               //check for keypad number input
+       numbers[index++] = customKey;
+       numbers[index] = '\0';
+       lcd.setCursor(z,3);                                //                   
+       lcd.print(customKey);                              //show number input on LCD
+       z = z+1;
+     }
+  
+  if(customKey == '>'){                                   //check if decimal button key pressed
+      if (decimalPoint != ('>')){                         //test if decimal point entered twice - if so skip 
+      numbers[index++] = '.';
+      numbers[index] = '\0';
+      lcd.setCursor(z,3);
+      lcd.print(".");
+      z = z+1;
+      decimalPoint = ('>');                             //used to indicate decimal point has been input
+        }
+      }
+
+  if(customKey == '<'){                                 //clear input entry
+     index = 0;
+     z = 1;                                             //sets column position for LCD displayed character
+     lcd.setCursor(z,3);
+     lcd.print("     ");
+     numbers[index] = '\0';                             //
+     decimalPoint = (' ');                              //clear decimal point test character reset
+    }
+
+  if(customKey == 'F') {                                //use entered number
+    x = atof(numbers);     
+         reading = x;
+         encoderPosition = reading*1000;
+         index = 0;
+         numbers[index] = '\0';
+         z = 1;                                         //sets column position for LCD displayed character
+         lcd.setCursor(0,3);
+         lcd.print("        ");
+         decimalPoint = (' ');                          //clear decimal point test character reset
+          }
+    }
+  
+}
+
+//----------------------Limit Maximum Current Setting-----------------------------------------
+void maxConstantCurrentSetting (void) {
+  if (Mode == "CC" && reading > CurrentCutOff){           //Limit maximum Current Setting
+  reading = CurrentCutOff;
+  encoderPosition = (CurrentCutOff * 1000);               //keep encoder position value at maximum Current Limit
+  lcd.setCursor(0,3);
+  lcd.print("                    ");                      //20 spaces to clear last line of LCD 
+  }
+
+  if (Mode == "CP" && reading > PowerCutOff) {             //Limit maximum Current Setting
+        reading = PowerCutOff;
+        encoderPosition = (PowerCutOff * 1000);            //keep encoder position value at maximum Current Limit
+        lcd.setCursor(0,3);
+        lcd.print("                    ");                   //20 spaces to clear last line of LCD 
+    }
+
+   if (Mode == "CR" && reading > ResistorCutOff ) {             //Limit maximum Current Setting
+        reading = ResistorCutOff;
+        encoderPosition = (ResistorCutOff * 1000);            //keep encoder position value at maximum Current Limit
+        lcd.setCursor(0,3);
+        lcd.print("                    ");                   //20 spaces to clear last line of LCD 
+    }
+
+}
+
+//----------------------Power Level Cutoff Routine-------------------------------------------
+void powerLevelCutOff (void) {
+  if (ActualPower  > PowerCutOff){                        //Check if Power Limit has been exceed
+  reading = 0;
+  encoderPosition = 0; 
+  lcd.setCursor(0,3);
+  lcd.print("                    ");
+  lcd.setCursor(0,3);
+  lcd.print("Exceeded Power");
+  lcd.setCursor(8,0);
+  lcd.print("OFF");
+  toggle = false;                                         //switch Load Off
+  }
+}
+
+//----------------------Battery Constant Current Limit Value------------------------------------------
+void batteryCurrentLimitValue (void) {
+  if (Mode == "BC" && reading > MaxBatteryCurrent){
+  reading = MaxBatteryCurrent;
+  encoderPosition = (MaxBatteryCurrent*1000);            //keep encoder position value at 1000mA
+  }
+}
+
+//----------------------Display Rotary Encoder Input Reading on LCD---------------------------
+void displayEncoderReading (void) {
+
+    lcd.setCursor(8,2);                                      //start position of setting entry
+
+    if ( ( Mode == "CP" || Mode == "CR" ) && reading < 100 ) {
+        lcd.print("0");
+    }
+    
+    if (reading < 10) {                                      //add a leading zero to display if reading less than 10
+        lcd.print("0"); 
+    }
+
+    if ( Mode == "CP" || Mode == "CR" ) {
+        lcd.print (reading, 2);                              //show input reading from Rotary Encoder on LCD
+    } else {
+        lcd.print (reading, 3);
+    }
+    lcd.setCursor (CP, 2);                                   //sets cursor position
+    lcd.cursor();                                            //show cursor on LCD
+}
+
+//--------------------------Cursor Position-------------------------------------------------------
+//Change cursor the position routine
+void CursorPosition(void) {
+
+    // Defaults for two digits before decimal and 3 after decimal point
+    int unitPosition = 9;
+
+    //Power and Resistance modes can be 3 digit before decimal but only 2 decimals
+    if ( Mode == "CP" || Mode == "CR" ) {
+        unitPosition = 10;        
+    }
+
+    if (digitalRead(CursorPos) == LOW) {
+    
+        delay(200);                                          //simple key bounce delay  
+        CP = CP + 1;
+        if (CP == unitPosition + 1 ) {
+            CP = CP + 1;
+        }
+    }
+    
+    if (CP > 13)  { CP = unitPosition; }                     //No point in turning tens and hundreds
+    if (CP == unitPosition +4 ) { factor = 1; }
+    if (CP == unitPosition +3 ) { factor = 10; }
+    if (CP == unitPosition +2 ) { factor = 100; }
+    if (CP == unitPosition )    { factor = 1000; }
+}
+
+//---------------------------------------------Read Voltage and Current--------------------------------------------------------------
+void readVoltageCurrent (void) {
+  
+  MCP342x::Config status;
+// Initiate a conversion; convertAndRead() will wait until it can be read
+  adc.convertAndRead(MCP342x::channel1, MCP342x::oneShot,
+           MCP342x::resolution16, MCP342x::gain1,                         //"gain1" means we have select the input amp of the ADC to x1
+           1000000, voltage, status);
+  
+// Initiate a conversion; convertAndRead() will wait until it can be read
+  adc.convertAndRead(MCP342x::channel2, MCP342x::oneShot,
+           MCP342x::resolution16, MCP342x::gain4,                         //"gain4" means we have select the input amp of the ADC to x4
+           1000000, current, status);
+  
+}
+
+//-----------------------------------Calculate Actual Voltage and Current and display on LCD-----------------------------------------
+void ActualReading(void) {
+
+  ActualCurrent = (((current*2.048)/32767) * 2.5);        //calculate load current
+  currentDisplayCal();                                    //LCD display current calibration correction
+  ActualVoltage = (((voltage*2.048)/32767) * 50.4);       //calculate load voltage upto 100v (was 50)
+  ActualPower = ActualVoltage*ActualCurrent;
+
+  if (ActualPower <=0){
+    ActualPower = 0;
+  }
+
+ if (ActualVoltage <=0.0){                              //added to prevent negative readings on LCD due to error
+  ActualVoltage = 0.0;
+ }
+ if (ActualCurrent <= 0.0){                             //added to prevent negative readings on LCD due to error
+  ActualCurrent = 0.0;
+ }
+ 
+ lcd.setCursor(0,1);
+    
+    if ( ActualCurrent < 10.0 ) {
+        lcd.print(ActualCurrent,3);
+    } else {
+        lcd.print(ActualCurrent,2);
+    }
+    
+    lcd.print("A");
+    lcd.print(" ");
+    
+    if (ActualVoltage < 10.0) {
+        lcd.print(ActualVoltage, 3);
+    } else {
+        lcd.print(ActualVoltage, 2);
+    }    
+
+    lcd.print("V");
+    lcd.print(" ");
+     
+    if (ActualPower < 100 ) {
+        lcd.print(ActualPower,2);
+    } else {
+        lcd.print(ActualPower,1);
+    }
+    lcd.print("W");
+    lcd.print(" ");
+}
+
+//-----------------------DAC Control Voltage for Mosfet---------------------------------------
+void dacControlVoltage (void) {
+  if (Mode == "CC"){
+  setCurrent = reading*1000;                                //set current is equal to input value in Amps
+  setReading = setCurrent;                                  //show the set current reading being used
+  setControlCurrent = setCurrent * setCurrentCalibrationFactor;
+  controlVoltage = setControlCurrent; 
+  }
+
+  if (Mode == "CP"){
+  setPower = reading*1000;                                  //in Watts
+  setReading = setPower;
+  setCurrent = setPower/ActualVoltage;
+  setControlCurrent = setCurrent * setCurrentCalibrationFactor;
+  controlVoltage = setControlCurrent;                       //
+  }
+
+  if (Mode == "CR"){
+  setResistance = reading;                                  //in ohms
+  setReading = setResistance;
+  setCurrent = (ActualVoltage)/setResistance*1000;
+  setControlCurrent = setCurrent * setCurrentCalibrationFactor;
+  controlVoltage = setControlCurrent; 
+  }
+
+if (Mode == "TC" || Mode == "TP" || Mode == "TT" || Mode == "TL"){                            //Transient Modes
+  setControlCurrent = (setCurrent * 1000) * setCurrentCalibrationFactor;
+  controlVoltage = setControlCurrent; 
+  }
+
+}
+
+//-------------------------------------Battery Capacity Discharge Routine----------------------------------------------------
+void batteryCapacity (void) {
+  if (Mode == "BC"){
+    
+    setCurrent = reading*1000;                             //set current is equal to input value in Amps
+    setReading = setCurrent;                               //show the set current reading being used
+    setControlCurrent = setCurrent * setCurrentCalibrationFactor;
+    controlVoltage = setControlCurrent;
+
+    lcd.setCursor(0,3);
+    lcd.print (timer.getTime());                           //start clock and print clock time
+
+    Seconds = timer.getTotalSeconds();                     //get totals seconds
+  
+    LoadCurrent = ActualCurrent;                           //if timer still running use present Actual Current reading
+    if (timer.status() == 2){                              //if timer is halted then use last Actual Current reading before timer stopped
+      LoadCurrent = BatteryCurrent;
+      }
+ 
+    BatteryLife = (LoadCurrent*1000)*(Seconds/3600);       //calculate battery capacity in mAh
+    lcd.setCursor(9,3);
+    BatteryLife = round(BatteryLife);
+
+    if(BatteryLife >= BatteryLifePrevious){                //only update LCD (mAh) if BatteryLife has increased
+  
+      if (BatteryLife < 10) {                              //add a 3 leading zero to display if reading less than 10
+      lcd.print("000");
+      }
+
+      if (BatteryLife >= 10 && BatteryLife <100){          //add a 2 leading zero to display
+      lcd.print("00");  
+      }
+
+      if (BatteryLife >= 100 && BatteryLife <1000){        //add a 1 leading zero to display
+      lcd.print("0"); 
+      }
+  
+    lcd.print(BatteryLife,0);
+    lcd.setCursor(13,3);
+    lcd.print("mAh");
+    BatteryLifePrevious = BatteryLife;                      //update displayed battery capacity on LCD
+    } 
+  }
+
+
+  if (Mode == "BC" && ActualVoltage <= BatteryCutoffVolts){ //stops clock if battery reached cutoff level and switch load off
+
+  BatteryCurrent = ActualCurrent;
+  dac.setVoltage(0,false);                                  //reset DAC to zero for no output current set at switch on                                             
+  toggle = false;                                           //Load is toggled OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");                                         //indicate that LOAD is off at start up
+  timer.stop();
+  }
+
+      if (Mode == "BC" && Load == 1){                       //Routine used for data logging in Battery Capacity Mode
+          if (Seconds != SecondsLog){                       //only send serial data if time has changed
+            SecondsLog = Seconds;
+            Serial.print (SecondsLog);                    //sends serial data of time in seconds
+            Serial.print (",");                             //sends a comma as delimiter for logged data
+            Serial.println (ActualVoltage);                   //sends serial data of Voltage reading         
+              }
+          }
+
+}
+
+//--------------------------------------------------Fan Control----------------------------------------------------------
+void fanControl (void) {
+  temp = analogRead(temperature);
+  temp = temp * 0.107421875;                                // convert to Celsius
+  
+  if (temp >= 40){                                        //if temperature 40 degree C or above turn fan on.
+    digitalWrite(fan, HIGH); 
+  }  else {
+    digitalWrite(fan, LOW);                               //otherwise turn fan turned off
+  }
+  
+  lcd.setCursor(16,0);
+  lcd.print(temp);                                        //display temperature of heatsink on LCD
+  lcd.print((char)0xDF);
+  lcd.print("C");
+
+}
+
+  
+//-----------------------Toggle Current Load ON or OFF------------------------------
+void LoadSwitch(void) {
+  
+  delay(200);                                              //simple key bounce delay 
+ 
+    if(toggle)
+    {
+      lcd.setCursor(8,0);
+      lcd.print("OFF");
+      current_instruction = 0;                            //reset current instruction for Transient List Mode to zero
+      last_time = 0;                                      //reset last time to zero
+      transientPeriod = 0;                                //reset transient period time to zero
+      setCurrent = 0;                                     //reset setCurrent to zero
+      toggle = !toggle;
+      Load = 0;        
+    }
+    else
+    {
+      lcd.setCursor(8,0);
+      lcd.print("ON ");
+      lcd.setCursor(0,3);
+      lcd.print("                    ");                 //clear bottom line of LCD
+      toggle = !toggle;
+      Load = 1;
+    }
+}
+
+//-----------------------Select Constant Current LCD set up--------------------------------
+void Current(void) {
+  Mode = ("CC");
+  lcd.setCursor(0,0);
+  lcd.print("DC LOAD");  
+  lcd.setCursor(0,2);
+  lcd.print("                ");
+  lcd.setCursor(0,2);
+  lcd.print("Set I = ");
+  lcd.setCursor(16,2);
+  lcd.print("    ");
+  lcd.setCursor(14,2);
+  lcd.print("A");
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("                    ");                    //20 spaces so as to allow for Load ON/OFF to still show
+  CP = 9;                                               //sets cursor starting position to units.
+}
+
+//----------------------Select Constant Power LCD set up------------------------------------
+void Power(void) {
+  Mode = ("CP");
+  lcd.setCursor(0,0);
+  lcd.print("DC LOAD");
+  lcd.setCursor(0,2);
+  lcd.print("                ");
+  lcd.setCursor(0,2);
+  lcd.print("Set W = ");
+  lcd.setCursor(16,2);
+  lcd.print("    ");
+  lcd.setCursor(14,2);
+  lcd.print("W");
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("                    ");                    //20 spaces so as to allow for Load ON/OFF to still show
+  CP = 10;                                               //sets cursor starting position to units.
+}
+
+//----------------------- Select Constant Resistance LCD set up---------------------------------------
+void Resistance(void) {
+  Mode = ("CR");
+  lcd.setCursor(0,0);
+  lcd.print("DC LOAD");  
+  lcd.setCursor(0,2);
+  lcd.print("                ");
+  lcd.setCursor(0,2);
+  lcd.print("Set R = ");
+  lcd.setCursor(16,2);
+  lcd.print("    ");
+  lcd.setCursor(14,2);
+  lcd.print((char)0xF4);
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("                    ");                    //20 spaces so as to allow for Load ON/OFF to still show
+  CP = 10;                                               //sets cursor starting position to units.
+}
+
+//----------------------- Select Battery Capacity Testing LCD set up---------------------------------------
+void BatteryCapacity(void) {
+  Mode = ("BC");
+  lcd.setCursor(0,0);
+  lcd.print("BATTERY");
+  lcd.setCursor(0,2);
+  lcd.print("                ");
+  lcd.setCursor(0,2);
+  lcd.print("Set I = ");
+  lcd.setCursor(14,2);
+  lcd.print("A");
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("                    ");                    //20 spaces so as to allow for Load ON/OFF to still show
+}
+
+//----------------------Battery Type Selection Routine------------------------------------------------
+void batteryType (void) {
+  exitMode = 0;                                         //reset EXIT mode
+  lcd.noCursor();                                       //switch Cursor OFF for this menu               
+  lcd.clear();
+  lcd.setCursor(0,0);
+  lcd.print("Select Battery Type");  
+  lcd.setCursor(0,1);
+  lcd.print("1=LiPo/Li-Ion 2=LiFe");
+  lcd.setCursor(0,2);
+  lcd.print("3=NiCd/NiMH   4=ZiZn");
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("5=Set Voltage 6=Exit");                    //20 spaces so as to allow for Load ON/OFF to still show
+
+  customKey = customKeypad.waitForKey();                //stop everything till the user press a key.
+
+  if (customKey == '1'){
+  BatteryCutoffVolts = LiPoCutOffVoltage;
+  BatteryType = ("LiPo");
+    }
+
+  if (customKey == '2'){
+  BatteryCutoffVolts = LiFeCutOffVoltage;
+  BatteryType = ("LiFe");
+    }
+
+  if (customKey == '3'){
+  BatteryCutoffVolts = NiCdCutOffVoltage;
+  BatteryType = ("NiCd");  
+    }
+
+  if (customKey == '4'){
+  BatteryCutoffVolts = ZiZnCutOffVoltage;
+  BatteryType = ("ZiZn"); 
+    }
+
+  if (customKey == '5'){ 
+  BatteryType = ("SetV");
+    }
+
+  if (customKey == '6'){                                  //Exit selection screen
+  exitMode = 1;
+    }
+
+  if (customKey == '7' || customKey == '8' || customKey == '9' || customKey == '0' || customKey == 'A' || customKey == 'B' || customKey == 'C' || customKey == 'D' || customKey == '*' || customKey == '#' || customKey == 'E' || customKey == 'F' || customKey == '<' || customKey == '>' ){
+  batteryType();                                                      //ignore other keys
+    }
+
+  if(BatteryType == "SetV" && exitMode != 1){
+  setBatteryCutOff();
+    }
+
+  batteryTypeSelected();                                    //briefly display battery type selected and discharge cut off voltage
+
+  lcd.clear();
+
+}
+
+//--------------------------Set DAC Voltage--------------------------------------------
+void dacControl (void) {
+  if (!toggle){
+  dac.setVoltage(0,false);                                 //set DAC output voltage to 0 if Load Off selected
+    if(Mode == "BC" && ActualVoltage >= BatteryCutoffVolts && timer.status() == 1){
+    timer.stop();
+    }
+  
+  }else{
+  //Serial.println("Control Voltage");                    //used for testing only
+  //Serial.println(controlVoltage);                       //used for testing only
+  dac.setVoltage(controlVoltage,false);                   //set DAC output voltage for Range selected
+    if(Mode == "BC" && ActualVoltage >= BatteryCutoffVolts && timer.status() != 1){
+    timer.start();
+    }
+  }
+}
+
+//--------------------------Battery Selected Information--------------------------------------------
+void batteryTypeSelected (void) {
+  if (exitMode !=1){                                      //if battery selection was EXIT then skip this routine
+  lcd.clear();
+  lcd.setCursor(2,0);
+  lcd.print("Battery Selected");
+  lcd.setCursor(8,1);
+  lcd.print(BatteryType);                                 //display battery type selected
+  lcd.setCursor(2,2);
+  lcd.print("Discharge Cutoff");
+  lcd.setCursor(6,3);
+  lcd.print(BatteryCutoffVolts);                          //display battery discharge cut off voltage
+  lcd.print(" volts");                                    
+  delay(3000);
+  }
+}
+
+//--------------------------Set Battery Cut-Off Voltage--------------------------------------------
+void setBatteryCutOff (void) {
+
+  lcd.clear();
+  lcd.setCursor(4,0);
+  lcd.print("Enter Battery");
+  lcd.setCursor(3,1);
+  lcd.print("Cut-Off Voltage");
+  y = 8;
+  z = 8;
+  r = 2;
+
+  inputValue();
+  BatteryCutoffVolts = x;
+
+  lcd.clear();
+}
+
+//------------------------Key input used for Battery Cut-Off and Transient Mode------------------------
+void inputValue (void){
+
+ while(customKey != 'F'){               //check if enter pressed (was previously #)
+  
+  customKey = customKeypad.getKey();
+  if(customKey >= '0' && customKey <= '9'){               //check for keypad number input
+       numbers[index++] = customKey;
+       numbers[index] = '\0';
+       lcd.setCursor(z,r);                              
+       lcd.print(customKey);                              //show number input on LCD
+       z = z+1;
+     }
+  
+  if(customKey == '>'){                                   //Decimal point
+      if (decimalPoint != ('>')){                         //test if decimal point entered twice - if so ski
+      numbers[index++] = '.';
+      numbers[index] = '\0';
+      lcd.setCursor(z,r);
+      lcd.print(".");
+      z = z+1;
+      decimalPoint = ('>');                               //used to indicate decimal point has been input
+        }
+      }
+
+ if(customKey == '<'){                                    //clear entry
+    index = 0;
+    z = y;
+    lcd.setCursor(y,r);
+    lcd.print("     ");
+    numbers[index] = '\0';                                //
+    decimalPoint = (' ');                                 //clear decimal point test character reset
+  }
+
+ }
+ 
+  if(customKey == 'F') {                                  //enter value 
+    x = atof(numbers);     
+    index = 0;
+    numbers[index] = '\0';
+    decimalPoint = (' ');                                 //clear decimal point test character reset
+  }
+}
+
+//----------------------------------------Transient Mode--------------------------------------------
+void transientMode (void) {
+
+if(Mode != "TL"){
+
+  y = 11;
+  z = 11;
+  
+  lcd.noCursor();                                       //switch Cursor OFF for this menu               
+  lcd.clear();
+  lcd.setCursor(3,0);
+  lcd.print("Transient Mode");  
+  lcd.setCursor(0,1);
+  lcd.print("Set Low  I=");
+  lcd.setCursor(19,1);
+  lcd.print("A");
+  r = 1;
+  inputValue();
+  
+  if(x >= CurrentCutOff){
+    LowCurrent = CurrentCutOff;
+  }else{
+    LowCurrent = x;
+  }
+  lcd.setCursor(11,r);
+  lcd.print(LowCurrent,3);
+  
+  customKey = '0';
+
+  z = 11;
+
+  lcd.setCursor(0,2);
+  lcd.print("Set High I=");
+  lcd.setCursor(19,2);
+  lcd.print("A");
+  r = 2;
+  inputValue();
+  if(x >= CurrentCutOff){
+    HighCurrent = CurrentCutOff;
+  }else{
+    HighCurrent = x;
+  }
+  lcd.setCursor(11,r);
+  lcd.print(HighCurrent,3);
+
+  customKey = '0';
+
+  if(Mode == "TC" || Mode == "TP"){
+  z = 11;
+
+  lcd.setCursor(0,3);
+  lcd.print("Set Time  = ");
+  lcd.setCursor(16,3);
+  lcd.print("mSec");
+  r = 3;
+  inputValue();
+  transientPeriod = x;
+  lcd.setCursor(11,r);
+  lcd.print(transientPeriod);
+  }else{
+  lcd.setCursor(0,3);
+  lcd.print("                    ");
+  }
+
+  lcd.clear();
+
+  toggle = false;                                           //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");                                         //print on display OFF
+    }else{  
+  transientListSetup();
+  lcd.clear();
+ 
+  toggle = false;                                           //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");                                         //print on display OFF
+  }
+}
+
+//----------------------------------------Transient Type Selection--------------------------------------------
+void transientType (void) {
+  toggle = false;                                         //switch Load OFF
+  exitMode = 0;                                           //reset EXIT mode
+  lcd.noCursor();                                         //switch Cursor OFF for this menu               
+  lcd.clear();
+  lcd.setCursor(3,0);
+  lcd.print("Transient Mode");  
+  lcd.setCursor(0,1);
+  lcd.print("1 = Continuous");
+  lcd.setCursor(0,2);
+  lcd.print("2 = Toggle");
+  lcd.setCursor(11,2);                                    //
+  lcd.print("3 = Pulse");                                 //
+  lcd.setCursor(0,3);                                     //
+  lcd.print("4 = List");                                  //
+  lcd.setCursor(11,3);                                    //
+  lcd.print("5 = Exit");                                  //
+
+  customKey = customKeypad.waitForKey();                  //stop everything till the user press a key.
+
+  if (customKey == '1'){
+  Mode = ("TC"); 
+    }
+
+  if (customKey == '2'){
+   Mode = ("TT");
+    }
+
+  if (customKey == '3'){
+  Mode = ("TP");  
+    }
+
+  if (customKey == '4'){
+  Mode = ("TL");  
+    }
+
+  if (customKey == '5'){                                  //Exit selection screen
+  exitMode = 1;
+    }
+
+  if (customKey == '6' || customKey == '7' || customKey == '8' || customKey == '9' || customKey == '0' || customKey == 'A' || customKey == 'B' || customKey == 'C' || customKey == 'D' || customKey == '*' || customKey == '#' || customKey == 'E' || customKey == 'F' || customKey == '<' || customKey == '>' ){
+  transientType();                                                      //ignore other keys
+  
+    }
+lcd.clear();
+
+if (exitMode == 1){                                       //if NO Transient Mode type selected revert to CC Mode
+    lcd.setCursor(8,0);
+    lcd.print("OFF");
+    Current();                                            //if selected go to Constant Current Selected routine
+    encoderPosition = 0;                                  //reset encoder reading to zero
+    customKey = 'A';
+      }else{
+    transientMode();
+      }
+ }
+ 
+//----------------------------------------Transient--------------------------------------------
+void transient (void) {
+  
+  if(Mode == "TC" || Mode == "TP" || Mode == "TT" || Mode == "TL"){
+  lcd.noCursor();                                         //switch Cursor OFF for this menu 
+  lcd.setCursor(0,0);
+  lcd.print("DC LOAD");
+  
+  if(Mode != "TL"){
+  lcd.setCursor(0,2);
+  lcd.print("Lo=");
+  lcd.setCursor(3,2);
+  lcd.print(LowCurrent,3);
+  lcd.setCursor(8,2);
+  lcd.print("A");
+  lcd.setCursor(11,2);
+  lcd.print("Hi=");
+  lcd.setCursor(14,2);                                    //
+  lcd.print(HighCurrent,3);
+  lcd.setCursor(19,2);
+  lcd.print("A");
+  }else{
+    delay(1);
+  }
+
+
+  if(Mode == "TC" || Mode == "TP" || Mode == "TL"){
+  lcd.setCursor(0,3);                                     //
+  lcd.print("Time = ");
+  lcd.setCursor(7,3);
+  lcd.print(transientPeriod);
+  lcd.setCursor(12,3);                                    //
+  lcd.print("mSecs");
+    }else{
+     lcd.setCursor(0,3);
+     lcd.print("  ");
+    }
+  }
+delay(1);
+}
+
+//-------------------------------------Transcient List Setup-------------------------------------------
+void transientListSetup(){
+
+  lcd.noCursor();                                                 
+  lcd.clear();
+  lcd.setCursor(0,0);
+  lcd.print("Setup Transient List");
+  lcd.setCursor(0,1);
+  lcd.print("Enter Number in List");
+  lcd.setCursor(0,2);
+  lcd.print("(between 2 to 10 max"); 
+  y = 0;
+  z = 0;
+  r = 3;
+  inputValue();
+  total_instructions = int(x-1);
+  customKey = '0';
+  lcd.clear();
+  
+    for(int i=0; i<=(total_instructions); i++){
+      lcd.setCursor(0,0);
+      lcd.print("Set Current ");
+      lcd.print(i+1);
+      lcd.setCursor(16,1);
+      lcd.print("A");
+      y = 0;
+      z = 0;
+      r = 1;
+      inputValue();            //get the users input value
+      transientList[i][0] = x; //store the users entered value in the transient list 
+      customKey = '0';
+      lcd.setCursor(0,2);
+      lcd.print("Set Time ");
+      lcd.print(i+1);
+      lcd.setCursor(16,3);
+      lcd.print("mSec");
+      y = 0;
+      z = 0;
+      r = 3;
+      inputValue();            //get the users input value
+      transientList[i][1] = x; //store the users entered value in the transient list
+      customKey = '0';
+      lcd.clear();   
+  }
+  current_instruction = 0;      //start at first instrution
+}
+
+//-------------------------------------Transcient Load Toggel-------------------------------------------
+void transientLoadToggle(){
+
+  if(Mode == "TC"){
+  current_time = micros();                              //get the current time in micro seconds()
+  if (last_time == 0){
+    last_time = current_time;
+  } else {
+    switch (transient_mode_status){
+      case (false):
+          // we are in the low current setting
+          if ((current_time - last_time) >= (transientPeriod * 1000.0)){
+             transientSwitch(LowCurrent, true);  
+          }
+        break;
+      case (true):
+          // we are in the high current setting 
+          if ((current_time - last_time) >= (transientPeriod * 1000.0)){
+            transientSwitch(HighCurrent, true);            
+          }
+        break; 
+      } 
+     }
+    }
+
+
+  if(Mode == "TP"){
+    current_time = micros();                            //get the current time in micro seconds()
+    if (last_time == 0){
+        last_time = current_time;
+        transientSwitch(LowCurrent, true);
+    }
+    if (digitalRead(TriggerPulse) == LOW){
+      // a trigger pluse is received
+      // set to the high current
+      transientSwitch(HighCurrent, true); 
+    } else {
+        if ((current_time - last_time) >= (transientPeriod * 1000.0)){
+            transientSwitch(LowCurrent, true);            
+        }
+      }  
+  }
+
+
+ if(Mode == "TT"){          // this function will toggle between high and low current when the trigger pin is taken low
+  if (digitalRead(TriggerPulse) == LOW){
+    switch (transient_mode_status){
+      case (false):
+        transientSwitch(LowCurrent, true);
+        delay(200);         //added to prevent key bounce when transient button used (date of addition 31-03-2018)
+        break;
+      case (true):
+        transientSwitch(HighCurrent, true);
+        delay(200);         //added to prevent key bounce when transient button used (date of addition 31-03-2018)   
+        break;
+      }
+    }
+  }
+
+
+if(Mode == "TL"){
+  if (Load == 1){                                                 //Only perform Transient List if Load is ON
+   current_time = micros();                                       //get the current time in micro seconds()
+    if (last_time == 0){
+      last_time = current_time;
+      transientPeriod = transientList[current_instruction][1];    //Time data for LCD display
+      transientSwitch(transientList[current_instruction][0], false);
+    }
+    if((current_time - last_time) >= transientList[current_instruction][1] * 1000){     //move to next list instruction
+        current_instruction++;
+        if(current_instruction > total_instructions){
+          current_instruction = 0;
+        }
+      transientPeriod = transientList[current_instruction][1];   //Time data for LCD display
+      transientSwitch(transientList[current_instruction][0], false);
+      }
+    }
+  }
+
+}
+
+//-------------------------------------Transcient Switch-------------------------------------------
+void transientSwitch(float current_setting, boolean toggle_status){
+  if (toggle_status){
+  transient_mode_status = !transient_mode_status;
+  }
+  setCurrent = current_setting;
+  //Serial.print("set current = ");                     //used for testing only
+  //Serial.println(setCurrent);                         //used for testing only
+  last_time = current_time;
+}
+
+//-------------------------------------User set up for limits-------------------------------------------------
+void userSetUp (void) {
+  y = 14;
+  z = 14;
+  
+  lcd.noCursor();                                       //switch Cursor OFF for this menu               
+  lcd.clear();
+  lcd.setCursor(4,0);
+  lcd.print("User Set-Up");
+  lcd.setCursor(0,1);
+  lcd.print("Current Limit=");
+  lcd.setCursor(19,1);
+  lcd.print("A");
+  r = 1;
+  inputValue();
+  CurrentCutOff = x;
+  EEPROM.write(0x00, CurrentCutOff);
+  lcd.setCursor(14,r);
+  lcd.print(CurrentCutOff);
+  
+  customKey = '0';
+
+  z = 14;
+
+  lcd.setCursor(0,2);
+  lcd.print("Power Limit  =");
+  lcd.setCursor(19,2);
+  lcd.print("W");
+  r = 2;
+  inputValue();
+  PowerCutOff = x;
+  EEPROM.write(0x20, PowerCutOff);              //
+  lcd.setCursor(14,r);
+  lcd.print(PowerCutOff);
+
+  customKey = '0';
+
+  z = 14;
+
+  lcd.setCursor(0,3);
+  lcd.print("Temp. Limit  =");
+  lcd.setCursor(18,3);
+  lcd.print((char)0xDF);
+  lcd.print("C");
+  r = 3;
+  inputValue();
+  tempCutOff = x;
+  EEPROM.write(0x40, tempCutOff);
+  lcd.setCursor(14,r);
+  lcd.print(tempCutOff);
+
+    lcd.clear();
+
+    lcd.setCursor(8,0);
+    lcd.print("OFF");
+    Current();                                            //if selected go to Constant Current Selected routine
+    encoderPosition = 0;                                  //reset encoder reading to zero
+    customKey = 'A';
+}
+
+//------------------------------------------High Temperature Cut-Off--------------------------------------------------------------
+void temperatureCutOff (void){
+  if (temp >= tempCutOff){                                 //if Maximum temperature is exceeded
+  reading = 0;
+  encoderPosition = 0; 
+  lcd.setCursor(0,3);
+  lcd.print("                    ");
+  lcd.setCursor(0,3);
+  lcd.print("Over Temperature");
+  lcd.setCursor(8,0);
+  lcd.print("OFF");
+  toggle = false;                                         //switch Load Off
+  }
+}
+
+//-----------------------------------------Current Read Calibration for LCD Display --------------------------------------------
+void currentDisplayCal (void){
+
+  if(ActualCurrent <= 0){
+    ActualCurrent = 0;
+  }else if(Load == 0){
+    ActualCurrent = 0;
+  }else{
+  ActualCurrent = ActualCurrent + displayCurrentCal;
+  }
+
+/*  if (ActualCurrent <= 0.5)
+    {
+    ActualCurrent = (ActualCurrent +(displayCurrentCal * 3));
+    }
+    else if (ActualCurrent >= 0.5 && ActualCurrent <1.0)
+    {
+    ActualCurrent = (ActualCurrent + (displayCurrentCal * 2));
+    }
+    else if (ActualCurrent >= 1.0 && ActualCurrent <= 1.4)
+    {
+    ActualCurrent = (ActualCurrent + (displayCurrentCal));
+    }
+    else 
+    {
+    ActualCurrent = ActualCurrent;
+    }
+*/
+}
+  
+//-----------------------------Show limits Stored Data for Current, Power and Temp-----------------------------
+  void setupLimits (void){
+  lcd.clear();
+  lcd.setCursor(1,0);
+  lcd.print("Maximum Limits Set");
+  lcd.setCursor(0,1);
+  lcd.print("Current Limit=");
+  lcd.setCursor(17,1);
+  lcd.print("A");
+  lcd.setCursor(15,1);
+  CurrentCutOff = EEPROM.read(0x00);
+  lcd.print(CurrentCutOff);
+
+  lcd.setCursor(0,2);
+  lcd.print("Power Limit  =");
+  lcd.setCursor(17,2);
+  lcd.print("W");
+  lcd.setCursor(15,2);
+  PowerCutOff = EEPROM.read(0x20);
+  lcd.print(PowerCutOff);
+
+  lcd.setCursor(0,3);
+  lcd.print("Temp. Limit  =");
+  lcd.setCursor(17,3);
+  lcd.print((char)0xDF);
+  lcd.print("C");
+  tempCutOff = EEPROM.read(0x40);
+  lcd.setCursor(15,3);
+  lcd.print(tempCutOff);
+  }
+  
+  //---------------------------------------------------------------------------------------------------------

+ 11 - 0
sw/DC_LOAD/test/README

@@ -0,0 +1,11 @@
+
+This directory is intended for PlatformIO Test Runner and project tests.
+
+Unit Testing is a software testing method by which individual units of
+source code, sets of one or more MCU program modules together with associated
+control data, usage procedures, and operating procedures, are tested to
+determine whether they are fit for use. Unit testing finds problems early
+in the development cycle.
+
+More information about PlatformIO Unit Testing:
+- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html

+ 1390 - 0
sw/Electronic_Load_software_V35.ino

@@ -0,0 +1,1390 @@
+//SCULLCOM HOBBY ELECTRONICS
+//ELECTRONIC DC LOAD PROJECT
+//Software Version 35 (4x5 Matrix Keypad Version - modified key layout)
+//14th April 2018
+
+#include <SPI.h>                              //include SPI library (Serial Peripheral Interface)
+#include <Wire.h>                             //include I2C library
+#include <LiquidCrystal_I2C.h>                // F Malpartida's NewLiquidCrystal library
+                                              // https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads/NewliquidCrystal_1.3.4.zip
+#include <math.h>                             //
+#include <Adafruit_MCP4725.h>                 //Adafruit DAC library  https://github.com/adafruit/Adafruit_MCP4725
+#include <MCP342x.h>                          //Steve Marple library avaiable from    https://github.com/stevemarple/MCP342x
+#include <MCP79410_Timer.h>                   //Scullcom Hobby Electronics library  http://www.scullcom.com/MCP79410Timer-master.zip
+#include <EEPROM.h>                           //include EEPROM library used for storing setup data
+
+#include <Keypad.h>                           //http://playground.arduino.cc/Code/Keypad
+
+const byte ROWS = 5;                          //five rows
+const byte COLS = 4;                          //four columns
+
+//define the symbols on the buttons of the keypads
+char hexaKeys[ROWS][COLS] = {
+  {'<','0','>','F'},
+  {'7','8','9','E'},
+  {'4','5','6','D'},
+  {'1','2','3','C'},
+  {'A','B','#','*'}
+};
+
+byte rowPins[ROWS] = {9, 10, 11, 12, 14}; //connect to the row pin outs of the keypad
+byte colPins[COLS] = {5, 6, 7, 8}; //connect to the column pin outs of the keypad
+
+//initialize an instance of class NewKeypad
+Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
+char customKey;
+
+char decimalPoint;                            //used to test for more than one press of * key (decimal point)
+
+Adafruit_MCP4725 dac;                         //constructor
+
+uint8_t address = 0x68;                       //0x68 is the default address for the MCP3426 device
+MCP342x adc = MCP342x(address);
+
+const byte MCP79410_ADDRESS = 0x6f;           //0x6f is the default address for the MCP79410 Real Time Clock IC
+MCP79410_Timer timer = MCP79410_Timer(MCP79410_ADDRESS);
+
+//Set the pins on the I2C chip used for LCD connections
+//ADDR,EN,R/W,RS,D4,D5,D6,D7
+LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7);    //0x27 is the default address of the LCD with I2C bus module
+
+const byte pinA = 2;                          //digital pin (also interrupt pin) for the A pin of the Rotary Encoder (changed to digital pin 2)
+const byte pinB = 4;                          //digital pin for the B pin of the Rotary Encoder
+
+const byte CursorPos = 17;                    //analog pin A3 used as a digital pin to set cursor position (rotary encoder push button)
+const byte LoadOnOff = 15;                    //analog pin A1 used as a digital pin to set Load ON/OFF
+
+const byte TriggerPulse = 16;                 //analog pin A2 used as a digital pin for trigger pulse input in transient mode
+
+const byte fan = 3;                           //digital pin 3 for fan control output (changed to Digital pin 3)
+const byte temperature = A6;                  //analog pin used for temperature output from LM35 (was A0 previously but changed)
+int temp;                                     //
+
+float BatteryLife = 0;                        //
+float BatteryLifePrevious = 0;                //
+float Seconds = 0;                            //time variable used in Battery Capacity Mode (BC)
+float SecondsLog = 0;                         //variable used for data logging of the time in seconds
+float BatteryCutoffVolts;                     //used to set battery discharge cut-off voltage
+float MaxBatteryCurrent = 1.0;                //maximum battery current allowed for Battery Capacity Testing
+
+int stopSeconds;                              //store for seconds when timer stopped
+
+int CP = 8;                                   //cursor start position
+
+boolean toggle = false;                       //used for toggle of Load On/Off button
+
+unsigned long controlVoltage = 0;             //used for DAC to control MOSFET
+
+long current = 0;                             //variable used by ADC for measuring the current
+long voltage = 0;                             //variable used by ADC for measuring the voltage
+
+float reading = 0;                            //variable for Rotary Encoder value divided by 1000
+
+float setCurrent = 0;                         //variable used for the set current of the load
+float setPower = 0;                           //variable used for the set power of the load
+float setResistance = 0;                      //variable used for the set resistance of the load
+float setCurrentCalibrationFactor = 0.980;    //calibration adjustment - set as required if needed (was 1.000)
+
+float displayCurrentCal = 0.000;              //calibration correction for LCD current display (was 0.040)
+int Load = 0;                                 //Load On/Off flag
+
+float setControlCurrent = 0;                  //variable used to set the temporary store for control current required
+
+int VoltsDecimalPlaces = 3;                   //number of decimal places used for Voltage display on LCD
+
+float ActualVoltage = 0;                      //variable used for Actual Voltage reading of Load
+float ActualCurrent = 0;                      //variable used for Actual Current reading of Load
+float ActualPower = 0;                        //variable used for Actual Power reading of Load
+
+float ResistorCutOff = 999;                   //maximum Resistor we want to deal with in software
+float BatteryCurrent;                         //
+float LoadCurrent;                            //
+
+int CurrentCutOff = EEPROM.read(0x00);
+int PowerCutOff = EEPROM.read(0x20);
+int tempCutOff = EEPROM.read(0x40);
+
+int setReading = 0;                           //
+
+int ControlVolts = 0;                         //used to set output current
+float OutputVoltage = 0;                      //
+
+String Mode ="  ";                            //used to identify which mode
+
+int modeSelected = 0;                         //Mode status flag
+
+int lastCount = 50;                           //
+volatile float encoderPosition = 0;           //
+volatile unsigned long factor= 0;             //number of steps to jump
+volatile unsigned long encoderMax = 999000;   //sets maximum Rotary Encoder value allowed CAN BE CHANGED AS REQUIRED (was 50000)
+
+float LiPoCutOffVoltage = 3.0;                //set cutoff voltage for LiPo battery
+float LiFeCutOffVoltage = 2.8;                //set cutoff voltage for LiFe battery
+float NiCdCutOffVoltage = 1.0;                //set cutoff voltage for NiCd battery
+float ZiZnCutOffVoltage = 1.0;                //set cutoff voltage for ZiZn battery
+float PbAcCutOffVoltage = 1.75;               //set cutoff voltage for PbAc battery
+String BatteryType ="    ";
+
+byte exitMode = 0;                           //used to exit battery selection menu and return to CC Mode
+
+char numbers[10];                            //keypad number entry - Plenty to store a representation of a float
+byte index = 0;
+int z = 1;                                   //was previously 0
+float x = 0;
+int y = 0;
+int r = 0;
+
+float LowCurrent = 0;               //the low current setting for transcient mode
+float HighCurrent = 0;              //the high current setting for transcient mode
+unsigned long transientPeriod;      //used to store pulse time period in transcient pulse mode
+unsigned long current_time;         //used to store the current time in microseconds
+unsigned long last_time;            //used to store the time of the last transient switch in micro seconds
+boolean transient_mode_status;      //used to maintain the state of the trascient mode (false = low current, true = high current)
+
+float transientList [10][2];        //array to store Transient List data
+int total_instructions;             //used in Transient List Mode
+int current_instruction;            //used in Transient List Mode
+
+//--------------------------------Interrupt Routine for Rotary Encoder------------------------
+void isr()
+{
+  static unsigned long lastInterruptTime = 0;
+  unsigned long interruptTime = millis();
+
+  if (interruptTime - lastInterruptTime > 5) {  //
+    if (digitalRead(pinB) == LOW)
+    {
+      encoderPosition = encoderPosition - factor;
+    }else{
+      encoderPosition = encoderPosition + factor;
+    }
+    encoderPosition = min(encoderMax, max(0, encoderPosition));  // sets maximum range of rotary encoder
+    lastInterruptTime = interruptTime;
+  }
+    }
+//---------------------------------Initial Set up---------------------------------------
+void setup() {
+  Serial.begin(9600);                                      //used for testing only
+ 
+  Wire.begin();                                            //join i2c bus (address optional for master)
+  Wire.setClock(400000L);                                  //sets bit rate to 400KHz
+
+  MCP342x::generalCallReset();                             //Reset devices
+  delay(1);                                                //MC342x needs 300us to settle, wait 1ms - (may not be required)
+
+  pinMode (pinA, INPUT);
+  pinMode (pinB, INPUT);
+
+  pinMode (CursorPos, INPUT_PULLUP);
+  pinMode (LoadOnOff, INPUT_PULLUP);
+ 
+  pinMode (TriggerPulse, INPUT_PULLUP);
+
+  pinMode (fan, OUTPUT);
+  TCCR2B = (TCCR2B & 0b11111000) | 1;                      //change PWM to above hearing (Kenneth Larvsen recommendation)
+  pinMode (temperature, INPUT);
+ 
+  analogReference(INTERNAL);                               //use Arduino internal reference for tempurature monitoring
+
+  attachInterrupt(digitalPinToInterrupt(pinA), isr, LOW);
+
+  dac.begin(0x61);                                         //the DAC I2C address with MCP4725 pin A0 set high
+  dac.setVoltage(0,false);                                 //reset DAC to zero for no output current set at Switch On
+
+  lcd.begin(20, 4);                                        //set up the LCD's number of columns and rows 
+  lcd.setBacklightPin(3,POSITIVE);                         // BL, BL_POL
+  lcd.setBacklight(HIGH);                                  //set LCD backlight on
+ 
+  lcd.clear();                                             //clear LCD display
+  lcd.setCursor(6,0);                                      //set LCD cursor to column 0, row 4
+  lcd.print("SCULLCOM");                                   //print SCULLCOM to display with 5 leading spaces (you can change to your own)
+  lcd.setCursor(1,1);                                      //set LCD cursor to column 0, row 1 (start of second line)
+  lcd.print("Hobby Electronics");                          //print Hobby Electronics to display (you can change to your own)
+  lcd.setCursor(1,2);
+  lcd.print("DC Electronic Load"); //
+  lcd.setCursor(0,3);
+  lcd.print("Ver. 35 (5x4 Keypad)"); //
+  delay(2000);                                             //3000 mSec delay for intro display
+  lcd.clear();                                             //clear dislay
+  setupLimits();
+  delay(3000);
+  lcd.clear();
+
+  last_time = 0;                                           //set the last_time to 0 at the start (Transicent Mode)
+  transient_mode_status = false;                           //set the initial transient mode status (false = low, true = high);
+  setCurrent = LowCurrent;                                 //first set the current to the low current value (Transicent Mode)
+ 
+  lcd.setCursor(8,0);
+  lcd.print("OFF");                                        //indicate that LOAD is off at start up
+  Current();                                               //sets initial mode to be CC (Constant Current) at Power Up
+  
+  customKey = customKeypad.getKey();
+  
+}
+
+//------------------------------------------Main Program Loop---------------------------------
+void loop() {
+
+ if(CurrentCutOff > 5){                                 //Test and go to user set limits if required
+    userSetUp();
+     }else{
+  
+  readKeypadInput();                                     //read Keypad entry
+  
+  if (digitalRead(LoadOnOff) == LOW) {
+    LoadSwitch();                                          //Load on/off
+  }
+  
+  transient();                                           //test for Transient Mode
+  
+  lcd.setCursor(18,3);                                   //sets display of Mode indicator at bottom right of LCD
+  lcd.print(Mode);                                       //display mode selected on LCD (CC, CP, CR or BC)
+
+  if(Mode != "TC" && Mode != "TP" && Mode != "TT" && Mode != "TL"){      //if NOT transient mode then Normal Operation
+    reading = encoderPosition/1000;                        //read input from rotary encoder 
+    maxConstantCurrentSetting();                           //set maxiumum Current allowed in Constant Current Mode (CC)
+    powerLevelCutOff();                                    //Check if Power Limit has been exceeded
+  
+    temperatureCutOff();                                   //check if Maximum Temperature is exceeded
+  
+    batteryCurrentLimitValue();                            //Battery Discharge Constant Current Limit Value in BC Mode
+    displayEncoderReading();                               //display rotary encoder input reading on LCD
+    lastCount = encoderPosition;                           //store rotary encoder current position
+    CursorPosition();                                      //check and change the cursor position if cursor button pressed
+  }else{
+    transientLoadToggle();                                  //Start Transient Mode
+  }
+    
+  readVoltageCurrent();                                  //routine for ADC's to read actual Voltage and Current
+  ActualReading();                                       //Display actual Voltage, Current readings and Actual Wattage
+  
+  dacControl();
+  dacControlVoltage();                                   //sets the drive voltage to control the MOSFET
+
+  batteryCapacity();                                     //test if Battery Capacity (BC) mode is selected - if so action
+  fanControl();                                          //call heatsink fan control
+  }
+}
+//------------------------------------------------Read Keypad Input-----------------------------------------------------
+void readKeypadInput (void) {
+  customKey = customKeypad.getKey();
+  
+//  if (customKey != NO_KEY){                             //only used for testing keypad (uncomment if required for testing keypad)
+// Serial.print("customKey = ");                          //only used for testing keypad (uncomment if required for testing keypad)
+// Serial.println(customKey);                             //only used for testing keypad (uncomment if required for testing keypad)
+//  }                                                     //only used for testing keypad (uncomment if required for testing keypad)
+
+if(customKey == 'E'){                                     //check for Load on/off
+  LoadSwitch();
+}
+
+  if(customKey == 'D'){                                   //check if Set-Up Mode Selected 
+  delay(200);
+  toggle = false;                                         //switch Load OFF
+  userSetUp();
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point text character reset
+}
+ 
+  if(customKey == 'C'){                                   //check if Transient Mode Selected
+  toggle = false;                                         //switch Load OFF
+  transientType();
+ 
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point text character reset
+  }
+               
+  if(customKey == 'A'){                                   //check if Constant Current button pressed
+  toggle = false;                                         //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");
+  Current();                                              //if selected go to Constant Current Selected routine
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point test character reset
+  }
+         
+  if(customKey == 'B'){                                   //check if Constant Power button pressed
+  toggle = false;                                         //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF"); 
+  Power();                                                //if selected go to Constant Power Selected routine
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point test character reset
+  }
+          
+  if(customKey == '#'){                                   //check if Constant Resistance button pressed  
+  toggle = false;                                         //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");  
+  Resistance();                                           //if selected go to Constant Resistance Selected routine
+  encoderPosition = 0;                                    //reset encoder reading to zero
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point test character reset
+  }
+
+  if(customKey == '*'){                                   //check if Battery Capacity button pressed
+  dac.setVoltage(0,false);                                //Ensures Load is OFF - sets DAC output voltage to 0
+  toggle = false;                                         //switch Load OFF
+  batteryType();                                          //select battery type
+  index = 0;
+  z = 1;                                                  //sets column position for LCD displayed character
+  decimalPoint = (' ');                                   //clear decimal point test character reset
+
+    if (exitMode == 1){                                   //if NO battery type selected revert to CC Mode
+    lcd.setCursor(8,0);
+    lcd.print("OFF");
+    Current();                                            //if selected go to Constant Current Selected routine
+    encoderPosition = 0;                                  //reset encoder reading to zero
+    customKey = 'A';
+    }
+    else
+    {
+    lcd.setCursor(16,2);
+    lcd.print(BatteryType);                               //print battery type on LCD 
+    lcd.setCursor(8,0);
+    lcd.print("OFF");
+    timer.reset();                                        //reset timer
+    BatteryLifePrevious = 0;
+    CP = 9;                                               //set cursor position
+    BatteryCapacity();                                    //go to Battery Capacity Routine
+    }
+  }
+
+if (Mode != "BC"){
+
+  if(customKey >= '0' && customKey <= '9'){               //check for keypad number input
+       numbers[index++] = customKey;
+       numbers[index] = '\0';
+       lcd.setCursor(z,3);                                //                   
+       lcd.print(customKey);                              //show number input on LCD
+       z = z+1;
+     }
+  
+  if(customKey == '>'){                                   //check if decimal button key pressed
+      if (decimalPoint != ('>')){                         //test if decimal point entered twice - if so skip 
+      numbers[index++] = '.';
+      numbers[index] = '\0';
+      lcd.setCursor(z,3);
+      lcd.print(".");
+      z = z+1;
+      decimalPoint = ('>');                             //used to indicate decimal point has been input
+        }
+      }
+
+  if(customKey == '<'){                                 //clear input entry
+     index = 0;
+     z = 1;                                             //sets column position for LCD displayed character
+     lcd.setCursor(z,3);
+     lcd.print("     ");
+     numbers[index] = '\0';                             //
+     decimalPoint = (' ');                              //clear decimal point test character reset
+    }
+
+  if(customKey == 'F') {                                //use entered number
+    x = atof(numbers);     
+         reading = x;
+         encoderPosition = reading*1000;
+         index = 0;
+         numbers[index] = '\0';
+         z = 1;                                         //sets column position for LCD displayed character
+         lcd.setCursor(0,3);
+         lcd.print("        ");
+         decimalPoint = (' ');                          //clear decimal point test character reset
+          }
+    }
+  
+}
+
+//----------------------Limit Maximum Current Setting-----------------------------------------
+void maxConstantCurrentSetting (void) {
+  if (Mode == "CC" && reading > CurrentCutOff){           //Limit maximum Current Setting
+  reading = CurrentCutOff;
+  encoderPosition = (CurrentCutOff * 1000);               //keep encoder position value at maximum Current Limit
+  lcd.setCursor(0,3);
+  lcd.print("                    ");                      //20 spaces to clear last line of LCD 
+  }
+
+  if (Mode == "CP" && reading > PowerCutOff) {             //Limit maximum Current Setting
+        reading = PowerCutOff;
+        encoderPosition = (PowerCutOff * 1000);            //keep encoder position value at maximum Current Limit
+        lcd.setCursor(0,3);
+        lcd.print("                    ");                   //20 spaces to clear last line of LCD 
+    }
+
+   if (Mode == "CR" && reading > ResistorCutOff ) {             //Limit maximum Current Setting
+        reading = ResistorCutOff;
+        encoderPosition = (ResistorCutOff * 1000);            //keep encoder position value at maximum Current Limit
+        lcd.setCursor(0,3);
+        lcd.print("                    ");                   //20 spaces to clear last line of LCD 
+    }
+
+}
+
+//----------------------Power Level Cutoff Routine-------------------------------------------
+void powerLevelCutOff (void) {
+  if (ActualPower  > PowerCutOff){                        //Check if Power Limit has been exceed
+  reading = 0;
+  encoderPosition = 0; 
+  lcd.setCursor(0,3);
+  lcd.print("                    ");
+  lcd.setCursor(0,3);
+  lcd.print("Exceeded Power");
+  lcd.setCursor(8,0);
+  lcd.print("OFF");
+  toggle = false;                                         //switch Load Off
+  }
+}
+
+//----------------------Battery Constant Current Limit Value------------------------------------------
+void batteryCurrentLimitValue (void) {
+  if (Mode == "BC" && reading > MaxBatteryCurrent){
+  reading = MaxBatteryCurrent;
+  encoderPosition = (MaxBatteryCurrent*1000);            //keep encoder position value at 1000mA
+  }
+}
+
+//----------------------Display Rotary Encoder Input Reading on LCD---------------------------
+void displayEncoderReading (void) {
+
+    lcd.setCursor(8,2);                                      //start position of setting entry
+
+    if ( ( Mode == "CP" || Mode == "CR" ) && reading < 100 ) {
+        lcd.print("0");
+    }
+    
+    if (reading < 10) {                                      //add a leading zero to display if reading less than 10
+        lcd.print("0"); 
+    }
+
+    if ( Mode == "CP" || Mode == "CR" ) {
+        lcd.print (reading, 2);                              //show input reading from Rotary Encoder on LCD
+    } else {
+        lcd.print (reading, 3);
+    }
+    lcd.setCursor (CP, 2);                                   //sets cursor position
+    lcd.cursor();                                            //show cursor on LCD
+}
+
+//--------------------------Cursor Position-------------------------------------------------------
+//Change cursor the position routine
+void CursorPosition(void) {
+
+    // Defaults for two digits before decimal and 3 after decimal point
+    int unitPosition = 9;
+
+    //Power and Resistance modes can be 3 digit before decimal but only 2 decimals
+    if ( Mode == "CP" || Mode == "CR" ) {
+        unitPosition = 10;        
+    }
+
+    if (digitalRead(CursorPos) == LOW) {
+    
+        delay(200);                                          //simple key bounce delay  
+        CP = CP + 1;
+        if (CP == unitPosition + 1 ) {
+            CP = CP + 1;
+        }
+    }
+    
+    if (CP > 13)  { CP = unitPosition; }                     //No point in turning tens and hundreds
+    if (CP == unitPosition +4 ) { factor = 1; }
+    if (CP == unitPosition +3 ) { factor = 10; }
+    if (CP == unitPosition +2 ) { factor = 100; }
+    if (CP == unitPosition )    { factor = 1000; }
+}
+
+//---------------------------------------------Read Voltage and Current--------------------------------------------------------------
+void readVoltageCurrent (void) {
+  
+  MCP342x::Config status;
+// Initiate a conversion; convertAndRead() will wait until it can be read
+  adc.convertAndRead(MCP342x::channel1, MCP342x::oneShot,
+           MCP342x::resolution16, MCP342x::gain1,                         //"gain1" means we have select the input amp of the ADC to x1
+           1000000, voltage, status);
+  
+// Initiate a conversion; convertAndRead() will wait until it can be read
+  adc.convertAndRead(MCP342x::channel2, MCP342x::oneShot,
+           MCP342x::resolution16, MCP342x::gain4,                         //"gain4" means we have select the input amp of the ADC to x4
+           1000000, current, status);
+  
+}
+
+//-----------------------------------Calculate Actual Voltage and Current and display on LCD-----------------------------------------
+void ActualReading(void) {
+
+  ActualCurrent = (((current*2.048)/32767) * 2.5);        //calculate load current
+  currentDisplayCal();                                    //LCD display current calibration correction
+  ActualVoltage = (((voltage*2.048)/32767) * 50.4);       //calculate load voltage upto 100v (was 50)
+  ActualPower = ActualVoltage*ActualCurrent;
+
+  if (ActualPower <=0){
+    ActualPower = 0;
+  }
+
+ if (ActualVoltage <=0.0){                              //added to prevent negative readings on LCD due to error
+  ActualVoltage = 0.0;
+ }
+ if (ActualCurrent <= 0.0){                             //added to prevent negative readings on LCD due to error
+  ActualCurrent = 0.0;
+ }
+ 
+ lcd.setCursor(0,1);
+    
+    if ( ActualCurrent < 10.0 ) {
+        lcd.print(ActualCurrent,3);
+    } else {
+        lcd.print(ActualCurrent,2);
+    }
+    
+    lcd.print("A");
+    lcd.print(" ");
+    
+    if (ActualVoltage < 10.0) {
+        lcd.print(ActualVoltage, 3);
+    } else {
+        lcd.print(ActualVoltage, 2);
+    }    
+
+    lcd.print("V");
+    lcd.print(" ");
+     
+    if (ActualPower < 100 ) {
+        lcd.print(ActualPower,2);
+    } else {
+        lcd.print(ActualPower,1);
+    }
+    lcd.print("W");
+    lcd.print(" ");
+}
+
+//-----------------------DAC Control Voltage for Mosfet---------------------------------------
+void dacControlVoltage (void) {
+  if (Mode == "CC"){
+  setCurrent = reading*1000;                                //set current is equal to input value in Amps
+  setReading = setCurrent;                                  //show the set current reading being used
+  setControlCurrent = setCurrent * setCurrentCalibrationFactor;
+  controlVoltage = setControlCurrent; 
+  }
+
+  if (Mode == "CP"){
+  setPower = reading*1000;                                  //in Watts
+  setReading = setPower;
+  setCurrent = setPower/ActualVoltage;
+  setControlCurrent = setCurrent * setCurrentCalibrationFactor;
+  controlVoltage = setControlCurrent;                       //
+  }
+
+  if (Mode == "CR"){
+  setResistance = reading;                                  //in ohms
+  setReading = setResistance;
+  setCurrent = (ActualVoltage)/setResistance*1000;
+  setControlCurrent = setCurrent * setCurrentCalibrationFactor;
+  controlVoltage = setControlCurrent; 
+  }
+
+if (Mode == "TC" || Mode == "TP" || Mode == "TT" || Mode == "TL"){                            //Transient Modes
+  setControlCurrent = (setCurrent * 1000) * setCurrentCalibrationFactor;
+  controlVoltage = setControlCurrent; 
+  }
+
+}
+
+//-------------------------------------Battery Capacity Discharge Routine----------------------------------------------------
+void batteryCapacity (void) {
+  if (Mode == "BC"){
+    
+    setCurrent = reading*1000;                             //set current is equal to input value in Amps
+    setReading = setCurrent;                               //show the set current reading being used
+    setControlCurrent = setCurrent * setCurrentCalibrationFactor;
+    controlVoltage = setControlCurrent;
+
+    lcd.setCursor(0,3);
+    lcd.print (timer.getTime());                           //start clock and print clock time
+
+    Seconds = timer.getTotalSeconds();                     //get totals seconds
+  
+    LoadCurrent = ActualCurrent;                           //if timer still running use present Actual Current reading
+    if (timer.status() == 2){                              //if timer is halted then use last Actual Current reading before timer stopped
+      LoadCurrent = BatteryCurrent;
+      }
+ 
+    BatteryLife = (LoadCurrent*1000)*(Seconds/3600);       //calculate battery capacity in mAh
+    lcd.setCursor(9,3);
+    BatteryLife = round(BatteryLife);
+
+    if(BatteryLife >= BatteryLifePrevious){                //only update LCD (mAh) if BatteryLife has increased
+  
+      if (BatteryLife < 10) {                              //add a 3 leading zero to display if reading less than 10
+      lcd.print("000");
+      }
+
+      if (BatteryLife >= 10 && BatteryLife <100){          //add a 2 leading zero to display
+      lcd.print("00");  
+      }
+
+      if (BatteryLife >= 100 && BatteryLife <1000){        //add a 1 leading zero to display
+      lcd.print("0"); 
+      }
+  
+    lcd.print(BatteryLife,0);
+    lcd.setCursor(13,3);
+    lcd.print("mAh");
+    BatteryLifePrevious = BatteryLife;                      //update displayed battery capacity on LCD
+    } 
+  }
+
+
+  if (Mode == "BC" && ActualVoltage <= BatteryCutoffVolts){ //stops clock if battery reached cutoff level and switch load off
+
+  BatteryCurrent = ActualCurrent;
+  dac.setVoltage(0,false);                                  //reset DAC to zero for no output current set at switch on                                             
+  toggle = false;                                           //Load is toggled OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");                                         //indicate that LOAD is off at start up
+  timer.stop();
+  }
+
+      if (Mode == "BC" && Load == 1){                       //Routine used for data logging in Battery Capacity Mode
+          if (Seconds != SecondsLog){                       //only send serial data if time has changed
+            SecondsLog = Seconds;
+            Serial.print (SecondsLog);                    //sends serial data of time in seconds
+            Serial.print (",");                             //sends a comma as delimiter for logged data
+            Serial.println (ActualVoltage);                   //sends serial data of Voltage reading         
+              }
+          }
+
+}
+
+//--------------------------------------------------Fan Control----------------------------------------------------------
+void fanControl (void) {
+  temp = analogRead(temperature);
+  temp = temp * 0.107421875;                                // convert to Celsius
+  
+  if (temp >= 40){                                        //if temperature 40 degree C or above turn fan on.
+    digitalWrite(fan, HIGH); 
+  }  else {
+    digitalWrite(fan, LOW);                               //otherwise turn fan turned off
+  }
+  
+  lcd.setCursor(16,0);
+  lcd.print(temp);                                        //display temperature of heatsink on LCD
+  lcd.print((char)0xDF);
+  lcd.print("C");
+
+}
+
+  
+//-----------------------Toggle Current Load ON or OFF------------------------------
+void LoadSwitch(void) {
+  
+  delay(200);                                              //simple key bounce delay 
+ 
+    if(toggle)
+    {
+      lcd.setCursor(8,0);
+      lcd.print("OFF");
+      current_instruction = 0;                            //reset current instruction for Transient List Mode to zero
+      last_time = 0;                                      //reset last time to zero
+      transientPeriod = 0;                                //reset transient period time to zero
+      setCurrent = 0;                                     //reset setCurrent to zero
+      toggle = !toggle;
+      Load = 0;        
+    }
+    else
+    {
+      lcd.setCursor(8,0);
+      lcd.print("ON ");
+      lcd.setCursor(0,3);
+      lcd.print("                    ");                 //clear bottom line of LCD
+      toggle = !toggle;
+      Load = 1;
+    }
+}
+
+//-----------------------Select Constant Current LCD set up--------------------------------
+void Current(void) {
+  Mode = ("CC");
+  lcd.setCursor(0,0);
+  lcd.print("DC LOAD");  
+  lcd.setCursor(0,2);
+  lcd.print("                ");
+  lcd.setCursor(0,2);
+  lcd.print("Set I = ");
+  lcd.setCursor(16,2);
+  lcd.print("    ");
+  lcd.setCursor(14,2);
+  lcd.print("A");
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("                    ");                    //20 spaces so as to allow for Load ON/OFF to still show
+  CP = 9;                                               //sets cursor starting position to units.
+}
+
+//----------------------Select Constant Power LCD set up------------------------------------
+void Power(void) {
+  Mode = ("CP");
+  lcd.setCursor(0,0);
+  lcd.print("DC LOAD");
+  lcd.setCursor(0,2);
+  lcd.print("                ");
+  lcd.setCursor(0,2);
+  lcd.print("Set W = ");
+  lcd.setCursor(16,2);
+  lcd.print("    ");
+  lcd.setCursor(14,2);
+  lcd.print("W");
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("                    ");                    //20 spaces so as to allow for Load ON/OFF to still show
+  CP = 10;                                               //sets cursor starting position to units.
+}
+
+//----------------------- Select Constant Resistance LCD set up---------------------------------------
+void Resistance(void) {
+  Mode = ("CR");
+  lcd.setCursor(0,0);
+  lcd.print("DC LOAD");  
+  lcd.setCursor(0,2);
+  lcd.print("                ");
+  lcd.setCursor(0,2);
+  lcd.print("Set R = ");
+  lcd.setCursor(16,2);
+  lcd.print("    ");
+  lcd.setCursor(14,2);
+  lcd.print((char)0xF4);
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("                    ");                    //20 spaces so as to allow for Load ON/OFF to still show
+  CP = 10;                                               //sets cursor starting position to units.
+}
+
+//----------------------- Select Battery Capacity Testing LCD set up---------------------------------------
+void BatteryCapacity(void) {
+  Mode = ("BC");
+  lcd.setCursor(0,0);
+  lcd.print("BATTERY");
+  lcd.setCursor(0,2);
+  lcd.print("                ");
+  lcd.setCursor(0,2);
+  lcd.print("Set I = ");
+  lcd.setCursor(14,2);
+  lcd.print("A");
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("                    ");                    //20 spaces so as to allow for Load ON/OFF to still show
+}
+
+//----------------------Battery Type Selection Routine------------------------------------------------
+void batteryType (void) {
+  exitMode = 0;                                         //reset EXIT mode
+  lcd.noCursor();                                       //switch Cursor OFF for this menu               
+  lcd.clear();
+  lcd.setCursor(0,0);
+  lcd.print("Select Battery Type");  
+  lcd.setCursor(0,1);
+  lcd.print("1=LiPo/Li-Ion 2=LiFe");
+  lcd.setCursor(0,2);
+  lcd.print("3=NiCd/NiMH   4=ZiZn");
+  lcd.setCursor(0,3);                                   //clear last line of time info
+  lcd.print("5=Set Voltage 6=Exit");                    //20 spaces so as to allow for Load ON/OFF to still show
+
+  customKey = customKeypad.waitForKey();                //stop everything till the user press a key.
+
+  if (customKey == '1'){
+  BatteryCutoffVolts = LiPoCutOffVoltage;
+  BatteryType = ("LiPo");
+    }
+
+  if (customKey == '2'){
+  BatteryCutoffVolts = LiFeCutOffVoltage;
+  BatteryType = ("LiFe");
+    }
+
+  if (customKey == '3'){
+  BatteryCutoffVolts = NiCdCutOffVoltage;
+  BatteryType = ("NiCd");  
+    }
+
+  if (customKey == '4'){
+  BatteryCutoffVolts = ZiZnCutOffVoltage;
+  BatteryType = ("ZiZn"); 
+    }
+
+  if (customKey == '5'){ 
+  BatteryType = ("SetV");
+    }
+
+  if (customKey == '6'){                                  //Exit selection screen
+  exitMode = 1;
+    }
+
+  if (customKey == '7' || customKey == '8' || customKey == '9' || customKey == '0' || customKey == 'A' || customKey == 'B' || customKey == 'C' || customKey == 'D' || customKey == '*' || customKey == '#' || customKey == 'E' || customKey == 'F' || customKey == '<' || customKey == '>' ){
+  batteryType();                                                      //ignore other keys
+    }
+
+  if(BatteryType == "SetV" && exitMode != 1){
+  setBatteryCutOff();
+    }
+
+  batteryTypeSelected();                                    //briefly display battery type selected and discharge cut off voltage
+
+  lcd.clear();
+
+}
+
+//--------------------------Set DAC Voltage--------------------------------------------
+void dacControl (void) {
+  if (!toggle){
+  dac.setVoltage(0,false);                                 //set DAC output voltage to 0 if Load Off selected
+    if(Mode == "BC" && ActualVoltage >= BatteryCutoffVolts && timer.status() == 1){
+    timer.stop();
+    }
+  
+  }else{
+  //Serial.println("Control Voltage");                    //used for testing only
+  //Serial.println(controlVoltage);                       //used for testing only
+  dac.setVoltage(controlVoltage,false);                   //set DAC output voltage for Range selected
+    if(Mode == "BC" && ActualVoltage >= BatteryCutoffVolts && timer.status() != 1){
+    timer.start();
+    }
+  }
+}
+
+//--------------------------Battery Selected Information--------------------------------------------
+void batteryTypeSelected (void) {
+  if (exitMode !=1){                                      //if battery selection was EXIT then skip this routine
+  lcd.clear();
+  lcd.setCursor(2,0);
+  lcd.print("Battery Selected");
+  lcd.setCursor(8,1);
+  lcd.print(BatteryType);                                 //display battery type selected
+  lcd.setCursor(2,2);
+  lcd.print("Discharge Cutoff");
+  lcd.setCursor(6,3);
+  lcd.print(BatteryCutoffVolts);                          //display battery discharge cut off voltage
+  lcd.print(" volts");                                    
+  delay(3000);
+  }
+}
+
+//--------------------------Set Battery Cut-Off Voltage--------------------------------------------
+void setBatteryCutOff (void) {
+
+  lcd.clear();
+  lcd.setCursor(4,0);
+  lcd.print("Enter Battery");
+  lcd.setCursor(3,1);
+  lcd.print("Cut-Off Voltage");
+  y = 8;
+  z = 8;
+  r = 2;
+
+  inputValue();
+  BatteryCutoffVolts = x;
+
+  lcd.clear();
+}
+
+//------------------------Key input used for Battery Cut-Off and Transient Mode------------------------
+void inputValue (void){
+
+ while(customKey != 'F'){               //check if enter pressed (was previously #)
+  
+  customKey = customKeypad.getKey();
+  if(customKey >= '0' && customKey <= '9'){               //check for keypad number input
+       numbers[index++] = customKey;
+       numbers[index] = '\0';
+       lcd.setCursor(z,r);                              
+       lcd.print(customKey);                              //show number input on LCD
+       z = z+1;
+     }
+  
+  if(customKey == '>'){                                   //Decimal point
+      if (decimalPoint != ('>')){                         //test if decimal point entered twice - if so ski
+      numbers[index++] = '.';
+      numbers[index] = '\0';
+      lcd.setCursor(z,r);
+      lcd.print(".");
+      z = z+1;
+      decimalPoint = ('>');                               //used to indicate decimal point has been input
+        }
+      }
+
+ if(customKey == '<'){                                    //clear entry
+    index = 0;
+    z = y;
+    lcd.setCursor(y,r);
+    lcd.print("     ");
+    numbers[index] = '\0';                                //
+    decimalPoint = (' ');                                 //clear decimal point test character reset
+  }
+
+ }
+ 
+  if(customKey == 'F') {                                  //enter value 
+    x = atof(numbers);     
+    index = 0;
+    numbers[index] = '\0';
+    decimalPoint = (' ');                                 //clear decimal point test character reset
+  }
+}
+
+//----------------------------------------Transient Mode--------------------------------------------
+void transientMode (void) {
+
+if(Mode != "TL"){
+
+  y = 11;
+  z = 11;
+  
+  lcd.noCursor();                                       //switch Cursor OFF for this menu               
+  lcd.clear();
+  lcd.setCursor(3,0);
+  lcd.print("Transient Mode");  
+  lcd.setCursor(0,1);
+  lcd.print("Set Low  I=");
+  lcd.setCursor(19,1);
+  lcd.print("A");
+  r = 1;
+  inputValue();
+  
+  if(x >= CurrentCutOff){
+    LowCurrent = CurrentCutOff;
+  }else{
+    LowCurrent = x;
+  }
+  lcd.setCursor(11,r);
+  lcd.print(LowCurrent,3);
+  
+  customKey = '0';
+
+  z = 11;
+
+  lcd.setCursor(0,2);
+  lcd.print("Set High I=");
+  lcd.setCursor(19,2);
+  lcd.print("A");
+  r = 2;
+  inputValue();
+  if(x >= CurrentCutOff){
+    HighCurrent = CurrentCutOff;
+  }else{
+    HighCurrent = x;
+  }
+  lcd.setCursor(11,r);
+  lcd.print(HighCurrent,3);
+
+  customKey = '0';
+
+  if(Mode == "TC" || Mode == "TP"){
+  z = 11;
+
+  lcd.setCursor(0,3);
+  lcd.print("Set Time  = ");
+  lcd.setCursor(16,3);
+  lcd.print("mSec");
+  r = 3;
+  inputValue();
+  transientPeriod = x;
+  lcd.setCursor(11,r);
+  lcd.print(transientPeriod);
+  }else{
+  lcd.setCursor(0,3);
+  lcd.print("                    ");
+  }
+
+  lcd.clear();
+
+  toggle = false;                                           //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");                                         //print on display OFF
+    }else{  
+  transientListSetup();
+  lcd.clear();
+ 
+  toggle = false;                                           //switch Load OFF
+  lcd.setCursor(8,0);
+  lcd.print("OFF");                                         //print on display OFF
+  }
+}
+
+//----------------------------------------Transient Type Selection--------------------------------------------
+void transientType (void) {
+  toggle = false;                                         //switch Load OFF
+  exitMode = 0;                                           //reset EXIT mode
+  lcd.noCursor();                                         //switch Cursor OFF for this menu               
+  lcd.clear();
+  lcd.setCursor(3,0);
+  lcd.print("Transient Mode");  
+  lcd.setCursor(0,1);
+  lcd.print("1 = Continuous");
+  lcd.setCursor(0,2);
+  lcd.print("2 = Toggle");
+  lcd.setCursor(11,2);                                    //
+  lcd.print("3 = Pulse");                                 //
+  lcd.setCursor(0,3);                                     //
+  lcd.print("4 = List");                                  //
+  lcd.setCursor(11,3);                                    //
+  lcd.print("5 = Exit");                                  //
+
+  customKey = customKeypad.waitForKey();                  //stop everything till the user press a key.
+
+  if (customKey == '1'){
+  Mode = ("TC"); 
+    }
+
+  if (customKey == '2'){
+   Mode = ("TT");
+    }
+
+  if (customKey == '3'){
+  Mode = ("TP");  
+    }
+
+  if (customKey == '4'){
+  Mode = ("TL");  
+    }
+
+  if (customKey == '5'){                                  //Exit selection screen
+  exitMode = 1;
+    }
+
+  if (customKey == '6' || customKey == '7' || customKey == '8' || customKey == '9' || customKey == '0' || customKey == 'A' || customKey == 'B' || customKey == 'C' || customKey == 'D' || customKey == '*' || customKey == '#' || customKey == 'E' || customKey == 'F' || customKey == '<' || customKey == '>' ){
+  transientType();                                                      //ignore other keys
+  
+    }
+lcd.clear();
+
+if (exitMode == 1){                                       //if NO Transient Mode type selected revert to CC Mode
+    lcd.setCursor(8,0);
+    lcd.print("OFF");
+    Current();                                            //if selected go to Constant Current Selected routine
+    encoderPosition = 0;                                  //reset encoder reading to zero
+    customKey = 'A';
+      }else{
+    transientMode();
+      }
+ }
+ 
+//----------------------------------------Transient--------------------------------------------
+void transient (void) {
+  
+  if(Mode == "TC" || Mode == "TP" || Mode == "TT" || Mode == "TL"){
+  lcd.noCursor();                                         //switch Cursor OFF for this menu 
+  lcd.setCursor(0,0);
+  lcd.print("DC LOAD");
+  
+  if(Mode != "TL"){
+  lcd.setCursor(0,2);
+  lcd.print("Lo=");
+  lcd.setCursor(3,2);
+  lcd.print(LowCurrent,3);
+  lcd.setCursor(8,2);
+  lcd.print("A");
+  lcd.setCursor(11,2);
+  lcd.print("Hi=");
+  lcd.setCursor(14,2);                                    //
+  lcd.print(HighCurrent,3);
+  lcd.setCursor(19,2);
+  lcd.print("A");
+  }else{
+    delay(1);
+  }
+
+
+  if(Mode == "TC" || Mode == "TP" || Mode == "TL"){
+  lcd.setCursor(0,3);                                     //
+  lcd.print("Time = ");
+  lcd.setCursor(7,3);
+  lcd.print(transientPeriod);
+  lcd.setCursor(12,3);                                    //
+  lcd.print("mSecs");
+    }else{
+     lcd.setCursor(0,3);
+     lcd.print("  ");
+    }
+  }
+delay(1);
+}
+
+//-------------------------------------Transcient List Setup-------------------------------------------
+void transientListSetup(){
+
+  lcd.noCursor();                                                 
+  lcd.clear();
+  lcd.setCursor(0,0);
+  lcd.print("Setup Transient List");
+  lcd.setCursor(0,1);
+  lcd.print("Enter Number in List");
+  lcd.setCursor(0,2);
+  lcd.print("(between 2 to 10 max"); 
+  y = 0;
+  z = 0;
+  r = 3;
+  inputValue();
+  total_instructions = int(x-1);
+  customKey = '0';
+  lcd.clear();
+  
+    for(int i=0; i<=(total_instructions); i++){
+      lcd.setCursor(0,0);
+      lcd.print("Set Current ");
+      lcd.print(i+1);
+      lcd.setCursor(16,1);
+      lcd.print("A");
+      y = 0;
+      z = 0;
+      r = 1;
+      inputValue();            //get the users input value
+      transientList[i][0] = x; //store the users entered value in the transient list 
+      customKey = '0';
+      lcd.setCursor(0,2);
+      lcd.print("Set Time ");
+      lcd.print(i+1);
+      lcd.setCursor(16,3);
+      lcd.print("mSec");
+      y = 0;
+      z = 0;
+      r = 3;
+      inputValue();            //get the users input value
+      transientList[i][1] = x; //store the users entered value in the transient list
+      customKey = '0';
+      lcd.clear();   
+  }
+  current_instruction = 0;      //start at first instrution
+}
+
+//-------------------------------------Transcient Load Toggel-------------------------------------------
+void transientLoadToggle(){
+
+  if(Mode == "TC"){
+  current_time = micros();                              //get the current time in micro seconds()
+  if (last_time == 0){
+    last_time = current_time;
+  } else {
+    switch (transient_mode_status){
+      case (false):
+          // we are in the low current setting
+          if ((current_time - last_time) >= (transientPeriod * 1000.0)){
+             transientSwitch(LowCurrent, true);  
+          }
+        break;
+      case (true):
+          // we are in the high current setting 
+          if ((current_time - last_time) >= (transientPeriod * 1000.0)){
+            transientSwitch(HighCurrent, true);            
+          }
+        break; 
+      } 
+     }
+    }
+
+
+  if(Mode == "TP"){
+    current_time = micros();                            //get the current time in micro seconds()
+    if (last_time == 0){
+        last_time = current_time;
+        transientSwitch(LowCurrent, true);
+    }
+    if (digitalRead(TriggerPulse) == LOW){
+      // a trigger pluse is received
+      // set to the high current
+      transientSwitch(HighCurrent, true); 
+    } else {
+        if ((current_time - last_time) >= (transientPeriod * 1000.0)){
+            transientSwitch(LowCurrent, true);            
+        }
+      }  
+  }
+
+
+ if(Mode == "TT"){          // this function will toggle between high and low current when the trigger pin is taken low
+  if (digitalRead(TriggerPulse) == LOW){
+    switch (transient_mode_status){
+      case (false):
+        transientSwitch(LowCurrent, true);
+        delay(200);         //added to prevent key bounce when transient button used (date of addition 31-03-2018)
+        break;
+      case (true):
+        transientSwitch(HighCurrent, true);
+        delay(200);         //added to prevent key bounce when transient button used (date of addition 31-03-2018)   
+        break;
+      }
+    }
+  }
+
+
+if(Mode == "TL"){
+  if (Load == 1){                                                 //Only perform Transient List if Load is ON
+   current_time = micros();                                       //get the current time in micro seconds()
+    if (last_time == 0){
+      last_time = current_time;
+      transientPeriod = transientList[current_instruction][1];    //Time data for LCD display
+      transientSwitch(transientList[current_instruction][0], false);
+    }
+    if((current_time - last_time) >= transientList[current_instruction][1] * 1000){     //move to next list instruction
+        current_instruction++;
+        if(current_instruction > total_instructions){
+          current_instruction = 0;
+        }
+      transientPeriod = transientList[current_instruction][1];   //Time data for LCD display
+      transientSwitch(transientList[current_instruction][0], false);
+      }
+    }
+  }
+
+}
+
+//-------------------------------------Transcient Switch-------------------------------------------
+void transientSwitch(float current_setting, boolean toggle_status){
+  if (toggle_status){
+  transient_mode_status = !transient_mode_status;
+  }
+  setCurrent = current_setting;
+  //Serial.print("set current = ");                     //used for testing only
+  //Serial.println(setCurrent);                         //used for testing only
+  last_time = current_time;
+}
+
+//-------------------------------------User set up for limits-------------------------------------------------
+void userSetUp (void) {
+  y = 14;
+  z = 14;
+  
+  lcd.noCursor();                                       //switch Cursor OFF for this menu               
+  lcd.clear();
+  lcd.setCursor(4,0);
+  lcd.print("User Set-Up");
+  lcd.setCursor(0,1);
+  lcd.print("Current Limit=");
+  lcd.setCursor(19,1);
+  lcd.print("A");
+  r = 1;
+  inputValue();
+  CurrentCutOff = x;
+  EEPROM.write(0x00, CurrentCutOff);
+  lcd.setCursor(14,r);
+  lcd.print(CurrentCutOff);
+  
+  customKey = '0';
+
+  z = 14;
+
+  lcd.setCursor(0,2);
+  lcd.print("Power Limit  =");
+  lcd.setCursor(19,2);
+  lcd.print("W");
+  r = 2;
+  inputValue();
+  PowerCutOff = x;
+  EEPROM.write(0x20, PowerCutOff);              //
+  lcd.setCursor(14,r);
+  lcd.print(PowerCutOff);
+
+  customKey = '0';
+
+  z = 14;
+
+  lcd.setCursor(0,3);
+  lcd.print("Temp. Limit  =");
+  lcd.setCursor(18,3);
+  lcd.print((char)0xDF);
+  lcd.print("C");
+  r = 3;
+  inputValue();
+  tempCutOff = x;
+  EEPROM.write(0x40, tempCutOff);
+  lcd.setCursor(14,r);
+  lcd.print(tempCutOff);
+
+    lcd.clear();
+
+    lcd.setCursor(8,0);
+    lcd.print("OFF");
+    Current();                                            //if selected go to Constant Current Selected routine
+    encoderPosition = 0;                                  //reset encoder reading to zero
+    customKey = 'A';
+}
+
+//------------------------------------------High Temperature Cut-Off--------------------------------------------------------------
+void temperatureCutOff (void){
+  if (temp >= tempCutOff){                                 //if Maximum temperature is exceeded
+  reading = 0;
+  encoderPosition = 0; 
+  lcd.setCursor(0,3);
+  lcd.print("                    ");
+  lcd.setCursor(0,3);
+  lcd.print("Over Temperature");
+  lcd.setCursor(8,0);
+  lcd.print("OFF");
+  toggle = false;                                         //switch Load Off
+  }
+}
+
+//-----------------------------------------Current Read Calibration for LCD Display --------------------------------------------
+void currentDisplayCal (void){
+
+  if(ActualCurrent <= 0){
+    ActualCurrent = 0;
+  }else if(Load == 0){
+    ActualCurrent = 0;
+  }else{
+  ActualCurrent = ActualCurrent + displayCurrentCal;
+  }
+
+/*  if (ActualCurrent <= 0.5)
+    {
+    ActualCurrent = (ActualCurrent +(displayCurrentCal * 3));
+    }
+    else if (ActualCurrent >= 0.5 && ActualCurrent <1.0)
+    {
+    ActualCurrent = (ActualCurrent + (displayCurrentCal * 2));
+    }
+    else if (ActualCurrent >= 1.0 && ActualCurrent <= 1.4)
+    {
+    ActualCurrent = (ActualCurrent + (displayCurrentCal));
+    }
+    else 
+    {
+    ActualCurrent = ActualCurrent;
+    }
+*/
+}
+  
+//-----------------------------Show limits Stored Data for Current, Power and Temp-----------------------------
+  void setupLimits (void){
+  lcd.clear();
+  lcd.setCursor(1,0);
+  lcd.print("Maximum Limits Set");
+  lcd.setCursor(0,1);
+  lcd.print("Current Limit=");
+  lcd.setCursor(17,1);
+  lcd.print("A");
+  lcd.setCursor(15,1);
+  CurrentCutOff = EEPROM.read(0x00);
+  lcd.print(CurrentCutOff);
+
+  lcd.setCursor(0,2);
+  lcd.print("Power Limit  =");
+  lcd.setCursor(17,2);
+  lcd.print("W");
+  lcd.setCursor(15,2);
+  PowerCutOff = EEPROM.read(0x20);
+  lcd.print(PowerCutOff);
+
+  lcd.setCursor(0,3);
+  lcd.print("Temp. Limit  =");
+  lcd.setCursor(17,3);
+  lcd.print((char)0xDF);
+  lcd.print("C");
+  tempCutOff = EEPROM.read(0x40);
+  lcd.setCursor(15,3);
+  lcd.print(tempCutOff);
+  }
+  
+  //---------------------------------------------------------------------------------------------------------