×

带自动升压功能的太阳能热水分流器

消耗积分:0 | 格式:zip | 大小:0.04 MB | 2023-02-02

俞舟群

分享资料个

描述

它有什么作用,为什么?

作为一个自豪的小型光伏系统的所有者,令我感到痛苦的是,我几乎没有回报地出口大部分发电量,而在太阳下山时以更高的价格进口。

白天用多余的太阳能为电热水储水箱“充电”,而不是将其输出到电网,这在某种程度上可以弥补不平衡、节省资金和保护地球。

该项目旨在满足以下要求:

  • 每天将水加热到最低温度,以防止军团病和冷水淋浴。
  • 仅在没有足够的多余太阳能以达到每日最低温度时才输入电力。
  • 下午 3 点到晚上 9 点之间禁止供电(高峰电费)。
  • 最小的射频干扰。

确定可用功率:

为了确定发送到加热元件的功率量,系统需要知道“房子”是输入还是输出功率。在我的例子中,此信息是通过对基于 NodeMCU 的 4 象限功率计的 HTTP 请求获得的,这不是该项目的一部分

HTTP 的替代方案:在 ESP32 上实施太阳能分流器(这样您就有多个模拟输入)并使用 analogueRead() 读取以下项目的输出以获得功率导入/导出读数。您可能需要添加一个运算放大器电路或类似的东西来将可用电压范围转换为更适合 ADC 的电压范围。

硬件

主要组件是一个温度传感器,我把它推到水箱周围的绝缘层下,一个固态继电器驱动加热元件,一个基于 NodeMCU/ESP8266 的控制器提供智能。

temp_sensor_6XOCp6KIkF.png?auto=compress%2Cformat&w=740&h=555&fit=max
罐壁和保温层之间的温度传感器
 

 

controller_JdFdsn65u7.png?auto=compress%2Cformat&w=740&h=555&fit=max
控制器+5v电源
 

 

负载控制

必须以平衡产生的多余太阳能的方式来控制加热功率。

最明显的方法是使用“相位延迟”开关三端双向可控硅开关元件,但这会产生大量 RFI。或者,可以使用继电器或双向晶闸管定期打开/关闭电源:没有 RFI,但电表将记录交替的输出和输入,而不仅仅是零消耗。

快乐的中位数:一个“突发式”开关固态接触器(过零),它在 36 周期突发周期(50Hz 网格)的可变部分关闭。实际上,这仍然是开/关原则,但速度足够快,电表记录平均消耗而不是单独的导入/导出事件。

选择“36”个周期是因为加热元件为 3600W,因此每个“开启”周期都会增加一个易于记忆的 100W 功率。

驾驶SSR

TRIAC 的输入由软件定时器 (ssr_control_fun) 在每个电源周期 (= 20 ms) 上的回调确定,每个周期编号为 [0..35]。

循环是“开”还是“关”由 3 个变量控制:

  • bBoost:表示我们必须以最大速率加热,以便在下午 3 点之前达到所需的水温。
  • nDivertCycles:仍然导致净导出的最大“开启”周期数。
  • nLimitCycles:加热元件与内置机械恒温器一起位于水箱底部。水箱依靠对流将热量从底部元件传输到水箱顶部。不幸的是,在全功率下,恒温器会在水箱完全“充电”之前启动。在恒温器再次关闭电路之前,温度需要下降近 10 度。同时,可能会浪费大量太阳能…… 值会限制在水温接近恒温器触发点时发送到水箱的功率,从而允许更长的渗透时间。
// Cycles per period to divert excess power.
static int16_t		nDivertCycles;

// Max cycles per period to prevent the thermostat from triggering early.
static int16_t		nLimitCycles;

// Max power boost is required to reach by .
static bool			bBoost;



