Go Down

### Topic: Uno, Joystick, XBee and Motor Shield (Read 1 time)previous topic - next topic

#### Renwaar

##### Jun 18, 2012, 10:44 pmLast Edit: Jun 19, 2012, 09:42 am by Renwaar Reason: 1
Hi Everyone

This is my first post and I've started looking at Arduino for a few small projects whilst in rehab from a major accident. So I do have a bit of time on my hands, however that being said I have run into a bit of a problem that has resulted in this post (must be a little impatient I guess) hope someone can point me in the right direction.

I have looked at a number of tutorials relating to the Xbee and the Motor Shield I purchased. I am at a stage where I have my Xbees talking, I can control the required 2 Motors by passing a variable to the second Arduino with the motor shield. But I now have two more steps (questions)

1, How can I make two variables pass to the second Arduino so that it will move my project in two directions at once i.e. horizontal and vertically resulting in a diagonal movement?

2, I wish to control the speed based on the Joystick position. I have this working fine in my head of course but just need a little help with the code if someone has the time?

Here is the code I have managed so far:

Joystick Arduino:
Code: [Select]
`//Code from Sparkfun with a few tweeks const byte PIN_ANALOG_X = 0;const byte PIN_ANALOG_Y = 1;const int X_THRESHOLD_LOW = 450;   //I have the contrains real big so there's less chance for const int X_THRESHOLD_HIGH = 550;  //analog misinterpretation. const int Y_THRESHOLD_LOW = 450;const int Y_THRESHOLD_HIGH = 550;int x_position;int y_position;int x_direction;int y_direction;void setup() {Serial.begin(9600);}void loop () {x_direction = 0;y_direction = 0;x_position = analogRead(PIN_ANALOG_X);y_position = analogRead(PIN_ANALOG_Y);if (x_position > X_THRESHOLD_HIGH) {x_direction = 1;} else if (x_position < X_THRESHOLD_LOW) {x_direction = -1;}if (y_position > Y_THRESHOLD_HIGH) {y_direction = 1;} else if (y_position < Y_THRESHOLD_LOW) {y_direction = -1;}if (x_direction == -1) {if (y_direction == -1) {Serial.println("left-down");} else if (y_direction == 0) {Serial.println("a");                // "a" is horiz pan right} else {// y_direction == 1Serial.println("left-up");}} else if (x_direction == 0) {if (y_direction == -1) {Serial.println("s");                // "s" is verti pan up} else if (y_direction == 0) {Serial.println("f");                // "f" is for Stop until something else is sent} else {// y_direction == 1Serial.println("w");                // "w" is verti pan down}} else {// x_direction == 1if (y_direction == -1) {Serial.println("right-down");} else if (y_direction == 0) {Serial.println("d");                // "d" is horiz pan left} else {// y_direction == 1Serial.println("right-up");}}}`

Motor Shield Arduino:
Code: [Select]
`#include <AFMotor.h>AF_DCMotor horiz(1, MOTOR12_1KHZ);AF_DCMotor verti(2, MOTOR12_1KHZ);AF_DCMotor motors[2] = {horiz, verti};void setup(void){ Serial.begin(9600);}void loop(void){ while (Serial.available() < 0) {} // Wait until a character is received char val = Serial.read(); int Xspeed = 255; //255 is maximum speed int Yspeed = 255; //horiz.setSpeed(155); //verti.setSpeed(255); switch(val) // Perform an action depending on the command {  case 'w'://Verti Pan Down  verti.setSpeed(Yspeed);  verti.run(FORWARD);  Serial.print("Pan Down");  break;  case 's'://Verti Pan Up  verti.setSpeed(Yspeed);  verti.run(BACKWARD);  Serial.print("Pan Up");  break;  case 'a'://Horiz Pan Right  horiz.setSpeed(Xspeed);  horiz.run(FORWARD);  Serial.print("Pan Right");  break;  case 'd'://Horiz Pan Left  horiz.setSpeed(Xspeed);  horiz.run(BACKWARD);  Serial.print("Pan Left");  break;  case 'f'://Stop  horiz.run(RELEASE);  verti.run(RELEASE);  break;  default:  break; }}`

#### njs552

#1
##### Jun 19, 2012, 04:48 am
Hi there,
I think the best way to do this would be to send two values between 10-99 over serial that control motor speed, which the second arduino would re-map back to 1-255 to output using PWM to the motor drivers.

THE 10-99 IS VERY IMPORTANT. If you sent a straight PWM(1-255) value, then if one variable was 23, and the other 223, and your variables on the receiving end were reading three characters, then the first variable will read 232 and the second 32. That is probably not what you want. the 10-99 keeps the variable two digits no matter what, and

Here is what you should do:
-read joystick and map the values for x and y to 10-99. ex: map(motorOutputvariable, 1,255,10,99); map(variable, variable range min, variable range max, new range min, new range max)
-use itoa to make the two(or more variables) into a string.
-send string using the Serial.println(variable); command.
-then loop

