Hello all,
I am fairly new to coding in C and i've got a school engineering project that i need help with.
I have 3D printed an artificial horizon which i have connected to servos and made it follow a control yokes inputs which come from 2 potentiometers.
And this works great, but it isn't how a plane works and as this is a flight simulator i want to to simulate as realistically as possible how a plane flies.
So i want it to do is:
have a deadzone in the centerpoint of the pots
continually move the servos in the direction which the pot is turned until it hits the end of the servos throw using the amount that the pot is turned as a kind of guide for speed (e.g when you move pot half way to the left, servo will move to the left at half speed, move it all the way and it will move at a much higher speed)
Here is a video of the thing in action maybe it will help.
I hope i have explained my problem as best as i could
Servo pitchServo; // create servo object to control a servo
Servo rollServo;
int pitchPin = A0; // analog pin used to connect the potentiometer
int rollPin = A1;
int val; // variable to read the value from the analog pin
void setup()
{
rollServo.attach(10);
pitchServo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop()
{
val = analogRead(pitchPin); // reads the value of the potentiometer (value between 0 and 1023)
val = map(val, 0, 1023, 180, 0); // scale it to use it with the servo (value between 0 and 180)
pitchServo.write(val); // sets the servo position according to the scaled value
delay(15); // waits for the servo to get there
val = analogRead(rollPin);
val = map(val, 0, 1023, 0, 180);
rollServo.write(val);
delay(15);
This is a fairly frequent question with joysticks where the person wants the servo to not follow the joystick when the joystick returns to the neutral position. Below is some test code that incrementally moves a servo when a condition (button press) is detected. You might use something similar with a pot with the servo move direction and speed determined by pot value.
//zoomkat servo button sweep test 12-23-2013
// Powering a servo from the arduino usually *DOES NOT WORK*.
#include <Servo.h>
int button1 = 5; //button pin, connect to ground to move servo
int press1 = 0;
int button2 = 6; //button pin, connect to ground to move servo
int press2 = 0;
Servo servo1;
int pos = 90; // variable to store and set the servo position
void setup()
{
Serial.begin(9600);
pinMode(button1, INPUT);
pinMode(button2, INPUT);
servo1.attach(7);
servo1.write(pos); //starting position
digitalWrite(5, HIGH); //enable pullups to make pin high
digitalWrite(6, HIGH); //enable pullups to make pin high
Serial.println("servo button sweep test 12-23-2013");
}
void loop()
{
press1 = digitalRead(button1);
if (press1 == LOW)
{
pos=(pos+1);
if(pos>180) pos=180; //limit upper value
Serial.println(pos); //for serial monitor debug
servo1.write(pos); // tell servo to go to position in variable 'pos'
delay(150); // waits 150ms to slow servo movement
}
press2 = digitalRead(button2);
if (press2 == LOW)
{
pos=(pos-1);
if(pos<0) pos=0; //limit lower value
Serial.println(pos); //for serial monitor debug
servo1.write(pos); // tell servo to go to position in variable 'pos'
delay(150); // waits 150ms to slow servo movement
}
}
Thats exactly what i was looking for Robin2, just now to make it move faster depending on where it is, any ideas how to write that into code?
Edit: I just tried it out on my setup and its very jittery, i guess you lower int servoMove = 3 to make it smoother? Other than that it works basically how i need it, thanks!
Hi Tom,
Yeah I have schematics as i designed and manufactured it all myself, heres some links to photos:
Panel drawn in CAD
Panel laser cut, painted then engraved
White backlighting closeup
Green backlighting closeup
Panel being laser engraved after being painted
Parts of the Artificial Horizon assembly
Enjoy!
If you have facebook it would be cool if you could throw me a like
Ive got other aviation related projects on there that i designed and made like a 1:55 scale Boeing 777-200
737_Sim_Builder:
Thats exactly what i was looking for Robin2, just now to make it move faster depending on where it is, any ideas how to write that into code?
Use the difference between potValue and potCentre to change the value of servoMove
You need two reference values for the ends of the deadband, if the value is above the top one
then take the difference from the top one, if below the bottom reference, take the difference
from that, else its in the middle, and you call it zero.
Robin2:
Use the difference between potValue and potCentre to change the value of servoMove
But wont that make the servo jitter as i said before? what if i adjusted the 100ms delay instead? so i can have it move at 1 degree intervals but faster?
Edit: Nevermind, i should test before i speak, lowering the delay to 5ms makes it much smoother regardless of the servoMove value.
MarkT:
You need two reference values for the ends of the deadband, if the value is above the top one
then take the difference from the top one, if below the bottom reference, take the difference
from that, else its in the middle, and you call it zero.
How would i do that with the current code? As i said im fairly new to coding so i don't quite have the hang of it for that
737_Sim_Builder: But wont that make the servo jitter as i said before? what if i adjusted the 100ms delay instead? so i can have it move at 1 degree intervals but faster?
Edit: Nevermind, i should test before i speak, lowering the delay to 5ms makes it much smoother regardless of the servoMove value.
I was going to say that depends on how you write the code - but perhaps you have figured that out.
Robin2:
I was going to say that depends on how you write the code - but perhaps you have figured that out.
i wish i had figured it out, i don't think my problem solving is any good, ill keep working on it but i doubt ill get a good outcome.
Although the only idea i have is to write if statements that say 'if the pot is beyond this certain point, change the servoMove value to 4'
Thats a solution to it though its a bit of a bodge as suddenly at one point of the pots movement the servo will speed up instead of gradually increasing with the pots movements.
737_Sim_Builder:
Although the only idea i have is to write if statements that say 'if the pot is beyond this certain point, change the servoMove value to 4'
That's a perfectly workable solution.
But what about something like
servoMove = (potValue - potCentre) / 32;
which will give a range from 0-16 for pot values from 512 to 1023 and 0 to -16 for the other half (I hope)
You will need to do some expermineting to get exactly what you want. The Arduino system is ideal for experimenting.
737_Sim_Builder:
Bingo, works, well, it does to one side, but to the other you run into a bit of a wall.
I made a spreadsheet that shows clearly what the problem is.
I attached a screenshot of that spreadsheet.
Your picture is exactly what I expected. What is the problem?
Robin2:
Your picture is exactly what I expected. What is the problem?
Well the negatives, you see servoMove dictates at what intervals the servo moves regardless of direction but when you make servoMove a negative number, it makes the servo move in the opposite direction, so what you get is a servo that can only turn to one side. I hope I didn't confuse you Because im sort of confusing myself here.