EMG controlling

HEY…I’m trying to operate my robot with EMG signal, but I’m having problems as it’s unable to hold the value.
Taking the example of forward motion I’ve set the threshold between 200 and 300.
As the muscles movement reaches to this range it does react and work, but the problem is, hand is required to maintain this motion until it wants to move forward, as soon as the hand stops moving, it drops down to initial value. Which stops the device. how can i maintain/hold the same value until the next treshold exceeds 400 i-e the comditon for stop?
below is my code

const int analogInPin = A0;
int sensorValue = 0;

void setup()
{
Serial.begin(9600);
pinMode(4,OUTPUT);
pinMode(6,OUTPUT);
pinMode(11,OUTPUT);
pinMode(12,OUTPUT);

}

void loop()
{

sensorValue = analogRead(analogInPin);
if(sensorValue > 400 ) // Stop
{
digitalWrite(4, LOW);
digitalWrite(12, LOW);
digitalWrite(11, LOW);
digitalWrite(6, LOW);
}
else if (sensorValue > 200 && sensorValue < 300) //FORWARD
{
digitalWrite(4, LOW);
digitalWrite(12, HIGH);
digitalWrite(11, LOW);
digitalWrite(6, HIGH);
}

Serial.println(sensorValue);
delay(100);
}

try to first express in plain english how this should work

  • what’s the start state
  • how does it start moving
  • when does it need to stop

then have a code that implement this. you will probably need to remember a state

how can i maintain/hold the same value until the next treshold exceeds 400

What value do you want to "maintain/hold"? Until what next exceeds 400?

If the reading from the analog pin exceeds 400, you can do something, but then you can't undo that when the reading is less than 400, and expect what happened when the value exceeded 400 to continue happening.

J-M-L:
try to first express in plain english how this should work

  • what's the start state
  • how does it start moving
  • when does it need to stop

then have a code that implement this. you will probably need to remember a state

when the hand is at rest the analog input reads values between 50 to 100...
i have not used these values in programming but when the hand is moved for example if the fist closes, these values increase. so i have set a condition that if the value reaches between 200 and 300 it should move forward, and it is moving that way, but maintaining the same gesture (i-e keeping the fist close ) drops the values (because now muscles are at rest in closed fist position ) hence it stops moving forward. I want to maintain this value until the gesture change happens. for example until the value exceeds 400 i want it to work in the same way as when the value was between 200 and 300 (i-e moving forward).

PaulS:
What value do you want to "maintain/hold"? Until what next exceeds 400?

If the reading from the analog pin exceeds 400, you can do something, but then you can't undo that when the reading is less than 400, and expect what happened when the value exceeded 400 to continue happening.

when the hand is at rest the analog input reads values between 50 to 100...
i have not used these values in programming but when the hand is moved for example if the fist closes, these values increase. so i have set a condition that if the value reaches between 200 and 300 it should move forward, and it is moving that way, but maintaining the same gesture (i-e keeping the fist close ) drops the values (because now muscles are at rest in closed fist position ) hence it stops moving forward. I want to maintain this value until the gesture change happens. for example until the value exceeds 400 i want it to work in the same way as when the value was between 200 and 300 (i-e moving forward).

if I understand well you have 4 states:

AT_REST:
initial condition. Value is <100. You want to start moving if value become HIGH ENOUGH > 200

MOVING_WAITING_FOR_LOW
You are moving and you know sensor will become LOW (<100)

STEADY_WAIT_FOR_CHANGE
You have reached the LOW and want to keep moving until the next HIGH (> 400). you know sensor will become LOW (<100) again and at that point you’ll be able to play again

AT_REST_WAITING_FOR_LOW
You have reached the LOW, so ready to record a new action. Go back to the AT_REST stage

this is a simple state machine, you could possibly try something like this (untested, just typed in on my cell phone)

