-
1Step 1
Attach the SpikerShield to an Arduino
The output of the SpikerShield is an analog value between 0 and 5 volts. It is connected to one of the Arduino's analog inputs. There is a jumper on the shield to determine which one. I keep mine on A0.
-
2Step 2
Attach the Electrodes to Your Arm and the Shield
The electrodes need to be attached in specific locations. The 2 signal electrodes go on the inside of your forearm. I had one located about 2-finger widths from the bend of my elbow (measuring from the bend to the edge of the electrode). Moving further away from my elbow I placed the next one about 2 finger widths after the first. Those get connected to the red and black cables (it doesn't matter which goes where). You also need a ground. I put that on the outside of the bend in my elbow and connected it is connected to the white cable. Each of those cables should be plugged into the corresponding colored RCA plug on the shield.
With the shield and electrodes connected we can begin measuring stuff!
-
3Step 3
Determine the Maximum Output Value
First let's see what range our output falls into. The following Arduino code will show the maximum and current value of the measurement from the shield on the serial monitor. Load this in your Arduino IDE, run it and start flexing (don't forget to relax too, ie flex, relax, flex, relax, flex, relax, stare at barrage of numbers, flex, relax):
#define SMOOTHING 1 int values[SMOOTHING]; int index = 0; const int inputEmg = A0; int maxReading = 0; void setup(){ Serial.begin(9600); Serial.println(' '); pinMode(inputEmg, INPUT); for( int i=0; i<SMOOTHING; i+=1 ){ values[i] = 0; } } void loop(){ // Read the current emg signal int reading = analogRead(inputEmg); // Update the buffer of last read values, overwriting the oldest values[index] = reading; index += 1; if( index >= SMOOTHING ){ index = 0; } // Compute the average of the last values int average = 0; for( int i = 0; i<SMOOTHING; i+=1 ){ average += values[i]; } average /= SMOOTHING; // if this is a new max, remember it if( average > maxReading ){ maxReading = average; } // Debug info: max, lastReading Serial.print(maxReading); Serial.print(", "); Serial.println(average); }
-
4Step 4
Count Some Flexes
Now that we (roughly) know the maximum value of the output, we can pick a value which signifies the impulse is strong enough to be a muscle action. I arbitrarily decided to use 1/2 of the maximum value. When the signal crosses above that value we'll add 1 to the count.
We're sampling this analog signal many times per second. The signal could be noisy so we smooth it out by averaging the last 50 samples.
When the threshold is passed the signal could stay at that level for several more samples so we need to wait for it to drop before we add to the count again.
What's a cool signal without cool output? A cool signal. But we want a cool output too. That's why there are 6 LEDs that we use to represent the count of muscle flexes.
Here's the code:
#define SMOOTHING 50 #define NORMAL_MAX 800 const int inputEmg = A0; const int nLeds = 6; const int ledPins[] = {8,9,10,11,12,13}; int waiting = 1; int readyToChange = 1; int threshold = NORMAL_MAX/2; int values[SMOOTHING]; int index = 0; void setup(){ // Enable serial for debugging Serial.begin(9600); Serial.println(' '); // Setup the EMG signal as an input pint pinMode(inputEmg, INPUT); // Set the LEDs as outputs for( int i=0; i<nLeds; i+=1 ){ pinMode(ledPins[i], OUTPUT); } // Set the 'averaging' buffer to all 0's for( int i=0; i<SMOOTHING; i+=1 ){ values[i] = 0; } } int count = 0; void loop(){ // Read the current emg signal int reading = analogRead(inputEmg); // Update the buffer of last read values, overwriting the oldest values[index] = reading; index += 1; if( index >= SMOOTHING ){ index = 0; } // Compute the average of the last values // TODO: update the average faster (without iterating over all values) int average = 0; for( int i = 0; i<SMOOTHING; i+=1 ){ average += values[i]; } average /= SMOOTHING; // When the signal is high and drops low (the spike has ended) if( readyToChange == 1 && average < threshold ){ readyToChange = 0; // Update the current count of flexes, remember the number of LEDS count += 1; if( count > nLeds ){ count = 0; } // Update the LED display for( int i=0; i<nLeds; i+=1 ){ digitalWrite(ledPins[i], LOW); } digitalWrite(ledPins[count], HIGH); } // When we're in a low and the signal goes high, (spike is starting) if( readyToChange == 0 && average > threshold ){ readyToChange = 1; } // send the data so we can see it on the serial monitor Serial.println(average); }
Load that into your Arduino and flex your muscles (close/open your hand) to see the LEDs count the number of times you've open or closed your hand. It only counts to 6. -
5Step 5
Improvements
Feel free to make the code count flexes in binary. Then you could count up to 63 flexes!
Also the spike detecting and averaging portion of the code could be improved so that it'll count small impulses and avoid over counting certain larger spikes.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.