Servo Twitch... On Loop() cycle

I’ve run into a problem…

I’m driving two servos based on the input from one joystick. While I’m working on building the maths I need to calculate the bearing indicated on the joystick to translate to where to send the servos, I’ve settled on the eight basic compass points, and fuzzy logic to determine where the joystick is pointing to. Code at the bottom. The issue I’m having is that after my servos initialize, respond to commands, and the loop ends, the servos (ServoA more than ServoB) twitch as the next loop starts.

The servos are not powered by the Arduino Uno r3. While it might be a power based problem I believe I have ruled that out as if I change the value of the delay at the end of the loop, the delay between twitches changes accordingly.

Note: ServoB is rotated 180 in its housing, so that it’s 180-degree rotational range allows the pair of servos to cover a circular area.

#include <SoftwareSerial.h>
#include <Servo.h>

SoftwareSerial lcd(2,6);
Servo Alpha;
Servo Bravo;

int ledPin = 13;
int joyPin1 = 0;
int joyPin2 = 5;
int value1 = 0;
int value2 = 0;
int value3 = 0;
int value4 = 0;
int AlphaLast = 0;
int BravoLast = 0;



void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(11, OUTPUT);

  Serial.begin(9600);
  Alpha.attach(9);
  Bravo.attach(11);
 
  lcd.begin(9600);
  clearDisplay();
  setLCDCursor(2);
  lcd.print("Hello, world");
  setLCDCursor(16);
  lcd.print(" Running Monitor");
}

void loop() {
  value1 = analogRead(joyPin1);   
  delay(100);			  
  value2 = analogRead(joyPin2);   

  Serial.print("J: X = ");
  Serial.print(value1);
  Serial.print(" Y = ");
  Serial.print(value2);

  clearDisplay();
  lcd.print("X: ");
  lcd.print(value1);
  setLCDCursor(7);
  lcd.print("SvA: ");
  lcd.print(AlphaLast);
  setLCDCursor(16);
  lcd.print("Y: ");
  lcd.print(value2);
  setLCDCursor(23);
  lcd.print("SvB: ");
  lcd.print(BravoLast);  
  
  value3 = 0;

  if (value1 < 350 && (value2 > 350 && value2 < 650)) {
    Serial.println(" W");
    value4 = 7;
    value3++;
  }

  if ((value3 == 0) && (value1 < 350 && value2 < 650)) {
    Serial.println(" NW");
    value4 = 8;
  }

  if ((value3 == 0) && (value1 < 350 && value2 > 350)) {
    Serial.println(" SW");
    value4 = 6;
  }

  if ((value1 > 650) && (value2 > 350 && value2 < 650)) {
    Serial.println(" E");
    value4 = 3;
    value3++;
  }

  if ((value3 == 0) && (value1 > 650 && value2 < 650)) {
    Serial.println(" NE");
    value4 = 2;
  }

  if ((value3 == 0) && (value1 > 650 && value2 > 350)) {
    Serial.println(" SE");
    value4 = 4;
  }

  if (value2 > 650 && (value1 > 350 && value1 < 650)) {
    Serial.println(" S");
    value4 = 5;
  }

  if (value2 < 350 && (value1 > 350 && value1 < 650)) {
    Serial.println(" N");
    value4 = 1;
  }

  if ((value1 > 350 && value1 < 650) && (value2 > 350 && value2 < 650)) {
    Serial.println(" Center");
    value4 = 0;
  }
  
  switch (value4) {
    
    case 0:
      Serial.println("Neither Servo Moves");
      break;
    case 1:
      Serial.println("Both Servos moves toward North");
      Alpha.write(0);
      AlphaLast = 0;
      delay(15);
      Bravo.write(180);
      BravoLast = 180;
      delay(15);
      break;
    case 2:
      Serial.println("Only Right Servo moves towards NorthEast");
      Bravo.write(135);
      BravoLast = 135;
      delay(15);
      break;
    case 3:
      Serial.println("Only Right Servo moves towards East");
      Bravo.write(90);
      BravoLast = 90;
      delay(15);
      break;
    case 4:
      Serial.println("Only Right Servo moves towards SouthEast");
      Bravo.write(45);
      BravoLast = 45;
      delay(15);
      break;
    case 5:
      Serial.println("Both Servos move toward South");
      Alpha.write(180);
      AlphaLast = 180;
      delay(15);
      Bravo.write(0);
      BravoLast = 0;
      delay(15);
      break;
    case 6:
      Serial.println("Only Left Servo moves towards SouthWest");
      Alpha.write(45);
      AlphaLast = 45;
      delay(15);
      break;
    case 7:
      Serial.println("Only Left Servo moves towards West");
      Alpha.write(90);
      AlphaLast = 90;
      delay(15);
      break;
    case 8:
      Serial.println("Only Left Servo moves towards NorthWest");
      Alpha.write(135);
      AlphaLast = 135;
      delay(15);
      break;
    default:
      Serial.println("No Instruction Received");
    
  }
  
    
  delay(500);


}

