SmartCharge
/
2017charger_16ampONLY
single current only
main.cpp
- Committer:
- magdamcn
- Date:
- 2017-02-06
- Revision:
- 4:41573ae73f98
- Parent:
- 3:bd056c7b3498
- Child:
- 5:3298063f12fe
File content as of revision 4:41573ae73f98:
////////////////////////////////////////// // Copyright (c) 2017 Smartcharge Ltd // ////////////////////////////////////////// // >>CONVEX 2017rev1 build<< // // >> 16 AMP only << // // MAIN FEATURES: // // - watchdog // // - 3 sec reset button // // - 16 Amp Charging // // - 9V & 6V timers not applied // // in this revision, line 315&325 // // - error when voltage out of range // // cp_check_voltage(); // ////////////////////////////////////////// #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 CHARGER_CURRENT 16 // Sets the lower current value desired. float pwm_duty_cycle = 1.0-((CHARGER_CURRENT / 30.0) * 0.5); // Calculates the float pwm duty cycle for the desired charger current. // ************************************************************ // * 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. #define PILOT_START_AGAIN 7 // Restart charger if stuck in stateB - 9V for defined amount of time. // ************************************************************ // * 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. int stateB_COUNTER = 0; // Variable to count number of cycles of main loop. Used to reset charger from state B - 9V to state A and re-initiate charging. // ************************************************************ // * 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_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). 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"); } 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 (cp_check_voltage(12) == false && cp_check_voltage(-12) == false)control_pilot = PILOT_NOK; // voltage not at 12 or -12, error accured } if (cable_connected == true) { if (cp_check_voltage(12) == true) control_pilot = PILOT_12V; 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; // if (out of range) control_pilot = PILOT_NOK; // voltage not at expected values, error accured } // ************************************************************ // * 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 based on cable instered * // ************************************************************ //if (stateB_COUNTER > 3600) control_pilot = PILOT_START_AGAIN; // Each cycle takes approximately 1 second, so 3600 seconds is a change of pwm every hour or so. //9V monitorin & time reser disabled for this version switch(control_pilot) { case PILOT_12V: contactor = 0; lock = 0; red = 0; green = 0; blue = 1; my_pwm = 0; my_pwm.write(0); pwm_state = false; pc.printf("Charger in STATE:------------------------------------------------ A. \r\n"); pc.printf("PILOT_12V - Pilot at 12 V. \r\n"); TESTCOUNTER =0; pc.printf("TESTCOUNTER timer:----------------------------------- %u seconds \r\n", TESTCOUNTER); stateB_COUNTER =0; pc.printf("stateB_COUNTER timer:-------------------------------- %u seconds \r\n", stateB_COUNTER); 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; pc.printf("TESTCOUNTER timer:----------------------------------- %u seconds \r\n", TESTCOUNTER); //stateB_COUNTER+=1; pc.printf("stateB_COUNTER timer: ------------------------------- %u seconds \r\n", stateB_COUNTER); 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); stateB_COUNTER = 0; pc.printf("stateB_COUNTER timer:-------------------------------- %u seconds \r\n", stateB_COUNTER); break; case PILOT_NOK: contactor = 0; relay = 0; lock = 0; my_pwm.period_ms(1); my_pwm.pulsewidth_ms(1); my_pwm.write(1); pwm_state = false; red = 1; green = 0; blue = 0; wait(0.5); // 500 ms red = 0; // LED is OFF wait(0.2); // 200 ms pc.printf("Error. \r\n"); pc.printf("PILOT_NOK:------------------------------------------------------- Pilot ERROR. \r\n"); TESTCOUNTER =0; pc.printf("TESTCOUNTER timer:----------------------------------- %u seconds \r\n", TESTCOUNTER); stateB_COUNTER =0; pc.printf("stateB_COUNTER timer:-------------------------------- %u seconds \r\n", stateB_COUNTER); 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 blue = 0; // LED is OFF wait(0.2); // 200 ms TESTCOUNTER =0; pc.printf("TESTCOUNTER timer:----------------------------------- %u seconds \r\n", TESTCOUNTER); stateB_COUNTER =0; pc.printf("stateB_COUNTER timer:-------------------------------- %u seconds \r\n", stateB_COUNTER); break; case PILOT_START_AGAIN: red = 1; green = 0; blue = 1; wait(0.1); pc.printf("Charger:--------------------------------------------------------- RESTARTING stat B - 9V. \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; pc.printf("TESTCOUNTER timer:----------------------------------- %u seconds \r\n", TESTCOUNTER); stateB_COUNTER =0; pc.printf("stateB_COUNTER timer:-------------------------------- %u seconds \r\n", stateB_COUNTER); break; } pc.printf("#################\r\n"); //wait(1); // wait(); added to slow down the feed from nucleo for easier evaluation } }