Show Posts
Pages: [1] 2 3
1  Using Arduino / Motors, Mechanics, and Power / Re: Torque control aka current control of brushed DC on: November 08, 2013, 02:23:29 pm
Hey
@ MarkT. It (of cause) helped with the RC filter (nice), now i am down to about 1/2 the noise (0.014V) how do you think that will work?
There is one funny (read terrible) but interesting response of the system. If i apply a steady low output from the arduino the spring will tighten but after a few seconds the motor begins to make a little audible noise. Thats not the problem, but once in a while it is as if the motor looses power for an instant - the duration of the "hole" is very short, only enough to make the motor rotate opposite the pulling direction for a few (15-20) degrees, then the motor reenergizes. My first guess was that it was the motor board is going into overcurrent protection (a feature it has to not burn out) due to the varying and very low resistance at certain rotor-positions, and the very low inductance of this kind of motor. I have looked at the PWM on a oscilloscope and it does not seem to change when the motor looses power.
So i have a motor that seems to get a constant PWM voltage but occasionally looses power for (less than) a split second. ????!!!!!!????? Anyone?
I am running PWM @ 32kHz

Thanks
2  Using Arduino / Motors, Mechanics, and Power / Re: Stopping a Motor with a Current Sensor... on: November 07, 2013, 04:51:27 pm
Yes that is possible, no problem at all.
The only thing you have to keep in mind is that placing the sensor there you will sense both the motor and the drivers consumption.

// Bear
3  Using Arduino / Motors, Mechanics, and Power / Re: Stopping a Motor with a Current Sensor... on: November 07, 2013, 03:13:19 pm
Well - its not me on the video, but i guess it is quite straight forward.

First off you need something to measure Amps. This can be done by measuring the voltage drop over a resistor or (if you prefer to spend a bit of $$) you can find a hall-sensor solution on ebay if you search on hall sensor current.......or something like that. you can also find it on any electronics shop or website.
If you need to run the motor in both directions you will need a Bi-directional sensor.

Implementing it is very simple and the datasheet will tell you how to wire it up. Be sure to get one that takes 5V (or 3.3V)  as input if you are using an Arduino. In the datasheet you will find a rating like 40mv/V which means that for every amp flowing through the sensor, its output voltage will increase by 40mV. Very straight forward.
The thing about motors is that they draw more current when you try to stop or slow down the rotation. This is because the BEMF (the voltage produced by a motor when it spins) becomes less as the speed is reduced. Conclusively you (as you wrote yourself) will be able to see if the motor has reached its stop if the Amps goes up. So your program will consist of a analogRead(ampSensor); compare that to the maximum allowable current and then either continue or stop.

hope it helped.

// Bear

You can always post your code here if you want to have it checked.

cheers  



4  Using Arduino / Motors, Mechanics, and Power / Re: Stopping a Motor with a Current Sensor... on: November 07, 2013, 11:53:02 am
Like this?
5  Using Arduino / Motors, Mechanics, and Power / Re: Torque control aka current control of brushed DC on: November 07, 2013, 09:17:29 am
Hello again.
First off, thanks for the feedback MarkT.

Sorry for my late reply - unfortunately i dont own a oscilloscope but i hope the readings form my DAQ will do the job.
The first picture (hallsensor uden load) is the hallsensor connected to 5v but with no movement of the motor. The other picture shows the output as i wrap the string around the shaft and pull so a current is induced in the motor and sensor.

It seems like the signal will produce an AMP-reading within half an amp?!? peak to peak=  0,0225V /0,04mv/V = 0,56Amp I dont think that will be satisfactory for me but i am no expert - perhaps my/a filter would be a solution (or make it worse)?
I have tried with several but not sure how big a timeconstant is too big - lack of experience. 

Regarding the PWM i can read from the datasheet that the motorboard outputs PWM @ 15kHz. i am signalling the motorboard @ 32kHz from the Arduino (TCCR2B = TCCR2B & 0b11111000 | 0x01) why is that important?

Here is the code so far:
Code:
#include <PID_v1.h>

//**************Declaring pins**********

//input/output pins
const int setpointPin = A3; // connected to a pot
const int inputPin = A1;  // connected to the Hallsensor
const int outputPin = 3; 
const int turnLeftPin = 2;  //Directionpin on the motor board.


