/* Battery cycler By Greg Fordyce Version 0.02 Arduino 0017 on ATmega168 - 120909 - www.go-ev.co.uk/projects/batteryCycler/ Binary sketch size: 6224 bytes (of a 14336 byte maximum) **************************** General Information ****************************** The Battery Cycler carries no warranty or guarantee of any kind! This is used at your own risk, and I make no claims as to its suitability for a particular function. Prospective users must evaluate the system before using it, and no liability will be entertained by myself in any shape or form whatsoever. The Battery Cycler and software have been produced at low cost for the benefit of the EV & electronic community. The software is available free via the internet. Users may modify or adapt the system as they see fit. Improperly charging or discharging batteries could cause a fire and/or explosion! If you are not fully competent to work on potentially lethal battery systems and high voltages, then do not experiment with or use this system. Do not use this device unattended! ************************** TellyMate shield ************************** TellyMate screen 38x25 characters */ #include // MsTimer2 library. int pot = 0; // Input potentiometer on analogue pin 0 int battVolt = 1; // Battery voltage read on analogue pin 1 int currentRef = 2; // LEM refernce voltage (ref = 0 amps) on analogue pin 2 int battCurrent = 3; // Battery current on analogue pin 3 int button = 2; // Input push button on digital pin 2 int charge = 5; // Charge IGBT on pin5 int discharge = 6; // Discharge IGBT on pin 6 int Mode = 0; // 0 = Automatic cycle, 1 = Charge only, 2 = Discharge only int Idis = 0; // Discharge current (1-100 amps) int Vlo = 0; // Discharge ending voltage (1-12 volts, 0.1 div) int Timer = 0; // Max charging time (10 minute to 2,550 minutes) int Ibulk = 0; // Stage 1 bulk charging amps (1-100 amps) int Vfin = 0; // Stage 2 constant voltage level (1-16 volts, 0.1 div) int Ifin = 0; // Stage 3 timer starts when current drops below this level (0-20 amps, 0.1 div) int TmrStg3 = 0; // Stage 3 timer (0-240 minutes) int Voltage = 0; // Battery voltage int Current = 0; // Battery current int AmpCount = 0; // Battery capacity in amps/sec int IGBT = 0; // Control value for IGBTs //unsigned long time1; // Timer used to calculate amp/sec /* TellyMate helper functions */ #define CHAR_ESC "\x1B" void cursor_move( uint8_t row , uint8_t col ) { // Yrc Serial.print( CHAR_ESC "Y" ) ; Serial.print((unsigned char)(32 + row)) ; Serial.print((unsigned char)(32 + col)) ; } void cursor_show( bool show ) { // e or f Serial.print( CHAR_ESC ) ; Serial.print( show?'e':'f' ) ; } void screen_clear( void ) { // E Serial.print( CHAR_ESC "E" ); } void setup() //run this section once. { pinMode(charge, OUTPUT); //Set chargeIGBT pin to output pinMode(discharge, OUTPUT); //Set dischargeIGBT pin to output Serial.begin( 57600 ) ; // set to 57600 baud screen_clear() ; cursor_show( false ) ; // turn the cursor off cursor_move(14,0); Serial.print("Cycler Mode.................."); do { // Select cycler mode Mode = map(analogRead(pot),0,1023,0,2); // Scales analog value to a range between 0 and 2 cursor_move(14,30); Serial.print(Mode); // print the result: delay(100); // wait 100 milliseconds } while (digitalRead(button) == LOW); // Store value and exit loop when button is pressed delay(100); cursor_move(15,0); Serial.print("Discharge Amps............... Amps"); do { // Set discharge amps Idis = map(analogRead(pot),0,1023,0,100); // Scales analog value to a range between 0 and 100 cursor_move(15,26); Serial.print(" "); // clear old value cursor_move(15,26); Serial.print(Idis); // print the result: delay(100); // wait 100 milliseconds } while (digitalRead(button) == LOW); // Store value and exit loop when button is pressed delay(100); cursor_move(16,0); Serial.print("Ending Voltage.............. Volt/10"); do { // Set discharge ending voltage (1-12 volts, 0.1 div) Vlo = map(analogRead(pot),0,1023,10,120); // Scales analog value to a range between 10 and 120 cursor_move(16,26); Serial.print(" "); // clear old value cursor_move(16,26); Serial.print(Vlo); // print the result: delay(100); // wait 100 milliseconds } while (digitalRead(button) == LOW); // Store value and exit loop when button is pressed delay(100); cursor_move(17,0); Serial.print("Max Charging time............ x10 min"); do { // Set max charging time (10 minute to 2,550 minutes) Timer = map(analogRead(pot),0,1023,0,255); // Scales analog value to a range between 0 and 255 cursor_move(17,26); Serial.print(" "); // clear old value cursor_move(17,26); Serial.print(Timer); // print the result: delay(100); // wait 100 milliseconds } while (digitalRead(button) == LOW); // Store value and exit loop when button is pressed delay(100); cursor_move(18,0); Serial.print("Charging Amps (CC stage)..... Amps"); do { // Set stage 1 bulk charging amps (1-100 amps) Ibulk = map(analogRead(pot),0,1023,1,100); // Scales analog value to a range between 0 and 100 cursor_move(18,26); Serial.print(" "); // clear old value cursor_move(18,26); Serial.print(Ibulk); // print the result: delay(100); // wait 100 milliseconds } while (digitalRead(button) == LOW); // Store value and exit loop when button is pressed delay(100); cursor_move(19,0); Serial.print("Charging Voltage............ volt/10"); do { // Set stage 2 constant voltage level (1-16 volts, 0.1 div) Vfin = map(analogRead(pot),0,1023,10,160); // Scales analog value to a range between 0 and 100 cursor_move(19,26); Serial.print(" "); // clear old value cursor_move(19,26); Serial.print(Vfin); // print the result: delay(100); // wait 100 milliseconds } while (digitalRead(button) == LOW); // Store value and exit loop when button is pressed delay(100); cursor_move(20,0); Serial.print("Current to start timer.... Amps/10"); do { // Set stage 3 timer, starts when current drops below this level Ifin = map(analogRead(pot),0,1023,0,200); // Scales analog value to a range between 0 and 200 cursor_move(20,26); Serial.print(" "); // clear old value cursor_move(20,26); Serial.print(Ifin); // print the result: delay(100); // wait 100 milliseconds } while (digitalRead(button) == LOW); // Store value and exit loop when button is pressed delay(100); cursor_move(21,0); Serial.print("Constant Volt Timer.......... min"); do { // Set TmrStg3 = 0; // Stage 3 timer (0-255 minutes) TmrStg3 = map(analogRead(pot),0,1023,0,255); // Scales analog value to a range between 0 and 255 cursor_move(21,26); Serial.print(" "); // clear old value cursor_move(21,26); Serial.print(TmrStg3); // print the result: delay(100); // wait 100 milliseconds } while (digitalRead(button) == LOW); // Store value and exit loop when button is pressed delay(100); /**********Discharge routine*******************************************/ // time1 = millis() + 1000; // Load starting time for discharge loop and add 1 second to value // millis() returns milliseconds since program execution started // Overflows after about 50 days, so not a problem for this sketch cursor_move(1,0); Serial.print(" Volts amps IGBT "); MsTimer2::set(1000, ampcounter); // 500ms period MsTimer2::start(); do { Voltage = map(analogRead(battVolt),0,1023,0,150); // Read battery voltage delay(10); int lasR = analogRead(currentRef); // Read zero reference voltage from current sensor delay(10); int lasM = analogRead(battCurrent); // Read current value from sensor // NOTE: THIS VALUE STILL NEEDS TO BE SCALED TO A ACTUALL CURRENT VALUE // AT THE MOMENT THIS VALUE IS THE RAW ANALOG VALUE! delay(10); Current = lasM - lasR; // note above applies here as well. //delay(200); if (IGBT > 0 && Current > Idis) IGBT --; // Decrease value of IGBT by 1 if IGBT value is > 0 AND // Current is > Idis if (IGBT < 255 && Current < Idis) IGBT ++; // Increase value of IGBT by 1 if IGBT value is < 255 // AND Current is < Idis cursor_move(0,15); Serial.print(IGBT); // Diagnostic output // Serial.print(" "); // Diagnostic output // Serial.print(time1); // Diagnostic output analogWrite(discharge, IGBT); // Set discharge pin pwm output to IGBT value delay(10); // if (time1 >= millis()) { // Once every second jump to ampcounter function // ampcounter() ; // time1 = time1 + 1000; // Increment timer variable by 1 second // // } } while(Voltage > Vlo); // Continue loop until battery voltage is no longer greater than Vlo value analogWrite(discharge, 0); // Turn off discharge IGBT cursor_move(3,0); Serial.println(" FINISHED "); Serial.print(AmpCount); // Print out value of AmpCount (Amps/second) // Final version will convert to A/hrs } void loop() { } void ampcounter( void ) { // Once a second calculate A/sec and update display // TODO: add datalogger output here to SD Card as well AmpCount = AmpCount + Current ; // Add battery current value for last second to ampcount total cursor_move(0,0); Serial.print(" "); // Clear old values cursor_move(0,0); Serial.print(Voltage); // Battery voltage output cursor_move(0,10); Serial.print(Current); // Current output cursor_move(0,25); Serial.print(AmpCount); // Current output }