Software comparator - Antenna Rotor Program

Hi guys;

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).

@johnwasser

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 doing my best at my programing skills here.

Your doing fine. First you did correctly identify a weakness in your control code and know you know a method for dealing with it.

Lefty

@retrolefty

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.

I did the exact same thing for someone on A dutch forum with the same problem.
http://www.zendamateur.com/viewtopic.php?f=11&t=7439&start=15

    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);
    }

edit: translated comments in the code to english

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.