Show Posts
Pages: [1] 2 3 4
1  Using Arduino / Project Guidance / Re: Alternator sizing for energy harvest (hydro)? on: September 23, 2014, 04:07:49 pm

Nice guys........

It is supposed to be a permanent installation so the engineering level is high. Battery is a good idea but out of the question. It is inside so no sunlight for cells. Regarding pressure drop, no limit but i dont want to be ridiculous. It is in a production facility so there is a LARGE pump connected (but unfortunately i cant pull power from a socket). But, when i do the math (pressure drop multiplied with volume flow) the available power becomes high quite quick. It is in SI-units so the pressure is in Pascal (100.000 to the Bar). Just to put it in perspektive - If 1/10 of a bar (10.000Pa or roughly 1m loss of head)  could be introduced, you could theoretically harvest 138W (which is about 70 times more then i need) if i am not mistaking.
Regarding the gearbox i was planning on using a belt drive with a ratio. I may need to make it in several steps, but there is a very high efficiency associated with belt drives - 95%ish.
Regarding the diameter of the pipe, it will vary but on the pilot project a 200mm.   

you will need to see 4000-6000rpm at the alternator shaft for good output.

I guess that depends on the size of the alternator. The small air-core motors from eg Maxon, have a no load speed of tens of thousands RPM, but down to 1200RPM can also be found in their catalogue.

The reason i would introduce a venturi is due to the equation i showed earlier: P=0,5*rho*A*v^3 because of the term v^3 so i would perhaps crank that up by reducing the cross section hereby increasing the velocity and reducing the pressure.

just a thought.

Thx alt
2  Using Arduino / Project Guidance / Re: Alternator sizing for energy harvest (hydro)? on: September 23, 2014, 11:19:56 am
I try to keep it short so you dont have to spend too much time reading but it does not seem to be working out for me ;-)
3  Using Arduino / Project Guidance / Re: Alternator sizing for energy harvest (hydro)? on: September 23, 2014, 11:17:14 am
..............................

@PaulS: Okay okay okay, here is the entire story - i guess i have to be happy since people seem to be paying attention to the small details ;-)
It is not a creek but flow in a pipe - i know there is more or less constant flow but form time to time the flow is stopped in order to maintain the pipes and the area they deliver water to. It is not for long but long enough for me to need a battery. Initially i have to design the harvester/logger for this system, but over time it will be implemented on other pipes with other velocities and dimensions.
I have already been looking at the propeller design, but the velocity is so slow (in the order of 0.5m/s) and the pitch of the propeller will be about 20 deg. I dont think is is very efficient to get lower then that - therefore the 50RPM. I know that i might need to implement a diffuser but i would rather not due to several factors.

Regarding the DC motor jremington, then i know about the relationship you are describing but i would rather use a BLDC due to maintenance (brushes) and noise (spikes from the commutator) in the system.

Regarding the energy needed i have calculated that it will be in the region of 2Wh/24h (on average 0,083W because the system is in sleep mode when not transmitting wirelessly)
Correct me if i am wrong but i was planning to use the dc/dc converter to boost my voltage to the desired in order to charge. Stepping up the voltage will reduce the amps but that is how it has to be. I know that the available  power in a stream of water is

P=0,5*density_of_water*A*v^3=1,3W
Cp is Betz limit = 59%, v= velocity of medium

It can be shown that the maximum theoretical power one is able to extract is dictated by Betz limit - therefore it would be 0,8W

BUT (not yelling)
The thing is that the calculation is for flow in an open canal - here we have water in a duct. The harvested energy will be the pressure drop over the propeller multiplied with the volume flow [m^3/sek]. But since i don't know what the pressure drop will be and i cant measure it i am a bit lost.



4  Using Arduino / Project Guidance / Alternator sizing for energy harvest (hydro)? on: September 23, 2014, 08:52:20 am
Hey forum.

This might be a silly question but here it goes.

I am designing a small energy harvester/measuring unit. A propeller is placed in a stream of water and will act as a energy harvester.  It should be able to generate power enough from the flow to send data twice a minute through an Xbee

The propeller will be rotating at about 50RPM - this is obviously not changeable.

Hardware:
  • I will be using an arduino Fio - it seems to have a charging circuit and Xbee is easily mounted. I will add a 1000mAh battery to have some power in reserve, should the water stop flowing.
  • Xbee pro to send data

The general approach i thought about taking was to connect a rectifier circuit to the alternator to get a DC voltage. Then to a DC/DC converter that regulates the voltage to > 3.7V (compatible with Arduino Fio) and then directly into the Arduino Fio since it will take care of charging the battery.

Question 1) How does that plan sound???  

Question 2) HOW DO I CHOOSE THE ALTERNATOR????
I am aware that i can use a BLDC motor, but how do i determine how large it has to be? It would be great if i could use a fan from a PC - knowing that the flow is almost constantly such that i will have 50RPM on my propeller i dont need to charge in bursts but rather a lower constant charge. But  

Question 3) I obviously need some kind of gearing since the low RPM wont give me any voltage from the alternator. But how many RPM will i be aiming for - would i want to aim for half the no load speed of my motor/alternator as the speed/power characteristic plot of a motor indicates?
  


Any help is greatly appreciated.

Bear
5  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
6  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
7  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  



8  Using Arduino / Motors, Mechanics, and Power / Re: Stopping a Motor with a Current Sensor... on: November 07, 2013, 11:53:02 am
Like this?
9  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
10  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. 
11  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);

}



















12  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
13  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
14  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
15  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);

}


















Pages: [1] 2 3 4