// Diverse globale variabler
double zeroInput;  // sensorreading at atartup or no load

double avgInput;    //Calculated average input
double avgSetpoint;
double Setpoint, Input, Output; // PID variables
double Kp;  //PID-reg***************
double Ki;
double Kd;


// smooth variables
float ampArray[5];
float ampSort[5];
float amp2;
float ampOut;
const int nrReadings = 5;


// changeble values
unsigned long previousMillis = 0UL;     // store timer current value, and start offset
unsigned long inputinterval = 0UL;   // speed the loop runs

PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);
unsigned long serialTime; //this will help us know when to talk with processing


void setup()
{
  // Motorcontroller
  pinMode(outputPin, OUTPUT);
  pinMode(turnLeftPin, OUTPUT);
  pinMode(inputPin, INPUT);
  pinMode(setpointPin, INPUT);

  // Diverse
  Serial.begin(9600);

  // PWM frekvens
  TCCR2B = TCCR2B & 0b11111000 | 0x01;  // Timer 2: PWM 3 & 11 @ 31372 Hz the motorboard is specified to want >20kHz

  //initialize the variables we're linked to
  Setpoint = 0;
  zeroInput = analogRead(inputPin);

  turnLeftPin, LOW; // before implementing PID in both directions i start with one direction
  //Turn the pid on
  myPID.SetMode(AUTOMATIC);
  myPID.SetOutputLimits(0, 150);  //Limits the output
  myPID.SetSampleTime(10); // Determines how often the PID algorithm evaluates (default = 200)


}


//**************************LOOP***************************************

void loop() {

  // current times since startup
  unsigned long currentMillis = millis();


  if (currentMillis - previousMillis > inputinterval) {
    //previousMillis = currentMillis;
    previousMillis += inputinterval; 

    Motormove();
  }

  //send-receive with processing if it's time
  if(millis()>serialTime)
  {
    SerialReceive();
    SerialSend();
    serialTime+=100;
  }
}


void Motormove() {
  Setpoint = getSetpoint(); //This can be commented out and then changed in processing instead of a pot.
  Input = getInput();
  myPID.Compute();
  analogWrite(outputPin, Output);
}

double getSetpoint() {
  double sum;
  double avg;
  for (int i = 0; i <= nrReadings; i++) {
    sum += analogRead(setpointPin); 
    delayMicroseconds(50);   
  }
  avgSetpoint = sum/nrReadings;
  sum = 0;
  return avgSetpoint;
}

double getInput() {
  double sum;
  double avg;
  for (int i = 0; i <= nrReadings; i++) {
    sum += analogRead(inputPin);       
    delayMicroseconds(50);
  }
  avgInput = sum/nrReadings;
  sum = 0;
  return avgInput;
}


// These functions should give a median but for now i am not using them.

double sortAmpMedian() {
  for (int i = 0; i < nrReadings; i++) {
    ampSort[i] = ampArray[i];
  }
  bubbleSort();
  bubbleSort();
  bubbleSort();
  for (int i=0; i < nrReadings; i++) {
    ampArray[i] = analogRead(inputPin)-zeroInput;
  }
  amp2 = 0;
  for (int j=1; j<nrReadings-1; j++) {
    amp2 += ampSort[j];
  }
  ampOut = 0;
  ampOut = amp2/nrReadings-2;
}

void bubbleSort() {
  int out, in;
  float swapper;
  for(out=0 ; out < 5; out++) {  // outer loop
    for(in=out; in < 5; in++)  {  // inner loop
      if( ampSort[in] > ampSort[in+1] ) {   
        // swap them:
        swapper = ampSort[in];
        ampSort[in] = ampSort[in+1];
        ampSort[in+1] = swapper;
      }
    }
  }
}






////*********************************
/********************************************
 * Serial Communication functions / helpers
 ********************************************/


union {                // This Data structure lets
  byte asBytes[24];    // us take the byte array
  float asFloat[6];    // sent from processing and
}                      // easily convert it to a
foo;                   // float array



// getting float values from processing into the arduino
// was no small task.  the way this program does it is
// as follows:
//  * a float takes up 4 bytes.  in processing, convert
//    the array of floats we want to send, into an array
//    of bytes.
//  * send the bytes to the arduino
//  * use a data structure known as a union to convert
//    the array of bytes back into an array of floats

//  the bytes coming from the arduino follow the following
//  format:
//  0: 0=Manual, 1=Auto, else = ? error ?
//  1: 0=Direct, 1=Reverse, else = ? error ?
//  2-5: float setpoint
//  6-9: float input
//  10-13: float output 
//  14-17: float P_Param
//  18-21: float I_Param
//  22-245: float D_Param
void SerialReceive()
{

  // read the bytes sent from Processing
  int index=0;
  byte Auto_Man = -1;
  byte Direct_Reverse = -1;
  while(Serial.available()&&index<26)
  {
    if(index==0) Auto_Man = Serial.read();
    else if(index==1) Direct_Reverse = Serial.read();
    else foo.asBytes[index-2] = Serial.read();
    index++;
  }

  // if the information we got was in the correct format,
  // read it into the system
  if(index==26  && (Auto_Man==0 || Auto_Man==1)&& (Direct_Reverse==0 || Direct_Reverse==1))
  {
    Setpoint=double(foo.asFloat[0]);
    //Input=double(foo.asFloat[1]);       // * the user has the ability to send the
    //   value of "Input"  in most cases (as
    //   in this one) this is not needed.
    if(Auto_Man==0)                       // * only change the output if we are in
    {                                     //   manual mode.  otherwise we'll get an
      Output=double(foo.asFloat[2]);      //   output blip, then the controller will
    }                                     //   overwrite.

    double p, i, d;                       // * read in and set the controller tunings
    p = double(foo.asFloat[3]);           //
    i = double(foo.asFloat[4]);           //
    d = double(foo.asFloat[5]);           //
    myPID.SetTunings(p, i, d);            //

    if(Auto_Man==0) myPID.SetMode(MANUAL);// * set the controller mode
    else myPID.SetMode(AUTOMATIC);             //

    if(Direct_Reverse==0) myPID.SetControllerDirection(DIRECT);// * set the controller Direction
    else myPID.SetControllerDirection(REVERSE);          //
  }
  Serial.flush();                         // * clear any random data from the serial buffer
}

// unlike our tiny microprocessor, the processing ap
// has no problem converting strings into floats, so
// we can just send strings.  much easier than getting
// floats from processing to here no?
void SerialSend()
{
  Serial.print("PID ");
  Serial.print(Setpoint);   
  Serial.print(" ");
  Serial.print(Input);   
  Serial.print(" ");
  Serial.print(Output);   
  Serial.print(" ");
  Serial.print(myPID.GetKp());   
  Serial.print(" ");
  Serial.print(myPID.GetKi());   
  Serial.print(" ");
  Serial.print(myPID.GetKd());   
  Serial.print(" ");
  if(myPID.GetMode()==AUTOMATIC) Serial.print("Automatic");
  else Serial.print("Manual"); 
  Serial.print(" ");
  if(myPID.GetDirection()==DIRECT) Serial.println("Direct");
  else Serial.println("Reverse");
}

If you made it to here - Thanks again for your time.

Bjorn
6  Using Arduino / Motors, Mechanics, and Power / Torque control aka current control of brushed DC on: November 05, 2013, 05:19:29 pm
Hi.

I have spent countless hours on my project and i am now out of ideas and energy. I dont understand the PID. I understand the math - no problem, but as i start to tune the system, everything i thought i knew about response of my tuning completely fails. And the worst thing is that i cant understand why (so pretty please with a cherry on the top) help me out.

I am trying to achieve true torque control (aka current control) which is done (as i understand it) by sampling the amount of current that runs in the system and using that as the Input-parameter of the PID algorithm. So far i have used the library from Arduino.cc but things get messed up when i start tuning.

The system consists of the following:
pancakemotor:           http://www.pml.com.cn/ver2en/motors/GPM16LR.html
Motorboard:               http://www.robotshop.com/eu/en/devantech-md03-50v-20a-h-bridge-driver.html
Ampsensor:               http://www.panucatt.com/product_p/cs-50a.htm
Arduino Uno
Pot for setpoint adjustment.

 
My system is (for now) very simular to this:                             
and i want to achieve exactly the same as seen in the video.

My hallsensor (to measure current) is quite jumpy, so i added a small low-pass filter. besides that i use an average of 5 measurements and the median when gathering Setpoint and Input.


