[solved]Controlling Servos Using Serial
hi,
i'm trying control servo motors using bluetooth(serial), have come across issue has had me baffled hours.
i using app called bluetooth electronics keuwl, , long story short, arduino receives sequence of bytes of following format on serial port: @bx111,y111b! ,where @ start byte, b method of telling packet contains data regarding servos, , numbers represent angle of x , y servos. ! end byte. explain why b there in moment.
on plain sight easy implement, since know if save packet byte array bytes[], bytes[3] bytes[5] numbers angle of x servo, , bytes[8] bytes[10] numbers y servo. , need subtract '0' following bytes(to convert them ascii decimal, since '0' in ascii 48 in decimal) , multiply them power of 10 before summing them convert value decimal format.
for example, input @bx111,y111b! angle x servo in decimal be:
however, problem placeholders aren't used, in no preceding 0's sent. example app sends @bx11,y111b! , not @bx011,y111b!
here's code have come far, works inputs not others. instance, if transmitted x value has 3 digits received value becomes 0. left comment in code highlighting think problem is. current approach inspired following post(look @ code state machine):
http://www.gammon.com.au/forum/?id=11425
the packet receive protocol taken following post:
https://forum.arduino.cc/index.php?topic=225329.0
coming why b in sequence, purpose tell code there no more number bits since using isdigit() function. (can't use end byte removed sequence after decoding).
thank bearing me, , appreciate spending time , effort .
i'm trying control servo motors using bluetooth(serial), have come across issue has had me baffled hours.
i using app called bluetooth electronics keuwl, , long story short, arduino receives sequence of bytes of following format on serial port: @bx111,y111b! ,where @ start byte, b method of telling packet contains data regarding servos, , numbers represent angle of x , y servos. ! end byte. explain why b there in moment.
on plain sight easy implement, since know if save packet byte array bytes[], bytes[3] bytes[5] numbers angle of x servo, , bytes[8] bytes[10] numbers y servo. , need subtract '0' following bytes(to convert them ascii decimal, since '0' in ascii 48 in decimal) , multiply them power of 10 before summing them convert value decimal format.
for example, input @bx111,y111b! angle x servo in decimal be:
code: [select]
x=(bytes[3]-'0')*100+(bytes[4]-'0')*10+(bytes[5]-'0');
however, problem placeholders aren't used, in no preceding 0's sent. example app sends @bx11,y111b! , not @bx011,y111b!
here's code have come far, works inputs not others. instance, if transmitted x value has 3 digits received value becomes 0. left comment in code highlighting think problem is. current approach inspired following post(look @ code state machine):
http://www.gammon.com.au/forum/?id=11425
the packet receive protocol taken following post:
https://forum.arduino.cc/index.php?topic=225329.0
coming why b in sequence, purpose tell code there no more number bits since using isdigit() function. (can't use end byte removed sequence after decoding).
code: [select]
#include <servo.h>
#define motora1 3 // pin 2 of l293
#define motora2 5 // pin 7 of l293
#define motorb1 6 // pin 10 of l293
#define motorb2 9 // pin 14 of l293
#define startmarker '@'
#define endmarker '!'
#define specialbyte 253
#define maxmessage 16
#define baseservopin 4
#define shoulderservopin 7
servo baseservo,shoulderservo;
int btin=0;
int maxspeed=0;
byte data[maxmessage];
byte tempbuffer[maxmessage];
byte bytesrecvd = 0;
byte datarecvcount = 0;
boolean inprogress = false;
boolean allreceived = false;
void setup() {
pinmode(motora1, output);
pinmode(motora2, output);
pinmode(motorb1, output);
pinmode(motorb2, output);
serial.begin(9600);
baseservo.attach(baseservopin);
shoulderservo.attach(shoulderservopin);
}
void loop() {
/* if(serial.available()>0){
btin=serial.read();
getserialdata();
switch(btin){
case'l':
analogwrite(motora1, maxspeed);
digitalwrite(motora2, 0);
break;
case'm':
analogwrite(motora2, maxspeed);
digitalwrite(motora1, 0);
break;
case'r':
analogwrite(motorb1, maxspeed);
digitalwrite(motorb2, 0);
break;
case'n':
analogwrite(motorb2, maxspeed);
digitalwrite(motorb1, 0);
break;
case's':
digitalwrite(motora2,0);
digitalwrite(motora1, 0);
break;
case't':
digitalwrite(motorb2,0);
digitalwrite(motorb1, 0);
break;
case's':
maxspeed=serial.parseint();
if(serial.read()=='s'){break;}
}
}*/
getserialdata();
processdata();
}
void processdata() {
// processes data in data[]
byte n,m;
byte anglex=0,angley=0;
if (allreceived) {
if(data[0]=='b'){
//this crucial part of code(well think)
for(n=2;n<5;n++){
if(isdigit(data[n])){
anglex *=10;
anglex +=data[n]-'0';
}
else{
n +=2;
break;
}
}
//serial.println(n);
for(m=n;m<(n+3);m++){
if(isdigit(data[m])){
angley *=10;
angley +=data[m]-'0';
}
else{
break;
}
}
//serial.println(anglex);
// serial.println(angley);
baseservo.write(anglex);
shoulderservo.write(angley);
allreceived = false;
}
}
}
void getserialdata() {
// receives data tempbuffer[]
// saves number of bytes pc said sent - in tempbuffer[1]
// uses decodehighbytes() copy data tempbuffer data[]
// arduino program use data finds in data[]
if(serial.available() > 0) {
byte x =serial.read();
if (x == startmarker) {
byte x = startmarker;
bytesrecvd = 0;
inprogress = true;
// blinkled(2);
// debugtopc("start received");
}
if(inprogress) {
tempbuffer[bytesrecvd] = x;
bytesrecvd ++;
}
if (x == endmarker) {
inprogress = false;
allreceived = true;
// save number of bytes sent
// datasentnum = tempbuffer[1];
decodehighbytes();
}
}
}
void decodehighbytes() {
// copies data[] data bytes i.e. excluding marker bytes , count byte
// and converts bytes of 253 etc intended numbers
// note bytesrecvd total of bytes including markers
datarecvcount = 0;
for (byte n = 1; n < bytesrecvd - 1 ; n++) { // 2 skips start marker , count byte, -1 omits end marker
byte x = tempbuffer[n];
if (x == specialbyte) {
// debugtopc("foundspecialbyte");
n++;
x = x + tempbuffer[n];
}
data[datarecvcount] = x;
datarecvcount ++;
}
}
void blinkled(byte numblinks) {
for (byte n = 0; n < numblinks; n ++) {
digitalwrite(13, high);
delay(200);
digitalwrite(13, low);
delay(200);
}
}
thank bearing me, , appreciate spending time , effort .
quote
however, problem placeholders aren't used, in no preceding 0's sent. example app sends @bx11,y111b! , not @bx011,y111b!that not problem. data of interest between x , comma , between y , b. find x, comma, y, , b, , you'll know data of interest is.
or, make app send data way want.
code: [select]
void loop() {
/* if(serial.available()>0){
btin=serial.read();
getserialdata();
switch(btin){
case'l':
analogwrite(motora1, maxspeed);
digitalwrite(motora2, 0);
break;
case'm':
analogwrite(motora2, maxspeed);
digitalwrite(motora1, 0);
break;
case'r':
analogwrite(motorb1, maxspeed);
digitalwrite(motorb2, 0);
break;
case'n':
analogwrite(motorb2, maxspeed);
digitalwrite(motorb1, 0);
break;
case's':
digitalwrite(motora2,0);
digitalwrite(motora1, 0);
break;
case't':
digitalwrite(motorb2,0);
digitalwrite(motorb1, 0);
break;
case's':
maxspeed=serial.parseint();
if(serial.read()=='s'){break;}
}
}*/
i thought putting line said "do not bother reading this", several dozen lines of irrelevant rambling, , line said "resume reading here". but, got on it. see didn't.
code: [select]
for(n=2;n<5;n++){
you should not assume 2 , 5 correct values.
code: [select]
byte x =serial.read();
if (x == startmarker) {
byte x = startmarker;
bytesrecvd = 0;
inprogress = true;
// blinkled(2);
// debugtopc("start received");
}
if value read serial port start marker, create variable same name, , assign value. then, never use variable. i'll bite. why doing that?
code: [select]
if(inprogress) {
tempbuffer[bytesrecvd] = x;
bytesrecvd ++;
}
store character in array containing useful data.
code: [select]
if (x == endmarker) {
then, see if idea. hmmm...
Arduino Forum > Using Arduino > Networking, Protocols, and Devices (Moderator: fabioc84) > [solved]Controlling Servos Using Serial
arduino
Comments
Post a Comment