Call me old-fashioned but I prefer to work with the actual values in situations like this.
In this particular case 16000000 / 2000000 will be 8, which is nice and even, so no problems there.
Yes I agree Nick, though if we use Timer3 with how it is originally we will not be doing the division first, but multiplying 16000000 by the value of microseconds and then dividing by 2000000.
In my setup function I do the following;
Timer3.initialize(100000);
Thereby setting the value of the variable in Timer3 to 100000 microseconds being the 100 milliseconds for my interrupt period.
I am guessing that if we were to take the original Timer3 code where it would multiply 16000000 by 100000 giving 1.6 x 10^12 which in this case does not fit withing the declared data 'long' type of microseconds.
Long data type is 2^32 which is only 2 and a wee bit x 10^9, so we are out by a long shot on the original code.
Changing it so that effectively we have as you say 8 x 100000 does fit and does work, and I have seen this to be the case.
This is just an error in the 'Timer3' library that others should be aware of.
But for other people following, remember the above is nothing to do with my existing problem, whereby the PWM signal from OCR3B simply ceases after some period of days of good operation.
Timer3.pwm(pin_TurbineDump, 0);
Why do you want a 0% duty cycle?
I do this so as be certain that on startup I am not presenting a value to the PWM output.
You may well be correct in thinking that it is not needed, as the PID control loop will feed the required value to the PWM function.
I guess belt and braces here a little bit doesn't hurt, and for me it is definite.
Rob,
It seems to me that it's either in the timer PWM code or the PID code. Can you verify one way or the other by checking that the timer is getting a correct value, say printing the value.
I guess that means waiting a few days.
Another option is to apply a sanity test to the PWM value, might be difficult though of the range is 0 to 100%.
You mean like the following?
/*-------------------------------------------------------------------------
pidControl.cpp
Created on: Sep 23, 2012
Author: Paul Alting van Geusau
*/
#include "pidControl.h"
// const type variable = value; comment
// pv sp err i d lst kp ki kd min max cv
PID hydroPID = {0, 2760, 0, 0, 0, 0, 5, 1, 0, 0, 1023, 0};
PID solarPID = {0, 2760, 0, 0, 0, 0, 10, 1, 0, 0, 1023, 0};
boolean loadStateHydro = false;
boolean loadStateSolar = false;
//-------------------------------------------------------------------------
// PID Load control of single phase AC from turbine:
//
// http://brettbeauregard.com/blog/category/pid/coding/
// https://groups.google.com/forum/?fromgroups=#!forum/diy-pid-control
//
void controlPID(PID& PID) {
/* data structure of PID block
int16_t pvPID;
int16_t spPID;
int16_t errPID;
int16_t intPID;
int16_t derPID;
int16_t pvLast;
const int16_t kp; // gain constant for proportional term:
const int16_t ki; // gain constant for integral term:
const int16_t kd; // gain constant for derivative term:
const int16_t outMin; // pid output minimum clamp value:
const int16_t outMax; // pid output maximum clamp value:
int16_t cvPID;
*/
PID.errPID = PID.pvPID - PID.spPID; // calculate setpoint error:
PID.intPID = PID.intPID + PID.ki * PID.errPID; // calculate integral term:
// constrain(PID.intPID, PID.outMin, PID.outMax); // clamp integral term:
if (PID.intPID > PID.outMax) { // clamp integral term:
PID.intPID = PID.outMax;
}
else if (PID.intPID < PID.outMin) {
PID.intPID = PID.outMin;
}
PID.derPID = PID.pvPID - PID.pvLast; // calculate derivative term:
PID.cvPID = PID.kp * PID.errPID + PID.intPID - PID.kd * PID.derPID; // calculate pid output:
// constrain(PID.cvPID, PID.outMin, PID.outMax); // clamp pid output value to 0 - 1023 for pwm:
if (PID.cvPID <= PID.outMin) { // clamp pid output value to 0 - 1023 for pwm:
PID.cvPID = PID.outMin;
}
else if (PID.cvPID > PID.outMax) {
PID.cvPID = PID.outMax;
}
PID.pvLast = PID.pvPID; // remember input value for next time:
}
Where I do perform range checks in the PID function.
You can see that my data structure holds the range, min of 0 and max of 1023 which is used in the last part of the above code.
So the PID output value, 'PID.cvPID' will then be constrained to those limits.
On the web page you see it as 0 - 100% on that dial guage you see, where as in the Arduino it is processed as 0 to 1023.
To wait a few days will mean I will need to cut that trace on the pcb that resets the cpu everytime I connect with the terminal program.
That might be a good thing anyhow for me, as it's generally a nuisance to have the Arduino reset everytime I want serial stuff.
More long term, I am looking more to developing debugs through the Ethernet connection.
Nick,
Second, after shifting dutyCycle (a 32 bit field) right 10 bits we have 22 bits left. But OCR3B is a 16 bit field. Now maybe the numbers are OK. Can you provide actual figures here?
I don't have any numbers to provide from the 'Timer3' library functions at present,
I will look at putting some debug points in the Timer3 function to get closer to the problem area.
I do appreciate the help.
Paul