single current only

Dependencies:   Watchdog mbed

Revision:
0:0ba5f6ec8fa5
Child:
1:31e63b43238f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jan 24 13:32:57 2017 +0000
@@ -0,0 +1,426 @@
+// Copyright (c) 2017 Smartcharge Ltd
+
+
+#include "mbed.h"
+#include "Watchdog.h"
+
+// ************************************************************
+// *     Variables for capturing analog cp and pp values      *       
+// ************************************************************
+AnalogIn cp_value(A1);                                          //A1 – cp analog read.
+AnalogIn pp_value(A2);                                          //A2 - pp analog read.
+
+// ************************************************************
+// *  Variables and constants for new cp acquisition routine  *
+// ************************************************************
+#define NUMBER_OF_SAMPLES 5000                                  // Size of ADC sample series for cp signal (default = 5000).
+#define VOLTAGE_RENORMALISATION 4.5                             // Renormalisation constant to correct cp measured voltages (default = 4.5).
+#define VOLTAGE_THRESHOLD 4.0                                   // Threshold value for pwm edge detection (default = 4.0).
+float cp_voltage;                                               // Global variable to store the measured voltage of the cp signal.
+float cp_duty_cycle;                                            // Global variable to store the measured duty cycle of the cp signal.
+float cp_frequency;                                             // Global variable to store the the measured frequency of the cp signal.
+Timer cp_timer;                                                 // Timer used to determine the frequency of the cp signal.
+uint16_t cp_array[NUMBER_OF_SAMPLES];                           // Array to store ADC sample series for cp signal.
+
+// ************************************************************
+// *          Constant for voltage checking routine           *
+// ************************************************************
+#define ACCEPTABLE_VOLTAGE_RANGE 0.5                            // Sets the acceptable range of measured cp voltages (default 0.5, i.e. +/-0.5 V around value of 12, 9, 6V) 
+
+// ************************************************************
+// *          Timers and variables for reset button           *                 
+// ************************************************************
+InterruptIn button(D8);                                         // Interupt for button on pin D8.
+Timer button_timer;                                             // Timer used for reset button press.
+Timeout button_timeout;                                         // Timeout case for reset button press.
+bool reset_down = false;                                        // Flag used to determine whether reset button is held down.
+bool reset_charger = false;                                     // Flag used to determine whether charger is to be reset.
+#define RESET_SECONDS 2                                         // Define length of time in seconds reset button needs to be held down before reset registered (default 3s).
+
+// ************************************************************
+// *   Variables and constants to set the charging current    *
+// ************************************************************
+#define UPPER_CURRENT 32                                        // Sets the upper current value desired. 
+#define LOWER_CURRENT 16                                         // Sets the lower current value desired.
+float pwm_duty_high = 1.0-((UPPER_CURRENT / 30.0) * 0.5);       // Calculates the pwm duty cycle for the desired upper current.
+float pwm_duty_low = 1.0-((LOWER_CURRENT / 30.0) * 0.5);        // Calculates the pwm duty cycle for the desired lower current.
+bool use_upper_current = false;
+
+// ************************************************************
+// *      Variables and constants to allow state changes      *        
+// ************************************************************
+unsigned char control_pilot;
+#define PILOT_NOK   0                                           // Error state.               
+#define PILOT_12V   1                                           // Standby state.
+#define PILOT_9V    2                                           // Vehicle detection state.
+#define PILOT_6V    3                                           // Charging state.
+#define PILOT_DIODE 4                                           // Charging state with ventilation (not currently implemented).
+#define PILOT_RESET 5                                           // Reset state.
+#define PWM_CHANGE  6                                           // New state added to allow change in PWM duty cycle and charging current.
+
+// ************************************************************
+// *                 Digital out definitions                  *                               
+// ************************************************************
+PwmOut my_pwm(D5);                                              // PWM out on pin D5.
+DigitalOut lock(D7);                                            // Cable lock on pin D7.
+DigitalOut relay(D12);                                          // Relay on pin D12.
+DigitalOut contactor(D13);                                      // Contactor on pin D13.
+DigitalOut green(D9);                                           // Green LED on pin D9.                
+DigitalOut red(D10);                                            // Red LED on pin D10.
+DigitalOut blue(D11);                                           // Blue LED on pin D11.                
+
+// ************************************************************
+// *                    Serial connections                    *                                    
+// ************************************************************
+Serial pc(USBTX, USBRX);                                        // Serial output to PC.
+int TESTCOUNTER = 0;                                            // Variable to count number of cycles of main loop. Used to determine when to switch the pwm in this test version.
+
+
+// ************************************************************
+// *   New Acquisition Routine for Capturing CP Signal Data   *                                    
+// ************************************************************
+void cp_acquire()
+{            
+    int i;                                                      // Variable for loop counter.
+    float sample_value_current = 0;                             // Stores the current cp value obtained by ADC (A1).
+    float sample_value_previous = 0;                            // Stores the previous cp value obtained by ADC (A1).
+    float peak_counter;                                         // Used to store the number of samples representing a peak of the pwm square wave.
+    float trough_counter;                                       // Used to store the number of samples representing a trough of the pwm square wave.
+    float voltage_average;                                      // Used to calculate the average peak voltage value.
+    float thres_cross_rise;                                     // Used to store the number of times the pwm wave goes from low to high.
+    float thres_cross_fall;                                     // Used to store the number of times the pwm wave goes from high to low. 
+    float t;                                                    // Used to determine the time over which samples were acquired.
+    
+    cp_timer.start();                                           // Starts a timer before we begin sampling the cp signal.
+    for (i = 0; i < NUMBER_OF_SAMPLES; i++)                     // Starts a loop to take a certain number of samples as defined in NUMBER_OF_SAMPLES.
+    {
+        wait_us(30);                                            // Waits 30 us. This sets the sample rate at approximately 33 KS/second.
+        cp_array[i] = cp_value.read_u16();                      // Reads the ADC (A1) and stores the measured cp voltage as a 16 bit integer in cp_array.
+    }
+    cp_timer.stop();                                            // Stop the timer once the acqusition has finished.
+    t = cp_timer.read_us();                                     // Read the timer value in microseconds and store the result in t. 
+    t = t / 1000000.0;                                          // Divide t by 1000000 to convert from microseconds to seconds.
+    cp_timer.reset();                                           // Reset the timer.
+    
+    peak_counter = 0;                                           // Set peak_counter to zero.  
+    trough_counter = 0;                                         // Set trough_counter to zero.
+    voltage_average = 0;                                        // Set voltage_average to zero. 
+    thres_cross_rise = 0;                                       // Set thres_cross_rise to zero.
+    thres_cross_fall = 0;                                       // Set thres_cross_fall to zero.
+    
+    // Having captured cp data, we now have to process each sample. This is done in a separate loop to maximize the ADC sampling rate.        
+    for (i = 0; i < NUMBER_OF_SAMPLES; i++) 
+    {
+        // The cp data was stored in cp_array as a 16 bit integer. To convert this into a voltage we divide by 65535 (16 bits is 0 - 65535)
+        // and multiply by 3.3 V. Because of the resistors and diode on the shield, we need to renormalise the values and scale them up
+        // by a factor of 4.5 (VOLTAGE_RENORMALISATION).
+        sample_value_current = (cp_array[i] * 3.3 * VOLTAGE_RENORMALISATION) / 65535.0;
+        
+               
+        if (sample_value_current > VOLTAGE_THRESHOLD)           // We examine the cp voltage. If it is above the threshold then we assume it is at the peak of the pwm square wave.
+        {
+            peak_counter+=1;                                    // Add one to the peak_counter.
+            voltage_average+=sample_value_current;              // Add the cp_voltage to a running total (voltage_average) so we can work out the average voltage later.
+        }
+        else
+        {
+            trough_counter+=1;                                  // If the cp voltage is less than the threshold then we assume it is at the trough of the pwm square wave and increment trough_counter.
+        }
+        
+                
+        if (i > 0)                                              // If we've already processed the first sample then ...                                                  
+        {
+            if (sample_value_current > VOLTAGE_THRESHOLD && sample_value_previous < VOLTAGE_THRESHOLD)          // ... we check if the cp voltage we're looking at is above the threshold and if the previous cp voltage
+                                                                                                                // is below the threshold. If this is the case then we've detected the rising edge of the pwm square wave.
+            {
+                thres_cross_rise+=1;                                                                            // We increment thres_cross_rise if this is the case.
+            }
+            if (sample_value_current < VOLTAGE_THRESHOLD && sample_value_previous > VOLTAGE_THRESHOLD)          // Alternatively, if the cp voltage we're looking at is below the theshold and the previous cp voltage 
+                                                                                                                // is above the threshold then we've detected the falling edge of the pwm square wave.
+            {
+                thres_cross_fall+=1;                                                                            // We increment thres_cross_fall is this is the case.
+            }
+        }                          
+        
+        sample_value_previous = sample_value_current;                                                           // Before we proces the next sample, we copy the current value into the previous value.
+    } 
+    
+    
+    if(peak_counter == 0)                                       // If, having processed each sample, the peak_counter is still zero, then every cp voltage we acquired was less than the threshold ...
+    {
+        cp_voltage = -12.0;                                     // ... which implies that the cp is not at 6, 9, or 12V. In the current implementation, that means the cp is actually at -12 V.   
+    }
+    else                                                        // On the other hand, if the peak_counter is greater than 0, then some (pwm is on) or all (DC, pwm is off) of the values were greater than the threshold ...
+    {
+        cp_voltage = voltage_average / peak_counter;            // ... so determine the cp voltage by taking the running total (voltage_average) and dividing it by peak_counter.               
+    }        
+    
+    cp_duty_cycle = peak_counter / NUMBER_OF_SAMPLES;           // The duty cycle is the number of peak samples of the pwm square waves divided by the total number of samples ... 
+    cp_duty_cycle = cp_duty_cycle * 100.0;                      // ... but we need to convert it into a percentage.
+    cp_frequency = ((thres_cross_rise + thres_cross_fall) / 2.0) / t;           // The frequency of the cp signal is the total number of crossings divided by 2, divided by the time. 
+    
+    pc.printf("CP Measured Peak/DC Voltage (V): %f \r\n", cp_voltage);  
+    pc.printf("CP Measured Duty Cycle (%%): %f \r\n", cp_duty_cycle);
+    pc.printf("CP Measured Frequency (Hz): %f \r\n", cp_frequency);
+}
+
+
+
+// ************************************************************
+// *         Routines for handling reset button press         *                                                
+// ************************************************************
+void button_timed_out() 
+{
+    reset_charger = true;
+    pc.printf("Reset button pressed for more than 3 sec! Charger reset! \r\n");
+}
+ 
+void reset_pressed() 
+{
+    pc.printf("Reset button pressed ... starting timer. \r\n");
+    button_timer.stop();
+    button_timer.reset();
+    button_timer.start();
+    reset_down = true;   
+    button_timeout.attach(&button_timed_out, RESET_SECONDS);   
+}
+    
+void reset_released() 
+{
+    int elapsed_seconds;    
+    pc.printf("Reset button released. \r\n");           
+    elapsed_seconds = button_timer.read();
+    button_timer.stop();
+    button_timer.reset();
+    if (elapsed_seconds > RESET_SECONDS) 
+    {
+        reset_charger = true;
+        pc.printf("Reset button was pressed for more than 3 sec! \r\n");
+    }
+    else
+    {
+        pc.printf("Reset button released before 3 seconds were up. \r\n");
+    }
+    pc.printf("Detach the timeout and setup for the next time.\r\n");
+    pc.printf("%u \r\n", elapsed_seconds);
+    button_timeout.detach();
+}
+
+
+
+// ************************************************************
+// *             Routine for Checking CP Voltages             *                                                                        
+// ************************************************************
+bool cp_check_voltage (float v)                                 // Function accepts a voltage value (eg. 12V, 9V, 6V) ...
+{
+    bool voltage_in_range = false;                              // ... and initially sets a flag to false.
+    
+    // If the measured cp voltage is within a range of +/- ACCEPTABLE_VOLTAGE_RANGE around the 
+    // value (12V, 9V, 6V) then we change the flag state to true.
+    if (cp_voltage < (v + ACCEPTABLE_VOLTAGE_RANGE) && cp_voltage > (v - ACCEPTABLE_VOLTAGE_RANGE)) voltage_in_range = true;
+                            
+    return voltage_in_range;                                    // The function then returns the value of the flag state.
+}
+
+
+
+// ************************************************************
+// *                           Main                           *                                                                                                    
+// ************************************************************
+int main() 
+{        
+    button.fall(&reset_pressed);                                // Attach interupt to button when pressed.
+    button.rise(&reset_released);                               // Attach interupt to button when released.
+    
+    float reading_pp;                                           // Create variable to store pp reading.
+    bool cable_32A = false;                                     // Create boolean to flag whether a 32 or 16A cable is being used. Default is 16A cable (cable_32A = false).
+    bool cable_connected = false;                               // Create boolean to flag whether a cable is attached.
+    bool pwm_state = false;                                     // Create boolean to flag current state of pwm (whether it is on or off). 
+    float pwm_duty_cycle;                                       // Create float to store the current pwm duty cycle.
+    
+    while(true)                                                 // Start of process loop. 
+    {
+        // check the cable using pp value
+        reading_pp = pp_value.read();                           // Read pp value and ...
+        reading_pp = reading_pp * 3300;                         // ... multiply it by 3300 to convert to mV.
+        
+        if(reading_pp > 3200)                                   // If the pp value is 3.3 V (greater than 3200 mV) then ... 
+        {
+            cable_connected = false;                            // ... the cable *isn't* connected to charger ...
+            pc.printf("Cable not connected. \r\n");
+        }
+        else
+        {
+            cable_connected = true;                             // ... otherwise the cable *is* connected to charger. 
+            pc.printf("Cable connected. \r\n");
+        }
+        
+        if(reading_pp > 200 && reading_pp < 300)                // If the pp reading is between 200 and 300 mV then ...
+        {
+            cable_32A = false;                                  // ... a 16A cable is being used.
+            pc.printf("16A cable detected. \r\n");
+        }
+        
+        if(reading_pp > 0 && reading_pp <100)                   // If the pp reading if between 0 and 100 mV then ...
+        {
+            cable_32A = true;                                   // ... a 32A cable is being used.
+            pc.printf("32A cable detected. \r\n");  
+        }
+        
+        cp_acquire();                                           // Call the new acquisition routine (replaces the moving average in previous versions).        
+
+        if (cable_connected == false)
+        {
+            if (cp_check_voltage(12) == true) control_pilot = PILOT_12V;     
+            
+            if (cp_check_voltage(-12) == true)
+            {
+                control_pilot = PILOT_12V;
+                reset_charger = false;
+            }
+        }
+        
+        if (cable_connected == true)
+        {
+            if (cp_check_voltage(9) == true) control_pilot = PILOT_9V;
+            if (cp_check_voltage(6) == true) control_pilot = PILOT_6V;
+            if (reset_charger == true) control_pilot = PILOT_RESET;
+        }
+// ************************************************************
+// *        Switching PWM Cycle & TEST Counter Timer          *                                                                                                    
+// ************************************************************        
+//      if (use_upper_current == false) pwm_duty_cycle = pwm_duty_low;
+//      if (use_upper_current == true) pwm_duty_cycle = pwm_duty_high;
+//        
+//      if (TESTCOUNTER > 1800) control_pilot = PWM_CHANGE; // Each cycle takes approximately 1 second, so 1800 seconds is a change of pwm every 30 mins or so.              
+//      * TESTERCOUNTER monitoring is switched of for the Smartcharge Home+ charger, PWN cycle based on a cable inserted      
+//  
+// ************************************************************ 
+ 
+// ************************************************************
+// *            PWM cycle basen on cable instered             *                                                                                                    
+// ************************************************************  
+        if (cable_32A == false) pwm_duty_cycle = pwm_duty_low;
+        if (cable_32A == true) pwm_duty_cycle = pwm_duty_high;
+ 
+ 
+ 
+        switch(control_pilot) 
+        {
+            case PILOT_12V:
+                contactor = 0;
+                lock = 0;
+                red = 0;
+                green = 0;
+                blue = 1;
+                my_pwm = 0;
+                pwm_state = false;
+                pc.printf("Charger in STATE A. \r\n");
+                pc.printf("PILOT_12V - Pilot at 12 V. \r\n");
+                TESTCOUNTER = 0;
+            break;
+  
+            case PILOT_9V:
+                contactor = 0;
+                //relay=0;
+                lock = 1;
+                red = 1;
+                green = 1;
+                blue = 0;
+                if (pwm_state == false)
+                {
+                    my_pwm.period_us(1000);
+                    my_pwm.pulsewidth_us(1000);
+                    my_pwm.write(pwm_duty_cycle);
+                pwm_state = true;
+                }
+                pc.printf("PWM duty cycle is at: %.1f  %% \r\n", 100-pwm_duty_cycle*100);
+                pc.printf("Charger in STATE B. \r\n");
+                pc.printf("PILOT_9V - Pilot at 9 V. \r\n");
+                TESTCOUNTER = 0;
+            break;
+                
+            case PILOT_6V:
+                contactor = 1;
+                relay = 1;
+                lock = 1;
+                red = 0;
+                green = 1;
+                blue = 0;
+                if (pwm_state == false)
+                {
+                    my_pwm.period_us(1000);
+                    my_pwm.pulsewidth_us(1000);
+                    my_pwm.write(pwm_duty_cycle);
+                    pwm_state = true;
+                }
+                pc.printf("PWM duty cycle is at: %.1f  %% \r\n", 100-pwm_duty_cycle*100);
+                pc.printf("Charger in STATE C. \r\n");
+                pc.printf("PILOT_6V - Pilot at 6 V. \r\n");
+//              TESTCOUNTER+=1;
+//              * TESTCOUNTER switched of
+                pc.printf("TESTCOUNTER timer: %u seconds  \r\n", TESTCOUNTER);
+            break;
+                   
+            case PILOT_NOK:
+                lock = 0;
+                red = 1;
+                green = 0;
+                blue = 0;
+                pc.printf("Error. \r\n");
+                pc.printf("PILOT_NOK - Pilot ERROR. \r\n");
+                TESTCOUNTER = 0;
+            break;
+            
+            case PILOT_RESET:
+                contactor = 0;
+                relay = 0;
+                lock = 0;
+                red = 0;
+                green = 0;
+                blue = 1;
+                my_pwm.period_ms(1);
+                my_pwm.pulsewidth_ms(1);
+                my_pwm.write(1);
+                pwm_state = false;
+                pc.printf("RESET IMPLEMENTED. \r\n");
+                pc.printf("PILOT_RESET - Pilot at -12V. \r\n");
+                wait(0.5); // 500 ms
+                red = 0; // LED is OFF
+                wait(0.2); // 200 ms
+                TESTCOUNTER = 0;
+                use_upper_current = false;
+            break;
+            
+            case PWM_CHANGE:
+                lock = 1;
+                contactor = 0;
+                red = 1;
+                green = 1;
+                blue = 1;
+                wait(0.1);
+                pc.printf("Charger changing PWM. \r\n");
+                my_pwm.period_ms(1);
+                my_pwm.pulsewidth_ms(1);
+                my_pwm.write(1);
+                wait(1);
+                pc.printf("STOPPED PWM - Switching to -12 V. \r\n");
+                my_pwm = 0;
+                pc.printf("STOPPED PWM - Switching to +12 V. \r\n");
+                wait(1);
+                pwm_state = false;
+                TESTCOUNTER = 0;
+                if(use_upper_current == false) 
+                {
+                   use_upper_current = true;
+                }
+                else
+                {
+                    use_upper_current = false;
+                }
+            break;  
+        }        
+        pc.printf("#################\r\n");
+        //wait(1);      // wait(); added to slow down the feed from nucleo for easier evaluation
+    }
+}
\ No newline at end of file