Im writing some code for a arduino project and in the SHOOTER::LOADERclass, when i try to declare the servo objects,this is the code:
#include <Servo.h>
char t;
const bool DEBUG = true;
// Defined variables for loader class
template <typename T_ty> struct TypeInfo {
static const char * name;
};
template <typename T_ty> const char * TypeInfo<T_ty>::name = "unknown";
#define TYPE_NAME(var) TypeInfo< typeof(var) >::name
#define MAKE_TYPE_INFO(type) template <> const char * TypeInfo<type>::name = #type;
MAKE_TYPE_INFO( int )
MAKE_TYPE_INFO( float )
MAKE_TYPE_INFO( short )
MAKE_TYPE_INFO( String )
MAKE_TYPE_INFO( char )
MAKE_TYPE_INFO( byte )
class DEBUG;
class MOTOR;
class SHOOTER;
class COMM;
class DEBUG
{
public:
static void print(int argCount, ...) {
if (::DEBUG) {
return ;
}
va_list args;
va_start(args, argCount);
for (int i = 0; i < argCount; i++) {
String arg = va_arg(args, String);
Serial.print(arg);
}
Serial.println();
va_end(args);
}
};
class MOTOR
{
protected:
static const int LEFT_FRONT = 13;
static const int LEFT_REAR = 12;
static const int RIGHT_FRONT = 11;
static const int RIGHT_REAR = 10;
public:
MOTOR() {
pinMode(LEFT_FRONT, OUTPUT);
pinMode(LEFT_REAR, OUTPUT);
pinMode(RIGHT_FRONT, OUTPUT);
pinMode(RIGHT_REAR, OUTPUT);
}
static void motor_control(int lf = LOW, int lr = LOW, int rf = LOW, int rr = LOW) {
digitalWrite(LEFT_FRONT, lf);
digitalWrite(LEFT_REAR, lr);
digitalWrite(RIGHT_FRONT, rf);
digitalWrite(RIGHT_REAR, rr);
}
};
class SHOOTER
{
protected:
static const int LOADER1 = 5;
static const int LOADER2 = 6;
public:
class LOADER {
public:
static const int servo1 = 3;
static const int servo2 = 4;
static Servo l1;
static Servo l2;
static void set(float p) {
l1.write(p);
l2.write(p);
}
static void load() {
for (float p = 0; p <= 90 ; p += 0.25) {
set(p);
delay(15);
}
for (float p = 90 ; p >= 0 ; p -= 0.25) {
set(p);
delay(15);
}
}
};
SHOOTER() {
pinMode(LOADER1, OUTPUT);
pinMode(LOADER2, OUTPUT);
}
};
void setup() {
MOTOR motor;
SHOOTER shooter;
SHOOTER::LOADER::l1.attach(SHOOTER::LOADER::servo1);
SHOOTER::LOADER::l2.attach(SHOOTER::LOADER::servo2);
pinMode(9, OUTPUT); //Led
Serial.begin(9600);
}
void loop() {
if (Serial.available()) {
t = Serial.read();
if (isdigit(t)) {
t = (int) t;
Serial.print(t);
Serial.print(", ");
Serial.print(TYPE_NAME(t));
} else {
Serial.print(t);
Serial.print(", ");
Serial.print(TYPE_NAME(t));
}
Serial.println();
}
if (t == 'F') { //move forward(all motors rotate in forward direction)
MOTOR::motor_control(HIGH, LOW, HIGH);
}
else if (t == 'B') { //move reverse (all motors rotate in reverse direction)
MOTOR::motor_control(LOW, HIGH, LOW, HIGH);
}
else if (t == 'L') { //turn right (left side motors rotate in forward direction, right side motors doesn't rotate)
MOTOR::motor_control(LOW, LOW, HIGH);
}
else if (t == 'R') { //turn left (right side motors rotate in forward direction, left side motors doesn't rotate)
MOTOR::motor_control(HIGH);
}
else if (t == 'W') { //turn led on or off)
digitalWrite(9, HIGH);
}
else if (t == 'w') {
digitalWrite(9, LOW);
}
else if (t == 'S') { //STOP (all motors stop)
MOTOR::motor_control();
}
}
I get the following error
Arduino: 1.8.19 (Linux), Board: "Arduino Uno"
/tmp/ccgiae58.ltrans0.ltrans.o: In function `attach':
/app/Arduino/libraries/Servo/src/avr/Servo.cpp:240: undefined reference to `SHOOTER::LOADER::l1'
/app/Arduino/libraries/Servo/src/avr/Servo.cpp:242: undefined reference to `SHOOTER::LOADER::l1'
/app/Arduino/libraries/Servo/src/avr/Servo.cpp:244: undefined reference to `SHOOTER::LOADER::l1'
/app/Arduino/libraries/Servo/src/avr/Servo.cpp:245: undefined reference to `SHOOTER::LOADER::l1'
/app/Arduino/libraries/Servo/src/avr/Servo.cpp:250: undefined reference to `SHOOTER::LOADER::l1'
/app/Arduino/libraries/Servo/src/avr/Servo.cpp:240: undefined reference to `SHOOTER::LOADER::l2'
/app/Arduino/libraries/Servo/src/avr/Servo.cpp:242: undefined reference to `SHOOTER::LOADER::l2'
/app/Arduino/libraries/Servo/src/avr/Servo.cpp:244: undefined reference to `SHOOTER::LOADER::l2'
/app/Arduino/libraries/Servo/src/avr/Servo.cpp:245: undefined reference to `SHOOTER::LOADER::l2'
/app/Arduino/libraries/Servo/src/avr/Servo.cpp:250: undefined reference to `SHOOTER::LOADER::l2'
collect2: error: ld returned 1 exit status
exit status 1
Error compiling for board Arduino Uno.
it seemed that the servo.attach function could not access the l1 and l2 objects, so i tried defineing them in the global scope
#include <Servo.h>
Servo l1;
Servo l2;
// the usual declaratins
void setup(){
l1.attach(4);
l2.attach(5);
//everything else the same as previously
}
tho it did solve the error, i want to know how i can declare them inside the LOADER class itself
Related
I am building a program that measure the voltage of a component. When the potential is under 1 V, the vibration motor will turn on.
But my problem is, I want the Arduino to turn on the motor, if the voltage has been under 1 V for 10 seconds or more. For example, if the voltage level is under 1 V for 8 seconds and then it changes to over 5 V again, the motor should not turn on. Also, the motor should turn off after 3 seconds of vibration. I am able to satisfy the first condition.. but I'm not able to turn off the motor.
Here is my code so far:
int Pin = 2;
const float baselineVoltage = 200.0;
int belowBaselineVoltage = false;
unsigned long turnOnAt = 10000;
const unsigned long turnOnDelay = 10 * 1000;
void setup() {
Serial.begin(9600);
pinMode(Pin, OUTPUT);
}
void loop() {
int sensorValue = analogRead(A0);
float voltage = sensorValue * (5.0 / 1023.0);
float voltage2 = voltage*(1023.0 / 5.0);
Serial.println(voltage2);
delay(1000);
if (voltage2 < baselineVoltage) {
if (belowBaselineVoltage == true) {
if (millis() >= turnOnAt) {
digitalWrite(2, HIGH);
} else {
} else {
belowBaselineVoltage = true;
turnOnAt = millis() + turnOnDelay;
}
} else {
belowBaselineVoltage = false;
}
}
State machines are very popular in embedded systems. It makes the code behave in a predictable way, and that's invaluable when you do not have a debugger to step through the code.
Let's define your states.
motor_off: Motor is OFF, read voltage, if voltage < 1V, go to time_low_voltage state.
time_low_voltage: Motor is OFF, read voltage, if voltage >= 1V go to state motor_off. After 8 seconds in this state, go to motor_on state.
motor_on: Motor is ON. after 3 seconds, go to motor_off state.
We have 1 data item to keep track of, a timestamp of when the state has changed.
// **********************************
// shaker motor related definitions
enum class shaker_state : char
{
motor_off,
time_low_voltage,
motor_on,
};
struct shaker_data_t
{
shaker_state state;
unsigned int timestamp;
// you could add here a small buffer to hold a few previous values
// of ADC readings to do a bit of filtering... The median of 5 filter
// should work very well here. It is not absolutely needed for now,
// but you should consider having some kind of filter. The motor may
// introduce noise in the readings. We'll just keep the last reading for
// now.
unsigned int adc_value;
};
// constants are declared constexpr to save memory space.
constexpr unsigned int SHAKER_TIMEOUT_LOW_VOLTAGE = 8000; // in milliseconds
constexpr unsigned int SHAKER_TIMEOUT_MOTOR_ON = 3000; // .idem.
// Again to save memory, and allow for DAC related constants
// to be computed at compile-time.
constexpr inline float adc_value_to_volts(unsigned int value)
{
return value * (5.f / 1024.f);
}
constexpr inline unsigned int volts_to_adc_value(float tension)
{
return unsigned int(tension * (1024.f / 5.f));
}
constexpr unsigned int SHAKER_ADC_THRESHOLD = volts_to_adc_value(1.f);
constexpr int SHAKER_MOTOR = 2;
constexpr int SHAKER_ADC = A0;
// **********************************
// global data
shaker_data_t shaker;
// **********************************
static void shaker_control()
{
// always read adc.
shaker.adc_value = analogRead(SHAKER_ADC);
switch (shaker.state)
{
default: // in case of catastrophic error, turn motor OFF.
case shaker_state::motor_off:
digitalWrite(SHAKER_MOTOR, LOW);
if (shaker.adc_value < SHAKER_ADC_THRESHOLD)
{
shaker.state = shaker_state::time_low_voltage;
shaker.timestamp = (unsigned int)millis();
}
break;
case shaker_state::time_low_voltage:
digitalWrite(SHAKER_MOTOR, LOW);
if (shaker.adc_value >= SHAKER_ADC_THRESHOLD)
{
shaker.state = shaker_state::motor_off;
}
else if ((unsigned int)millis() - shaker.timestamp >= SHAKER_TIMEOUT_LOW_VOLTAGE)
{
digitalWrite(SHAKER_MOTOR, HIGH);
shaker.state = shaker_state::motor_on;
shaker.timestamp = (unsigned int)millis();
}
break;
case shaker_state::motor_on:
digitalWrite(SHAKER_MOTOR, HIGH);
if ((unsigned int)millis() - shaker.timestamp >= SHAKER_TIMEOUT_MOTOR_ON)
{
digitalWrite(SHAKER_MOTOR, LOW);
shaker.state = shaker_state::motor_off;
shaker.timestamp = (unsigned int)millis();
}
break;
}
}
// **********************************
void setup()
{
Serial.begin(9600);
digitalWrite(SHAKER_MOTOR, LOW);
pinMode(SHAKER_MOTOR, OUTPUT);
shaker.state = shaker_state::motor_off;
shaker.timestamp = (unsigned int)millis();
}
// **********************************
void loop()
{
// get temp and control moror.
shaker_control();
// shaker_control is very fast and never blocks, so you have plenty
// of extra time to blink LEDs, read switches, etc...
}
[EDIT]
Here is a simple median of 5 filter that you can add to filter out unwanted noise on the ADC reading.
class median_of_5_filter
{
public:
void push(unsigned int value)
{
buffer_[next_] = value;
if (++next_ >= 5)
next_ = 0;
compute();
}
unsigned int get() const
{
return filtered_;
}
private:
void compute()
{
// bubble sort, but only the first 3 elements
unsigned int buf_copy[5] = { buffer_[0], buffer_[1], buffer_[2],
buffer_[3], buffer_[4] };
for (unsigned char i = 0; i < 3; ++i)
{
auto min_index = i;
auto min_value = buf_copy[i];
for (unsigned char j = i + 1; j < 5; ++j)
{
if (buf_copy[j] < min_value)
{
min_value = buf_copy[j];
min_index = j;
}
}
if (i != min_index)
swap(buf_copy[i], buf_copy[min_index]);
}
filtered_ = buf_copy[2];
}
static void swap(unsigned int& a, unsigned int& b)
{
auto t = a;
a = b;
b = t;
}
private:
unsigned int filtered_ = 0;
unsigned char next_ = 0;
unsigned int buffer_[5] = {};
};
To use:
struct shaker_data_t
{
// ...
median_of_5_filter adc_value;
};
// when reading ADC...
shaker.adc_value.push(analogRead(SHAKER_ADC));
// to get filtered adc reading
if (shaker.adc_value.get() < SHAKER_ADC_THRESHOLD)
I am trying to access a function of a pointer and it does not work and it gives me an LoadStoreAlignmentCause Exception. Furthermore I want to check if the pointer does exist, but it always returns true for that.
LedFunction.h
#include "Led/LedStates.h"
class LedStates;
class LedFunction {
public:
LedStates *state;
virtual bool init();
bool loadValues();
virtual void render() = 0;
};
LedFunction.cpp
#include "Led/LedFunction.h"
bool LedFunction::init() {
return false;
}
RainbowFunction.h
class RainbowFunction: public LedFunction {
public:
RainbowFunction() {
Serial.println("Rainbow Constructor.");
}
void render() {
Serial.println("From Rainbow...");
}
}
};
LedStates.h
#include "Handlers/LedHandler.h"
#include "Led/LedFunction.h"
class LedHandler;
class LedFunction;
class LedStates {
public:
uint8_t (*values)[3];
int count = 0;
bool dirty = false;
LedHandler* ledHandler;
LedFunction* function = 0;
LedStates(LedHandler* handler);
void setFunction(LedFunction *newFunction);
void setRgb(int i, uint8_t r, uint8_t g, uint8_t b);
void render(); //TODO check virtual key
void setValues(LedStates &to);
void commit();
void fade(LedStates &to, long f0, long f1);
};
LedStates.cpp
#include "Led/LedStates.h"
#include "Led/Animations/RainbowFunction.h"
LedStates::LedStates(LedHandler* handler) {
this->ledHandler = handler;
count = ledHandler->getLength();
values = new uint8_t[count][3];
this->setFunction(new RainbowFunction());
}
void LedStates::setFunction(LedFunction* newFunction) {
Serial.println("SETTING FUNCTION");
if(function)
delete function; //TODO check virtual destructor
function = newFunction;
if(!function)
return;
function->state = this;
Serial.println("-----Setting Done-----");
}
void LedStates::render() {
Serial.println(2);
Serial.println("B:" + (String) (function != 0));
Serial.println("B:" + (String) (function != false));
if(function == nullptr) { //This is the check that is not working properly
Serial.println(22222);
//delay(1000);
//function->render();
} else {
Serial.println(33333);
function->render();
}
Serial.println(3);
}
LedHandler.h
#include <Arduino.h>
#include <Adafruit_NeoPixel.h>
#include <FastLED.h>
//#include "Led/LedFunction.h"
#include "Led/LedStates.h"
#include "Led/Fading.h"
class LedStates;
class LedHandler {
public:
LedHandler(int length, uint16_t pin);
void clear();
void show();
void setColor(int s, int r, int g, int b);
void loop();
Adafruit_NeoPixel getStrip();
int getLength();
private:
LedStates* currentState;
LedStates* targetState;
Fader<LedStates> *ledFader;
int length;
Adafruit_NeoPixel strip;
CRGB* leds;
};
LedHandler.cpp
#include "Handlers/LedHandler.h"
LedHandler::LedHandler(int length, uint16_t pin) {
Serial.begin(115200);
this->length = length;
this->strip = Adafruit_NeoPixel(length, pin);
this->strip.begin();
CRGB* arr = new CRGB[length];
this->leds = arr;
FastLED.addLeds<WS2812B, 6, RGB>(leds, 60).setCorrection(TypicalLEDStrip);
//Serial.println("-----Creating States-----");
LedStates currentLedStates = LedStates(this);
LedStates targetLedStates = LedStates(this);
Fader<LedStates> ledFader = Fader<LedStates>(currentLedStates, targetLedStates);
//Serial.println("-----Created States-----");
this->currentState = ¤tLedStates;
this->targetState = &targetLedStates;
this->ledFader = &ledFader;
}
void LedHandler::loop() {
Serial.println("--::--::--::--::--::--::--");
currentState->render();
Serial.println(99);
Serial.println(6);
currentState->commit();
Serial.println("-------------------------");
delay(10000);
}
The Serialmonitor output:
SETTING FUNCTION
-----Setting Done-----
Rainbow Constructor.
SETTING FUNCTION
-----Setting Done-----
--::--::--::--::--::--::--
2
B:1
B:1
33333
Exception (9):
epc1=0x40202a92 epc2=0x00000000 epc3=0x00000000 excvaddr=0x4020d32d depc=0x00000000
These lines define local variables inside the function LedHandler::LedHandler(int length, uint16_t pin):
LedStates currentLedStates = LedStates(this);
LedStates targetLedStates = LedStates(this);
These lines remember the address of the local variables:
this->currentState = ¤tLedStates;
this->targetState = &targetLedStates;
This line deletes the local variables so the memory can be used for something else:
}
and this line calls the something else (nobody knows what it will be):
currentState->render();
I'm trying to count how many instances or the class mole2 there are and store the number in a public static variable called mole_count.
mole2.h
#ifndef mole2_h
#define mole2_h
#include "Arduino.h"
class mole2 {
public:
mole2(int input, int output);
void popUp();
void popdown();
boolean moleBrainThinkPopUpNow();
void setUpTimer(int up_timer);
boolean didMoleGetHit();
void setRecoveryTimer(int recovery_timer);
void decrementRecoveryTimer();
boolean dosePlayerMistMole();
void moleReset();
int input, output;
static int mole_count;
static int odds_of_poping;
private:
boolean _is_popped = false;
int _up_timer = 0;
int _recovery_timer = 0;
};
#endif
mole2.cpp
#include "Arduino.h"
#include "mole2.h"
int mole2::odds_of_poping = 10;
mole2::mole2(int input, int output) {
input = input;
output = output;
int mole2::mole_count = mole2::mole_count + 1;
pinMode(input, INPUT);
pinMode(output, OUTPUT);
}
void mole2::popUp() {
_is_popped = true;
digitalWrite(input, HIGH);
}
void mole2::popdown() {
_is_popped = false;
digitalWrite(input, LOW);
}
boolean mole2::moleBrainThinkPopUpNow() {
if (_recovery_timer == 0 && _is_popped == false && rand() % odds_of_poping == 1) {
popUp();
return true;
}
else {
return false;
}
}
void mole2::setUpTimer(int up_timer) {
_up_timer = up_timer;
}
boolean mole2::didMoleGetHit() {
if (_is_popped == true && digitalRead(input) == HIGH) {
popdown();
_up_timer = 0;
return true;
}
else {
return false;
}
}
void mole2::setRecoveryTimer(int recovery_timer) {
_recovery_timer = recovery_timer;
}
void mole2::decrementRecoveryTimer() {
if (_recovery_timer > 0) {
_recovery_timer--;
}
}
boolean mole2::dosePlayerMistMole() {
if (_is_popped == true && _up_timer > 0) {
_up_timer--;
}
if (_is_popped == true && _up_timer == 0) {
popdown();
return true;
}
else {
return false;
}
}
void mole2::moleReset() {
popdown();
_up_timer = 0;
_recovery_timer = 0;
}
FullError
Arduino: 1.6.12 (Windows 7), Board: "Arduino/Genuino Uno"
C:\Users\Strings\Documents\Arduino\libraries\mole2\mole2.cpp: In constructor 'mole2::mole2(int, int)':
C:\Users\Strings\Documents\Arduino\libraries\mole2\mole2.cpp:9:25: error: qualified-id in declaration before '=' token
int mole2::mole_count = mole2::mole_count + 1;
^
exit status 1
Error compiling for board Arduino/Genuino Uno.
This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
First this:
int mole2::mole_count = mole2::mole_count + 1;
has no sense: you're declaring something and assigning it to its value + 1
Anyway, you already declared mole_count in your class. Since you're in the constructor, you're in the mole2 class already (the "qualified-id" bit comes from here), so you just have to do:
mole_count++;
Also, you have to declare storage for the variable in the .cpp class & initialize it:
int mole2::mole_count = 0;
You have to do the same thing as with odds_of_poping:
Definition:
int mole2::mole_count = 0; // initialization can be ommited as static variables are initialized to the default value
and later just increment: ++mole_count;
int mole2::mole_count has already been defined. This is trying to make another int mole2::mole_count. Lose the int and assign to the pre-existing variable.
You also need to allocate storage for and initialize mole_count. Place
int mole2::mole_count = 0; // replace 0 if starting with more than 0 mole2s
in somewhere around
int mole2::odds_of_poping = 10;
in mole2.cpp
Also watch out for
input = input;
output = output;
The compiler doesn't know whether you want to use the passed parameter input or the class's input so it will pick the closest defined input, the parameter, on both sides of the = . Refrain from reusing the same variable names in the same places at the same times.
This can be resolved by explicitely stating
this->input = input;
this->output = output;
Or (my favourite!) by using the member initializer list
mole2::mole2(int input, int output): input(input), output(output) {
But to prevent other confusion you should still not repeat the names.
I am trying to write a library that reads 5 variables, then sends them through the serial port to a bluetooth reciever, I am getting a number of errors and I am not sure where to go from here, do I need to implement pointers?
Here is the Arduino code....
#include <serialComms.h>
serialComms testing;
void setup()
{
Serial.begin(9600);
}
char data[] = {1,2,3,4,5,6};
void loop()
{
for(int t = 0;t<6;t++)
{
data[t] = data[t]++;
}
testing.updateUser(data);
delay(250);
}
serialComms.cpp
#include <Arduino.h>
#include <serialComms.h>
void serialComms::init()
{
// This is where the constructor would be...right now we are too stupid to have one
}
void serialComms::readAllBytes() // Target Pin,Values
{
}
void serialComms::assignBytes()
{
for(int t = 0;t<5;t++)
{
digitalWrite(12,HIGH);
delay(250);
digitalWrite(12,LOW);
}
}
void serialComms::updateUser(char t[])
{
Serial.write(t,5);
}
serialComms.h
#ifndef serialComms_h
#define serialComms_h
/* serialComms Class */
class serialComms
{
public:
serialComms() {};
void init();
void readAllBytes(); // Will be used to create the array --> two variables for now...
void assignBytes();
void updateUser(char t[]);
};
#endif
Here are the errors that I am getting...
- serialComms.cpp:28: error: initializing argument 1 of 'virtual size_t Print::write(const uint8_t*, size_t)'
-
- serialComms.cpp:28: error: invalid conversion from 'char*' to 'const uint8_t*'
- serialComms.cpp: In member function 'void serialComms::updateUser(char*)':
- serialComms.cpp:27: error: expected primary-expression before ']' token
Example:
void setup()
{
Serial.begin(9600);
char string_array[] = "hello";
char data_array[] = {1,2,3,4,5,6};
unsigned char data_array_uchar[] = {21,22,23,24,25,26};
uint8_t uint8_array[] = {11,12,13,14,15,16};
char alpha_array[] = {0x41,0x42,0x43,0x44,0x45,0x46};
// take note that sizeof() is a precompile command... number of places/size of each place.
updateUserPrint(string_array);
updateUserWrite(data_array, sizeof(string_array));
updateUserWriteUchar(data_array_uchar, sizeof(data_array_uchar));
updateUserWriteUchar(uint8_array, sizeof(uint8_array));
updateUserWriteUint(uint8_array, sizeof(string_array));
updateUserAlpha(alpha_array, sizeof(string_array));
}
void updateUserPrint(char *s)
{ //note a string aka array of char's is ended with a null.
Serial.print(s); // this can detect.
Serial.println();
}
void updateUserWrite(char *t, size_t len)
{ //note an array of int's is not ended with a null. so you need to know how long it is.
for (int n = 0; n < len ; n++) {
Serial.print(t[n],DEC);
Serial.print(",");
}
Serial.println();
}
void updateUserWriteUchar(unsigned char *t, size_t len)
{ //note an array of int's is not ended with a null. so you need to know how long it is.
for (int n = 0; n < len ; n++) {
Serial.print(t[n],DEC);
Serial.print(",");
}
Serial.println();
}
void updateUserWriteUint(uint8_t *t, size_t len)
{ //note an array of int's is not ended with a null. so you need to know how long it is.
for (int n = 0; n < len ; n++) {
Serial.print(t[n],DEC);
Serial.print(",");
}
Serial.println();
}
void updateUserAlpha(char *t, int len)
{ //note an array of int's is not ended with a null. so you need to know how long it is.
for (int n = 0; n < len ; n++) {
Serial.write(t[n]);
}
Serial.println();
}
produces the following:
hello
1,2,3,4,5,6,
21,22,23,24,25,26,
11,12,13,14,15,16,
11,12,13,14,15,16,
ABCDEF
Serial.write can only send constant strings like
Serial.write(“hello”);
That is why the error error: invalid conversion from 'char*' to 'const uint8_t*'
use as
char temp[max_length];
sprintf(temp,"%s",t);
Serial.write(temp);
I have a class called PID. I #include the header for the class. I have been using this class in various files including the file the error points to. The compiler complains about defining the function declaration itself void dispPid(char *name, PID &pid){}. All the contents of the function are commented out. The error reads AutoTrucker:-1: error: 'PID' has not been declared with no other errors. Commenting out the function in its entirety removes the error completely, compiles and works fine.
What really gets me confused is that:
The error points to line -1
The file exists, and is included
I use this PID class in right above as a pointer:
PID *pid;
if (chk(arg2,"roll")){pid = &aircraft.ap.pid.wingLeveler;}
else if (chk(arg2,"heading") || chk(arg2,"hdg")){pid = &aircraft.ap.pid.headingHold;}
else if (chk(arg2,"pitch")){pid = &aircraft.ap.pid.pitchHold;}
...
This code specified directly above compiles and works properly. So what gives?
EDIT 2:
This is such a jimmy rig it makes me sick. But is does solve the problem for the time being. So what gives? The compiler does not like the PID class as a function argument, but it finds it acceptable inside the function? I would really like to find a proper solution to this instead of passing in a void pointer and converting it!
void dispPid(const char *name, void *tpid)
{
PID &pid = *((PID*)tpid);
...
}
EDIT: (adding in some more source code as requested)
void cmdsPid(char *buffer)
{
if (chk(buffer,"pid"))
{
char *arg1 = next(buffer);
if (chk(arg1,"ls"))
{
char *arg2 = next(arg1);
if (chk(arg2,"") || chk(arg2,"all"))
{
/*
Serial.println("Listing all PIDs:");
dispPid("Roll",aircraft.ap.pid.wingLeveler);
Serial.print("\t");
dispPid("Heading",aircraft.ap.pid,headingHold);
dispPid("Pitch",aircraft.ap.pid,pitchHold);
Serial.print("\t");
dispPid("V-Rate",aircraft.ap.pid.climbHold);
Serial.print("\t\t");
dispPid("Altitude",aircraft.ap.pid.altHold);
dispPid("Throttle",aircraft.ap.pid.throttleHold);
dispPid("Slip",aircraft.ap.pid.slipHold);
*/
}
else
{
Serial.print("Unknown argument");
}
}
else if (chk(arg1,"w"))
{
char *arg2 = next(arg1);//name
char *arg3 = next(arg2);//attr
char *arg4 = next(arg3);//val
double val = 0.0;
bool onoff = false;
if (chk(arg3,"inv"))
{
onoff = (chk(arg4,"off") || chk(arg4,"-"));
}
else if (chk(arg3,"max") || chk(arg3,"min"))
{
if (chk(arg4,"off") || chk(arg4,"-"))
{
onoff = false;
}
else
{
onoff = true;
val = parseDoubleArg(arg4);
}
}
else
{
val = parseDoubleArg(arg4);
}
PID *pid;
if (chk(arg2,"roll")){pid = &aircraft.ap.pid.wingLeveler;}
else if (chk(arg2,"heading") || chk(arg2,"hdg")){pid = &aircraft.ap.pid.headingHold;}
else if (chk(arg2,"pitch")){pid = &aircraft.ap.pid.pitchHold;}
else if (chk(arg2,"vrate")){pid = &aircraft.ap.pid.climbHold;}
else if (chk(arg2,"alt")){pid = &aircraft.ap.pid.altHold;}
else if (chk(arg2,"th")||chk(arg2,"thr")||chk(arg2,"thro")||chk(arg2,"throttle")){pid = &aircraft.ap.pid.throttleHold;}
else if (chk(arg2,"slip")){pid = &aircraft.ap.pid.slipHold;}
if (chk(arg3,"p")){pid->setPGain(val);}
else if (chk(arg3,"i")){pid->setIGain(val);}
else if (chk(arg4,"d")){pid->setDGain(val);}
else if (chk(arg4,"max"))
{
if (onoff){pid->setLimitMax(val);}
else{pid->disableMaxLimit();}
}
else if (chk(arg4,"min"))
{
if (onoff){pid->setLimitMin(val);}
else{pid->disableMinLimit();}
}
}
else
{
Serial.println("Unknown argument");
}
}
}
void dispPid(char *name, PID &pid){}
The PID class (header):
#pragma once
#define PID_VERSION "1.1"
#include <inttypes.h>
#define allowLimitMax 1
#define allowLimitMin 2
#define invert 4
#define enabled 8
class PID
{
private:
double pGain,iGain,dGain;
double integrator;
double *input,*output,*setpoint;
double lastInput;
double limitMax,limitMin;
char settings;
public:
struct Spid {
double p,i,d,limitMax,limitMin;
char settings;
};
PID();//constructor
//getters
double getPGain();
double getIGain();
double getDGain();
double getLimitMax();
double getLimitMin();
bool isLimitMaxSet();
bool isLimitMinSet();
bool isInverted();
//setters
void setPGain(double newPGain);
void setIGain(double newIGain);
void setDGain(double newDGain);
void setPIDGain(double newPGain, double newIGain, double newDGain);
void setInput(double *newInput);
void setOutput(double *newOutput);
void setSetpoint(double *newSetpoint);
void setIOS(double *newInput, double *newOutput, double *newSetpoint);
void setLimitMax(double newLimitMax);
void setLimitMin(double newLimitMin);
void setLimits(double newLimitMin, double newLimitMax);
void disableMaxLimit();
void disableMinLimit();
void disableLimits();
void zeroOutIntegrator();
void nullOut();
void setInverted(bool newInvert);
//actions
void run();
void run(double dt);
void setFrom(Spid copy);
void copy(Spid ©);
};