本文首发于数码之家论坛,也放到自己的博客上。
前言:
做这个小东西的原因是家里的太阳能供电DCDC降压供给网络设备+NAS之后还有富余,想用逆变器把这部分多余的电量利用起来。
最开始我是直接用一个电量监控控制模块控制逆变器的输出端
这模块有多种控制模式可供选择,我用的是放电控制模式。控制逻辑如下:
电池电压低于65V,断开开关;电池电压达到66V,接通开关
这个开关再连接着一个双路继电器实现太阳能逆变AC220V和市电AC220V的自动切换。
使用上没有问题,但开关断开之后逆变器还是开机的,有10-12W的待机功耗,一天有超过10小时在待机,浪费了0.1度电多。就想有一个双路开关,既控制逆变器输出,也控制输入。
控制逻辑如下
接通时先接通输入,逆变器开机延时5秒再接通输出;
断开时先断开输出,延时5秒再断开逆变器输入。
接通和断开都需要延迟主要是因为逆变器开机是软启动,逆变器输入断开也不会立刻切断输出,而是先报警输入欠压,再利用大电容里的电量慢慢下降输出电压,启动和关闭都有一个过程,会导致AC双路切换器切换不迅速导致后端设备重启。
市面上找不到现成的继电器模块可以实现我这个需求,就学习arduino用arduino配合四路继电器切换模块做了一个,纯新手,代码质量不高,已实际使用两三天了,功能实现正常。
模块制作:
主要都是用的手里现有的东西做了下拼凑集成:
arduino nano开发板*1
四路继电器模块*1
LM2596S降压模块*1
7*9CM洞洞板*1
使用降压模块是因为旁边就是12V双路不间断电源,而12V电压无法供应开发板及继电器模块。
成品如下
因为之前其实折腾过一次,烧过一次开发板,这次我做了一些保护措施
1、控制继电器高低电平的两个针脚串连了100欧电阻,以期在继电器出故障时限流保护开发板不烧电源
2、降压模块输出和继电器模块输入处都加了一个5V TVS二极管进行过压保护,继电器模块处的TVS二极管还有吸收继电器动作时的反向电动势的作用。
3、开发板输入额外加了个10uf的电容以稳压和滤波。
4、analogRead()读取电压的针脚加了个1nf的电容以过滤一些高频噪声防止误动作。
读取外部电压值峰值为73V,arduino开发板是无法直接读取这么高的电压的,使用一个简单的分压电路,我使用的电阻阻值为100K和5.1K,分压比值约为20:1,可测量电压量程约为0-100V。
计算公式为: R1/(R1+R2)=5V/V(range)
注意选择电阻的时候要注意流过电阻的电流,不可超过其耗散功率极值,在我这个电路中两颗电阻承受的最大功率为P=73^2/(100K+5.1K)=0.05W,实际使用中基本感觉不到温升。
逆变器接通的冲击电流太大,无法用继电器模块的小继电器直接控制,使用的是小继电器另外控制一个120A大继电器的办法。
注意使用这种大电流继电器一定要在控制脚接二极管以吸收反向电动势,我用示波器看过这120继电器动作时的波形,反向电压高达600V以上,非常恐怖,不保护的话很容易击穿锂电池的保护板!
弄好后背面贴一张青稞纸以防止放在金属表面时发生短路。
两路继电器都动作时测试输入电流为0.1A左右,功耗1W左右。
arduino代码:
- const float voltage_lowval = 65;
- const float voltage_reval = 66;
- const int delay_time = 5000;
- const int relay_pin_1 = 9;
- const int relay_pin_2 = 10;
- const int voltage_reader = A1;
- float voltage_val;
- bool current_status = 0;
- bool last_status = 0;
- bool debug_status= 0;
- void setup() {
- if (debug_status) {
- Serial.begin(9600);
- }
- pinMode(LED_BUILTIN,OUTPUT);
- pinMode(relay_pin_1,OUTPUT);
- pinMode(relay_pin_2,OUTPUT);
- read_voltage();
- if (voltage_val >= voltage_lowval) {
- current_status = 1;
- turn_on();
- } else {
- current_status = 0;
- turn_off();
- }
- // put your setup code here, to run once:
- }
- void loop() {
- read_voltage();
- if (debug_status) {
- Serial.print(“the current voltage is “);
- Serial.println(voltage_val);
- Serial.print(“the current status is “);
- Serial.println(current_status);
- delay(1000);
- }
- check_status();
- if (current_status != last_status) {
- if (current_status) {
- turn_on();
- } else {
- turn_off();
- }
- last_status = current_status;
- }
- // put your main code here, to run repeatedly:
- }
- void read_voltage() {
- int val = analogRead(voltage_reader);
- voltage_val = val / 1023.0f * 85.7f;
- delay(100);
- }
- void check_status () {
- if (voltage_val <= voltage_lowval) {
- current_status = 0;
- } else if (voltage_val >= voltage_reval) {
- current_status = 1;
- }
- }
- void turn_on() {
- digitalWrite(LED_BUILTIN,HIGH);
- digitalWrite(relay_pin_2,HIGH);
- delay(delay_time);
- digitalWrite(relay_pin_1,HIGH);
- }
- void turn_off() {
- digitalWrite(LED_BUILTIN,LOW);
- digitalWrite(relay_pin_1,LOW);
- delay(delay_time);
- digitalWrite(relay_pin_2,LOW);
- }
复制代码
初学者水平,目前测试能正常工作。
大神