Renamed SpanStep to StepperControl and moved into HoneSpan Extras
Also updated StepperMotorControl Example.
This commit is contained in:
parent
d7aca25ac9
commit
5e1d65f436
|
|
@ -34,7 +34,7 @@
|
||||||
// that Example first if new to HomeSpan since it is fully commented.
|
// that Example first if new to HomeSpan since it is fully commented.
|
||||||
|
|
||||||
#include "HomeSpan.h"
|
#include "HomeSpan.h"
|
||||||
#include "Stepper_TB6612.h" // include stepper motor control for a TB6612 driver chip
|
#include "Stepper_TB6612.h"
|
||||||
|
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
|
|
||||||
|
|
@ -63,7 +63,7 @@ struct DEV_WindowShade : Service::WindowCovering {
|
||||||
// Move motor to absolute position, assuming 200 steps per revolution and 20 revolutions for full up/travel travel.
|
// Move motor to absolute position, assuming 200 steps per revolution and 20 revolutions for full up/travel travel.
|
||||||
// Specify that motor should BRAKE upon moving to desired position.
|
// Specify that motor should BRAKE upon moving to desired position.
|
||||||
|
|
||||||
motor->moveTo(target->getNewVal()*20,5,SpanStep::BRAKE);
|
motor->moveTo(target->getNewVal()*20,5,Stepper_TB6612::BRAKE);
|
||||||
LOG1("Setting Shade Position=%d\n",target->getNewVal());
|
LOG1("Setting Shade Position=%d\n",target->getNewVal());
|
||||||
return(true);
|
return(true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
/*********************************************************************************
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Gregg E. Berman
|
||||||
|
*
|
||||||
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#include "extras/StepperControl.h"
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
struct Stepper_TB6612 : StepperControl {
|
||||||
|
|
||||||
|
int pins[4];
|
||||||
|
uint8_t phase;
|
||||||
|
uint8_t nPhases;
|
||||||
|
uint32_t runCode;
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
Stepper_TB6612(int a1Pin, int a2Pin, int b1Pin, int b2Pin) : StepperControl(){
|
||||||
|
pins[3]=a1Pin;
|
||||||
|
pins[2]=a2Pin;
|
||||||
|
pins[1]=b1Pin;
|
||||||
|
pins[0]=b2Pin;
|
||||||
|
|
||||||
|
for(int i=0;i<4;i++)
|
||||||
|
pinMode(pins[i],OUTPUT);
|
||||||
|
|
||||||
|
setStepType(FULL_STEP_TWO_PHASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void onEnable() override {
|
||||||
|
setPinCode((runCode>>(phase*4)) & 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void onDisable() override {
|
||||||
|
setPinCode(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void onBrake() override {
|
||||||
|
setPinCode(0xF);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void onStep(boolean direction){
|
||||||
|
if(direction)
|
||||||
|
phase=(phase+1)%nPhases;
|
||||||
|
else
|
||||||
|
phase=(phase+nPhases-1)%nPhases;
|
||||||
|
|
||||||
|
setPinCode((runCode>>(phase*4)) & 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void setPinCode(uint8_t pinCode){
|
||||||
|
for(int i=0;i<4;i++)
|
||||||
|
digitalWrite(pins[i],(pinCode>>i)&1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void setStepType(int mode) override {
|
||||||
|
switch(mode){
|
||||||
|
case FULL_STEP_ONE_PHASE:
|
||||||
|
phase=0;
|
||||||
|
nPhases=4;
|
||||||
|
runCode=0x2418;
|
||||||
|
break;
|
||||||
|
case FULL_STEP_TWO_PHASE:
|
||||||
|
phase=0;
|
||||||
|
nPhases=4;
|
||||||
|
runCode=0x659A;
|
||||||
|
break;
|
||||||
|
case HALF_STEP:
|
||||||
|
phase=0;
|
||||||
|
nPhases=8;
|
||||||
|
runCode=0x2645198A;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG,"Unknown StepType=%d. Stepper Unchanged",mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*********************************************************************************
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2023 Gregg E. Berman
|
||||||
|
*
|
||||||
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../src/extras/StepperControl.h"
|
||||||
|
|
@ -52,7 +52,7 @@ LedC::LedC(uint8_t pin, uint16_t freq, boolean invert){
|
||||||
|
|
||||||
timerList[nTimer][nMode]->duty_resolution=(ledc_timer_bit_t)res;
|
timerList[nTimer][nMode]->duty_resolution=(ledc_timer_bit_t)res;
|
||||||
if(ledc_timer_config(timerList[nTimer][nMode])!=0){
|
if(ledc_timer_config(timerList[nTimer][nMode])!=0){
|
||||||
ESP_LOGW(PWM_TAG,"Frequency=%d Hz is out of allowed range ---",freq);
|
ESP_LOGE(PWM_TAG,"Frequency=%d Hz is out of allowed range ---",freq);
|
||||||
delete timerList[nTimer][nMode];
|
delete timerList[nTimer][nMode];
|
||||||
timerList[nTimer][nMode]=NULL;
|
timerList[nTimer][nMode]=NULL;
|
||||||
return;
|
return;
|
||||||
|
|
@ -83,7 +83,7 @@ LedC::LedC(uint8_t pin, uint16_t freq, boolean invert){
|
||||||
LedPin::LedPin(uint8_t pin, float level, uint16_t freq, boolean invert) : LedC(pin, freq, invert){
|
LedPin::LedPin(uint8_t pin, float level, uint16_t freq, boolean invert) : LedC(pin, freq, invert){
|
||||||
|
|
||||||
if(!channel){
|
if(!channel){
|
||||||
ESP_LOGW(PWM_TAG,"Can't create LedPin(%d) - no open PWM channels and/or Timers",pin);
|
ESP_LOGE(PWM_TAG,"Can't create LedPin(%d) - no open PWM channels and/or Timers",pin);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -224,7 +224,7 @@ void LedPin::HSVtoRGB(float h, float s, float v, float *r, float *g, float *b ){
|
||||||
ServoPin::ServoPin(uint8_t pin, double initDegrees, uint16_t minMicros, uint16_t maxMicros, double minDegrees, double maxDegrees) : LedC(pin, 50){
|
ServoPin::ServoPin(uint8_t pin, double initDegrees, uint16_t minMicros, uint16_t maxMicros, double minDegrees, double maxDegrees) : LedC(pin, 50){
|
||||||
|
|
||||||
if(!channel)
|
if(!channel)
|
||||||
ESP_LOGW(PWM_TAG,"Can't create ServoPin(%d) - no open PWM channels and/or Timers",pin);
|
ESP_LOGE(PWM_TAG,"Can't create ServoPin(%d) - no open PWM channels and/or Timers",pin);
|
||||||
else
|
else
|
||||||
ESP_LOGI(PWM_TAG,"ServoPin=%d: mode=%d channel=%d, timer=%d, freq=%d Hz, resolution=%d bits",
|
ESP_LOGI(PWM_TAG,"ServoPin=%d: mode=%d channel=%d, timer=%d, freq=%d Hz, resolution=%d bits",
|
||||||
channel->gpio_num,
|
channel->gpio_num,
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ RFControl::RFControl(uint8_t pin, boolean refClock, boolean installDriver){
|
||||||
#else
|
#else
|
||||||
if(nChannels==RMT_CHANNEL_MAX){
|
if(nChannels==RMT_CHANNEL_MAX){
|
||||||
#endif
|
#endif
|
||||||
ESP_LOGW(RFControl_TAG,"Can't create RFControl(%d) - no open channels",pin);
|
ESP_LOGE(RFControl_TAG,"Can't create RFControl(%d) - no open channels",pin);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -139,17 +139,17 @@ void RFControl::enableCarrier(uint32_t freq, float duty){
|
||||||
uint32_t lowTime=period*(1.0-duty)+0.5;
|
uint32_t lowTime=period*(1.0-duty)+0.5;
|
||||||
|
|
||||||
if(highTime>0xFFFF || lowTime>0xFFFF){
|
if(highTime>0xFFFF || lowTime>0xFFFF){
|
||||||
ESP_LOGW(RFControl_TAG,"Can't enable carrier frequency=%d Hz for RF Control pin=%d, duty=%0.2f. Frequency is too low!",freq,config->gpio_num,duty);
|
ESP_LOGE(RFControl_TAG,"Can't enable carrier frequency=%d Hz for RF Control pin=%d, duty=%0.2f. Frequency is too low!",freq,config->gpio_num,duty);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(highTime==0){
|
if(highTime==0){
|
||||||
ESP_LOGW(RFControl_TAG,"Can't enable carrier frequency=%d Hz for RF Control pin=%d, duty=%0.2f. Duty is too low or frequency is too high!",freq,config->gpio_num,duty);
|
ESP_LOGE(RFControl_TAG,"Can't enable carrier frequency=%d Hz for RF Control pin=%d, duty=%0.2f. Duty is too low or frequency is too high!",freq,config->gpio_num,duty);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lowTime==0){
|
if(lowTime==0){
|
||||||
ESP_LOGW(RFControl_TAG,"Can't enable carrier frequency=%d Hz for RF Control pin=%d, duty=%0.2f. Duty is too high or frequency is too high!",freq,config->gpio_num,duty);
|
ESP_LOGE(RFControl_TAG,"Can't enable carrier frequency=%d Hz for RF Control pin=%d, duty=%0.2f. Duty is too high or frequency is too high!",freq,config->gpio_num,duty);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,171 @@
|
||||||
|
/*********************************************************************************
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Gregg E. Berman
|
||||||
|
*
|
||||||
|
* https://github.com/HomeSpan/HomeStep
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#include "StepperControl.h"
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
StepperControl::StepperControl(uint32_t priority, uint32_t cpu){
|
||||||
|
|
||||||
|
upLinkQueue = xQueueCreate(1,sizeof(upLink_t));
|
||||||
|
downLinkQueue = xQueueCreate(1,sizeof(downLink_t));
|
||||||
|
xTaskCreateUniversal(motorTask, "motorTaskHandle", 8096, this, priority, &motorTaskHandle, cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void StepperControl::setAccel(float accelSize, float accelSteps){
|
||||||
|
if(accelSize<0.0){
|
||||||
|
ESP_LOGE(TAG,"accelSize cannot be less than 0.0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(accelSteps<1.0){
|
||||||
|
ESP_LOGE(TAG,"accelSteps cannot be less than 1.0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->accelSize=accelSize;
|
||||||
|
this->accelSteps=accelSteps;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void StepperControl::move(int nSteps, uint32_t msDelay, endAction_t endAction){
|
||||||
|
if(msDelay==0){
|
||||||
|
ESP_LOGE(TAG,"msDelay must be greater than zero");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
upLink_t upLinkData = { .nSteps=nSteps, .msDelay=msDelay, .absoluteStep=false, endAction=endAction };
|
||||||
|
xQueueReceive(downLinkQueue,&downLinkData,0);
|
||||||
|
downLinkData.stepsRemaining=nSteps;
|
||||||
|
xQueueOverwrite(upLinkQueue,&upLinkData);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void StepperControl::moveTo(int nPosition, uint32_t msDelay, endAction_t endAction){
|
||||||
|
if(msDelay==0){
|
||||||
|
ESP_LOGE(TAG,"msDelay must be greater than zero");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
upLink_t upLinkData = { .nSteps=nPosition, .msDelay=msDelay, .absoluteStep=true, .endAction=endAction };
|
||||||
|
xQueueReceive(downLinkQueue,&downLinkData,0);
|
||||||
|
downLinkData.stepsRemaining=nPosition-downLinkData.position;
|
||||||
|
xQueueOverwrite(upLinkQueue,&upLinkData);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
int StepperControl::stepsRemaining(){
|
||||||
|
xQueuePeek(downLinkQueue,&downLinkData,0);
|
||||||
|
return(downLinkData.stepsRemaining);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
int StepperControl::position(){
|
||||||
|
xQueuePeek(downLinkQueue,&downLinkData,0);
|
||||||
|
return(downLinkData.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void StepperControl::brake(){
|
||||||
|
move(0,10,BRAKE);
|
||||||
|
while(stepsRemaining());
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void StepperControl::disable(){
|
||||||
|
move(0,10,DISABLE);
|
||||||
|
while(stepsRemaining());
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void StepperControl::enable(){
|
||||||
|
move(0,10);
|
||||||
|
while(stepsRemaining());
|
||||||
|
|
||||||
|
}//////////////////////////
|
||||||
|
|
||||||
|
void StepperControl::motorTask(void *args){
|
||||||
|
StepperControl *motor = (StepperControl *)args;
|
||||||
|
upLink_t upLinkData = { .nSteps=0, .msDelay=10, .absoluteStep=false, .endAction=NONE };
|
||||||
|
downLink_t downLinkData = { .stepsRemaining=0, .position=0 };
|
||||||
|
boolean running=false;
|
||||||
|
|
||||||
|
for(;;){
|
||||||
|
|
||||||
|
if(xQueueReceive(motor->upLinkQueue, &upLinkData, 0)){
|
||||||
|
if(upLinkData.absoluteStep)
|
||||||
|
upLinkData.nSteps-=downLinkData.position;
|
||||||
|
downLinkData.stepsRemaining=upLinkData.nSteps;
|
||||||
|
motor->onEnable();
|
||||||
|
running=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t msDelay=upLinkData.msDelay;
|
||||||
|
|
||||||
|
if(running==false){
|
||||||
|
vTaskDelay(msDelay);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(downLinkData.stepsRemaining!=0)
|
||||||
|
msDelay+=msDelay * motor->accelSize * (exp(-fabs(upLinkData.nSteps-downLinkData.stepsRemaining)/motor->accelSteps) + exp(-(fabs(downLinkData.stepsRemaining)-1.0)/motor->accelSteps));
|
||||||
|
|
||||||
|
ESP_LOGD(TAG,"Position: %d Steps Remaining: %d Delay=%d ms",downLinkData.position,downLinkData.stepsRemaining,(int)(msDelay));
|
||||||
|
|
||||||
|
int dStep=0;
|
||||||
|
|
||||||
|
if(downLinkData.stepsRemaining>0){
|
||||||
|
dStep=-1;
|
||||||
|
motor->onStep(1);
|
||||||
|
} else if(downLinkData.stepsRemaining<0){
|
||||||
|
dStep=1;
|
||||||
|
motor->onStep(0);
|
||||||
|
} else {
|
||||||
|
if(upLinkData.endAction==DISABLE)
|
||||||
|
motor->onDisable();
|
||||||
|
else if(upLinkData.endAction==BRAKE)
|
||||||
|
motor->onBrake();
|
||||||
|
running=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
xQueueOverwrite(motor->downLinkQueue,&downLinkData);
|
||||||
|
downLinkData.stepsRemaining+=dStep;
|
||||||
|
downLinkData.position-=dStep;
|
||||||
|
vTaskDelay(msDelay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*********************************************************************************
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Gregg E. Berman
|
||||||
|
*
|
||||||
|
* https://github.com/HomeSpan/HomeStep
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
[[maybe_unused]] static const char* TAG = "StepperControl";
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
class StepperControl {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum {
|
||||||
|
FULL_STEP_ONE_PHASE=0,
|
||||||
|
FULL_STEP_TWO_PHASE=1,
|
||||||
|
HALF_STEP=2,
|
||||||
|
QUARTER_STEP=4,
|
||||||
|
EIGHTH_STEP=8
|
||||||
|
};
|
||||||
|
|
||||||
|
enum endAction_t {
|
||||||
|
NONE,
|
||||||
|
DISABLE,
|
||||||
|
BRAKE
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct upLink_t {
|
||||||
|
int nSteps;
|
||||||
|
uint32_t msDelay;
|
||||||
|
boolean absoluteStep;
|
||||||
|
endAction_t endAction;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct downLink_t {
|
||||||
|
int stepsRemaining;
|
||||||
|
int position;
|
||||||
|
};
|
||||||
|
|
||||||
|
float accelSteps=1;
|
||||||
|
float accelSize=0;
|
||||||
|
downLink_t downLinkData = { .stepsRemaining=0, .position=0 };
|
||||||
|
|
||||||
|
TaskHandle_t motorTaskHandle;
|
||||||
|
QueueHandle_t upLinkQueue;
|
||||||
|
QueueHandle_t downLinkQueue;
|
||||||
|
|
||||||
|
virtual void onStep(boolean direction)=0;
|
||||||
|
virtual void onEnable(){};
|
||||||
|
virtual void onDisable(){};
|
||||||
|
virtual void onBrake(){};
|
||||||
|
static void motorTask(void *args);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
StepperControl(uint32_t priority=2, uint32_t cpu=0);
|
||||||
|
virtual void setStepType(int mode){};
|
||||||
|
void setAccel(float accelSize, float accelSteps);
|
||||||
|
void move(int nSteps, uint32_t msDelay, endAction_t endAction=NONE);
|
||||||
|
void moveTo(int nPosition, uint32_t msDelay, endAction_t endAction=NONE);
|
||||||
|
int position();
|
||||||
|
int stepsRemaining();
|
||||||
|
void enable();
|
||||||
|
void disable();
|
||||||
|
void brake();
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
@ -28,57 +28,210 @@
|
||||||
// This is a placeholder .ino file that allows you to easily edit the contents of this files using the Arduino IDE,
|
// This is a placeholder .ino file that allows you to easily edit the contents of this files using the Arduino IDE,
|
||||||
// as well as compile and test from this point. This file is ignored when the library is included in other sketches.
|
// as well as compile and test from this point. This file is ignored when the library is included in other sketches.
|
||||||
|
|
||||||
#include "PwmPin.h"
|
#include "StepperControl.h"
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
struct Stepper_TB6612 : StepperControl {
|
||||||
|
|
||||||
|
int pins[4];
|
||||||
|
uint8_t phase;
|
||||||
|
uint8_t nPhases;
|
||||||
|
uint32_t runCode;
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
Stepper_TB6612(int a1Pin, int a2Pin, int b1Pin, int b2Pin) : StepperControl(){
|
||||||
|
pins[3]=a1Pin;
|
||||||
|
pins[2]=a2Pin;
|
||||||
|
pins[1]=b1Pin;
|
||||||
|
pins[0]=b2Pin;
|
||||||
|
|
||||||
|
for(int i=0;i<4;i++)
|
||||||
|
pinMode(pins[i],OUTPUT);
|
||||||
|
|
||||||
|
setStepType(FULL_STEP_TWO_PHASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void onEnable() override {
|
||||||
|
setPinCode((runCode>>(phase*4)) & 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void onDisable() override {
|
||||||
|
setPinCode(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void onBrake() override {
|
||||||
|
setPinCode(0xF);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void onStep(boolean direction){
|
||||||
|
if(direction)
|
||||||
|
phase=(phase+1)%nPhases;
|
||||||
|
else
|
||||||
|
phase=(phase+nPhases-1)%nPhases;
|
||||||
|
|
||||||
|
setPinCode((runCode>>(phase*4)) & 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void setPinCode(uint8_t pinCode){
|
||||||
|
for(int i=0;i<4;i++)
|
||||||
|
digitalWrite(pins[i],(pinCode>>i)&1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void setStepType(int mode) override {
|
||||||
|
switch(mode){
|
||||||
|
case FULL_STEP_ONE_PHASE:
|
||||||
|
phase=0;
|
||||||
|
nPhases=4;
|
||||||
|
runCode=0x2418;
|
||||||
|
break;
|
||||||
|
case FULL_STEP_TWO_PHASE:
|
||||||
|
phase=0;
|
||||||
|
nPhases=4;
|
||||||
|
runCode=0x659A;
|
||||||
|
break;
|
||||||
|
case HALF_STEP:
|
||||||
|
phase=0;
|
||||||
|
nPhases=8;
|
||||||
|
runCode=0x2645198A;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG,"Unknown StepType=%d. Stepper Unchanged",mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
struct Stepper_A3967 : StepperControl {
|
||||||
|
|
||||||
|
int m1Pin;
|
||||||
|
int m2Pin;
|
||||||
|
int stepPin;
|
||||||
|
int dirPin;
|
||||||
|
int enablePin;
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
Stepper_A3967(int m1Pin, int m2Pin, int stepPin, int dirPin, int enablePin) : StepperControl(){
|
||||||
|
this->m1Pin=m1Pin;
|
||||||
|
this->m2Pin=m2Pin;
|
||||||
|
this->stepPin=stepPin;
|
||||||
|
this->dirPin=dirPin;
|
||||||
|
this->enablePin=enablePin;
|
||||||
|
|
||||||
|
pinMode(m1Pin,OUTPUT);
|
||||||
|
pinMode(m2Pin,OUTPUT);
|
||||||
|
pinMode(stepPin,OUTPUT);
|
||||||
|
pinMode(dirPin,OUTPUT);
|
||||||
|
pinMode(enablePin,OUTPUT);
|
||||||
|
|
||||||
|
setStepType(FULL_STEP_TWO_PHASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void onStep(boolean direction){
|
||||||
|
digitalWrite(dirPin,direction);
|
||||||
|
digitalWrite(stepPin,HIGH);
|
||||||
|
digitalWrite(stepPin,LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void onEnable() override {
|
||||||
|
digitalWrite(enablePin,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void onDisable() override {
|
||||||
|
digitalWrite(enablePin,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
void setStepType(int mode) override {
|
||||||
|
switch(mode){
|
||||||
|
case FULL_STEP_TWO_PHASE:
|
||||||
|
digitalWrite(m1Pin,LOW);
|
||||||
|
digitalWrite(m2Pin,LOW);
|
||||||
|
break;
|
||||||
|
case HALF_STEP:
|
||||||
|
digitalWrite(m1Pin,HIGH);
|
||||||
|
digitalWrite(m2Pin,LOW);
|
||||||
|
break;
|
||||||
|
case QUARTER_STEP:
|
||||||
|
digitalWrite(m1Pin,LOW);
|
||||||
|
digitalWrite(m2Pin,HIGH);
|
||||||
|
break;
|
||||||
|
case EIGHTH_STEP:
|
||||||
|
digitalWrite(m1Pin,HIGH);
|
||||||
|
digitalWrite(m2Pin,HIGH);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG,"Unknown StepType=%d. Stepper Unchanged",mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
StepperControl *motor[2];
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
|
|
||||||
Serial.begin(115200); // start the Serial interface
|
Serial.begin(115200);
|
||||||
Serial.flush();
|
|
||||||
delay(1000); // wait for interface to flush
|
|
||||||
|
|
||||||
Serial.println("\n\nHomeSpan LED Fade Test\n");
|
|
||||||
|
|
||||||
LedPin red(14,0);
|
|
||||||
LedPin green(14,0);
|
|
||||||
LedPin blue(14,0);
|
|
||||||
LedPin blue2(14,0,1000);
|
|
||||||
LedPin blue3(14,0,2000);
|
|
||||||
LedPin blue4(14,0,3000);
|
|
||||||
LedPin blue5(14,0,60000);
|
|
||||||
LedPin blue6(14,0,5000);
|
|
||||||
LedPin blue7(14,0,6000);
|
|
||||||
LedPin blue8(14,0,7000);
|
|
||||||
LedPin blue9(14,0,8000);
|
|
||||||
LedPin blue10(14,0,8000);
|
|
||||||
LedPin blue11(14,0,8000);
|
|
||||||
LedPin blue12(14,0,8000);
|
|
||||||
LedPin blue13(14,0,8000);
|
|
||||||
LedPin blue14(14,0,5000);
|
|
||||||
LedPin blue15(14,0,5000);
|
|
||||||
LedPin blue16(14,0,15000);
|
|
||||||
|
|
||||||
int redLevel=0;
|
|
||||||
|
|
||||||
for(int i=100;i<=100;i+=10){
|
|
||||||
while(red.fadeStatus()==LedPin::FADING);
|
|
||||||
red.fade(i,1000,LedPin::PROPORTIONAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
while(1);
|
|
||||||
|
|
||||||
|
|
||||||
while(1){
|
|
||||||
delay(1000);
|
delay(1000);
|
||||||
if(red.fade(redLevel,5000))
|
Serial.printf("\nReady.\n\n");
|
||||||
Serial.printf("Failed\n");
|
|
||||||
else{
|
|
||||||
Serial.printf("Success\n");
|
|
||||||
redLevel=100-redLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
motor[0]=new Stepper_A3967(16,17,21,19,18);
|
||||||
|
motor[1]=new Stepper_TB6612(23,32,22,14);
|
||||||
|
|
||||||
|
motor[0]->setStepType(Stepper_A3967::QUARTER_STEP);
|
||||||
|
motor[1]->setStepType(Stepper_TB6612::HALF_STEP);
|
||||||
|
|
||||||
|
motor[0]->setAccel(10,20);
|
||||||
|
motor[1]->setAccel(50,100);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
motor[0]->move(1000,5);
|
||||||
|
motor[1]->move(2000,2);
|
||||||
|
|
||||||
|
do {
|
||||||
|
for(int i=0;i<2;i++)
|
||||||
|
Serial.printf("Motor %d - %5d %5d ",i,motor[i]->stepsRemaining(),motor[i]->position());
|
||||||
|
Serial.printf("\n");
|
||||||
|
delay(500);
|
||||||
|
} while(motor[0]->stepsRemaining() || motor[1]->stepsRemaining());
|
||||||
|
|
||||||
|
motor[0]->moveTo(0,5);
|
||||||
|
motor[1]->moveTo(0,2);
|
||||||
|
|
||||||
|
do {
|
||||||
|
for(int i=0;i<2;i++)
|
||||||
|
Serial.printf("Motor %d - %5d %5d ",i,motor[i]->stepsRemaining(),motor[i]->position());
|
||||||
|
Serial.printf("\n");
|
||||||
|
delay(500);
|
||||||
|
} while(motor[0]->stepsRemaining() || motor[1]->stepsRemaining());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue