[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:

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

Popular posts from this blog

DHT11 Time out error using v0.4.1library

Sketch upload fails with Java error (___REMOVE___/bin/avrdude)!

Arduino Uno + KTY81/210 temperature sensor