2019-09-07 13:03:07 +01:00
/*
xsns_22_sr04 . ino - SR04 ultrasonic sensor support for Sonoff - Tasmota
Copyright ( C ) 2019 Nuno Ferreira and Theo Arends
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>
/*********************************************************************************************\
* Stepper mötör on driver A4988
*
* - https : //www.dfrobot.com/wiki/index.php/Weather-proof_Ultrasonic_Sensor_SKU_:_SEN0207
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define XDRV_98 98
enum A4988Errors { A4988_NO_ERROR , A4988_NO_JSON_COMMAND , A4988_INVALID_JSON } ;
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 ) ;
A4988_spr = myA4988 - > getSPR ( ) ;
A4988_rpm = myA4988 - > getRPM ( ) ;
2019-09-07 13:09:44 +01:00
A4988_mis = myA4988 - > getMIS ( ) ;
2019-09-07 13:03:07 +01:00
if ( ( A4988_ms1_pin < 99 ) & & ( A4988_ms2_pin < 99 ) & & ( A4988_ms3_pin < 99 ) & & ( A4988_ena_pin < 99 ) ) {
2019-09-07 19:38:06 +01:00
AddLog_P2 ( LOG_LEVEL_INFO , PSTR ( " STP: A4988-Driver initialized (%dSPR, %dRPM,%dMIS). Pins: Dir[%d] Stp[%d] Ena[%d] MS1[%d] MS2[%d] MS3[%d] " ) , A4988_spr , A4988_rpm , A4988_mis , A4988_dir_pin , A4988_stp_pin , A4988_ena_pin , A4988_ms1_pin , A4988_ms2_pin , A4988_ms3_pin ) ;
2019-09-07 13:03:07 +01:00
} else {
if ( ( A4988_ena_pin < 99 ) ) {
2019-09-07 19:38:06 +01:00
AddLog_P2 ( LOG_LEVEL_INFO , PSTR ( " STP: A4988-Driver initialized (%dSPR, %dRPM,%dMIS). Pins: Dir[%d] Stp[%d] Ena[%d] MicroStepping hardwired " ) , A4988_spr , A4988_rpm , A4988_mis , A4988_dir_pin , A4988_stp_pin , A4988_ena_pin ) ;
2019-09-07 13:03:07 +01:00
} else {
2019-09-07 19:38:06 +01:00
AddLog_P2 ( LOG_LEVEL_INFO , PSTR ( " STP: A4988-Driver initialized (%dSPR, %dRPM,%dMIS). Pins: Dir[%d] Stp[%d] motor permanently on, MicroStepping hardwired " ) , A4988_spr , A4988_rpm , A4988_mis , A4988_dir_pin , A4988_stp_pin , A4988_ena_pin ) ;
2019-09-07 13:03:07 +01:00
}
}
}
const char kA4988Commands [ ] PROGMEM = " MOTOR| "
" doMove|doRotate|doTurn|setSPR|setRPM|setMIC|getSPR|getRPM|getMIC|doVader " ;
2019-09-07 19:38:06 +01:00
void ( * const A4988Command [ ] ) ( void ) PROGMEM = { & CmndMOTOR , & CmndDoMove , & CmndDoRotate , & CmndDoTurn , & CmndSetSPR , & CmndSetRPM , & CmndSetMIS , & CmndGetSPR , & CmndGetRPM , & CmndGetMIS , & CmndDoVader } ;
2019-09-07 13:03:07 +01:00
uint32_t MOTORCmndJson ( void )
{
2019-09-07 19:38:06 +01:00
// MOTOR {"Command":"doMove","Value":200}
// MOTOR {"Command":"doRotate","Value":360}
// MOTOR {"Command":"doTurn","Value":1.0}
2019-09-07 13:03:07 +01:00
char dataBufUc [ XdrvMailbox . data_len ] ;
UpperCase ( dataBufUc , XdrvMailbox . data ) ;
RemoveSpace ( dataBufUc ) ;
2019-09-07 19:38:06 +01:00
if ( strlen ( dataBufUc ) < 8 ) { return 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 ) ;
if ( ! json . success ( ) ) { return A4988_INVALID_JSON ; }
2019-09-07 13:03:07 +01:00
2019-09-07 19:38:06 +01:00
if ( json . containsKey ( D_JSON_MOTOR_MOVE ) ) {
long stepsPlease = 50 ;
stepsPlease = strtoul ( json [ D_JSON_MOTOR_MOVE ] , nullptr , 10 ) ;
AddLog_P2 ( LOG_LEVEL_INFO , PSTR ( " A4988: Moving %d steps " ) , stepsPlease ) ;
myA4988 - > doMove ( stepsPlease ) ;
} else if ( json . containsKey ( D_JSON_MOTOR_ROTATE ) ) {
long degrsPlease = 45 ;
degrsPlease = strtoul ( json [ D_JSON_MOTOR_ROTATE ] , nullptr , 10 ) ;
AddLog_P2 ( LOG_LEVEL_INFO , PSTR ( " A4988: Rotating %d degrs " ) , degrsPlease ) ;
myA4988 - > doRotate ( degrsPlease ) ;
} else if ( json . containsKey ( D_JSON_MOTOR_TURN ) ) {
float turnsPlease = 0.25 ;
turnsPlease = strtod ( json [ D_JSON_MOTOR_TURN ] , nullptr ) ;
AddLog_P2 ( LOG_LEVEL_DEBUG , PSTR ( " A4988: Turning %d times " ) , turnsPlease ) ;
myA4988 - > doTurn ( turnsPlease ) ;
} else return A4988_NO_JSON_COMMAND ;
return A4988_NO_ERROR ;
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 ) {
if ( strstr ( XdrvMailbox . data , " { " ) = = nullptr ) {
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 :
ResponseCmndChar ( D_JSON_INVALID_JSON ) ;
break ;
default : // A4988_NO_ERROR
ResponseCmndDone ( ) ;
}
2019-09-07 13:03:07 +01:00
}
void CmndGetSPR ( void ) {
AddLog_P2 ( LOG_LEVEL_INFO , PSTR ( " A4988: SPR = %d steps " ) , myA4988 - > getSPR ( ) ) ;
}
void CmndGetRPM ( void ) {
AddLog_P2 ( LOG_LEVEL_INFO , PSTR ( " A4988: RPM = %d rounds " ) , myA4988 - > getRPM ( ) ) ;
}
2019-09-07 19:38:06 +01:00
void CmndGetMIS ( void ) {
AddLog_P2 ( LOG_LEVEL_INFO , PSTR ( " A4988: MIS = %d steps " ) , myA4988 - > getMIS ( ) ) ;
2019-09-07 13:03:07 +01:00
}
void CmndDoMove ( void )
{
if ( XdrvMailbox . data_len > 0 ) {
long stepsPlease = 1 ;
stepsPlease = strtoul ( XdrvMailbox . data , nullptr , 10 ) ;
AddLog_P2 ( LOG_LEVEL_INFO , PSTR ( " A4988: Moving %d steps " ) , stepsPlease ) ;
myA4988 - > doMove ( stepsPlease ) ;
} else {
AddLog_P2 ( LOG_LEVEL_INFO , PSTR ( " A4988: Moving 25 steps " ) ) ;
myA4988 - > doMove ( 25 ) ;
}
ResponseCmndDone ( ) ;
}
void CmndDoRotate ( void )
{
if ( XdrvMailbox . data_len > 0 ) {
long degrsPlease = 1 ;
degrsPlease = strtoul ( XdrvMailbox . data , nullptr , 10 ) ;
AddLog_P2 ( LOG_LEVEL_INFO , PSTR ( " A4988: Rotating %d degrs " ) , degrsPlease ) ;
myA4988 - > doRotate ( degrsPlease ) ;
} else {
AddLog_P2 ( LOG_LEVEL_INFO , PSTR ( " A4988: Moving 45 degrs " ) ) ;
myA4988 - > doRotate ( 45 ) ;
}
ResponseCmndDone ( ) ;
}
void CmndDoTurn ( void )
{
if ( XdrvMailbox . data_len > 0 ) {
float turnsPlease = 0 ;
turnsPlease = strtod ( XdrvMailbox . data , nullptr ) ;
AddLog_P2 ( LOG_LEVEL_DEBUG , PSTR ( " A4988: Turning %d times " ) , turnsPlease ) ;
myA4988 - > doTurn ( turnsPlease ) ;
} else {
AddLog_P2 ( LOG_LEVEL_DEBUG , PSTR ( " A4988: Turning 0.25 times " ) ) ;
myA4988 - > doRotate ( 0.25 ) ;
}
ResponseCmndDone ( ) ;
}
void CmndSetRPM ( void )
{
short rpmPlease = 60 ;
if ( XdrvMailbox . data_len > 0 ) {
rpmPlease = strtoul ( XdrvMailbox . data , nullptr , 10 ) ;
}
AddLog_P2 ( LOG_LEVEL_DEBUG , PSTR ( " A4988: RPM set to %d " ) , rpmPlease ) ;
myA4988 - > setRPM ( rpmPlease ) ;
ResponseCmndDone ( ) ;
}
void CmndSetSPR ( void )
{
int sprPlease = 200 ;
if ( XdrvMailbox . data_len > 0 ) {
sprPlease = strtoul ( XdrvMailbox . data , nullptr , 10 ) ;
}
AddLog_P2 ( LOG_LEVEL_DEBUG , PSTR ( " A4988: SPR set to %d " ) , sprPlease ) ;
myA4988 - > setSPR ( sprPlease ) ;
ResponseCmndDone ( ) ;
}
2019-09-07 13:09:44 +01:00
void CmndSetMIS ( void )
2019-09-07 13:03:07 +01:00
{
if ( ( pin [ GPIO_A4988_MS1 ] < 99 ) & & ( pin [ GPIO_A4988_MS2 ] < 99 ) & & ( pin [ GPIO_A4988_MS3 ] < 99 ) ) {
2019-09-07 19:38:06 +01:00
short misPlease = 1 ;
2019-09-07 13:03:07 +01:00
if ( XdrvMailbox . data_len > 0 ) {
2019-09-07 19:38:06 +01:00
misPlease = strtoul ( XdrvMailbox . data , nullptr , 10 ) ;
AddLog_P2 ( LOG_LEVEL_DEBUG , PSTR ( " A4988: Microsteps set to %d " ) , misPlease ) ;
myA4988 - > setMIS ( misPlease ) ;
2019-09-07 13:03:07 +01:00
}
} else {
AddLog_P2 ( LOG_LEVEL_DEBUG , PSTR ( " A4988: Microsteps constant = 1. You'll have to define GPIO's for MS1-MS3 and connect them to A4988 or hardwire A4988 itself " ) ) ;
}
ResponseCmndDone ( ) ;
}
void CmndDoVader ( void ) {
myA4988 - > enable ( ) ;
myA4988 - > setRPM ( 25 ) ; myA4988 - > doMove ( 30 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 25 ) ; myA4988 - > doMove ( - 30 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 25 ) ; myA4988 - > doMove ( 30 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 20 ) ; myA4988 - > doMove ( - 25 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 30 ) ; myA4988 - > doMove ( 20 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 25 ) ; myA4988 - > doMove ( 50 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 20 ) ; myA4988 - > doMove ( - 25 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 30 ) ; myA4988 - > doMove ( 20 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 25 ) ; myA4988 - > doMove ( - 50 ) ; delay ( 5 ) ; //
myA4988 - > setRPM ( 38 ) ; myA4988 - > doMove ( 31 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 38 ) ; myA4988 - > doMove ( - 31 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 38 ) ; myA4988 - > doMove ( 31 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 38 ) ; myA4988 - > doMove ( - 31 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 41 ) ; myA4988 - > doMove ( 21 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 30 ) ; myA4988 - > doMove ( - 21 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 25 ) ; myA4988 - > doMove ( 30 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 20 ) ; myA4988 - > doMove ( - 25 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 30 ) ; myA4988 - > doMove ( 20 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 25 ) ; myA4988 - > doMove ( - 50 ) ; delay ( 5 ) ; //
myA4988 - > setRPM ( 50 ) ; myA4988 - > doMove ( 40 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 25 ) ; myA4988 - > doMove ( - 20 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 25 ) ; myA4988 - > doMove ( 15 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 50 ) ; myA4988 - > doMove ( - 40 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 48 ) ; myA4988 - > doMove ( 35 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 45 ) ; myA4988 - > doMove ( - 25 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 41 ) ; myA4988 - > doMove ( 25 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 38 ) ; myA4988 - > doMove ( - 26 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 41 ) ; myA4988 - > doMove ( 25 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 25 ) ; myA4988 - > doMove ( 25 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 41 ) ; myA4988 - > doMove ( - 35 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 38 ) ; myA4988 - > doMove ( 25 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 36 ) ; myA4988 - > doMove ( - 25 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 33 ) ; myA4988 - > doMove ( 25 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 30 ) ; myA4988 - > doMove ( - 27 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 33 ) ; myA4988 - > doMove ( 25 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 33 ) ; myA4988 - > doMove ( 25 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 38 ) ; myA4988 - > doMove ( - 30 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 18 ) ; myA4988 - > doMove ( 10 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 18 ) ; myA4988 - > doMove ( - 10 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 25 ) ; myA4988 - > doMove ( 20 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 20 ) ; myA4988 - > doMove ( - 25 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 30 ) ; myA4988 - > doMove ( 20 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 25 ) ; myA4988 - > doMove ( - 50 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 20 ) ; myA4988 - > doMove ( 25 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 30 ) ; myA4988 - > doMove ( - 20 ) ; delay ( 5 ) ;
myA4988 - > setRPM ( 25 ) ; myA4988 - > doMove ( 50 ) ; delay ( 5 ) ;
myA4988 - > disable ( ) ;
AddLog_P2 ( LOG_LEVEL_INFO , PSTR ( " Stepper: may the force be with you! " ) ) ;
ResponseCmndDone ( ) ;
}
/*********************************************************************************************\
* Interface
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool Xdrv98 ( uint8_t function )
{
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