Динамически создавать функции для AccelStepper, использующие методы Adafrut_StepperMotor.oneStep?

В примере Adafruit_MotorShieldV2Library>Accel_MultiStepper AccelStepper инициализируются с использованием следующих static forwardstep1 и backstep1:

#include <Wire.h>
#include <AccelStepper.h>
#include <Adafruit_MotorShield.h>

//Сначала получите Adafruit_MotorShield
Adafruit_MotorShield AFMStop(0x60); // Адрес по умолчанию, без перемычек

//Затем достаем из него шаговый двигатель
Adafruit_StepperMotor *myStepper1 = AFMStop.getStepper(200, 1);

//Затем создаем обратные вызовы для конструктора AccelStepper
void forwardstep1() {  
    myStepper1->onestep(FORWARD, SINGLE);
}
void backwardstep1() {  
    myStepper1->onestep(BACKWARD, SINGLE);
}

//Наконец создадим шаговый двигатель
AccelStepper stepper1(forwardstep1, backwardstep1);

Я намерен затем использовать эти AccelStepper в качестве элементов в MultiStepper, который я я пропускаю здесь, потому что это не имеет отношения к делу.

Я хочу сделать функцию, автоматизирующую этот процесс. В идеале это должно работать примерно так:

typedef void(*mover)();
AccelStepper makeStepper(Adafruit_StepperMotor myStepper){
    // создаем функции перемещения типа
    mover forward = []{myStepper->onestep(FORWARD, DOUBLE);};
    mover back = []{myStep->onestep(BACKWARD, DOUBLE);};
    return AccelStepper step(forward, back);
}
  • Что я пробовал:
    • Очевидно, решение выше. Это не работает, потому что myStepper не захвачен, но если вы зафиксируете его, он не будет движущимся объектом и не может быть передан в AccelStepper.
    • Использование функции объекта. Это не работает, потому что объектные функции имеют неявный первый параметр this. Дополнительную информацию см. здесь
    • Сделать параметр myStepper статическим после его передачи. Это не работает, поскольку он перезаписывается при каждом вызове функции.
    • Использование std::forward. Вероятно, это сработает, но я не думаю, что std::forward определен в ArduinoSTL, потому что я продолжаю получать сообщение об ошибке 'forward' не является членом 'std'. См. код ниже:
      • Примечание. Пытаясь заставить это работать, я обновил следующие папки до -std=gnu++17 на своем компьютере с Ubuntu, в результате чего __cplusplus == 201500:
        • ~/.local/share/umake/ide/arduino/hardware/arduino/avr/platform.txt
        • ~/.local/share/umake/ide/arduino/hardware/hardware/platform.txt

попытка std::forward

#include <ArduinoSTL.h>
using namespace std;
#include <iostream>
#include <functional>
#include <utility>

typedef void(*mover)();

template <classF>
mover lambda_to_ptr(F&& f){
    static F fn = std::forward<F>(f);
    return []{ return fn();};
}
AccelStepper makeStepper(Adafruit_StepperMotor myStepper){
    // создаем функции перемещения типа
    mover forward = []{myStepper->onestep(FORWARD, DOUBLE);};
    mover back = []{myStep->onestep(BACKWARD, DOUBLE);};
    return AccelStepper step(lambda_to_prt(forward), lambda_to_ptr(back));
}

ps Конечно, я всегда могу изменить функции в библиотеке, но это (почти) всегда плохая идея.

, 👍1


1 ответ


1

В итоге я просто унаследовал AccelStepper и расширил AccelStepper::AccelStepper ( uint8_t interface = AccelStepper::FULL4WIRE,uint8_t pin1 = 2,uint8_t pin2 = 3, uint8_t pin3 = 4, uint8_t pin4 = 5, bool enable = true ) для добавления собственной переменной экземпляра Adafruit_StepperMotor и использовать его в переопределенном шаге0 (это единственная функция, в которой использовались эти обратные вызовы).

class MyAccelStepper: public AccelStepper
{
   public:
       MyAccelStepper(Adafruit_StepperMotor *myStepper):AccelStepper(0,0,0,0,0,false)
       {
         //MyStepper(0, 0, 0, 0, 0, ложь);
         _myStepper = myStepper;
       }
   protected:
       void step0(long step){
          (void)(step);
          if(speed() > 0){
            _myStepper->onestep(FORWARD, DOUBLE);
          }else{
            _myStepper->onestep(BACKWARD, DOUBLE);            
          }
       }
    private:
       Adafruit_StepperMotor *_myStepper;
};
,