const byte analogInPin = A0;   // <-- WOULD BE GOOD TO GIVE A MEANINGFUL NAME TO THIS PINS
const byte pin4 = 4;   // <-- WOULD BE GOOD TO GIVE A MEANINGFUL NAME TO THIS PINS
const byte pin6 = 6;   // <-- WOULD BE GOOD TO GIVE A MEANINGFUL NAME TO THIS PINS
const byte pin11 = 11; // <-- WOULD BE GOOD TO GIVE A MEANINGFUL NAME TO THIS PINS
const byte pin12 = 12; // <-- WOULD BE GOOD TO GIVE A MEANINGFUL NAME TO THIS PINS

enum {AT_REST, MOVING_WAITING_FOR_LOW, STEADY_WAIT_FOR_CHANGE, AT_REST_WAITING_FOR_LOW} currentStatus;

int sensorValue = 0;

void setup()
{
  Serial.begin(9600);

  pinMode(pin4, OUTPUT);
  pinMode(pin6, OUTPUT);
  pinMode(pin11, OUTPUT);
  pinMode(pin12, OUTPUT);

  // fully ensure we are at rest
  digitalWrite(pin4, LOW);
  digitalWrite(pin12, LOW);
  digitalWrite(pin11, LOW);
  digitalWrite(pin6, LOW);
  currentStatus = AT_REST;
}

void loop()
{
  sensorValue = analogRead(analogInPin);
  Serial.println(sensorValue);


  // could use else between the if in this example, but not always in state machines

  // ------------------------------------------------------------
  // AT_REST waiting for a sensor trigger to start moving
  // ------------------------------------------------------------
  if ((currentStatus == AT_REST) && (sensorValue > 200)) {//MOVE FORWARD
    digitalWrite(pin4, LOW);
    digitalWrite(pin12, HIGH);
    digitalWrite(pin11, LOW);
    digitalWrite(pin6, HIGH);
    currentStatus = MOVING_WAITING_FOR_LOW;
  }

  // ------------------------------------------------------------
  // We are moving waiting for a sensor to go back Low
  // ------------------------------------------------------------
  if ((currentStatus == MOVING_WAITING_FOR_LOW) && (sensorValue < 100)) {  // received LOW
    currentStatus = STEADY_WAIT_FOR_CHANGE;
  }

  // ------------------------------------------------------------
  // Sensor went back Low, is new movement starting?
  // ------------------------------------------------------------
  if ((currentStatus == STEADY_WAIT_FOR_CHANGE) && (sensorValue > 200))  {// STOP
    digitalWrite(pin4, LOW);
    digitalWrite(pin12, LOW);
    digitalWrite(pin11, LOW);
    digitalWrite(pin6, LOW);
    currentStatus = AT_REST_WAITING_FOR_LOW;
  }

  // ------------------------------------------------------------
  // New movement started, is it stopping ?
  // ------------------------------------------------------------
  if ((currentStatus == AT_REST_WAITING_FOR_LOW) && (sensorValue < 100)) {  // received LOW
    currentStatus = AT_REST;
  }
}

Thank you so very much!! :slight_smile: your code is working exactly the way i want it to work :smiley: :smiley:
meanwhile I tried to do it and made a code. it’s also working but yet I want your second opinion should I go for it ?

const int analogInPin = A0;
int sensorValue = 0;

void setup()
{
Serial.begin(9600);
pinMode(4,OUTPUT);
pinMode(6,OUTPUT);
pinMode(11,OUTPUT);
pinMode(12,OUTPUT);

}

void loop()
{

sensorValue = analogRead(analogInPin);
if (sensorValue > 400) //STOP
{
digitalWrite(4, LOW);
digitalWrite(12, LOW);
digitalWrite(11, LOW);
digitalWrite(6, LOW);
delay (1000);
}

if (sensorValue > 100 && sensorValue <350) //FORWARD
{
do
{
digitalWrite(4, LOW);
digitalWrite(12, HIGH);
digitalWrite(11, LOW);
digitalWrite(6, HIGH);

} while (sensorValue > 400); }

Serial.println(sensorValue);
delay(100);
}

