[Solved]Joystick remote

Hey, I’m hacking an old remote w/ an uno and a hc05 bluetooth module to control a uno w/ an hc06. I’m not sure on how to transfer the x and y joystick positions to the uno. I can get them to the uno in the car
but I don’t know how to separate them in the car. Here is my remote code:

int joyPin1 = 0;
int joyPin2 = 1;
int value1 = 0;
int value2 = 0;
int outcome1;
int outcome2;
void setup() {
  Serial.begin(9600);
}

int treatValue(int data) {
  return (data / 37) - 1;
}

void loop() {
  value1 = analogRead(joyPin1);

  outcome1 = treatValue(value1);

  delay(100);

  value2 = analogRead(joyPin2);

  outcome2 = treatValue(value2);

  delay(100);

  if (outcome1 < 0) {
    outcome1 = 0;
  }
  if (outcome2 < 0) {
    outcome2 = 0;
  }
  Serial.print(outcome1);
  Serial.print(outcome2);
}

and the robots code:

char serialRead;
int motorAVal;
int motorBVal;
void setup() {
  Serial.begin(9600);
}

void loop() {
  while (Serial.available() > 0) {
    serialRead = Serial.read();
    if (serialRead > 5) {
      motorAVal = serialRead;
    }
    else {
      motorBVal = serialRead;
    }
    delay(200);
  }
}

Please help.

but I don't know how to separate them in the car.

The values that you send are going to be between 0 and 26. Suppose that the first is 13 and the second is 8. What you are currently sending is "138". Now, knowing what you sent and what you got, you can see how to separate the values. But, what if you get 223? Is that 22 and 3 or 2 and 23?

I think you can see that you need to send some kind of delimiter between the values. It may be less obvious that you need to send one between packets, too.

So, like send x and then send y with a , in between? If so, then how would I separate them at the end?
Thank you for answering.

Have a look at the system that is used in the 3rd example in Serial Input Basics and the parse example.

…R

I can get them to the uno in the car but I don’t know how to separate them in the car.

The below servo command receiving code is setup for receiving a command packet with a numeric value, an identifier for the servo to be commanded, and an end of packet marker. Something similar may work for you.

//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
    }
  }
}

Robin2, I changed your code yet I don’t see how to get 2 values:

const byte numChars = 32;
char receivedChars[numChars];  // an array to store the received data
char rc;
boolean newData = false;
// I send code like this from the remote(no parentheses or x and y): (x)4,(y)7
void setup() {
  Serial.begin(9600);
  Serial.println("<Arduino is ready>");
}

void loop() {
  recvWithEndMarker();
  showNewData();
}

void recvWithEndMarker() {
  static byte ndx = 0;
  char endMarker = ',';

  // if (Serial.available() > 0) {
  while (Serial.available() > 0 && newData == false) {
    rc = Serial.read();

    if (rc != endMarker) {
      receivedChars[ndx] = rc;
      ndx++;
      if (ndx >= numChars) {
        ndx = numChars - 1;
      }
    }
    else {
      receivedChars[ndx] = '\0'; // terminate the string
      ndx = 0;
      newData = true;
    }
  }
}

void showNewData() {
  if (newData == true) {

    Serial.println(receivedChars);
    newData = false;
  }
}

// I send code like this from the remote

You can not send code to the Arduino from a remote anything. You can send DATA.

no parentheses or x and y

Then you do NOT have any start and end markers. Add them, or write your own damned parsing code with no clue where a packet starts and ends,

Ok, I will send DATA.
Is this ok: <10, 10>
Edit: or like this

Ok, I will send DATA.
Is this ok: <10, 10>

Below is the transmitting test code which sends the data in the format for the data receiving code I previously posted.

//zoomkat multi pot/servo test 3-23-13
//includes dead band for testing and limit servo hunting
//view output using the serial monitor

#include <Servo.h> 
Servo myservo1;  //declare servos
Servo myservo2;
Servo myservo3;
Servo myservo4;
Servo myservo5;

int potpin1 = 0;  //analog input pin A0
int potpin2 = 1;
int potpin3 = 2;
int potpin4 = 3;
int potpin5 = 4;

int newval1, oldval1;  //pot input values
int newval2, oldval2;
int newval3, oldval3;
int newval4, oldval4;
int newval5, oldval5;

