samples: servo_motor: cleanups and changes

Align the sample with changes made to other basic samples.

Move away from 'pwm-0' as a devicetree alias, requiring applications
to define a 'pwm-servo' alias. We are getting rid of the aliases that
just bounce through to node labels as soon as we can, might as well
get the applications ready now.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This commit is contained in:
Martí Bolívar 2020-05-04 13:03:34 -07:00 committed by Carles Cufí
parent a0f940ae04
commit e959386bd2
3 changed files with 68 additions and 37 deletions

View File

@ -1,20 +1,47 @@
.. _servo-motor-sample:
PWM: Servo motor
################
Servomotor
##########
Overview
********
This is a sample app which drives a servo motor using PWM.
This is a sample app which drives a servomotor using PWM.
This app is targeted for servo motor ROB-09065. With the PWM control signal, the
servo motor can rotate to any angle between 0 and 180 degrees. The corresponding
PWM pulse width is between 700 micro seconds and 2300 micro seconds. The motor
is programmed to rotate back and forth in the 180 degree range.
The sample rotates a servomotor back and forth in the 180 degree range with a
PWM control signal.
Since different servo motors may require different PWM pulse width, you may need
to modify the pulse width in the app if you are using a different servo motor.
This app is targeted for servomotor ROB-09065. The corresponding PWM pulse
widths for a 0 to 180 degree range are 700 to 2300 microseconds, respectively.
Different servomotors may require different PWM pulse widths, and you may need
to modify the source code if you are using a different servomotor.
Requirements
************
The servomotor must be connected via PWM. The PWM device must be configured
using the ``pwm-servo`` :ref:`devicetree <dt-guide>` alias. Usually you will
need to set this up via a :ref:`devicetree overlay <set-devicetree-overlays>`
like so:
.. code-block:: DTS
/ {
aliases {
pwm-servo = &foo;
};
};
Where ``foo`` is the node label of a PWM device in your system.
You will see this error if you try to build this sample for an unsupported
board:
.. code-block:: none
Unsupported board: pwm-servo devicetree alias is not defined
The sample uses PWM channel 0.
Wiring
******
@ -28,6 +55,9 @@ ground and the white wire to pad 0 on the edge connector.
Building and Running
********************
The sample has a devicetree overlay for the :ref:`bbc_microbit` which uses
``pwm0``.
This sample can be built for multiple boards, in this example we will build it
for the bbc_microbit board:

View File

@ -5,4 +5,4 @@ tests:
tags: drivers pwm
depends_on: pwm
harness: motor
filter: dt_alias_exists("pwm-0")
filter: dt_alias_exists("pwm-servo")

View File

@ -5,9 +5,7 @@
*/
/**
* @file Sample app to demonstrate PWM.
*
* This app uses PWM[0].
* @file Sample app to demonstrate PWM-based servomotor control
*/
#include <zephyr.h>
@ -15,54 +13,57 @@
#include <device.h>
#include <drivers/pwm.h>
#if !DT_NODE_HAS_STATUS(DT_ALIAS(pwm_0), okay)
#error "Choose supported board or add new board for the application"
#define PWM_NODE DT_ALIAS(pwm_servo)
#if !DT_NODE_HAS_STATUS(PWM_NODE, okay)
#error "Unsupported board: pwm-servo devicetree alias is not defined or enabled"
#define PWM_LABEL ""
#else
#define PWM_LABEL DT_LABEL(PWM_NODE)
#endif
/*
* Unlike pulse width, period is not a critical parameter for
* motor control. 20ms is commonly used.
* Unlike pulse width, the PWM period is not a critical parameter for
* motor control. 20 ms is commonly used.
*/
#define PERIOD (USEC_PER_SEC / 50U)
/* all in micro second */
#define STEPSIZE 100
#define MINPULSEWIDTH 700
#define MAXPULSEWIDTH 2300
#define PERIOD_USEC (20U * USEC_PER_MSEC)
#define STEP_USEC 100
#define MIN_PULSE_USEC 700
#define MAX_PULSE_USEC 2300
void main(void)
{
struct device *pwm_dev;
u32_t pulse_width = MINPULSEWIDTH;
struct device *pwm;
u32_t pulse_width = MIN_PULSE_USEC;
u8_t dir = 0U;
printk("PWM demo app-servo control\n");
printk("Servomotor control\n");
pwm_dev = device_get_binding(DT_LABEL(DT_ALIAS(pwm_0)));
if (!pwm_dev) {
printk("Cannot find PWM device!\n");
pwm = device_get_binding(PWM_LABEL);
if (!pwm) {
printk("Error: didn't find %s device\n", PWM_LABEL);
return;
}
while (1) {
if (pwm_pin_set_usec(pwm_dev, 0, PERIOD, pulse_width, 0)) {
printk("pwm pin set fails\n");
if (pwm_pin_set_usec(pwm, 0, PERIOD_USEC, pulse_width, 0)) {
printk("Error %d: failed to set pulse width\n", ret);
return;
}
if (dir) {
if (pulse_width <= MINPULSEWIDTH) {
if (pulse_width <= MIN_PULSE_USEC) {
dir = 0U;
pulse_width = MINPULSEWIDTH;
pulse_width = MIN_PULSE_USEC;
} else {
pulse_width -= STEPSIZE;
pulse_width -= STEP_USEC;
}
} else {
pulse_width += STEPSIZE;
pulse_width += STEP_USEC;
if (pulse_width >= MAXPULSEWIDTH) {
if (pulse_width >= MAX_PULSE_USEC) {
dir = 1U;
pulse_width = MAXPULSEWIDTH;
pulse_width = MAX_PULSE_USEC;
}
}