diff --git a/README.md b/README.md index 6b8c5a8..881bd96 100644 --- a/README.md +++ b/README.md @@ -310,7 +310,9 @@ VIN sensing
# Revision History -### Version 2.1.1 +### Version 2.2.0 +- Added 2 functions startGoDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, ...). +- ESP32 core 3.x support. - Improved examples, especially follower examples. ### Version 2.1.0 diff --git a/examples/Basic/RobotCarConfigurations.h b/examples/Basic/RobotCarConfigurations.h index fc07c5d..ba7f32d 100644 --- a/examples/Basic/RobotCarConfigurations.h +++ b/examples/Basic/RobotCarConfigurations.h @@ -317,7 +317,7 @@ * BASIC CONFIGURATION for ESP32-Cam car * Car controlled by an ESP32-Cam module */ -#if defined(ESP32) // a temporarily hack +#if defined(ESP32) && !defined(CAR_IS_ESP32_CAM_BASED) // a temporarily hack #define CAR_IS_ESP32_CAM_BASED #endif #if defined(CAR_IS_ESP32_CAM_BASED) diff --git a/examples/IRDispatcherControl/Distance.hpp b/examples/IRDispatcherControl/Distance.hpp index 5cbcee2..50e2109 100644 --- a/examples/IRDispatcherControl/Distance.hpp +++ b/examples/IRDispatcherControl/Distance.hpp @@ -33,12 +33,16 @@ #include "HCSR04.hpp" // include sources #include "RobotCarConfigurations.h" // helps the pretty printer / Ctrl F -#if defined(CAR_HAS_SERVO) && defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) -#define DISABLE_SERVO_TIMER_AUTO_INITIALIZE // saves 70 bytes program space +#if defined(CAR_HAS_DISTANCE_SERVO) +# if defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) #include "LightweightServo.hpp" -#endif +# if defined(_LIGHTWEIGHT_SERVO_HPP) +LightweightServo DistanceServo; // The pan servo instance for distance sensor +# else // LightweightServo is not applicable for this CPU +#undef USE_LIGHTWEIGHT_SERVO_LIBRARY +# endif +# endif // defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) -#if defined(CAR_HAS_DISTANCE_SERVO) # if !defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) Servo DistanceServo; // The pan servo instance for distance sensor # endif @@ -87,7 +91,7 @@ ForwardDistancesInfoStruct sForwardDistancesInfo; void initDistance() { getDistanceModesFromPins(); -#if defined(CAR_HAS_DISTANCE_SERVO) && !defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) +#if defined(CAR_HAS_DISTANCE_SERVO) DistanceServo.attach(DISTANCE_SERVO_PIN); #endif @@ -492,11 +496,8 @@ void DistanceServoWriteAndWaitForStop(uint8_t aTargetDegrees, bool doWaitForStop // The servo is top down and therefore inverted aTargetDegrees = 180 - aTargetDegrees; #endif -#if defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) - write10(aTargetDegrees); -#else DistanceServo.write(aTargetDegrees); -#endif + /* * Delay until stopped diff --git a/examples/IRDispatcherControl/RobotCarIRCommands.hpp b/examples/IRDispatcherControl/RobotCarIRCommands.hpp index 0331900..a41968b 100644 --- a/examples/IRDispatcherControl/RobotCarIRCommands.hpp +++ b/examples/IRDispatcherControl/RobotCarIRCommands.hpp @@ -80,19 +80,19 @@ void doReset() { void goForward() { if (IRDispatcher.IRReceivedData.isRepeat) { // if repeat was pressed, we enable a "fast" stop - RobotCar.startGoDistanceMillimeter(RobotCar.rightCarMotor.DriveSpeedPWM, DEFAULT_CIRCUMFERENCE_MILLIMETER / 4, + RobotCar.startGoDistanceMillimeterWithSpeed(RobotCar.rightCarMotor.DriveSpeedPWM, DEFAULT_CIRCUMFERENCE_MILLIMETER / 4, DIRECTION_FORWARD); } else { - RobotCar.startGoDistanceMillimeter(RobotCar.rightCarMotor.DriveSpeedPWM, DEFAULT_CIRCUMFERENCE_MILLIMETER, + RobotCar.startGoDistanceMillimeterWithSpeed(RobotCar.rightCarMotor.DriveSpeedPWM, DEFAULT_CIRCUMFERENCE_MILLIMETER, DIRECTION_FORWARD); } } void goBackward() { if (IRDispatcher.IRReceivedData.isRepeat) { - RobotCar.startGoDistanceMillimeter(RobotCar.rightCarMotor.DriveSpeedPWM, DEFAULT_CIRCUMFERENCE_MILLIMETER / 4, + RobotCar.startGoDistanceMillimeterWithSpeed(RobotCar.rightCarMotor.DriveSpeedPWM, DEFAULT_CIRCUMFERENCE_MILLIMETER / 4, DIRECTION_BACKWARD); } else { - RobotCar.startGoDistanceMillimeter(RobotCar.rightCarMotor.DriveSpeedPWM, DEFAULT_CIRCUMFERENCE_MILLIMETER, + RobotCar.startGoDistanceMillimeterWithSpeed(RobotCar.rightCarMotor.DriveSpeedPWM, DEFAULT_CIRCUMFERENCE_MILLIMETER, DIRECTION_BACKWARD); } } diff --git a/examples/RobotCarBasic/Distance.hpp b/examples/RobotCarBasic/Distance.hpp index 5cbcee2..50e2109 100644 --- a/examples/RobotCarBasic/Distance.hpp +++ b/examples/RobotCarBasic/Distance.hpp @@ -33,12 +33,16 @@ #include "HCSR04.hpp" // include sources #include "RobotCarConfigurations.h" // helps the pretty printer / Ctrl F -#if defined(CAR_HAS_SERVO) && defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) -#define DISABLE_SERVO_TIMER_AUTO_INITIALIZE // saves 70 bytes program space +#if defined(CAR_HAS_DISTANCE_SERVO) +# if defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) #include "LightweightServo.hpp" -#endif +# if defined(_LIGHTWEIGHT_SERVO_HPP) +LightweightServo DistanceServo; // The pan servo instance for distance sensor +# else // LightweightServo is not applicable for this CPU +#undef USE_LIGHTWEIGHT_SERVO_LIBRARY +# endif +# endif // defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) -#if defined(CAR_HAS_DISTANCE_SERVO) # if !defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) Servo DistanceServo; // The pan servo instance for distance sensor # endif @@ -87,7 +91,7 @@ ForwardDistancesInfoStruct sForwardDistancesInfo; void initDistance() { getDistanceModesFromPins(); -#if defined(CAR_HAS_DISTANCE_SERVO) && !defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) +#if defined(CAR_HAS_DISTANCE_SERVO) DistanceServo.attach(DISTANCE_SERVO_PIN); #endif @@ -492,11 +496,8 @@ void DistanceServoWriteAndWaitForStop(uint8_t aTargetDegrees, bool doWaitForStop // The servo is top down and therefore inverted aTargetDegrees = 180 - aTargetDegrees; #endif -#if defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) - write10(aTargetDegrees); -#else DistanceServo.write(aTargetDegrees); -#endif + /* * Delay until stopped diff --git a/examples/RobotCarBlueDisplay/Distance.hpp b/examples/RobotCarBlueDisplay/Distance.hpp index 5cbcee2..50e2109 100644 --- a/examples/RobotCarBlueDisplay/Distance.hpp +++ b/examples/RobotCarBlueDisplay/Distance.hpp @@ -33,12 +33,16 @@ #include "HCSR04.hpp" // include sources #include "RobotCarConfigurations.h" // helps the pretty printer / Ctrl F -#if defined(CAR_HAS_SERVO) && defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) -#define DISABLE_SERVO_TIMER_AUTO_INITIALIZE // saves 70 bytes program space +#if defined(CAR_HAS_DISTANCE_SERVO) +# if defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) #include "LightweightServo.hpp" -#endif +# if defined(_LIGHTWEIGHT_SERVO_HPP) +LightweightServo DistanceServo; // The pan servo instance for distance sensor +# else // LightweightServo is not applicable for this CPU +#undef USE_LIGHTWEIGHT_SERVO_LIBRARY +# endif +# endif // defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) -#if defined(CAR_HAS_DISTANCE_SERVO) # if !defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) Servo DistanceServo; // The pan servo instance for distance sensor # endif @@ -87,7 +91,7 @@ ForwardDistancesInfoStruct sForwardDistancesInfo; void initDistance() { getDistanceModesFromPins(); -#if defined(CAR_HAS_DISTANCE_SERVO) && !defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) +#if defined(CAR_HAS_DISTANCE_SERVO) DistanceServo.attach(DISTANCE_SERVO_PIN); #endif @@ -492,11 +496,8 @@ void DistanceServoWriteAndWaitForStop(uint8_t aTargetDegrees, bool doWaitForStop // The servo is top down and therefore inverted aTargetDegrees = 180 - aTargetDegrees; #endif -#if defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) - write10(aTargetDegrees); -#else DistanceServo.write(aTargetDegrees); -#endif + /* * Delay until stopped diff --git a/examples/RobotCarBlueDisplay/LightweightServo.h b/examples/RobotCarBlueDisplay/LightweightServo.h index c4b1231..115646d 100644 --- a/examples/RobotCarBlueDisplay/LightweightServo.h +++ b/examples/RobotCarBlueDisplay/LightweightServo.h @@ -41,12 +41,12 @@ #define ISR_COUNT_FOR_2_5_MILLIS (F_CPU / (8 * 400)) // 5000 For 400 Hz, 2.5 ms using a prescaler of 8. #if defined(__AVR_ATmega2560__) -#define LEIGHTWEIGHT_SERVO_CHANNEL_A_PIN 46 -#define LEIGHTWEIGHT_SERVO_CHANNEL_B_PIN 45 -#define LEIGHTWEIGHT_SERVO_CHANNEL_C_PIN 44 +#define LIGHTWEIGHT_SERVO_CHANNEL_A_PIN 46 +#define LIGHTWEIGHT_SERVO_CHANNEL_B_PIN 45 +#define LIGHTWEIGHT_SERVO_CHANNEL_C_PIN 44 #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined (__AVR_ATmega328PB__) -#define LEIGHTWEIGHT_SERVO_CHANNEL_A_PIN 9 -#define LEIGHTWEIGHT_SERVO_CHANNEL_B_PIN 10 +#define LIGHTWEIGHT_SERVO_CHANNEL_A_PIN 9 +#define LIGHTWEIGHT_SERVO_CHANNEL_B_PIN 10 #endif void initLightweightServoPins(); // currently only pin 44 = OC5C/PL5, 45 = OC5B/PL4 + 46 = OC5A/PL3 on 2560 and pin 9 = OC1A + 10 = OC1B on 328 @@ -54,7 +54,8 @@ void checkAndInitLightweightServoPin(uint8_t aPin); void deinitLightweightServoPin(uint8_t aPin); // Set pin to input and disable non-inverting Compare Output mode int writeLightweightServoPin(int aDegree, uint8_t aPin, bool aUpdateFast = false); -void writeMicrosecondsLightweightServoPin(int aMicroseconds, uint8_t aPin, bool aUpdateFast = false); +// The last parameter requires 8 byte more than DISABLE_SERVO_TIMER_AUTO_INITIALIZE, if false, but saves around 60 bytes anyway +void writeMicrosecondsLightweightServoPin(int aMicroseconds, uint8_t aPin, bool aUpdateFast = false, bool aDoAutoInit = true); void setLightweightServoPulseMicrosFor0And180Degree(int aMicrosecondsForServo0Degree, int a180DegreeValue); void setLightweightServoRefreshRate(unsigned int aRefreshPeriodMicroseconds); @@ -89,6 +90,22 @@ int writeLightweightServo(int aDegree, bool aUsePin9, bool aUpdateFast = false); void writeMicrosecondsLightweightServo(int aMicroseconds, bool aUsePin9, bool aUpdateFast = false); #endif // Old and fast ATmega328 functions +class LightweightServo { +public: + uint8_t attach(int aPin); + uint8_t attach(int aPin, int aMicrosecondsForServo0Degree, int aMicrosecondsForServo180Degree); + void detach(); + void write(int aTargetDegreeOrMicrosecond); + void writeMicroseconds(int aTargetMicrosecond); // Write pulse width in microseconds + /* + * Variables to enable adjustment for different servo types + * 544 and 2400 are values compatible with standard arduino values + */ + int MicrosecondsForServo0Degree = 544; + int MicrosecondsForServo180Degree = 2400; + uint8_t LightweightServoPin; +}; + #endif // defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined (__AVR_ATmega328PB__) || defined(__AVR_ATmega2560__) /* diff --git a/examples/RobotCarBlueDisplay/LightweightServo.hpp b/examples/RobotCarBlueDisplay/LightweightServo.hpp index 1362790..b9ca849 100644 --- a/examples/RobotCarBlueDisplay/LightweightServo.hpp +++ b/examples/RobotCarBlueDisplay/LightweightServo.hpp @@ -1,7 +1,10 @@ /* * LightweightServo.hpp * - * Lightweight Servo implementation only for pin 9 and 10 using only timer1 hardware and no interrupts or other overhead. + * Lightweight Servo implementation timer hardware and no interrupts or other overhead. + * Supported pins: + * ATmega328: pin 44 = OC5C/PL5, 45 = OC5B/PL4 and 46 = OC5A/PL3 using only timer5 hardware + * ATmega2560 pin 9 = OC1A and 10 = OC1B on 328 using only timer1 hardware * Provides auto initialization. * 300 bytes code size / 4 bytes RAM including auto initialization compared to 700 / 48 bytes for Arduino Servo library. * 8 bytes for each call to setLightweightServoPulse... @@ -26,12 +29,12 @@ * */ -#ifndef _LIGHTWEIGHT_SERVO_HPP -#define _LIGHTWEIGHT_SERVO_HPP - #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined (__AVR_ATmega328PB__) || defined(__AVR_ATmega2560__) #include "LightweightServo.h" +#ifndef _LIGHTWEIGHT_SERVO_HPP +#define _LIGHTWEIGHT_SERVO_HPP + #if defined(DEBUG) #define LOCAL_DEBUG #else @@ -213,7 +216,9 @@ void writeMicroseconds10Direct(int aMicroseconds) { * Attention - both pins are set to OUTPUT here! * 32 bytes code size * Assume, that PRR1 PRTIM5 bit is low, which enables timer 5 - * Currently only pin 44 = OC5C/PL5, 45 = OC5B/PL4 + 46 = OC5A/PL3 on 2560 and pin 9 = OC1A + 10 = OC1B on 328 + * Supported pins: + * ATmega328: pin 44 = OC5C/PL5, 45 = OC5B/PL4 and 46 = OC5A/PL3 using only timer5 hardware + * ATmega2560 pin 9 = OC1A and 10 = OC1B on 328 using only timer1 hardware */ void initLightweightServoPins() { #if defined(__AVR_ATmega2560__) @@ -246,17 +251,17 @@ void checkAndInitLightweightServoPin(uint8_t aPin) { // Mask all other bits to zero! #if defined(__AVR_ATmega2560__) uint8_t tNewTCCR5A = TCCR5A & (_BV(COM5A1) | _BV(COM5B1) | _BV(COM5C1) | _BV(WGM51)); - if (aPin == LEIGHTWEIGHT_SERVO_CHANNEL_A_PIN && !(TCCR5A & (_BV(COM5A1)))) { + if (aPin == LIGHTWEIGHT_SERVO_CHANNEL_A_PIN && !(TCCR5A & (_BV(COM5A1)))) { OCR5A = UINT16_MAX; DDRL |= (_BV(DDL3)); tNewTCCR5A |= (_BV(COM5A1)) | _BV(WGM51); // FastPWM Mode mode TOP (20 ms) determined by ICR tPinWasNotInitialized = true; - } else if (aPin == LEIGHTWEIGHT_SERVO_CHANNEL_B_PIN && !(TCCR5A & (_BV(COM5B1)))) { + } else if (aPin == LIGHTWEIGHT_SERVO_CHANNEL_B_PIN && !(TCCR5A & (_BV(COM5B1)))) { OCR5B = UINT16_MAX; DDRL |= (_BV(DDL4)); tNewTCCR5A |= (_BV(COM5B1)) | _BV(WGM51); tPinWasNotInitialized = true; - } else if (aPin == LEIGHTWEIGHT_SERVO_CHANNEL_C_PIN && !(TCCR5A & (_BV(COM5C1)))) { + } else if (aPin == LIGHTWEIGHT_SERVO_CHANNEL_C_PIN && !(TCCR5A & (_BV(COM5C1)))) { OCR5C = UINT16_MAX; DDRL |= (_BV(DDL5)); tNewTCCR5A |= (_BV(COM5C1)) | _BV(WGM51); @@ -264,12 +269,12 @@ void checkAndInitLightweightServoPin(uint8_t aPin) { } #else uint8_t tNewTCCR1A = TCCR1A & (_BV(COM1A1) | _BV(COM1B1)); // keep existing COM1A1 and COM1B1 settings - if (aPin == LEIGHTWEIGHT_SERVO_CHANNEL_A_PIN && !(TCCR1A & (_BV(COM1A1)))) { + if (aPin == LIGHTWEIGHT_SERVO_CHANNEL_A_PIN && !(TCCR1A & (_BV(COM1A1)))) { OCR1A = UINT16_MAX; DDRB |= _BV(DDB1); // set OC1A = PortB1 -> PIN 9 to output direction tNewTCCR1A |= (_BV(COM1A1)) | _BV(WGM11); // FastPWM Mode mode TOP (20 ms) determined by ICR1 tPinWasNotInitialized = true; - } else if (aPin == LEIGHTWEIGHT_SERVO_CHANNEL_B_PIN && !(TCCR1A & (_BV(COM1B1)))) { + } else if (aPin == LIGHTWEIGHT_SERVO_CHANNEL_B_PIN && !(TCCR1A & (_BV(COM1B1)))) { OCR1B = UINT16_MAX; DDRB |= _BV(DDB2); // set OC1B = PortB2 -> PIN 10 to output direction tNewTCCR1A |= (_BV(COM1B1)) | _BV(WGM11); @@ -305,13 +310,14 @@ void checkAndInitLightweightServoPin(uint8_t aPin) { /* * Set pin to input and disable non-inverting Compare Output mode + * Init state is reflected by COMXX1 register bit */ void deinitLightweightServoPin(uint8_t aPin) { #if defined(__AVR_ATmega2560__) - if (aPin == LEIGHTWEIGHT_SERVO_CHANNEL_A_PIN) { + if (aPin == LIGHTWEIGHT_SERVO_CHANNEL_A_PIN) { DDRL &= ~(_BV(DDL3)); TCCR5A &= ~(_BV(COM5A1)); - } else if (aPin == LEIGHTWEIGHT_SERVO_CHANNEL_B_PIN) { + } else if (aPin == LIGHTWEIGHT_SERVO_CHANNEL_B_PIN) { DDRL &= ~(_BV(DDL4)); TCCR5A &= ~(_BV(COM5B1)); } else { @@ -319,10 +325,10 @@ void deinitLightweightServoPin(uint8_t aPin) { TCCR5A &= ~(_BV(COM5C1)); } #else - if (aPin == LEIGHTWEIGHT_SERVO_CHANNEL_A_PIN) { + if (aPin == LIGHTWEIGHT_SERVO_CHANNEL_A_PIN) { DDRB &= ~(_BV(DDB1)); // set OC1A = PortB1 -> PIN 9 to input direction TCCR1A &= ~(_BV(COM1A1)); // disable non-inverting Compare Output mode OC1A - } else if (aPin == LEIGHTWEIGHT_SERVO_CHANNEL_B_PIN) { + } else if (aPin == LIGHTWEIGHT_SERVO_CHANNEL_B_PIN) { DDRB &= ~(_BV(DDB2)); // set OC1B = PortB2 -> PIN 10 to input direction TCCR1A &= ~(_BV(COM1B1)); // disable non-inverting Compare Output mode OC1B } @@ -343,7 +349,7 @@ int writeLightweightServoPin(int aDegree, uint8_t aPin, bool aUpdateFast) { return aDegree; } -void writeMicrosecondsLightweightServoPin(int aMicroseconds, uint8_t aPin, bool aUpdateFast) { +void writeMicrosecondsLightweightServoPin(int aMicroseconds, uint8_t aPin, bool aUpdateFast, bool aDoAutoInit) { #if defined(LOCAL_DEBUG) Serial.print(F(" Micros=")); // trailing space required if called by _writeMicrosecondsOrUnits() Serial.print(aMicroseconds); @@ -351,29 +357,31 @@ void writeMicrosecondsLightweightServoPin(int aMicroseconds, uint8_t aPin, bool Serial.println(aPin); #endif #if !defined(DISABLE_SERVO_TIMER_AUTO_INITIALIZE) - checkAndInitLightweightServoPin(aPin); + if (aDoAutoInit) { + checkAndInitLightweightServoPin(aPin); + } #endif - // since the resolution is 1/2 of microsecond for 16 MHz CPU clock and prescaler of 8 +// since the resolution is 1/2 of microsecond for 16 MHz CPU clock and prescaler of 8 #if (F_CPU == 16000000L) aMicroseconds *= 2; #elif (F_CPU < 8000000L) // for 8 MHz resolution is exactly 1 microsecond :-) - aMicroseconds /= (8000000L / F_CPU); +aMicroseconds /= (8000000L / F_CPU); #endif #if defined(__AVR_ATmega2560__) - if (aUpdateFast) { - uint16_t tTimerCount = TCNT5; - if (tTimerCount > ISR_COUNT_FOR_2_5_MILLIS) { - // more than 2.5 ms since last pulse -> start a new one - TCNT5 = ICR5 - 1; - } - } - if (aPin == LEIGHTWEIGHT_SERVO_CHANNEL_A_PIN) { - OCR5A = aMicroseconds; - } else if (aPin == LEIGHTWEIGHT_SERVO_CHANNEL_B_PIN) { - OCR5B = aMicroseconds; - } else { - OCR5C = aMicroseconds; +if (aUpdateFast) { + uint16_t tTimerCount = TCNT5; + if (tTimerCount > ISR_COUNT_FOR_2_5_MILLIS) { + // more than 2.5 ms since last pulse -> start a new one + TCNT5 = ICR5 - 1; } +} +if (aPin == LIGHTWEIGHT_SERVO_CHANNEL_A_PIN) { + OCR5A = aMicroseconds; +} else if (aPin == LIGHTWEIGHT_SERVO_CHANNEL_B_PIN) { + OCR5B = aMicroseconds; +} else { + OCR5C = aMicroseconds; +} #else if (aUpdateFast) { uint16_t tTimerCount = TCNT1; @@ -382,7 +390,7 @@ void writeMicrosecondsLightweightServoPin(int aMicroseconds, uint8_t aPin, bool TCNT1 = ICR1 - 1; } } - if (aPin == LEIGHTWEIGHT_SERVO_CHANNEL_A_PIN) { + if (aPin == LIGHTWEIGHT_SERVO_CHANNEL_A_PIN) { OCR1A = aMicroseconds; } else { OCR1B = aMicroseconds; @@ -395,7 +403,11 @@ void writeMicrosecondsLightweightServoPin(int aMicroseconds, uint8_t aPin, bool * No parameter checking is done here! */ void setLightweightServoRefreshRate(unsigned int aRefreshPeriodMicroseconds) { +#if defined(__AVR_ATmega2560__) + ICR5 = aRefreshPeriodMicroseconds * 2; +#else ICR1 = aRefreshPeriodMicroseconds * 2; +#endif } /* * Set the mapping pulse width values for 0 and 180 degree @@ -416,8 +428,46 @@ int MicrosecondsToDegreeLightweightServo(int aMicroseconds) { return map(aMicroseconds, sMicrosecondsForServo0Degree, sMicrosecondsForServo180Degree, 0, 180); } +/* + * LightweightServo class functions + */ +uint8_t LightweightServo::attach(int aPin) { + LightweightServoPin = aPin; + checkAndInitLightweightServoPin(aPin); + return aPin; +} + +/* + * do not use parameters aMicrosecondsForServo0Degree and aMicrosecondsForServo180Degree + */ +uint8_t LightweightServo::attach(int aPin, int aMicrosecondsForServo0Degree, int aMicrosecondsForServo180Degree) { + LightweightServoPin = aPin; + MicrosecondsForServo0Degree = aMicrosecondsForServo0Degree; + MicrosecondsForServo180Degree = aMicrosecondsForServo180Degree; + checkAndInitLightweightServoPin(aPin); + return aPin; +} + +void LightweightServo::detach() { + deinitLightweightServoPin(LightweightServoPin); +} + +void LightweightServo::write(int aTargetDegreeOrMicrosecond) { + if (aTargetDegreeOrMicrosecond <= 180) { + aTargetDegreeOrMicrosecond = (map(aTargetDegreeOrMicrosecond, 0, 180, MicrosecondsForServo0Degree, + MicrosecondsForServo180Degree)); + } + // The last false parameter requires 8 byte more than DISABLE_SERVO_TIMER_AUTO_INITIALIZE, but saves around 60 bytes anyway + writeMicrosecondsLightweightServoPin(aTargetDegreeOrMicrosecond, LightweightServoPin, false, false); +} + +void LightweightServo::writeMicroseconds(int aTargetMicrosecond){ + // The last false parameter requires 8 byte more than DISABLE_SERVO_TIMER_AUTO_INITIALIZE, but saves around 60 bytes anyway + writeMicrosecondsLightweightServoPin(aTargetMicrosecond, LightweightServoPin, false, false); +} + #if defined(LOCAL_DEBUG) #undef LOCAL_DEBUG #endif -#endif // defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega2560__) #endif // _LIGHTWEIGHT_SERVO_HPP +#endif // defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega2560__) diff --git a/examples/SmartCarFollower/Distance.hpp b/examples/SmartCarFollower/Distance.hpp index 5cbcee2..50e2109 100644 --- a/examples/SmartCarFollower/Distance.hpp +++ b/examples/SmartCarFollower/Distance.hpp @@ -33,12 +33,16 @@ #include "HCSR04.hpp" // include sources #include "RobotCarConfigurations.h" // helps the pretty printer / Ctrl F -#if defined(CAR_HAS_SERVO) && defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) -#define DISABLE_SERVO_TIMER_AUTO_INITIALIZE // saves 70 bytes program space +#if defined(CAR_HAS_DISTANCE_SERVO) +# if defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) #include "LightweightServo.hpp" -#endif +# if defined(_LIGHTWEIGHT_SERVO_HPP) +LightweightServo DistanceServo; // The pan servo instance for distance sensor +# else // LightweightServo is not applicable for this CPU +#undef USE_LIGHTWEIGHT_SERVO_LIBRARY +# endif +# endif // defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) -#if defined(CAR_HAS_DISTANCE_SERVO) # if !defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) Servo DistanceServo; // The pan servo instance for distance sensor # endif @@ -87,7 +91,7 @@ ForwardDistancesInfoStruct sForwardDistancesInfo; void initDistance() { getDistanceModesFromPins(); -#if defined(CAR_HAS_DISTANCE_SERVO) && !defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) +#if defined(CAR_HAS_DISTANCE_SERVO) DistanceServo.attach(DISTANCE_SERVO_PIN); #endif @@ -492,11 +496,8 @@ void DistanceServoWriteAndWaitForStop(uint8_t aTargetDegrees, bool doWaitForStop // The servo is top down and therefore inverted aTargetDegrees = 180 - aTargetDegrees; #endif -#if defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) - write10(aTargetDegrees); -#else DistanceServo.write(aTargetDegrees); -#endif + /* * Delay until stopped diff --git a/examples/SmartCarFollower/RobotCarIRCommands.hpp b/examples/SmartCarFollower/RobotCarIRCommands.hpp index 0331900..a41968b 100644 --- a/examples/SmartCarFollower/RobotCarIRCommands.hpp +++ b/examples/SmartCarFollower/RobotCarIRCommands.hpp @@ -80,19 +80,19 @@ void doReset() { void goForward() { if (IRDispatcher.IRReceivedData.isRepeat) { // if repeat was pressed, we enable a "fast" stop - RobotCar.startGoDistanceMillimeter(RobotCar.rightCarMotor.DriveSpeedPWM, DEFAULT_CIRCUMFERENCE_MILLIMETER / 4, + RobotCar.startGoDistanceMillimeterWithSpeed(RobotCar.rightCarMotor.DriveSpeedPWM, DEFAULT_CIRCUMFERENCE_MILLIMETER / 4, DIRECTION_FORWARD); } else { - RobotCar.startGoDistanceMillimeter(RobotCar.rightCarMotor.DriveSpeedPWM, DEFAULT_CIRCUMFERENCE_MILLIMETER, + RobotCar.startGoDistanceMillimeterWithSpeed(RobotCar.rightCarMotor.DriveSpeedPWM, DEFAULT_CIRCUMFERENCE_MILLIMETER, DIRECTION_FORWARD); } } void goBackward() { if (IRDispatcher.IRReceivedData.isRepeat) { - RobotCar.startGoDistanceMillimeter(RobotCar.rightCarMotor.DriveSpeedPWM, DEFAULT_CIRCUMFERENCE_MILLIMETER / 4, + RobotCar.startGoDistanceMillimeterWithSpeed(RobotCar.rightCarMotor.DriveSpeedPWM, DEFAULT_CIRCUMFERENCE_MILLIMETER / 4, DIRECTION_BACKWARD); } else { - RobotCar.startGoDistanceMillimeter(RobotCar.rightCarMotor.DriveSpeedPWM, DEFAULT_CIRCUMFERENCE_MILLIMETER, + RobotCar.startGoDistanceMillimeterWithSpeed(RobotCar.rightCarMotor.DriveSpeedPWM, DEFAULT_CIRCUMFERENCE_MILLIMETER, DIRECTION_BACKWARD); } } diff --git a/library.json b/library.json index dd051c6..710fc20 100644 --- a/library.json +++ b/library.json @@ -6,7 +6,7 @@ "type": "git", "url": "https://github.com/ArminJo/PWMMotorControl" }, - "version": "2.1.0", + "version": "2.2.0", "exclude": "pictures", "authors": { "name": "Armin Joachimsmeyer", diff --git a/library.properties b/library.properties index 5701a36..bd692b3 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=PWMMotorControl -version=2.1.0 +version=2.2.0 author=Armin Joachimsmeyer maintainer=Armin Joachimsmeyer sentence=Control brushed DC motors by PWM and uses optional attached encoders to drive fixed distances. For L298 or TB6612, or Adafruit Motor Shield diff --git a/src/CarPWMMotorControl.h b/src/CarPWMMotorControl.h index e65b526..d444eb8 100644 --- a/src/CarPWMMotorControl.h +++ b/src/CarPWMMotorControl.h @@ -141,14 +141,17 @@ class CarPWMMotorControl { * Functions for moving a fixed distance */ // With signed distance - void startGoDistanceMillimeter(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, - uint8_t aRequestedDirection); // only setup values - void startGoDistanceMillimeter(unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection); // only setup values void startGoDistanceMillimeter(int aRequestedDistanceMillimeter); // only setup values, no movement -> use updateMotors() - + void startGoDistanceMillimeter(unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection); // only setup values + void startGoDistanceMillimeter(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, + uint8_t aRequestedDirection)__attribute__ ((deprecated ("Renamed to startGoDistanceMillimeterWithSpeed()."))); // only setup values void goDistanceMillimeter(int aRequestedDistanceMillimeter, void (*aLoopCallback)(void) = NULL); // Blocking function, uses waitUntilStopped + void goDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, int aRequestedDistanceMillimeter, void (*aLoopCallback)(void) = NULL); // Blocking function, uses waitUntilStopped void goDistanceMillimeter(unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection, void (*aLoopCallback)(void) = NULL); // Blocking function, uses waitUntilStopped + void startGoDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, int aRequestedDistanceMillimeter); // only setup values + void startGoDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, + uint8_t aRequestedDirection); // only setup values bool checkAndHandleDirectionChange(uint8_t aRequestedDirection); // used internally diff --git a/src/CarPWMMotorControl.hpp b/src/CarPWMMotorControl.hpp index 3dbb1ff..25967ac 100644 --- a/src/CarPWMMotorControl.hpp +++ b/src/CarPWMMotorControl.hpp @@ -553,13 +553,17 @@ void CarPWMMotorControl::startRampUpAndWaitForDriveSpeedPWM(uint8_t aRequestedDi } void CarPWMMotorControl::startGoDistanceMillimeter(unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection) { - startGoDistanceMillimeter(rightCarMotor.DriveSpeedPWMFor2Volt, aRequestedDistanceMillimeter, aRequestedDirection); + startGoDistanceMillimeterWithSpeed(rightCarMotor.DriveSpeedPWMFor2Volt, aRequestedDistanceMillimeter, aRequestedDirection); } +void CarPWMMotorControl::startGoDistanceMillimeter(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, + uint8_t aRequestedDirection) { + startGoDistanceMillimeterWithSpeed(aRequestedSpeedPWM, aRequestedDistanceMillimeter, aRequestedDirection); +} /* * initialize motorInfo fields LastDirection and CompensatedSpeedPWM */ -void CarPWMMotorControl::startGoDistanceMillimeter(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, +void CarPWMMotorControl::startGoDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection) { #if defined(USE_MPU6050_IMU) @@ -572,26 +576,34 @@ void CarPWMMotorControl::startGoDistanceMillimeter(uint8_t aRequestedSpeedPWM, u setSpeedPWMWithRamp(aRequestedSpeedPWM, aRequestedDirection); #else checkAndHandleDirectionChange(aRequestedDirection); - rightCarMotor.startGoDistanceMillimeter(aRequestedSpeedPWM, aRequestedDistanceMillimeter, aRequestedDirection); - leftCarMotor.startGoDistanceMillimeter(aRequestedSpeedPWM, aRequestedDistanceMillimeter, aRequestedDirection); + rightCarMotor.startGoDistanceMillimeterWithSpeed(aRequestedSpeedPWM, aRequestedDistanceMillimeter, aRequestedDirection); + leftCarMotor.startGoDistanceMillimeterWithSpeed(aRequestedSpeedPWM, aRequestedDistanceMillimeter, aRequestedDirection); #endif } void CarPWMMotorControl::goDistanceMillimeter(unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection, void (*aLoopCallback)(void)) { - startGoDistanceMillimeter(rightCarMotor.DriveSpeedPWMFor2Volt, aRequestedDistanceMillimeter, aRequestedDirection); + startGoDistanceMillimeterWithSpeed(rightCarMotor.DriveSpeedPWMFor2Volt, aRequestedDistanceMillimeter, aRequestedDirection); waitUntilStopped(aLoopCallback); } void CarPWMMotorControl::startGoDistanceMillimeter(int aRequestedDistanceMillimeter) { if (aRequestedDistanceMillimeter < 0) { aRequestedDistanceMillimeter = -aRequestedDistanceMillimeter; - startGoDistanceMillimeter(rightCarMotor.DriveSpeedPWMFor2Volt, aRequestedDistanceMillimeter, DIRECTION_BACKWARD); + startGoDistanceMillimeterWithSpeed(rightCarMotor.DriveSpeedPWMFor2Volt, aRequestedDistanceMillimeter, DIRECTION_BACKWARD); } else { - startGoDistanceMillimeter(rightCarMotor.DriveSpeedPWMFor2Volt, aRequestedDistanceMillimeter, DIRECTION_FORWARD); + startGoDistanceMillimeterWithSpeed(rightCarMotor.DriveSpeedPWMFor2Volt, aRequestedDistanceMillimeter, DIRECTION_FORWARD); } } +void CarPWMMotorControl::startGoDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, int aRequestedDistanceMillimeter) { + if (aRequestedDistanceMillimeter < 0) { + aRequestedDistanceMillimeter = -aRequestedDistanceMillimeter; + startGoDistanceMillimeterWithSpeed(aRequestedSpeedPWM, aRequestedDistanceMillimeter, DIRECTION_BACKWARD); + } else { + startGoDistanceMillimeterWithSpeed(aRequestedSpeedPWM, aRequestedDistanceMillimeter, DIRECTION_FORWARD); + } +} /** * Wait until distance is reached * @param aLoopCallback called until car has stopped to avoid blocking @@ -601,6 +613,11 @@ void CarPWMMotorControl::goDistanceMillimeter(int aRequestedDistanceMillimeter, waitUntilStopped(aLoopCallback); } +void CarPWMMotorControl::goDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, int aRequestedDistanceMillimeter, void (*aLoopCallback)(void)) { + startGoDistanceMillimeterWithSpeed(aRequestedSpeedPWM, aRequestedDistanceMillimeter); + waitUntilStopped(aLoopCallback); +} + /* * Stop car (with ramp) */ @@ -797,8 +814,8 @@ void CarPWMMotorControl::startRotate(int aRotationDegrees, turn_direction_t aTur tLeftMotorIfPositiveTurn->setSpeedPWMAndDirection(tTurnSpeedPWMLeft, DIRECTION_BACKWARD); } #else - tRightMotorIfPositiveTurn->startGoDistanceMillimeter(tTurnSpeedPWMRight, tDistanceMillimeterRight, DIRECTION_FORWARD); - tLeftMotorIfPositiveTurn->startGoDistanceMillimeter(tTurnSpeedPWMLeft, tDistanceMillimeterLeft, DIRECTION_BACKWARD); + tRightMotorIfPositiveTurn->startGoDistanceMillimeterWithSpeed(tTurnSpeedPWMRight, tDistanceMillimeterRight, DIRECTION_FORWARD); + tLeftMotorIfPositiveTurn->startGoDistanceMillimeterWithSpeed(tTurnSpeedPWMLeft, tDistanceMillimeterLeft, DIRECTION_BACKWARD); #endif } diff --git a/src/EncoderMotor.h b/src/EncoderMotor.h index 4ad7ee2..566208d 100644 --- a/src/EncoderMotor.h +++ b/src/EncoderMotor.h @@ -1,7 +1,6 @@ /* * EncoderMotor.h * - * Created on: 12.05.2019 * Copyright (C) 2019-2020 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * @@ -79,7 +78,9 @@ class EncoderMotor: public PWMDcMotor { */ void startGoDistanceMillimeter(int aRequestedDistanceMillimeter); // Signed distance count void startGoDistanceMillimeter(unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection); - void startGoDistanceMillimeter(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection); + void startGoDistanceMillimeter(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection)__attribute__ ((deprecated ("Renamed to startGoDistanceMillimeterWithSpeed()."))); + void startGoDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, int aRequestedDistanceMillimeter); // Signed distance count + void startGoDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection); bool updateMotor(); /* diff --git a/src/EncoderMotor.hpp b/src/EncoderMotor.hpp index d5a506d..2438f6b 100644 --- a/src/EncoderMotor.hpp +++ b/src/EncoderMotor.hpp @@ -11,8 +11,7 @@ * * Tested for Adafruit Motor Shield and plain TB6612 breakout board. * - * Created on: 12.05.2019 - * Copyright (C) 2019-2022 Armin Joachimsmeyer + * Copyright (C) 2019-2024 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of PWMMotorControl https://github.com/ArminJo/PWMMotorControl. @@ -90,10 +89,14 @@ void EncoderMotor::init(uint8_t aForwardPin, uint8_t aBackwardPin, uint8_t aPWMP } #endif +void EncoderMotor::startGoDistanceMillimeter(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, + uint8_t aRequestedDirection) { + startGoDistanceMillimeterWithSpeed( aRequestedSpeedPWM, aRequestedDistanceMillimeter, aRequestedDirection); +} /* * If motor is already running, adjust TargetDistanceMillimeter to go to aRequestedDistanceMillimeter */ -void EncoderMotor::startGoDistanceMillimeter(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, +void EncoderMotor::startGoDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection) { if (aRequestedDistanceMillimeter == 0) { stop(DefaultStopMode); // In case motor was running @@ -118,7 +121,7 @@ void EncoderMotor::startGoDistanceMillimeter(uint8_t aRequestedSpeedPWM, unsigne } void EncoderMotor::startGoDistanceMillimeter(unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection) { - startGoDistanceMillimeter(DriveSpeedPWM, aRequestedDistanceMillimeter, aRequestedDirection); + startGoDistanceMillimeterWithSpeed(DriveSpeedPWMFor2Volt, aRequestedDistanceMillimeter, aRequestedDirection); } /* @@ -128,9 +131,18 @@ void EncoderMotor::startGoDistanceMillimeter(unsigned int aRequestedDistanceMill void EncoderMotor::startGoDistanceMillimeter(int aRequestedDistanceMillimeter) { if (aRequestedDistanceMillimeter < 0) { aRequestedDistanceMillimeter = -aRequestedDistanceMillimeter; - startGoDistanceMillimeter(aRequestedDistanceMillimeter, DIRECTION_BACKWARD); + startGoDistanceMillimeterWithSpeed(DriveSpeedPWMFor2Volt, aRequestedDistanceMillimeter, DIRECTION_BACKWARD); + } else { + startGoDistanceMillimeterWithSpeed(DriveSpeedPWMFor2Volt, aRequestedDistanceMillimeter, DIRECTION_FORWARD); + } +} + +void EncoderMotor::startGoDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, int aRequestedDistanceMillimeter) { + if (aRequestedDistanceMillimeter < 0) { + aRequestedDistanceMillimeter = -aRequestedDistanceMillimeter; + startGoDistanceMillimeterWithSpeed(aRequestedSpeedPWM, aRequestedDistanceMillimeter, DIRECTION_BACKWARD); } else { - startGoDistanceMillimeter(aRequestedDistanceMillimeter, DIRECTION_FORWARD); + startGoDistanceMillimeterWithSpeed(aRequestedSpeedPWM, aRequestedDistanceMillimeter, DIRECTION_FORWARD); } } diff --git a/src/IMUCarData.h b/src/IMUCarData.h index f2404d8..1be7df5 100644 --- a/src/IMUCarData.h +++ b/src/IMUCarData.h @@ -3,7 +3,6 @@ * * Functions for getting IMU data from MPU6050 for car control. * - * Created on: 19.11.2020 * Copyright (C) 2020-2022 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * diff --git a/src/IMUCarData.hpp b/src/IMUCarData.hpp index 935f428..fd7ea45 100644 --- a/src/IMUCarData.hpp +++ b/src/IMUCarData.hpp @@ -9,7 +9,6 @@ * Automatic offset recalculation is done, if we do not detect any movement for NUMBER_OF_OFFSET_CALIBRATION_SAMPLES samples. * It can be activated (default) or suspended. * - * Created on: 19.11.2020 * Copyright (C) 2020-2022 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * diff --git a/src/MecanumWheelCarPWMMotorControl.h b/src/MecanumWheelCarPWMMotorControl.h index e731d13..ed55f2d 100644 --- a/src/MecanumWheelCarPWMMotorControl.h +++ b/src/MecanumWheelCarPWMMotorControl.h @@ -3,7 +3,7 @@ * * Contains functions for control of the 4 motors of a mecanum wheel car. * - * Copyright (C) 2022 Armin Joachimsmeyer + * Copyright (C) 2022-2024 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of PWMMotorControl https://github.com/ArminJo/PWMMotorControl. @@ -71,10 +71,13 @@ class MecanumWheelCarPWMMotorControl : public CarPWMMotorControl { * Functions for moving a fixed distance */ // With signed distance + void startGoDistanceMillimeter(int aRequestedDistanceMillimeter); // only setup values, no movement -> use updateMotors() + void startGoDistanceMillimeter(unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection); // only setup values void startGoDistanceMillimeter(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, + uint8_t aRequestedDirection) __attribute__ ((deprecated ("Renamed to startGoDistanceMillimeterWithSpeed()."))); + void startGoDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, int aRequestedDistanceMillimeter); // only setup values, no movement -> use updateMotors() + void startGoDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection); // only setup values - void startGoDistanceMillimeter(unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection); // only setup values - void startGoDistanceMillimeter(int aRequestedDistanceMillimeter); // only setup values, no movement -> use updateMotors() void goDistanceMillimeter(int aRequestedDistanceMillimeter, void (*aLoopCallback)(void) = NULL); // Blocking function, uses waitUntilStopped void goDistanceMillimeter(unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection, diff --git a/src/MecanumWheelCarPWMMotorControl.hpp b/src/MecanumWheelCarPWMMotorControl.hpp index 973a191..2433e08 100644 --- a/src/MecanumWheelCarPWMMotorControl.hpp +++ b/src/MecanumWheelCarPWMMotorControl.hpp @@ -424,13 +424,17 @@ void MecanumWheelCarPWMMotorControl::startRampUpAndWaitForDriveSpeedPWM(uint8_t void MecanumWheelCarPWMMotorControl::startGoDistanceMillimeter(unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection) { - startGoDistanceMillimeter(rightCarMotor.DriveSpeedPWM, aRequestedDistanceMillimeter, aRequestedDirection); + startGoDistanceMillimeterWithSpeed(rightCarMotor.DriveSpeedPWM, aRequestedDistanceMillimeter, aRequestedDirection); } +void MecanumWheelCarPWMMotorControl::startGoDistanceMillimeter(uint8_t aRequestedSpeedPWM, + unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection) { + startGoDistanceMillimeterWithSpeed(aRequestedSpeedPWM, aRequestedDistanceMillimeter, aRequestedDirection); +} /* * initialize motorInfo fields LastDirection and CompensatedSpeedPWM */ -void MecanumWheelCarPWMMotorControl::startGoDistanceMillimeter(uint8_t aRequestedSpeedPWM, +void MecanumWheelCarPWMMotorControl::startGoDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection) { #if defined(USE_MPU6050_IMU) @@ -443,23 +447,32 @@ void MecanumWheelCarPWMMotorControl::startGoDistanceMillimeter(uint8_t aRequeste setSpeedPWMWithRamp(aRequestedSpeedPWM, aRequestedDirection); #else checkAndHandleDirectionChange(aRequestedDirection); - rightCarMotor.startGoDistanceMillimeter(aRequestedSpeedPWM, aRequestedDistanceMillimeter, aRequestedDirection); + rightCarMotor.startGoDistanceMillimeterWithSpeed(aRequestedSpeedPWM, aRequestedDistanceMillimeter, aRequestedDirection); setDirection(aRequestedDirection); // this sets the direction for all the other motors #endif } void MecanumWheelCarPWMMotorControl::goDistanceMillimeter(unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection, void (*aLoopCallback)(void)) { - startGoDistanceMillimeter(rightCarMotor.DriveSpeedPWM, aRequestedDistanceMillimeter, aRequestedDirection); + startGoDistanceMillimeterWithSpeed(rightCarMotor.DriveSpeedPWM, aRequestedDistanceMillimeter, aRequestedDirection); waitUntilStopped(aLoopCallback); } void MecanumWheelCarPWMMotorControl::startGoDistanceMillimeter(int aRequestedDistanceMillimeter) { if (aRequestedDistanceMillimeter < 0) { aRequestedDistanceMillimeter = -aRequestedDistanceMillimeter; - startGoDistanceMillimeter(rightCarMotor.DriveSpeedPWM, aRequestedDistanceMillimeter, DIRECTION_BACKWARD); + startGoDistanceMillimeterWithSpeed(rightCarMotor.DriveSpeedPWM, aRequestedDistanceMillimeter, DIRECTION_BACKWARD); + } else { + startGoDistanceMillimeterWithSpeed(rightCarMotor.DriveSpeedPWM, aRequestedDistanceMillimeter, DIRECTION_FORWARD); + } +} + +void MecanumWheelCarPWMMotorControl::startGoDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, int aRequestedDistanceMillimeter) { + if (aRequestedDistanceMillimeter < 0) { + aRequestedDistanceMillimeter = -aRequestedDistanceMillimeter; + startGoDistanceMillimeterWithSpeed(aRequestedSpeedPWM, aRequestedDistanceMillimeter, DIRECTION_BACKWARD); } else { - startGoDistanceMillimeter(rightCarMotor.DriveSpeedPWM, aRequestedDistanceMillimeter, DIRECTION_FORWARD); + startGoDistanceMillimeterWithSpeed(aRequestedSpeedPWM, aRequestedDistanceMillimeter, DIRECTION_FORWARD); } } @@ -567,7 +580,7 @@ void MecanumWheelCarPWMMotorControl::startRotate(int aRotationDegrees, turn_dire tTurnSpeed = DEFAULT_START_SPEED_PWM; } // Use direction set by setDirection() above - rightCarMotor.startGoDistanceMillimeter(tTurnSpeed, tDistanceMillimeter, rightCarMotor.getDirection()); + rightCarMotor.startGoDistanceMillimeterWithSpeed(tTurnSpeed, tDistanceMillimeter, rightCarMotor.getDirection()); #if defined(LOCAL_DEBUG) Serial.print(F("RotationDegrees=")); Serial.print(aRotationDegrees); diff --git a/src/PWMDcMotor.h b/src/PWMDcMotor.h index 08f81b6..1a2cd67 100644 --- a/src/PWMDcMotor.h +++ b/src/PWMDcMotor.h @@ -14,7 +14,7 @@ * With encoder: - distance is measured by Encoder. * * - * Copyright (C) 2019-2022 Armin Joachimsmeyer + * Copyright (C) 2019-2024 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of PWMMotorControl https://github.com/ArminJo/PWMMotorControl. @@ -378,7 +378,11 @@ class PWMDcMotor { void startGoDistanceMillimeter(int aRequestedDistanceMillimeter); // Signed distance void startGoDistanceMillimeter(unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection); void startGoDistanceMillimeter(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, + uint8_t aRequestedDirection) __attribute__ ((deprecated ("Renamed to startGoDistanceMillimeterWithSpeed()."))); + void startGoDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, int aRequestedDistanceMillimeter); // Signed distance + void startGoDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection); + uint32_t convertMillimeterToMillis(uint8_t aSpeedPWM, unsigned int aRequestedDistanceMillimeter); unsigned int convertMillisToMillimeter(uint8_t aSpeedPWM, unsigned int aMillis); unsigned int convertMillisToCentimeterFor2Volt(unsigned int aMillis); @@ -462,6 +466,11 @@ class PWMDcMotor { }; /* + * Version 2.2.0 - 11/2024 + * - Added 2 functions startGoDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, ...). + * - ESP32 core 3.x support. + * - Improved examples, especially follower examples. + * * Version 2.1.0 - 09/2023 * - Added convertMillimeterToMillis() etc. * - Added Variable computedMillisOfMotorForDistance. diff --git a/src/PWMDcMotor.hpp b/src/PWMDcMotor.hpp index f18bb72..256855d 100644 --- a/src/PWMDcMotor.hpp +++ b/src/PWMDcMotor.hpp @@ -19,8 +19,7 @@ * A fixed speed compensation PWM value to be subtracted can be specified. * * - * Created on: 12.05.2019 - * Copyright (C) 2019-2022 Armin Joachimsmeyer + * Copyright (C) 2019-2024 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of PWMMotorControl https://github.com/ArminJo/PWMMotorControl. @@ -807,7 +806,7 @@ void PWMDcMotor::goDistanceMillimeter(unsigned int aRequestedDistanceMillimeter, */ void PWMDcMotor::goDistanceMillimeter(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection) { - startGoDistanceMillimeter(aRequestedSpeedPWM, aRequestedDistanceMillimeter, aRequestedDirection); + startGoDistanceMillimeterWithSpeed(aRequestedSpeedPWM, aRequestedDistanceMillimeter, aRequestedDirection); #if defined(DO_NOT_SUPPORT_RAMP) delay(computedMillisOfMotorForDistance); #else @@ -819,7 +818,7 @@ void PWMDcMotor::goDistanceMillimeter(uint8_t aRequestedSpeedPWM, unsigned int a } void PWMDcMotor::startGoDistanceMillimeter(unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection) { - startGoDistanceMillimeter(DriveSpeedPWMFor2Volt, aRequestedDistanceMillimeter, aRequestedDirection); + startGoDistanceMillimeterWithSpeed(DriveSpeedPWMFor2Volt, aRequestedDistanceMillimeter, aRequestedDirection); } /* @@ -828,9 +827,18 @@ void PWMDcMotor::startGoDistanceMillimeter(unsigned int aRequestedDistanceMillim void PWMDcMotor::startGoDistanceMillimeter(int aRequestedDistanceMillimeter) { if (aRequestedDistanceMillimeter < 0) { aRequestedDistanceMillimeter = -aRequestedDistanceMillimeter; - startGoDistanceMillimeter(DriveSpeedPWMFor2Volt, aRequestedDistanceMillimeter, DIRECTION_BACKWARD); + startGoDistanceMillimeterWithSpeed(DriveSpeedPWMFor2Volt, aRequestedDistanceMillimeter, DIRECTION_BACKWARD); } else { - startGoDistanceMillimeter(DriveSpeedPWMFor2Volt, aRequestedDistanceMillimeter, DIRECTION_FORWARD); + startGoDistanceMillimeterWithSpeed(DriveSpeedPWMFor2Volt, aRequestedDistanceMillimeter, DIRECTION_FORWARD); + } +} + +void PWMDcMotor::startGoDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, int aRequestedDistanceMillimeter) { + if (aRequestedDistanceMillimeter < 0) { + aRequestedDistanceMillimeter = -aRequestedDistanceMillimeter; + startGoDistanceMillimeterWithSpeed(aRequestedSpeedPWM, aRequestedDistanceMillimeter, DIRECTION_BACKWARD); + } else { + startGoDistanceMillimeterWithSpeed(aRequestedSpeedPWM, aRequestedDistanceMillimeter, DIRECTION_FORWARD); } } @@ -848,10 +856,15 @@ unsigned int PWMDcMotor::convertMillisToCentimeterFor2Volt(unsigned int aMillis) return aMillis / MillisPerCentimeter; } +void PWMDcMotor::startGoDistanceMillimeter(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, + uint8_t aRequestedDirection) { + startGoDistanceMillimeterWithSpeed(aRequestedSpeedPWM, aRequestedDistanceMillimeter, aRequestedDirection); +} + /* * If motor is already running, just update speed and new stop time */ -void PWMDcMotor::startGoDistanceMillimeter(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, +void PWMDcMotor::startGoDistanceMillimeterWithSpeed(uint8_t aRequestedSpeedPWM, unsigned int aRequestedDistanceMillimeter, uint8_t aRequestedDirection) { if (aRequestedDistanceMillimeter == 0) { stop(STOP_MODE_BRAKE); // In case motor was running