本帖最后由 sunany 于 2013-5-3 23:01 编辑
五一在家里闲暇之余,想起了我前段时间买的一个移动电源,据说是香港的专利设计,转换效率极低,给手机充电外壳可以煮鸡蛋,同时三个LED还不时的闪烁,整体充电效率估计都不到60%。心想要不就是山寨要不就是二货设计。
心痒痒,决定把升压和充电部分更改。
当然,这个移动电源好处就是外形设计比较漂亮,两节18650的电芯可以拆下来、USB充电口,这样连带我18650的手电外出方便至极。
先上PP:
从图片可以看出,虽然主控板看上去极为复杂,但仔细分析无非就充电部分MCU+MOS,升压部分用了垃圾的电路(从使用的电感可见),电量显示板则用单片机的I/O口点灯实现。
4月30号下午开工(测绘原板外形及设计电路图): 首先针对高性能的升压效率,升压用凌特尔LTC1700+MOSFET来实现,升压效率可达95%以上(实测90%)。 第二,充电及电量显示方案有三: 方案一:用ATmega8单片机+MOSFET设计充电,同时用单片机的I/O口配合单片机内部的10位ADC进行电量显示。 方案二:用max1879+MOSFET设计充电,同时用LM3914N+LED硬件进行电量显示。 方案三:用max1879+MOSFET设计充电,用Atiny13 MCU的五个I/O口配合内部ADC做电量显示。 对比上述三种方案,从成本考虑方案一为最优选择,从难易度考虑方案二为最简,方案三则具备上述两个方案的优点。同时因为高老师上次送我tiny系列MCU的高压串行编程器,可以对tiny13的rst引脚进行编程,所以确定按方案三进行设计。
用Altium进行电路及电路板设计:
充电电路及LED显示电路PCB板设计,按原有电路板外形测绘,因单面板无法完成布局,只能整成双面板,画图示要考虑DIY的难易程度,同时考验我制板手艺的时刻到了。
5月1号上午(DIY电路板): 首先将已设计完成的PCB电路板打印:
硒鼓好,打印的笨清晰。
第二步:用家里的电运斗将打印的正面板转印到双面板的其中一面,完成正面转印后钻下四个定位孔,同时在打印的反面板上打四个相应的定位孔,将纸上四个孔和板上四个孔对应后粘好固定(其实体现DIY双面板水平就在对孔这一道工序)。固定完成用电运斗转印第二面。 第三步:腐蚀电路板,将上步已转印完成的双面板放入FECL3液,加上热水腐蚀,整个腐蚀过程大概要30分钟。
第四步:焊接,双面板过孔采用导线穿孔形式实现,注意走大电流处要多打几个孔。焊完后整体电路板:
5月1号中午:
忙了一上午,累了,陪娃娃玩会就睡着了,醒来是大概三点。
开始改LED电显示的程序。原来的移动电源只带3个LED,所以我那5个LED有点浪费了,但又觉的每33%显示档有点太对不起我的MCU,所以突发奇想还是整成5个档位显示电亮,每个灯长亮、闪烁及熄灭分成三态,最后面一个灯闪烁时频率加大,表示电显已经危险(正好高老师送我的高压编程器没搞定,RST脚不用也不影响)。
搞定,贴上原代码:
//ICC-AVR application builder : // Target : T13 // Crystal: 4.8000Mhz //Author:Sunany //Date:2013-5-1
#include <iot13v.h> #include <macros.h>
unsigned int ADC_data=0; unsigned char flag_low_bat=0;
void port_init(void) { DDRB = 0b00111011; PORTB = 0b00111011; }
void timer0_init(void) { TCCR0B = 0x00; //stop TCNT0 = 0xB4; //set count TCCR0A = 0x00; TCCR0B = 0x03; //start timer }
//ADC initialize void adc_init(void) { ADCSRA = 0x00; //disable adc ADMUX = (1<<REFS0); //采用内部REF ACSR=(1<<ACD); //关闭模拟比较器 ADCSRB = 0x00; ADCSRA = 0b11100011; ADMUX |= 0x01; //启用ADC1 }
unsigned int ADC_Convert(void) { unsigned int temp1,temp2; temp1= (unsigned int)ADCL; temp2= (unsigned int)ADCH; temp2= (temp2<<8) +temp1; return(temp2); }
unsigned int ADC_save(void) //ADC求平均 { unsigned char i; unsigned int add_data=0; for(i=0;i<60;i++) { add_data += ADC_Convert(); delay_1ms(); } add_data = add_data/60; return(add_data); }
void LED_display(unsigned int ADC_temp) { unsigned char i; if(ADC_temp<400) { flag_low_bat=1; } else { i=ADC_temp/5; switch(i) { case 0: PORTB=0b00111001; //PB1 flag_low_bat=0; break; case 1: PORTB=0b00111001; //PB1 flag_low_bat=2; //PB3闪 break; case 2: PORTB=0b00101001;//PB1,PB3 flag_low_bat=0; break; case 3: PORTB=0b00101001;//PB1,PB3 flag_low_bat=3; //PB4F闪 break; case 4: PORTB=0b00100001;//PB1,PB3,PB4 flag_low_bat=0; break; defaultORTB=0b00100001; flag_low_bat=0; break; } } }
void init_devices(void) { CLI(); port_init(); timer0_init(); adc_init(); MCUCR = (1<<SM0); TIMSK0 = 0x02; //timerinterrupt sources GIMSK = 0x00; SEI(); }
//*****************1ms中断入口函数******************// #pragma interrupt_handler timer0_ovf_isr:4 void timer0_ovf_isr(void) { static unsigned int cnt0; TCNT0 = 0xB4; //reload counter value cnt0++; if(cnt0==20) { cnt0=0; switch(flag_low_bat) { case 1ORTB^=0x02; break; case 2ORTB^=0x10; break; case 3ORTB^=0x08; break; default:break; } } }
//1ms delay function void delay_1ms(void) { unsigned int i; for(i=1;i<180;i++) ; } void main(void) { init_devices(); delay_1ms(); ADC_Convert(); delay_1ms(); while(1) { ADC_data=ADC_save(); LED_display(ADC_data); } }
接下来就是装机了,LED显示这块测绘的相当准确,装进去正好,充电板那块因为选的贴片的USB口有点不一样,用刀子整了大半天才整好。
完成后的整机图,是不是和原来一样?
哦错了,有点不一样,我的充电在那个USB口上方加开了个孔,用来显示充电状态的LED。 整机搞定时间:2013年5月1日下午17:30 |