Go Down

Topic: A Problem Restarting A Loop, I Think. (Read 460 times) previous topic - next topic

Just_Rhys

Jul 12, 2018, 10:02 am Last Edit: Jul 12, 2018, 10:03 am by Just_Rhys
Hello all, I am trying to control a servo using the serial monitor. I want to input a rotational velocity (deg/s) and the motor will hit that within the positional constraints I set. Simple enough. And I have got it to do it once and stay at that velocity oscillating as I want. But I can't get the thing to change its speed again.


I want to be able to type various velocities into the serial monitor and have it change when there is a new input. I'm relatively new to code and very new to Arduino, I know I could achieve this with certain loops in certain places but for the life of me I can't work it out.

Here is my code so far:

Code: [Select]
#include <Servo.h>

Servo myservo;  // create servo object to control a servo
int pos = 0;    // variable to store the servo position
long val = 0; // New Speed
int input =0;
char incomingByte;

void setup() {
    Serial.begin(9600);
    Serial.println("Enter A New Velocity (deg/s)"); //Write instructions
    myservo.attach(9);     //Setting servo pin
}
void loop() {

    if(Serial.available()){ //Checks that there is data in the buffer?
      input = 0;

      while (1) {
      incomingByte = Serial.read();
      if (incomingByte == '\n') break; // exit the while(1), we're done receiving
      if (incomingByte == -1) continue; // if no characters are in the buffer read() returns -1

      input *=10; //shift left 1 decimal place
      input = ((incomingByte - 48)+input); //Converting ASCII to integer, add, and shift, left one decimal place
          }   
      Serial.print("New Speed:");
      Serial.print(input);
      Serial.println("(deg/s)");
    }

       while(input = input){

  for (pos = 0; pos <= 80; pos += input) { // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);             // waits 15ms for the servo to reach the position
  }

  for (pos = 80; pos >= 0; pos -= input) { // goes from 180 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
    }

}


I know the connection works as running basic servo code runs everything fine. I am using an Arduino Uno and the standard Tower Pro micro servo motor.

Thank you in advance.

teunman

First of all don't run a servo of just the arduino since this can damage the arduino.

Your comments seem to disagree with your code.
Where and how do you think you are setting the velocity of the servo?

wvmarle

The moment you have a Serial.available() you're going to get stuck in the while(1) loop until you receive a \n character. That's a pretty bad idea.

But after clearing that hurdle you're ending up stuck in the while(input = input) loop forever (no idea what you're really trying to there in the first place as the statement doesn't make sense).
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

Just_Rhys

I understand not to run servos on the Arduino but this is the starter kit servo and it's managed before so it should be fine but I will look into a better power supply later.

I think I am setting the velocity at the bottom where 'input' is the for loop condition. Once it gets there the other for loop takes it back and they go back and fourth, oscillating the servo.

Okay, I'll clear that hurdle and keep trying.

The while input = input loop was an attempt at having the loop run constantly but change when a new input is sent. I realise that probably isn't the best way to do it and it in fact does not do it but I can't think of another way to do it.

TomGeorge

Hi,
Can you post a schematic of how you have connected your project please?

Do you have a DMM to measure some voltages on your project?

Thanks.. Tom.. :)
Everything runs on smoke, let the smoke out, it stops running....

Just_Rhys

Dead easy connections, servo is connected to 5V port, the ground port and the 9 attachment port on the Arduino uno which is connected via USB to my laptop. No way to measure voltages on me I dont think, what are yout thinking I could do with that?


wvmarle

loop() will run constantly by itself.

To check for a change you need to store the old value in a separate variable, comparing something to itself is always correct.

Then you're not comparing, you're assigning. A = is assignment; a == is boolean comparison.

There's a "serial input basics" tutorial around here, look it up.

Don't wait for Serial input - grab characters as they come in, store them in a char array, then when you see your terminating \n you process that string (look at atoi() for easy conversion to int).

So for you the Serial input should look more like this (untested; may have typos):
Code: [Select]

char input[5]; // store values 0-9999.
byte index;
int speed;

void loop() {
  if (Serial.available()) {
    char c = Serial.read();
    if (c == '\n') {
      input[index] = 0; // null termination
      speed = atoi(input);
      index = 0;
    }
    else {
      input[index] = c;
      index++;
    }
  }
  // Servo code here - without while loops, loop() is doing that for you.
}