void setup() 
{
  Serial.begin(9600);  
  myservo1.attach(2);  
  myservo2.attach(3);
  myservo3.attach(4);
  myservo4.attach(5);
  myservo5.attach(6);
  Serial.println("testing multi pot servo");  
}

void loop()
{ 
  newval1 = analogRead(potpin1);           
  newval1 = map(newval1, 0, 1023, 0, 179); 
  if (newval1 < (oldval1-2) || newval1 > (oldval1+2)){ //dead band 
    myservo1.write(newval1); //position the servo
    Serial.print(newval1); //print the new value for testing 
    Serial.print("a,");
    oldval1=newval1; //set the current old value
  }

  newval2 = analogRead(potpin2);
  newval2 = map(newval2, 0, 1023, 0, 179);
  if (newval2 < (oldval2-2) || newval2 > (oldval2+2)){  
    myservo2.write(newval2);
    Serial.print(newval2);
    Serial.print("b,");
    oldval2=newval2;
  }

  newval3 = analogRead(potpin3);           
  newval3 = map(newval3, 0, 1023, 0, 179); 
  if (newval1 < (oldval1-2) || newval3 > (oldval3+2)){  
    myservo1.write(newval3);
    Serial.print(newval3);
    Serial.print("c,");
    oldval3=newval3;
  }

  newval4 = analogRead(potpin4);           
  newval4 = map(newval4, 0, 1023, 0, 179); 
  if (newval1 < (oldval1-2) || newval4 > (oldval4+2)){  
    myservo1.write(newval4);
    Serial.print(newval4);
    Serial.print("d,");
    oldval4=newval4;
  }

  newval5 = analogRead(potpin5);           
  newval5 = map(newval5, 0, 1023, 0, 179); 
  if (newval1 < (oldval5-2) || newval5 > (oldval5+2)){  
    myservo1.write(newval5);
    Serial.print(newval5);
    Serial.print("e,");
    oldval5=newval5;
  } 
  delay(50);  //to slow loop for testing, adjust as needed
}

Is this ok: <10, 10>

Perfect. Just be sure to change the value of endMarker in the code to ‘>’.

Should I have a startMarker and midMarker? I'm trying Zoomkats code also.

Should I have a startMarker and midMarker?

I like having a startMarker. That tells you when to start storing data. The "midMarker" is a delimiter, between successive values in the packet. That comes into play when parsing the stored data.

What is parsing? Separating the data? If so, I really don’t now how to.
Here’s my code(i’m not done)

const byte numChars = 32;
char receivedChars[numChars];  // an array to store the received data
char rc;
boolean newData = false;

void setup() {
  Serial.begin(9600);
  Serial.println("<Arduino is ready>");
}

void loop() {
  recvWithEndMarker();
  showNewData();
}

void recvWithEndMarker() {
  static byte ndx = 0;
  char startMarker = '<';
  char midMarker = ',';
  char endMarker = '>';


  if (Serial.available() > 0) {
    while (Serial.available() > 0 && newData == false) {
      rc = Serial.read();
      if (rc == startMarker || rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars)
          ndx = numChars - 1;
      }
    }
    else {
      receivedChars[ndx] = '\0'; // terminate the string
      ndx = 0;
      newData = true;
    }
  }
}
}
void showNewData() {
  if (newData == true) {

    Serial.println(receivedChars);
    newData = false;
  }
}

Owensoo:
What is parsing? Separating the data? If so, I really don’t now how to.

If you send the data as <10, 10> (which works without making any change to my code) you can then use a variation of the code from the parse example to separate it into two values.

…R

Here is my remote code:

int joyPin1 = 0;
int joyPin2 = 1;
int value1 = 0;
int value2 = 0;
int outcome1;
int outcome2;
void setup() {
  Serial.begin(9600);
}

int treatValue(int data) {
  return (data / 37) - 1;
}

void loop() {
  value1 = analogRead(joyPin1);

  outcome1 = treatValue(value1);

  delay(20);

  value2 = analogRead(joyPin2);

  outcome2 = treatValue(value2);

  delay(20);

  if (outcome1 < 0) {
    outcome1 = 0;
  }
  if (outcome2 < 0) {
    outcome2 = 0;
  }
  Serial.print('<');
  Serial.print(outcome1);
  Serial.print(',');
  Serial.print(outcome2);
  Serial.print('>');
  //delay(200);
}

