2

I have an Arduino connected to a pico motor driver that is supposed to take a number of steps for a specific number of triggers that gets from a source (i.e. waveform generator). I've setup the code so that it would ask the user to input number of steps and number of triggers. For example, if I want the motor to take 10 steps once it got 60 triggers, I should input s10; and t60; separately into Serial Monitor.

In addition, I want to be able to change the number of steps and triggers any time that I want. However the problem is that sometimes Arduino doesn't receive the input string entirely for the first time. Sometimes it works on the second try. Or even not at all. I really appreciate if someone can give a hint on why this is happening.

This is a simple version of the code (without the parts that move the motor):

#include<String.h>

long int steps;
long int num_triggers;
long int newtrigger;
long int newstep;
long int oldtrigger;
long int oldstep;

const int main_control = 0;
int triggers_count;
bool motor_trigger = true;

void setup() {

 Serial.begin(19200);
 Serial.println("Please enter chosen number of steps and triggers.");
 Serial.println("Example: \n If you want the pico-motor to take 10 steps per 40 triggers,");
 Serial.println(" write 's10;' and press enter then do the same for 't45;'(Order doesn't matter).");
}

void loop() {

  while (num_triggers == 0 || steps == 0) {

    getcommand(&steps, &num_triggers);

  }

  attachInterrupt(main_control, trigger, RISING);  // it starts looking for trigger  

  if (motor_trigger == false) {

    getcommand(&steps, &num_triggers);
  }

  else if (motor_trigger == true) {

    motor_trigger = false;
    detachInterrupt(main_control);

    if (triggers_count <= (num_triggers - 1)) {

      getcommand(&steps, &num_triggers);

    }

    else {

      for (int i = 0; i < steps; i++) {

        oldstep = steps;
        oldtrigger = num_triggers;
        getcommand(&steps, &num_triggers);

        if (  num_triggers != oldtrigger || steps != oldstep) {
          break;
        }
      }
    }
  }    
}






void trigger(void) {

  motor_trigger = true;
  triggers_count++; 
}

void getcommand (long int *newstep, long int *newtrigger) {

    char   char_input;
    String string_input;
    String output_1;
    String output_2;

  while (Serial.available()) {

    char_input = Serial.read();
      if (char_input == ';'){
    Serial.println("done");

      }
      else{
    string_input += char_input;
    delay(500);
    }    
  }

  Serial.println("Getting input...");
  Serial.println(string_input);
  Serial.println("Input printed.");

  int inputlen = string_input.length();
  output_1 = string_input[0];

    for ( int i = 1; i < inputlen; i++ ) {
      output_2 += string_input[i];
    }

      if ( output_2.toInt()<=0 && inputlen>0 ){   // check if there's an error 

        Serial.println("Error with input number");
        delay(5000);
        Serial.println("Reading the input string");
        Serial.println(Serial.readString());
        Serial.println("Done reading the input string");
        }

    if (output_1 == "s") {

      *newstep = output_2.toInt();

    }

    else if (output_1 == "t") {

      *newtrigger = output_2.toInt();
    }

  }
  • Edits must not change literal details of command codes which the program is looking for; also, editing just to insert a comma or optional definite article is merely a waste of everyone's time and attention. – Chris Stratton Sep 18 '16 at 5:35
1

I can see several issues:

  • If the Serial buffer contains more than one command already, you'll read it too. For example serial buffer contains "s43;t25;" and the input_string would be something like "s43t25". This is highly to happen if you send those characters in less than 3seconds (as you have delay(500) for each appended character). You have to stop reading from buffer if you detect ';'.

  • Parsing of commands is also pretty weird. You are blocking for some time, so you can detect 's'/'t' and then use Serial.parseInt(); with Serial.setTimeout(1000); to do similar but much faster get command.

  • Variables set inside of ISR (function trigger is called from ISR) must be volatile. Otherwise it might be optimized out or into register by compiler.

Anyway, if you want to read whole commands try the serialEvent() example. Just change checking for '\n' to ';' and then you can parse that command in your way when it's complete.

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.