The goal of this lab is to
attenuate the noise in an electromyography signal and process it to move a
prosthesis. To detect the EMG signal, two electrodes are placed on the moving
muscle of choice. These electrodes provide a differential signal (V+ and V-). A
third electrode is placed on a non-moving body part, to act as a
ground-reference for the signal. An instrumentation amplifier is then used to
amplify the differential signal, without amplifying power supply noise.
Additional filters are used to mitigate electrical noise and DC offset.
Finally, a microcontroller and H-bridge are used to control DC motor rotation,
to facilitate prosthesis motion, in relation to muscle flexion.
Instrumentation Amplifier
Design
An FFT of the initial EMG
setup shows the presence of a DC offset and power-supply noise occurs at
integer-multiples of 60Hz (120Hz, 240Hz, 480Hz, etc.), reference Figure 1.
Since EMG signals occupy 50-500Hz, using a notch/bandpass filter in this
application would either attenuate useful frequencies of the signal, or would
allow the presence of power supply noise. Since the signals from both EMG
electrodes share the same power-supply noise, we can use a differential
amplifier to amplify the difference between the two signals, without increasing
power supply noise. As the difference in signal is amplified, the 60Hz gets
proportionally smaller. This helps to reduce the relative strength of the power
supply noise, in comparison to the EMG signal. This effectively allows for a
high common mode rejection ratio (CMRR) between the two EMG electrodes.
Since the two EMG inputs may
be connected to things with different resistances, an instrumentation
amplifier, which is a type of differential amplifier, is used so that such
differences will not interfere with measurement accuracy. LM741 ICs are used to
construct a three-opamp instrumentation amplifier, as shown in Figure 2. Testing
showed that this circuit provides sufficient gain to make power supply
negligible.
Figure 1 - FFT of signal from
Biopac before amplifier is implemented. The code for performing this analysis
is provided in the Appendix section.
Decoupling Capacitor Design
The three LM741 amplifiers
used are integrated circuit components. Fundamentally, ICs add their own
electrical noise to the output signal. In this application, the 9V power supply
comes with tiny voltage ripples which add noise to the output signal. This
high-frequency noise in power supply signals is mitigated by adding 0.1uF
decoupling capacitors between the IC’s power supply and ground, reference
Figure 2. The electrical noise generated by the IC is shunted through the
capacitor, allowing for a cleaner signal output.
Figure 2 - Decoupling capacitor circuit diagram.
Design for Mitigating DC
Offset
Referencing the FFT in Figure
1, the large impulse around frequency 0Hz implies the presence of a DC offset.
This component of the signal is removed with a high-pass filter. Typically, a
0.1Hz passive high-pass filter is sufficient however, testing showed that a
flexing the muscle generated a wandering DC offset. This made signal processing
difficult for the microcontroller, reference Figure 3. A 0.1Hz high-pass filter
therefore ineffectively mitigated the DC offset of EMG signals.
Figure 3 - Signal after
amplifier is implemented, bad filters (left image). DC offset drift caused the signal to
inconsistently wander when integrating with the Arduino (right).
To mitigate the wandering DC
offset, the 0.1Hz high-pass filter was replaced with a 40Hz high-pass filter,
reference Figure 4. Since EMG frequency range is 50-500Hz, a 40Hz high-pass
filter does not attenuate useful EMG frequencies.
The filtered signal is then
input into BIOPAC equipment, which outputs an EMG signal with a DC offset. This
secondary DC offset did not wander and is mitigated with a 0.1Hz high-pass
filter, reference Figure 3. By mitigating these two sources of DC offset, we
can optimize signal processing before it is passed into the Arduino
microcontroller.
Figure
4 - Passive 40Hz (left) & 0.1Hz (middle) RC high-pass filter circuit. This led to superior signal output (right).
Figure 5 – Using a 40Hz high-pass filter (left)
vs a 0.1Hz high-pass filter (right) before sending to BIOPAC.
Figure 6 – Adding a 0.1Hz high-pass filter to
BIOPAC output mitigates DC offset.
Signal Processing for Optimal
Arduino Performance
All of the above circuitry is
summarized in a flowchart, reference Figure 7. The final element added to the
circuit, before sending the EMG signal into the Arduino microcontroller, was an
envelope detector, reference Figure 5. This makes it easy for the
microcontroller to control the motor based on a threshold, rather than
requiring additional local signal processing software (peak detection, signal
smoothing, etc.).
The final circuit for processing and enveloping EMG signals is
summarized in Figures 7 & 8.
Figure 7 - Circuit flowchart.
Figure
8 - Envelope detector circuit where R=8.2kOhm and C = 10uF.
Figure 9 – Signal before (left) and
after (right) the envelope detector is added. Notice that the envelope detector
adds a negative-voltage DC offset.
The enveloped signal is
passed into the Arduino. The microcontroller then analyzes the signal and,
based off of a certain threshold value, determines if the muscle is contracted
or relaxed, and controls the DC motor accordingly. If the muscle is relaxed,
then the DC motor spins one direction. If the muscle is contracted, the DC
motor spins the opposite direction. An H-bridge (L293D) is necessary for
controlling the DC motor’s direction, by reversing the direction of current
flow. The circuit require for integration of this component into the system is
provided in Figure 10. Pulse width modulation (PWM) was used to control motor
speed. A minimum of 15% duty cycle was required to make the motor move, while a
20% duty cycle was required to move the prosthesis mechanism.
The threshold value for
controlling motor direction was determined by observing the signal while the
muscle was both relaxed & contracted. While under this threshold, the
Arduino would move the motor in one direction. When the input signal exceeded this
threshold (40mV), the Arduino interpreted this as a muscle contraction and
would reverse the direction of the motor, reference Figure 11. Code for
controlling the microcontroller and motor is provided in the appendix section.
To simulate control over a prosthesis, a simple rack and pinion mechanism were
used.
Figure
10 – Circuit diagram for integrating the H-bridge and motor with the Arduino
microcontroller.
Figure 11 –
Example of Arduino-input interpreting the difference between muscle moving from
relaxed to contracted position.
The envelope detector caused
a negative DC offset, which centered the signal below 0V. Since the Arduino can
only read inputs within the range of 0 to 5V, some of the signal was lost. When
the muscle was flexed, the signal continuously peaked and troughed, preventing
it from staying above the Arduino’s threshold. These issues can be mitigated by
adding a zero-offset stage amplifier circuit, as shown in Figure 12. The
threshold value for indicating muscle contraction was 40mV. The maximum for
Arduino is Vin=5V, so adding gain to the signal can make signal processing
easier for the microcontroller.
Control over prosthesis was
demonstrated while physically holding the DC motor. This oftentimes led to
incorrect gear meshing upon contact. Superior demonstration could be possible
by adding a fixture to hold the motor in the correct orientation, in mesh with
rack gears. Additionally, friction and lateral-misalignment caused occasional
issues when moving the rack. Improving gear fixation and adding lubricant could
also improve demonstration of prosthesis-control.
Figure 13 - Variable noise in the
environment, testing different filter parameters, 60Hz noise persists. Some of this noise is due to batteries not
being fully charged. Graph on right is result when batteries are fully charged.
Signal quality also seemed to depend on which BIOPAC was used.
Appendix - MATLAB Code
%%%%%%%%%%%%%%%% Gather Data
%%%%%%%%%%%%%%%%%%%%%%%%%
s = daq.createSession('ni');
addAnalogInputChannel(s,'myDaq1', 0,
'Voltage');
s.Rate = 2000;
s.DurationInSeconds = 10;
[data,time]=s.startForeground;
figure();
subplot(2,1,1)
plot(time,data);
title('Original Signal');
xlabel('Time');
ylabel('Voltage');
%%%%%%%%%%%%%%%%%%%% FFT
%%%%%%%%%%%%%%%%%%%%%
Fs = 2000; % Sample Rate
fs = 2000; % Sample Rate
T = 1/Fs; % Sampling period
L = length(data); % Length of signal
t = (0:L-1)*T; % Time vector
Y = fft(data); % Compute the Fourier
transform of the signal.
% Compute the two-sided spectrum
P2. Then compute the single-sided
% spectrum P1 based on P2 and the
even-valued signal length L.
% Define the frequency domain f
and plot the single-sided amplitude
% spectrum P1. The amplitudes are
not exactly at 0.7 and 1, as expected,
% because of the added noise. On
average, longer signals produce better
% frequency approximations.
f = Fs*(0:(L/2))/L;
subplot(2,1,2);
plot(f,P1)
title('Stationary: Single-Sided
Amplitude Spectrum of X(t)');
xlabel('f (Hz)');
ylabel('|P1(f)|');
const int
controlPin1 = 3; // connected to pin 7 on the H-bridge const int controlPin2 =
4; // connected to pin 2 on the H-bridge const int enablePin = 9; // connected
to pin 1 on the H-bridge
float threshold = 8 // threshold value
float voltage;
int counter=0;
void setup() { // initialize the
inputs and outputs
pinMode(A0, INPUT);
pinMode(controlPin1, OUTPUT);
pinMode(controlPin2, OUTPUT);
pinMode(enablePin, OUTPUT);
digitalWrite(enablePin, HIGH);
Serial.begin(9600);
}
void loop() { // read the
value of the incoming voltage
voltage = analogRead(A0);
Serial.println(voltage);
if (voltage
> threshold) { //if voltage
is above the threshold (flexing,) turn motor one way for 3 seconds
digitalWrite(controlPin1, LOW);
digitalWrite(controlPin2, HIGH);
delay(20); // 20% duty cycle to
control motor speed
digitalWrite(controlPin1, LOW);
digitalWrite(controlPin2, LOW);
delay(100); // 20% duty cycle to
control motor speed
}
else{
digitalWrite(controlPin1, HIGH);
digitalWrite(controlPin2, LOW);
delay(20); // 20% duty cycle to
control motor speed
digitalWrite(controlPin1, LOW);
digitalWrite(controlPin2, LOW);
delay(100); // 20% duty cycle to
control motor speed
}
}













0 comments:
Post a Comment