KUCKY
October 28, 2019, 7:58pm
1
Hallo.
I modified a library. This library is located in the Libraries directory. I have included debug functions.
I would like to switch these functions on or off with a Preprocessor directive. I would like to activate these functions from my project. Look like this:
In der *.ino
#define PID_VALUES
in *.h
#ifndef PID_VALUES
#define DEBUG
#endif
in*.cpp:
#ifdef DEBUG
_P_out = P;
#endif
Unfortunately, no success. Can anybody help me?
Thanks in advance for your help.
Regards Willi
uxomm
October 28, 2019, 10:15pm
2
Do you have the define before you include *.h?
It will not work like this:
#include "myinclude.h"
#define mydefine
But it will like this:
#define mydefine
#include "myinclude.h"
MorganS
October 28, 2019, 10:25pm
3
But the .cpp file doesn't see that #define .
You have to have all the code in the .h file or pick another method.
gfvalvo
October 29, 2019, 12:34am
4
MorganS:
You have to have all the code in the .h file or pick another method.
.... and, the "all code in the .h file" method should only be used if the code is in a class or template (not sure about a namespace). Otherwise, you'll end up with multiple definitions of the functions should the .h file be included in more than one .cpp file.
"pick another method" is almost always the best option. But, you can see an example of the former method (using a class) by looking at the PRJC Encoder Library
KUCKY
October 29, 2019, 7:50am
5
Thanks for all your answers. I will try it.
Willi
KUCKY
October 29, 2019, 8:04am
6
No success.
Here the code:
This library was created by Mike Matera. She is integrated into my Drohne project. Thanks to him.
*.ino
/*
*
*
********************************************************/
#define PID_VALUES
#include <FastPIDnew.h>
#define PIN_INPUT A0
#define PIN_SETPOINT A1
#define PIN_OUTPUT 9
float Kp=0.1, Ki=0.5, Kd=0, Hz=10;
int output_bits = 8;
bool output_signed = false;
FastPIDnew myPID(Kp, Ki, Kd, Hz, output_bits, output_signed);
void setup()
{
Serial.begin(9600);
}
void loop()
{
int setpoint = analogRead(PIN_SETPOINT) / 2;
int feedback = analogRead(PIN_INPUT);
uint32_t before, after;
before = micros();
uint8_t output = myPID.step(setpoint, feedback);
after = micros();
analogWrite(PIN_OUTPUT, output);
Serial.print("runtime: ");
Serial.print(after - before);
Serial.print(" sp: ");
Serial.print(setpoint);
Serial.print(" fb: ");
Serial.print(feedback);
Serial.print(" out: ");
Serial.println(output);
delay(100);
}
*.h
#include <Arduino.h>
#include "FastPIDnew.h"
FastPIDnew::~FastPIDnew() {
}//---------------------------------------------- end of destructor ------------------------------
void FastPIDnew::clear() {
_last_sp = 0;
_last_out = 0;
_sum = 0;
_last_err = 0;
_cfg_err = false;
}//---------------------------------------------- end of clear ------------------------------------
bool FastPIDnew::setCoefficients(float kp, float ki, float kd, float hz) {
_p = floatToParam(kp);
_i = floatToParam(ki / hz);
_d = floatToParam(kd * hz);
return ! _cfg_err;
}//---------------------------------------------- end of setCoefficients --------------------------
bool FastPIDnew::setOutputConfig(int bits, bool sign) {
// Set output bits
if (bits > 16 || bits < 1) {
setCfgErr();
}
else {
if (bits == 16) {
_outmax = (0xFFFFULL >> (17 - bits)) * PARAM_MULT;
}
else{
_outmax = (0xFFFFULL >> (16 - bits)) * PARAM_MULT;
}
if (sign) {
_outmin = -((0xFFFFULL >> (17 - bits)) + 1) * PARAM_MULT;
}
else {
_outmin = 0;
}
}
return ! _cfg_err;
}//---------------------------------------------- end of setOutputConfig --------------------------
bool FastPIDnew::setOutputRange(int16_t min, int16_t max){
if (min >= max) {
setCfgErr();
return ! _cfg_err;
}
_outmin = int64_t(min) * PARAM_MULT;
_outmax = int64_t(max) * PARAM_MULT;
return ! _cfg_err;
}//---------------------------------------------- end of setOutputRange ---------------------------
bool FastPIDnew::configure(float kp, float ki, float kd, float hz, int bits, bool sign) {
clear();
setCoefficients(kp, ki, kd, hz);
setOutputConfig(bits, sign);
return ! _cfg_err;
}//---------------------------------------------- end of configure --------------------------------
uint32_t FastPIDnew::floatToParam(float in) {
if (in > PARAM_MAX || in < 0) {
_cfg_err = true;
return 0;
}
uint32_t param = in * PARAM_MULT;
if (in != 0 && param == 0) {
_cfg_err = true;
return 0;
}
return param;
}//---------------------------------------------- end of floatToParam -----------------------------
int16_t FastPIDnew::step(int16_t sp, int16_t fb) {
// int16 + int16 = int17
int32_t err = int32_t(sp) - int32_t(fb);
int32_t P = 0, I = 0;
int32_t D = 0;
if (_p) {
// uint16 * int16 = int32
P = int32_t(_p) * int32_t(err);
#ifdef DEBUG
_P_out = P;
Serial3.print("P-Portion = ");Serial3.println(_P_out);
#endif
}//-------------- end of P part ---------------
if (_i) {
// int17 * int16 = int33
_sum += int64_t(err) * int64_t(_i);
// Limit sum to 32-bit signed value so that it saturates, never overflows.
if (_sum > INTEG_MAX)
_sum = INTEG_MAX;
else if (_sum < INTEG_MIN)
_sum = INTEG_MIN;
// int32
I = _sum;
#ifdef DEBUG
_I_out = I;
Serial3.print("I-Portion = ");Serial3.println(_I_out);
#endif
}//-------------- end of I part ---------------
if (_d) {
// (int17 - int16) - (int16 - int16) = int19
int32_t deriv = (err - _last_err) - int32_t(sp - _last_sp);
_last_sp = sp;
_last_err = err;
// Limit the derivative to 16-bit signed value.
if (deriv > DERIV_MAX)
deriv = DERIV_MAX;
else if (deriv < DERIV_MIN)
deriv = DERIV_MIN;
// int16 * int16 = int32
D = int32_t(_d) * int32_t(deriv);
#ifdef DEBUG
_D_out = D;
Serial3.print("D-Portion = ");Serial3.println(_D_out);
#endif
}//-------------- end of D part ---------------
// int32 (P) + int32 (I) + int32 (D) = int34
int64_t out = int64_t(P) + int64_t(I) + int64_t(D);
// Make the output saturate
if (out > _outmax)
out = _outmax;
else if (out < _outmin)
out = _outmin;
// Remove the integer scaling factor.
int16_t rval = out >> PARAM_SHIFT;
// Fair rounding.
if (out & (0x1ULL << (PARAM_SHIFT - 1))) {
rval++;
}
#ifdef DEBUG
_pid_out = rval;
Serial3.print("Output = ");Serial3.println(_pid_out);
#endif
return rval;
}//-------------------------- end of step ---------------------------------------------------------
void FastPIDnew::setCfgErr() {
_cfg_err = true;
_p = _i = _d = 0;
}//-------------------------- end of setCfgErr ----------------------------------------------------
#ifdef DEBUG
int32_t FastPIDnew::getP() {
Serial3.print("FastPID P = ");Serial3.println(_P_out);
return _P_out;
}//-------------------------- end of getP ---------------------------------------------------------
int32_t FastPIDnew::getI() {
Serial3.print("FastPID I = ");Serial3.println(_I_out);
return _I_out;
}//-------------------------- end of getI ---------------------------------------------------------
int32_t FastPIDnew::getD() {
Serial3.print("FastPID D = ");Serial3.println(_D_out);
return _D_out;
}//-------------------------- end of getD ---------------------------------------------------------
int16_t FastPIDnew::getPIDout() {
Serial3.print("FastPID Out = ");Serial3.println(_pid_out);
return _pid_out;
}//-------------------------- end of getPIDout ----------------------------------------------------
#endif
/*----------------- end of FastPID class --------------------------------------------------------*/
Hello, I define a function in the (new) class to test, when debug should be used. From setup() in the sketch I set the debug of the library. The memory footprint will a small couple of bytes.
In the test object:
bool bDebug = false; // Initial state - no debug
bool ::setDebug (bool flag) {
bDebug = flag;
}
In my sketch.ino:
.setDebug(true); // Enable debug in
DrAzzy
October 29, 2019, 2:48pm
8
I have never figured out how to get a define from the ino to a library, if it is possible.
Intensely irritating limitation. In my core, I had to add tools submenus to set parameters in libraries bundled with the core that could have been handled with a define if it would just propagate from the .ino