Weird things happening is the following:

1) the output wont go back to 0 as i turn the setpoint to 0 - i am not using any I gain, so it should stabilize quite quickly at 0 PWM right? Sometimes (not all the time) my output will continue to run, leaving the Input floating way over (20-100 from 0-1023) my setpoint thats turned down to 0.

2) I cant stabilize the system, the output is varying too much, so the feel of the shaft is very jumpy.


PLEASE..........ANYONE i am out of things to try. 
7  Using Arduino / Sensors / Re: PID (maybe) has its own life. on: August 29, 2013, 02:22:35 am
And the Code

Code:
#include <PID_v1.h>


// Define input/output pins
const int steerPot = A3;
const int wheelPot = A1;
const int outputPin = 3;
const int directionPin = 2;

const int KpPin = A5;  //PID-reg*****************
const int KiPin = A4 ;
const int KdPin = A2;

// Define variables
int steerPos;    // position of steeringwheel
int wheelPos;    // position of wheels
double error;    //error between wheelPot and steerPot
double avgInput;    //Calculated average input
double avgSetpoint;    //Calculated average setpoint
double Setpoint, Input, Output; // PID variables

float Kp;  //PID-reg***************
float Ki;
float Kd;

// Define changeble values
double readings = 5;    //Amount of readings the averege setpoint,input is calculated on
byte outputMax = 100;    //Max output to motor (PWM)
const byte errorMax = 2;  // Max error between input/setpoint before action is taken
const int steerUL = (1023-175);    //Upper limit for pot
const int steerLL = 175;    //Lower limit for pot

// Major timer, lets user adjust how often the major loop (read pots and take action) should run
unsigned long previousMillis = 0UL;    
unsigned long inputinterval = 25UL; // Time between main-loop run

// Serial output to console
unsigned long serialMillis = 0UL; // store timer current value, and start offset
unsigned long serialFeedbackMillis = 20UL;  //Time between sending feedback to serial


//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint, 1 ,0 ,0, DIRECT);


void setup() {

  TCCR2B = TCCR2B & 0b11111000 | 0x02;  // Timer 2: PWM 3 & 11 @ 3906,25 Hz
  Serial.begin(115200);

  pinMode(steerPot, INPUT);                 //Not needed if analogRead is used.
  pinMode(wheelPot, INPUT);
  pinMode(outputPin, OUTPUT);
  pinMode(directionPin, OUTPUT);

  pinMode(Kp, INPUT);    //PID-reg******************
  pinMode(Ki, INPUT);
  pinMode(Kd, INPUT);

  //initialize the variables we're linked to
  Input = analogRead(steerPot);
  Setpoint = analogRead(wheelPot);

  //turn the PID on
  myPID.SetMode(AUTOMATIC);
  myPID.SetOutputLimits(0, outputMax);  //Limits the output
  myPID.SetSampleTime(200); // Determines how often the PID algorithm evaluates (default = 200)
}

void loop() {

  // current times since startup
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > inputinterval) {  //Checks if its time to run the master loop
    previousMillis += inputinterval;  // if its time, it ads one interuptinterval for the next interval

  // reads the 3 pots and updates the Kp,Ki,Kd values
    Kp = analogRead(KpPin) / 100.0;  // Values from 0.0 to 10.23
    Ki = analogRead(KiPin) / 1000.0;  // Values from 0.0 to 1.023
    Kd = analogRead(KdPin) / 1000.0;  // Values from 0.0 to 1.023
    myPID.SetTunings(Kp, Ki, Kd);
    
     /* Kp = analogRead(KpPin); // reads the 3 pots and updates the Kp,Ki,Kd values
    Ki = analogRead(KiPin);
    Kd = analogRead(KdPin);
    myPID.SetTunings(analogRead(KpPin)/100, analogRead(KiPin)/1000, analogRead(KdPin)/1000);
*/
    error = getError();
    if(error >= errorMax ) {
      TurnR();
    }
    else if (error <= -errorMax)  {
      TurnL();
    }
    else {
      digitalWrite(3, LOW);
    }
  }

  if(currentMillis - serialMillis > serialFeedbackMillis) { //Checks if its time to run the master loop
    serialMillis += serialFeedbackMillis; // if its time to print, it ads one interuptinterval for the next interval

    Cprint();
  }
}
void TurnR() {
  if (analogRead(steerPot) < steerLL) {  // To stop the pot from overturning
    analogWrite(outputPin, 0);
  }    
  else {
    Setpoint = getSetpoint()*-1;
    Input = getInput()*-1;
    myPID.Compute();
    //Output = abs(Output);
    digitalWrite(directionPin, HIGH);
    analogWrite(outputPin, Output);
  }
}
void TurnL() {
  if (analogRead(steerPot) > steerUL) {  // To stop the pot from overturning
    analogWrite(outputPin, 0);
  }    
  else {
    Setpoint = getSetpoint();   // If the pot is within the limits, the output is generated and sent to the motorboard
    Input = getInput();
    myPID.Compute();
    Output = abs(Output);
    digitalWrite(directionPin, LOW);
    analogWrite(outputPin, Output);
  }
}

