This charger will charge battery or super-cap to either pre-programmed voltage or to the voltage of the cell that we want to match (<3.3V). The charged cell/super-cap can be charged up to 4V. Charge current can be chosen to be either 8mA or 25mA. These are max charging current for Tadiran HLC batteries of 2 sizes (hybrid rechargeable cell and super-cap). This was just a project to learn; no use in production settings, maybe usefull for R&D.
main.cpp@1:822b4281ebbb, 2014-03-01 (annotated)
- Committer:
- krzysiekf
- Date:
- Sat Mar 01 20:03:11 2014 +0000
- Revision:
- 1:822b4281ebbb
- Parent:
- 0:763f2afa5e8b
this one has improved "Charging" work. Steady when controlling current, blinking with low frequency when topping off.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
krzysiekf | 0:763f2afa5e8b | 1 | #include "mbed.h" |
krzysiekf | 0:763f2afa5e8b | 2 | |
krzysiekf | 0:763f2afa5e8b | 3 | DigitalOut o5(p5);//o5 through o14 and o30 set as outputs to prevent any coupling of the external noise |
krzysiekf | 0:763f2afa5e8b | 4 | DigitalOut o6(p6); |
krzysiekf | 0:763f2afa5e8b | 5 | DigitalOut o7(p7); |
krzysiekf | 0:763f2afa5e8b | 6 | DigitalOut o8(p8); |
krzysiekf | 0:763f2afa5e8b | 7 | DigitalOut o9(p9); |
krzysiekf | 0:763f2afa5e8b | 8 | DigitalOut o10(p10); |
krzysiekf | 0:763f2afa5e8b | 9 | DigitalOut o11(p11); |
krzysiekf | 0:763f2afa5e8b | 10 | DigitalOut o12(p12); |
krzysiekf | 0:763f2afa5e8b | 11 | DigitalOut o13(p13); |
krzysiekf | 0:763f2afa5e8b | 12 | DigitalOut o14(p14); |
krzysiekf | 0:763f2afa5e8b | 13 | DigitalOut o30(p30); |
krzysiekf | 0:763f2afa5e8b | 14 | |
krzysiekf | 0:763f2afa5e8b | 15 | PwmOut chrg(p21);//PWM output |
krzysiekf | 0:763f2afa5e8b | 16 | |
krzysiekf | 0:763f2afa5e8b | 17 | AnalogIn vrsIn(p16);//rectified voltage measurement, high side of sense resistor |
krzysiekf | 0:763f2afa5e8b | 18 | AnalogIn vrsOut(p17);//charged battery voltage measurement, low side of sense resistor |
krzysiekf | 0:763f2afa5e8b | 19 | AnalogIn sens(p15);//sense Primary Cell voltage |
krzysiekf | 0:763f2afa5e8b | 20 | |
krzysiekf | 0:763f2afa5e8b | 21 | DigitalIn s1(p22);//switch for togling START/STOP |
krzysiekf | 0:763f2afa5e8b | 22 | DigitalIn s2(p23);//switch for togling between 8 and 25mA |
krzysiekf | 0:763f2afa5e8b | 23 | DigitalIn s3(p19);//switch for togling PrimCell/ProgVolt |
krzysiekf | 0:763f2afa5e8b | 24 | |
krzysiekf | 0:763f2afa5e8b | 25 | DigitalOut PrimCellInd(p20);//Primary Cell sensed voltage chosen as limit for HLC battery |
krzysiekf | 0:763f2afa5e8b | 26 | DigitalOut ProgVoltInd(p18);//Programmed Voltage chosen as limit for HLC battery |
krzysiekf | 0:763f2afa5e8b | 27 | |
krzysiekf | 0:763f2afa5e8b | 28 | DigitalOut chrgInd(p26);//indicates real time charging; only on when PWM was issued |
krzysiekf | 0:763f2afa5e8b | 29 | |
krzysiekf | 0:763f2afa5e8b | 30 | DigitalOut Rs1EnInd(p25);//indicator for 8mA charge current |
krzysiekf | 0:763f2afa5e8b | 31 | DigitalOut Rs1En(p27);//enable 8mA sense resistor |
krzysiekf | 0:763f2afa5e8b | 32 | |
krzysiekf | 0:763f2afa5e8b | 33 | DigitalOut Rs2EnInd(p24);//indicator for 25mA charge current |
krzysiekf | 0:763f2afa5e8b | 34 | DigitalOut Rs2En(p28);//enable 25mA sense resistor |
krzysiekf | 0:763f2afa5e8b | 35 | |
krzysiekf | 0:763f2afa5e8b | 36 | DigitalOut hlcEn(p29);//enable HLC for charging |
krzysiekf | 0:763f2afa5e8b | 37 | |
krzysiekf | 0:763f2afa5e8b | 38 | int main() |
krzysiekf | 0:763f2afa5e8b | 39 | { |
krzysiekf | 0:763f2afa5e8b | 40 | hlcEn=0; |
krzysiekf | 0:763f2afa5e8b | 41 | Rs1En=0; |
krzysiekf | 0:763f2afa5e8b | 42 | Rs2En=0; |
krzysiekf | 0:763f2afa5e8b | 43 | wait(1); |
krzysiekf | 0:763f2afa5e8b | 44 | float Vprog=3.65;//arbitrary voltage chosen for testing purposes; this is the voltage of the battery to be charged that should be never exceeded |
krzysiekf | 0:763f2afa5e8b | 45 | float tempChrg=0.0;//temporary holding of the PWM Duty Cycle level |
krzysiekf | 0:763f2afa5e8b | 46 | float chrgIncr=0.0;//temporary holding of the PWM increment Duty Cycle |
krzysiekf | 0:763f2afa5e8b | 47 | |
krzysiekf | 0:763f2afa5e8b | 48 | o5=0;//o5 through o14 and o30 set to output "0" (GND) |
krzysiekf | 0:763f2afa5e8b | 49 | o6=0; |
krzysiekf | 0:763f2afa5e8b | 50 | o7=0; |
krzysiekf | 0:763f2afa5e8b | 51 | o8=0; |
krzysiekf | 0:763f2afa5e8b | 52 | o9=0; |
krzysiekf | 0:763f2afa5e8b | 53 | o10=0; |
krzysiekf | 0:763f2afa5e8b | 54 | o11=0; |
krzysiekf | 0:763f2afa5e8b | 55 | o12=0; |
krzysiekf | 0:763f2afa5e8b | 56 | o13=0; |
krzysiekf | 0:763f2afa5e8b | 57 | o14=0; |
krzysiekf | 0:763f2afa5e8b | 58 | o30=0; |
krzysiekf | 0:763f2afa5e8b | 59 | |
krzysiekf | 0:763f2afa5e8b | 60 | float k=3;//default scaling factor for Vrs measurements |
krzysiekf | 0:763f2afa5e8b | 61 | |
krzysiekf | 0:763f2afa5e8b | 62 | float Vmax=Vprog;//holding of, either, Primary Cell sensed voltage or Programmed Voltage |
krzysiekf | 0:763f2afa5e8b | 63 | float Vsens=0;//holding of Primary Cell sensed voltage |
krzysiekf | 0:763f2afa5e8b | 64 | |
krzysiekf | 0:763f2afa5e8b | 65 | chrg.period_ms(1);//PWM period |
krzysiekf | 0:763f2afa5e8b | 66 | |
krzysiekf | 0:763f2afa5e8b | 67 | char s1State=0;//the soft state of s1 switch; charging stopped as default |
krzysiekf | 0:763f2afa5e8b | 68 | char s2State=0;//the soft state of s2 switch; Rs1 enabled, Rs2 disabled as default |
krzysiekf | 0:763f2afa5e8b | 69 | char s3State=0;//the soft state of s3 switch; Vprog enabled as dafult |
krzysiekf | 0:763f2afa5e8b | 70 | |
krzysiekf | 0:763f2afa5e8b | 71 | float VrsIn=0;//measured voltage after rectification and filtering |
krzysiekf | 0:763f2afa5e8b | 72 | float VrsOut=0;//measured voltage on charged battery side |
krzysiekf | 0:763f2afa5e8b | 73 | float Vrs=3; |
krzysiekf | 0:763f2afa5e8b | 74 | float Vrsdrop=0; |
krzysiekf | 0:763f2afa5e8b | 75 | |
krzysiekf | 0:763f2afa5e8b | 76 | hlcEn=0;//turn off all externals |
krzysiekf | 0:763f2afa5e8b | 77 | |
krzysiekf | 0:763f2afa5e8b | 78 | Rs1En=1;//enable 8mA charge current as default |
krzysiekf | 0:763f2afa5e8b | 79 | wait_us(1); |
krzysiekf | 0:763f2afa5e8b | 80 | Rs1EnInd=Rs1En;//light up 8mA indicator |
krzysiekf | 0:763f2afa5e8b | 81 | |
krzysiekf | 0:763f2afa5e8b | 82 | Rs2En=0;//disable 25mA charge current as default |
krzysiekf | 0:763f2afa5e8b | 83 | wait_us(1); |
krzysiekf | 0:763f2afa5e8b | 84 | Rs2EnInd=Rs2En;//turn off 25mA indicator |
krzysiekf | 0:763f2afa5e8b | 85 | |
krzysiekf | 0:763f2afa5e8b | 86 | ProgVoltInd=1;//light up Programmed Voltage chosen indicator as a default |
krzysiekf | 0:763f2afa5e8b | 87 | PrimCellInd=0;//turn off the Primary Cell Sensed Voltage indicator as a default |
krzysiekf | 0:763f2afa5e8b | 88 | |
krzysiekf | 0:763f2afa5e8b | 89 | while(1) { |
krzysiekf | 0:763f2afa5e8b | 90 | chrg=0.0;//start conditions after reset |
krzysiekf | 0:763f2afa5e8b | 91 | chrgInd=0; |
krzysiekf | 0:763f2afa5e8b | 92 | chrgIncr=0.0; |
krzysiekf | 0:763f2afa5e8b | 93 | tempChrg=0.0; |
krzysiekf | 0:763f2afa5e8b | 94 | |
krzysiekf | 0:763f2afa5e8b | 95 | if(!s1) { //s1 being pressed; Start/Stop charging |
krzysiekf | 0:763f2afa5e8b | 96 | s1State=!s1State;//flip the soft state of s1 |
krzysiekf | 0:763f2afa5e8b | 97 | wait_us(10);//delay to allow reading of the s1State after flip |
krzysiekf | 0:763f2afa5e8b | 98 | while(!s1)wait(0.3); |
krzysiekf | 0:763f2afa5e8b | 99 | } |
krzysiekf | 0:763f2afa5e8b | 100 | if(!s2) { //s2 being pressed; choose charge current level between 8mA and 25mA |
krzysiekf | 0:763f2afa5e8b | 101 | s2State=!s2State;//TRUE after first press |
krzysiekf | 0:763f2afa5e8b | 102 | wait_us(10); |
krzysiekf | 0:763f2afa5e8b | 103 | if(s2State) {//TRUE for Rs2:25mA |
krzysiekf | 0:763f2afa5e8b | 104 | wait_us(10); |
krzysiekf | 0:763f2afa5e8b | 105 | Rs1En=0;//disable Rs1:8mA |
krzysiekf | 0:763f2afa5e8b | 106 | Rs2En=1;//enable Rs2:25mA charging current |
krzysiekf | 0:763f2afa5e8b | 107 | Rs1EnInd=0;//turn off the Rs1 indicator |
krzysiekf | 0:763f2afa5e8b | 108 | Rs2EnInd=1;//turn on the Rs2 indicator |
krzysiekf | 0:763f2afa5e8b | 109 | } else {//TRUE for Rs1:8mA |
krzysiekf | 0:763f2afa5e8b | 110 | wait_us(10); |
krzysiekf | 0:763f2afa5e8b | 111 | Rs1En=1;//enable Rs1:8mA charging current |
krzysiekf | 0:763f2afa5e8b | 112 | Rs2En=0;//disable Rs2:25mA |
krzysiekf | 0:763f2afa5e8b | 113 | Rs1EnInd=1;//turn on the Rs1 indicator |
krzysiekf | 0:763f2afa5e8b | 114 | Rs2EnInd=0;//turn off the Rs2 indicator |
krzysiekf | 0:763f2afa5e8b | 115 | } |
krzysiekf | 0:763f2afa5e8b | 116 | while(!s2)wait(0.3); |
krzysiekf | 0:763f2afa5e8b | 117 | } |
krzysiekf | 0:763f2afa5e8b | 118 | if(!s3) { |
krzysiekf | 0:763f2afa5e8b | 119 | s3State=!s3State;//TRUE after first press |
krzysiekf | 0:763f2afa5e8b | 120 | wait_us(10); |
krzysiekf | 0:763f2afa5e8b | 121 | if(s3State) {//TRUE for Primary Cell sense |
krzysiekf | 0:763f2afa5e8b | 122 | Vsens=sens.read()*3.3;//read Primary Cell voltage |
krzysiekf | 0:763f2afa5e8b | 123 | wait_us(50); |
krzysiekf | 0:763f2afa5e8b | 124 | Vmax=Vsens;//use Primary Cell voltage as a limit for battery being charged |
krzysiekf | 0:763f2afa5e8b | 125 | PrimCellInd=1;//Turn on Primary Cell voltage indicator |
krzysiekf | 0:763f2afa5e8b | 126 | ProgVoltInd=0;//turn off Programmed Voltage indicator |
krzysiekf | 0:763f2afa5e8b | 127 | } else { |
krzysiekf | 0:763f2afa5e8b | 128 | Vmax=Vprog;//Programmed Voltage is being used as a limit for battery being charged |
krzysiekf | 0:763f2afa5e8b | 129 | PrimCellInd=0;//turn off Primary Cell indicator |
krzysiekf | 0:763f2afa5e8b | 130 | ProgVoltInd=1;//turn on Programmed Voltage indicator |
krzysiekf | 0:763f2afa5e8b | 131 | } |
krzysiekf | 0:763f2afa5e8b | 132 | wait(.3); |
krzysiekf | 0:763f2afa5e8b | 133 | } |
krzysiekf | 0:763f2afa5e8b | 134 | if(s1State) {//start charging process if soft state of s1 is TRUE |
krzysiekf | 0:763f2afa5e8b | 135 | do { |
krzysiekf | 0:763f2afa5e8b | 136 | if(!s1) {//stop charging if s1 is pressed during charging |
krzysiekf | 0:763f2afa5e8b | 137 | chrgInd=0; |
krzysiekf | 0:763f2afa5e8b | 138 | s1State=0; |
krzysiekf | 0:763f2afa5e8b | 139 | hlcEn=0; |
krzysiekf | 0:763f2afa5e8b | 140 | while(!s1)wait(0.3); |
krzysiekf | 0:763f2afa5e8b | 141 | break; |
krzysiekf | 0:763f2afa5e8b | 142 | } |
krzysiekf | 0:763f2afa5e8b | 143 | hlcEn=1; |
krzysiekf | 0:763f2afa5e8b | 144 | chrgInd=0; |
krzysiekf | 0:763f2afa5e8b | 145 | tempChrg=chrg; |
krzysiekf | 0:763f2afa5e8b | 146 | chrg=0; |
krzysiekf | 0:763f2afa5e8b | 147 | hlcEn=0; |
krzysiekf | 0:763f2afa5e8b | 148 | Rs1En=0; |
krzysiekf | 0:763f2afa5e8b | 149 | Rs2En=0; |
krzysiekf | 0:763f2afa5e8b | 150 | wait_us(10); |
krzysiekf | 0:763f2afa5e8b | 151 | VrsOut=vrsOut.read()*3.3*k;//measure voltage of the charged battery |
krzysiekf | 0:763f2afa5e8b | 152 | VrsIn=vrsIn.read()*3.3*k;//measure the rectified voltage |
krzysiekf | 0:763f2afa5e8b | 153 | wait_us(10); |
krzysiekf | 0:763f2afa5e8b | 154 | Vrsdrop=VrsIn-VrsOut; |
krzysiekf | 0:763f2afa5e8b | 155 | chrg=tempChrg;//resume charging at current charging level |
krzysiekf | 0:763f2afa5e8b | 156 | if(s2State)Rs2En=1; |
krzysiekf | 0:763f2afa5e8b | 157 | if(!s2State)Rs1En=1; |
krzysiekf | 0:763f2afa5e8b | 158 | if(Vrsdrop<Vrs) { |
krzysiekf | 0:763f2afa5e8b | 159 | hlcEn=1; |
krzysiekf | 1:822b4281ebbb | 160 | chrgInd=1; |
krzysiekf | 0:763f2afa5e8b | 161 | chrgIncr=0.001; |
krzysiekf | 0:763f2afa5e8b | 162 | wait_ms(10); |
krzysiekf | 0:763f2afa5e8b | 163 | chrg=chrg+chrgIncr; |
krzysiekf | 0:763f2afa5e8b | 164 | } |
krzysiekf | 0:763f2afa5e8b | 165 | } while(VrsOut<Vmax); |
krzysiekf | 1:822b4281ebbb | 166 | chrgInd=0; |
krzysiekf | 0:763f2afa5e8b | 167 | wait(0.5); |
krzysiekf | 0:763f2afa5e8b | 168 | } |
krzysiekf | 0:763f2afa5e8b | 169 | } |
krzysiekf | 0:763f2afa5e8b | 170 | } |