From 50758a96adc4b7247e4ba0b7c7671400cc3196e5 Mon Sep 17 00:00:00 2001 From: dijidiji Date: Tue, 19 Aug 2025 19:01:29 +1000 Subject: [PATCH 1/8] Clean up whitespace and comments --- coresdk/src/coresdk/raspi_motor_driver.h | 6 +----- coresdk/src/coresdk/raspi_servo_driver.cpp | 2 +- coresdk/src/test/test_raspi_servo.cpp | 4 ++-- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/coresdk/src/coresdk/raspi_motor_driver.h b/coresdk/src/coresdk/raspi_motor_driver.h index 1a4f6226..bc27ae97 100644 --- a/coresdk/src/coresdk/raspi_motor_driver.h +++ b/coresdk/src/coresdk/raspi_motor_driver.h @@ -11,7 +11,7 @@ #include #include -#include "backend_types.h" // for pointer_identifier +#include "backend_types.h" // for pointer_identifier #include "easylogging++.h" #include "types.h" @@ -42,14 +42,11 @@ * @attribute class motor_device */ namespace splashkit_lib { - /** * @brief Opaque handle for an L298N motor driver instance. */ typedef struct _motor_data *motor_device; - - /** * Checks if a motor device with the given name is already opened. * @param name Identifier for the motor driver. @@ -111,7 +108,6 @@ namespace splashkit_lib { * Closes all opened motor devices. */ void close_all_motors(); - } #endif // RASPI_MOTOR_DRIVER_H diff --git a/coresdk/src/coresdk/raspi_servo_driver.cpp b/coresdk/src/coresdk/raspi_servo_driver.cpp index ab638482..eaa5c163 100644 --- a/coresdk/src/coresdk/raspi_servo_driver.cpp +++ b/coresdk/src/coresdk/raspi_servo_driver.cpp @@ -45,7 +45,7 @@ namespace splashkit_lib raspi_init(); auto dev = new _servo_data(); - dev->id = SERVO_DRIVER_PTR; // you'll need to #define this in backend_types.h + dev->id = SERVO_DRIVER_PTR; // defined SERVO_DRIVER_PTR in backend_types.h dev->name = name; dev->pin = control_pin; diff --git a/coresdk/src/test/test_raspi_servo.cpp b/coresdk/src/test/test_raspi_servo.cpp index 50cc67fc..3294d84b 100644 --- a/coresdk/src/test/test_raspi_servo.cpp +++ b/coresdk/src/test/test_raspi_servo.cpp @@ -25,7 +25,7 @@ void run_servo_driver_tests() // Pause until user is ready write_line("Press ENTER to begin...\n"); - read_line(); // splashkit’s line-reader :contentReference[oaicite:0]{index=0} + read_line(); // splashkit’s line-reader // Open the servo on board pin 12 servo_device srv = open_servo("TestServo", PIN_12); @@ -44,7 +44,7 @@ void run_servo_driver_tests() for (int deg = 0; deg <= 180; deg += STEP_DEG) { set_servo_angle(srv, deg); - delay(DELAY_MS); // splashkit’s millisecond delay :contentReference[oaicite:1]{index=1} + delay(DELAY_MS); // splashkit’s millisecond delay } // Hold at 180° for a second From 47c482df50b52f293241ac404ab928dc1cf5be6e Mon Sep 17 00:00:00 2001 From: dijidiji Date: Thu, 21 Aug 2025 15:49:07 +1000 Subject: [PATCH 2/8] Separate brake function from stop_motor --- coresdk/src/coresdk/raspi_motor_driver.cpp | 23 ++++++++++++++++------ coresdk/src/coresdk/raspi_motor_driver.h | 6 ++++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/coresdk/src/coresdk/raspi_motor_driver.cpp b/coresdk/src/coresdk/raspi_motor_driver.cpp index d0434514..7e8489f0 100644 --- a/coresdk/src/coresdk/raspi_motor_driver.cpp +++ b/coresdk/src/coresdk/raspi_motor_driver.cpp @@ -94,7 +94,7 @@ namespace splashkit_lib return; // input speed goes from 0 to 1 // output speed goes from 0 to 255 - int pwm_speed = static_cast(speed * 255); + int pwm_speed = static_cast(speed * 255); // TODO: Scale to current PWM range if (speed < 0) { speed = 0; @@ -114,14 +114,25 @@ namespace splashkit_lib #endif } - void stop_motor(motor_device dev) + void brake_motor(motor_device dev) { -#ifdef RASPBERRY_PI +#ifdef RAPSBERRY_PI if (!dev || dev->id != MOTOR_DRIVER_PTR) return; - // Brake: both inputs high + // L298N goes into brake mode when the two inputs are equal raspi_write(dev->in1, GPIO_HIGH); raspi_write(dev->in2, GPIO_HIGH); +#else + LOG(ERROR) << "motor driver not supported on this platform"; +#endif + } + + void stop_motor(motor_device dev) + { +#ifdef RASPBERRY_PI + if (!dev || dev->id != MOTOR_DRIVER_PTR) + return; + raspi_set_pwm_dutycycle(dev->en, GPIO_LOW); #else LOG(ERROR) << "Motor driver not supported on this platform"; @@ -135,7 +146,7 @@ namespace splashkit_lib return; raspi_write(dev->in1, GPIO_LOW); raspi_write(dev->in2, GPIO_LOW); - raspi_set_pwm_dutycycle(dev->en, GPIO_LOW); + raspi_set_pwm_dutycycle(dev->en, GPIO_LOW) // TODO: Set PWM low before inputs _motor_devices.erase(dev->name); delete dev; #else @@ -166,7 +177,7 @@ namespace splashkit_lib motor_device dev = kv.second; raspi_write(dev->in1, GPIO_LOW); raspi_write(dev->in2, GPIO_LOW); - raspi_set_pwm_dutycycle(dev->en, GPIO_LOW); + raspi_set_pwm_dutycycle(dev->en, GPIO_LOW); // TODO: Set PWM low before inputs delete dev; } _motor_devices.clear(); diff --git a/coresdk/src/coresdk/raspi_motor_driver.h b/coresdk/src/coresdk/raspi_motor_driver.h index bc27ae97..610f10a5 100644 --- a/coresdk/src/coresdk/raspi_motor_driver.h +++ b/coresdk/src/coresdk/raspi_motor_driver.h @@ -90,6 +90,12 @@ namespace splashkit_lib { * Stops the motor immediately (brake). * @param dev The motor device handle. */ + void brake_motor(motor_device dev); + + /** + * Stops the motor and allows it to coast to a stop. + * @param dev The motor device handle. + */ void stop_motor(motor_device dev); /** From 5c8124c91ce624641b31e1ed69ef54a96f244bf6 Mon Sep 17 00:00:00 2001 From: dijidiji Date: Thu, 21 Aug 2025 16:44:59 +1000 Subject: [PATCH 3/8] Amend comments --- coresdk/src/coresdk/raspi_motor_driver.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/coresdk/src/coresdk/raspi_motor_driver.cpp b/coresdk/src/coresdk/raspi_motor_driver.cpp index 7e8489f0..3efaaa83 100644 --- a/coresdk/src/coresdk/raspi_motor_driver.cpp +++ b/coresdk/src/coresdk/raspi_motor_driver.cpp @@ -132,7 +132,7 @@ namespace splashkit_lib #ifdef RASPBERRY_PI if (!dev || dev->id != MOTOR_DRIVER_PTR) return; - + // L298N goes into coast mode when EN = LOW raspi_set_pwm_dutycycle(dev->en, GPIO_LOW); #else LOG(ERROR) << "Motor driver not supported on this platform"; @@ -146,7 +146,7 @@ namespace splashkit_lib return; raspi_write(dev->in1, GPIO_LOW); raspi_write(dev->in2, GPIO_LOW); - raspi_set_pwm_dutycycle(dev->en, GPIO_LOW) // TODO: Set PWM low before inputs + raspi_set_pwm_dutycycle(dev->en, GPIO_LOW) _motor_devices.erase(dev->name); delete dev; #else @@ -177,7 +177,7 @@ namespace splashkit_lib motor_device dev = kv.second; raspi_write(dev->in1, GPIO_LOW); raspi_write(dev->in2, GPIO_LOW); - raspi_set_pwm_dutycycle(dev->en, GPIO_LOW); // TODO: Set PWM low before inputs + raspi_set_pwm_dutycycle(dev->en, GPIO_LOW); delete dev; } _motor_devices.clear(); From 29a9bfcc77bfc0993322e2c3b1d63818b9d14416 Mon Sep 17 00:00:00 2001 From: dijidiji Date: Thu, 21 Aug 2025 17:23:44 +1000 Subject: [PATCH 4/8] Add functions to get PWM range --- coresdk/src/backend/gpio_driver.cpp | 14 ++++++++++++++ coresdk/src/backend/gpio_driver.h | 1 + coresdk/src/coresdk/raspi_gpio.cpp | 15 +++++++++++++++ coresdk/src/coresdk/raspi_gpio.h | 10 ++++++++++ 4 files changed, 40 insertions(+) diff --git a/coresdk/src/backend/gpio_driver.cpp b/coresdk/src/backend/gpio_driver.cpp index ef99839a..f5bb4035 100644 --- a/coresdk/src/backend/gpio_driver.cpp +++ b/coresdk/src/backend/gpio_driver.cpp @@ -128,6 +128,20 @@ namespace splashkit_lib } } } + + int sk_get_pwm_range(int pin) + { + if (check_pi()) + { + int result = get_PWM_range(pi, pin); + if (result < 0) + { + LOG(ERROR) << sk_gpio_error_message(result); + } + return result; + } + } + void sk_set_pwm_frequency(int pin, int frequency) { if (check_pi()) diff --git a/coresdk/src/backend/gpio_driver.h b/coresdk/src/backend/gpio_driver.h index c370b360..b155b8b4 100644 --- a/coresdk/src/backend/gpio_driver.h +++ b/coresdk/src/backend/gpio_driver.h @@ -191,6 +191,7 @@ namespace splashkit_lib void sk_gpio_set_pull_up_down(int pin, int pud); void sk_gpio_write(int pin, int value); void sk_set_pwm_range(int pin, int range); + void sk_get_pwm_range(int pin); void sk_set_pwm_frequency(int pin, int frequency); void sk_set_pwm_dutycycle(int pin, int dutycycle); void sk_gpio_clear_bank_1(); diff --git a/coresdk/src/coresdk/raspi_gpio.cpp b/coresdk/src/coresdk/raspi_gpio.cpp index e3290bf0..4022c488 100644 --- a/coresdk/src/coresdk/raspi_gpio.cpp +++ b/coresdk/src/coresdk/raspi_gpio.cpp @@ -173,6 +173,21 @@ namespace splashkit_lib #endif } + int raspi_get_pwm_range(gpio_pin pin) + { +#ifdef RASPBERRY_PI + int bcmPin = boardToBCM(pin); + if (bcmPin >= 2) + { + return sk_get_pwm_range(bcmPin); + } + return -1; +#else + LOG(ERROR) << "Unable to get PWM range - GPIO not supported on this platform"; + return -1; +#endif + } + void raspi_set_pwm_frequency(gpio_pin pin, int frequency) { #ifdef RASPBERRY_PI diff --git a/coresdk/src/coresdk/raspi_gpio.h b/coresdk/src/coresdk/raspi_gpio.h index 3c0c420e..9eaf7343 100644 --- a/coresdk/src/coresdk/raspi_gpio.h +++ b/coresdk/src/coresdk/raspi_gpio.h @@ -81,6 +81,16 @@ namespace splashkit_lib */ void raspi_set_pwm_range(gpio_pin pin, int range); + /** + * @brief Gets the PWM range for the specified pin. + * + * This function gets the PWM range for the specified pin. + * + * @param pin The pin to get the PWM range for. + * @returns The PWM range of the pin. + */ + int raspi_get_pwm_range(gpio_pin pin); + /** * @brief Sets the PWM frequency for the specified pin. * From 7736363943913a9b9b2dd7af9670913824ba027f Mon Sep 17 00:00:00 2001 From: dijidiji Date: Thu, 21 Aug 2025 17:29:56 +1000 Subject: [PATCH 5/8] Scale input speed range to PWM range --- coresdk/src/coresdk/raspi_motor_driver.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/coresdk/src/coresdk/raspi_motor_driver.cpp b/coresdk/src/coresdk/raspi_motor_driver.cpp index 3efaaa83..fee2177c 100644 --- a/coresdk/src/coresdk/raspi_motor_driver.cpp +++ b/coresdk/src/coresdk/raspi_motor_driver.cpp @@ -93,8 +93,9 @@ namespace splashkit_lib if (!dev || dev->id != MOTOR_DRIVER_PTR) return; // input speed goes from 0 to 1 - // output speed goes from 0 to 255 - int pwm_speed = static_cast(speed * 255); // TODO: Scale to current PWM range + // scale to EN pin's PWM range + int pwm_range = raspi_get_pwm_range(dev->en); + int pwm_speed = static_cast(speed * pwm_range); if (speed < 0) { speed = 0; From 3c34b5019a1e6b7e6c0cb6216d7284764c59ad80 Mon Sep 17 00:00:00 2001 From: dijidiji Date: Sun, 24 Aug 2025 16:30:07 +1000 Subject: [PATCH 6/8] Remove PWM pin checks The pigpio uses software PWM for the PWM and servo functions, which is supported on all GPIO pins. So, these functions were changed to be similar to the other GPIO functions. If hardware PWM is to be added, it should use hardware_PWM from pigpio. --- coresdk/src/coresdk/raspi_gpio.cpp | 45 +++++++----------------------- 1 file changed, 10 insertions(+), 35 deletions(-) diff --git a/coresdk/src/coresdk/raspi_gpio.cpp b/coresdk/src/coresdk/raspi_gpio.cpp index 4022c488..fe2e7a1d 100644 --- a/coresdk/src/coresdk/raspi_gpio.cpp +++ b/coresdk/src/coresdk/raspi_gpio.cpp @@ -257,58 +257,33 @@ namespace splashkit_lib return ""; #endif } + int raspi_get_servo_pulsewidth(gpio_pin pin) { #ifdef RASPBERRY_PI - if (has_gpio()) + int bcmPin = boardToBCM(pin); + // if the pin is not a PWM pin, return + if (bcmPin >= 2) { - gpio_pin pwmPins[] = {PIN_12, PIN_32, PIN_33, PIN_35}; - // if the pin is not a PWM pin, return - if (std::find(std::begin(pwmPins), std::end(pwmPins), pin) == std::end(pwmPins)) - { - LOG(ERROR) << "Pin " << pin << " is not a PWM pin"; - return -1; - } - int bcmPin = boardToBCM(pin); - // if the pin is not a PWM pin, return - if (bcmPin < 2) - { - LOG(ERROR) << "Pin " << pin << " is not a PWM pin"; - return -1; - } return sk_get_servo_pulsewidth(bcmPin); } - else - { - LOG(ERROR) << "Servo driver not supported on this platform"; - return -1; - } + return -1; #else - LOG(ERROR) << "Servo driver not supported on this platform"; + LOG(ERROR) << "Unable to get servo pulse width - GPIO not supported on this platform"; return -1; #endif } + void raspi_set_servo_pulsewidth(gpio_pin pin, int pulsewidth) { #ifdef RASPBERRY_PI - if (has_gpio()) + int bcmPin = boardToBCM(pin); + if (bcmPin >= 2) { - gpio_pin pwmPins[] = {PIN_12, PIN_32, PIN_33, PIN_35}; - // if the pin is not a PWM pin, return - if (std::find(std::begin(pwmPins), std::end(pwmPins), pin) == std::end(pwmPins)) - { - LOG(ERROR) << "Pin " << pin << " is not a PWM pin"; - return; // ← early return so we don’t drive an unsupported pin - } - int bcmPin = boardToBCM(pin); sk_set_servo_pulsewidth(bcmPin, pulsewidth); } - else - { - LOG(ERROR) << "Servo driver not supported on this platform"; - } #else - LOG(ERROR) << "Servo driver not supported on this platform"; + LOG(ERROR) << "Unable to set servo pulse width - GPIO not supported on this platform"; #endif } From 58a01884559597be37a93a762b402709ca561172 Mon Sep 17 00:00:00 2001 From: dijidiji Date: Sun, 24 Aug 2025 17:22:36 +1000 Subject: [PATCH 7/8] Rework servo movement functions Servos are now opened with min_angle and max_angle variables. These are optional in the signature and default to 0 and 180, following the original code. set_servo_angle functions the same as before but maps to this range, rather than the static range of 0..180 it was before. set_servo_value takes an input from 0 to 1 and maps it to the PWM range. This is useful when the user doesn't know the angle range of a servo, in which case set_servo_angle is unintuitive. --- coresdk/src/coresdk/raspi_servo_driver.cpp | 37 +++++++++++++++++----- coresdk/src/coresdk/raspi_servo_driver.h | 12 ++++++- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/coresdk/src/coresdk/raspi_servo_driver.cpp b/coresdk/src/coresdk/raspi_servo_driver.cpp index eaa5c163..78a65845 100644 --- a/coresdk/src/coresdk/raspi_servo_driver.cpp +++ b/coresdk/src/coresdk/raspi_servo_driver.cpp @@ -18,11 +18,13 @@ namespace splashkit_lib pointer_identifier id; std::string name; gpio_pin pin; + double min_angle, max_angle; }; static std::map _servo_devices; - static const unsigned MIN_PW = 500; // µs at 0° - static const unsigned MAX_PW = 2500; // µs at 180° + // Pulse widths for the min and max values of servo range + static const unsigned MIN_PW = 500; + static const unsigned MAX_PW = 2500; bool has_servo_device(const std::string &name) { @@ -35,7 +37,7 @@ namespace splashkit_lib return (it != _servo_devices.end()) ? it->second : nullptr; } - servo_device open_servo(const std::string &name, gpio_pin control_pin) + servo_device open_servo(const std::string &name, gpio_pin control_pin, double min_angle = 0, double max_angle = 180) { #ifdef RASPBERRY_PI if (has_servo_device(name)) @@ -48,6 +50,8 @@ namespace splashkit_lib dev->id = SERVO_DRIVER_PTR; // defined SERVO_DRIVER_PTR in backend_types.h dev->name = name; dev->pin = control_pin; + dev->min_angle = min_angle; + dev->max_angle = max_angle; // configure as output raspi_set_mode(control_pin, GPIO_OUTPUT); @@ -65,17 +69,34 @@ namespace splashkit_lib #endif } + void set_servo_value(servo_device dev, double value) + { +#ifdef RASPBERRY_PI + if (!dev || dev->id != SERVO_DRIVER_PTR) + return; + + // input value is 0..1 + // scale to servo pulse width range + unsigned pw = static_cast(value * (MAX_PW - MIN_PW) + MIN_PW); + raspi_set_servo_pulsewidth(dev->pin, pw); +#else + LOG(ERROR) << "Servo driver not supported on this platform"; +#endif + } + void set_servo_angle(servo_device dev, double angle) { #ifdef RASPBERRY_PI if (!dev || dev->id != SERVO_DRIVER_PTR) return; - // clamp to [0,180] - angle = std::clamp(angle, 0.0, 180.0); - unsigned pw = static_cast( - MIN_PW + (angle / 180.0) * (MAX_PW - MIN_PW)); - // raspi_set_pwm_dutycycle(dev->pin, pw); + double min = dev->min_angle; + double max = dev->max_angle; + + // clamp input to servo range + angle = std::clamp(angle, min, max); + // scale angle to pulse width range + unsigned pw = static_cast((angle - min / max - min) * (MAX_PW - MIN_PW) + MIN_PW); raspi_set_servo_pulsewidth(dev->pin, pw); #else LOG(ERROR) << "Servo driver not supported on this platform"; diff --git a/coresdk/src/coresdk/raspi_servo_driver.h b/coresdk/src/coresdk/raspi_servo_driver.h index b4ac9750..868204f1 100644 --- a/coresdk/src/coresdk/raspi_servo_driver.h +++ b/coresdk/src/coresdk/raspi_servo_driver.h @@ -67,10 +67,20 @@ namespace splashkit_lib * Open (and initialize) a servo on the given board pin. * @param name Your identifier for this servo. * @param control_pin Board‐numbered GPIO pin for the servo signal line. + * @param min_angle The minimum angle of this servo in degrees, defaults to 0. + * @param max_angle The maximum angle of this servo in degrees, defaults to 180. * @returns A valid servo_device, or nullptr on failure. */ - servo_device open_servo(const std::string &name, gpio_pin control_pin); + servo_device open_servo(const std::string &name, gpio_pin control_pin, double min_angle = 0, double max_angle = 180); + /** + * Maps 0..1 to the pulse width range of a servo. + * Useful if someone doesn't know the min and max angle of a servo device. + * @param dev The servo device to control. + * @param value The value, from 0 (min) to 1 (max) to set the servo to. + */ + void set_servo_value(servo_device dev, double value); + /** * Convenience: map an angle (0…180°) into the 500…2500 µs range. * This is a linear mapping, so it may not be accurate for all servos. From db25e5b89ea1426e874282c0fd7d4fb01944363f Mon Sep 17 00:00:00 2001 From: dijidiji Date: Sun, 24 Aug 2025 18:08:53 +1000 Subject: [PATCH 8/8] Remove defaults in definition of open_servo --- coresdk/src/coresdk/raspi_servo_driver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coresdk/src/coresdk/raspi_servo_driver.cpp b/coresdk/src/coresdk/raspi_servo_driver.cpp index 78a65845..8177e469 100644 --- a/coresdk/src/coresdk/raspi_servo_driver.cpp +++ b/coresdk/src/coresdk/raspi_servo_driver.cpp @@ -37,7 +37,7 @@ namespace splashkit_lib return (it != _servo_devices.end()) ? it->second : nullptr; } - servo_device open_servo(const std::string &name, gpio_pin control_pin, double min_angle = 0, double max_angle = 180) + servo_device open_servo(const std::string &name, gpio_pin control_pin, double min_angle, double max_angle) { #ifdef RASPBERRY_PI if (has_servo_device(name))