mirror of
https://github.com/MarlinFirmware/Marlin.git
synced 2025-12-29 10:50:36 -07:00
✨ Simulator: Virtual servos, BLTouch (#27779)
Co-authored-by: Christopher Pepper <p3p@p3psoft.co.uk>
This commit is contained in:
parent
3c32770faf
commit
d009c48b11
7 changed files with 206 additions and 97 deletions
|
|
@ -52,7 +52,9 @@ uint8_t _getc();
|
|||
// ------------------------
|
||||
|
||||
#define CPU_32_BIT
|
||||
#define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp
|
||||
|
||||
class Servo;
|
||||
typedef Servo hal_servo_t;
|
||||
|
||||
#define F_CPU 100000000
|
||||
#define SystemCoreClock F_CPU
|
||||
|
|
@ -232,8 +234,10 @@ public:
|
|||
* No option to invert the duty cycle [default = false]
|
||||
* No option to change the scale of the provided value to enable finer PWM duty control [default = 255]
|
||||
*/
|
||||
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) {
|
||||
analogWrite(pin, v);
|
||||
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false) {
|
||||
auto value = map(v, 0, v_size, 0, UINT16_MAX);
|
||||
value = invert ? UINT16_MAX - value : value;
|
||||
analogWrite(pin, value);
|
||||
}
|
||||
|
||||
static void set_pwm_frequency(const pin_t, int) {}
|
||||
|
|
|
|||
104
Marlin/src/HAL/NATIVE_SIM/Servo.cpp
Normal file
104
Marlin/src/HAL/NATIVE_SIM/Servo.cpp
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2025 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "../platforms.h"
|
||||
|
||||
#ifdef __PLAT_NATIVE_SIM__
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_SERVOS
|
||||
|
||||
#include "Servo.h"
|
||||
|
||||
//#define DEBUG_SERVOS
|
||||
#define DEBUG_OUT ENABLED(DEBUG_SERVOS)
|
||||
#include "../../../core/debug_out.h"
|
||||
|
||||
uint8_t ServoCount = 0; // the total number of attached servos
|
||||
|
||||
Servo::Servo() {
|
||||
// Constructor stub
|
||||
DEBUG_ECHOLNPGM("Debug Servo: constructor");
|
||||
this->servoIndex = ServoCount++; // assign a servo index to this instance
|
||||
}
|
||||
|
||||
uint8_t Servo::attach(int pin) {
|
||||
// Attach stub
|
||||
DEBUG_ECHOLNPGM("Debug Servo: attach to pin ", pin, " servo index ", this->servoIndex);
|
||||
return attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
|
||||
}
|
||||
|
||||
uint8_t Servo::attach(int pin, int min, int max) {
|
||||
// Attach with min and max stub
|
||||
DEBUG_ECHOLNPGM("Debug Servo: attach to pin ", pin, " with min ", min, " and max ", max);
|
||||
if (pin > 0) servo_pin = pin;
|
||||
return this->servoIndex;
|
||||
}
|
||||
|
||||
void Servo::detach() {
|
||||
// Detach stub
|
||||
DEBUG_ECHOLNPGM("Debug Servo: detach");
|
||||
}
|
||||
|
||||
// If value is < 200 it is treated as an angle, otherwise as pulse width in microseconds
|
||||
void Servo::write(int value) {
|
||||
if (value < MIN_PULSE_WIDTH) { // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
|
||||
value = map(constrain(value, 0, 180), 0, 180, SERVO_MIN_US(min), SERVO_MAX_US(max));
|
||||
}
|
||||
writeMicroseconds(value);
|
||||
DEBUG_ECHOLNPGM("Debug Servo: write ", value);
|
||||
}
|
||||
|
||||
void Servo::writeMicroseconds(int value) {
|
||||
// Simulate the servo movement
|
||||
this->value = value;
|
||||
hal.set_pwm_duty(pin_t(this->servo_pin), (float(value) / 20000) * UINT16_MAX, UINT16_MAX);
|
||||
DEBUG_ECHOLNPGM("Debug Servo: write microseconds ", value);
|
||||
}
|
||||
|
||||
int Servo::read() {
|
||||
// Read stub
|
||||
DEBUG_ECHOLNPGM("Debug Servo: read ", this->value);
|
||||
return this->value;
|
||||
}
|
||||
|
||||
int Servo::readMicroseconds() {
|
||||
// Read microseconds stub
|
||||
DEBUG_ECHOLNPGM("Debug Servo: read microseconds");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Servo::attached() {
|
||||
// Attached stub
|
||||
DEBUG_ECHOLNPGM("Debug Servo: attached");
|
||||
return false;
|
||||
}
|
||||
|
||||
int Servo::move(const unsigned char cmd) {
|
||||
// Move stub
|
||||
DEBUG_ECHOLNPGM("Debug Servo: move ", cmd);
|
||||
write(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // HAS_SERVOS
|
||||
#endif // __PLAT_NATIVE_SIM__
|
||||
48
Marlin/src/HAL/NATIVE_SIM/Servo.h
Normal file
48
Marlin/src/HAL/NATIVE_SIM/Servo.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2025 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
|
||||
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
|
||||
#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
|
||||
#define SERVO_MIN_US(v) (MIN_PULSE_WIDTH - (v) * 4) // minimum value in uS for this servo
|
||||
#define SERVO_MAX_US(v) (MAX_PULSE_WIDTH - (v) * 4) // maximum value in uS for this servo
|
||||
|
||||
class Servo {
|
||||
public:
|
||||
Servo();
|
||||
uint8_t attach(int pin); // Attach the given pin to the next free channel, set pinMode, return channel number or INVALID_SERVO if failure
|
||||
uint8_t attach(int pin, int min, int max); // As above but also set min and max values for writes.
|
||||
void detach();
|
||||
void write(int value); // If value is < 200 it's treated as an angle, otherwise as pulse width in microseconds
|
||||
void writeMicroseconds(int value); // Write pulse width in microseconds
|
||||
int read(); // Return current pulse width as an angle between 0 and 180 degrees
|
||||
int readMicroseconds(); // Return current pulse width in microseconds for this servo
|
||||
bool attached(); // Return true if this servo is attached, otherwise false
|
||||
int move (const unsigned char cmd);
|
||||
private:
|
||||
uint8_t servoIndex; // Index into the channel data for this servo
|
||||
int8_t min; // Minimum is this value times 4 added to MIN_PULSE_WIDTH
|
||||
int8_t max; // Maximum is this value times 4 added to MAX_PULSE_WIDTH
|
||||
int value; // Pulse width in microseconds for this servo
|
||||
int servo_pin = 0; // pin number for this servo
|
||||
};
|
||||
30
Marlin/src/HAL/NATIVE_SIM/endstop_interrupts.h
Normal file
30
Marlin/src/HAL/NATIVE_SIM/endstop_interrupts.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2025 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#error "ENDSTOP_INTERRUPTS_FEATURE is not supported in this simulation environment."
|
||||
|
||||
void setup_endstop_interrupts() {
|
||||
// This function is a stub for setting up endstop interrupts.
|
||||
// Since this is a simulation environment, actual hardware interrupts
|
||||
// are not applicable. Add any necessary simulation-specific logic here.
|
||||
}
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* servo.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
|
||||
* Copyright (c) 2009 Michael Margolis. All right reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* Based on "servo.h - Interrupt driven Servo library for Arduino using 16 bit timers -
|
||||
* Version 2 Copyright (c) 2009 Michael Margolis. All right reserved.
|
||||
*
|
||||
* The only modification was to update/delete macros to match the LPC176x.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Macros
|
||||
//values in microseconds
|
||||
#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
|
||||
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
|
||||
#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
|
||||
#define REFRESH_INTERVAL 20000 // minimum time to refresh servos in microseconds
|
||||
|
||||
#define MAX_SERVOS 4
|
||||
|
||||
#define INVALID_SERVO 255 // flag indicating an invalid servo index
|
||||
|
||||
// Types
|
||||
|
||||
typedef struct {
|
||||
uint8_t nbr : 8 ; // a pin number from 0 to 254 (255 signals invalid pin)
|
||||
uint8_t isActive : 1 ; // true if this channel is enabled, pin not pulsed if false
|
||||
} ServoPin_t;
|
||||
|
||||
typedef struct {
|
||||
ServoPin_t Pin;
|
||||
unsigned int pulse_width; // pulse width in microseconds
|
||||
} ServoInfo_t;
|
||||
|
||||
// Global variables
|
||||
|
||||
extern uint8_t ServoCount;
|
||||
extern ServoInfo_t servo_info[MAX_SERVOS];
|
||||
|
|
@ -59,7 +59,7 @@
|
|||
* write() - Sets the servo angle in degrees. (invalid angle that is valid as pulse in microseconds is treated as microseconds)
|
||||
* writeMicroseconds() - Sets the servo pulse width in microseconds
|
||||
* read() - Gets the last written servo pulse width as an angle between 0 and 180.
|
||||
* readMicroseconds() - Gets the last written servo pulse width in microseconds. (was read_us() in first release)
|
||||
* readMicroseconds() - Gets the last written servo pulse width in microseconds.
|
||||
* attached() - Returns true if there is a servo attached.
|
||||
* detach() - Stops an attached servos from pulsing its i/o pin.
|
||||
* move(angle) - Sequence of attach(0), write(angle),
|
||||
|
|
@ -86,6 +86,8 @@
|
|||
#include "../ESP32/Servo.h"
|
||||
#elif defined(__PLAT_RP2040__)
|
||||
#include "../RP2040/Servo.h"
|
||||
#elif defined(__PLAT_NATIVE_SIM__)
|
||||
#include "../NATIVE_SIM/Servo.h"
|
||||
#else
|
||||
#include <stdint.h>
|
||||
|
||||
|
|
@ -100,22 +102,22 @@
|
|||
class Servo {
|
||||
public:
|
||||
Servo();
|
||||
int8_t attach(const int pin); // attach the given pin to the next free channel, set pinMode, return channel number (-1 on fail)
|
||||
int8_t attach(const int pin, const int min, const int max); // as above but also sets min and max values for writes.
|
||||
int8_t attach(const int pin); // Attach the given pin to the next free channel, set pinMode, return channel number (-1 on fail)
|
||||
int8_t attach(const int pin, const int min, const int max); // As above but also set min and max values for writes.
|
||||
void detach();
|
||||
void write(int value); // if value is < 200 it is treated as an angle, otherwise as pulse width in microseconds
|
||||
void writeMicroseconds(int value); // write pulse width in microseconds
|
||||
void move(const int value); // attach the servo, then move to value
|
||||
// if value is < 200 it is treated as an angle, otherwise as pulse width in microseconds
|
||||
// if DEACTIVATE_SERVOS_AFTER_MOVE wait SERVO_DELAY, then detach
|
||||
int read(); // returns current pulse width as an angle between 0 and 180 degrees
|
||||
int readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release)
|
||||
bool attached(); // return true if this servo is attached, otherwise false
|
||||
void write(int value); // If value is < 200 it is treated as an angle, otherwise as pulse width in microseconds
|
||||
void writeMicroseconds(int value); // Write pulse width in microseconds
|
||||
void move(const int value); // Attach the servo, then move to value
|
||||
// If value is < 200 it is treated as an angle, otherwise as pulse width in microseconds
|
||||
// If DEACTIVATE_SERVOS_AFTER_MOVE wait SERVO_DELAY, then detach
|
||||
int read(); // Return current pulse width as an angle between 0 and 180 degrees
|
||||
int readMicroseconds(); // Return current pulse width in microseconds for this servo
|
||||
bool attached(); // Return true if this servo is attached, otherwise false
|
||||
|
||||
private:
|
||||
uint8_t servoIndex; // index into the channel data for this servo
|
||||
int8_t min; // minimum is this value times 4 added to MIN_PULSE_WIDTH
|
||||
int8_t max; // maximum is this value times 4 added to MAX_PULSE_WIDTH
|
||||
uint8_t servoIndex; // Index into the channel data for this servo
|
||||
int8_t min; // Minimum is this value times 4 added to MIN_PULSE_WIDTH
|
||||
int8_t max; // Maximum is this value times 4 added to MAX_PULSE_WIDTH
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ debug_build_flags = -fstack-protector-strong -g -g3 -ggdb
|
|||
lib_compat_mode = off
|
||||
build_src_filter = ${common.default_src_filter} +<src/HAL/NATIVE_SIM>
|
||||
lib_deps = ${common.lib_deps}
|
||||
MarlinSimUI=https://github.com/p3p/MarlinSimUI/archive/afe7c1c293.zip
|
||||
MarlinSimUI=https://github.com/p3p/MarlinSimUI/archive/6ea016e104.zip
|
||||
Adafruit NeoPixel=https://github.com/p3p/Adafruit_NeoPixel/archive/c6b319f447.zip
|
||||
LiquidCrystal=https://github.com/p3p/LiquidCrystal/archive/322fb5fc23.zip
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue