Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/dynamic reconfigure #12

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Conversation

4c3y
Copy link
Member

@4c3y 4c3y commented Aug 3, 2022

  • Added support for changing mode and clock frequency during runtime with dynamic reconfigure

@4c3y 4c3y added the enhancement New feature or request label Aug 3, 2022
Copy link
Member

@michaelpantic michaelpantic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, see comments!

@@ -4,7 +4,7 @@ project(time_stamper_ros)
add_compile_options(-std=c++17 -Wdeprecated-declarations)

find_package(catkin_simple REQUIRED)
catkin_simple()
catkin_simple(ALL_DEPS_REQUIRED)


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unecessary vspace

from dynamic_reconfigure.parameter_generator_catkin import *

gen = ParameterGenerator()
gen.add("frequency", int_t, 0, "Clock frequency", 50, 1, 10526315)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm I wonder if it makes sense to change frequency completely freely as an integer, as usually not all frequencies can be achieved by the clock. Maybe a divisor makes more sense? Depends on the use case, though.
Make sure the default, min and max are correct.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, this is difficult problem indeed. A divider may also be hard to work with for some scrip not knowing very well about the hardware. One possible way to deal with this is on the node side to change the requested value to a closest possible frequency (see my comment below for how to do that). For interactive configuration this should work well. The user would effectively only be able to adjust the value to something possible. And scripts may also be happy with that. If they really need to know precisely, they could read the effective value back and work with that.

gen.const("Exposure", int_t, 1, "Exposure Mode")],
"Set Led Mode")

gen.add("mode", int_t, 0, "Led Mode", 1, 0, 3, edit_method=size_enum)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 as max value probably makes no sense given that there are only 2 values possible

Comment on lines 12 to 15
enum LedMode {
FPS,
EXPOSURE
FPS = 0,
EXPOSURE = 1
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mode_ = static_cast<LedMode>(config.mode); //Convert int to enum

pwm_subsystem_.setFrequency(config.frequency);
setGpioMode();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm I guess this sets the LedMode to the GPIO driver?
Nitpick, but for maintainability it would be better to have a comment and/or put this next to the mode_ assignment. So future Mariano or Hannes don't need to think too much about sideeffects when changing anything here.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this isn't perfect this way. Without looking much into the code (lack of time :( ), to me the underlying problem seems to be again, the fact that this method doesn't take the mode (static_cast<LedMode>(config.mode)) as an argument. Wouldn't that make more sense? Then, here you wouldn't need to use the knowledge how the mode is stored (mode_). Maybe you wouldn't even need the mode_ variable if you could just directly pass it to the hardware. Generally, I'd recommend to try avoiding redundant state (and that includes hardware state in addition to memory state). Duplicating it may of course be justified by the hardware being to slow or not able to provide back the value in case it needed again somewhere later.

Copy link

@HannesSommer HannesSommer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm very sorry for the huge delay. Please, in future, ping until I react. It is never on purpose.

from dynamic_reconfigure.parameter_generator_catkin import *

gen = ParameterGenerator()
gen.add("frequency", int_t, 0, "Clock frequency", 50, 1, 10526315)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, this is difficult problem indeed. A divider may also be hard to work with for some scrip not knowing very well about the hardware. One possible way to deal with this is on the node side to change the requested value to a closest possible frequency (see my comment below for how to do that). For interactive configuration this should work well. The user would effectively only be able to adjust the value to something possible. And scripts may also be happy with that. If they really need to know precisely, they could read the effective value back and work with that.

mode_ = static_cast<LedMode>(config.mode); //Convert int to enum

pwm_subsystem_.setFrequency(config.frequency);
setGpioMode();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this isn't perfect this way. Without looking much into the code (lack of time :( ), to me the underlying problem seems to be again, the fact that this method doesn't take the mode (static_cast<LedMode>(config.mode)) as an argument. Wouldn't that make more sense? Then, here you wouldn't need to use the knowledge how the mode is stored (mode_). Maybe you wouldn't even need the mode_ variable if you could just directly pass it to the hardware. Generally, I'd recommend to try avoiding redundant state (and that includes hardware state in addition to memory state). Duplicating it may of course be justified by the hardware being to slow or not able to provide back the value in case it needed again somewhere later.

return;
}
mode_ = static_cast<LedMode>(config.mode); //Convert int to enum

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Around here you could mutate the config object and set the frequency to a closest valid value.

@4c3y
Copy link
Member Author

4c3y commented Oct 27, 2022

Unfortunately I don't have time at the moment due to preparations for the Swiss Robotics Day. I'll have a look at it the week afterwards. AFAIK you can indeed freely set the clock frequency up to 10.5 MHz (At least sysfs is fine with it 😄).

@4c3y
Copy link
Member Author

4c3y commented Nov 11, 2022

@HannesSommer As far as I can tell, it should be possible to freely set the clock frequency according to chapter 5.4 in the bcm2711 peripherals datasheet

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow changing the parameters (mode and clock frequency) of the timestamper device during runtime
3 participants