4 servos, 2 joysticks, last position

Good morning / afternoon:
My BOM for the project:
Arduino UNO
4 servos (TowerPro SG-5010 double ball bearing)
2 Parallax joysticks (# 27800 ver B)
2 Bunkerhill camera.

My objective: To build a pan tilt mechanism, that will move the cameras that are mounted in the direction I request for the purpose of weather monitoring, utilizing the 2 listed joysticks.

What I have been able to do so far.
I was able to obtain a sketch from instructables which was originally written for only 1 joystick and 2 servos. I was able to add to that code to include the additional 2 servos and additional joystick. Credit for the pre-additions of programming can be found here: http://www.instructables.com/id/Arduino-2-Servos-Thumbstick-joystick/
The new programming (aka my additional information), works as required.

Now, what I thought I could simply achieve:
I thought that once I moved the joystick to a certain direction, the servo would stay at that location until I resent another signal.
For example: The servo for panning was looking North (this would be the 90 degree or zero mark of the servo). I want to see what is coming in from the northwest so I would then engage the joystick to pan the camera in that direction, release the joystick and the pan stays locked in that position (again being northwest), until I engaged the joystick to move the servo in a different direction.

What I am finding out:
My “thought” isn’t working, and believe that it is either a coding issue, a joystick issue or both.

Would you please take a look at the following code, again as it is written it works, its just not “locking” the servo in that last position.

Now the code:

#include <Servo.h>

const int servo1 = 3; // first servo
const int servo2 = 11; // second servo
const int servo3 = 6; // third servo
const int servo4 = 10; // fourth servo
const int joyH = 3; // L/R Parallax Thumbstick
const int joyV = 4; // U/D Parallax Thumbstick
const int joyI = 1; // L/R Parallax Thumbstick
const int joyW = 2; // U/D Parallax Thumbstick

int servoVal; // variable to read the value from the analog pin

Servo myservo1; // create servo object to control a servo
Servo myservo2; // create servo object to control a servo
Servo myservo3; // create servo object to control a servo
Servo myservo4; // create servo object to control a servo

void setup() {

// Servo
myservo1.attach(servo1); // attaches the servo
myservo2.attach(servo2); // attaches the servo
myservo3.attach(servo3); // attaches the servo
myservo4.attach(servo4); // attaches the servo

// Inizialize Serial
Serial.begin(9600);
}

void loop(){

// Display Joystick values using the serial monitor
outputJoystick();

// Read the horizontal joystick value (value between 0 and 1023)
servoVal = analogRead(joyH);
servoVal = map(servoVal, 0, 1023, 0, 180); // scale it to use it with the servo (result between 0 and 180)

myservo2.write(servoVal); // sets the servo position according to the scaled value

// Read the horizontal joystick value (value between 0 and 1023)
servoVal = analogRead(joyV);
servoVal = map(servoVal, 0, 1023, 70, 180); // scale it to use it with the servo (result between 70 and 180)

myservo4.write(servoVal); // sets the servo position according to the scaled value

// Read the horizontal joystick value (value between 0 and 1023)
servoVal = analogRead(joyI);
servoVal = map(servoVal, 0, 1023, 70, 180); // scale it to use it with the servo (result between 70 and 180)

myservo1.write(servoVal); // sets the servo position according to the scaled value

// Read the horizontal joystick value (value between 0 and 1023)
servoVal = analogRead(joyW);
servoVal = map(servoVal, 0, 1023, 70, 180); // scale it to use it with the servo (result between 70 and 180)

myservo3.write(servoVal); // sets the servo position according to the scaled value

delay(15); // waits for the servo to get there

}

/**

  • Display joystick values
    */
    void outputJoystick(){

Serial.print(analogRead(joyH));
Serial.print ("---");
Serial.print(analogRead(joyV));
Serial.println ("----------------");
Serial.print(analogRead(joyI));
Serial.print ("---");
Serial.print(analogRead(joyW));
Serial.println ("----------------");

}

Thank you in advance for your assistance.

Tony

I thought that once I moved the joystick to a certain direction, the servo would stay at that location until I resent another signal.

Thing is, you are sending another signal. When you release the joystick and it centres, it's being read almost immediately next time the code runs through loop() again. The joystick's being read all the time and sending the servo to that position every split second.

You could think of moving that pot read / servo write stuff out of loop() and into a piece of code that's in an "if" which runs when a button is pushed. The "if" would have an "else" which is active when the button's released.... at that point the servo isn't moving because the part that makes it move is in the "if" not the "else".

Something like this (very pseudo) code:

void loop()
{
if button is pushed
   read the pot
   write the value to the servo
else 
   run the camera
}

loop() will still run over and over of course, but next time through, if the button isn't pressed, the "else" part of the "if" fires and the camera stays running.

It'll need some more work but that might get you going?

HTH

Would I write the code like this:

void loop()
{
if button is pushed
read the pot
write the value to the servo
else
run the camera
}

// Display Joystick values using the serial monitor
outputJoystick();

// Read the horizontal joystick value (value between 0 and 1023)
servoVal = analogRead(joyH);
servoVal = map(servoVal, 0, 1023, 0, 180); // scale it to use it with the servo (result between 0 and 180)

myservo2.write(servoVal); // sets the servo position according to the scaled value

// Read the horizontal joystick value (value between 0 and 1023)
servoVal = analogRead(joyV);
servoVal = map(servoVal, 0, 1023, 70, 180); // scale it to use it with the servo (result between 70 and 180)

myservo4.write(servoVal); // sets the servo position according to the scaled value

// Read the horizontal joystick value (value between 0 and 1023)
servoVal = analogRead(joyI);
servoVal = map(servoVal, 0, 1023, 70, 180); // scale it to use it with the servo (result between 70 and 180)

myservo1.write(servoVal); // sets the servo position according to the scaled value

// Read the horizontal joystick value (value between 0 and 1023)
servoVal = analogRead(joyW);
servoVal = map(servoVal, 0, 1023, 70, 180); // scale it to use it with the servo (result between 70 and 180)

myservo3.write(servoVal); // sets the servo position according to the scaled value

delay(15); // waits for the servo to get there

}