static void ssr_control_fun( void * )
// Runs on a 20msec timer, i.e. once every mains cycle.
// counts cycles, turns off power after the specified # of cycles,
// resets at the end of the PWM period.
{
	static int16_t		iCurrentCycle;	// Current cycle counter.
	
	// Turn on SSR until we have reached nDivertCycles, or when we need to boost.
	digitalWrite
	(	ssrControlPin, 
			(	bBoost											// Always on when boosting.
			||	(haveImport && (iCurrentCycle < nDivertCycles))// or when diversion is on
			)
		&&	(iCurrentCycle < nLimitCycles)	// either way, never exceed temp based power limit.
	);
	
	// Give each cycle a number 0..PwmCycles-1
	iCurrentCycle = (iCurrentCycle+1) % PwmCycles;
}

促进:

我们需要在每天下午 3 点之前达到 :我们估计从当前温度到 应用全功率需要多长时间。=67>如果晚于下一个下午 3 点,则激活“提升”。估计时间基于一组 10 度温度间隔,其中包含应用满载时估计度数/小时的增加。

// Target temperature to aim for by TargetTOD
#define TargetTemp			67



// Time-of-day after which only solar power should be used (secs)
// (start of peak tariff)
#define TargetTOD		(15 * SECS_PER_HOUR)

// Estimated average temperature rise for every hour under 100% power (C/hr)
// The rate varies depending on temp in 10 degree increments, starting at 0.

static const uint8_t	heating_rates[] =
            {	15, 15, 13, 11,  9,  7,  6,  6,  6 };
// start-temp	0    10    20    30    40    50    60	70    80

static float heatingTime( const float from, const float to ) {....}
// estimated time in hours to reach  starting at 

static void updateBoost(const uint32_t	utc, const float curTemp) {....}
// Check if it is still possible to reach  by  at less
// than full power. If not, start a 15 min timer to turn on full power.
// The timer is prevent unnecessary boosts (which cost money) due to temporary
// temperature reductions when the hot tap is opened and cold water flows in.

转移周期:

转移的功率量通过 nDivertCycles 控制,应用 36 个功率中的循环数。该值通过一个简单的反馈回路确定:系统每 10 秒检查一次当前功率输出/输入水平并调整活动周期数以获得 0 到 100W 之间的输出。

static void updateDivertCycles( const int16_t exp )
// Updates nDivertCycles to match spare power.

极限循环:

(可选)为了最大化存储容​​量,我们需要防止内置在水箱中的机械恒温器断开电路。这发生在大约 69℃。不幸的是,在全功率下,水箱内的温度分布使得我靠在水箱壁上的传感器不能很好地指示内置恒温器的温度。所以我们需要降低功率,以便在不触发恒温器的情况下进一步加热水箱。

这是通过线性减少最大值来完成的。在 67 和 69℃ 之间从 100% 到 12.5% 的活性循环数。

static void updateLimitCycles( const float curTemp )
// Limit the duty-cycle when water temperature exceeds TargetTemp

当地时间:

该系统旨在每天在同一当地时间完成对水的加热。因此,它需要访问时间服务器以获取 UTC,并将 UTC 转换为本地时间,同时考虑夏令时的变化。

获得 UTC 是相当标准的。本地时间的转换由“timeZone”库模块提供(根据 Jack Christensen 的设计稍作修改)。timeZone 模块为澳大利亚维多利亚州提供转换例程和单一时区规范。您需要修改/添加您所在地区的 TZ 规范。

时区.cpp

// Victoria, Oz timezone
static TimeChangeRule aeST = {"AEST", First, Sun, Apr, 3, 600};   // UTC + 10 hours
static TimeChangeRule aeDT = {"AEDT", First, Sun, Oct, 2, 660};   // UTC + 11 hours
Timezone ae(aeDT, aeST);

solar_diverter_report.ino:

#include                   // settimeofday_cb()
#include 

const uint32_t	utc = utcTime();
const uint32_t	localTime = ae.toLocal( utc );

网络监控:

该系统包括许多 http/svg 网页,提供多个时间尺度上的温度/功率历史记录。提供了代码,但没有记录......

cloudy_day_o9VrT4Po8V.png?auto=compress%2Cformat&w=740&h=555&fit=max
阴天:太阳能不足,导致多次升压。
 

 


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.lene-v.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'带自动升压功能的太阳能热水分流器',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.lene-v.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);