How count pulse with matlab?

I have the signal outputs from the rotary encoder. I'd like to count pulses using Matlab software. How can I count pulses? I attach the signal outputs. Would you please find the attachment files. Any codes? Any Solutions?

3 Comments

What is the sampling frequency (samples/second) in your ‘pulses.mat’ data?
The sampling interval is 3.90625E-05 seconds.

Sign in to comment.

Answers (1)

Find the bottom envelope by using imerode() (in the Image Processing Toolbox). Then subtract the envelope from the signal. Then threshold and call bwlabel to count the pulses. Or you can use diff but it's more complicated.
bottomEnvelope = imerode(signal, true(1, windowWidth));
flattenedSignal = signal - bottomEnvelope;
hold on;
plot(flattenedSignal, 'r-');
binarySignal = flattenedSignal > 50;
plot(binarySignal, 'r-');
[~, numberOfPulses] = bwlabel(binarySignal);

18 Comments

Thanks for your reply. I only show the outputs as the image. I have the data as pulse data. How can I count them? I attach the fig of signal output.
Attach your data in a .mat file so I can do something with it. I already told you how to count the pulses. You just need to figure out what the window width is.
I attach the mat file for you. I did what you say; however, there is error when I use your code. The Error is : "Data cannot have more than 2 dimensions."
The erosion direction needed to be changed, and the range is different than your first signal so the threshold needed to be changed. And then the bottom was a bit rough so I smoothed it with a Savitzky-Golay filter. See attached code. Here it is on just a few pulses:
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 20;
s = load('pulse.mat')
% Let's just extract a few of the pulses, not all of them since there are so many we can't see them all in the plot.
signal = s.pulse_data(1:100);
whos signal
plot(signal, 'b-', 'LineWidth', 2);
% Get the bottom envelope:
windowWidth = 19;
bottomEnvelope = imerode(signal, true(windowWidth, 1));
% It's a bit rough. It's supposed to be a sine wave so let's fit it to a cubic
% by using a Savitzky-Golay filter
bottomEnvelope = sgolayfilt(bottomEnvelope, 3, windowWidth);
hold on;
plot(bottomEnvelope, 'r-', 'LineWidth', 2);
grid on;
flattenedSignal = signal - bottomEnvelope;
hold on;
plot(flattenedSignal, 'm-', 'LineWidth', 2);
binarySignal = flattenedSignal > 7;
plot(binarySignal, 'g-', 'LineWidth', 2);
[~, numberOfPulses] = bwlabel(binarySignal);
legend('Original', 'Bottom', 'Flattened', 'Binary');
% Set up figure properties:
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1]);
% Get rid of tool bar and pulldown menus that are along top of figure.
set(gcf, 'Toolbar', 'none', 'Menu', 'none');
% Give a name to the title bar.
set(gcf, 'Name', 'Line segmentation', 'NumberTitle', 'Off')
message = sprintf('The number of pulses is %d', numberOfPulses);
uiwait(helpdlg(message));
Thank you very much. It works very well.
Can i Use the same to find the number of pulses in my data i have attached here. But the code shows number of pulses as zero.
binarySignal = flattenedSignal > 7;
SHANTANU KSHIRSAGAR : for your data, use about 0.2 instead of 7.
However, your data has minor peaks as well, so you will need to examine the plots to decide whether 0.2 is the value you want.
Use signal = y1(1:100); and work from whos signal onward in the code Image Analyst posted.
I smooothened the earlier signal now and have attached ,it does not contain minor peaks but still showing zero pulses.
The code was doing some baseline flattening. When you do that with your signal, the little wiggles near the beginning of your pulses turn into something that were individually getting counted as pulses. So this version estimates the baseline but does not flatten the signal.
s = load('req3.mat');
% Let's just extract a few of the pulses, not all of them since there are so many we can't see them all in the plot.
signal = s.y1;
whos signal
plot(signal, 'b-', 'LineWidth', 2);
% Get the bottom envelope:
windowWidth = 19;
bottomEnvelope = imerode(signal, true(windowWidth, 1));
% It's a bit rough. It's supposed to be a sine wave so let's fit it to a cubic
% by using a Savitzky-Golay filter
bottomEnvelope = sgolayfilt(bottomEnvelope, 3, windowWidth);
hold on;
plot(bottomEnvelope, 'r-', 'LineWidth', 2);
grid on;
flattenedSignal = signal - min(bottomEnvelope);
hold on;
plot(flattenedSignal, 'm-', 'LineWidth', 2);
binarySignal = flattenedSignal > 2;
plot(binarySignal, 'g-', 'LineWidth', 2);
[~, numberOfPulses] = bwlabel(binarySignal);
hold off
legend('Original', 'Bottom', 'Flattened', 'Binary');
% Set up figure properties:
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1]);
% Get rid of tool bar and pulldown menus that are along top of figure.
%set(gcf, 'Toolbar', 'none', 'Menu', 'none');
% Give a name to the title bar.
set(gcf, 'Name', 'Line segmentation', 'NumberTitle', 'Off')
message = sprintf('The number of pulses is %d', numberOfPulses);
uiwait(helpdlg(message));
yes now it is identifying the pulses correctly .thanks you very much.
Can we eliminate the half waves detected in such pulses and count the remaining pulses?
thanks.
Not sure what you mean by half waves. Please identify them.
sorry the attachments were not sent. i have attached them here. There is half pulse at begining , how do we eleminate it.
Try masking it away
indexes = x < -0.165;
y(indexes) = min(y);
this is effective but it cancels out the the values keeping the minimum value indexes.
I wanted to remove the values of half wave completely and then start the remaining waveform with the next full pulse.
Try this:
s = load('req4.mat')
x = s.x1;
y = s.z1;
subplot(2, 1, 1);
plot(x, y, 'b-', 'LineWidth', 2);
index = findchangepts(y)
hold on;
plot(x(index), y(index), 'r*', 'LineWidth', 2, 'MarkerSize', 15);
grid on;
% This finds a point on the upward slope. Fall down the slope until it starts to turn around again.
while y(index) > y(index - 1)
index = index - 1;
end
xline(x(index), 'Color', 'r', 'LineWidth', 2);
caption = sprintf('Original Signal with %d elements. Start crop at index = %d, x = %f', length(x), index, x(index));
fontSize = 20;
title(caption, 'FontSize', fontSize);
xlabel('x1', 'FontSize', fontSize);
ylabel('z1', 'FontSize', fontSize);
% Extract just the part to the right of the index (red line).
x2 = x(index : end);
y2 = y(index : end);
subplot(2, 1, 2);
plot(x2, y2, 'b-', 'LineWidth', 2);
grid on;
xlim([min(x2), max(x2)]);
xlabel('x1', 'FontSize', fontSize);
ylabel('z1', 'FontSize', fontSize);
g = gcf;
g.WindowState = 'maximized';
caption = sprintf('Cropped Signal with %d elements.', length(x2));
title(caption, 'FontSize', fontSize);
the findchangepts is not working due to absence of signal processing toolox. Is there any way similarly robust.
Find the first place where the signal exceeds 2.5 and then fall down the left side until it turns around.
% Initialization steps. Brute force cleanup of everything currently existing to start with a clean slate.
clc; % Clear the command window.
fprintf('Beginning to run %s.m ...\n', mfilename);
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 20;
s = load('req4.mat')
x = s.x1;
y = s.z1;
subplot(2, 1, 1);
plot(x, y, 'b-', 'LineWidth', 2);
index = find(y > 2.5, 1, 'first');
hold on;
plot(x(index), y(index), 'r*', 'LineWidth', 2, 'MarkerSize', 15);
grid on;
% This finds a point on the upward slope. Fall down the slope until it starts to turn around again.
while y(index) > y(index - 1) && index >= 2
index = index - 1;
end
xline(x(index), 'Color', 'r', 'LineWidth', 2);
caption = sprintf('Original Signal with %d elements. Start crop at index = %d, x = %f', length(x), index, x(index));
fontSize = 20;
title(caption, 'FontSize', fontSize);
xlabel('x1', 'FontSize', fontSize);
ylabel('z1', 'FontSize', fontSize);
% Extract just the part to the right of the index (red line).
x2 = x(index : end);
y2 = y(index : end);
subplot(2, 1, 2);
plot(x2, y2, 'b-', 'LineWidth', 2);
grid on;
xlim([min(x2), max(x2)]);
xlabel('x1', 'FontSize', fontSize);
ylabel('z1', 'FontSize', fontSize);
g = gcf;
g.WindowState = 'maximized';
caption = sprintf('Cropped Signal with %d elements.', length(x2));
title(caption, 'FontSize', fontSize);

Sign in to comment.

Asked:

on 7 Apr 2016

Commented:

on 31 May 2020

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!