ArduinoFio/xbee +wii-chuck code > skid steering algorithm

It would help to know what part of the code is not working. Note: signed versus unsigned math depends on types of variables… the type byte that is returned by several of the nunchuck functions returns byte values which are unsigned. But it looked like you already moved these to a signed int value…

Kurt

Mixing the x and y in to differential drive output (foward/ rev + left/right), the code in that last message I posted was taken from the following code, when I tried to modify it for the Wii chuck the drive output is all over the place, my best guess (is that I dont have a clue:cry:… ) it seems that the negative values are not working correctly or something… this was seen by viewing the output to serial… If you need more detail, I’ll reload the TX and log the transmission via serial…

[code]/*
Joystick controlled differential steer mobile robot.
Author: Dustin Maki
Date: Sept 1 2011
GPL License. Free to use, just give credit where due.
This program scales the joystick reading to start at 1 just outside the deadband so you do not have a large jump in speed.
It adjusts to the common case where the centered joystick does not rest at quite the center of the range.
This was first used with
Teensy++ v.1 http://www.pjrc.com/teensy/pinout.html
Solarbotics LM298D H bridge http://www.solarbotics.com/products/k_cmd/
with transistor on each side to switch the direction as in datasheet.
Joystick http://www.sparkfun.com/products/9032

*/
#define START_BUTTON 21 // not a momentary switch, a toggle switch will work
#define JOYSTICK_BUTTON_PIN 10 // hold joystick with ‘tail’ toward you. side with holes on sparkfun breakout board
#define JOYSTICK_X_PIN A0 //full left is 1023, full right is 0
#define JOYSTICK_Y_PIN A1//full forward is 1023, full backward is 0
#define LEFT_PWM_PIN 14
#define LEFT_DIRECTION_PIN 13
#define RIGHT_PWM_PIN 24
#define RIGHT_DIRECTION_PIN 23
#define HALF_DEADBAND 3 //adjust till desired deadband is achieved
#define XRAW_CENTERED 525 // set to whatever "x joystick value is: " on the serial monitor
#define YRAW_CENTERED 493 // set to whatever "y joystick value is: " on the serial monitor
#define DEBUG true // set to false to stop serial messages

void setup()
{
if (DEBUG)
Serial.begin(38400);

pinMode(LEFT_PWM_PIN, OUTPUT);
pinMode(RIGHT_PWM_PIN, OUTPUT);
pinMode(LEFT_DIRECTION_PIN, INPUT);// sets high impedance on pin, brake
pinMode(RIGHT_DIRECTION_PIN, INPUT);// sets high impedance on pin, brake
digitalWrite(LEFT_PWM_PIN, LOW);
digitalWrite(RIGHT_PWM_PIN, LOW);
}

int throttle, steering;
int xraw, yraw, leftSpd, rightSpd;

void loop()
{
// start button is a push on, push off type. grounded when on
// when start button is released, program just runs main loop
while(digitalRead(START_BUTTON) == LOW)
{
if (digitalRead(JOYSTICK_BUTTON_PIN) == LOW)//brake requested
{
pinMode(LEFT_DIRECTION_PIN, INPUT);// sets high impedance on pin, brake
pinMode(RIGHT_DIRECTION_PIN, INPUT);// sets high impedance on pin, brake

  if (DEBUG)
  { 
    Serial.println("brake applied");
  }
  continue;// will not continue main loop, only while
}

else //start button pressed and not braked
{
// capture joystick position
yraw = analogRead(JOYSTICK_Y_PIN);
xraw = analogRead(JOYSTICK_X_PIN);

// scale x and y axis so that both are zeroed at natural center of potentiometer, implement deadband
if(yraw > YRAW_CENTERED + HALF_DEADBAND)//forward
{
  throttle = map(yraw, YRAW_CENTERED + HALF_DEADBAND, 1023, 0, 255);      
  if(xraw > XRAW_CENTERED + HALF_DEADBAND)//left
  {
    steering = map(xraw, XRAW_CENTERED + HALF_DEADBAND, 1023, -0, -255);// reverse pot coordinates to agree with cartesian        
  }
  else if(xraw < XRAW_CENTERED - HALF_DEADBAND)// right
  {
    steering = map(xraw, XRAW_CENTERED - HALF_DEADBAND, 0, 0, 255);// reverse pot coordinates to agree with cartesian        
  }
  else // in X deadband
  {
    steering = 0;
  }
}

else if(yraw < YRAW_CENTERED - HALF_DEADBAND)//reverse
{
  throttle = map(yraw, YRAW_CENTERED - HALF_DEADBAND, 0, -0, -255);      
  if(xraw > XRAW_CENTERED + HALF_DEADBAND)//left
  {
    steering = map(xraw, XRAW_CENTERED + HALF_DEADBAND, 1023, -0, -255);// reverse pot coordinates to agree with cartesian        
  }
  else if(xraw < XRAW_CENTERED - HALF_DEADBAND)// right
  {
    steering = map(xraw, XRAW_CENTERED - HALF_DEADBAND, 0, 0, 255);// reverse pot coordinates to agree with cartesian        
  }
  else// in X deadband
  {
    steering = 0;
  }
}
else //in Y deadband
{
  throttle = 0;
  if(xraw > XRAW_CENTERED + HALF_DEADBAND)//left
  {
    steering = map(xraw, XRAW_CENTERED + HALF_DEADBAND, 1023, -0, -255);// reverse pot coordinates to agree with cartesian        
  }
  else if(xraw < XRAW_CENTERED - HALF_DEADBAND)// right
  {
    steering = map(xraw, XRAW_CENTERED - HALF_DEADBAND, 0, 0, 255);// reverse pot coordinates to agree with cartesian        
  }
  else// in X deadband
  {
    steering = 0;
  }
}

//transfer from x,y to l,r
leftSpd = throttle + steering;
rightSpd = throttle - steering;
//leftSpd and rightSpd will contain a number from -255 to 255 that gets updated each time the loop runs.
//-255 equates to full reverse. 0 equates to anywhere within the deadband. 255 is full forward.

// The next 2 sections can be replaced to use with servos, stepper motors, BLDCs or whatever drive you like.

//write direction pin
if (leftSpd < 0)
digitalWrite(LEFT_DIRECTION_PIN, LOW);
else if (leftSpd > 0)
digitalWrite(LEFT_DIRECTION_PIN, HIGH);
if (rightSpd < 0)
digitalWrite(RIGHT_DIRECTION_PIN, LOW);
else if (rightSpd > 0)
digitalWrite(RIGHT_DIRECTION_PIN, HIGH);

//write PWM pin
analogWrite(LEFT_PWM_PIN, abs(leftSpd));
analogWrite(RIGHT_PWM_PIN, abs(rightSpd));

if (DEBUG)
{
Serial.print("x joystick value is: ");
Serial.println(xraw);
Serial.print("y joystick value is: ");
Serial.println(yraw);
Serial.print("throttle is: ");
Serial.println(throttle);
Serial.print("steering is: ");
Serial.println(steering);
Serial.print("leftSpd is: ");
Serial.println(leftSpd);
Serial.print("rightSpd is: ");
Serial.println(rightSpd);

delay(250);
}
}
}
}[/code]

