Varible splitting....aaarghhhh, help please?

Hi all,

Got a wierd one here, not sure if its somthing stupid...but here goes..

got a 4 digit number coming onto the serial port (by design)

This ranges from 0 - 5000

when this number comes in, i need to split this up..

like follows...

variable 'value' = 2345 (number arrived on port could be any number up to as above)

this then gets split into a=2 b=3 c=4 d=5 these variables are then passed to another process everytime a new 'value' appears on the port.

i can insert the variables into the next process with no issues, but cant figure out how to split it up...

The other problem could be (me thinks..) is that when we have say '123' on the port 'a' needs to be 0 so that would be a=0 b=1 c=2 d=3...
anyone got any clues how to get through this?

regards,

Mike

Assuming the four digit number is the ASCII representation of a four digit number?

So '2345' is received as four bytes 0x32 0x33 0x34 0x35 ?

Or are you receiving a 16 bit binary value?

Can you post your sketch, please?

Hi, thanks for jumping in..

yes teh number is an ascii rep...as integer 0-5000

here is the relavent code..

//softserial rxtx
 
 int a = 00;  
 int b = 00;
 int c = 00;
 int d = 00;
 int zp = 0;
// process a command string
void HandleCommand(char* input, int length)
{
  Serial.println(input);
  if (length < 2) { // not a valid command
    return;
  }
  int value = 0;
  // calculate number following command
  if (length > 2) {
    value = atoi(&input[2]);
  }
  int* command = (int*)input;
  
  
    
  // check commands
  // note that the two bytes are swapped, ie 'RA' means command AR
  switch(*command) {

case 'PZ':


      // action  ZOOM Position 
   CAMCOM.print(129, BYTE);   // 81
   CAMCOM.print(01, BYTE);   // 01
   CAMCOM.print(04, BYTE);   // 04
   CAMCOM.print(71, BYTE);   // 47
   CAMCOM.print(a, BYTE);   // 0a
  CAMCOM.print(b, BYTE);   // 0b
  CAMCOM.print(c, BYTE);   // 0c
   CAMCOM.print(d, BYTE);   // 0d
   CAMCOM.println(255, BYTE);   // FF
   // 81 04 01 47 0a 0b 0c 0d FF
     
      Serial.println("ZOOM Position");
Serial.println(zp);
      break;
void loop()
{
  // get a command string from the serial port
  int inputLength = 0;
  do {
    while (!Serial.available()); // wait for input
    inputBuffer[inputLength] = Serial.read(); // read it in
  }
  while (inputBuffer[inputLength] != LineEnd && ++inputLength < BufferLength);
  inputBuffer[inputLength] = 0; //  add null terminator
  HandleCommand(inputBuffer, inputLength);

so the serial reader deos its bit and gives us a variable called value..

this is then split into a,b,c,d then inserted in the case switch.

make any sence.

regards,

Mike.

Here's one way:

loop()
{
    int a, b, c, d;

    ....
    split_digits(input_str,&a,&b,&c,&d);
}

void
split_digits(char *str,int *a,int *b,int *c,int *d)
{
    int val;

    val = atoi(str);
    *a = val / 1000;
    *b = (val / 100) % 10;
    *c = (val / 10) % 10;
    *d = val % 10;
}

-Mike

HI mfm,
Thanks..

so drop the loop into viod loop in main program, and drop the spli_digi into the case?

sorry very new and learning fast....
regards,

Mike.

Sorry mike, Tried this every which way, need a little more info on implamiting it.

regards,

Mike.

Dr. Mike,

Sorry, I should have been more explicit.

Step 1: Add the split_digits function to your sketch and get it to compile. You could, for example, add it to the end of your sketch. I would add it without worrying about calling it, and see if your sketch still compiles without errors.

Step 2: Move the 'int a = 00;', 'int b = 00', etc., from the top of your sketch to the HandleCommand function. You can also remove the 'length' from the call to the HandleCommand function.

The call to HandleCommand from loop() would be:

HandleCommand(inputBuffer);

Now, change the beginning of HandleCommand to look like this:

void HandleCommand(char *input)
{
  int a;
  int b;
  int c;
  int d;

  Serial.println(input);
  split_digits(input,&a,&b,&c,&d);
  /* now do commands based on a, b, c & d */
}

I don't understand what your case statement is trying to do, but I hope that with the number split into the four variables, it will be easy for you to finish the rest of HandleCommand. That's if I've understood your question correctly :slight_smile:

Regards,

-Mike

Hi Mike, and once again thanks for helping with this...but i must have something A**E about face here..

here is the complete code...

What happens is that when the command is read it passes to a case ZP in this example and then passes a,b,c,d to the missing variables so that softserial outputs the right code for the control..

//    S120#   servo 1 to position 20 degrees

#include <ctype.h>
#include <Servo.h>
#include <SoftwareSerial.h>

//softserial setup

#define rxPin 8
#define txPin 7
SoftwareSerial CAMCOM=SoftwareSerial(rxPin,txPin);


//main serial in
#define SerialSpeed 57000
#define BufferLength 16
#define LineEnd '#'
#define PinServo1 2
#define PinServo2 3
#define PinServo3 4
#define DefaultServoPosition 90

//servo setup
Servo servo1;
Servo servo2;
Servo servo3;
char inputBuffer[BufferLength];
//softserial rxtx


int zp = 0;


void setup()
{
  //softserial setup

//split_digits(input_str,&a,&b,&c,&d);


    pinMode(rxPin,INPUT);
  pinMode(txPin,OUTPUT);


  // servo pins outputs
  pinMode(PinServo1, OUTPUT);
  pinMode(PinServo2, OUTPUT);
  pinMode(PinServo3, OUTPUT);
  // attach servos and set servo-specific timing details
  servo1.attach(PinServo1, 900, 2100); // Azimuth servo
  servo2.attach(PinServo2, 900, 2100); // Elevation servo
  servo3.attach(PinServo3, 900, 2100); // back up servo
  // default servo positions
  servo1.write(DefaultServoPosition);
  servo2.write(DefaultServoPosition);
  servo3.write(DefaultServoPosition);

  Serial.begin(SerialSpeed);
  CAMCOM.begin(9600);
}

// process a command string
void HandleCommand(char *input)
{
  int a;
  int b;
  int c;
  int d;

  Serial.println(input);
  split_digits(input,&a,&b,&c,&d);
  /* now do commands based on a, b, c & d */
}


{
  Serial.println(input);
  if (length < 2) { // not a valid command
    return;
  }
  int value = 0;
  // calculate number following command
  if (length > 2) {
    value = atoi(&input[2]);
  }
  int* command = (int*)input;



  // check commands
  // note that the two bytes are swapped, ie 'RA' means command AR
  switch(*command) {
  case '1S':
 
  case 'PZ':


    // action  ZOOM Position 
    CAMCOM.print(129, BYTE);   // 81
    CAMCOM.print(01, BYTE);   // 01
    CAMCOM.print(04, BYTE);   // 04
    CAMCOM.print(71, BYTE);   // 47
    CAMCOM.print(a, BYTE);   // 0a
    CAMCOM.print(b, BYTE);   // 0b
    CAMCOM.print(c, BYTE);   // 0c
    CAMCOM.print(d, BYTE);   // 0d
    CAMCOM.println(255, BYTE);   // FF
    // 81 04 01 47 0a 0b 0c 0d FF

    Serial.println("Position");
    
    break;


  }
}

void loop()
{
  // get a command string from the serial port
  int inputLength = 0;
  do {
    while (!Serial.available()); // wait for input
    inputBuffer[inputLength] = Serial.read(); // read it in
  }
  while (inputBuffer[inputLength] != LineEnd && ++inputLength < BufferLength);
  inputBuffer[inputLength] = 0; //  add null terminator
  HandleCommand(inputBuffer, inputLength);

  //soft serial output


  int a, b, c, d;


  

}

the rest of the commands are simple like S1150# which is servo 1 position 150 (0-180 deg)

any of this make any sence?

thanks again.....still fighting with it...

regards,

Mike.

OK..with more playing......i have got i compiling....

here is the code.... is this right?

regards.

Mike.

//    S120#   servo 1 to position 20 degrees

#include <ctype.h>
#include <Servo.h>
#include <SoftwareSerial.h>


//softserial setup

#define rxPin 8
#define txPin 7
#define split_digits
SoftwareSerial CAMCOM=SoftwareSerial(rxPin,txPin);


//main serial in
#define SerialSpeed 57000
#define BufferLength 16
#define LineEnd '#'
#define PinServo1 2
#define PinServo2 3
#define PinServo3 4
#define DefaultServoPosition 90

//servo setup
Servo servo1;
Servo servo2;
Servo servo3;
char inputBuffer[BufferLength];
//softserial rxtx






void setup()
{
  //softserial setup


//split_digits(input_str,&a,&b,&c,&d);


    pinMode(rxPin,INPUT);
  pinMode(txPin,OUTPUT);


  // servo pins outputs
  pinMode(PinServo1, OUTPUT);
  pinMode(PinServo2, OUTPUT);
  pinMode(PinServo3, OUTPUT);
  // attach servos and set servo-specific timing details
  servo1.attach(PinServo1, 900, 2100); // Azimuth servo
  servo2.attach(PinServo2, 900, 2100); // Elevation servo
  servo3.attach(PinServo3, 900, 2100); // back up servo
  // default servo positions
  servo1.write(DefaultServoPosition);
  servo2.write(DefaultServoPosition);
  servo3.write(DefaultServoPosition);

  Serial.begin(SerialSpeed);
  CAMCOM.begin(9600);
}

// process a command string
void HandleCommand(char *input, int length)
{
  int a;
  int b;
  int c;
  int d;

  Serial.println(input);
  split_digits(input,&a,&b,&c,&d);
  /* now do commands based on a, b, c & d */

  Serial.println(input);
  if (length < 2) { // not a valid command
    return;
  }
  int value = 0;
  // calculate number following command
  if (length > 2) {
    value = atoi(&input[2]);
  }
  int* command = (int*)input;



  // check commands
  // note that the two bytes are swapped, ie 'RA' means command AR
  switch(*command) {
  

  case 'PZ':


    // action  ZOOM Position 
    CAMCOM.print(129, BYTE);   // 81
    CAMCOM.print(01, BYTE);   // 01
    CAMCOM.print(04, BYTE);   // 04
    CAMCOM.print(71, BYTE);   // 47
    CAMCOM.print(a, BYTE);   // 0a
    CAMCOM.print(b, BYTE);   // 0b
    CAMCOM.print(c, BYTE);   // 0c
    CAMCOM.print(d, BYTE);   // 0d
    CAMCOM.println(255, BYTE);   // FF
    // 81 04 01 47 0a 0b 0c 0d FF

    Serial.println(" Position");
   
    break;

default:
    Serial.println("unknown command");
    break;
  }
}

void loop()
{
  // get a command string from the serial port
  int inputLength = 0;
  do {
    while (!Serial.available()); // wait for input
    inputBuffer[inputLength] = Serial.read(); // read it in
  }
  while (inputBuffer[inputLength] != LineEnd && ++inputLength < BufferLength);
  inputBuffer[inputLength] = 0; //  add null terminator
  HandleCommand(inputBuffer, inputLength);

  //soft serial output


  int a, b, c, d;


  

}

Dr. Mike,

Sorry, I did not read your original code closely enough, so I didn't realize that there were letters before the digits.

Can you change the command format? The reason I'm asking is that it would be easier if there were always the same number of letters at the beginning of the command. I see that one command starts with 'ZP' and another starts with 'S'. Can you change this, or is it coming from a program you don't have control over?

-Mike