【非侵入式负载监测】低采样率电动汽车充电的无训练非侵入式负载监测(Matlab代码实现)

news2024/12/29 11:34:02

💥💥💞💞欢迎来到本博客❤️❤️💥💥

🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。

⛳️座右铭:行百里者,半于九十。

📋📋📋本文目录如下:🎁🎁🎁

目录

💥1 概述

📚2 运行结果

🎉3 参考文献

🌈4 Matlab代码实现


💥1 概述

摘要非侵入式负载监测(NILM)是智能电网和智能家居中的一个重要课题。已经提出了许多能量分解算法来从一个聚集的信号观测中检测各种单独的设备。

然而,由于电动汽车在家充电是最近才出现的,因此很少有研究在住宅环境中对插电式电动汽车(EV)充电进行能量分解的工作。最近的研究表明,电动汽车充电对智能电网有很大影响,尤其是在夏季。因此,电动汽车充电监测已成为能源分解中一个更为重要和紧迫的缺失部分。在本文中,我们提出了一种新的方法来从聚集的实际功率信号中分解EV充电信号。所提出的方法可以有效地减轻来自空调(AC)的干扰,在存在AC电力信号的情况下实现准确的EV充电检测和能量估计。此外,所提出的算法不需要训练,需要较轻的计算负载,提供较高的估计精度,并且适用于以1/60 Hz的低采样率记录的数据。当该算法在大约一整年(总共125个月的数据)内对11所房屋记录的真实世界数据进行测试时,估计电动汽车充电能耗的平均误差为15.7 kwh/月(而电动汽车充电的真实平均能耗为208.5 kwh/),分解电动汽车充电负载信号的平均归一化均方误差为0.19。

文献来源:

📚2 运行结果

 

 

 

 

 

部分代码:

% Reference:
%   Zhilin Zhang, Jae Hyun Son, Ying Li, Mark Trayer, Zhouyue Pi, 
%   Dong Yoon Hwang, Joong Ki Moon, Training-Free Non-Intrusive Load 
%   Monitoring of Electric Vehicle Charging with Low Sampling Rate, 
%   The 40th Annual Conference of the IEEE Industrial Electronics Society 
%   (IECON 2014), Oct.29-Nov.1, 2014, Dallas, TX

if iscolumn(orgAgg), orgAgg = orgAgg'; end;
EVest = zeros(size(orgAgg));

if isempty(contextInfo.EVamplitude), 
    EVAMP = 3000;
else
    EVAMP = contextInfo.EVamplitude;
end

% Although one day has 1440 samples, we may want to estimate current day
% plus the early morning of the next day (because EV signal can happen 
% around mid-night). So, orgAgg can be a vector including samples from 
% current day and the early morning of the next day. Thus DAYLEN may be 
% larger than 1440. However, in this simulation, we only focus on exactly 
% one day. So, the length of orgAgg is 1440.
DAYLEN = length(orgAgg);     


%=====================================================================
% 1. Remove baseline noise
%    This can enhance the robustness (Sometimes the baseline noise is 
%    very large, thus making the pre-set threshold value is not suitable). 
%    The baseline noise will be further removed at the end of this 
%    algorithm.
%=====================================================================
res = min(orgAgg);  
ts = orgAgg - res;
 

if verbose, fprintf('\nStep 1: Removed residual noise (%f) \n',res); end;

%=====================================================================
% 2. Thresholding
%=====================================================================
% Set threshold value
% We could set 3000, since EV always has amplitude >3000 W. However, this 
% value will remove many context information (such as AC spikes and lumps),
% which is useful to remove ambiguility. 
THRESHOLD = 2500; 
if verbose, fprintf('Step 2: Calculate threshold value: %f\n',THRESHOLD); end;

% Thresholding
EVsignal = ts;
EVsignal(EVsignal<THRESHOLD) = 0;

% Record the thresholded signal
EV_step2 = EVsignal;      


% =========================================================================
%  3. Use bumpTrainFilter to remove AC spike trains
% =========================================================================
% Obtain segments with amplitude > THRESHOLD
[segment, ~] = getSegment(EVsignal);
if isempty(segment), EVest = zeros(size(ts)); return; end;