double getError(){
  double wheelPos = getSetpoint();
  double steerPos = getInput();
  error = (steerPos-wheelPos);
  return error;
}
double getSetpoint() {
  long sum;
  long avg;
  for (int i = 0; i <= readings; i++) {
    sum += analogRead(wheelPot);  
    //delay(1);    
  }
  avgSetpoint = sum/readings;
  sum = 0;
  return avgSetpoint;
}

double getInput() {
  long sum;
  long avg;
  for (int i = 0; i <= readings; i++) {
    sum += analogRead(steerPot);      
    delay(1);
  }
  avgInput = sum/readings;
  sum = 0;
  return avgInput;
}

void Cprint() {
  Serial.write("SteerPot: ");
  Serial.print(analogRead(steerPot));
  Serial.write("  wheelPot: ");
  Serial.print(analogRead(wheelPot));
  Serial.write(" error: ");
  Serial.print(error);
    Serial.write("  Output: ");
  Serial.println(Output);
  Serial.print(" P: ");
  Serial.print(Kp);
  Serial.print("  I: ");
  Serial.print(Ki );
  Serial.print("  D: ");
  Serial.println(Kd);

}



















8  Using Arduino / Sensors / PID (maybe) has its own life. on: August 29, 2013, 02:22:08 am
I am having some rather weird outputs from my Arduino. I am using PID and everything seems to be going fine but once in a while the system will output either max-output (255) or min-output (0) i dont know why! Has anyone else had problems of that sort with the PID library? i am trying to control the position of one motor with a Pot, the motor also has a pot connected to it to get a servo-like application.
The output to serial will give it off like this:

Code:
SteerPot: 577  wheelPot: 593 error: -20.00  Output: 23.58
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 576  wheelPot: 593 error: -20.00  Output: 23.58
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 577  wheelPot: 593 error: -20.20  Output: 23.58
 P: 1.29  I: 0.00  D: 0.00
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 576  wheelPot: 593 error: -19.40  Output: 23.58
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 578  wheelPot: 593 error: -21.60  Output: 23.58
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 577  wheelPot: 593 error: -20.00  Output: 0.00
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 577  wheelPot: 593 error: -20.00  Output: 0.00
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 576  wheelPot: 593 error: -17.80  Output: 0.00
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 577  wheelPot: 593 error: -19.40  Output: 0.00
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 577  wheelPot: 593 error: -19.20  Output: 0.00
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 577  wheelPot: 593 error: -19.40  Output: 0.00
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 577  wheelPot: 593 error: -19.40  Output: 0.00
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 577  wheelPot: 593 error: -19.20  Output: 0.00
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 577  wheelPot: 593 error: -19.40  Output: 0.00
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 577  wheelPot: 593 error: -19.20  Output: 0.00
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 576  wheelPot: 593 error: -19.20  Output: 24.58
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 576  wheelPot: 593 error: -19.20  Output: 24.58
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 577  wheelPot: 593 error: -19.40  Output: 24.58
 P: 1.29  I: 0.00  D: 0.00
SteerPot: 577  wheelPot: 593 error: -19.80  Output: 24.58
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 577  wheelPot: 593 error: -19.40  Output: 24.58
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 577  wheelPot: 593 error: -19.80  Output: 24.58
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 577  wheelPot: 593 error: -19.80  Output: 24.58
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 577  wheelPot: 593 error: -19.40  Output: 24.58
 P: 1.29  I: 0.00  D: 0.00
