Pages: [1]   Go Down
Author Topic: Conflict between Servo and Serial commands on Arduino Uno with Mega 2560.  (Read 836 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I've been trying to get a project up and running for controlling a remote control car using a netbook and an arduino Uno Mega 2560. It's been an absolute nightmare as the Serial library seems to be stomping on the Servo memory. Every time I poll for sensors, the servo memory connected to the forward/backward driving motor goes into full speed forward.

Any attempt to use a state variable to update the servo value causes the system to go full speed forward as well (where the full speed corresponds to a zero being written to the servo using c_drive.write(0); )

Is there any way to avoid the system losing control when the sensor data is returned using   

for (int i2 = 0;i2 < k_numberOfSensors;i2++)
  {   
    Serial.write(f_processDistance(f_readValue(i2)));
  } 
  Serial.write('~');
}


I've tried several methods such as keep a state variable and updating the motor each time, yet it seems likely that it's a fault with the hardware, seeing as though I have no control over whether the memory for the system is being overwritten.

Attached below is the source code.


#include <Servo.h>

#define k_upperBound 150          // Highest allowed angle for servo motors
#define k_lowerBound 50           // Lowest allowed angle for servo motors

#define k_servoSteerNeutral 100    // Neutral position in relation to servo degrees for direction
#define k_servoSteerRight   70
#define k_servoSteerLeft    130

#define k_servoDriveNeutral  100   // Neutral position in relation to servo degrees for driving
#define k_servoDriveForward  90
#define k_servoDriveBackward 110

#define k_servoDrivePin 9         // Pin on board used for driving
#define k_servoSteerPin 10        // Pin on board used for steering

#define k_smoothingFactor 32      // Constant used in the smoothing function
#define k_calibSlope 2323.66      // Calibration constant for linear regression in
// the conversion function
#define k_calibIntercept 16.8     // Calibration constant for linear regression intercept
// in the conversion function
#define k_calibDelay 5000         // Delay for 'x' microseconds for calibration of sensors.                                
#define k_numberOfSensors 1       // Number of sensors currently active on the board

Servo c_steer;                    // Servo controller for the steering motor
Servo c_drive;                    // Servo controller for the driving motor
unsigned char m_serialData[129];  // Buffer for incoming serial data
int c_state = 0;                  // Auxiliary state variable

unsigned char m_serialResponse[129];  // Buffer for outgoing serial data.
char m_respond = 0;          // Indicates the data will be flushed serially.

int t_i = 0;
int i_values[k_numberOfSensors];



// ------- PROTOTYPES --------

int f_readValue(int i_num);
double f_convDistance(int i_valueD);
unsigned char f_processDistance(int i_value1);
int limit(int input);


// ------- MAIN PROGRAM ------

void setup()
{
  Serial.begin(9600);
  c_steer.attach(k_servoSteerPin);
  c_steer.write(k_servoSteerNeutral);
  c_drive.attach(k_servoDrivePin);
  c_drive.write(k_servoDriveNeutral);

  for (int i = 0; i < 128; i++)  // Initialize the storage buffer.
  {
    m_serialData = 0;
  }
}

void loop()
{
  if (Serial.available() > 0)
  {
    for (int i = 0; i <= 3 ;i++)
    {
      m_serialData = Serial.read();
    }

    if ((m_serialData[0] & 0x80) != 0x80)
    {
      // Control it using automated commands
      int in_state = (m_serialData[0]) & 0x03;
      switch (in_state)
      {
      case 0:
        break;
      case 1:
        c_drive.write(k_servoDriveForward);
        break;
      case 2:
        c_drive.write(k_servoDriveBackward);
        break;
      case 3:
        c_drive.write(k_servoDriveNeutral);
        break;
      }
      in_state = ((m_serialData[0]) & 0x0C) >> 2;
      switch(in_state)
      {
      case 0:
        break;
      case 1:
        c_steer.write(k_servoSteerRight);
        break;
      case 2:
        c_steer.write(k_servoSteerLeft);
        break;
      case 3:
        c_steer.write(k_servoSteerNeutral);
        break;
      }
    }
     else  // MANUAL CONTROL
    {
       if ((m_serialData[1] & 0x01) == 0x01) { c_steer.write(limit(((signed char)m_serialData[1] >> 1)+k_servoSteerNeutral));}
       if ((m_serialData[2] & 0x01) == 0x01) { c_drive.write(limit(((signed char)m_serialData[2] >> 1)+k_servoDriveNeutral));}
    
    }
  }

  for (int i2 = 0;i2 < k_numberOfSensors;i2++)
  {    
    Serial.write(f_processDistance(f_readValue(i2)));
  }  
  Serial.write('~');
}










// ----------------------------------------- FUNCTIONS ------------------------------------

int f_readValue(int i_num)
{
  int input;

  switch(i_num)
  {
  case 0:
    input = analogRead(A0);
    break;
  case 1:
    input = analogRead(A1);
    break;
  case 2:
    input = analogRead(A2);
    break;
  case 3:
    input = analogRead(A3);
    break;
  case 4:
    input = analogRead(A4);
    break;
  case 5:
    input = analogRead(A5);
    break;
  case 6:
    input = analogRead(A6);
    break;
  case 7:
    input = analogRead(A7);
    break;
  default:
    input = analogRead(A0);
    break;
  }
  return input;

}

double f_convDistance(int i_valueD)
{
  // For a rough estimate of the distance from the sensor to the object,
  // it will be roughly reverse-regressed linearly. The returned value
  // is a value in centimeters, based on the previously accumulated data
  // from both the data sheet for the Sharp 2D120X F 01 and from physical
  // data.

  if (i_valueD - k_calibIntercept == 0)
  {
    return 255.0;
  }
  else{  
    return (abs(k_calibSlope / (i_valueD - k_calibIntercept)));
  }

  // In case of demons trying to eat the carpet again....

    return 0.0;
}

unsigned char f_processDistance(int i_value1)
{
  // To simplify the data being sent, the distance is turned from a full
  // "double" to an unsigned character.
  double i_distance = f_convDistance(i_value1);

  if ((i_distance >0)&&(i_distance <=255))
  {
    return (unsigned char)ceil(i_distance);
  }
  if (i_distance < 0)  
  {
    return 0;

  }
  if (i_distance >255)  return 255;

  // In case of escaping cats of shame...
  return 0;
}


int limit(int input)
{
  // To make sure the system operates correctly, all inputs must be
  // bounded values when outputted to the servo.
  int output = 0;
  output = input;
  if (output > k_upperBound) {
    output = k_upperBound;
  }
  if (output < k_lowerBound) {
    output = k_lowerBound;
  }
  return output;
}


« Last Edit: February 11, 2011, 02:46:50 pm by Kaikydelan » Logged

New Hampshire
Offline Offline
God Member
*****
Karma: 17
Posts: 781
There are 10 kinds of people, those who know binary, and those who don't.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Don't know if this is related to your problem or not, but you have one line in setup() "m_serialData = 0 "and one line near the beginning of loop() "m_serialData = Serial.read()", and both should be using m_serialData since m_serialData is an array.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ah sorry,

When the code was copied from the source file, it seems that m_serialData didn't make it. I don't know why. It's still not working though.
Logged

Pages: [1]   Go Up
Jump to: