EMG control program for use with Olimex ECG/EMG boards. Interacts with my OlimexChart Matlab programs to produce ECG or EMG strip chart displays. Also controls a relay for my Human-Human interface activity.

Dependencies:   mbed

Fork of TimeTests by Charles Tritt

Committer:
CSTritt
Date:
Tue Oct 31 21:20:05 2017 +0000
Revision:
1:d835bb04d8f0
Parent:
0:cbee9f6e3fe9
Child:
2:60d9595f9981
Initial Nucleo version.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
CSTritt 0:cbee9f6e3fe9 1 /*
CSTritt 1:d835bb04d8f0 2 Project: EMG_Control
CSTritt 0:cbee9f6e3fe9 3 File: main.cpp
CSTritt 1:d835bb04d8f0 4 Created by: Dr. C. S. Tritt
CSTritt 1:d835bb04d8f0 5 Last revision on: 9/30/17 (v. 1.0)
CSTritt 0:cbee9f6e3fe9 6
CSTritt 1:d835bb04d8f0 7 EMG control program for use with Olimex ECG/EMG shields and active low relays.
CSTritt 1:d835bb04d8f0 8 For use with my Matlab OlimexChart4.m program. Use for my Human-Human
CSTritt 1:d835bb04d8f0 9 interface activity. See external documentation for more information.
CSTritt 0:cbee9f6e3fe9 10
CSTritt 0:cbee9f6e3fe9 11 */
CSTritt 0:cbee9f6e3fe9 12 #include "mbed.h"
CSTritt 1:d835bb04d8f0 13 // Needed for isdigit function.
CSTritt 1:d835bb04d8f0 14 #include <ctype.h>
CSTritt 0:cbee9f6e3fe9 15
CSTritt 1:d835bb04d8f0 16 // Global Constants...
CSTritt 1:d835bb04d8f0 17 // EMG input pin (set by Olimex jumper).
CSTritt 1:d835bb04d8f0 18 #define EMG_IN_PIN A0
CSTritt 1:d835bb04d8f0 19 // Relay digital output pin.
CSTritt 1:d835bb04d8f0 20 #define RELAY_OUT_PIN D12
CSTritt 0:cbee9f6e3fe9 21
CSTritt 1:d835bb04d8f0 22 // ID String
CSTritt 1:d835bb04d8f0 23 const char idString[] = {"EMG Control Nucleo v. 1.0"};
CSTritt 1:d835bb04d8f0 24 // Buad rate, must be matched in Serial Monitor/Matlab. 115200 works.
CSTritt 1:d835bb04d8f0 25 const int PSPD = 115200;
CSTritt 1:d835bb04d8f0 26 // Default wait time between samples (mS). 50 Hz.
CSTritt 1:d835bb04d8f0 27 const int WAIT = 20;
CSTritt 1:d835bb04d8f0 28 // Default hold time for simulator output (mS).
CSTritt 1:d835bb04d8f0 29 const int HOLD = 500;
CSTritt 1:d835bb04d8f0 30 // Default decay factor (larger is faster).
CSTritt 1:d835bb04d8f0 31 const int DECAY = 2;
CSTritt 1:d835bb04d8f0 32 // Default mean of EMG signal (usually around 512).
CSTritt 1:d835bb04d8f0 33 const int MEAN = 512;
CSTritt 1:d835bb04d8f0 34 // Default scale factor (larger lowers sum).
CSTritt 1:d835bb04d8f0 35 const int SCALE = 4;
CSTritt 1:d835bb04d8f0 36 // Default threshold for relay activation.
CSTritt 1:d835bb04d8f0 37 const float THRESHOLD = 512;
CSTritt 1:d835bb04d8f0 38 // Default output code: 1 = EMG, 2 = RSum
CSTritt 1:d835bb04d8f0 39 const int CODE = 1;
CSTritt 0:cbee9f6e3fe9 40
CSTritt 1:d835bb04d8f0 41 // Global mbed objects...
CSTritt 1:d835bb04d8f0 42 // Relay output object & pin.
CSTritt 1:d835bb04d8f0 43 DigitalOut relay(RELAY_OUT_PIN);
CSTritt 1:d835bb04d8f0 44 // EMG analogy input object & pin.
CSTritt 1:d835bb04d8f0 45 AnalogIn oliVal(EMG_IN_PIN);
CSTritt 1:d835bb04d8f0 46 // PC serial object pins & baud rate.
CSTritt 1:d835bb04d8f0 47 Serial pc(USBTX, USBRX, PSPD);
CSTritt 1:d835bb04d8f0 48 // Ticker for millisecond clock.
CSTritt 1:d835bb04d8f0 49 Ticker milliTick;
CSTritt 1:d835bb04d8f0 50
CSTritt 1:d835bb04d8f0 51 // Global variable...
CSTritt 1:d835bb04d8f0 52 volatile unsigned int millis = 0; // Milliseconds since reset for timestamp.
CSTritt 1:d835bb04d8f0 53
CSTritt 1:d835bb04d8f0 54 // Function declarations...
CSTritt 1:d835bb04d8f0 55 // Millisecond clock callback/ISR.
CSTritt 1:d835bb04d8f0 56 void milliIncr(void);
CSTritt 1:d835bb04d8f0 57 // Converts ASCII digit code to corresponding int value.
CSTritt 1:d835bb04d8f0 58 int dig2Int(char myChar);
CSTritt 0:cbee9f6e3fe9 59
CSTritt 0:cbee9f6e3fe9 60 int main()
CSTritt 0:cbee9f6e3fe9 61 {
CSTritt 1:d835bb04d8f0 62 relay.write(1); // Assure active low relay is off at start.
CSTritt 1:d835bb04d8f0 63 // Announce program identity.
CSTritt 1:d835bb04d8f0 64 pc.printf("%s\n", idString);
CSTritt 1:d835bb04d8f0 65
CSTritt 1:d835bb04d8f0 66 // Define and initialize important variables...
CSTritt 1:d835bb04d8f0 67 unsigned int actTime = 0; // Most recent relay activation time (mS).
CSTritt 1:d835bb04d8f0 68 float waitTime = (float) WAIT / 1000.f; // Wait time between samples (S).
CSTritt 1:d835bb04d8f0 69
CSTritt 1:d835bb04d8f0 70 int hold = HOLD; // Hold time for stimulator output (mS).
CSTritt 1:d835bb04d8f0 71 int decay = DECAY; // Decay factor (larger is faster).
CSTritt 1:d835bb04d8f0 72 int mean = MEAN; // Mean of EMG signal (usually around 512).
CSTritt 1:d835bb04d8f0 73 int scale = SCALE; // Scale factor (larger lowers sum).
CSTritt 1:d835bb04d8f0 74 int threshold = THRESHOLD; // Threshold for relay activation.
CSTritt 1:d835bb04d8f0 75 int rSum = 0; // Initial decaying running sum of squared activity.
CSTritt 1:d835bb04d8f0 76
CSTritt 1:d835bb04d8f0 77 int parmVal = 0; // Initial command parameter value.
CSTritt 1:d835bb04d8f0 78 int code = CODE; // Output code: 1 = EMG, 2 = Running Sum.
CSTritt 1:d835bb04d8f0 79 bool go = false; // Flag for sending data. Start not sending.
CSTritt 1:d835bb04d8f0 80
CSTritt 1:d835bb04d8f0 81 milliTick.attach_us(milliIncr, 1000); // Attach ISR to mS clock ticker.
CSTritt 0:cbee9f6e3fe9 82 while(true) {
CSTritt 1:d835bb04d8f0 83 if (pc.readable()) { // Process command text...
CSTritt 1:d835bb04d8f0 84 char myChar = pc.getc(); // Read a character.
CSTritt 1:d835bb04d8f0 85 pc.putc(myChar); // Echo the character.
CSTritt 1:d835bb04d8f0 86 if (isdigit(myChar)) { // Process the digit...
CSTritt 1:d835bb04d8f0 87 parmVal = 10 * parmVal + dig2Int(myChar); // Shift & add value.
CSTritt 1:d835bb04d8f0 88 } else { // Deal with command code letters...
CSTritt 1:d835bb04d8f0 89 switch (myChar) { // Add cases below for more commands.
CSTritt 1:d835bb04d8f0 90 case 'd': // Change decay value.
CSTritt 1:d835bb04d8f0 91 if (parmVal == 0) parmVal = DECAY; // Use default.
CSTritt 1:d835bb04d8f0 92 decay = parmVal; // Change decay.
CSTritt 1:d835bb04d8f0 93 break; // All but last case needs a break.
CSTritt 1:d835bb04d8f0 94 case 'g': // Switch into go (read & output data) mode.
CSTritt 1:d835bb04d8f0 95 go = true;
CSTritt 1:d835bb04d8f0 96 break; // All but last case needs a break.
CSTritt 1:d835bb04d8f0 97 case 'h': // Change hold value.
CSTritt 1:d835bb04d8f0 98 if (parmVal == 0) parmVal = HOLD; // Use default.
CSTritt 1:d835bb04d8f0 99 hold = parmVal; // Change hold.
CSTritt 1:d835bb04d8f0 100 case 'i': // Send program ID.
CSTritt 1:d835bb04d8f0 101 pc.printf("%s\n", idString);
CSTritt 1:d835bb04d8f0 102 break; // All but last case needs a break.
CSTritt 1:d835bb04d8f0 103 case 'm': // Change expected mean value.
CSTritt 1:d835bb04d8f0 104 if (parmVal == 0) parmVal = MEAN; // Use default.
CSTritt 1:d835bb04d8f0 105 mean = parmVal; // Change mean.
CSTritt 1:d835bb04d8f0 106 break; // All but last case needs a break.
CSTritt 1:d835bb04d8f0 107 case 'o': // Change output code value.
CSTritt 1:d835bb04d8f0 108 if (parmVal == 0) parmVal = CODE; // Use default.
CSTritt 1:d835bb04d8f0 109 code = parmVal; // Change code.
CSTritt 1:d835bb04d8f0 110 break; // All but last case needs a break.
CSTritt 1:d835bb04d8f0 111 case 's': // Change scale factor value.
CSTritt 1:d835bb04d8f0 112 if (parmVal == 0) parmVal = SCALE; // Use default.
CSTritt 1:d835bb04d8f0 113 scale = parmVal; // Change scale.
CSTritt 1:d835bb04d8f0 114 break; // All but last case needs a break.
CSTritt 1:d835bb04d8f0 115 case 't': // Change activation threshold value.
CSTritt 1:d835bb04d8f0 116 if (parmVal == 0) parmVal = THRESHOLD; // Use default.
CSTritt 1:d835bb04d8f0 117 threshold = parmVal; // Change threshold.
CSTritt 1:d835bb04d8f0 118 break; // All but last case needs a break.
CSTritt 1:d835bb04d8f0 119 case 'w': // Change between sample wait value (S).
CSTritt 1:d835bb04d8f0 120 if (parmVal == 0) parmVal = WAIT; // Use default.
CSTritt 1:d835bb04d8f0 121 waitTime = (float) parmVal / 1000.f; // Change waitTime.
CSTritt 1:d835bb04d8f0 122 break; // All but last case needs a break.
CSTritt 1:d835bb04d8f0 123 case 'x': // Send data marker (time & minus parmVal).
CSTritt 1:d835bb04d8f0 124 // Also use for debugging command processing.
CSTritt 1:d835bb04d8f0 125 pc.printf("%u, %d\n", millis, -parmVal);
CSTritt 1:d835bb04d8f0 126 break; // All but last case needs a break.
CSTritt 1:d835bb04d8f0 127 case 'z': // Switch out of go (read & output data) mode.
CSTritt 1:d835bb04d8f0 128 go = false;
CSTritt 1:d835bb04d8f0 129 break; // All but last case needs a break.
CSTritt 1:d835bb04d8f0 130 }
CSTritt 1:d835bb04d8f0 131 parmVal = 0; // Reset parmVal to zero for next command.
CSTritt 1:d835bb04d8f0 132 }
CSTritt 1:d835bb04d8f0 133 } // End of command text processing.
CSTritt 1:d835bb04d8f0 134 if (go) { // Complete go mode tasks...
CSTritt 1:d835bb04d8f0 135 // Read and process EMG data...
CSTritt 1:d835bb04d8f0 136 float EMG_float = oliVal.read(); // Read & save analog Olimex value.
CSTritt 1:d835bb04d8f0 137 unsigned int time = millis; // Save read time.
CSTritt 1:d835bb04d8f0 138 int EMG_int = (int)(1023.f * EMG_float); // Scale EMG reading.
CSTritt 1:d835bb04d8f0 139 int diff =EMG_int - mean; // Center on specified mean.
CSTritt 1:d835bb04d8f0 140 // Accumulate decaying running sum of squares (filtered value).
CSTritt 1:d835bb04d8f0 141 rSum = rSum/decay + diff*diff/scale;
CSTritt 1:d835bb04d8f0 142
CSTritt 1:d835bb04d8f0 143 // Activate relay if appropriate...
CSTritt 1:d835bb04d8f0 144 if (time - actTime > hold) {
CSTritt 1:d835bb04d8f0 145 relay.write(0); // Activate active low relay.
CSTritt 1:d835bb04d8f0 146 actTime = time; // Save activation time.
CSTritt 1:d835bb04d8f0 147 } else {
CSTritt 1:d835bb04d8f0 148 relay.write(1); // Deactivate active low relay.
CSTritt 1:d835bb04d8f0 149 }
CSTritt 1:d835bb04d8f0 150
CSTritt 1:d835bb04d8f0 151 // Send data to PC...
CSTritt 1:d835bb04d8f0 152 pc.printf("%u, ", time); // Send the time and a comma.
CSTritt 1:d835bb04d8f0 153 if (code == 1) {
CSTritt 1:d835bb04d8f0 154 pc.printf("%d\n", EMG_int);
CSTritt 1:d835bb04d8f0 155 } else if (code == 2) {
CSTritt 1:d835bb04d8f0 156 pc.printf("%d\n", rSum);
CSTritt 1:d835bb04d8f0 157 } else { // Invalid code value.
CSTritt 1:d835bb04d8f0 158 pc.printf("?\n");
CSTritt 1:d835bb04d8f0 159 }
CSTritt 1:d835bb04d8f0 160 } else if (!relay.read()){
CSTritt 1:d835bb04d8f0 161 relay.write(1); // Deactivate relay in
CSTritt 0:cbee9f6e3fe9 162 }
CSTritt 1:d835bb04d8f0 163 wait(waitTime);
CSTritt 0:cbee9f6e3fe9 164 }
CSTritt 0:cbee9f6e3fe9 165 }
CSTritt 0:cbee9f6e3fe9 166
CSTritt 0:cbee9f6e3fe9 167 void milliIncr(void) // Call back that adds millisconds to millis.
CSTritt 0:cbee9f6e3fe9 168 {
CSTritt 0:cbee9f6e3fe9 169 millis++; // Increment by 10 milliseconds each time.
CSTritt 1:d835bb04d8f0 170 }
CSTritt 1:d835bb04d8f0 171
CSTritt 1:d835bb04d8f0 172 int dig2Int(char myChar)
CSTritt 1:d835bb04d8f0 173 {
CSTritt 1:d835bb04d8f0 174 /*
CSTritt 1:d835bb04d8f0 175 Utility function for Converting a digit to the equivalent int.
CSTritt 1:d835bb04d8f0 176 */
CSTritt 1:d835bb04d8f0 177 int charVal = (int) myChar; // ASCII digit binary values are shifted by 48.
CSTritt 1:d835bb04d8f0 178 return charVal - 48;
CSTritt 0:cbee9f6e3fe9 179 }