Some things left for you to add: input validation and making sure your buffer doesn't overrun.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

Just_Rhys

Very helpful thank you. I will look into and implement all of that soon and update on my progress.  :)

Just_Rhys

I still can't get it to work even trying to use your adaption. Below is the code that I am trying to use now except now it isn't even oscillating for any, even the first, input. I have no idea where it's going wrong.

Code: [Select]
#include <Servo.h>

Servo myservo;  // create servo object to control a servo
int pos = 0;    // variable to store the servo position
long val = 0; // New Speed
byte index;
char input [3];
char incomingByte;

void setup() {
    Serial.begin(9600);
    Serial.println("Enter A New Velocity (deg/s)"); //Write instructions
    myservo.attach(9);     //Setting servo pin
}
void loop() {

    if(Serial.available()){ //Checks that there is data in the buffer?
      incomingByte = Serial.read();
      if (incomingByte == '\n');{ // If we hit enter
      val = atoi(input);
      input[index] = 0;}
    }else {
        input[index] = incomingByte;
        index++;}
     
      Serial.print("Input Speed:");
      Serial.print(val);
      Serial.println(); //Giving Space
     
  for (pos = 0; pos <= 80; pos += val) { // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);             // waits 15ms for the servo to reach the position
  }
  for (pos = 80; pos >= 0; pos -= val) { // goes from 180 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
    }


MorganS

index never gets set back to zero after recognizing the \n.

You set the last byte in the input to the null character AFTER trying to read the input number. Swap the order of those two lines. Otherwise if you entered "12" and the next entry is "3" then the array contains "32".

You never check if you exceed the bounds of the input[3] array. If you entered "123" then you will be writing to a memory location you don't own.

The prompt to enter a speed prints on every oscillation instead of just printing once each time a new number is entered.
"The problem is in the code you didn't post."

Just_Rhys

#10
Jul 12, 2018, 09:51 pm Last Edit: Jul 12, 2018, 09:52 pm by Just_Rhys
Okay, thank you, that made a lot of sense but I have changed those things around and I'm still not getting an output. And it doesn't like the nestled if statement within the other if statement. Gives an error that '}' is expected before 'else'.

Code: [Select]
#include <Servo.h>

Servo myservo;  // create servo object to control a servo
int pos = 0;    // variable to store the servo position
long val = 0; // New Speed
byte index;
char input [3];
char incomingByte;

void setup() {
    Serial.begin(9600);
    Serial.println("Enter A New Velocity (deg/s)"); //Write instructions
    myservo.attach(9);     //Setting servo pin
}
void loop() {

    if(Serial.available()){ //Checks that there is data in the buffer?
      incomingByte = Serial.read();
      if (incomingByte == '\n');{ // If we hit enter
      Serial.print("Input Speed:");
      Serial.println(); //Giving Space
      input[index] = 0;
      val = atoi(incomingByte);
      Serial.print(val);
    }    else {
        input[index] = incomingByte;
        index++;
    }
   
  for (pos = 0; pos <= 80; pos += val) { // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);             // waits 15ms for the servo to reach the position
  }
  for (pos = 80; pos >= 0; pos -= val) { // goes from 180 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
    }
}


Any more ideas?

MorganS

Use the control-T auto format feature in the IDE. It will help you find the missing }
"The problem is in the code you didn't post."

TolpuddleSartre

#12
Jul 12, 2018, 09:55 pm Last Edit: Jul 12, 2018, 09:55 pm by TolpuddleSartre
Code: [Select]
if (incomingByte == '\n');Whoops

No amount of ctrl-T is going to find that one.

Just_Rhys

The error still holds. The only thing I can think is that I'm missing some kind of protocol when putting an if … else statement within another if statement...

Code: [Select]
if (incomingByte == '\n');Whoops

No amount of ctrl-T is going to find that one.
Bloody hell :') Thanks for the catch there. I fixed that and still no output mind, hopefully there's another stupid thing like that maybe?

MorganS

Yes, because the lines below that if(); will not be indented as expected.
"The problem is in the code you didn't post."

Go Up