Pointer to element in struct- help with scary compiler warnings

I need help with syntax best dealing with one structure that contains two substructures. I want to pass a part of a structure into a subroutine (debounce), pass by reference, where it gets some values updated. The struc is volatile because the ISR modifies it.
This compiles, runs... but has notes and warnings I cannot understand and kind of worry about:

F:\Data\Arduino\LL_Det_Jun03_fix_syntax.ino: In function 'void __vector_11()':
F:\Data\Arduino\LL_Det_Jun03_fix_syntax.ino:77:23: warning: invalid conversion from 'volatile electrodestruct*' to 'electrodestruct*' [-fpermissive]
    Debounce_Electrode(&tank.top_sensor, SensorTopPin);
                       ^~~~~~~~~~~~~~~~
F:\Data\Arduino\LL_Det_Jun03_fix_syntax.ino:47:6: note:   initializing argument 1 of 'void Debounce_Electrode(electrodestruct*, int)'
 void Debounce_Electrode(electrodestruct *p, int pin_number) {
      ^~~~~~~~~~~~~~~~~~
F:\Data\Arduino\LL_Det_Jun03_fix_syntax.ino:78:23: warning: invalid conversion from 'volatile electrodestruct*' to 'electrodestruct*' [-fpermissive]
    Debounce_Electrode(&tank.bottom_sensor, SensorBottomPin);
                       ^~~~~~~~~~~~~~~~~~~
F:\Data\Arduino\LL_Det_Jun03_fix_syntax.ino:47:6: note:   initializing argument 1 of 'void Debounce_Electrode(electrodestruct*, int)'
 void Debounce_Electrode(electrodestruct *p, int pin_number) {
      ^~~~~~~~~~~~~~~~~~
F:\Data\Arduino\LL_Det_Jun03_fix_syntax.ino: In function 'void loop()':
F:\Data\Arduino\LL_Det_Jun03_fix_syntax.ino:94:41: warning: invalid conversion from 'volatile electrodestruct*' to 'electrodestruct*' [-fpermissive]
    Serial.print("Top=");  Sensors_Print(&tank.top_sensor);
                                         ^~~~~~~~~~~~~~~~
F:\Data\Arduino\LL_Det_Jun03_fix_syntax.ino:70:6: note:   initializing argument 1 of 'void Sensors_Print(electrodestruct*)'
 void Sensors_Print(electrodestruct *q) {
      ^~~~~~~~~~~~~
F:\Data\Arduino\LL_Det_Jun03_fix_syntax.ino:95:43: warning: invalid conversion from 'volatile electrodestruct*' to 'electrodestruct*' [-fpermissive]
    Serial.print(", Bot=");  Sensors_Print(&tank.bottom_sensor);
                                           ^~~~~~~~~~~~~~~~~~~
F:\Data\Arduino\LL_Det_Jun03_fix_syntax.ino:70:6: note:   initializing argument 1 of 'void Sensors_Print(electrodestruct*)'
 void Sensors_Print(electrodestruct *q) {
      ^~~~~~~~~~~~~

This is the sketch stripped down to the basics to show the compiler messages:

#define DEBOUNCEMAX 10 // 10 of 100msec RTI calls

//------  I / O   P i n   A s s i g n m e n t s  -----  U N O  ------------------
#define SensorTopPin 3   // pin "D3", PD3
#define SensorBottomPin 4 // pin "D4", PD4

//------  G l o b a l   V a r s  ----------------------------------------------

typedef struct {   
   boolean wet;
   unsigned int debounce_integrator;
} electrodestruct;
//-----------------------------------
typedef struct {   
   electrodestruct top_sensor;
   electrodestruct bottom_sensor;
} tankstruct;
//*****************************************************************************
volatile tankstruct tank;


//-----------------------------------------------------------------------------
void Debounce_Electrode99(electrodestruct p, int pin_number) {
// debounce water sensor 
   if (digitalRead(pin_number) == 0) {
      if (p.debounce_integrator > 0) {
         p.debounce_integrator--;
      }
   }
   //----------------------      
   else if (p.debounce_integrator < DEBOUNCEMAX) {
      p.debounce_integrator++;
   }
   //----------------------            
   if (p.debounce_integrator == DEBOUNCEMAX) {
      p.wet = true;
   }
   else if (p.debounce_integrator == 0) {
      p.wet = false;
   }
   if (p.debounce_integrator > DEBOUNCEMAX) { // safety clip if corrupt
      p.debounce_integrator = DEBOUNCEMAX;
   }
} // sub
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void Debounce_Electrode(electrodestruct *p, int pin_number) {
// debounce water sensor using integrator, not enough for slow sloshing. RTI@10Hz for 10 is 1Hz.
   if (digitalRead(pin_number) == 0) {
      if (p->debounce_integrator > 0) {
         p->debounce_integrator--;
      }
   }
   //----------------------      
   else if (p->debounce_integrator < DEBOUNCEMAX) {
      p->debounce_integrator++;
   }
   //----------------------            
   if (p->debounce_integrator == DEBOUNCEMAX) {
      p->wet = true;
   }
   else if (p->debounce_integrator == 0) {
      p->wet = false;
   }
   if (p->debounce_integrator > DEBOUNCEMAX) { // safety clip if corrupt
      p->debounce_integrator = DEBOUNCEMAX;
   }
} // sub
//-----------------------------------------------------------------------------
void Sensors_Print(electrodestruct *q) {
   Serial.print(q->wet);
   Serial.print(", d_integ="); 
   Serial.print(q->debounce_integrator);
}
//--------------------------------------------------------------------------------------
ISR(TIMER1_COMPA_vect) { // every 100msec
   Debounce_Electrode(&tank.top_sensor, SensorTopPin);
   Debounce_Electrode(&tank.bottom_sensor, SensorBottomPin);
}
//-------------------------------------------------
//************************************************************************
void setup() {
 
  pinMode(SensorTopPin, INPUT);      // sets the digital pin as input
  pinMode(SensorBottomPin, INPUT);      // sets the digital pin as input
  //----------------------------
  Serial.begin(115200); delay(50);   // open the serial port at 115.2K for dev
  //-------------------------------
} 
    
//*******************************************************************************************
void loop() {

   Serial.print("Top=");  Sensors_Print(&tank.top_sensor); 
   Serial.print(", Bot=");  Sensors_Print(&tank.bottom_sensor);
   Serial.println("");   
   delay(300);
} //main
//*******************************************************************************************

Why are you using an interrupt instead of blink-without-delay?

I always use an RTI for debouncing. That way I know what timer I'm using.
Blink-without-delay, I could find no docs about it and digging for that is no fun.

If

void Debounce_Electrode(electrodestruct *p, int pin_number) {

becomes

void Debounce_Electrode(volatile electrodestruct *p, int pin_number) {

and

void Sensors_Print(electrodestruct *q) {

becomes

void Sensors_Print(volatile electrodestruct *q) {

then the compiler is happy.

Thanks so much.
I didn't know there is a difference when referencing a volatile variable, verses declaring it. I though it was only important for the declaration.

There does remain a serious bug.

The adding a volatile to type make an absolute different (and incompatible) type of variable.

I deleted a bunch of code and routines for this post - just to give the bare bones, stripped down problem to make it easier for people to help. I could see it looks buggy.

The compiler knows the declared (struct) variable is type volatile. I pass a pointer to it to a subroutine and somehow that's a problem. A pointer to a volatile is somehow required in the function prototype, which I did not expect or understand.

volatile is part of the type, just like const. You must specify the parameter's complete type in the function's prototype.

What you posted has a serious bug. But, you're not interested so I'll move on.

If you won't share it, I'm not interested.

The type of the argument passed to the function must match the type of the parameter in the function prototype. Are you surprised that you cannot pass a pointer to a float to a function that expects a pointer to a byte? So why is the exact same discrepancy between the volatile and non-volatile types unclear to you?

A quick Google search came up with Blink Without Delay as the first result. It's also a built-in example in the Arduino IDE.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.