SteerPot: 576  wheelPot: 593 error: -19.20  Output: 24.58
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 578  wheelPot: 593 error: -19.80  Output: 24.58
 P: 1.28  I: 0.00  D: 0.00

Or like this:
Code:
SteerPot: 498  wheelPot: 486 error: 12.60  Output: 18.01
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 498  wheelPot: 487 error: 12.80  Output: 18.01
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 498  wheelPot: 487 error: 13.20  Output: 18.01
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 498  wheelPot: 486 error: 12.60  Output: 18.01
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 497  wheelPot: 486 error: 13.20  Output: 18.01
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 498  wheelPot: 487 error: 13.00  Output: 18.01
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 498  wheelPot: 486 error: 13.60  Output: 18.01
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 498  wheelPot: 486 error: 12.00  Output: 100.00
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 497  wheelPot: 485 error: 16.20  Output: 100.00
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 495  wheelPot: 480 error: 14.20  Output: 100.00
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 488  wheelPot: 481 error: 13.00  Output: 100.00
 P: 1.29  I: 0.00  D: 0.00
SteerPot: 477  wheelPot: 477 error: 3.80  Output: 100.00
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 464  wheelPot: 478 error: -6.40  Output: 100.00
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 450  wheelPot: 473 error: -19.80  Output: 100.00
 P: 1.29  I: 0.00  D: 0.00
SteerPot: 438  wheelPot: 474 error: -37.80  Output: 57.94
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 429  wheelPot: 476 error: -49.60  Output: 57.94
 P: 1.28  I: 0.00  D: 0.00
SteerPot: 426  wheelPot: 473 error: -57.60  Output: 57.94
 P: 1.29  I: 0.00  D: 0.00


If i run my feedback loop (serial connection) faster i see that the output of max/min will almost always come several times at a time. I cant seem to find any consistency in the wrong output.
I am taking the average of several readings to minimize jitter, dont know what else to do. Maybe i am using the PID library wrong?
Any advice would be great.

THX
9  Using Arduino / Sensors / Re: Adjusting PID with Pot on: August 23, 2013, 01:29:46 am
That is kinda what i did. I followed wikipedia in the following way:
If the system must remain online, one tuning method is to first set K_i and K_d values to zero. Increase the K_p until the output of the loop oscillates, then the K_p should be set to approximately half of that value for a "quarter amplitude decay" type response. Then increase K_i until any offset is corrected in sufficient time for the process. However, too much K_i will cause instability. Finally, increase K_d, if required, until the loop is acceptably quick to reach its reference after a load disturbance.
I also tried the Ziegler–Nichols tuning method by using a DAQ to measure the oscillation period (plot of the 2 pots) but it yielded something like P= 2,7 I= 6,3 D=0,29. that is completely off and the result was that the system went crazy instantly.

My problem with the tuning is that my Ki factor cant be turned down! if i turn it (Ki) up and the system starts to get unstable, i cant stabilize it again by turning Ki  down -. even if i turn all 3 parameters down to 0, the system is still unstable. I dont understand that.

Thanks for the reply

//Bear
10  Using Arduino / Sensors / Re: Adjusting PID with Pot on: August 22, 2013, 10:26:56 am
Hi.
I see what you mean using double, i have changed it to int.
Did not know that analogRead() lets me loose the INPUT
The reason for the 100 was that as i get over P=5, the system begins to oscillate and the same goes for teh I and D, the system gets weird when they get high (above 1) - is that normal?

Thanks for the feedback
11  Using Arduino / Sensors / Adjusting PID with Pot on: August 22, 2013, 07:50:45 am
Hi. I am trying to find the correct PID prarmeters for my homebuilt servo motor. I have combined a Dc motor and a Pot to get a servomotor as you can see on the picture. the motor is mounted on a gear and the pot is mounted directly on the steering shaft under the motor. The servo is supposed to move a steering wheel to a constantly changing position as fast as possible.... it is giving me some trouble though and i cant figure out why. Hope to find someone smarter then myself here.
I have attached 3 pots (one for each parameter) and by adjusting them i can adjust the P,I,D values... but the weird thing is that when i adjust the P and D factores, the system seems to change acordingly, but if i play with the I parameter, it is like the value can only go up! so if i have turned it to a too high value, i have to turn it down and reload the program. Does anyone know why?

