Want to turn motor off when it hits 0 degrees or 90 degrees

Hi,

I am controlling a motor driving a gate with a MEMs sensor that will correlate from 0 to 90 degrees from an analog input.

It works fine from the standpoint of moving a gate up and down from 0 to 90 degrees but it wants to keep searching for an exact degree. When the gate gets to position it bounces and the motor continually tries to find 90 or zero. I want it to stop the motor as soon as it hits 90 or zero degrees and let the gate mechanically stabilize without motor help. I think I need to use some flags buy not sure how to code it.

Sid

void Output() //Turns motors on/off based on GC output           
{
    if(digitalRead(Maintenance_Switch)==1) //OFF-             
     {   
        if(gate_control_output ==0)//off - gate goes dn
             {                                             
               if(Degrees > 15)
                    {
                      digitalWrite(Motor_Up_Control,0);
                      analogWrite(Motor_Down_Control,220); 
                    }
//               else if((Degrees <= 15) && (Degrees >=(1)))
                 else if((Degrees <= 15) && (Degrees >=Degrees_Low))
                    {
                      digitalWrite(Motor_Up_Control,0);
                      analogWrite(Motor_Down_Control,120); //pin 
                    }
               else
                    {
                      digitalWrite(Motor_Down_Control,0);
                    }
             }  

         else  //if(gate_control_output ==1)on - gate goes up
             {
                if((Degrees <= (Degrees_High)) && (Degrees >80))
                   {
                     digitalWrite(Motor_Down_Control,0);
                     analogWrite(Motor_Up_Control,120);
                   }
               else if(Degrees <= (Degrees_High))
                   {
                     digitalWrite(Motor_Down_Control,0);
                     analogWrite(Motor_Up_Control,220);
                   }
                else               
                   {
                     digitalWrite(Motor_Up_Control,0);//pin  
                   }
             }




}

can you afford the motor to stop a few degrees out (say 89 to 91) or does it have to be dead on 90 ?

A few degrees out is acceptable.

Gate_Control_Output == 1 brings gate up to 90 and 0 brings gate down to zero degrees.

I would have said that you could try something like this

else if((Degrees <= 15) && ((Degrees +1) >=Degrees_Low) && ((Degrees -1) >=Degrees_Low))

but theres no telling in your code if 0 degrees is binary 0. If it is then it will get unhappy when you go lower than binary 0 as this may cause a problem. if degrees_low was 1 binary then it should work.

else if((Degrees <= 15) && ((Degrees +2) >=Degrees_Low) && ((Degrees ) >=Degrees_Low))

maybe this would be safer to test.

Hi, You need to add some dead band to the end of your travels.

When the gate gets to 90Deg STOP, and make it that you now need the gate at 85Deg to make it close further, this will allow the bounce to occur inside the 5Deg deadband.

Likewise at 0Deg STOP, and make it that you now need the gate at 5Deg to make it close further, this will allow the bounce to occur inside the 5Deg deadband.

Hope it helps.

Tom..... :)

Here is where degrees zero comes from. I know multiple statements here is clumsy but it was quick. Will condense it after I fix my problem in cleanup.

//.......................Calc Degrees............................. MEMS_Count = analogRead(MEMS_Input_A6); //return a count between 0-1023 MEMS_Count = MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count = MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count = MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count = MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count = MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count = MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count = MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count = MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6); MEMS_Count =MEMS_Count + analogRead(MEMS_Input_A6);

MEMS_Count = MEMS_Count/40;

Degrees=map(MEMS_Count,517,722,0,90);// 0-5 volts (counts) to 0-90 Degrees=Degrees-0; //calibrates sensor to a mechanical level input_volts = (MEMS_Count * 5.027) / 1024.0; Serial.println(MEMS_Count); Serial.println(Degrees); //.......................End Calc Degrees.........................

I was getting some motor jitter and doing an average of 40 fixed that problem.

Degrees_High and Degrees_Low are setpoints in case I don't want 0 and 90 degrees. Could be set at 3 degrees and 88 degrees, for example.

I was thinking that if, for example, it bounced between 85 degrees and 92 degrees, as soon as it saw 90, the motor would just stop. The gate would still keep bouncing because of the slop in the mechanical system, but the motor would not be running.

But, when the program loops around again, milliseconds later, it would again start looking for 90 degrees and the motor would start running again.

Once it stops, I do not want the motor to come on again until the Gate_Up_Control==0, telling the gate to come down.

I was getting some motor jitter and doing an average of 40 fixed that problem.

Copying and pasting the code 40 times, instead of using a for loop, borders on the insane.

Very helpful PaulS.

It does work and it was quick and I explained I will streamline it in my cleanup and it has nothing to do with my question. I have bigger fish to fry than trying to make it pretty.

I have bigger fish to fry than trying to make it pretty.

Pretty and maintainable are two different things.

Counting the number of times you pasted the line of code was WAY harder than typing

for(byte i=0; i<40; i++)
{

and

}

God forbid that you should need to do something 938 times.

Thanks for the helpful code. Any ideas on the motor stop?

Sid

Any ideas on the motor stop?

Specifically, what is the problem? You have received suggestions and posted snippets. I can’t tell what code you are actually running, or what it is actually doing, or how that differs from what you want.

Even when using a microprocessor, I would use a limit switch at the top and bottom to indicate we have physically reached the top or bottom.

Hi,

Thanks,

Right now I'm still using the code in the block I submitted. I'm in the middle of modifying it but I have not tried any new code yet. Not sure what I will end up with since I'm looking for input.

Short explanation:

When my gate that crosses a road sees a signal called gate_control_output==0 (binary), it tells the gate to go down to an angle in Degrees that is set in a calibration function as Degrees_Low. Typically zero but may be 1 or 2 degrees, its set visually. Same with Degrees_High. Typically 90 degrees but could be anywhere from 85 to 90 degrees depending if there are obstructions.

The mechanism has some slop in it and I think I need to have some machined parts made to tighter tolerances. It bounces on the way up and down. Maybe a combination of speed, loose tolerances and balance of counter weights.

Right now the program does cause the gate to stop at the high and low set points but since it is bouncing, it keeps on trying to find the setpoints. It takes about 5 to 10 seconds to stop at those setpoints.

What I thought I would do is try to make the motor stop as soon as it sees those setpoints and then not activate the motor again until it sees the opposite gate_control_output signal to make it go down if it is up and vica versa. I may not end up right where I want but I think it will be acceptable.

I was thinking flags are needed but I'm in the middle of thinking about that.

Thanks for your help. I will post my current untried code in a minute.

void Output() //Turns motors on/off based on GC output           
{
    if(digitalRead(Maintenance_Switch)==1) //OFF-             
     {   
//     if(gate_control_output ==0)//off - gate goes dn
       if(gate_control_output ==0) &&  Gate_Status==1  //Gate is up and we bring it down
             {                                             
               if(Degrees > 15)
                    {
                      digitalWrite(Motor_Up_Control,0);
                      analogWrite(Motor_Down_Control,150); 
                    }
//             else if((Degrees <= 15) && (Degrees >=(1)))
//             else if((Degrees <= 15) && (Degrees >=Degrees_Low))
               else if((Degrees <= 15) && (Degrees >Degrees_Low))
                    {
                      digitalWrite(Motor_Up_Control,0);
                      analogWrite(Motor_Down_Control,110); //pin 
                    }
               else if(Degrees == Degrees_Low) 
                    {
                      digitalWrite(Motor_Up_Control,0);
                      digitalWrite(Motor_Down_Control,0); 
                      delay(4000);
                      Gate_Status=-1;  //down
                    }
               else
                    {
                      digitalWrite(Motor_Down_Control,0);
                    }
              }  
           elseif(gate_control_output ==0) &&  Gate_Status==0    //Gate is down and we bring it up
//         else  //if(gate_control_output ==1)on - gate goes up
             {
            //    if((Degrees <= (Degrees_High)) && (Degrees >70))
                if((Degrees < (Degrees_High)) && (Degrees >70)) 
                   {
                     digitalWrite(Motor_Down_Control,0);
                     analogWrite(Motor_Up_Control,110);
                   }
              // else if(Degrees <= (Degrees_High))
                else if(Degrees < (Degrees_High))
                   {
                     digitalWrite(Motor_Down_Control,0);
                     analogWrite(Motor_Up_Control,150);
                   }
               else if(Degrees == Degrees_High) 
                   {
                     digitalWrite(Motor_Up_Control,0);
                     digitalWrite(Motor_Down_Control,0); 
                     delay(4000);
                     Gate_Status=1;  //gate up
                   }
               else               
                   {
                     digitalWrite(Motor_Up_Control,0);//pin  
                   }
             }
}

When my gate that crosses a road sees a signal called gate_control_output==0 (binary), it tells the gate to go down to an angle in Degrees that is set in a calibration function as Degrees_Low.

This is way too confusing. Where/how the gate is used is irrelevant. How can the gate see a signal? How can the gate tell the gate to move? Gates go along for the ride. Motors move. Motor controllers make motors move. Microcontrollers make motor controllers do stuff.

The value 0 is the same in binary, octal, decimal, or hexidecimal. You sound like a dweed when you keep dragging the word binary into the discussion.

Using meaningful names in your code helps with understand it. Which makes more sense? Gate_Status == 1 or gateOpen?

Does 1 mean open? Or does it mean closed? Is there any ambiguity about what gateOpen means?

gate_control_output looks like an input to me.

Here’s some modified code from a rollup door job I did a few years ago, maybe you can get some ideas.
One thought: What happens if power fails while the gate is in motion and then resets ?
Maybe you should arrange your code so the default startup direction is OPEN.

//Put these declarations at the top of sketch, before "void setup()"

/**************************************************************************/

const byte dnFast = 220, dnSlow = 120, upFast = 220, upSlow = 120;
const byte dnCreep = 15, upCreep = 80;
const byte bottom = 2, top = 88; // adjust for proper open & close positions
boolean gateDown = false, gateUP = false;

/**************************************************************************/

void Output() //Turns motors on/off based on GC output           
{
    if(digitalRead(Maintenance_Switch)==1) //OFF-             
  {
    if(gate_control_output == 0 && !gateDown) //off - gate goes dn
    {                                             
      gateUp = false;
      digitalWrite(Motor_Up_Control,0);
      if(Degrees < bottom)
      {
        digitalWrite(Motor_Down_Control,0);
        gateDown = true;
        return;
      }
      if(Degrees >= dnCreep)
      {         
        analogWrite(Motor_Down_Control,dnFast);
      }
      else
      {
        analogWrite(Motor_Down_Control,dnSlow);
      }
    }
    
    if(gate_control_output ==1 && !gateUp)  //on - gate goes up
    {
      gateDown = false;
      digitalWrite(Motor_Down_Control,0);
      if(Degrees > top)
      {
        digitalWrite(Motor_Up_Control,0);
        gateUp = true;
        return;
      }
      if(Degrees <= upCreep)
      {         
        analogWrite(Motor_UP_Control,upFast);
      }
      else
      {
        analogWrite(Motor_Up_Control,upSlow);
      }
    }
  }
}