how would I create a "dead zone"

I have this code that I have been working on for a long time and its finally coming to together. for now it is a code to read a RC receiver and use that out put to control two serial motor controllers connected to a deferential robotic platform. The issue I am having is that the RC controller is bouncing around a lot (-+ 15 when at center position) and causing the motors to move forward or backwards. I am wondering if there is a way to create a “dead zone” for the center position of each channel. I am using a chipkit max32. The typical output of the receiver for each channel is 3500-4500. so for the only way I have solved this issue is by ignoring the last two digits of the numbers. ie(3500/100), but i would like to have the resolution back.
As of this point in time I dont believe I can use interrupts due to software.

unsigned long counter = 0;
unsigned long Channel1Value;
unsigned long Channel2Value;
unsigned long lastgood1;
unsigned long lastgood2;
unsigned long InitialSteer;
unsigned long InitialThrottle;
unsigned long InitialMotorLimit;
long MotorLimit;
int Channel3Value;
boolean Right;
//motor stuff
int Steer;
int Thrust;
int RightMotor;
int LeftMotor;
int Chan1 = 11;
int Chan2 = 10;
int Chan3 = 9;


HardwareSerial mySerial = Serial1;

/**************************************************************
 * Subroutine to exit saft start;
 ***************************************************************/
void exitSafeStartBoth()  
{  
  mySerial.print(0x83, BYTE);  
}  
/**************************************************************
 * Subroutine to control right motor= motorRight(speed, direction);
 ***************************************************************/
void setMotorSpeedleft(int speedleft)
{
  if (speedleft < 0)
  {
    mySerial.print(0xAA, BYTE);
    mySerial.print(0xd, BYTE);
    mySerial.print(0x6, BYTE); // motor reverse command
    speedleft = -speedleft; // make speed positive
  }
  else
  {
    mySerial.print(0xAA, BYTE);
    mySerial.print(0xd, BYTE);  
    mySerial.print(0x5, BYTE); // motor forward command
  }
  mySerial.print((unsigned char)(speedleft & 0x1F), BYTE);
  mySerial.print((unsigned char)(speedleft >> 5), BYTE);
}

/**************************************************************
 * Subroutine to control left motor
 ***************************************************************/
void setMotorSpeedright(int speedright)
{
  if (speedright < 0)
  {
    mySerial.print(0xAA, BYTE);
    mySerial.print(0xa, BYTE);
    mySerial.print(0x06, BYTE); // motor reverse command
    speedright = -speedright; // make speed positive
  }
  else
  {
    mySerial.print(0xAA, BYTE);
    mySerial.print(0xa, BYTE);  
    mySerial.print(0x05, BYTE); // motor forward command
  }
  mySerial.print((unsigned char)(speedright & 0x1F), BYTE);
  mySerial.print((unsigned char)(speedright >> 5), BYTE);
}



void setup()
{
  mySerial.begin(19200);
  Serial.println("Ready");
  pinMode (Chan3, INPUT); // connect Rx channel 1 to PD3, which is labled "D3" on the Arduino board
  pinMode (Chan2, INPUT); // connect Rx channel 2 to PD4, which is labled "D4" on the Arduino board
  pinMode (Chan1, INPUT); //  connect Rx channel 3 to PD5, which is labled "D5" on the Arduino board
  InitialSteer = (pulseIn (Chan2, HIGH)/100); //read RC channel 1
  lastgood1 = InitialSteer;
  InitialThrottle = (pulseIn (Chan1, HIGH)/100); //read RC channel 2
  lastgood2 = InitialThrottle; 
  InitialMotorLimit = (pulseIn (Chan3, HIGH)/100); 
}