void clearDisplay()
{
    lcd.write(0xFE);  // send the special command
    lcd.write(0x01);  // send the clear screen command
}

void setLCDCursor(byte cursor_position)
{
    lcd.write(0xFE);  // send the special command
    lcd.write(0x80);  // send the set cursor command
    lcd.write(cursor_position);  // send the cursor position
}

Moderator edit: code tags added

Dain: The servos are not powered by the Arduino Uno r3. While it might be a power based problem I believe I have ruled that out as if I change the value of the delay at the end of the loop, the delay between twitches changes accordingly.

Running the servos on separate power is fine, but the Arduino and servos do need to share common ground to have a clear signal. IE your Arduino ground needs to be tied to your servo power ground.

  value1 = analogRead(joyPin1);   
  delay(100);            
  value2 = analogRead(joyPin2);   

  Serial.print("J: X = ");
  Serial.print(value1);
  Serial.print(" Y = ");
  Serial.print(value2);

Meaningful names would be helpful. Something like valueX and valueY, maybe. value3 and value4 don't mean anything, either,

  Serial.begin(9600);

You can send data to the Serial Monitor 12 times this fast. That makes the communication take 1/12th as long.

jraskell: Running the servos on separate power is fine, but the Arduino and servos do need to share common ground to have a clear signal. IE your Arduino ground needs to be tied to your servo power ground.

I have the ground on a common bus on the breadboard, I'll be using a LiPro shield once I get the proof of concept down.

Arduino IDE version?

PaulS: Meaningful names would be helpful. Something like valueX and valueY, maybe. value3 and value4 don't mean anything, either,

...snip...

You can send data to the Serial Monitor 12 times this fast. That makes the communication take 1/12th as long.

Scavenged code is scavenged. I'm trying to sort out the proof of concept before I spend much effort on prettin' up the code, I don't want to be stuck with the delay()'s as it is... I understand your complaint on my lazy.programming.protocols. If it matters Value3 is simply a semaphore to let the obtuse IF logic tree determine if a vector had been decided on. Value4 stores what Logic decision was made for a SWITCH/CASE structure that does the work of assigning what angle(s) to assign to which servo. Personally, I'm trying to learn enough trig to try and tackle sine, cosine, and tangent allow with their arc variants and various Radian computations so that I can ditch the cardinal logic with the servos and have one joystick set a bearing that will control both servos.

As for speeding up the serial transfer, sure... But if it doesn't do what I want at 9600 why should I have it not work at tweleve times that speed? grin Its sorta a crawl before you run a marathon sorta mentality.

In truth, I'm trying to figure out why it seems the servos twitch at the top of the loop() because when I translate into using millis() and away from delay() if the servos need to be idle at current position and they twitch at the top of the loop() while waiting for the next input, it sorta ruins the soup. Incidentally, if the root cause of the twitch could be isolated and demostrated on demand, that would be useful too, though its more of a 'would be nice if' rather than a mission-killer.

I'm using the 1.0 IDE running on OSX 10.7.3

Dain

Incidentally, if the root cause of the twitch could be isolated and demostrated on demand, that would be useful too, though its more of a ‘would be nice if’ rather than a mission-killer.