Serial Sending Code:
Code: [Select]
`//Written by njs552 06/18/2012//Last Modified: 06/18/2012 1806hrs PST//Released to the public domain//=============================================================//MARK: USER INTERFACE//Debugint debug = 0; //0 = off, 1 = on//=============================================================//MARK: Pin Declarations //Headtbeatint ledPin = 9;//=============================================================//MARK: VARIABLES:int variable_1 = 20;int variable_2 = 43;int variable_3 = 51;int variable_4 = 74;//=============================================================//MARK: Serialchar replySerial[25];char sendSerial[100];byte startByte = '#';byte endByte = '*';//=============================================================//MARK: TIMING VARIABLE DECLARATION SECTION//Heartbeat Blinkunsigned long lastHeartbeatTime = 0;  unsigned long heartBeatInterval = 1000; //1sec bool heartbeatState = false;//send serialunsigned long lastSend = 0;unsigned long currentTime;unsigned long sendInterval = 100;//===================================================================================================================================//===================================================================================================================================//===================================================================================================================================//===================================================================================================================================//===================================================================================================================================void setup(){ Serial.begin(9600); if(debug == 1)   //1 = ON, 0 = OFF { Serial.println("Started"); } pinMode(ledPin, OUTPUT);}//============================================================= void loop(){ unsigned long currentHeartbeatTime = millis(); currentTime = millis(); if(currentTime - lastSend > sendInterval) { lastSend = currentTime; sendOverSerial(); //send serial packet }  //heartbeat or "dead" ROV if(currentHeartbeatTime - lastHeartbeatTime > heartBeatInterval) //if more tine than interval has passed { lastHeartbeatTime = currentHeartbeatTime; //set last time to current time if(heartbeatState == false) //if led is off { heartbeatState = true; //set its state to on } else { heartbeatState = false; //if on, set state to off }            } digitalWrite(ledPin, heartbeatState); //write the led on or off, depending on state}//=============================================================inline void sendOverSerial(){ memset(sendSerial, 0, sizeof(sendSerial));    itoa(variable_1, replySerial, 10);    strcat(sendSerial, replySerial);    itoa(variable_2, replySerial, 10);    strcat(sendSerial, replySerial);    itoa(variable_3, replySerial, 10);    strcat(sendSerial, replySerial);    itoa(variable_4, replySerial, 10);    strcat(sendSerial, replySerial); if(debug == 0) { Serial.write(startByte); Serial.write(sendSerial); Serial.println(endByte); }}`

Code: [Select]
`//written by Njs552 (06/18/2012)//last modified 06/18/2012 1825hrs PST//released into the public domain//=======================================================//MARK: Serialchar incomingData[100]; //to store incoming serial datachar variable[4]; //=======================================================//MARK: Timing Variables//Serial receiveunsigned long last1 = 0;unsigned long interval1 = 50;unsigned long current1;//======================================void setup(){ Serial.begin(9600);}//============================void loop(){ current1 = millis(); receiveSerial();}//==========================================================================inline void receiveSerial(){ byte ch; static int cpt=0; static byte flag=false; if (Serial.available()>0) { ch = Serial.read(); switch( ch ) { case '#' : { cpt =0; flag=false; break; } case '*' : { flag=true; break; }  default: //else of a switch statement { incomingData[cpt++]=ch; } } } if (flag==true) { variable[0] = incomingData[0]; variable[1] = incomingData[1]; variable[2] = incomingData[2]; variable[3] = incomingData[3]; memset(incomingData, 0, sizeof(incomingData)); }        Serial.flush Serial.println(variable);}`

You will have to add your code to this code to test this, but this code has worked for me in the past.

#### Renwaar

#2
##### Jun 19, 2012, 09:39 am
Hi njs552,

Many thanks for the reply, I have been looking at this code and I am having a little difficulty still in getting where I need to be. You have answered how I get more than one variable across and I get that, the string and the itoa. But my issue is getting it to function with my code.

My Joystick provides only two values (Anaolog 0 and 1) Xpos and Ypos both 0-1024, so as I understand it I map that to Xpos 10-19, then Ypos to 20-29 etc. This will give me what you suggest, but then I have the speed to address which is 0-255, so do I re-map it again? Would I need to make something like: (not actual code just how I would imagine it obviously) :

Code: [Select]
`variable1 = map(Xpos, 10,19,0,255);          // remap to 0-255if Xpos < 120 horizMotor.run(BACKWARD) setspeed(Xpos)    // run the motor in desired direction and speedif Xpos > 130 horizMotor.run(FORWARD) setspeed(Xpos)     // run the other motor in desired direction and speed`

This is just how I would see it, but I'm not sure how to get this into the code (and make this syntax correct)

Could you maybe just add that line for me to see it in action, I see that you have explained it but I just can't quite nail it.

Thanks Again,

Renwaar

#### njs552

#3
##### Jun 20, 2012, 05:35 am
Hi,
You could also map Xpos, Ypos, and Xspeed, and Yspeed  from 10-99 each, then send.

Code: [Select]
`variable1 = map(Xpos, 1, 1024, 10, 99);       // map controller input to 10-99 from original 1-1024variable2 = map(Ypos, 1, 1024, 10, 99);       //same as above, but different axis variable3 = map(Xspeed, 1, 255, 10, 99);      //x axis speed speedvariable4 = map(Yspeed, 1, 255, 10, 99);      //y axis speed//send variable in string`

Code: [Select]
`variable[0] =  incomingData[0];variable[1] =  incomingData[1];variable[2] =  incomingData[2];variable[3] =  incomingData[3];variable1 = map(variable[0], 10, 99, 1, 1024);variable2 = map(variable[1], 10, 99, 1, 1024);variable3 = map(variable[2], 10, 99, 1, 255);variable4 = map(variable[3], 10, 99, 1, 255);`

This code then re-maps the values so they are very close to the original numbers.

Next:
if Xpos < 120 horizMotor.run(BACKWARD) setspeed(Xspeed);    // run the motor in desired direction and speed
if Xpos > 130 horizMotor.run(FORWARD) setspeed(Xspeed);     // run the other motor in desired direction and speed
if Ypos < 120 verticalMotor.run(BACKWARD) setspeed(Yspeed); //vertical motor and speed
if Ypos > 130 verticalMotor.run(FORWARD) setspeed(Yspeed);  //vertical motor other direction and speed

Please let me know if this helps, and feel free to ask any questions,
njs552

Go Up