void loop()
{
  //  counter++;  // this just increments a counter for benchmarking the impact of the pulseIn's on CPU performance
  Channel1Value = (pulseIn (Chan1, HIGH, 50000)/100); //read RC channel 1
  Channel2Value = (pulseIn (Chan2, HIGH, 35000)/100); //read RC channel 2
  Channel3Value = (pulseIn (Chan3, HIGH, 50000)/100); // read RC channel 3


  if (Channel1Value == 0) {
    Channel1Value = lastgood1;
  } 
  else {
    lastgood1 = Channel1Value;
  }
  if (Channel1Value < InitialSteer) {
    Right = false;
  } 
  else {
    Right = true;
  }

  if (Right) {
    Steer = Channel1Value - InitialSteer;
  } 
  else {
    // Steer = InitialSteer - Channel1Value;
  }
  Steer = map(Channel1Value, 34, 56, -(MotorLimit), MotorLimit); // convert to -3200 to 3200
  constrain (Steer, -MotorLimit, MotorLimit); //just in case

  // Thrust = Channel2Value - InitialThrottle;
  Thrust = map(Channel2Value, 36, 55, -(MotorLimit), MotorLimit); // convert to 0-100 range
  constrain (Thrust, -(MotorLimit), MotorLimit); //just in case
  MotorLimit = map(Channel3Value, 35, 54, 0, 3200); // map to 0-3200
  constrain (MotorLimit, 0, 3200);

  Serial.print ("Channel 1: ");  // if you turn on your serial monitor you can see the readings.
  Serial.println (Channel1Value);
  Serial.print("Channel 2: ");
  Serial.println (Channel2Value);
  Serial.print ("Channel 3: ");
  Serial.println (Channel3Value);
  Serial.println(LeftMotor);
  Serial.println(RightMotor);
  Serial.println("");
  Serial.println("");
  Serial.println("");
  Serial.println("");

  if (Right == true) // turn right 
  {
    RightMotor = Thrust - Steer; // reduce power to the motor in the direction you want to go 
    // if (RightMotor < 0) RightMotor = 0; //mike changed this so that they will run backwards
    LeftMotor = Thrust + Steer; // increase power to the motor opposite the direction you want to go
    if (LeftMotor > 3200) LeftMotor = 3200;
  }
  if (Right == false) //turn left
  {
    LeftMotor = Thrust - Steer; // reduce power to the motor in the direction you want to go 
    // if (LeftMotor < 0) LeftMotor = 0; //mike changed this so that they will run backwards
    RightMotor = Thrust + Steer; // increase power to the motor opposite the direction you want to go
    if (RightMotor > 3200) RightMotor = 3200;

  }
  constrain (LeftMotor, -3200, 3200);
  constrain (RightMotor, -3200, 3200);
  setMotorSpeedleft(LeftMotor);
  setMotorSpeedright(RightMotor);
  delay(500);
}

Creating a “dead zone” is easy. All that “dead zone” means, in this case, it that there is a range of values that is ignored. If one reading is 3550, the next reading of interest must be greater than or equal 3550 + some value or less than or equal 3550 - some value.

  Channel1Value = (pulseIn (Chan1, HIGH, 50000)/100); //read RC channel 1

The outer parentheses are not required.

Change that statement to:

int newVal1 = pulseIn(Chan1, HIGH, 50000);
if(newVal1+deadZone >= Channel1Value ||
   newVal1-deadZone <= Channel1Value)
   Channel1Value = newVal1;

Now, Channel1Value will have a new value only if it differed significantly from the previous value, where you define “significantly” by the value in deadZone.

Creating a dead zone or hysteresis is easy solution to "mask" a bouncing problem, but not the best one. Other approach is implement PID control algorithm, so your robot will react faster when it far away from "center" and slowdown when it close to it.

I have used paulS 's solution 2 or three times on tankdrive projects of the sort you are working on with much sucess. I found that the PID style response generally gave me response time issues due to increased loop time. It may be entirely dependent on the project itself as to which works best.

This will do it - replace the assignment to Steer with this:

  if((Channel1Value < CHANNEL_ONE_MIDPOINT-DEADZONE) || (Channel1Value > CHANNEL_ONE_MIDPOINT+DEADZONE))
    {
    Steer = map(Channel1Value, 34, 56, -(MotorLimit), MotorLimit); // convert to -3200 to 3200
    Steer = constrain (Steer, -MotorLimit, MotorLimit); //just in case
    }
  else 
    Steer = 0;

Put in the #defines at the top somewhere:

#define CHANNEL_ONE_MIDPOINT 4000 // Reading when Channel one is centered
#define DEADZONE 100              // Deadzone extends plus or minus this around the midpoint

Note that your constrain statements don’t do anything - you need to use the return value, as in my example above.

okay, so i mostly fixed issue with the bouncing center point, but one thing i have found in testing is that the drives nine time out of ten will only turn right. It steers right when I tell it to steer right of left. I’m not sure what is causing this. my question is does any one know how to control a tank style drive better than mine. Okay, thinking about it , there most likely a thousand way to do it better but what works for you guys?

void setup()
{
  Serial3.begin(19200);
  Serial.begin(19200);
  Serial.println("Ready");
  pinMode (Chan3, INPUT); // connect Rx channel 1 to PD3, which is labled "D3" on the Arduino board
  pinMode (Chan2, INPUT); // connect Rx channel 2 to PD4, which is labled "D4" on the Arduino board
  pinMode (Chan1, INPUT); //  connect Rx channel 3 to PD5, which is labled "D5" on the Arduino board
  InitialSteer = pulseIn (Chan2, HIGH); //read RC channel 1
  lastgood1 = InitialSteer;
  InitialThrottle = pulseIn (Chan1, HIGH); //read RC channel 2
  lastgood2 = InitialThrottle; 
  InitialMotorLimit = pulseIn (Chan3, HIGH)/100; 
}

void loop()
{
  //  counter++;  // this just increments a counter for benchmarking the impact of the pulseIn's on CPU performance
  newVal1 = pulseIn(Chan1, HIGH, 50000);
  newVal2 = pulseIn(Chan2, HIGH, 35000);
  Channel3Value = pulseIn (Chan3, HIGH, 50000)/100; // read RC channel 3
  if(newVal1+deadZone1 >= Channel1Value ||
    newVal1-deadZone1 <= Channel1Value)
    Channel1Value = newVal1;

  if(newVal2+deadZone2 >= Channel2Value ||
    newVal2-deadZone2 <= Channel2Value)
    Channel2Value = newVal2; //read RC channel 2

    if (Channel1Value == 0) {
    Channel1Value = lastgood1;
  } 
  else {
    lastgood1 = Channel1Value;
  }
  if (Channel1Value < InitialSteer) {
    Right = false;
  } 
  else {
    Right = true;
  }

  if (Right) {
    Steer = Channel1Value - InitialSteer;
  } 
  else {
    // Steer = InitialSteer - Channel1Value;
  }
  Steer = map(Channel1Value, 3498, 5686, -(MotorLimit), MotorLimit); // convert to -3200 to 3200
  constrain (Steer, -MotorLimit, MotorLimit); //just in case

  // Thrust = Channel2Value - InitialThrottle;
  Thrust = map(Channel2Value, 3650, 5672, -(MotorLimit), MotorLimit); // convert to 0-100 range
  Thrust = constrain (Thrust, -(MotorLimit), MotorLimit); //just in case
  MotorLimit = map(Channel3Value, 35, 54, 0, 3200); // map to 0-3200
  MotorLimit = constrain (MotorLimit, 0, 3200);

  Serial.print ("Channel 1: ");  // if you turn on your serial monitor you can see the readings.
  Serial.println (Channel1Value);
  Serial.print("Channel 2: ");
  Serial.println (Channel2Value);
  Serial.print ("Channel 3: ");
  Serial.println (Channel3Value);
  Serial.println(LeftMotor);
  Serial.println(RightMotor);
  Serial.println("");
  Serial.println("");
  Serial.println("");
  Serial.println("");

  if (Channel3Value > 0){ 
     exitSafeStartBoth();
  }
    if (Right == true) // turn right 
    {
      RightMotor = Thrust - Steer; // reduce power to the motor in the direction you want to go 
      // if (RightMotor < 0) RightMotor = 0; //mike changed this so that they will run backwards
      LeftMotor = Thrust + Steer; // increase power to the motor opposite the direction you want to go
      if (LeftMotor > 3200) LeftMotor = 3200;
    }
  if (Right == false) //turn left
  {
    LeftMotor = Thrust - Steer; // reduce power to the motor in the direction you want to go 
    // if (LeftMotor < 0) LeftMotor = 0; //mike changed this so that they will run backwards
    RightMotor = Thrust + Steer; // increase power to the motor opposite the direction you want to go
    if (RightMotor > 3200) RightMotor = 3200;

  }
  LeftMotor = constrain (LeftMotor, -3200, 3200);
  RightMotor = constrain (RightMotor, -3200, 3200);
  setMotorSpeedleft(LeftMotor);
  setMotorSpeedright(RightMotor);
  delay(50);

It looks to me that the mapping of Steer to a value from -3200 to 3200 is the issue.

Assume initial steer is 4400 if Channel1 is 3498, right = false. Steer will be mapped to -3200

then, LeftMotor=Thrust - -3200 RightMotor=Thrust+-3200

So even though your intent is to go left, leftmotor has much more power than right & you're turning right.

Work through the same exercise when Channel1=5686 and you'll see that that too results in a right turn. Map Steer to be between 0 and motorlimit.

BTW, your constrain statements have not changed and therefore, they still do nothing.

Wow!!! that did the trick! I removed // Steer = map(Channel1Value, 3600, 5810, -MotorLimit, MotorLimit); // convert to -3200 to 3200 why is that part messing with the code?

[quote author=Pack Rat link=topic=66741.msg491417#msg491417 date=1311037529] Wow!!! that did the trick! I removed // Steer = map(Channel1Value, 3600, 5810, -MotorLimit, MotorLimit); // convert to -3200 to 3200 why is that part messing with the code? [/quote] Because it allows Steer to take a negative value and your steering logic implicitly assumes that Steer is non-negative. Try dry running your code with some different values of channel1 and you'll see that it always speeds up leftmotor and slows down rightmotor whichever way you tell it to turn.

Yeah, that makes sense. Are there better ways to control a track drive? not i just need to find some lead batteries that will last.