2019-09-07 13:03:07 +01:00
|
|
|
|
|
|
|
/*
|
2019-09-08 02:28:19 +01:00
|
|
|
xdrv_25_A4988_Stepper.ino - A4988-StepMotorDriverCircuit- support for Sonoff-Tasmota
|
2019-09-07 13:03:07 +01:00
|
|
|
|
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef USE_A4988_Stepper
|
|
|
|
#include <A4988_Stepper.h>
|
2019-09-07 20:37:01 +01:00
|
|
|
#define XDRV_25 25
|
2019-09-07 13:03:07 +01:00
|
|
|
|
2019-09-08 02:28:19 +01:00
|
|
|
enum A4988Errors { A4988_NO_ERROR, A4988_NO_JSON_COMMAND, A4988_INVALID_JSON, A4988_MOVE, A4988_ROTATE, A4988_TURN};
|
2019-09-07 13:03:07 +01:00
|
|
|
|
|
|
|
short A4988_dir_pin = pin[GPIO_MAX];
|
|
|
|
short A4988_stp_pin = pin[GPIO_MAX];
|
|
|
|
short A4988_ms1_pin = pin[GPIO_MAX];
|
|
|
|
short A4988_ms2_pin = pin[GPIO_MAX];
|
|
|
|
short A4988_ms3_pin = pin[GPIO_MAX];
|
|
|
|
short A4988_ena_pin = pin[GPIO_MAX];
|
|
|
|
int A4988_spr = 0;
|
|
|
|
float A4988_rpm = 0;
|
2019-09-07 19:38:06 +01:00
|
|
|
short A4988_mis = 0;
|
2019-09-07 13:03:07 +01:00
|
|
|
|
|
|
|
A4988_Stepper* myA4988 = nullptr;
|
|
|
|
|
|
|
|
void A4988Init(void)
|
|
|
|
{
|
|
|
|
A4988_dir_pin = pin[GPIO_A4988_DIR];
|
|
|
|
A4988_stp_pin = pin[GPIO_A4988_STP];
|
|
|
|
A4988_ena_pin = pin[GPIO_A4988_ENA];
|
|
|
|
A4988_ms1_pin = pin[GPIO_A4988_MS1];
|
|
|
|
A4988_ms2_pin = pin[GPIO_A4988_MS2];
|
|
|
|
A4988_ms3_pin = pin[GPIO_A4988_MS3];
|
|
|
|
A4988_spr = 200;
|
|
|
|
A4988_rpm = 30;
|
2019-09-07 13:09:44 +01:00
|
|
|
A4988_mis = 1;
|
2019-09-07 13:03:07 +01:00
|
|
|
|
|
|
|
myA4988 = new A4988_Stepper( A4988_spr
|
|
|
|
, A4988_rpm
|
2019-09-07 13:09:44 +01:00
|
|
|
, A4988_mis
|
2019-09-07 13:03:07 +01:00
|
|
|
, A4988_dir_pin
|
|
|
|
, A4988_stp_pin
|
|
|
|
, A4988_ena_pin
|
|
|
|
, A4988_ms1_pin
|
|
|
|
, A4988_ms2_pin
|
|
|
|
, A4988_ms3_pin );
|
|
|
|
}
|
|
|
|
|
2019-09-08 02:28:19 +01:00
|
|
|
const char kA4988Commands[] PROGMEM = "|"
|
|
|
|
"MOTOR";
|
2019-09-07 13:03:07 +01:00
|
|
|
|
2019-09-07 20:37:01 +01:00
|
|
|
void (* const A4988Command[])(void) PROGMEM = { &CmndMOTOR};
|
2019-09-07 13:03:07 +01:00
|
|
|
|
|
|
|
uint32_t MOTORCmndJson(void)
|
|
|
|
{
|
2019-09-08 02:28:19 +01:00
|
|
|
// MOTOR {"doMove":200}
|
|
|
|
// MOTOR {"doRotate":360}
|
|
|
|
// MOTOR {"doTurn":1.0}
|
|
|
|
uint32_t returnValue =A4988_NO_JSON_COMMAND;
|
|
|
|
|
|
|
|
char parm_uc[12];
|
2019-09-07 13:03:07 +01:00
|
|
|
char dataBufUc[XdrvMailbox.data_len];
|
|
|
|
UpperCase(dataBufUc, XdrvMailbox.data);
|
|
|
|
RemoveSpace(dataBufUc);
|
2019-09-08 02:28:19 +01:00
|
|
|
if (strlen(dataBufUc) < 8) { returnValue =A4988_INVALID_JSON; }
|
2019-09-07 13:03:07 +01:00
|
|
|
|
2019-09-07 19:38:06 +01:00
|
|
|
DynamicJsonBuffer jsonBuf;
|
|
|
|
JsonObject &json = jsonBuf.parseObject(dataBufUc);
|
2019-09-08 02:28:19 +01:00
|
|
|
if (json.success()) {
|
|
|
|
UpperCase_P(parm_uc, PSTR(D_JSON_MOTOR_SPR));
|
|
|
|
if (json.containsKey(parm_uc)){
|
|
|
|
int howManySteps =strtoul(json[parm_uc],nullptr,10);
|
|
|
|
myA4988->setSPR(howManySteps);
|
|
|
|
returnValue = A4988_NO_ERROR;
|
|
|
|
}
|
|
|
|
UpperCase_P(parm_uc, PSTR(D_JSON_MOTOR_RPM));
|
|
|
|
if (json.containsKey(parm_uc)){
|
|
|
|
int howManyRounds =strtoul(json[parm_uc],nullptr,10);
|
|
|
|
myA4988->setRPM(howManyRounds);
|
|
|
|
returnValue = A4988_NO_ERROR;
|
|
|
|
}
|
|
|
|
UpperCase_P(parm_uc, PSTR(D_JSON_MOTOR_MIS));
|
|
|
|
if (json.containsKey(parm_uc)){
|
|
|
|
short oneToSixteen =strtoul(json[parm_uc],nullptr,10);
|
|
|
|
myA4988->setMIS(oneToSixteen);
|
|
|
|
returnValue = A4988_NO_ERROR;
|
|
|
|
}
|
|
|
|
UpperCase_P(parm_uc, PSTR(D_JSON_MOTOR_MOVE));
|
|
|
|
if (json.containsKey(parm_uc)){
|
|
|
|
long stepsPlease = strtoul(json[parm_uc],nullptr,10);
|
|
|
|
myA4988->doMove(stepsPlease);
|
|
|
|
returnValue = A4988_MOVE;
|
|
|
|
}
|
|
|
|
UpperCase_P(parm_uc, PSTR(D_JSON_MOTOR_ROTATE));
|
|
|
|
if (json.containsKey(parm_uc)){
|
|
|
|
long degrsPlease = strtoul(json[parm_uc],nullptr,10);
|
|
|
|
myA4988->doRotate(degrsPlease);
|
|
|
|
returnValue = A4988_ROTATE;
|
|
|
|
}
|
|
|
|
UpperCase_P(parm_uc, PSTR(D_JSON_MOTOR_TURN));
|
|
|
|
if (json.containsKey(parm_uc)){
|
|
|
|
float turnsPlease = strtod(json[parm_uc],nullptr);
|
|
|
|
myA4988->doTurn(turnsPlease);
|
|
|
|
returnValue = A4988_TURN;
|
|
|
|
}
|
|
|
|
} else returnValue =A4988_INVALID_JSON;
|
|
|
|
return returnValue;
|
2019-09-07 13:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CmndMOTOR(void){
|
2019-09-07 19:38:06 +01:00
|
|
|
uint32_t error;
|
2019-09-07 13:03:07 +01:00
|
|
|
if (XdrvMailbox.data_len) {
|
2019-09-08 02:28:19 +01:00
|
|
|
if (strstr(XdrvMailbox.data, "}") == nullptr) {
|
2019-09-07 13:03:07 +01:00
|
|
|
error = A4988_NO_JSON_COMMAND;
|
|
|
|
} else {
|
|
|
|
error = MOTORCmndJson();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
A4988CmndResponse(error);
|
|
|
|
}
|
|
|
|
|
|
|
|
void A4988CmndResponse(uint32_t error){
|
2019-09-07 19:38:06 +01:00
|
|
|
switch (error) {
|
|
|
|
case A4988_NO_JSON_COMMAND:
|
2019-09-08 16:30:17 +01:00
|
|
|
ResponseCmndChar(PSTR("No command!"));
|
2019-09-08 02:28:19 +01:00
|
|
|
break;
|
|
|
|
case A4988_MOVE:
|
|
|
|
ResponseCmndChar(PSTR("Stepping!"));
|
|
|
|
break;
|
|
|
|
case A4988_ROTATE:
|
|
|
|
ResponseCmndChar(PSTR("Rotating!"));
|
|
|
|
break;
|
|
|
|
case A4988_TURN:
|
|
|
|
ResponseCmndChar(PSTR("Turning!"));
|
2019-09-07 19:38:06 +01:00
|
|
|
break;
|
|
|
|
default: // A4988_NO_ERROR
|
|
|
|
ResponseCmndDone();
|
|
|
|
}
|
2019-09-07 13:03:07 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*********************************************************************************************\
|
|
|
|
* Interface
|
|
|
|
\*********************************************************************************************/
|
2019-09-07 20:37:01 +01:00
|
|
|
bool Xdrv25(uint8_t function)
|
2019-09-07 13:03:07 +01:00
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
if ((pin[GPIO_A4988_DIR] < 99) && (pin[GPIO_A4988_STP] < 99)) {
|
|
|
|
switch (function) {
|
|
|
|
case FUNC_INIT:
|
|
|
|
A4988Init();
|
|
|
|
break;
|
|
|
|
case FUNC_COMMAND:
|
|
|
|
result = DecodeCommand(kA4988Commands, A4988Command);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|