/**

  • Display joystick values
    */
    void outputJoystick(){

Serial.print(analogRead(joyH));
Serial.print ("---");
Serial.print(analogRead(joyV));
Serial.println ("----------------");
Serial.print(analogRead(joyI));
Serial.print ("---");
Serial.print(analogRead(joyW));
Serial.println ("----------------");

}

Ah sorry, I didn't make it clear what "pseudo code" is.... pseudo code isn't real, it's an outline of what you would code in real code...

So this:

void loop()
{
if button is pushed
   read the pot
   write the value to the servo
else 
   run the camera
}

... isn't real. You need to write the actual code to declare a variable for a button's value, read the button, if it's pushed do "this" else do "that".

Adding to JimboZA's suggestion, you might like to make the servo movements relative to the position of the joystick when the joystick was enabled. In other words, with the joystick in the normal rest position you press the button to engage it and then move it slightly to the left - the servo assembly will move slightly to the left.

With the current approach where the servos follow the absolute position of the joystick, each time you press the button the servos will jump to the current position of the joystick, which might be a long way away from where you left them.

To implement that change would be very simple.

You'd have a variable for each input pot to record the initial position of that pot when the joystick was enabled.

You'd have a variable for each servo to record the initial position of the servo when the joystick was enabled.

The variables above would be updated when the joystick was enabled.

While the joystick was enabled, you'd read the current position of the pot at regular intervals and subtract the initial position to find the offset. You'd scale that offset and add it to the servo's initial position to calculate the servo's new position, and write that to the servo.

I do not think these joysticks are momentary (push button) I do not here a clicking sound, nor can I actually feel anything engage or disengage.

Well you would know since there would be a connection for the button wire as well as the pots.

So is it safe to assume that with out these being momentary joysticks, the projection off holding the last position of the servo is not going to happen.

Well I don't know what a "momentary joystick" is... if you mean one with a thumb press-switch, which is usually used to fire a laser or something, you could easily just wire up a separate switch. Might not be so easy to manipulate of course- need more fingers 8) but you could use a foot switch?- or glue a separate switch on top of the knob.

My objective: To build a pan tilt mechanism, that will move the cameras that are mounted in the direction I request for the purpose of weather monitoring, utilizing the 2 listed joysticks.

Well, you've discovered the problem with using self centering analog joysticks. Some years ago I made a joystick servo based cam pan/tilt setup and used the trigger button press to enter/exit the servo control loop. The disadvantage was matching the previous and current stick positions to prevent the cam from jumping when the trigger was pressed to engage the servos. Possible solutions:

  1. remove the spring returns from the joystick.

  2. use the analog joystick outputs to control left/right servo "sweep" code.

  3. use two individual pots instead of a joystick.

  4. use button/toggle switch to control servo "sweep" code.

  5. Just use two inexpensive servo testers to replace the arduino.

instead of using myservo2.write(servoVal);
you should make int pan = 90; (or tilt) // this centers servos to 90 degrees
then, since you aleady haveservoVal = map(servoVal, 0, 1023, 0, 180); 
simply do this:

if(servoval > 95) // if the mapped joystick value is above 95, increase Pan value
{
pan++;
}
if(servoval < 85) // if the mapped joystick valie is below 85, decrease Pan value
{
pan--;
}
myservo2.write(pan); // move Servo to Pan value

Ok...so ran up to the local Radio Shack here in town. Picked up an imitation PS2 control. I dismantled and now have 2 nice push button joysticks...going to attempt to continue...