Hello,
I have been using the navigator board and have had some issues with a safe shutdown of the PWM module - as far as such I recently blew one of the BR 5V/6A power supplies which was powering the Navigator and the servos. When I go to shut down an application which was driving PWM values, when I go to kill the PWM chip, it seems like a random signal gets sent where all the servos (and the esc/thruster…) get driven to a random value (which is sometimes terrifying when the M200 motor/propeller spins at max RPM). Does anyone have any suggestions to achieving a more stable way to disable and shut down the PWM pins?
Here is an example script I use for calibrating the fins on the vehicle. Sometimes when I hit Ctrl+C, the fins jump to a random value which pulls a large amount of current up front.
#include "bindings.h"
#include <chrono>
#include <thread>
#include <iostream>
#include <csignal>
void signalHandler(int signum)
{
set_pwm_enable(false);
exit(signum);
}
using namespace std;
void setPinPulseWidth(PwmChannel pin_num, double target)
{
double max = 409.5; // at 50 Hz, corresponds to 2000 microseconds pulsewidth
double min = 204.75; // at 50 Hz, corresponds to 1000 microseconds pulsewidth
double center_pwm = min + (max - min) / 2;
double range_pwm = max - min;
double pulse_width = center_pwm + (target / 100.0) * range_pwm / 2;
set_pwm_channel_value(pin_num, pulse_width);
}
int main(int ac, char *av[])
{
std::string argi;
if (ac != 4)
{
showHelpAndExit();
}
double rudder_angle = 0;
double stbd_angle = 0;
double port_angle = 0;
for (int i = 1; i < ac; ++i)
{
argi = string(av[i]);
if (argi == "-h" || argi == "--help")
{
showHelpAndExit();
}
else if (i == 1)
{
rudder_angle = stod(argi);
}
else if (i == 2)
{
stbd_angle = stod(argi);
}
else if (i == 3)
{
port_angle = stod(argi);
}
}
signal(SIGINT, signalHandler);
init();
set_pwm_freq_hz(50);
set_pwm_enable(true);
PwmChannel pin_2 = PwmChannel::Ch2;
PwmChannel pin_3 = PwmChannel::Ch3;
PwmChannel pin_4 = PwmChannel::Ch4;
// https://discuss.bluerobotics.com/t/navigator-lib-pwm-outputs-c/16378
// https://docs.bluerobotics.com/navigator-lib/python/#bluerobotics_navigator.set_pwm_channel_value
setPinPulseWidth(pin_2, rudder_angle);
std::this_thread::sleep_for(std::chrono::milliseconds(250));
setPinPulseWidth(pin_3, stbd_angle);
std::this_thread::sleep_for(std::chrono::milliseconds(250));
setPinPulseWidth(pin_4, port_angle);
cout << "Shut down with Ctrl+C" << endl;
while (true)
;
}
I’m using (new) BR 5V/6A power supply which is now only powering the servos, and a dedicated 5V power supply for the Pi/Navigator. I was having this issue when I was also powering them both with the same power supply. I’m wondering if it is likely if I am missing something in my electrical stack (which was intended to be pretty straightforward and rely on the Navigator mostly), or if I can do something in my software which makes it safer and more reliable to work with. Is this a Navigator issue, a software/library issue, or an external electrical issue?
Updates:
When testing I added these blocks to the application in my middleware and the other applets I test with and I seem to catch most of the bad hangups, but I would still like a guaranteed to reduce/minimize the likelihood in which a bad signal gets sent to the actuators.
void safePwmShutdown() {
// Set all servos to a neutral position before disabling PWM
AftCtrlV1::setPinPulseWidth(PwmChannel::Ch1, 0);
AftCtrlV1::setPinPulseWidth(PwmChannel::Ch2, 0);
AftCtrlV1::setPinPulseWidth(PwmChannel::Ch3, 0);
AftCtrlV1::setPinPulseWidth(PwmChannel::Ch4, 0);
// Ensure the PWM values have been applied
std::this_thread::sleep_for(std::chrono::milliseconds(500));
set_pwm_enable(false);
}
void signalHandler(int signum)
{
safePwmShutdown();
exit(signum);
};
//---------------------------------------------------------
// Constructor()
AftCtrlV1::AftCtrlV1()
{
signal(SIGINT, signalHandler); // Interrupt from keyboard (Ctrl+C)
signal(SIGTERM, signalHandler); // Termination signal
signal(SIGABRT, signalHandler); // Abnormal termination (abort)
signal(SIGQUIT, signalHandler); // Quit from keyboard
signal(SIGSEGV, signalHandler); // Invalid memory access (segmentation fault)
signal(SIGFPE, signalHandler); // Floating point exception
signal(SIGHUP, signalHandler); // Hangup detected on controlling terminal or death of controlling process
signal(SIGPIPE, signalHandler); // Write to a pipe with no one to read it
signal(SIGALRM, signalHandler); // Timer signal from alarm()
signal(SIGUSR1, signalHandler); // User-defined signal 1
signal(SIGUSR2, signalHandler); // User-defined signal 2
atexit(safePwmShutdown);