-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy path10-06
More file actions
243 lines (208 loc) · 6.96 KB
/
10-06
File metadata and controls
243 lines (208 loc) · 6.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <AccelStepper.h>
#include "EMGFilters.h"
// Define constants
#define TIMING_DEBUG 1
#define NUM_FLEX_SENSORS 5
#define SAMPLE_RATE SAMPLE_FREQ_1000HZ // EMG filter supports 500Hz or 1000Hz
#define HUM_FREQ NOTCH_FREQ_50HZ // Power line interference frequency
// Calibration settings
const int calibrationDuration = 10000; // 10 seconds
static const int threshold = 0; // EMG calibration threshold
// Motor and stepper settings
const int stepsPerRevolution = 200;
const int stepDelay = 1000;
const int stepsThumb = 200;
const int stepsIndex = 400;
const int stepsFingers = 450;
const int maxSpeed = 800;
const int accel = 600;
// Idle disable settings
const int ENABLE_PIN = 10; // Shared enable pin (LOW = enabled)
const unsigned long IDLE_TIMEOUT = 3000; // 3 seconds
unsigned long lastMoveTime = 0;
bool motorsEnabled = true;
// Pin definitions
const int sensorPins[NUM_FLEX_SENSORS] = {A0, A1, A2, A3, A4};
const int emgInputPin = A5;
const int stepPinThumb = 9, dirPinThumb = 8;
const int stepPinPoint = 3, dirPinPoint = 2;
const int stepPinFingers = 5, dirPinFingers = 4;
// Global variables
EMGFilters emgFilter;
int baselineEmgValue = 0;
bool isCalibrated = false;
unsigned long calibrationStartTime = 0;
int totalEmgValue = 0;
int sampleCount = 0;
int sensorValues[NUM_FLEX_SENSORS];
long baselineFlexSensorValues[NUM_FLEX_SENSORS] = {0, 0, 0, 0, 0};
// Stepper motor instances (DRIVER mode)
AccelStepper thumbMotor(AccelStepper::DRIVER, stepPinThumb, dirPinThumb);
AccelStepper indexMotor(AccelStepper::DRIVER, stepPinPoint, dirPinPoint);
AccelStepper fingersMotor(AccelStepper::DRIVER, stepPinFingers, dirPinFingers);
// Function Prototypes
void calibrateSensors();
void readFlexSensors();
void moveMotor(AccelStepper &motor, int steps, bool tighten);
void setupMotors();
void enableMotors();
void disableMotors();
void setup() {
Serial.begin(9600);
// Initialize EMG Filter
emgFilter.init(SAMPLE_RATE, HUM_FREQ, true, true, true);
// Flex sensor pin setup
for (int i = 0; i < NUM_FLEX_SENSORS; i++) {
pinMode(sensorPins[i], INPUT);
}
// Motor pin setup
pinMode(stepPinThumb, OUTPUT);
pinMode(dirPinThumb, OUTPUT);
pinMode(stepPinPoint, OUTPUT);
pinMode(dirPinPoint, OUTPUT);
pinMode(stepPinFingers, OUTPUT);
pinMode(dirPinFingers, OUTPUT);
// Enable pin setup
pinMode(ENABLE_PIN, OUTPUT);
digitalWrite(ENABLE_PIN, LOW); // Motors start enabled
// Motor setup
setupMotors();
// Start calibration
calibrationStartTime = millis();
Serial.println("Thumb Index Middle Ring Pinky");
}
void loop() {
if (!isCalibrated) {
calibrateSensors();
return;
}
// Process flex sensors
readFlexSensors();
// Continuously run motors
thumbMotor.run();
indexMotor.run();
fingersMotor.run();
// Check if any motor is active
bool anyRunning = thumbMotor.isRunning() || indexMotor.isRunning() || fingersMotor.isRunning();
if (anyRunning) {
lastMoveTime = millis();
if (!motorsEnabled) enableMotors();
} else {
if (motorsEnabled && (millis() - lastMoveTime > IDLE_TIMEOUT)) {
disableMotors();
}
}
}
// --- Calibration ---
void calibrateSensors() {
unsigned long currentTime = millis();
int timeRemaining = (calibrationDuration - (currentTime - calibrationStartTime)) / 1000;
if (currentTime - calibrationStartTime < calibrationDuration) {
int emgValue = analogRead(emgInputPin);
int filteredEmgValue = emgFilter.update(emgValue);
totalEmgValue += filteredEmgValue;
sampleCount++;
// Accumulate sensor values
for (int i = 0; i < NUM_FLEX_SENSORS; i++) {
sensorValues[i] = analogRead(sensorPins[i]);
baselineFlexSensorValues[i] += sensorValues[i];
}
// Print once per second
static int lastPrintedSecond = -1;
if (timeRemaining != lastPrintedSecond) {
Serial.print("Calibrating... Time left: ");
Serial.print(timeRemaining);
Serial.println(" sec");
lastPrintedSecond = timeRemaining;
}
} else {
// Calculate baselines
baselineEmgValue = totalEmgValue / sampleCount;
for (int i = 0; i < NUM_FLEX_SENSORS; i++)
baselineFlexSensorValues[i] /= sampleCount;
Serial.println("Calibration complete!");
isCalibrated = true;
}
}
// --- Motor Setup ---
void setupMotors() {
thumbMotor.setMaxSpeed(maxSpeed);
thumbMotor.setAcceleration(accel);
indexMotor.setMaxSpeed(maxSpeed);
indexMotor.setAcceleration(accel);
fingersMotor.setMaxSpeed(maxSpeed);
fingersMotor.setAcceleration(accel);
}
// --- Flex Sensor Processing ---
void readFlexSensors() {
for (int i = 0; i < NUM_FLEX_SENSORS; i++)
sensorValues[i] = analogRead(sensorPins[i]);
bool pinkyTriggered = (baselineFlexSensorValues[0] - sensorValues[0] > 100);
bool ringTriggered = (baselineFlexSensorValues[1] - sensorValues[1] > 100);
bool middleTriggered = (baselineFlexSensorValues[2] - sensorValues[2] > 100);
bool indexTriggered = (baselineFlexSensorValues[3] - sensorValues[3] > 100);
bool thumbTriggered = (baselineFlexSensorValues[4] - sensorValues[4] > 100);
// Serial plotter output
for (int i = 4; i >= 0; i--) {
Serial.print(sensorValues[i]);
Serial.print(" ");
}
Serial.println();
// Priority motion logic
if (thumbTriggered && indexTriggered && middleTriggered && ringTriggered && pinkyTriggered) {
Serial.println("All fingers flexed. Moving all motors.");
moveMotor(thumbMotor, stepsThumb, true);
moveMotor(indexMotor, stepsIndex, true);
moveMotor(fingersMotor, stepsFingers, true);
}
else if (thumbTriggered && indexTriggered) {
Serial.println("Thumb + Index triggered.");
moveMotor(thumbMotor, stepsThumb, true);
moveMotor(indexMotor, stepsIndex, true);
}
else if (indexTriggered && (middleTriggered || ringTriggered || pinkyTriggered)) {
Serial.println("Index + Fingers triggered.");
moveMotor(indexMotor, stepsIndex, true);
moveMotor(fingersMotor, stepsFingers, true);
}
else {
if (indexTriggered) {
Serial.println("Index only triggered.");
moveMotor(indexMotor, stepsIndex, true);
}
if (middleTriggered || ringTriggered || pinkyTriggered) {
Serial.println("Fingers only triggered.");
moveMotor(fingersMotor, stepsFingers, true);
}
if (thumbTriggered) {
Serial.println("Thumb only triggered.");
moveMotor(thumbMotor, stepsThumb, true);
}
}
}
// --- Motor Control ---
void moveMotor(AccelStepper &motor, int steps, bool tighten) {
long targetPos = 0;
if (tighten) {
targetPos = motor.currentPosition() + steps;
} else {
targetPos = motor.currentPosition() - steps;
}
motor.moveTo(targetPos);
}
// --- Enable/Disable Motors ---
void enableMotors() {
digitalWrite(ENABLE_PIN, LOW);
motorsEnabled = true;
Serial.println("Motors enabled.");
}
void disableMotors() {
digitalWrite(ENABLE_PIN, HIGH); // Disable (freewheel)
motorsEnabled = false;
Serial.println("Motors disabled after inactivity.");
}