Code:
#include <PID_v1.h>


// Define input/output pins
const int steerPot = A3;
const int wheelPot = A1;
const int outputPin = 3;
const int directionPin = 2;

const double KpPin = A5;  //PID-reg*****************
const double KiPin = A4 ;
const double KdPin = A2;

// Define variables
int steerPos;    // position of steeringwheel
int wheelPos;    // position of wheels
double error;
double Setpoint, Input, Output; // PID variables

double Kp;  //PID-reg***************
double Ki;
double Kd;

// Define changeble values
byte outputMax = 255;
const byte errorMax = 2;
const int steerUL = (1023-175);
const int steerLL = 175;

// Major timer, lets user adjust how often the major loop (read pots and take action) should run
unsigned long previousMillis = 0UL;     
unsigned long inputinterval = 25UL; // Time between main-loop run

// Serial output to console
unsigned long serialMillis = 0UL; // store timer current value, and start offset
unsigned long serialFeedbackMillis = 200UL;  //Time between sending feedback to serial


//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint, 1 ,0 ,0, DIRECT);


void setup() {

  TCCR2B = TCCR2B & 0b11111000 | 0x02;  // Timer 2: PWM 3 & 11 @ 3906,25 Hz
  Serial.begin(115200);

  pinMode(steerPot, INPUT);                 
  pinMode(wheelPot, INPUT);
  pinMode(Output, OUTPUT);
  pinMode(directionPin, OUTPUT);

  pinMode(Kp, INPUT);    //PID-reg******************
  pinMode(Ki, INPUT);
  pinMode(Kd, INPUT);

  //initialize the variables we're linked to
  Input = analogRead(steerPot);
  Setpoint = analogRead(wheelPot);

  //turn the PID on
  myPID.SetMode(AUTOMATIC);
  myPID.SetOutputLimits(0, outputMax);  //Limits the output
  myPID.SetSampleTime(50); // Determines how often the PID algorithm evaluates (default = 200)
}

void loop() {

  // current times since startup
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > inputinterval) {  //Checks if its time to run the master loop
    previousMillis += inputinterval;  // if its time, it ads one interuptinterval for the next interval

      Kp = analogRead(KpPin); // reads the 3 pots and updates the Kp,Ki,Kd values
    Ki = analogRead(KiPin);
    Kd = analogRead(KdPin);
    myPID.SetTunings(analogRead(KpPin)/100, analogRead(KiPin)/1000, analogRead(KdPin)/1000);

    error = getError();
    if(error >= errorMax ) {
      TurnR();
    }
    else if (error <= -errorMax)  {
      TurnL();
    }
    else {
      digitalWrite(3, LOW);
    }
  }

  if(currentMillis - serialMillis > serialFeedbackMillis) { //Checks if its time to run the master loop
    serialMillis += serialFeedbackMillis; // if its time to print, it ads one interuptinterval for the next interval

    Cprint();
  }
}
void TurnR() {
  if (analogRead(steerPot) < steerLL) {  // To stop the pot from overturning
    analogWrite(outputPin, 0);
  }   
  else {
    Setpoint = getSetpoint()*-1;
    Input = getInput()*-1;
    myPID.Compute();
    Output = abs(Output);
    digitalWrite(directionPin, HIGH);
    analogWrite(outputPin, Output);
  }
}
void TurnL() {
  if (analogRead(steerPot) > steerUL) {  // To stop the pot from overturning
    analogWrite(outputPin, 0);
  }   
  else {
    Setpoint = getSetpoint();   // If the pot is within the limits, the output is generated and sent to the motorboard
    Input = getInput();
    myPID.Compute();
    Output = abs(Output);
    digitalWrite(directionPin, LOW);
    analogWrite(outputPin, Output);
  }
}
double getError(){
  double wheelPos = analogRead(wheelPot);
  double steerPos = analogRead(steerPot);
  error = (steerPos-wheelPos);
  return error;
}
double getSetpoint(){
  int No1 = analogRead(wheelPot);
  delay(3);
  int No2 = analogRead(wheelPot);
  delay(3);
  int No3 = analogRead(wheelPot);
  Setpoint = (No1+No2+No3)/3;
  return Setpoint;
}
double getInput(){
   int No1 = analogRead(steerPot);
  delay(3);
  int No2 = analogRead(steerPot);
  delay(3);
  int No3 = analogRead(steerPot);
  Input = (No1+No2+No3)/3;
  return Input;
}
void Cprint() {
  Serial.write("error: ");
  Serial.print(error);
  Serial.write("  potRAT: ");
  Serial.print(analogRead(steerPot));
  Serial.write("  potHJUL: ");
  Serial.print(analogRead(wheelPot));
  Serial.write("  Output: ");
  Serial.println(Output);
  Serial.print(" P: ");
  Serial.print(Kp/100);
  Serial.print("  I: ");
  Serial.print(Ki/1000);
  Serial.print("  D: ");
  Serial.println(Kd/1000);

}


