Since I happen to have an Arduino with a nunchuck hooked up (actually an Seeeduino Mega with prototype Botboarduino Mega shield and 2 nunchucks…), I decided to run your code to figure out what was going on.

Once I started running it, the problem became obvious…

If you look at some of your code like:

Serial.print("xjoy: "); Serial.print((byte)xraw,DEC); Serial.print("\tyjoy: "); Serial.print((byte)yraw,DEC); Serial.print("\tthrottle: "); Serial.print((byte)throttle,DEC); Serial.print("\tsteering: "); Serial.print((byte)steering,DEC); Serial.print("\tleftSpd: "); Serial.print((byte)leftSpd,DEC); Serial.print("\trightSpd: "); Serial.println((byte)rightSpd,DEC);
You see that when you are outputting the values, such as Throttle, you are casting the value to a byte, which is an unsigned value with the range to 0-255. This more or less translates to: Serial.Print(throttle & 0xff, DEC);

So if you simply remove the casting of variables, you all of a sudden start to see both positive and negative values… On my machine I also kept the values of the previous xjoy, yjoy and only output the data when these change, that way it is easier to see how the values change without it all scrolling by real quick…

like:
Added defines: byte xjoyPrev, yjoyPrev;

[code] if (DEBUG)
{
if ((xjoy != xjoyPrev) || (yjoy != yjoyPrev)) {
Serial.print("xjoy: “);
Serial.print(xraw,DEC);
Serial.print(”\tyjoy: “);
Serial.print(yraw,DEC);
Serial.print(”\tthrottle: “);
Serial.print(throttle,DEC);
Serial.print(”\tsteering: “);
Serial.print(steering,DEC);
Serial.print(”\tleftSpd: “);
Serial.print(leftSpd,DEC);
Serial.print(”\trightSpd: ");
Serial.println(rightSpd,DEC);
xjoyPrev = xjoy;
yjoyPrev = yjoy;

                delay(1);
            }
        }

[/code]

Kurt

So, that means the code works as is, just my noob-ness outputting (byte) was stripping the negatives and trying to use variables mapped to a unsigned byte (when I first started playing with this). I see this the major drawback to trying to teach yourself how the coding work when you (I) have no idea what the basic stuff does, RTFM fail on my part… lol
Also now that I am starting to understand the processing restraints with the arduino platform have any of you thought about using the Leaf Maple micro controller?

Thanks for all the code help Kurte, I’ll post back soon after I play with the code you posted and do some RTFM so I can attempt to avoid some more simple mistakes. :smiley:

~Wolf

… Still trying to get this to work, Mostly still need help with the 2 axis joy input (x,y) to skid steer servo control. The code I have currently running works… sort of, steering control is next to nill, smooth radius turns do not exist. I can either get foward/back or pivot/zero space turns

Oh, and searching I found viewtopic.php?t=2860 , BUT… I don’t understand any of the code in there :frowning:

Really… The night after my new DX6I arrives because I finally decide to shelf the whole channel mixing idea I find on the web…

[code]#include <Servo.h>

Servo servo1;
Servo servo2;
int gain1 = 2;
int gain2 = 2;
int s1= 0;
int s2= 0;

void setup()
{
// Serial.begin(115200);
servo1.attach(9); // attach Servo 1 to pin 9
servo2.attach(10); // attach Servo 2 to pin 10
pinMode(3, INPUT); // Signal 1 input at pin3 (Elevator)
pinMode(4, INPUT); // Signal 2 input at pin4 (Rudder)
}

void loop()
{
s1 = (pulseIn( 3,HIGH)-1500)/gain1;
s2 = (pulseIn( 4,HIGH) -1500)/gain2;
servo1.writeMicroseconds(s1+s2+1500);
servo2.writeMicroseconds(s1-s2+1500);
// Serial.println(s1);
} [/code]

Could it really be this simple? :unamused: Seems the mixing term is Elevon wing/tail mixing which for seems to be the same mix rate/result as needed for the differential steer…