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;
}
asked Jan 23, 2023 at 18:41
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? Commented Jan 23, 2023 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().

answered Jan 23, 2023 at 20:40
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. Commented Jan 23, 2023 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. Commented Jan 23, 2023 at 22:14

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.