I'm so helpless in my topic. I want to control 3 servos (0-180°) via Bluetooth on an Android mobile. I already get 1 servo worked fine. The Android App works also fine. So the Problem is the Arduino-Code.
Problem with 3 Servos: I need an extra byte, char or int to tell arduino which servo should be controlled. I tried so much ways, but no one worked really fine.
way:
Send a control Byte (1;2;3;) and after that, sending the servo-position as a Byte. Well, this worked a little bit, but the servo motor does strange things.
Code:
#include <Servo.h>
byte valueByte;
int value, servo;
Servo servoeins, servozwei, servodrei; // declare Servo
void setup()
{
pinMode(servo = 8, OUTPUT); // pin 13 (on-board LED) as OUTPUT
pinMode(servo = 9, OUTPUT);
pinMode(servo = 10, OUTPUT);
servoeins.attach(8); // initialize servo to pin 8
servozwei.attach(9);
servodrei.attach(10);
Serial.begin(9600); // start serial communication at 9600bps
}
void loop() {
if(Serial.available()){ // if data is available to read
byte command = Serial.read(); //store 1.st Byte as command
switch(command){
valueByte = Serial.read(); //store 2.nd Byte as value
value = (int) valueByte; //cast ValueByte into Integer
case 1:
servoeins.write(value); //start Servo with integer value
delay(10);
case 2:
servozwei.write(value);
delay(10);
case 3:
servodrei.write(value);
delay(10);
}
}
}
way:
Send a 2 Byte message to Arduino, containing a number till 543. So the Arduino checks the value, and sees which servo he shall control. 0...180 he controls servo1, 181...361 he controls servo2, 362...542 he controls servo3. Thats the point why i use a 2Byte message.
But how can I receive a 2 Byte Message? I tried so many ways (googled examples etc..) but none worked for me.
Does anyone of you guys have a working idea? Im pretty sure that it will work anyway, but how?
Thanks a lot!
P.S. Im workin with App Inventor 2. I can choose between 1-Byte-Number, 2-Byte-Number oder 4-Byte-Number.
There is no point in assigning a value to servo there. Stop that crap.
if(Serial.available()){ // if data is available to read
byte command = Serial.read(); //store 1.st Byte as command
switch(command){
valueByte = Serial.read(); //store 2.nd Byte as value
Serial.available() returns the number of bytes available to be read, not true or false.
If it says that there is one byte, it is NOT okay to read two.
NOTHING follows a switch statement except cases.
Failing to omit the break statement from a case is a classic mistake.
What is the phone sending? ASCII data or binary data?
Get the bluetooth device off the hardware serial port so you can debug your program. Debug by guess is the worst possible way.
Does anyone of you guys have a working idea? Im pretty sure that it will work anyway, but how?
I don't know if this will fit your situation, but below is dome multiservo control code. The code provides for a servo position code, a servo identifier, and an end of data packet marker.
//zoomkat 11-22-12 simple delimited ',' string parse
//from serial port input (via serial monitor)
//and print result out serial port
//multi servos added
// Powering a servo from the arduino usually *DOES NOT WORK*.
String readString;
#include <Servo.h>
Servo myservoa, myservob, myservoc, myservod; // create servo object to control a servo
void setup() {
Serial.begin(9600);
//myservoa.writeMicroseconds(1500); //set initial servo position if desired
myservoa.attach(6); //the pin for the servoa control
myservob.attach(7); //the pin for the servob control
myservoc.attach(8); //the pin for the servoc control
myservod.attach(9); //the pin for the servod control
Serial.println("multi-servo-delimit-test-dual-input-11-22-12"); // so I can keep track of what is loaded
}
void loop() {
//expect single strings like 700a, or 1500c, or 2000d,
//or like 30c, or 90a, or 180d,
//or combined like 30c,180b,70a,120d,
if (Serial.available()) {
char c = Serial.read(); //gets one byte from serial buffer
if (c == ',') {
if (readString.length() >1) {
Serial.println(readString); //prints string to serial port out
int n = readString.toInt(); //convert readString into a number
// auto select appropriate value, copied from someone elses code.
if(n >= 500)
{
Serial.print("writing Microseconds: ");
Serial.println(n);
if(readString.indexOf('a') >0) myservoa.writeMicroseconds(n);
if(readString.indexOf('b') >0) myservob.writeMicroseconds(n);
if(readString.indexOf('c') >0) myservoc.writeMicroseconds(n);
if(readString.indexOf('d') >0) myservod.writeMicroseconds(n);
}
else
{
Serial.print("writing Angle: ");
Serial.println(n);
if(readString.indexOf('a') >0) myservoa.write(n);
if(readString.indexOf('b') >0) myservob.write(n);
if(readString.indexOf('c') >0) myservoc.write(n);
if(readString.indexOf('d') >0) myservod.write(n);
}
readString=""; //clears variable for new input
}
}
else {
readString += c; //makes the string readString
}
}
}
zoomkat you gave me the right input! Now my code works fine. I changed the code to my values and everything is fine. Thank you very much!
Here is the compelte code:
#include <Servo.h>
int value; // declare an integer named 'value'
Servo servoeins, servozwei, servodrei; // declare servo1, servo2, servo3
String readString; // declare a String named 'readString'
void setup() // Setup Code
{
pinMode(8, OUTPUT); // initialize pin 8 as Output
pinMode(9, OUTPUT); // initialize pin 9 as Output
pinMode(10, OUTPUT); // initialize pin 10 as Output
servoeins.attach(8); // initialize servo1 to pin 8
servozwei.attach(9); // initialize servo2 to pin 9
servodrei.attach(10); // initialize servo3 to pin 10
Serial.begin(9600); // start serial communication at 9600bps
}
void loop() { // expects Data like "0a," "180b," or "270c,"
if(Serial.available()){ // if data is available to read
char c = Serial.read(); // stores 1.st byte from sent data
if (c == ','){ // check if its a ',' - so data comes from mobile
if (readString.length()>1){ // check if the data is valid
value = readString.toInt(); // convert the received String to a Number (skips alphabetics)
if(readString.indexOf('a')>0){ // check if data is according to servo1
servoeins.write(value); // start Servo with received value
delay(10);} // time for arduino to control servo to value position
if(readString.indexOf('b')>0){ // check if data is according to servo2
servozwei.write(value); // start Servo with received value
delay(10);} // time for arduino to control servo to value position
if(readString.indexOf('c')>0){ // check if data is according to servo3
servodrei.write(value); // start Servo with received value
delay(10);} // time for arduino to control servo to value position
readString=""; // clears String for new input
}
}
else{
readString += c;} // makes the String readString
}
}
Is there a possibility to optimize this process, so the latence gets lower? I think the delay for the servos a low enough, or?
Mhmm.. yeah i tried using functions like 'ReadyBytes' but it doesnt work. With 'readBytes' it should be also possible i think?
Is there an example, how to use it?
So i could send a 1-Byte-Number to choose the servo, and after that, the value shall be sent with an 1-Byte-Number.