- 积分
- 10608
- 在线时间
- 15508 小时
- 最后登录
- 2022-3-31
- 阅读权限
- 150
- 精华
- 6
 
- UID
- 13663
- 帖子
- 13726
- 精华
- 6
- 经验
- 10608 点
- 金钱
- 8449 ¥
- 注册时间
- 2006-10-21
|

楼主 |
发表于 2012-10-10 16:03
|
显示全部楼层
本帖最后由 ahao 于 2013-3-6 10:26 编辑
没有经过正腐同意就私自开发太阳能?违法滴,小心明天供电人员找上门
hzg 发表于 2012-10-10 15:10 
太阳能属于国有 你这是偷窃 小心 被查水表 嗯嗯 不对是电表!
limitarea 发表于 2012-10-10 15:17 
未经同意就随意开发国家资源,兄弟,小心啊。
四离谱 发表于 2012-10-10 15:17 
太阳能属于国有 你这是偷窃 小心
hifilw 发表于 2012-10-10 15:34 
郑州暂时还没有看到这个规定。
还没看到最后,我就猜了是不是用山特在线式,果然猜对了。。。。
op111op 发表于 2012-10-10 15:17 
恭喜你猜对了 用ups要比买逆变器划算。
据我一个同学说,太阳能发电的成本主要在电池板,而不是蓄电池,电池板整天曝晒老化很快,所以它的寿命比蓄 ...
swing 发表于 2012-10-10 15:28 
不应该吧,电池板最起码也应该能坚持十年八年的吧,到时估计房子也该拆了。
我前些年做过一个小型风车装阳台上,新的还好,家里LED 还亮过一阵子,可惜输出电流小,电压低。只是玩具, ...
旭秋原 发表于 2012-10-10 15:46 
可惜我不在顶楼主,要不然我还打算弄风、光互补的
想不通上次lz搞在线式逆变器为啥,今天找到答案了。1KW的逆变器要这么多电瓶吗?
fysy 发表于 2012-10-10 15:49 
1kva的那个不够猛,这个是用96v电池组3kva的。
·
·
·
·
·
更新,电压、电流等显示部分快完工了,先发上来慢慢更新改动。
显示部分原理图如下
使用LCD1602液晶显示屏,正好趁机学习了一下怎么操作这种LCD显示器,初学阶段程序比较弱智仅供新手参考吧。
制作过程
成品完成
2013.3月更新:
基本搞定,来个控制部分的全家福。如下图,上部是充电限压电路(暂时只有限压功能,限压到112v。mppt技术正在研究中);下面是接触器切换市电、ups电的,中间是单片机控制板等。
·
·
·C程序如下红色字体部分:
/*********
本段程序包含LCD1602自定义字符的显示、A/D转换、PWM等,可供正准备初学的朋友参考
********/
#include"STC12C5A60S2.H" //头文件
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit RS=P2^7; //几个位定义
sbit RW=P2^6;
sbit EN=P2^5;
sbit GUANG=P4^4;
sbit UPS_ON=P3^7;
sbit UPS_OFF=P3^6;
sbit ON=P3^5;
sbit UP=P3^4;
sbit DOWN=P3^3;
sbit YES=P3^2;
sbit IN=P1^6;
uint tempv,tempv1,tempv2,tempa,tempp,ADC_result0,ADC_p1,ADC_i2,ADC_v3,tt1;
uchar kuan,tm0,tm1,biaozhi0,biaozhi1,biaozhi2,adc,tt0,tt11,tt12,shi,fen,miao;
uchar table[]={"0123456789"};
uchar lcd_better[]={0x0e,0x1f,0x11,0x13,0x17,0x1f,0x1f,0x00}; //电池编码
uchar lcd_changer[]={0x03,0x06,0x0c,0x1f,0x06,0x0c,0x18,0x00}; //充电编码
uchar lcd_out[]={0x04,0x0e,0x15,0x04,0x04,0x04,0x04,0x00}; //输出编码 表示负载功率
uchar lcd_on[]={0x0a,0x0a,0x1f,0x11,0x0e,0x04,0x04,0x00}; //插上插头编码 表示开机
uchar lcd_off[]={0x04,0x04,0x0e,0x11,0x1f,0x0a,0x0a,0x00}; //插头拔下编码 表示关机
void delay(uint dd) //延时函数
{
while(--dd);
}
void lcd1602() //LCD初始化函数
{
EN=0;
RS=1;
RW=1;
P0=0xff;
}
void read_busy() //读状态,读忙函数
{
P0=0xff;
RS=0;
RW=1;
EN=1;
while(P0&0x80); //如果不为0说明LCD在忙,继续等待
EN=0;
}
void write_lcd(uchar xyz,bit i) //LCD写操作函数。i=0写指令 i=1写数据
{
read_busy();
P0=xyz;
RS=i;
RW=0;
EN=1;
EN=0;
}
void init_lcd() //lcd显示初始化复位过程
{
delay(15000); //延时15ms
write_lcd(0x38,0); //0为写指令
delay(5000); //延时5ms
write_lcd(0x38,0); //写指令
delay(5000); //延时5ms
write_lcd(0x38,0); //写指令
write_lcd(0x08,0); //显示关闭
write_lcd(0x01,0); //显示清屏
write_lcd(0x06,0); //显示光标移动设置
write_lcd(0x0c,0); //显示开及光标设置
}
void display_lcd(uchar y,uchar x,uchar aa1)
{
y&=0x01; //y不能大于1
x&=0x0f; //x不能大于15
if(y) //如果y=1显示在第二行
{
x+=0x40; //加0x40后就可以显示在第二行
}
x+=0x80;
write_lcd(x,0); //写入显示的位置
write_lcd(aa1,1); //写入显示的数据
}
void display_zidingyi() //显示自定义编码的函数
{
uchar zdy=0;
write_lcd(0x40,0); //向CGRAM40-47区写入自定义电池显示数据
for(zdy=0;zdy<8;zdy++)
{
write_lcd(lcd_better[zdy],1); //分8次写入CGRAM区
}
write_lcd(0x48,0);
for(zdy=0;zdy<8;zdy++) //48-4f区写入充电显示数据
{
write_lcd(lcd_changer[zdy],1);
}
write_lcd(0x50,0);
for(zdy=0;zdy<8;zdy++) //50-57区写入功率输出数据
{
write_lcd(lcd_out[zdy],1);
}
write_lcd(0x58,0);
for(zdy=0;zdy<8;zdy++) //58-5f区写入插头插上数据
{
write_lcd(lcd_on[zdy],1);
}
write_lcd(0x60,0);
for(zdy=0;zdy<8;zdy++) //60-6f写入插头拔下数据
{
write_lcd(lcd_off[zdy],1);
}
write_lcd(0x80,0); //显示在第一行 0位置
write_lcd(0x00,1); //指向CGRAM区00位置
write_lcd(0x80+0x40,0); //显示在第二行 0位置
write_lcd(0x01,1); //指向CGRAM区01位置
write_lcd(0x80+8,0); //显示在第一行 8位置
write_lcd(0x02,1); //指向CGRAM区02位置
}
uint get_ad_result(uchar channel) //AD转换函数
{
uchar ad_finished=0; //存储A/D转换标志
ADC_RES=0; //高8位清零
ADC_RESL=0; //低2位清零
channel&=0x07; //0000 0111 清零高5位
ADC_CONTR=0x60; //转换速率为70个时钟周期转换1次
_nop_();
ADC_CONTR|=channel; //选择A/D当前通道
_nop_();
ADC_CONTR|=0x80; //启动A/D电源
delay(5000); //延时一下使输入电压达到稳定
ADC_CONTR|=0x08; //0000,1000 令 ADCS = 1, 启动A/D转换,
ad_finished=0;
while(ad_finished==0) //等待A/D转换结束
{
ad_finished=(ADC_CONTR&0x10); //0001,0000 测试A/D转换结束否
}
ADC_CONTR&=0xE7; //1111,0111 清 ADC_FLAG 位, 关闭A/D转换,
return(ADC_RES*256+ADC_RESL); //返回 A/D 高8位+低2位转换结果
}
void init_timer()
{
TMOD=0x11; //设定定时器0、1工作方式
EA=1; //开总中断
ET0=1; //开定时器0
TR0=1; //启动定时器0
TH0=(65536-50000)/256; //高、低8位装初值 50ms
TL0=(65536-50000)%256;
ET1=1; //开定时器1
TR1=1; //启动定时器1
TH1=(65536-10000)/256; //高、低8位装初值 10ms
TL1=(65536-10000)%256;
}
void pwm_init()
{
CMOD=0x02; //设置PCA定时器 fosc/2
CCAPM0=0x42; //设置PCA工作方式为PWM0方式
CL=0x00; //PWM0初始时为0
CH=0x00;
CCAP0L=0x80; //设置PWM0初始值与CCAP0H相同
CCAP0H=0x80;
CR=1; //启动PCA定时器
}
void pwm0_set(uchar a) //设置PWM脉宽 0x00~0xff (0~255)
{
CCAP0L=a; //设置值直接写入CCAP0L、CCAP0H
CCAP0H=a; //为0时全部高电平,为1时全部低电平
}
void main() //主程序
{
P4SW=0x10; //0x70=0001 0000 ,将P4.4设置成IO口
P4M1=0x00;
P4M0=0x10; //0001 0000 设定P4.4口为强推挽输出模式
P3M1=0x00;
P3M0=0xc0; //1100 0000 设定P3.7、P3.6口为强推挽输出模式
GUANG=1; //背光打开
UPS_ON=0; //ups开关机均不动作
UPS_OFF=0;
AUXR1|=0x04; //0000 0100 令ADRJ=1,10位A/D转换结果的最高2位放在ADC_RES寄存器,低8位放在ADC_RESL
ADC_CONTR|=0x80; //打开A/D转换电源启动A/D转换
P1ASF=0x87; //1000 0111 将P1.0、P1.1、P1.2、P1.7置为模拟口
lcd1602(); //LCD初始化
init_lcd(); //LCD显示初始化
pwm_init(); //PWM初始化
kuan=1;
init_timer(); //初始化定时器
tm1=1;
display_zidingyi(); //显示自定义字符
biaozhi0=0;
biaozhi1=0;
while(1)
{
if(IN) //IN==1 输入为高电平时显示插头插上标志
{
write_lcd(0x80+0x40+7,0); //显示在第二行 7位置
write_lcd(0x03,1); //指向CGRAM区03位置
if(!tm1) //tm1==0
{
shi=fen=miao=0; //时分秒置零开始新阶段的计时
tm1=1;
}
}
else //IN==0 输入为低电平时显示插头拔下标志
{
write_lcd(0x80+0x40+7,0); //显示在第二行 7位置
write_lcd(0x04,1); //指向CGRAM区04位置
if(tm1) //tm1==1;
{
shi=fen=miao=0;
tm1=0;
}
}
tempv=(ADC_v3*1.0/ADC_result0)*2500; //算出电压、电流、功率,得出的结果为mv,比如1234mv表示电压为123.4v
tempa=(ADC_i2*1.0/ADC_result0)*2500; //现在最后一位会出现乱跳情况,研究一下软件滤波再更新
tempp=(ADC_p1*1.0/ADC_result0)*2500;
display_lcd(0,1,table[tempv/1000]); //显示电池电压
display_lcd(0,2,table[tempv%1000/100]);
display_lcd(0,3,table[tempv%100/10]);
display_lcd(0,4,'.');
display_lcd(0,5,table[tempv%10]);
display_lcd(0,6,'v');
display_lcd(1,1,table[tempa/1000]); //显示充电电流
display_lcd(1,2,table[tempa%1000/100]);
display_lcd(1,3,'.');
display_lcd(1,4,table[tempa%100/10]);
display_lcd(1,5,'A');
display_lcd(0,9,table[tempp/1000]); //显示功率
display_lcd(0,10,table[tempp%1000/100]);
display_lcd(0,11,table[tempp%100/10]);
display_lcd(0,12,table[tempp%10]);
display_lcd(0,13,'w');
display_lcd(1,15,table[miao%10]); //显示时间
display_lcd(1,14,table[miao/10]);
display_lcd(1,13,':');
display_lcd(1,12,table[fen%10]);
display_lcd(1,11,table[fen/10]);
display_lcd(1,10,':');
display_lcd(1,9,table[shi%10]);
display_lcd(1,8,table[shi/10]);
if(tempv>1150) //测试用,未完成待续
UPS_ON=1;
else
UPS_ON=0;
if(tempv<900)
UPS_OFF=1;
else
UPS_OFF=0;
if(!ON) //ON==0 ON按键按下背光开启或者关闭
{
if(!biaozhi0) //biaozhi0==0 标志0为零时
{
biaozhi1=1; //标志1置1,定时器1中的变量tt11开始自加
}
if(tt11>3) //30ms后
{
GUANG=~GUANG;
tt11=0;
biaozhi0=1;
biaozhi1=0;
}
}
else
{
biaozhi0=0;
biaozhi1=0;
tt11=0;
}
pwm0_set(kuan); //呼吸灯,PWM调宽方式
}
}
void timer0() interrupt 1 //定时器0中断程序
{
TH0=(65536-50000)/256; //先装初值
TL0=(65536-50000)%256;
adc++;
if(adc>=6) //300ms转换一次
{
ADC_result0=get_ad_result(0); //A/D转换0、1、2、7通道
ADC_p1=get_ad_result(1);
ADC_i2=get_ad_result(2);
ADC_v3=get_ad_result(7);
adc=0;
}
tt0++; //开机或者关机持续时间
if(tt0>=20) //1秒到
{
miao++; //秒自加1
if(miao>=60) //1分钟到
{
fen++; //分钟自加1
if(fen>=60) //1小时到
{
shi++; //小时自加1
if(shi>=24)
shi=0; //小时归零
fen=0; //分归零
}
miao=0; //秒归零
}
tt0=0;
}
if(GUANG) //GUANG==1 如果背光亮着就开始计时,延时20分钟关闭
tt1++;
else
tt1=0;
if(tt1>=24000) //24000/20=1200秒=20分钟
GUANG=0;
}
void timer1() interrupt 3 //定时器1中断程序
{
TH1=(65536-10000)/256; //高、低8位装初值 10ms
TL1=(65536-10000)%256;
if(biaozhi1)
{
tt11++;
}
if(tt12==0) //呼吸灯。 呼吸效果暂时还不理想有待以后改进
{
kuan+=2;
if(kuan>=255)
{
tt12=1;
}
}
if(tt12)
{
kuan-=2;
if(kuan<=1)
{
tt12=0;
}
}
} |
|