I need some help in programming here. I made a small program to control an antenna using : A motor, a feedback pot and a pot to select the direction of the antenna. <-- That the project, but for now I tested using 2 leds, and 2 pot of 50 K. My program work, but a closed loop system, there are a risk of oscillations ( motor on/off ) Let face it, in reality, it is hard that two pot to be EXACT - valueA == valueB So the solution is the stop the motor WITHIN a range of a value. example 1 <-- value --> 1.
My question is : How do you program this "range" in a if () statment. I try in my program by using OR ||. I use a +/- 1. But I don't know how the place a value within a bigger range ex : +/- 2 or more.
Here my code so far:
/*
Version 1.0
It will have a PICAXE version using PICAXE-08/08M
size = 1542
Program to control an outdoor antenna
using degree setting has an input ( a potentiometer )
and the motor will set to that angle using a feedback potentiometer
Need : Need for Testing:
A motor - strong type 2 LED
A few gears. 2 330 resistor
1 relay SPDT 2 50 K small pot
1 relay DPDT
2 1N4001
2 2N3904 - NPN type
2 4.7 K resistor
2 50 K potentiometer
Control Box will be indoor.
Motor,gears and 1 pot will be a box outdoor
Created by Serge J Desjardins aka techone
Compiled and Tested ( with a test circuit )
Based on a closed loop system
http://en.wikipedia.org/wiki/Control_theory
*/
byte motor=12; // Motor control pin
byte dir=11; // Direction control pin
byte feedpin=0; // Feedback potentiometer pin
byte setdegreepin=1; // Degree Setting potentiometer pin
unsigned int feedbackdegree=0; // Feebback value
unsigned int degreein=0; // Degree setting value
void setup()
{ // Init the out pins and set motor off
pinMode(motor,OUTPUT);
pinMode(dir,OUTPUT);
digitalWrite(motor, LOW);
}
void loop()
{
// read the voltage from Degree Setting pot
degreein=analogRead(setdegreepin);
// read the voltage from the feedback pot
feedbackdegree=analogRead(feedpin);
// convert input value to degree
degreein=map(degreein, 0,1023,0,180);
feedbackdegree=map(feedbackdegree, 0,1023,0,180);
/* degree setting is equal to the feedback
turn off motor
I give a tolerance of +/- 1 degree
to prevent an oscillation condition.
*/
//That is the section I need help. A range setting
if ((degreein==(feedbackdegree-1))||(degreein==feedbackdegree)||(degreein==(feedbackdegree+1)))
{
digitalWrite(motor, LOW);
}
else
{
// turn on motor and turn counter clock wise
if (degreein > feedbackdegree)
{
digitalWrite(motor, HIGH);
digitalWrite(dir, HIGH);
}
// turn on motor and turn clock wise
if (degreein < feedbackdegree)
{
digitalWrite(motor, HIGH);
digitalWrite(dir, LOW);
}
}
}
const int delta = 3;
//That is the section I need help. A range setting
if ((degreein >= (feedbackdegree-delta) && degreein <= (feedbackdegree + delta))
For example if feedbackdegree is 90 then the 'if' will be true if degree is >= 87 and degree <= 93 (values from 87 to 93, inclusive).
Thank for that tip. So you use <= , >= and &&. OK I get it. Let say degreein is 25 and feedbackdegree is 90, that if stement will be False ---> False AND True = False. Yep, like a AND gate. OK, so the motor will be going until it reach the degree I set. ei : 25 +/- delta. I assume "delta" is the "tolerance" , the +/-.
Thank you. The new change will help eliminate the oscillation problem. Because my initial program line was :
if (degreein==feedbackdegree) // Hard to get EXACT values using a normal potentiometer.
{
digitalWrite(motor, LOW);
}
I bet you can "see" the oscillation problem occuring.
Here why : analog pin - 5 Vto 0 V. analog value of analogRead() - 0 to 1023 so 5 V / 1023 = 4.887585 mV / step
value = map (value, 0,1023,0,180); That line use the ratio formula x/y = a/b --> x / 1023 = 1 / 180
x = 5.68333333 round off x = 5 step = 1 degree so 5 step = 24.437927 mV.
Conclusion : It is hard to be THAT precicise using a normal potentiometer. Maybe a multiturn pot is possible.
That is why I need that if statement line using a range.
I am doing my best at my programing skills here.
Sorry that I am explaining to myself here. It will help others when they read this post.
I am trying to do my projects with the best of my abilities, using my limited resources ( $$$), limited tools, using my arsenals of Electronics magazines, Texts Books from my college days ( Texts books from my DeVry classes ) , my old job ( Elec Bench Tech ) and the Internet. I also baught a few new books ( my lattest is Robot Building Bonanza, 4th ed. I have the 1st ed. Lots of changes ). As for programming, I do have a few books too ( Pascal, C, Basic, Assembler - 80XXX, old assembler - 8085, 6809 ). I also recently baught Arduino Cookbook and Begining Arduino. <---- Sorry to be off topic.
Thank for the vote of confidance, retrolefty.
Has for my project, The Antenna Controller will work better with the new program ( software control feedback ), and it is also a good "servo" programm, because my design copy a servo design except it will not use pulses to control it, just a pot ( voltage into a n analog pin ). The challenge in this project will be choosing the proper motor and to choose the "right" set of gears and "hook it" to the feedback pot. Because motor goes fast, it need to be reduce, ( I wil try to "reverse" engineer a servo by measuring the diameter of the gear set of the servo ). And some hardwares to hook the antenna. I few trip to the nearest hardware store and a surplus store to give me a few ideas how to do this project.
const int sensorPin1= A0; // potmeter 1
const int sensorPin2=A1; // potmeter 2
int diff = 5; //differentie
void setup() {
Serial.begin(9600);
//set output pins 11 up, 12 down, 13 motor enable
pinMode(11, OUTPUT); // motor left
pinMode(12, OUTPUT); //motor right
pinMode(13, OUTPUT); //motor enable
}
void loop() {
int Val1 = analogRead(sensorPin1); // value pot 1
Serial.println(Val1);//print value off potmeter 1
int Val2 = analogRead(sensorPin2); // value pot 2
Serial.println(Val2);//print value pot 2
//if pot2 is lower than pot 1 -diff , 11 high and 13 high
if (Val2<Val1-diff) {
digitalWrite (11, HIGH);
digitalWrite (12, LOW);
digitalWrite (13, HIGH);
Serial.println("up");
}
//if pot2 is bigger than pot 1 +diff, 12 high and 13 high
else if (Val2>Val1+diff) {
digitalWrite (11, LOW);
digitalWrite (12, HIGH);
digitalWrite (13, HIGH);
Serial.println("down");
}
// in all other cases everything off
else {
digitalWrite (11, LOW);
digitalWrite (12, LOW);
digitalWrite (13, LOW);
Serial.println("ok");
}
//serial line ofr end of loop
Serial.println();
//use A higher delay to read serial for debugging
delay (0);
}
If you want to get fancy you can use a PWM 'analog' output to control speed and proportional control to have the motor slow down as it approaches the target value:
void loop()
{
unsigned targetValue = analogRead(targetPot);
unsigned positionValue = analogRead(positionPot);
if (positionValue < targetValue)
{
// Need to move forward
int error = targetValue - positionValue;
int speed = constrain(error, 0, 255); // PWM output is limited to 0 to 255
analogWrite(PWMpin, speed);
digitalWrite(directionPin, HIGH); // Forward motion
}
if (positionValue > targetValue)
{
// Need to move in reverse
int error = positionValue - targetValue;
int speed = constrain(error, 0, 255); // PWM output is limited to 0 to 255
analogWrite(PWMpin, speed);
digitalWrite(directionPin, LOW); // Reverse motion
}
}
You can multiply 'error' by a constant if the motor doesn't slow down early enough.
You can divide 'error' by a constant if the motor slows down too early.