Go Down

Topic: My Servo won't move [SOLVED] (Read 2428 times) previous topic - next topic

InventiousTech

Nov 14, 2012, 02:41 am Last Edit: Nov 14, 2012, 09:03 pm by InventiousTech Reason: 1
I have a program that receives data over Serial1 of the mega 2560. The data is a series of bytes that represent a number in english from about -10 to 10, followed by an 'E'. anyway, what this is supposed to do is map the number to 0 to 179 for the servo, and write it to the motor. The problem is that after initially moving the servo to 90, nothing happens to the servo. I know from the Serial output that the values are being manipulated correctly, so it is definitely a problem with the implementation of Servo. The hardware is right because the servo sweep example works. Any ideas? Also, if anyone knows an easier way to cast from a character array to a float, that would be much appreciated.

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

char byteIn;
char numberChar[6];
int sVal;
int x;
int y;
float number = 0.000;
Servo myservo;

void setup() {
 Serial1.begin(9600);       // start serial communication at 9600bps
 Serial.begin(9600);
 myservo.attach(9);
 myservo.write(90);
}

void loop()
{
 if (Serial1.available())
 {
   byteIn = Serial1.read();
   if (byteIn == 'E')
   {
    x = 0;
    y = 0;
    if (numberChar[0]=='-')\
    {
     y = 1;
    }
    number = numberChar[0+y]-'0';
    number += ((numberChar[2+y]-'0')/10.0);
    number += ((numberChar[3+y]-'0')/100.0);
    number += ((numberChar[4+y]-'0')/1000.0);
    if (numberChar[0]=='-')\
    {
     number = number*-1;
    }
    sVal = (int)map(number, -10, 10, 0, 179);
    myservo.write(sVal);
    Serial.println(number);
    Serial.println(sVal);
    delay(10);
   }
   else
   {
    numberChar[x] = byteIn;
    x++;
   }
 }
}

PeterH

Those Serial print statements are rather anonymous so it'd be easy to be mistaken about which value is which. I suggest you prefix each output with the name of the value you're printing. If you still think the number processing part is correct, then post the input and output from running the sketch and describe what the servo does.
I only provide help via the forum - please do not contact me for private consultancy.

InventiousTech

Wow, that was fast. Ok. how about this:

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

char byteIn;
char numberChar[6];
int sVal;
int x;
int y;
float number = 0.000;
Servo myservo;

void setup() {
  Serial1.begin(9600);       // start serial communication at 9600bps
  Serial.begin(9600);
  myservo.attach(9);
  myservo.write(90);
}

void loop()
{
  if (Serial1.available())
  {
    byteIn = Serial1.read();
    if (byteIn == 'E')
    {
     x = 0;
     y = 0;
     if (numberChar[0]=='-')\
     {
      y = 1;
     }
     number = numberChar[0+y]-'0';
     number += ((numberChar[2+y]-'0')/10.0);
     number += ((numberChar[3+y]-'0')/100.0);
     number += ((numberChar[4+y]-'0')/1000.0);
     if (numberChar[0]=='-')\
     {
      number = number*-1;
     }
     sVal = (int)map(number, -10, 10, 0, 179);
     myservo.write(sVal);
     Serial.print("Raw value: ");
     Serial.println(number);
     Serial.print("Servo angle: ");
     Serial.println(sVal);
     Serial.println();
     delay(10);
    }
    else
    {
     numberChar[x] = byteIn;
     x++;
    }
  }
}


The input is actually coming from a python script running on scripting layer for android (SL4A) over bluetooth through a JY-MCU module to the Serial1 input, so it's a little hard to tell you exactly what is coming in, given that the data goes through a couple layers of android data manipulation then the bluetooth module, but I can tell you with reasonable certainty that the value coming in (for this example) is "5.057" as a series of bytes through Serial1. The output is

Raw value: 5.06
Servo angle: 134


So yes, I am pretty sure the data is right. The servo essentially does nothing. Hence the problem, since it started at 90 degrees and should be at 134.

AWOL

Can I introduce you to a good friend of mine?

How is the servo connected and powered?
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

PaulS

Code: [Select]
     number = numberChar[0+y]-'0';
     number += ((numberChar[2+y]-'0')/10.0);
     number += ((numberChar[3+y]-'0')/100.0);
     number += ((numberChar[4+y]-'0')/1000.0);

0, 2, 3, 4? Are you missing a finger?

AWOL

No, he's missing the point   ;)
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

InventiousTech

Lol, yes I am missing the point.  ;)
As to the servo, the white is connected to pin 9, the red is on VIN (Straight to the USB cable powering the device), and the black is obviously ground. Servos usually don't draw more than 50 mA, or so I have read, and USB can supply up to 500mA, so I think power is fine. What makes me think the wiring is good is that the "sweep" example works fine. I am at rather a loss here, not even getting any errors. I tried myservo.writeMicroseconds, mapping the data between 1000 and 2000, but that didn't work either.

PaulS

Quote
Servos usually don't draw more than 50 mA

Bullpoop. Servos can pull up to an amp under load.

If your servo works with the sweep example, then the problem isn't with the servo or the wiring. It is with the input that you are sending it, or the way you are processing that input.

What are you sending the Arduino? From what?


fungus

What happens if you set the servo to 0 degrees in setup?
No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

InventiousTech

Paul, yes, but this servo is not under load, as I am just testing it. As to the input, my thoughts exactly. Read my first two posts to see what the input is.
If I set it to 0, then it goes to 0 and stays there for the duration of the program. Currently it goes to 90 and stays there.

PaulS

Quote
Read my first two posts to see what the input is.

You've explained what you think they are, not what they actually are, or where the input is coming from. Let's start with some really simple questions, one at a time.

Are you using the Serial Monitor to send data to the Arduino?

InventiousTech

Au contraire, mon ami. I have explained exactly where the data is coming from. It originates in an android phone, it is sent by a python script to the JY-MCU bluetooth module connected to the Serial1 input of the Arduino Mega 2560. The data received by the bluetooth chip is sent to the arduino, fed into a character array until the program hits the end character 'E', then it converts the character array to a floating point number, maps it to the servo's range of 0 to 179, and sends it to the servo via myservo.write(sVal). The data is sent to the computer via Serial both before and after mapping and appears to be correct. Another possibly related issue is that I have the program set up to go to the thousandths place on the float value, but I appear to only be getting hundredths. For a specific example, refer to my second post.

PaulS

The reason for the questions about the source of the data are because you are assuming that EVERY character read from the serial port is useful, and goes in a specific spot. If the sender is tacking a carriage return/line feed after the E, that will screw up the next iteration, since the carriage return and line feed are going where you expect the ones digit and the decimal point.

Quote
but I appear to only be getting hundredths.

Getting? Or printing?

InventiousTech

#13
Nov 14, 2012, 02:10 pm Last Edit: Nov 14, 2012, 02:15 pm by InventiousTech Reason: 1
Yes, I see your point, but no there is no carriage return at the end of transmission. If I create a program that just  relays information from one serial to another, I just get a long string of numbers separated by 'E's. Also, I know that's not the case because the data being printed to the computer would also be screwed up, but it's not. About the precision, I am wondering what would cause there to be a difference between calculating hundredths and printing hundredths. By the way, thanks for the help so far.
Just for clarity, here is the python script on the phone:

Code: [Select]
import android, time

BT_DEVICE_ID = '00:12:09:13:97:48'

droid = android.Android()
droid.bluetoothConnect('00001101-0000-1000-8000-00805F9B34FB', BT_DEVICE_ID)
x = 0
while x<100:
droid.startSensingTimed(1, 25)
time.sleep(0.1)
s4 = droid.sensorsReadAccelerometer().result
droid.stopSensing()
ret = round(s4[1], 3)
droid.bluetoothWrite(str(ret)+"E")
print(ret)
x += 1

exit()

AWOL

Quote
, I am wondering what would cause there to be a difference between calculating hundredths and printing hundredths.

The default two places of decimals for the "print" method?
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Go Up