12  Using Arduino / Project Guidance / Re: Feasibility of an underwater DC motor on: August 07, 2013, 05:27:47 pm
If you want to make a proper design, you should buy a "stern tube". It lets you put a shaft through without water running in. They are quite inexpensive.
One could worry that if you made a motor through the container you would loose most of your power, remember that the magnetic force travels 1000 times easier in metal than in air.
13  Using Arduino / General Electronics / Re: "Quick and dirty" question on: August 07, 2013, 04:17:24 am
Thank you for the feedback, its appreciated.

The 7805 seems to be doing the job, without getting hot at all. The only thing i am using it for is for reference, so "no" current is being drawn.
Quote
Decoupling caps would be good
I have placed capacitors all the places i could imagine (motors and on all power inputs to the individual IC) it could be needed, have a look at the new schematic...... what do you think, do i need any more, perhaps on the power source of the Arduinos (9V battery). Would you put a cap on the pot as well?
 
14  Using Arduino / Motors, Mechanics, and Power / Re: Stalling the motor... on: August 06, 2013, 04:34:16 am
Hi.
I have now made a schematic of what i have setup (criticism is welcomed, it is for a school project). @ joe mcd, as you can see i have a motor controlling the steering wheel - this is basically a servo with 2 potentiometers as encoders.
I am almost done with wiring up the system so now i have quite a bit of work cut out for me in regulating the damn thing. The issue is that the driver does not have any control of the steering wheel!!! the driver can apply a force on the steering wheel but it is locked in place due to the gear (it is meant to be like that) - the only thing that can rotate the steering wheel is the motor connected to the gear. So when a force is applied to the steering wheel the motors on the (road)wheels will start to turn because an equivalent force is "sent" to the motor. When the steering wheels turn, an error between the two potentiometers (one to measuring the angle on steering wheel and one measuring the traveled distance on the (road)wheels) is calculated - this error is used in my PID loop to move the steering wheel to a position in conjunction with the (road)wheels.

 The very tricky part is that because a force in the steering wheel is measured it is very hard to make the system work fluently and smooth. Thats because, the moment the motor starts to turn the steering wheel, the force is reduced hereby making the motor on the (road)wheels produce less torque, making them go back towards the center..... if you run this loop through a few times at high speed you will get a oscillating system..... and i am not quite sure how to go about making it better. My plan is to start very slowly (turning the steering wheel) and then (while tuning the PID and the code) try to increase the speed of which i apply force on the steering wheel. If you have ANY idea, please share, because i am a little bit out of my league by now.

Cheers

15  Using Arduino / General Electronics / "Quick and dirty" question on: August 06, 2013, 02:45:00 am
Hi
I have 2 potensiometers setup as a servo system in a circuit with motors and delicate measurements. My question is how you would go about supplying the 2 potentiometers with 5V? As i see it, i can either give them 5V from the arduino or i can use a voltage regulator. Which of the possibilities would you use and why?
I am afraid that if i use the Arduino i might get a noise problem when drawing a fair bit of current (10-15Amps) in the motor.

If you can answer the above question, then i have one more.
Lets say a lot of current is drawn by the motor which is hooked up to the same power supply as the rest of the system (24V batt) this will produce some noise in the rest of the system right? i can try to keep this down by placing decoupling-capacitors on every IC i have (does that go for the Arduino itself as well?) and hereby reducing the noise. But what i am not sure about is how much ripple would be seen if i placed a 5V voltage regulator in the system, when fluctuations occur because of the motors drawing current.

The diagram of my system is attached - feel free to comment ;-)

Cheers
Pages: [1] 2 3