and Robin2 code:

// simple parse demo
char receivedChars[] = "This is a test, 1234, 45.3" ;

char messageFromPC[32] = {0};
int integerFromPC = 0;
float floatFromPC = 0.0;

char recvChar;
char endMarker = '>';
boolean newData = false;


void setup() {
 Serial.begin(9600);
 Serial.println("<Arduino is ready>");
 
 parseData();
 showParsedData();
}


void loop() {

}

 
void parseData() {

    // split the data into its parts
    
  char * strtokIndx; // this is used by strtok() as an index
  
  strtokIndx = strtok(receivedChars,",");      // get the first part - the string
  strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
  
  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  integerFromPC = atoi(strtokIndx);     // convert this part to an integer
  
  strtokIndx = strtok(NULL, ","); 
  floatFromPC = atof(strtokIndx);     // convert this part to a float

}


void showParsedData() {
 Serial.print("Message ");
 Serial.println(messageFromPC);
 Serial.print("Integer ");
 Serial.println(integerFromPC);
 Serial.print("Float ");
 Serial.println(floatFromPC);
}

But the serial monitor(the car) displays this:

Message This is a test
Integer 1234
Float 45.30
Do you know what the problem is?
Edit: Sorry, I didn’t look at the code thoroughly.

Edit: or like this

I’d skip using a start marker as it adds extra code development with little benefit. Putting the identifier character after the numeric value might simplify your code parsing.

Do you know what the problem is?

I don't see that there IS a problem. Robin2's code is parsing a fixed string, and doing it properly.

You need to replace the fixed string with the data read from the serial part, when the end of packet marker arrives.

Owensoo: Do you know what the problem is?

Yes.

My code is just a demonstration. It is not possible to write deminstration code to meet every specific requirement.

You need to join the serial receive code with the parse code. The common element is the array receivedChars[]

...R

Ok, like this?

const byte numChars = 32;
char receivedChars[numChars];  // an array to store the received data
char rc;
boolean newData = false;

void setup() {
  Serial.begin(9600);
  Serial.println("<Arduino is ready>");
}

void loop() {
  recvWithEndMarker();
  showNewData();
}

void recvWithEndMarker() {
  static byte ndx = 0;
  char startMarker = '<';
  char midMarker = ',';
  char endMarker = '>';


  if (Serial.available() > 0) {
    while (Serial.available() > 0 && newData == false) {
      rc = Serial.read();
      if (rc == startMarker || rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars)
          ndx = numChars - 1;
      }
    }
    else {
      receivedChars[ndx] = '\0'; // terminate the string
      ndx = 0;
      newData = true;
    }
  }
}
}
void showNewData() {
  if (newData == true) {

    Serial.println(receivedChars);
    newData = false;
  }
}

One more thing, if I send something like 2,5>
it returns this:
2
0
0
0
5
0
0
0
0
0
Do you know why?
Thanks alot.

You seem to be making very hard work out of what is essentially the business of copy and pasting two functions from the parse demo.

This works
I have marked the few new lines with // <-----
and I have left in old lines and just commented them out so you can relate the code to the demo

const byte numChars = 32;
char receivedChars[numChars];

int integerFromPC;  // <------------
int integerBFromPC;  // <------------

boolean newData = false;

void setup() {
    Serial.begin(9600);
    Serial.println("<Arduino is ready>");
}

void loop() {
    recvWithStartEndMarkers();
    if (newData == true) {  // <------------
        parseData();       // <------------
        showParsedData();  // <------------
        newData = false;  // <------------
    }
    //showNewData();
}

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

 // if (Serial.available() > 0) {
    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

void showNewData() {
    if (newData == true) {
        Serial.print("This just in ... ");
        Serial.println(receivedChars);
        newData = false;
    }
}

void parseData() {

    // split the data into its parts

    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(receivedChars,",");      // get the first part
    // strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

    // strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    integerFromPC = atoi(strtokIndx);     // convert this part to an integer

    strtokIndx = strtok(NULL, ",");
    // floatFromPC = atof(strtokIndx);     // convert this part to a float
    integerBFromPC = atoi(strtokIndx);  // <-------- convert this part to another integer

}


void showParsedData() {
    Serial.print("Integer ");
    Serial.println(integerFromPC);
    Serial.print("IntegerB ");
    Serial.println(integerBFromPC);
}

…R