1

I want to write a class for a model bike.

For controlling the steering I use a DC motor with two encoders. To get the steering angle stAng of the bike, I attach a interrupt to the pin ST_ENC_A where one of the encoders is connected to. This interrupt is attached when the bike is initialized with the function bike.begin(). When the interrupt is triggerd, the increment-steering-angle-function incStAng is triggerd. Said function is member of the class Bike. To make the whole code compile and upload I had to make the increment-steering-angle-function static void incStAng() and the steering-angle-variable volatile static float stAng static.

The code is running, there are no errors or warnings.

Now, when I provide pin ST_ENC_A with 3.3V the interrupt should be triggerd and I should see the printed value of stAng increse in the Serial Monitor. This is not the case. It stays at 0.00.

This is my first real class I am writing. I only want to create one instance of my bike so the static definition of stAng and incStAng should be no problem.

So far I found the following websites helpful for information on 'static' and ISR.

I would be glad if someone could help me and give me a hint why the steering angle is not increasing when I give said pin 3.3V!

Board: Arduino Nano RP2040 Connect

Below you will see the .ino, .h, .cpp files in this order.

// myBike.ino - main file

#include "Bike.h"

Bike bike;

void setup() {
  Serial.begin(9600);
  bike.begin();
}

void loop() {
  float val = bike.getStAng();
  Serial.println(val);
}
// Bike.h - header file for the Bike library

#ifndef Bike_h
#define Bike_h

#include "Arduino.h"

class Bike {
  public:
    Bike();
    void begin();
    float getStAng();
  private:
    volatile static float stAng;
    static void incStAng();
};

#endif
// Bike.cpp - implementation file for the Bike library

#include "Bike.h"

#define ST_ENC_A      12
#define ST_ENC_B      11

#define DEG_PER_CNT   0.51428571428

Bike::Bike() {
  pinMode(ST_ENC_A, INPUT);
  pinMode(ST_ENC_B, INPUT);
}

void Bike::begin() {
  attachInterrupt(digitalPinToInterrupt(ST_ENC_A),incStAng,RISING);
}

void Bike::incStAng() {
  volatile float stAng;
  int b = digitalRead(ST_ENC_B);
  if(b==HIGH){
    stAng = stAng - DEG_PER_CNT;
  }else{
    stAng = stAng - DEG_PER_CNT;
  }
}

float Bike::getStAng() {
  volatile float stAng;
  return stAng;
}


1
  • Did you connect that pin to ground previosly before changing to 3.3V? Do you use external pullup or pulldown resistors? The pin might already have been at 3.3V, thus connecting it to 3.3V would not generate a rising edge. Have you tried connecting and rotating the actual encoder?
    – chrisl
    Jan 23 at 19:11

1 Answer 1

3

You have three different variables named stAng here:

  • a static member of the Bike class, which has been declared but not defined, and is never used
  • a local variable of the Bike::incStAng() method
  • a local variable of the Bike::getStAng() method

There should be only one such variable. For this, you should define the first one: in Bike.cpp

volatile float Bike::stAng;

and get rid of the other two.

Side note: I would recommend avoiding floating point computations within an ISR, as these can be quite slow. Instead, count the integer number of encoder steps in the ISR, and convert to an angle within Bike::getStAng().

2
  • Thank you for this quick help, it works like I want it to! I am still wondering why it has to be like this though. Adding these two local variables you mentioned made the code compile, this is why I did it. So, in the class I only declare stAng as a static member but with volatile float Bike::stAng; in Bike.cpp I define it, right? I do not get the underlying rule why I have to do it this way. Could you give me a short explanation? If I add a non-static variable to the class and want to access and modify it using a method of Bike I do not have to add such a definition in Bike.cpp.
    – Ole
    Jan 23 at 21:32
  • 1
    @Ole: The class definition in Bike.h defines a type only. No data. The line Bike bike; in myBike.ino defines a Bike object, and thus all the data belonging to that object (which in this case just happens to be none). A static data member does not belong to any object, and thus has to de defined elsewhere. It has also to be defined only once, so a .h file, which could potentially be included in multiple other files, would not be appropriate. Jan 23 at 22:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.