% Remove segments with short duration (basically from AC, dryer/oven, etc)
min_shrtDuration = 20;
max_duration = 90;
incrPercentage = 1;
segment_lowthr_info = bumpTrainFilter(segment, min_shrtDuration, max_duration, incrPercentage);

% Reconstruct the signal after filtering bump trains
EV_step3 = getSignal(segment_lowthr_info,EVsignal); 
if isempty(EV_step3), EVest = zeros(size(ts)); return; end;

if verbose, fprintf('Step 3: Running bumpTrainFilter. \n'); end;


% =========================================================================
%  4. Fill the very short gaps between two successive segments
% =========================================================================
gapDistanceMax = 10; 
[EV_step4, segment_lowthr_pit] = pitFilter(EVsignal,segment_lowthr_info,gapDistanceMax);

if verbose, fprintf('Step 4: Running pitFilter. \n'); end;

if verbose,
    set(0, 'DefaultFigurePosition', [300 10 600 700]);
    figure;
    subplot(411); plot(ts); title('Aggregated Signal After Removal Residual');
    subplot(412); plot(EV_step2); title(['Signal After Low Thresholding:',num2str(THRESHOLD)]);
    subplot(413); plot(EV_step3); title('Signal After BumpTrainFilter');
    subplot(414); plot(EV_step4); title('Signal After PitFilter');
end

%=====================================================================
% 5. Determine the type of each segment
%=====================================================================
newSegmentNum = size(segment_lowthr_pit,1);
heightResolution = 2;
differentiateRange = 200;
type = [];    
for k = 1 : newSegmentNum
    segment_study = EV_step4(segment_lowthr_pit(k,1):segment_lowthr_pit(k,2));

    [type(k), temp] = findType(segment_study, heightResolution, differentiateRange);
    changeAmplitude{k} = temp;
end
 

if verbose, fprintf('Step 5: Classify Segment Type. Type of Each Segment: \n'); disp(type);  end;

%=====================================================================
% 6. Energy disaggregation
%=====================================================================

finalSegmentInfo = [];  % Variable storing information of the EV segments.
                        % The (i,1)-th entry records the beginning
                        % location of the i-th segment. The (i,2)-th entry
                        % records the ending location of the i-th segment.
                        % The (i,3)-th entry records the height of the
                        % segment.
finalSegmentNb = 0;
for k = 1 : newSegmentNum
    if verbose, fprintf('Check No.%d Segment\n',k); end;
    
    curSegment = orgAgg(segment_lowthr_pit(k,1):segment_lowthr_pit(k,2));
       
    % Height of curSegment including residual noise
    rawHeight = getHeight(curSegment);
    
    % Remove approximate local residual noise
    avgNoiseAmplitude = localNoiseAmplitude([segment_lowthr_pit(k,1),segment_lowthr_pit(k,2)], orgAgg);
    curHeight = rawHeight - avgNoiseAmplitude;    
    
    
    if type(k) == 0
        % For this type, it is probably the dryer/oven waveforms, which has
        % no sharp drop-off in signal points at some amplitude. However, we
        % need to consider one rare situation, i.e. the almost completely
        % overlapping of EV and dryer/oven waveforms.
        
        if length(curSegment)<30 | length(curSegment)>300
            % jump to the next segment, thus automatically remove curSegment
        else

            if curHeight > 5500, 
                % construct a square wave with height given
                % by 3500 (or taking from other EV waveforms)
                finalSegmentNb = finalSegmentNb + 1;
                finalSegmentInfo(finalSegmentNb,:) = [segment_lowthr_pit(k,1),segment_lowthr_pit(k,2),EVAMP,type(k)];
                
            else
                % jump to the next segment, thus automatically removing curSegment
            end
        end
            
        
    elseif type(k) == 1
        % For this type, it could be a single EV waveform (with residual
        % noise), an EV waveform overlapping with a narrow dryer/oven
        % waveform or with one or two bumps of AC
        % 
        
        if length(curSegment) > 300 | curHeight < max(EVAMP - 300, 3000)
            % jump to the next segment, thus automatically removing curSegment
        else
                        
            % Flag to indicate whether curSegment is EV
            curSegmentEV = 1;
            
            % If curSegmentEV locates between 12pm-10pm (720 - 1320)
            curSegmentLoc1 = segment_lowthr_pit(k,1);
            curSegmentLoc2 = segment_lowthr_pit(k,2);
            if 1 <= curSegmentLoc1 & curSegmentLoc2 <= DAYLEN
                
                % if surrounding segments are AC spikes, and the top layer
                % of curSegment has no AC spikes (note it should be
                % classified as Type 2, but sometimes when the AC spike
                % number is one or two, and it may be classified as Type 1)
                
                % Remove dryer/oven waveform around the curSegment (2 hours
                % before and after curSegment)
                studyArea = EVsignal( [max(1,segment_lowthr_pit(k,1)-120) : max(1,segment_lowthr_pit(k,1)-1), ...
                    min(DAYLEN,segment_lowthr_pit(k,2)+1): min(DAYLEN,segment_lowthr_pit(k,2)+120)] );
                [studyArea_filtdryer, ~] = dryerFilter(studyArea);
                
                [ACseg,~] = getSegment(studyArea_filtdryer);
                
                % Remove AC spike train
                min_shrtDuration_sur = 25;
                max_duration_sur = min(90,max(min_shrtDuration_sur,length(curSegment)*0.6));
                incrPercentage_sur = 1;
                [~, rmvBumpInfo, removeFlag] = bumpTrainFilter(ACseg, min_shrtDuration_sur, max_duration_sur, incrPercentage_sur);
                
                if removeFlag & size(rmvBumpInfo,1)> 4
                    % Check if the top layer of curSegment has AC spikes;
                    % if so, then curSegment is EV; otherwise, not EV
                    
                    % get the segment information of the top layer
                    curSegment_topLayer = curSegment;
                    curSegment_topLayer(curSegment_topLayer < getHeight(curSegment)+ 1000) = 0;
                    
                    % -----------------------------------------------------
                    % Decide if the top layer has AC spikes using autocorrelation
                    [ACindicator] = ACdetector(curSegment_topLayer);
                    
                    if ~ACindicator
                         
                            curSegmentEV = 0;
                         

                    end

                    
                else
                    % Check if nearby segments have similar width as
                    % curSegment. If so, curSegment is not EV
                    
                    % Find the left segment closest to curSegment
                    leading_loc2 = max( segment(find(segment(:,2) < segment_lowthr_pit(k,1)),2)   );
                    
                    if ~isempty(leading_loc2)  % if leading_loc2 is empty, then curSegment is at the beginning of this day
                        leading_loc1 = max( segment(find(segment(:,1) < leading_loc2),1) );
                        leading_flag = 1;
                    else
                        leading_flag = 0;
                    end
                    
                    % Find the right segment closest to curSegment
                    following_loc1 = min( segment( find(segment_lowthr_pit(k,2) < segment(:,1)),1) );
                    
                    if ~isempty(following_loc1)  % if following_loc1 is empty, then curSegment is at the end of this day
                        following_loc2 = min( segment( find( following_loc1 < segment(:,2)),2) );
                        following_flag = 1;
                    else
                        following_flag = 0;
                    end
                    
                    if leading_flag & following_flag
                        
                        if length(curSegment)/length(leading_loc1:leading_loc2) < 3 & (segment_lowthr_pit(k,1)-leading_loc2 <= 30) | ...
                                length(curSegment)/length(following_loc1:following_loc2)< 3 & (following_loc1 - segment_lowthr_pit(k,2) <= 30)
                            % if surrounding segments have similar width and close gaps
                            curSegmentEV = 0;
                        end
                        
                    elseif leading_flag
                        if length(curSegment)/length(leading_loc1:leading_loc2) < 3 & (segment_lowthr_pit(k,1)-leading_loc2 <= 30)
                            curSegmentEV = 0;
                        end
                        
                    elseif following_flag
                        if length(curSegment)/length(following_loc1:following_loc2)< 3 & (following_loc1 - segment_lowthr_pit(k,2) <= 30)
                            curSegmentEV = 0;
                        end
                    end
                    
                    
                end
                

                
            end
            
            
            if curSegmentEV,
                % construct the EV signal
                finalSegmentNb = finalSegmentNb + 1;
                finalSegmentInfo(finalSegmentNb,:) = [segment_lowthr_pit(k,1),segment_lowthr_pit(k,2),curHeight,type(k)];
            end
    
        end
            
        
        
    elseif type(k) >= 2
        % For this type, it could be an overlap with EV and AC (with other 
        % appliances). We need to determine whether the upper part
        % or the bottom part is an EV waveform

                   
            % determine the up-bound and the bottom-bound of the threshold
            upBound = max(curSegment)-200;
            bottomBound = max( changeAmplitude{k}(1)+200,  getHeight(curSegment) );
            
            
            highThreshold = max(5000, changeAmplitude{k}(1)*0.4 + changeAmplitude{k}(2)*0.6);
            if highThreshold <bottomBound  | highThreshold > upBound
                highThreshold = (bottomBound + upBound)/2;
            end
                

            topSegment = curSegment;  
            topSegment(topSegment<highThreshold) = 0;
        

            [topSegmentInfo, topSegNum] = getSegment(topSegment);   
        
            
        
        % Filling pits in topSegment with very short duration
        [topSegment2, topSegmentInfo2] = pitFilter(topSegment,topSegmentInfo,10);
        topSegNum2 = size(topSegmentInfo2,1);
        
        %figure(1);subplot(515); plot(topSegment2); title('Top Part After Filling Pits');
        
        
        topSegmentWidthList = diff(topSegmentInfo2');
        
        
        if length(curSegment) > 300
            % In this situation, the bottom one is AC part, and thus the top one is EV
            
            for tsn = 1 : topSegNum2
                
                % If each segment of the top part is long enough, then it
                % is an EV waveform
                if topSegmentWidthList(tsn) > 20
                    
                    % obtain current top segment associated with curSegment
                    segmentStudy = curSegment(topSegmentInfo2(tsn,1):topSegmentInfo2(tsn,2));   
                    
                    % check if it is a dryer waveform
                    windowLen = length(segmentStudy);   % window length (used to slide the aggregated signal)      
                    thr_crossRate = 5*windowLen/30;     % thresholding for level-crossing counting (a dryer should have larger counting than this value)
                    incremental = 200;                  % value to increase the level for level-crossing counting
                    [dryerFlag,~] = detectDryer(segmentStudy, windowLen, thr_crossRate, incremental); % detect whether dryer exists
                    
                    if ~dryerFlag   % if not dryer, then reconstruct a square signal by using its width and the height
 
                        % location of beginning and the ending of the top bump in the whole aggregated signal
                        globalLocation = [topSegmentInfo2(tsn,1) + segment_lowthr_pit(k,1)-1, ...
                                          topSegmentInfo2(tsn,2) + segment_lowthr_pit(k,1)-1];
                        
                        
                        % calculate the height of the bump
                        topHeight = getHeight( curSegment(topSegmentInfo2(tsn,1):topSegmentInfo2(tsn,2)));
                         
                        % calculate the height of the bottom bump
                        bottomHeight = getHeight(curSegment);
                         
                    
                        % height
                        curHeight = topHeight - bottomHeight;
                         
                        
                        % determine if there is random flunctuation
                        if max(ts(globalLocation)) > 6000
                            if curHeight < 3500, 
                                curHeight = 3500;
                            end  
                        
                            % record the information of the bump
                            finalSegmentNb = finalSegmentNb + 1;
                            finalSegmentInfo(finalSegmentNb,:) = [globalLocation, curHeight, type(k)];
                        end
                    
                    end
                          
                end
            end

🎉3 参考文献

部分理论来源于网络,如有侵权请联系删除。

[1]Zhilin Zhang, Jae Hyun Son, Ying Li, Mark Trayer, Zhouyue Pi, Dong Yoon Hwang, Joong Ki Moon, Training-Free Non-Intrusive Load Monitoring of Electric Vehicle Charging with Low Sampling Rate, The 40th Annual Conference of the IEEE Industrial Electronics Society (IECON 2014), Oct.29-Nov.1, 2014, Dallas, TX 

🌈4 Matlab代码实现

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/138031.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一、TTY子系统介绍

个人主页&#xff1a;董哥聊技术我是董哥&#xff0c;嵌入式领域新星创作者创作理念&#xff1a;专注分享高质量嵌入式文章&#xff0c;让大家读有所得&#xff01;文章目录1、TTY介绍2、控制台终端2.1 系统控制台2.2 当前控制台2.3 虚拟控制台3、伪终端4、串口终端5. 其它类型…

《移动安全》(10)Frida第一篇之环境搭建

0x00 前言 Frida是一款轻量级HOOK框架&#xff0c;我们在电脑上安装Frida环境后&#xff0c;还需要将frida-server上传到目标机器上运行&#xff08;需要Root&#xff09;&#xff0c;通过它来注入进程完成hook操作。本文主要讲述Frida环境的搭建。 0x01 Frida环境搭建 &…

node.js创建网站实例3

node.js访问mysql数据库并把查询结果返回给前端 1.cmd中运行&#xff1a;npm install mysql -s 2.修改api.js的代码 // 1.先引入express模块&#xff0c;express是一个函数 var express require("express") //2.执行express函数&#xff1b;用变量接收express函数…

概论_第2章_重点_随机变量函数的概率分布___定理法和分布函数法的应用

一 定义 概括地说&#xff1a; 随机变量Y是随机变量X的函数。 设g(x) 是一给定的连续函数&#xff0c; 称Yg(X) 为随机变量X的一个函数&#xff0c; Y也是一个随机变量。当X取值 时&#xff0c;Y取值 . ~~~~~~~~~~~~~~ 本文讨论连续型随机变量函数。 定理1: 设X为连续型…

【3.2】Eureka-搭建注册中心/服务注册/服务发现

【3.2】Eureka-搭建注册中心/服务注册/服务发现1 搭建EurekaServer1.1 详细步骤1.2 搭建EurekaServer小结2 服务注册2.1 详细步骤&#xff08;踩坑点&#xff01;解决&#xff09;2.2 模拟多实例部署2.3 服务注册小结3 服务发现3.1 详细步骤4 总结1 搭建EurekaServer 搭建Eure…

2022年,我每天都会用的linux常用命令

作者简介&#xff1a;一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.Linux常用命令 1.Linux命令概述 2.Linux命令的分类 &#…

科研 | 学生研究方向指导 | 技术路线 | 相关学习资源

1. AI某领域 1.1 Python基础 慕课教程&#xff1a;Python 入门语法教程 哔哩哔哩&#xff1a;3小时快速入门Python 1.2 机器学习框架 sklearn框架&#xff1a;菜菜的机器学习sklearn 1.3 深度学习框架 慕课教程&#xff1a;TensorFlow 入门教程 PyTorch官方教程中文版 不…

【回答问题】ChatGPT上线了!给我推荐20个比较流行的AI作画模型!

目录给我推荐20个比较流行的AI作画模型给我推荐20个比较流行的AI作画模型代码给我推荐20个比较流行的AI作画模型 好的&#xff0c;下面是20个比较流行的AI作画模型&#xff1a; DALL-E GAN Deep Dream CycleGAN StyleGAN pix2pix SketchRNN BigGAN ProGAN ESRGAN SPADE BigVA…

Vue+Leaflet.PM插件实现创建和编辑几何图形(点、线、面、圆等)

场景VueLeaflet实现加载OSM显示地图&#xff1a;https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/122317394在上面加载显示OSM的基础上&#xff0c;使用Leaflet.pm插件实现在页面上绘制、编辑、剪切、移动几何元素。Leaflet.pm插件用于创建和编辑几何图层的插件可绘…

如何避免无效外贸邮件营销?

如何避免无效的邮件营销&#xff0c;米贸搜为您整理如下&#xff0c;希望对您有所帮助:1 .和邮件正文一样重视主题主题对于电子邮件就像标题对于文章或博客一样重要。即使你有全宇宙最吸引人的散文诗&#xff0c;或者最吸引人的求婚&#xff0c;如果根本没有人打开这封邮件&…

CSS 中各种居中你真的玩明白了么

前言 页面布局中最常见的需求就是元素或者文字居中了&#xff0c;但是根据场景的不同&#xff0c;居中也有简单到复杂各种不同的实现方式&#xff0c;有的特定场景下可能还有一些稀奇古怪的bug&#xff0c;本篇就带大家一起了解下&#xff0c;各种场景下&#xff0c;该如何使用…

72、【哈希表】leetcode——454. 四数相加 II(C++版本)

题目描述 原题链接&#xff1a;454. 四数相加 II 解题思路 本题构建Hash表的关键是确定Value的含义&#xff0c;因为目标是找到四个集合中各种情况为0的情况之和&#xff0c;因此不需要对相同情况去重&#xff0c;Value设置为满足某种对应情况的出现次数。当找到一次满足nums…

实验室小分子PEG衍生物之Aminoxy-PEG2-azide 1043426-13-6异双功能PEG

Aminoxy-PEG2-azide异双功能PEG接头可交联官能团 中文名称&#xff1a;氨氧基-二聚乙二醇-叠氮化物 英文名称&#xff1a;Aminoxy-PEG2-azide 分子式&#xff1a;C6H14N4O3 分子量&#xff1a;190.2 CAS&#xff1a;1043426-13-6 外观&#xff1a;粘稠液体或者固体粉末&#x…

文件误删怎么办?恢复误删的数据,就靠这4种方法

现在是信息爆炸的时代&#xff0c;我们每天都会保存许多重要信息。这让我们的电脑保存了大量的文件、图片、视频等数据。为了保存电脑整洁&#xff0c;提高它的运行速度&#xff0c;我们必须要对它进行定期地清理。在清理的过程中&#xff0c;重要文件误删怎么办&#xff1f;恢…

ArcGIS基础实验操作100例--实验45按要素融合多边形

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 高级编辑篇--实验45 按要素融合多边形 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;1&…

概论_第2章_重点内容__随机变量函数的概率分布___定理法和分布函数法的应用

一 定义 概括地说&#xff1a; 随机变量Y是随机变量X的函数。 设g(x) 是一给定的连续函数&#xff0c; 称Yg(X) 为随机变量X的一个函数&#xff0c; Y也是一个随机变量。当X取值 时&#xff0c;Y取值 . ~~~~~~~~~~~~~~ 本文讨论连续型随机变量函数。 定理1: 设X为连续型…

chrony服务部署

一&#xff0c;要求 chrony服务部署&#xff1a;两台机器 a: 第一台机器从阿里云同步时间&#xff0c;第二台机器从第一台机器同步时间 b: 第一台服务器使用系统时间作为第二台服务器的时钟源&#xff0c; 第一台服务器层级设置为6 二&#xff0…

有关于Transformer 的max_seq_length (max_source_length)

Transformer 的最大输入长度&#xff0c;即max_seq_length / max_source_length是一个非常值得注意的参数。 Transformer的encoder大多是Auto-encoder的结构&#xff0c;不同于Auto-regressive encode&#xff0c;由于auto-encoder缺乏时序序列的位置信息&#xff0c;因此其需…

dom截图——探究长截图的极限

长截图问题 问题&#xff1a;使用dom-to-image和html2canvas来进行长截图会出现一个问题&#xff0c;如果图片非常长&#xff0c;一些图片会只加载一半&#xff0c;如果图片再长一些&#xff0c;截图就会为空。 目前我测试的结果&#xff1a;截图的大小在8mb出现图片缺了的情况…

Blender 编辑骨骼动画,重复动作,并导出动画为视频

文章目录制作动作动画.重复动作.导出动画为视频制作动作动画. 1 进入姿态模式。调整各个部位的位置。调整好后&#xff0c;A&#xff0c;全选&#xff0c;I 记录置和旋转并创建一个关键帧 2 如果回放时间轴上没有关键帧&#xff0c;可以去 动画时间表/动作编辑器 窗口查看。注…