mirror of
https://github.com/apache/nuttx.git
synced 2026-05-27 11:26:12 +08:00
Cleanup interface and a4988 implementation
Change step frequency from step/ms to step/s Add DRV8825 stepper driver
This commit is contained in:
committed by
Xiang Xiao
parent
444b6d9635
commit
98b15b1409
@@ -32,3 +32,7 @@ endif()
|
|||||||
if(CONFIG_STEPPER_A4988)
|
if(CONFIG_STEPPER_A4988)
|
||||||
target_sources(drivers PRIVATE a4988.c)
|
target_sources(drivers PRIVATE a4988.c)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_STEPPER_DRV8825)
|
||||||
|
target_sources(drivers PRIVATE drv8825.c)
|
||||||
|
endif()
|
||||||
|
|||||||
@@ -81,4 +81,10 @@ config STEPPER_A4988
|
|||||||
---help---
|
---help---
|
||||||
Enables A4988 stepper driver.
|
Enables A4988 stepper driver.
|
||||||
|
|
||||||
|
config STEPPER_DRV8825
|
||||||
|
bool "DRV8825 Stepper Motor Driver"
|
||||||
|
default n
|
||||||
|
---help---
|
||||||
|
Enables DRV8825 stepper driver.
|
||||||
|
|
||||||
endif # STEPPER
|
endif # STEPPER
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ ifeq ($(CONFIG_STEPPER_A4988),y)
|
|||||||
CSRCS += a4988.c
|
CSRCS += a4988.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_STEPPER_DRV8825),y)
|
||||||
|
CSRCS += drv8825.c
|
||||||
|
endif
|
||||||
|
|
||||||
# Include motor drivers in the build
|
# Include motor drivers in the build
|
||||||
|
|
||||||
|
|||||||
+21
-16
@@ -39,7 +39,6 @@
|
|||||||
struct a4988_dev_s
|
struct a4988_dev_s
|
||||||
{
|
{
|
||||||
FAR struct a4988_ops_s *ops; /* A4988 ops */
|
FAR struct a4988_ops_s *ops; /* A4988 ops */
|
||||||
int32_t position;
|
|
||||||
uint8_t auto_idle; /* If true, go in idle mode between movement */
|
uint8_t auto_idle; /* If true, go in idle mode between movement */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -51,8 +50,7 @@ static int a4988_setup(FAR struct stepper_lowerhalf_s *dev);
|
|||||||
static int a4988_shutdown(FAR struct stepper_lowerhalf_s *dev);
|
static int a4988_shutdown(FAR struct stepper_lowerhalf_s *dev);
|
||||||
static int a4988_work(FAR struct stepper_lowerhalf_s *dev,
|
static int a4988_work(FAR struct stepper_lowerhalf_s *dev,
|
||||||
FAR struct stepper_job_s const *param);
|
FAR struct stepper_job_s const *param);
|
||||||
static int a4988_state(FAR struct stepper_lowerhalf_s *dev,
|
static int a4988_update_status(FAR struct stepper_lowerhalf_s *dev);
|
||||||
FAR struct stepper_state_s *state);
|
|
||||||
static int a4988_clear(FAR struct stepper_lowerhalf_s *dev, uint8_t fault);
|
static int a4988_clear(FAR struct stepper_lowerhalf_s *dev, uint8_t fault);
|
||||||
static int a4988_idle(FAR struct stepper_lowerhalf_s *dev, uint8_t idle);
|
static int a4988_idle(FAR struct stepper_lowerhalf_s *dev, uint8_t idle);
|
||||||
static int a4988_microstepping(FAR struct stepper_lowerhalf_s *dev,
|
static int a4988_microstepping(FAR struct stepper_lowerhalf_s *dev,
|
||||||
@@ -69,7 +67,7 @@ static const struct stepper_ops_s g_a4988_ops =
|
|||||||
a4988_setup, /* setup */
|
a4988_setup, /* setup */
|
||||||
a4988_shutdown, /* shutdown */
|
a4988_shutdown, /* shutdown */
|
||||||
a4988_work, /* work */
|
a4988_work, /* work */
|
||||||
a4988_state, /* state */
|
a4988_update_status, /* update status */
|
||||||
a4988_clear, /* clear */
|
a4988_clear, /* clear */
|
||||||
a4988_idle, /* idle */
|
a4988_idle, /* idle */
|
||||||
a4988_microstepping, /* microstepping */
|
a4988_microstepping, /* microstepping */
|
||||||
@@ -114,12 +112,15 @@ static int a4988_work(FAR struct stepper_lowerhalf_s *dev,
|
|||||||
|
|
||||||
/* Compute delay between pulse */
|
/* Compute delay between pulse */
|
||||||
|
|
||||||
delay = USEC_PER_MSEC / job->speed;
|
delay = USEC_PER_SEC / job->speed;
|
||||||
if (delay < 1)
|
if (delay < 1)
|
||||||
{
|
{
|
||||||
delay = 1;
|
delay = 1;
|
||||||
|
stpwarn("Delay is clamped to 1 us\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stpinfo("Delay is %ld us\n", delay);
|
||||||
|
|
||||||
/* Set direction */
|
/* Set direction */
|
||||||
|
|
||||||
if (job->steps > 0)
|
if (job->steps > 0)
|
||||||
@@ -139,6 +140,7 @@ static int a4988_work(FAR struct stepper_lowerhalf_s *dev,
|
|||||||
usleep(USEC_PER_MSEC);
|
usleep(USEC_PER_MSEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dev->status.state = STEPPER_STATE_RUN;
|
||||||
for (int32_t i = 0; i < count; ++i)
|
for (int32_t i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
priv->ops->step(true);
|
priv->ops->step(true);
|
||||||
@@ -147,30 +149,32 @@ static int a4988_work(FAR struct stepper_lowerhalf_s *dev,
|
|||||||
up_udelay(delay);
|
up_udelay(delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dev->status.state = STEPPER_STATE_READY;
|
||||||
|
|
||||||
if (priv->auto_idle)
|
if (priv->auto_idle)
|
||||||
{
|
{
|
||||||
priv->ops->idle(true);
|
priv->ops->idle(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update position */
|
/* Update steps done (a4988 cannot detect miss steps) */
|
||||||
|
|
||||||
priv->position += job->steps;
|
dev->status.position += job->steps;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int a4988_state(FAR struct stepper_lowerhalf_s *dev,
|
static int a4988_update_status(FAR struct stepper_lowerhalf_s *dev)
|
||||||
FAR struct stepper_state_s *state)
|
|
||||||
{
|
{
|
||||||
FAR struct a4988_dev_s *priv = (FAR struct a4988_dev_s *)dev->priv;
|
/* No state to fetch */
|
||||||
state->position = priv->position;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int a4988_clear(FAR struct stepper_lowerhalf_s *dev, uint8_t fault)
|
static int a4988_clear(FAR struct stepper_lowerhalf_s *dev, uint8_t fault)
|
||||||
{
|
{
|
||||||
return -ENOSYS;
|
/* No fault to clear ever */
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int a4988_idle(FAR struct stepper_lowerhalf_s *dev, uint8_t idle)
|
static int a4988_idle(FAR struct stepper_lowerhalf_s *dev, uint8_t idle)
|
||||||
@@ -188,11 +192,13 @@ static int a4988_idle(FAR struct stepper_lowerhalf_s *dev, uint8_t idle)
|
|||||||
if (idle == STEPPER_ENABLE_IDLE)
|
if (idle == STEPPER_ENABLE_IDLE)
|
||||||
{
|
{
|
||||||
priv->ops->idle(true);
|
priv->ops->idle(true);
|
||||||
|
dev->status.state = STEPPER_STATE_IDLE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
priv->ops->idle(false);
|
priv->ops->idle(false);
|
||||||
usleep(USEC_PER_MSEC);
|
usleep(USEC_PER_MSEC);
|
||||||
|
dev->status.state = STEPPER_STATE_READY;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -274,7 +280,6 @@ int a4988_register(FAR const char *devpath, FAR struct a4988_ops_s *ops)
|
|||||||
}
|
}
|
||||||
|
|
||||||
priv->ops = ops;
|
priv->ops = ops;
|
||||||
priv->position = 0;
|
|
||||||
|
|
||||||
lower = kmm_malloc(sizeof(struct stepper_lowerhalf_s));
|
lower = kmm_malloc(sizeof(struct stepper_lowerhalf_s));
|
||||||
if (priv == NULL)
|
if (priv == NULL)
|
||||||
@@ -285,9 +290,9 @@ int a4988_register(FAR const char *devpath, FAR struct a4988_ops_s *ops)
|
|||||||
}
|
}
|
||||||
|
|
||||||
lower->priv = priv;
|
lower->priv = priv;
|
||||||
lower->state.fault = STEPPER_FAULT_CLEAR;
|
lower->status.fault = STEPPER_FAULT_CLEAR;
|
||||||
lower->state.state = STEPPER_STATE_INIT;
|
lower->status.state = STEPPER_STATE_READY;
|
||||||
lower->state.position = 0;
|
lower->status.position = 0;
|
||||||
lower->ops = &g_a4988_ops;
|
lower->ops = &g_a4988_ops;
|
||||||
|
|
||||||
/* Initialize lower layer (only once) */
|
/* Initialize lower layer (only once) */
|
||||||
|
|||||||
@@ -0,0 +1,346 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* drivers/motor/drv8825.c
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the
|
||||||
|
* License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/kmalloc.h>
|
||||||
|
#include <nuttx/motor/drv8825.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
struct drv8825_dev_s
|
||||||
|
{
|
||||||
|
FAR struct drv8825_ops_s *ops; /* drv8825 ops */
|
||||||
|
uint8_t auto_idle; /* If true, go in idle mode between movement */
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Function Prototypes
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int drv8825_setup(FAR struct stepper_lowerhalf_s *dev);
|
||||||
|
static int drv8825_shutdown(FAR struct stepper_lowerhalf_s *dev);
|
||||||
|
static int drv8825_work(FAR struct stepper_lowerhalf_s *dev,
|
||||||
|
FAR struct stepper_job_s const *param);
|
||||||
|
static int drv8825_update_status(FAR struct stepper_lowerhalf_s *dev);
|
||||||
|
static int drv8825_clear(FAR struct stepper_lowerhalf_s *dev, uint8_t fault);
|
||||||
|
static int drv8825_idle(FAR struct stepper_lowerhalf_s *dev, uint8_t idle);
|
||||||
|
static int drv8825_microstepping(FAR struct stepper_lowerhalf_s *dev,
|
||||||
|
uint16_t resolution);
|
||||||
|
static int drv8825_ioctl(FAR struct stepper_lowerhalf_s *dev, int cmd,
|
||||||
|
unsigned long arg);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static const struct stepper_ops_s g_drv8825_ops =
|
||||||
|
{
|
||||||
|
drv8825_setup, /* setup */
|
||||||
|
drv8825_shutdown, /* shutdown */
|
||||||
|
drv8825_work, /* work */
|
||||||
|
drv8825_update_status, /* update status */
|
||||||
|
drv8825_clear, /* clear */
|
||||||
|
drv8825_idle, /* idle */
|
||||||
|
drv8825_microstepping, /* microstepping */
|
||||||
|
drv8825_ioctl /* ioctl */
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int drv8825_setup(FAR struct stepper_lowerhalf_s *dev)
|
||||||
|
{
|
||||||
|
FAR struct drv8825_dev_s *priv = (FAR struct drv8825_dev_s *)dev->priv;
|
||||||
|
priv->ops->idle(false);
|
||||||
|
priv->ops->enable(true);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int drv8825_shutdown(FAR struct stepper_lowerhalf_s *dev)
|
||||||
|
{
|
||||||
|
FAR struct drv8825_dev_s *priv = (FAR struct drv8825_dev_s *)dev->priv;
|
||||||
|
priv->ops->idle(true);
|
||||||
|
priv->ops->enable(false);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int drv8825_work(FAR struct stepper_lowerhalf_s *dev,
|
||||||
|
FAR struct stepper_job_s const *job)
|
||||||
|
{
|
||||||
|
FAR struct drv8825_dev_s *priv = (FAR struct drv8825_dev_s *)dev->priv;
|
||||||
|
int delay;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
if (priv->ops->fault())
|
||||||
|
{
|
||||||
|
/* In fault: do not proceed */
|
||||||
|
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (job->steps == 0)
|
||||||
|
{
|
||||||
|
/* Nothing to do */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute delay between pulse */
|
||||||
|
|
||||||
|
delay = USEC_PER_SEC / job->speed;
|
||||||
|
if (delay < 2)
|
||||||
|
{
|
||||||
|
delay = 2;
|
||||||
|
stpwarn("Delay is clamped to 2 us\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
stpinfo("Delay is %ld us\n", delay);
|
||||||
|
|
||||||
|
/* Set direction */
|
||||||
|
|
||||||
|
if (job->steps > 0)
|
||||||
|
{
|
||||||
|
priv->ops->direction(true);
|
||||||
|
count = job->steps;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
priv->ops->direction(false);
|
||||||
|
count = -job->steps;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->auto_idle)
|
||||||
|
{
|
||||||
|
priv->ops->idle(false);
|
||||||
|
usleep(USEC_PER_MSEC * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->status.state = STEPPER_STATE_RUN;
|
||||||
|
for (int32_t i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
priv->ops->step(true);
|
||||||
|
up_udelay(2);
|
||||||
|
priv->ops->step(false);
|
||||||
|
up_udelay(delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->status.state = STEPPER_STATE_READY;
|
||||||
|
|
||||||
|
if (priv->auto_idle)
|
||||||
|
{
|
||||||
|
priv->ops->idle(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update steps done (drv8825 cannot detect miss steps) */
|
||||||
|
|
||||||
|
dev->status.position += job->steps;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int drv8825_update_status(FAR struct stepper_lowerhalf_s *dev)
|
||||||
|
{
|
||||||
|
FAR struct drv8825_dev_s *priv = (FAR struct drv8825_dev_s *)dev->priv;
|
||||||
|
|
||||||
|
if (priv->ops->fault())
|
||||||
|
{
|
||||||
|
/* The same pin is used for overtemp and overcurrent fault.
|
||||||
|
* Since the current implementation is blocking and fetching
|
||||||
|
* is on demand (no interrupt), it is impossible to detect
|
||||||
|
* overcurrent.
|
||||||
|
*/
|
||||||
|
|
||||||
|
dev->status.fault = STEPPER_FAULT_OVERTEMP;
|
||||||
|
dev->status.state = STEPPER_STATE_FAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int drv8825_clear(FAR struct stepper_lowerhalf_s *dev, uint8_t fault)
|
||||||
|
{
|
||||||
|
/* No fault to clear ever */
|
||||||
|
|
||||||
|
dev->status.fault &= ~fault;
|
||||||
|
if (dev->status.fault == STEPPER_FAULT_CLEAR)
|
||||||
|
{
|
||||||
|
dev->status.state = STEPPER_STATE_READY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int drv8825_idle(FAR struct stepper_lowerhalf_s *dev, uint8_t idle)
|
||||||
|
{
|
||||||
|
FAR struct drv8825_dev_s *priv = (FAR struct drv8825_dev_s *)dev->priv;
|
||||||
|
|
||||||
|
if (idle == STEPPER_AUTO_IDLE)
|
||||||
|
{
|
||||||
|
priv->auto_idle = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->auto_idle = false;
|
||||||
|
|
||||||
|
if (idle == STEPPER_ENABLE_IDLE)
|
||||||
|
{
|
||||||
|
priv->ops->idle(true);
|
||||||
|
dev->status.state = STEPPER_STATE_IDLE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
priv->ops->idle(false);
|
||||||
|
usleep(USEC_PER_MSEC * 2);
|
||||||
|
dev->status.state = STEPPER_STATE_READY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int drv8825_microstepping(FAR struct stepper_lowerhalf_s *dev,
|
||||||
|
uint16_t resolution)
|
||||||
|
{
|
||||||
|
FAR struct drv8825_dev_s *priv = (FAR struct drv8825_dev_s *)dev->priv;
|
||||||
|
|
||||||
|
switch (resolution)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
priv->ops->microstepping(false, false, false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
priv->ops->microstepping(true, false, false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
priv->ops->microstepping(false, true, false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
priv->ops->microstepping(true, true, false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 16:
|
||||||
|
{
|
||||||
|
priv->ops->microstepping(false, false, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 32:
|
||||||
|
{
|
||||||
|
priv->ops->microstepping(true, true, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int drv8825_ioctl(FAR struct stepper_lowerhalf_s *dev, int cmd,
|
||||||
|
unsigned long arg)
|
||||||
|
{
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int drv8825_register(FAR const char *devpath, FAR struct drv8825_ops_s *ops)
|
||||||
|
{
|
||||||
|
FAR struct drv8825_dev_s *priv;
|
||||||
|
FAR struct stepper_lowerhalf_s *lower;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
|
||||||
|
DEBUGASSERT(ops != NULL);
|
||||||
|
|
||||||
|
/* Initialize the drv8825 dev structure */
|
||||||
|
|
||||||
|
priv = kmm_malloc(sizeof(struct drv8825_dev_s));
|
||||||
|
if (priv == NULL)
|
||||||
|
{
|
||||||
|
stperr("Failed to allocate instance\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->ops = ops;
|
||||||
|
|
||||||
|
lower = kmm_malloc(sizeof(struct stepper_lowerhalf_s));
|
||||||
|
if (priv == NULL)
|
||||||
|
{
|
||||||
|
stperr("Failed to allocate instance\n");
|
||||||
|
kmm_free(priv);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
lower->priv = priv;
|
||||||
|
lower->status.fault = STEPPER_FAULT_CLEAR;
|
||||||
|
lower->status.state = STEPPER_STATE_READY;
|
||||||
|
lower->status.position = 0;
|
||||||
|
lower->ops = &g_drv8825_ops;
|
||||||
|
|
||||||
|
/* Initialize lower layer (only once) */
|
||||||
|
|
||||||
|
priv->ops->initialize();
|
||||||
|
|
||||||
|
/* Register the character driver */
|
||||||
|
|
||||||
|
ret = stepper_register(devpath, lower);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
stperr("Failed to register driver: %d\n", ret);
|
||||||
|
kmm_free(priv);
|
||||||
|
kmm_free(lower);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
stpinfo("drv8825 registered at %s\n", devpath);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
+16
-6
@@ -168,23 +168,24 @@ static ssize_t stepper_read(FAR struct file *filep, FAR char *buffer,
|
|||||||
FAR struct inode *inode = filep->f_inode;
|
FAR struct inode *inode = filep->f_inode;
|
||||||
FAR struct stepper_upperhalf_s *stepper = inode->i_private;
|
FAR struct stepper_upperhalf_s *stepper = inode->i_private;
|
||||||
FAR struct stepper_lowerhalf_s *lower = stepper->lower;
|
FAR struct stepper_lowerhalf_s *lower = stepper->lower;
|
||||||
FAR struct stepper_state_s *state;
|
FAR struct stepper_status_s *status;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (buflen != sizeof(struct stepper_state_s))
|
if (buflen != sizeof(struct stepper_status_s))
|
||||||
{
|
{
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
state = (FAR struct stepper_state_s *)buffer;
|
status = (FAR struct stepper_status_s *)buffer;
|
||||||
ret = lower->ops->state(lower, state);
|
ret = lower->ops->update_status(lower);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
stperr("Get stepper state failed: %d\n", ret);
|
stperr("Update stepper state failed: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sizeof(struct stepper_state_s);
|
*status = lower->status;
|
||||||
|
return sizeof(struct stepper_status_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -261,6 +262,15 @@ static int stepper_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case STEPIOC_SET_CURRENT_POS:
|
||||||
|
{
|
||||||
|
lower->status.position = (int32_t)arg;
|
||||||
|
ret = 0;
|
||||||
|
stpinfo("STEPIOC_SET_CURRENT_POS: new position is %ld\n",
|
||||||
|
lower->status.position);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
ret = lower->ops->ioctl(lower, cmd, arg);
|
ret = lower->ops->ioctl(lower, cmd, arg);
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ extern "C"
|
|||||||
* Register the a4988 character device as 'devpath'
|
* Register the a4988 character device as 'devpath'
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* devpath - The full path to the driver to register. E.g., "/dev/pwrmntr0"
|
* devpath - The full path to the driver to register. E.g., "/dev/stepper0"
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* ops - operations on the concrete hardware
|
* ops - operations on the concrete hardware
|
||||||
* Zero (OK) on success; a negated errno value on failure.
|
* Zero (OK) on success; a negated errno value on failure.
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* include/nuttx/motor/drv8825.h
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the
|
||||||
|
* License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __INCLUDE_NUTTX_MOTOR_DRV8825_H
|
||||||
|
#define __INCLUDE_NUTTX_MOTOR_DRV8825_H
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/motor/stepper.h>
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#if defined(CONFIG_STEPPER_DRV8825)
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
struct drv8825_ops_s
|
||||||
|
{
|
||||||
|
/* Initialize the control, called at register step */
|
||||||
|
|
||||||
|
CODE void (*initialize)(void);
|
||||||
|
|
||||||
|
/* Control step output */
|
||||||
|
|
||||||
|
CODE void (*step)(int level);
|
||||||
|
|
||||||
|
/* Direction */
|
||||||
|
|
||||||
|
CODE void (*direction)(int level);
|
||||||
|
|
||||||
|
/* Configure microstepping */
|
||||||
|
|
||||||
|
CODE void (*microstepping)(int ms1, int ms2, int ms3);
|
||||||
|
|
||||||
|
/* Enable control */
|
||||||
|
|
||||||
|
CODE void (*enable)(int level);
|
||||||
|
|
||||||
|
/* Idle control */
|
||||||
|
|
||||||
|
CODE void (*idle)(int level);
|
||||||
|
|
||||||
|
/* Fault fetch */
|
||||||
|
|
||||||
|
CODE int (*fault)(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Function Prototypes
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define EXTERN extern "C"
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#else
|
||||||
|
#define EXTERN extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: drv8825_register
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Register the drv8825 character device as 'devpath'
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* devpath - The full path to the driver to register. E.g., "/dev/stepper0"
|
||||||
|
* Returned Value:
|
||||||
|
* ops - operations on the concrete hardware
|
||||||
|
* Zero (OK) on success; a negated errno value on failure.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int drv8825_register(FAR const char *devpath, FAR struct drv8825_ops_s *ops);
|
||||||
|
|
||||||
|
#undef EXTERN
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CONFIG_STEPPER_DRV8825 */
|
||||||
|
#endif /* __INCLUDE_NUTTX_DRIVERS_MOTOR_DRV8825_H */
|
||||||
@@ -61,8 +61,9 @@ enum stepper_state_e
|
|||||||
{
|
{
|
||||||
STEPPER_STATE_INIT = 0, /* Initial state */
|
STEPPER_STATE_INIT = 0, /* Initial state */
|
||||||
STEPPER_STATE_IDLE = 1, /* IDLE state */
|
STEPPER_STATE_IDLE = 1, /* IDLE state */
|
||||||
STEPPER_STATE_RUN = 2, /* Run state */
|
STEPPER_STATE_READY = 2, /* Ready to work */
|
||||||
STEPPER_STATE_FAULT = 3 /* Fault state */
|
STEPPER_STATE_RUN = 3, /* Run state */
|
||||||
|
STEPPER_STATE_FAULT = 4 /* Fault state */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Stepper driver fault type */
|
/* Stepper driver fault type */
|
||||||
@@ -89,13 +90,13 @@ enum stepper_idle_e
|
|||||||
STEPPER_AUTO_IDLE = 2, /* Set automaticaly IDLE when stepper not in movement */
|
STEPPER_AUTO_IDLE = 2, /* Set automaticaly IDLE when stepper not in movement */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Stepper driver state */
|
/* Stepper driver status */
|
||||||
|
|
||||||
struct stepper_state_s
|
struct stepper_status_s
|
||||||
{
|
{
|
||||||
uint8_t state; /* Stepper driver state */
|
uint8_t state; /* Stepper driver state */
|
||||||
uint8_t fault; /* Stepper driver faults */
|
uint8_t fault; /* Stepper driver faults */
|
||||||
int32_t position; /* Feedback from motor - absolute position */
|
int32_t position; /* Current absolute position */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Stepper parameters. */
|
/* Stepper parameters. */
|
||||||
@@ -103,7 +104,7 @@ struct stepper_state_s
|
|||||||
struct stepper_job_s
|
struct stepper_job_s
|
||||||
{
|
{
|
||||||
int32_t steps; /* Steps to do. Position: CW, Negative: CCW */
|
int32_t steps; /* Steps to do. Position: CW, Negative: CCW */
|
||||||
uint16_t speed; /* Stepper speed in step/ms */
|
uint32_t speed; /* Stepper speed in step/s */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Stepper operations used to call from the upper-half, generic stepper driver
|
/* Stepper operations used to call from the upper-half, generic stepper driver
|
||||||
@@ -121,15 +122,14 @@ struct stepper_ops_s
|
|||||||
|
|
||||||
CODE int (*shutdown)(FAR struct stepper_lowerhalf_s *dev);
|
CODE int (*shutdown)(FAR struct stepper_lowerhalf_s *dev);
|
||||||
|
|
||||||
/* work */
|
/* Work */
|
||||||
|
|
||||||
CODE int (*work)(FAR struct stepper_lowerhalf_s *dev,
|
CODE int (*work)(FAR struct stepper_lowerhalf_s *dev,
|
||||||
FAR struct stepper_job_s const *param);
|
FAR struct stepper_job_s const *param);
|
||||||
|
|
||||||
/* Get motor state */
|
/* Update motor/driver status */
|
||||||
|
|
||||||
CODE int (*state)(FAR struct stepper_lowerhalf_s *dev,
|
CODE int (*update_status)(FAR struct stepper_lowerhalf_s *dev);
|
||||||
FAR struct stepper_state_s *state);
|
|
||||||
|
|
||||||
/* Clear fault state */
|
/* Clear fault state */
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ struct stepper_lowerhalf_s
|
|||||||
{
|
{
|
||||||
FAR const struct stepper_ops_s *ops; /* Arch-specific operations */
|
FAR const struct stepper_ops_s *ops; /* Arch-specific operations */
|
||||||
struct stepper_job_s param; /* Motor settings */
|
struct stepper_job_s param; /* Motor settings */
|
||||||
struct stepper_state_s state; /* Motor state */
|
struct stepper_status_s status; /* Motor status */
|
||||||
FAR void *priv; /* Private data */
|
FAR void *priv; /* Private data */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,9 @@
|
|||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define STEPIOC_IDLE _STEPIOC(1)
|
#define STEPIOC_IDLE _STEPIOC(1)
|
||||||
#define STEPIOC_CLEAR_FAULT _STEPIOC(2)
|
#define STEPIOC_CLEAR_FAULT _STEPIOC(2)
|
||||||
#define STEPIOC_MICROSTEPPING _STEPIOC(3)
|
#define STEPIOC_MICROSTEPPING _STEPIOC(3)
|
||||||
|
#define STEPIOC_SET_CURRENT_POS _STEPIOC(4)
|
||||||
|
|
||||||
#endif /* __INCLUDE_NUTTX_MOTOR_STEPPER_IOCTL_H */
|
#endif /* __INCLUDE_NUTTX_MOTOR_STEPPER_IOCTL_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user