microbit: added Servo API to MicroBitPin
* Added a number of #defines to MicroBitPin.h which ultimately lead to retabulation of the #defines * Added two new instance methods: - setServoValue() which sets the default servo period (20ms) and accepts a value in the range 0 - 180, which maps to a duty cycle between 5% and 10% respectively. This mapping is also configurable. - setServoPulseUs() which accepts a pulse width in microseconds, and maps it onto the PWM channel.
This commit is contained in:
parent
2650aaa569
commit
983e9e1ad3
2 changed files with 147 additions and 38 deletions
|
@ -3,36 +3,40 @@
|
|||
|
||||
#include "mbed.h"
|
||||
#include "MicroBitComponent.h"
|
||||
// Status Field flags...
|
||||
#define IO_STATUS_DIGITAL_IN 0x01 // Pin is configured as a digital input, with no pull up.
|
||||
#define IO_STATUS_DIGITAL_OUT 0x02 // Pin is configured as a digital output
|
||||
#define IO_STATUS_ANALOG_IN 0x04 // Pin is Analog in
|
||||
#define IO_STATUS_ANALOG_OUT 0x08 // Pin is Analog out
|
||||
#define IO_STATUS_TOUCH_IN 0x10 // Pin is a makey-makey style touch sensor
|
||||
#define IO_STATUS_EVENTBUS_ENABLED 0x80 // Pin is will generate events on change
|
||||
// Status Field flags...
|
||||
#define IO_STATUS_DIGITAL_IN 0x01 // Pin is configured as a digital input, with no pull up.
|
||||
#define IO_STATUS_DIGITAL_OUT 0x02 // Pin is configured as a digital output
|
||||
#define IO_STATUS_ANALOG_IN 0x04 // Pin is Analog in
|
||||
#define IO_STATUS_ANALOG_OUT 0x08 // Pin is Analog out
|
||||
#define IO_STATUS_TOUCH_IN 0x10 // Pin is a makey-makey style touch sensor
|
||||
#define IO_STATUS_EVENTBUS_ENABLED 0x80 // Pin is will generate events on change
|
||||
|
||||
//#defines for each edge connector pin
|
||||
#define MICROBIT_PIN_P0 P0_3 //P0 is the left most pad (ANALOG/DIGITAL) used to be P0_3 on green board
|
||||
#define MICROBIT_PIN_P1 P0_2 //P1 is the middle pad (ANALOG/DIGITAL)
|
||||
#define MICROBIT_PIN_P2 P0_1 //P2 is the right most pad (ANALOG/DIGITAL) used to be P0_1 on green board
|
||||
#define MICROBIT_PIN_P3 P0_4 //COL1 (ANALOG/DIGITAL)
|
||||
#define MICROBIT_PIN_P4 P0_17 //BTN_A
|
||||
#define MICROBIT_PIN_P5 P0_5 //COL2 (ANALOG/DIGITAL)
|
||||
#define MICROBIT_PIN_P6 P0_12 //COL9
|
||||
#define MICROBIT_PIN_P7 P0_11 //COL8
|
||||
#define MICROBIT_PIN_P8 P0_18 //PIN 18
|
||||
#define MICROBIT_PIN_P9 P0_10 //COL7
|
||||
#define MICROBIT_PIN_P10 P0_6 //COL3 (ANALOG/DIGITAL)
|
||||
#define MICROBIT_PIN_P11 P0_26 //BTN_B
|
||||
#define MICROBIT_PIN_P12 P0_20 //PIN 20
|
||||
#define MICROBIT_PIN_P13 P0_23 //SCK
|
||||
#define MICROBIT_PIN_P14 P0_22 //MISO
|
||||
#define MICROBIT_PIN_P15 P0_21 //MOSI
|
||||
#define MICROBIT_PIN_P16 P0_16 //PIN 16
|
||||
#define MICROBIT_PIN_P19 P0_0 //SCL
|
||||
#define MICROBIT_PIN_P20 P0_30 //SDA
|
||||
#define MICROBIT_PIN_P0 P0_3 //P0 is the left most pad (ANALOG/DIGITAL) used to be P0_3 on green board
|
||||
#define MICROBIT_PIN_P1 P0_2 //P1 is the middle pad (ANALOG/DIGITAL)
|
||||
#define MICROBIT_PIN_P2 P0_1 //P2 is the right most pad (ANALOG/DIGITAL) used to be P0_1 on green board
|
||||
#define MICROBIT_PIN_P3 P0_4 //COL1 (ANALOG/DIGITAL)
|
||||
#define MICROBIT_PIN_P4 P0_17 //BTN_A
|
||||
#define MICROBIT_PIN_P5 P0_5 //COL2 (ANALOG/DIGITAL)
|
||||
#define MICROBIT_PIN_P6 P0_12 //COL9
|
||||
#define MICROBIT_PIN_P7 P0_11 //COL8
|
||||
#define MICROBIT_PIN_P8 P0_18 //PIN 18
|
||||
#define MICROBIT_PIN_P9 P0_10 //COL7
|
||||
#define MICROBIT_PIN_P10 P0_6 //COL3 (ANALOG/DIGITAL)
|
||||
#define MICROBIT_PIN_P11 P0_26 //BTN_B
|
||||
#define MICROBIT_PIN_P12 P0_20 //PIN 20
|
||||
#define MICROBIT_PIN_P13 P0_23 //SCK
|
||||
#define MICROBIT_PIN_P14 P0_22 //MISO
|
||||
#define MICROBIT_PIN_P15 P0_21 //MOSI
|
||||
#define MICROBIT_PIN_P16 P0_16 //PIN 16
|
||||
#define MICROBIT_PIN_P19 P0_0 //SCL
|
||||
#define MICROBIT_PIN_P20 P0_30 //SDA
|
||||
|
||||
#define MICROBIT_PIN_MAX_OUTPUT 1023
|
||||
#define MICROBIT_PIN_MAX_OUTPUT 1023
|
||||
|
||||
#define MICROBIT_PIN_MAX_SERVO_RANGE 180
|
||||
#define MICROBIT_PIN_DEFAULT_SERVO_RANGE 1000
|
||||
#define MICROBIT_PIN_DEFAULT_SERVO_CENTER MICROBIT_PIN_DEFAULT_SERVO_RANGE + MICROBIT_PIN_DEFAULT_SERVO_RANGE/2
|
||||
|
||||
|
||||
/**
|
||||
|
@ -69,6 +73,12 @@ class MicroBitPin : public MicroBitComponent
|
|||
*/
|
||||
void disconnect();
|
||||
|
||||
/**
|
||||
* Performs a check to ensure that the current Pin is in control of a
|
||||
* DynamicPwm instance, and if it's not, allocates a new DynamicPwm instance.
|
||||
*/
|
||||
int obtainAnalogChannel();
|
||||
|
||||
public:
|
||||
PinName name; // mBed pin name of this pin.
|
||||
|
||||
|
@ -120,6 +130,21 @@ class MicroBitPin : public MicroBitComponent
|
|||
*/
|
||||
int setAnalogValue(int value);
|
||||
|
||||
/**
|
||||
* Configures this IO pin as an analog/pwm output if it isn't already, configures the period to be 20ms,
|
||||
* and sets the duty cycle between 0.05 and 0.1 (i.e. 5% or 10%) based on the value given to this method.
|
||||
*
|
||||
* A value of 180 sets the duty cycle to be 10%, and a value of 0 sets the duty cycle to be 5% by default.
|
||||
*
|
||||
* This range can be modified to fine tune, and also tolerate different servos.
|
||||
*
|
||||
* @param value the level to set on the output pin, in the range 0 - 180
|
||||
* @param range which gives the span of possible values the i.e. lower and upper bounds center ± range/2 (Defaults to: MICROBIT_PIN_DEFAULT_SERVO_RANGE)
|
||||
* @param center the center point from which to calculate the lower and upper bounds (Defaults to: MICROBIT_PIN_DEFAULT_SERVO_CENTER)
|
||||
* @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if value is out of range, or MICROBIT_NOT_SUPPORTED
|
||||
* if the given pin does not have analog capability.
|
||||
*/
|
||||
int setServoValue(int value, int range = MICROBIT_PIN_DEFAULT_SERVO_RANGE, int center = MICROBIT_PIN_DEFAULT_SERVO_CENTER);
|
||||
|
||||
/**
|
||||
* Configures this IO pin as an analogue input (if necessary and possible).
|
||||
|
@ -172,6 +197,16 @@ class MicroBitPin : public MicroBitComponent
|
|||
*/
|
||||
int isTouched();
|
||||
|
||||
/**
|
||||
* Configures this IO pin as an analog/pwm output if it isn't already, configures the period to be 20ms,
|
||||
* and sets the pulse width, based on the value it is given
|
||||
*
|
||||
* @param pulseWidth the desired pulse width in microseconds.
|
||||
* @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if value is out of range, or MICROBIT_NOT_SUPPORTED
|
||||
* if the given pin does not have analog capability.
|
||||
*/
|
||||
int setServoPulseUs(int pulseWidth);
|
||||
|
||||
/**
|
||||
* Configures the PWM period of the analog output to the given value.
|
||||
*
|
||||
|
|
|
@ -120,9 +120,21 @@ int MicroBitPin::getDigitalValue()
|
|||
return ((DigitalIn *)pin)->read();
|
||||
}
|
||||
|
||||
int MicroBitPin::obtainAnalogChannel()
|
||||
{
|
||||
// Move into an analogue input state if necessary, if we are no longer the focus of a DynamicPWM instance, allocate ourselves again!
|
||||
if (!(status & IO_STATUS_ANALOG_OUT) || !(((DynamicPwm *)pin)->getPinName() == name)){
|
||||
disconnect();
|
||||
pin = (void *)DynamicPwm::allocate(name);
|
||||
status |= IO_STATUS_ANALOG_OUT;
|
||||
}
|
||||
|
||||
return MICROBIT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures this IO pin as an analog/pwm output, and change the output value to the given level.
|
||||
* @param value the level to set on the output pin, in the range 0 - 1024
|
||||
* @param value the level to set on the output pin, in the range 0 - 1023
|
||||
* @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if value is out of range, or MICROBIT_NOT_SUPPORTED
|
||||
* if the given pin does not have analog capability.
|
||||
*/
|
||||
|
@ -132,26 +144,57 @@ int MicroBitPin::setAnalogValue(int value)
|
|||
if(!(PIN_CAPABILITY_ANALOG & capability))
|
||||
return MICROBIT_NOT_SUPPORTED;
|
||||
|
||||
//sanitise the brightness level
|
||||
//sanitise the level value
|
||||
if(value < 0 || value > MICROBIT_PIN_MAX_OUTPUT)
|
||||
return MICROBIT_INVALID_PARAMETER;
|
||||
|
||||
float level = (float)value / float(MICROBIT_PIN_MAX_OUTPUT);
|
||||
|
||||
// Move into an analogue input state if necessary, if we are no longer the focus of a DynamicPWM instance, allocate ourselves again!
|
||||
if (!(status & IO_STATUS_ANALOG_OUT) || !(((DynamicPwm *)pin)->getPinName() == name)){
|
||||
disconnect();
|
||||
pin = (void *)DynamicPwm::allocate(name);
|
||||
status |= IO_STATUS_ANALOG_OUT;
|
||||
}
|
||||
|
||||
//perform a write with an extra check! :)
|
||||
if(((DynamicPwm *)pin)->getPinName() == name)
|
||||
//obtain use of the DynamicPwm instance, if it has changed / configure if we do not have one
|
||||
if(obtainAnalogChannel() == MICROBIT_OK)
|
||||
return ((DynamicPwm *)pin)->write(level);
|
||||
|
||||
return MICROBIT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures this IO pin as an analog/pwm output if it isn't already, configures the period to be 20ms,
|
||||
* and sets the duty cycle between 0.05 and 0.1 (i.e. 5% or 10%) based on the value given to this method.
|
||||
*
|
||||
* A value of 180 sets the duty cycle to be 10%, and a value of 0 sets the duty cycle to be 5% by default.
|
||||
*
|
||||
* This range can be modified to fine tune, and also tolerate different servos.
|
||||
*
|
||||
* @param value the level to set on the output pin, in the range 0 - 180
|
||||
* @param range which gives the span of possible values the i.e. lower and upper bounds center ± range/2 (Defaults to: MICROBIT_PIN_DEFAULT_SERVO_RANGE)
|
||||
* @param center the center point from which to calculate the lower and upper bounds (Defaults to: MICROBIT_PIN_DEFAULT_SERVO_CENTER)
|
||||
* @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if value is out of range, or MICROBIT_NOT_SUPPORTED
|
||||
* if the given pin does not have analog capability.
|
||||
*/
|
||||
int MicroBitPin::setServoValue(int value, int range, int center)
|
||||
{
|
||||
//check if this pin has an analogue mode...
|
||||
if(!(PIN_CAPABILITY_ANALOG & capability))
|
||||
return MICROBIT_NOT_SUPPORTED;
|
||||
|
||||
//sanitise the servo level
|
||||
if(value < 0 || range < 1 || center < 1)
|
||||
return MICROBIT_INVALID_PARAMETER;
|
||||
|
||||
//clip - just in case
|
||||
if(value > MICROBIT_PIN_MAX_SERVO_RANGE)
|
||||
value = MICROBIT_PIN_MAX_SERVO_RANGE;
|
||||
|
||||
//calculate the lower bound based on the midpoint
|
||||
int lower = (center - (range / 2)) * 1000;
|
||||
|
||||
value = value * 1000;
|
||||
|
||||
//add the percentage of the range based on the value between 0 and 180
|
||||
int scaled = lower + (range * (value / MICROBIT_PIN_MAX_SERVO_RANGE));
|
||||
|
||||
return setServoPulseUs(scaled / 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures this IO pin as an analogue input (if necessary and possible).
|
||||
|
@ -245,6 +288,37 @@ int MicroBitPin::isTouched()
|
|||
return ((MicroBitButton *)pin)->isPressed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures this IO pin as an analog/pwm output if it isn't already, configures the period to be 20ms,
|
||||
* and sets the pulse width, based on the value it is given
|
||||
*
|
||||
* @param pulseWidth the desired pulse width in microseconds.
|
||||
* @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if value is out of range, or MICROBIT_NOT_SUPPORTED
|
||||
* if the given pin does not have analog capability.
|
||||
*/
|
||||
int MicroBitPin::setServoPulseUs(int pulseWidth)
|
||||
{
|
||||
//check if this pin has an analogue mode...
|
||||
if(!(PIN_CAPABILITY_ANALOG & capability))
|
||||
return MICROBIT_NOT_SUPPORTED;
|
||||
|
||||
//sanitise the pulse width
|
||||
if(pulseWidth < 0)
|
||||
return MICROBIT_INVALID_PARAMETER;
|
||||
|
||||
//Check we still have the control over the DynamicPwm instance
|
||||
if(obtainAnalogChannel() == MICROBIT_OK)
|
||||
{
|
||||
//check if the period is set to 20ms
|
||||
if(((DynamicPwm *)pin)->getPeriodUs() != MICROBIT_DEFAULT_PWM_PERIOD)
|
||||
((DynamicPwm *)pin)->setPeriodUs(MICROBIT_DEFAULT_PWM_PERIOD);
|
||||
|
||||
((DynamicPwm *)pin)->pulsewidth_us(pulseWidth);
|
||||
}
|
||||
|
||||
return MICROBIT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the PWM period of the analog output to the given value.
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue