Height Control

I need to change or add a way to stop oscillations. The device I am trying to control fly's out of the dead band / hysteresis before it can get stopped in time and in return bounces up and down. The noise cancelling that is currently in the code made it worse by adding to much delay so I stopped using it. Is there a way to have it see the end is near and predict the needed stop. PWM is not an option due to how the control circuit reads the up and down.

This is the current code I have been using. Thanks go to Blackfin for the coding so far. :slight_smile:

#define DESIRED_HEIGHT      500         //# raw ADC counts representing desired height and the lower the number the greater the down pressure on the ground
#define HIGH_HYSTERESIS     105         //# hysteresis -- positive side
#define LOW_HYSTERESIS      105         //# hysteresis -- negative side

#define NUM_AVGS            1          //# number of samples in averaging array
#define SAMPLE_PERIOD       1          //mS number of milliseconds between samples

//Constants
const byte PotPin = A0;
const byte UpPin = 2;
const byte DownPin = 4;

unsigned long
   timeNow;
unsigned long
   timeSample = 0;
int
   grAvgHeight[NUM_AVGS];
unsigned long
   ulSum;
int
   Height;

void setup()
{
   Serial.begin( 9600 );
  
   pinMode(UpPin, OUTPUT);
   pinMode(DownPin, OUTPUT);
   digitalWrite( UpPin, HIGH );
   digitalWrite( DownPin, HIGH );
   //
   pinMode(PotPin, INPUT);
   //initialize the averaging array and sum
   Height = analogRead( PotPin );
   for( int i=0; i<NUM_AVGS; i++ )
       grAvgHeight[i] = Height;
   ulSum = Height * NUM_AVGS;
  
}//setup

//state names
#define NOT_MOVING      0
#define MOVING_UP       1
#define MOVING_DOWN     2
//
void loop()
{
   static byte
       stateMovement = NOT_MOVING;

   //get the time now
   timeNow = millis();

   //is it time for a check on the position?
   if( (timeNow - timeSample) >= SAMPLE_PERIOD )
   {
       //yes; save this time for the next compare
       timeSample = timeNow;

       //read the position sensing pot and filter it
       Height = FilterHeight( analogRead( PotPin ) );

       //what are we currently doing?
       switch( stateMovement )
       {
           case    NOT_MOVING:
               //we're in the deadband now. Check to see if we're outside the limits
               if( Height < (DESIRED_HEIGHT - LOW_HYSTERESIS) )
               {
                   //too low; set the Up direction
                   Serial.println( "MOVING UP" );
                   digitalWrite( UpPin, LOW );
                   stateMovement = MOVING_UP;      //and move to that state

               }//if
               else if( Height > (DESIRED_HEIGHT + HIGH_HYSTERESIS) )
               {
                   //too high; set the Down direction
                   Serial.println( "MOVING DOWN" );
                   digitalWrite( DownPin, LOW );
                   stateMovement = MOVING_DOWN;    //and move to that state
                  
               }//else
                  
           break;
                  
           case    MOVING_UP:
               //when actually moving up, we seek to stop moving when the filtered height matches or is greater than that desired
               if( Height >= DESIRED_HEIGHT )
               {
                   Serial.println( "STOPPING UPWARD MOVEMENT" );
                   digitalWrite( UpPin, HIGH );
                   stateMovement = NOT_MOVING;
                  
               }//if
          
           break;
                      
           case    MOVING_DOWN:
               //when actually moving up, we seek to stop moving when the filtered height matches or is less than that desired
               if( Height <= DESIRED_HEIGHT )
               {
                   Serial.println( "STOPPING DOWNWARD MOVEMENT" );
                   digitalWrite( DownPin, HIGH );
                   stateMovement = NOT_MOVING;
                  
               }//if
          
           break;
          
       }//switch

   }//if
  
}//loop

//add a bit of noise filtering to the ADC readings
int FilterHeight( int NewReading )
{
   static int
       idx = 0;

   //on each pass, we subtract from the sum the value in the array pointed to by idx
   ulSum -= grAvgHeight[idx];
   //then add in the new value
   ulSum += NewReading;
   //and store that new value in the array
   grAvgHeight[idx] = NewReading;

   //walk through the array each pass; when we hit the end of the array, reset to zero
   //this treats the array as a "circular" array
   idx++;
   if( idx == NUM_AVGS )
       idx = 0;

   //compute avg of updated sum divided by number of samples
   return( (int)(ulSum / NUM_AVGS) );
  
}//FilterHeight

Hi and welcome to the forum. Nice italic code! To fix that, please read "How to use the forum" before you make any more posts and fixed your first post :slight_smile:

septillion:
Hi and welcome to the forum. Nice italic code! To fix that, please read "How to use the forum" before you make any more posts and fixed your first post :slight_smile:

Is that better?

Is there a way to have it see the end is near and predict the needed stop

This sounds like a job for PID controller. Google will show you what it means

Can you explain some more why PWM is not an option ?

UKHeliBob:
This sounds like a job for PID controller. Google will show you what it means

Can you explain some more why PWM is not an option ?

This control was originally done with a mechanical switch. It was a spring in between two contact bars on each side. If it hit one side it was up and if it hit the other it was down with a 12 volt signal. The new combine harvester headers use a potentiometer. However my combine still has the old circuitry for auto height control.

I am trying to build a box that will read the potentiometer position and give an up or down output through the mechanical relays. Currently it kind of works however if it had a way of seeing the end of the hysteresis coming it would be much more accurate and far Superior of the old system. It tends to jump around and oscillate.

PWM wouldn't work the greatest through the relays nor the current combine harvester circuit that controls the hydraulic valve bank. I believe the valve bank would need to be a proportional control valve and that is just not an option. I am stuck using an on or off valve. If PWM works with the electromagnetical relays then maybe it would be an option that I am not aware of....

I know what PID control is, I just have no idea how it is coded nor added to my current code.

Would the use of fast smoothing help this scenario?

I am a visual learner :S

Thanks,