The way to handle that situation is to comment-out code until the problem disappears. The last thing removed is the most likely culprit. I suggest starting with SoftwareSerial / lcd. Comment-out the declaration and let the compiler lead you through the rest…

// SoftwareSerial lcd(2,6);

I'm trying to sort out the proof of concept before I spend much effort on prettin' up the code

It takes no more time to pick a meaningful name than it does to pick a useless name. If you find yourself unable to come up with a meaningful name, that's a clue that you are going in the wrong direction/don't understand the problem. The thing to do is to stop, not to pick a meaningless name and think that you'll "pretty it up" later. Because, you won't.

The next time you look at the code, it won't make any more sense then, either.

You can spend 10 minutes now, using ctrl-H and changing useless names to meaningful names, OR you can continue to struggle with the useless names. Your choice.

PaulS:

I’m trying to sort out the proof of concept…

…using ctrl-H and changing useless names to meaningful names, OR you can continue to struggle with the useless names. Your choice.

Ctrl-H hides windows on MacOS, I fail to see how that is helpful.

I wasn’t struggling with useless names. I was struggling with my servos twitching at the start (or end) of every loop() whether or not they had been given an instruction in any particular loop().

Now that I’ve renamed the ambiguous variables (this reply with the new code with comments exceeds 9500 characters, the forum won’t take it, I also find it ironic that the IDE’s copy for forum command is broken)… Can we set aside the lazy.code sniping and look at my issue?

If I have borked the way I’m supposed to call the servo library, would that explain the twitch? Is the servo library less than ideal? Is the Arduino’s default PWM frequency and what the Servo looks for having a fight? Is there something other than a pet-peeve wrong with my code?

I need to find out if I can manage the servo twitch, or if I’m stuck with it. $Frustration++;

#include <SoftwareSerial.h>
#include <Servo.h>

SoftwareSerial lcd(2,6);
Servo Alpha;
Servo Bravo;

int joyPin1 = 0;
int joyPin2 = 5;
int RawJoyX = 0;
int RawJoyY = 0;
int LogicToken1 = 0;  // PaulS's Renamed Logic Tree Semaphore
int CardAction = 0;   // Cardinal Action to be given to the Servos
int AlphaLast = 0;
int BravoLast = 0;



