-
Notifications
You must be signed in to change notification settings - Fork 2
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
base: main
Are you sure you want to change the base?
Conversation
4c3y
commented
Aug 3, 2022
- Added support for changing mode and clock frequency during runtime with dynamic reconfigure
There was a problem hiding this 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) | |||
|
|||
|
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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
enum LedMode { | ||
FPS, | ||
EXPOSURE | ||
FPS = 0, | ||
EXPOSURE = 1 | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer class enums, see https://www.geeksforgeeks.org/enum-classes-in-c-and-their-advantage-over-enum-datatype/
mode_ = static_cast<LedMode>(config.mode); //Convert int to enum | ||
|
||
pwm_subsystem_.setFrequency(config.frequency); | ||
setGpioMode(); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this 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) |
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
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 | ||
|
There was a problem hiding this comment.
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.
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 😄). |
@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 |