if (sensorValue > 100 && sensorValue <350) //FORWARD
  {
  do
  {
      digitalWrite(4, LOW);
      digitalWrite(12, HIGH);
      digitalWrite(11, LOW);
      digitalWrite(6, HIGH);
 
} while (sensorValue > 400); }

If the sensor value is between 101 and 349, inclusive, do some stuff while the sensor value is above 400. How likely is it that the do/while statement will iterate more than once? Why should it iterate even once?

Do/while has to be the most misused statement in C. Your use is incorrect, as are many other places where it is used.

Even if it were correct to use a do/while loop, and it were logically placed, what would cause the loop to end? Once started, the value in sensorValue never changes, so the loop would never end.

Now, if you address all those issues, you have to ask yourself why you need to set those pins to those states more than once.

Your code will not work actually - and is not very clean (nor indented - presss ctrl-T in the IDE)

you have an inner loop (the do while) constantly setting the pins - this is not needed - set the pins and then do the active wait.

In your active wait you wait for sensorValue to go above 400 but you don’t read it… So no chance this will work. You need to call analogRead to update that value

the “non clean” version with active Wait could be:

  if (sensorValue > 100 && sensorValue <350) {

      //FORWARD
      digitalWrite(4, LOW);
      digitalWrite(12, HIGH);
      digitalWrite(11, LOW);
      digitalWrite(6, HIGH);

      // wait until sensor changes
      while (analogRead(analogInPin) <= 400); 
  
  }

But performing an active wait is not a great practice - it prevents you from doing other things in the loop while waiting for the condition to be met … or your code will soon become spaghetti code because you’ll add tons of tests everywhere …

So I would recommend to study the state machine approach I gave you above

PaulS:
what would cause the loop to end? Once started, the value in sensorValue never changes, so the loop would never end.

As it is an Emg sensor value does change.

Crony:
As it is an Emg sensor value does change.

CF post #8

Yes the value will change but his point and mine is that you are not reading it in your do-while loop

  do
  {
      digitalWrite(4, LOW);
      digitalWrite(12, HIGH);
      digitalWrite(11, LOW);
      digitalWrite(6, HIGH);
 
} while ([color=red]sensorValue[/color] > 400);

→ what is changing

sensorValue

in this infinite loop?

(and as mentioned, it’s useless to keep setting the LOW or HIGH while you wait for state change - hence the hint about doing this instead

  if (sensorValue > 100 && sensorValue <350) {

      //FORWARD
      digitalWrite(4, LOW);
      digitalWrite(12, HIGH);
      digitalWrite(11, LOW);
      digitalWrite(6, HIGH);

      // wait until sensor changes
      while (analogRead(analogInPin) <= 400); 
  
  }

As it is an Emg sensor value does change.

The value that you COULD read from the sensor will change. The value that you DO read in the while loop doesn't because you don't read from the sensor in the while loop.

okay.. I got your point you guys are probably trying to say that, as it is an inner loop it won't understand what does the variable "sensorValue" read. but strangely it was working :open_mouth:

anyways I'll follow the approach you mentioned above, thanks man, you've been a great help! thanks to both of you! will bother you again in case of further queries :smiley:

you guys are probably trying to say that, as it is an inner loop it won't understand what does the variable "sensorValue" read. but strangely it was working :open_mouth:

No your code was not working... it was in an infinite loop... really...

the variable sensorValue does not READ anything.. it's a value. it's not because you initialized it with the value of analogRead(analogInPin) that it will keep in sync with that pin's value..sensorValue = analogRead(analogInPin); means call the analogRead() function with parameter analogInPin and store the result in memory at the location pointed by the variable with name sensorValue.

When you access variable with name sensorValue, you read what is stored at that memory location. nothing is magically changing that memory location