void setup() {
  pinMode(6, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(11, OUTPUT);

  Serial.begin(9600);  // Yes, I'm still doing this slow
  Alpha.attach(9);
  Bravo.attach(11);

  lcd.begin(9600);
  clearDisplay();
  setLCDCursor(2);
  lcd.print("Joystick-->Servo");
  setLCDCursor(16);
  lcd.print("Rotation Monitor");
  delay(500);          // Its nice to see the splash screen

}

void loop() {
  RawJoyX = analogRead(joyPin1);
  delay(100);
  RawJoyY = analogRead(joyPin2);

  clearDisplay();
  lcd.print("X: ");
  lcd.print(RawJoyX);
  setLCDCursor(7);
  lcd.print("SvA: ");
  lcd.print(AlphaLast);
  setLCDCursor(16);
  lcd.print("Y: ");
  lcd.print(RawJoyY);
  setLCDCursor(23);
  lcd.print("SvB: ");
  lcd.print(BravoLast);

  LogicToken1 = 0;

  if (RawJoyX < 400 && (RawJoyY > 400 && RawJoyY < 600)) {
    CardAction = 7; // West
    LogicToken1++;
  }

  if ((LogicToken1 == 0) && (RawJoyX < 400 && RawJoyY < 600)) {
    CardAction = 8; // NorthWest
  }

  if ((LogicToken1 == 0) && (RawJoyX < 400 && RawJoyY > 400)) {
    CardAction = 6; // SouthWest
  }

  if ((RawJoyX > 600) && (RawJoyY > 400 && RawJoyY < 600)) {
    CardAction = 3; // East
    LogicToken1++;
  }

  if ((LogicToken1 == 0) && (RawJoyX > 600 && RawJoyY < 600)) {
    CardAction = 2; // NorthEast
  }

  if ((LogicToken1 == 0) && (RawJoyX > 600 && RawJoyY > 400)) {
    CardAction = 4; // SouthEast
  }

  if (RawJoyY > 600 && (RawJoyX > 400 && RawJoyX < 600)) {
    CardAction = 5; // South
  }

  if (RawJoyY < 400 && (RawJoyX > 400 && RawJoyX < 600)) {
    CardAction = 1; // North
  }

  if ((RawJoyX > 400 && RawJoyX < 600) && (RawJoyY > 400 && RawJoyY < 600)) {
    CardAction = 0; // Center -- reserved for a soft-reset
  }

  switch (CardAction) {

  case 0:
    // Neither Servo Moves
    break;
  case 1:
    // Both Servos moves toward North
    Alpha.write(0);
    AlphaLast = 0;
    delay(15);
    Bravo.write(180);
    BravoLast = 180;
    break;
  case 2:
    // Only Servo Bravo moves towards NorthEast
    Bravo.write(135);
    BravoLast = 135;
    delay(15);
    break;
  case 3:
    // Only Servo Bravo moves towards East
    Bravo.write(90);
    BravoLast = 90;
    delay(15);
    break;
  case 4:
    // Only Servo Bravo moves towards SouthEast
    Bravo.write(45);
    BravoLast = 45;
    delay(15);
    break;
  case 5:
    // Both Servos move toward South
    Alpha.write(180);
    AlphaLast = 180;
    delay(15);
    Bravo.write(0);
    BravoLast = 0;
    break;
  case 6:
    // Only Servo Alpha moves towards SouthWest
    Alpha.write(45);
    AlphaLast = 45;
    delay(15);
    break;
  case 7:
    // Only Servo Alpha moves towards West
    Alpha.write(90);
    AlphaLast = 90;
    delay(15);
    break;
  case 8:
    // Only Servo Alpha moves towards NorthWest
    Alpha.write(135);
    AlphaLast = 135;
    delay(15);
    break;
  default:
    // Servos at-rest at current bearing
    delay(15);

  }


  delay(1000);  //This will get replaced with millis() for final production.


}

void clearDisplay()
{
  lcd.write(0xFE);
  lcd.write(0x01);
}

void setLCDCursor(byte cursor_position)
{
  lcd.write(0xFE);
  lcd.write(0x80);
  lcd.write(cursor_position);
}

I’d set CardAction to zero in loop before you have all those ifs - in case that logic leaves it non-zero. Not that that should make the motors twitch.

This doesn’t look right:

  if (RawJoyX < 400 && (RawJoyY > 400 && RawJoyY < 600)) 
 {
    CardAction = 7; // West
    LogicToken1++;
  }

  if ((LogicToken1 == 0) && (RawJoyX < 400 && RawJoyY < 600)) {
    CardAction = 8; // NorthWest
  }

Looks like there’s a typo there somewhere - as it is, you will never go west, it’ll always overrride to North west.

wildbill:
I’d set CardAction to zero in loop before you have all those ifs - in case that logic leaves it non-zero. Not that that should make the motors twitch.

Considering I reset my LogicToken but not my ActionToken… Gotcha, fixed.

if (RawJoyX < 400 && (RawJoyY > 400 && RawJoyY < 600))
{
CardAction = 7; // West
LogicToken1++;
}

if ((LogicToken1 == 0) && (RawJoyX < 400 && RawJoyY < 600)) {
CardAction = 8; // NorthWest
}

Looks like there’s a typo there somewhere - as it is, you will never go west, it’ll always overrride to North west.

It does work. The joystick I’m using has a ugly dead-zone, and since I don’t really need high precision to get only eight cardinal points I can afford to be generous with the dead zone.

In the First-IF, The joystick X-axis has to be registering a leftward datum AND the Y-axis must not be registering either a upwards or downwards datum. If the First-IF tests true, it sets the appropriate CardAction and increments the LogicToken (to a value greater than zero). If the First-IF does not test true, it does nothing and moves to the next IF.

In the Second-IF, the LogicToken must equal zero AND the X-axis register leftward datum & the Y-axis register downward datum. If the First-IF tested true, LogicToken does not equal zero and the Second-IF cannot test true, so the program skips it and moves on to the next IF.

This LogicToken test is only needed on the Sub-Cardinals (NW, NE, SE, & SW). The Prime-Cardinals are tested for in a similar fashion but since the off-axis must be in the dead-zone it doesn’t need an external logic-gate to prevent the intended process from being overridden by a later one. I can’t use IF-ELSE here either because I’ll run into the same problems. I suppose I could use a SWITCH-CASE tree for both the detection and application, but I don’t care to bloat out each CASE on the SWITCH. It gets harder to debug when your typo in one of ten CASES only appears once and you fail to test that CASE enough to find it the easy way.

Dain

When RawJoyX is exactly 400, what is supposed to happen?

When RawJoyX is exactly 600, what is supposed to happen?

When RawJoyY is exactly 400, what is supposed to happen?

When RawJoyY is exactly 600, what is supposed to happen?

I’ll faint. Even if it does on one pass, the el cheapo pots on this joystick fluctuate fair too much for me to worry about this. Even so, it still does not explain the servo twitch.

I’ll add a handful of equal signs on the tests… There…

A quick search brought up several results indicating a compatibility issue between the servo and softwareserial libraries (ie servos twitching when using the softwareserial port) Sounds very similar to your problem. Nothing indicated a solution to this issue short of detaching the servos when using the softwareserial port, then attaching when changing position of the servos.

I'll add a handful of equal signs on the tests.... There...

If you change the code, no matter how minor the change, and do not republish, I stop helping. I suspect there are others who share my attitude.

compatibility issue between the servo and softwareserial

Huh. Sounds familiar. Let's see if I can find that post. There it is... http://arduino.cc/forum/index.php/topic,101808.msg765237.html#msg765237

[quote author=Coding Badly link=topic=101808.msg766096#msg766096 date=1334859646] Huh. Sounds familiar. Let's see if I can find that post. There it is... http://arduino.cc/forum/index.php/topic,101808.msg765237.html#msg765237 [/quote]

Your post was what tweaked my memory on the issue. I was just more explicit about it.

Alright… My frustration at being dumped into this board by a mod and getting Programming help that felt like step #15 when I was on step#2 aside… I apologize if I have offended you or anyone else. I did not repost the code because I was 1) answering as I was packing down and 2) hadn’t actually done anything to the code yet. Just made a note to translate my Greater-thans and Lesser-thans to Greater-or-Equal-to’s and Lesser-or-Equal-to’s. My attempt at tension reducing humor fell similarly flat. me() != Perfect.

compatibility issue between the servo and softwareserial

I hadn’t figured out how to answer that post while maintaining a reasonable level of !snarky(). While I had gotten my hackles up, I was trying to refrain from outward flameyness, anger, and other associated social ills.

I added the LCD package to try and diagnose the twitching. Since the twitching was there before the LCD and its associated softwareserial.h I didn’t see a reason to strip it out and try again. Although I agree with the methodology as suggested.

In deeper searches that I wasn’t sure were germane to my issue, I’ve seen notations on pins 9 and 10 causing issues with Timers… Thinking this had to do with Millis() and Micros(), I kept looking.

So if I deduce that using Delay() uses the default timer, then using a servo on pin 9 or 10, may well be the genesis of the issue. If the servo twitches when the timer at the end of the loop lets go, it would explain much, especially how the twitches seem to mirror the start of the loop(). I had tried commenting out the delay and letting the loop() without one, and it twitched constantly, I could still order the servos with the joystick per the code, but the results were not desirable. But there are other delays in the code that don’t seem to trigger a twitch… Come to think on it, I could see the screen on the LCD react at the same rough time as the servo twitching. Still servo Alpha twitches much more than Bravo. Alpha is on pin9 and Bravo is on Pin11, but since its tied to a common ground a noisy signature from the timer, could still be at blame.

When I get a chance to dig my hobby box back out (when your day job is an OTR trucker, life gets interesting… Have you ever tried soldering at 65 MPH?) and put the pieces back together, I’ll see if I can get different results with either swapping pins on my Uno (far more desirable, as I like simple (well, simpler in this case) code or detaching the servos when I’m finished with them (adds a level of complexity to the code), by writing a function to call when the servo(s) need to move.

Most current version of the code follows

#include <SoftwareSerial.h>
#include <Servo.h>

SoftwareSerial lcd(2,6);
Servo Alpha;
Servo Bravo;

int joyPin1 = 0;      // AnalogPin 0
int joyPin2 = 5;      // AnalogPin 5 -- Might try and change this if I end up with a different joystick
int RawJoyX = 0;
int RawJoyY = 0;
int LogicToken1 = 0;  // Logic IF Tree Semaphore
int CardAction = 0;   // Cardinal Action to be given to the Servos
int AlphaLast = 0;
int BravoLast = 0;



void setup() {
  pinMode(6, OUTPUT);  // Will try moving this to Pin3
  pinMode(9, OUTPUT);  // Will try moving this to Pin5
  pinMode(11, OUTPUT); // Will try moving this to Pin6

  Serial.begin(9600);  // Yes, I'm still doing this slow
  Alpha.attach(9);     
  Bravo.attach(11);

  lcd.begin(9600);
  clearDisplay();
  setLCDCursor(2);
  lcd.print("Joystick-->Servo");
  setLCDCursor(16);
  lcd.print("Rotation Monitor");
  delay(500);          // Its nice to see the splash screen

}

void loop() {
  RawJoyX = analogRead(joyPin1);
  delay(100);
  RawJoyY = analogRead(joyPin2);

  clearDisplay();
  lcd.print("X: ");
  lcd.print(RawJoyX);
  setLCDCursor(7);
  lcd.print("SvA: ");
  lcd.print(AlphaLast);
  setLCDCursor(16);
  lcd.print("Y: ");
  lcd.print(RawJoyY);
  setLCDCursor(23);
  lcd.print("SvB: ");
  lcd.print(BravoLast);

  LogicToken1 = 0;
  CardAction = 0; // On second thought, not sure resetting this is nessisary...
  //because the state is implicit, and the SWITCH has a default fallback.
  //If nothing else, the loop falls through and waits for the next iteration.

  if (RawJoyX <= 400 && (RawJoyY >= 400 && RawJoyY <= 600)) {
    CardAction = 7; // West
    LogicToken1++;
  }

  if ((LogicToken1 == 0) && (RawJoyX <= 400 && RawJoyY <= 600)) {
    CardAction = 8; // NorthWest
  }

  if ((LogicToken1 == 0) && (RawJoyX <= 400 && RawJoyY >= 400)) {
    CardAction = 6; // SouthWest
  }

  if ((RawJoyX >= 600) && (RawJoyY >= 400 && RawJoyY <= 600)) {
    CardAction = 3; // East
    LogicToken1++;
  }

  if ((LogicToken1 == 0) && (RawJoyX >= 600 && RawJoyY <= 600)) {
    CardAction = 2; // NorthEast
  }

  if ((LogicToken1 == 0) && (RawJoyX >= 600 && RawJoyY >= 400)) {
    CardAction = 4; // SouthEast
  }

  if (RawJoyY >= 600 && (RawJoyX >= 400 && RawJoyX <= 600)) {
    CardAction = 5; // South
  }

  if (RawJoyY <= 400 && (RawJoyX >= 400 && RawJoyX <= 600)) {
    CardAction = 1; // North
  }

  if ((RawJoyX >= 400 && RawJoyX <= 600) && (RawJoyY >= 400 && RawJoyY <= 600)) {
    CardAction = 0; // Center -- reserved for a soft-reset
  }

  switch (CardAction) {

  case 0:
    // Neither Servo Moves
    break;
  case 1:
    // Both Servos moves toward North
    Alpha.write(0);
    AlphaLast = 0;
    delay(15);
    Bravo.write(180);
    BravoLast = 180;
    break;
  case 2:
    // Only Servo Bravo moves towards NorthEast
    Bravo.write(135);
    BravoLast = 135;
    delay(15);
    break;
  case 3:
    // Only Servo Bravo moves towards East
    Bravo.write(90);
    BravoLast = 90;
    delay(15);
    break;
  case 4:
    // Only Servo Bravo moves towards SouthEast
    Bravo.write(45);
    BravoLast = 45;
    delay(15);
    break;
  case 5:
    // Both Servos move toward South
    Alpha.write(180);
    AlphaLast = 180;
    delay(15);
    Bravo.write(0);
    BravoLast = 0;
    break;
  case 6:
    // Only Servo Alpha moves towards SouthWest
    Alpha.write(45);
    AlphaLast = 45;
    delay(15);
    break;
  case 7:
    // Only Servo Alpha moves towards West
    Alpha.write(90);
    AlphaLast = 90;
    delay(15);
    break;
  case 8:
    // Only Servo Alpha moves towards NorthWest
    Alpha.write(135);
    AlphaLast = 135;
    delay(15);
    break;
  default:
    // Servos at-rest at current bearing
    delay(15);

  }


  delay(1000);  //This will get replaced with millis() for final production.


}

void clearDisplay()
{
  lcd.write(0xFE);
  lcd.write(0x01);
}

void setLCDCursor(byte cursor_position)
{
  lcd.write(0xFE);
  lcd.write(0x80);
  lcd.write(cursor_position);
}

I’ve pulled the code for writing to the servos out and nested it into a function… I think. Writing functions are a bit new to me.

void RotServo()
{
  if (AlphaNew != AlphaLast) {
    Alpha.attach(9);
    Alpha.write(AlphaNew);
    AlphaLast = AlphaNew;
    Alpha.detach();
    delay(15);
  }
  if (BravoNew != BravoLast) {
    Bravo.attach(11);
    Bravo.write(BravoNew);
    BravoLast = BravoNew;
    Bravo.detach();
    delay(15);
  }
}

Now you can see I’ve added two new varibles and the function simply tests to see if it has new data to apply, then attach()es, sends the new positon to change to, detach()es, and exits. The more and more I move towards millis() and away from delay() for the main loop the more and more this looks to make better code as well as sense.

Now the compiler has given it a pass, but I’ve not had a chance to dig out the hardward and do a function test on it yet. Speaking of hardware, I’ve spent an hour wrangling with Friziting to outline what my project looks like. I’ll grant you, the Medusa’s head of jumpers and such I last had put together looked a far cry from this orderly ideal.

Current code follows.

#include <SoftwareSerial.h>
#include <Servo.h>

SoftwareSerial lcd(2,6);
Servo Alpha;
Servo Bravo;

int joyPin1 = 0;      // AnalogPin 0
int joyPin2 = 5;      // AnalogPin 5 -- Might try and change this if I end up with a different joystick
int RawJoyX = 0;
int RawJoyY = 0;
int LogicToken1 = 0;  // Logic IF Tree Semaphore
int CardAction = 0;   // Cardinal Action to be given to the Servos
int AlphaLast = 0;
int AlphaNew = 0;
int BravoLast = 0;
int BravoNew = 0;



void setup() {
  pinMode(6, OUTPUT);  // Will try moving this to Pin3
  pinMode(9, OUTPUT);  // Will try moving this to Pin5
  pinMode(11, OUTPUT); // Will try moving this to Pin6

  Serial.begin(9600);  // Yes, I'm still doing this slow
  //Alpha.attach(9);     
  //Bravo.attach(11);

  lcd.begin(9600);
  clearDisplay();
  setLCDCursor(2);
  lcd.print("Joystick-->Servo");
  setLCDCursor(16);
  lcd.print("Rotation Monitor");
  delay(500);          // Its nice to see the splash screen

}

void loop() {
  RawJoyX = analogRead(joyPin1);
  delay(100);
  RawJoyY = analogRead(joyPin2);

  clearDisplay();
  lcd.print("X: ");
  lcd.print(RawJoyX);
  setLCDCursor(7);
  lcd.print("SvA: ");
  lcd.print(AlphaLast);
  setLCDCursor(16);
  lcd.print("Y: ");
  lcd.print(RawJoyY);
  setLCDCursor(23);
  lcd.print("SvB: ");
  lcd.print(BravoLast);

  LogicToken1 = 0;
  CardAction = 0; // On second thought, not sure resetting this is nessisary...
  //because the state is implicit, and the SWITCH has a default fallback.
  //If nothing else, the loop falls through and waits for the next iteration.

  if (RawJoyX <= 400 && (RawJoyY >= 400 && RawJoyY <= 600)) {
    CardAction = 7; // West
    LogicToken1++;
  }

  if ((LogicToken1 == 0) && (RawJoyX <= 400 && RawJoyY <= 600)) {
    CardAction = 8; // NorthWest
  }

  if ((LogicToken1 == 0) && (RawJoyX <= 400 && RawJoyY >= 400)) {
    CardAction = 6; // SouthWest
  }

  if ((RawJoyX >= 600) && (RawJoyY >= 400 && RawJoyY <= 600)) {
    CardAction = 3; // East
    LogicToken1++;
  }

  if ((LogicToken1 == 0) && (RawJoyX >= 600 && RawJoyY <= 600)) {
    CardAction = 2; // NorthEast
  }

  if ((LogicToken1 == 0) && (RawJoyX >= 600 && RawJoyY >= 400)) {
    CardAction = 4; // SouthEast
  }

  if (RawJoyY >= 600 && (RawJoyX >= 400 && RawJoyX <= 600)) {
    CardAction = 5; // South
  }

  if (RawJoyY <= 400 && (RawJoyX >= 400 && RawJoyX <= 600)) {
    CardAction = 1; // North
  }

  if ((RawJoyX >= 400 && RawJoyX <= 600) && (RawJoyY >= 400 && RawJoyY <= 600)) {
    CardAction = 0; // Center -- reserved for a soft-reset
  }

  switch (CardAction) {

  case 0:
    // Neither Servo Moves
    break;
  case 1:
    // Both Servos moves toward North
    AlphaNew = 0;
    BravoNew = 0;
    break;
  case 2:
    // Only Servo Bravo moves towards NorthEast
    BravoNew = 135;
    break;
  case 3:
    // Only Servo Bravo moves towards East
    BravoNew = 90;
    break;
  case 4:
    // Only Servo Bravo moves towards SouthEast
    BravoNew = 45;
    break;
  case 5:
    // Both Servos move toward South
    AlphaNew = 180;
    BravoNew = 0;
    break;
  case 6:
    // Only Servo Alpha moves towards SouthWest
    AlphaNew = 45;
    break;
  case 7:
    // Only Servo Alpha moves towards West
    AlphaNew = 90;
    break;
  case 8:
    // Only Servo Alpha moves towards NorthWest
    AlphaNew = 135;
    break;
  default:
    // Servos at-rest at current bearing
    delay(1);

  }


  RotServo();
  delay(1000);  //This will get replaced with millis() for final production.


}

void clearDisplay()
{
  lcd.write(0xFE);
  lcd.write(0x01);
}

void setLCDCursor(byte cursor_position)
{
  lcd.write(0xFE);
  lcd.write(0x80);
  lcd.write(cursor_position);
}

void RotServo()
{
  if (AlphaNew != AlphaLast) {
    Alpha.attach(9);
    Alpha.write(AlphaNew);
    AlphaLast = AlphaNew;
    Alpha.detach();
    delay(15);
  }
  if (BravoNew != BravoLast) {
    Bravo.attach(11);
    Bravo.write(BravoNew);
    BravoLast = BravoNew;
    Bravo.detach();
    delay(15);
  }
}

Bear in mind that after you call detach, the signal output to the servo stops. With the attach and detach calls so close together I doubt the servos will even move.

Before you apply any fixes (like attach + detach), you need to first determine what is actually causing the problem. While it is likely that SoftwareSerial and Servo are interfering with each other it is possible the problem lies elsewhere. Which is why I suggested temporarily removing lcd. If the problem disappears, that was the culprit. If not, you know to continue searching.

If the problem is SoftwareSerial / Servo interference, Mikal Hart recommended an alternative servo library. Search for "@Conrad,"... http://arduiniana.org/libraries/newsoftserial/