Compare commits
16 commits
main
...
servo-patc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5de21e9397 | ||
|
|
6a3d996a0a | ||
|
|
33443ce133 | ||
|
|
83153c8f90 | ||
|
|
be57b06c29 | ||
|
|
bbfccbe980 | ||
|
|
6e95e99ae3 | ||
|
|
8e49d9ee48 | ||
|
|
a047f723d3 | ||
|
|
68d6b13333 | ||
|
|
570a3e1750 | ||
|
|
793caa5ba7 | ||
|
|
5e9bd2485d | ||
|
|
0741c9061b | ||
|
|
dec68f0e66 | ||
|
|
fb04193c87 |
19 changed files with 1019 additions and 14 deletions
|
|
@ -780,6 +780,143 @@ bool cbDecodeSignalRequestI2C(pb_istream_t *stream, const pb_field_t *field,
|
|||
return is_success;
|
||||
}
|
||||
|
||||
/******************************************************************************************/
|
||||
/*!
|
||||
@brief Decodes a servo message and dispatches to the servo component.
|
||||
@param stream
|
||||
Incoming data stream from buffer.
|
||||
@param field
|
||||
Protobuf message's tag type.
|
||||
@param arg
|
||||
Optional arguments from decoder calling function.
|
||||
@returns True if decoded and executed successfully, False otherwise.
|
||||
*/
|
||||
/******************************************************************************************/
|
||||
bool cbDecodeServoMsg(pb_istream_t *stream, const pb_field_t *field,
|
||||
void **arg) {
|
||||
bool is_success = true;
|
||||
WS_DEBUG_PRINTLN("Decoding Servo Message...");
|
||||
|
||||
if (field->tag == wippersnapper_signal_v1_ServoRequest_servo_attach_tag) {
|
||||
WS_DEBUG_PRINTLN("GOT: Servo Attach");
|
||||
// Attempt to decode contents of servo_attach message
|
||||
wippersnapper_servo_v1_ServoAttachReq msgServoAttachReq =
|
||||
wippersnapper_servo_v1_ServoAttachReq_init_zero;
|
||||
if (!pb_decode(stream, wippersnapper_servo_v1_ServoAttachReq_fields,
|
||||
&msgServoAttachReq)) {
|
||||
WS_DEBUG_PRINTLN(
|
||||
"ERROR: Could not decode wippersnapper_servo_v1_ServoAttachReq");
|
||||
return false; // fail out if we can't decode the request
|
||||
}
|
||||
// execute servo attach request
|
||||
char *servoPin = msgServoAttachReq.servo_pin + 1;
|
||||
bool attached = true;
|
||||
if (!WS._servoComponent->servo_attach(
|
||||
atoi(servoPin), msgServoAttachReq.min_pulse_width,
|
||||
msgServoAttachReq.max_pulse_width, msgServoAttachReq.servo_freq)) {
|
||||
WS_DEBUG_PRINTLN("ERROR: Unable to attach servo to pin!");
|
||||
attached = false;
|
||||
}
|
||||
|
||||
// Create and fill a servo response message
|
||||
size_t msgSz; // message's encoded size
|
||||
wippersnapper_signal_v1_ServoResp msgServoResp =
|
||||
wippersnapper_signal_v1_ServoResp_init_zero;
|
||||
msgServoResp.which_payload =
|
||||
wippersnapper_signal_v1_ServoResp_servo_attach_resp_tag;
|
||||
msgServoResp.payload.servo_attach_resp.attach_success = attached;
|
||||
|
||||
// Encode and publish response back to broker
|
||||
memset(WS._buffer_outgoing, 0, sizeof(WS._buffer_outgoing));
|
||||
pb_ostream_t ostream = pb_ostream_from_buffer(WS._buffer_outgoing,
|
||||
sizeof(WS._buffer_outgoing));
|
||||
if (!pb_encode(&ostream, wippersnapper_signal_v1_ServoResp_fields,
|
||||
&msgServoResp)) {
|
||||
WS_DEBUG_PRINTLN("ERROR: Unable to encode servo response message!");
|
||||
return false;
|
||||
}
|
||||
pb_get_encoded_size(&msgSz, wippersnapper_signal_v1_ServoResp_fields,
|
||||
&msgServoResp);
|
||||
WS_DEBUG_PRINT("-> Servo Attach Response...");
|
||||
WS._mqtt->publish(WS._topic_signal_servo_device, WS._buffer_outgoing, msgSz,
|
||||
1);
|
||||
WS_DEBUG_PRINTLN("Published!");
|
||||
return true;
|
||||
} else if (field->tag ==
|
||||
wippersnapper_signal_v1_ServoRequest_servo_write_tag) {
|
||||
WS_DEBUG_PRINTLN("GOT: Servo Write");
|
||||
|
||||
// Attempt to decode contents of servo write message
|
||||
wippersnapper_servo_v1_ServoWriteReq msgServoWriteReq = wippersnapper_servo_v1_ServoWriteReq_init_zero;
|
||||
|
||||
if (!pb_decode(stream, wippersnapper_servo_v1_ServoWriteReq_fields,
|
||||
&msgServoWriteReq)) {
|
||||
WS_DEBUG_PRINTLN(
|
||||
"ERROR: Could not decode wippersnapper_servo_v1_ServoWriteReq");
|
||||
return false; // fail out if we can't decode the request
|
||||
}
|
||||
// execute servo write request
|
||||
char *servoPin = msgServoWriteReq.servo_pin + 1;
|
||||
WS._servoComponent->servo_write(atoi(servoPin), (int)msgServoWriteReq.pulse_width);
|
||||
} else if (field->tag ==
|
||||
wippersnapper_signal_v1_ServoRequest_servo_detach_tag) {
|
||||
WS_DEBUG_PRINTLN("GOT: Servo Detach");
|
||||
|
||||
// Attempt to decode contents of servo detach message
|
||||
wippersnapper_servo_v1_ServoDetachReq msgServoDetachReq =
|
||||
wippersnapper_servo_v1_ServoDetachReq_init_zero;
|
||||
|
||||
if (!pb_decode(stream, wippersnapper_servo_v1_ServoDetachReq_fields,
|
||||
&msgServoDetachReq)) {
|
||||
WS_DEBUG_PRINTLN(
|
||||
"ERROR: Could not decode wippersnapper_servo_v1_ServoDetachReq");
|
||||
return false; // fail out if we can't decode the request
|
||||
}
|
||||
// execute servo detach request
|
||||
char *servoPin = msgServoDetachReq.servo_pin + 1;
|
||||
WS._servoComponent->servo_detach(atoi(servoPin));
|
||||
} else {
|
||||
WS_DEBUG_PRINTLN("Unable to decode servo message type!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Called when the device recieves a new message from the
|
||||
/servo/ topic.
|
||||
@param data
|
||||
Incoming data from MQTT broker.
|
||||
@param len
|
||||
Length of incoming data.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void cbServoMsg(char *data, uint16_t len) {
|
||||
WS_DEBUG_PRINTLN("* NEW MESSAGE [Topic: Servo]: ");
|
||||
WS_DEBUG_PRINT(len);
|
||||
WS_DEBUG_PRINTLN(" bytes.");
|
||||
// zero-out current buffer
|
||||
memset(WS._buffer, 0, sizeof(WS._buffer));
|
||||
// copy mqtt data into buffer
|
||||
memcpy(WS._buffer, data, len);
|
||||
WS.bufSize = len;
|
||||
|
||||
// Zero-out existing servo message
|
||||
wippersnapper_signal_v1_ServoRequest msgServo =
|
||||
wippersnapper_signal_v1_ServoRequest_init_zero;
|
||||
|
||||
// Set up the payload callback, which will set up the callbacks for
|
||||
// each oneof payload field once the field tag is known
|
||||
WS.msgServo.cb_payload.funcs.decode = cbDecodeServoMsg;
|
||||
|
||||
// Decode servo message from buffer
|
||||
pb_istream_t istream = pb_istream_from_buffer(WS._buffer, WS.bufSize);
|
||||
if (!pb_decode(&istream, wippersnapper_signal_v1_ServoRequest_fields,
|
||||
&WS.msgServo))
|
||||
WS_DEBUG_PRINTLN("ERROR: Unable to decode servo message");
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Called when i2c signal sub-topic receives a new message and
|
||||
|
|
@ -1125,18 +1262,28 @@ bool Wippersnapper::buildWSTopics() {
|
|||
sizeof(char) * strlen(WS._username) + strlen("/wprsnpr/") +
|
||||
strlen(_device_uid) + strlen(TOPIC_SIGNALS) + strlen("broker") + 1);
|
||||
|
||||
// Topic for i2c signals from device to broker
|
||||
// Topic for i2c signals from broker to device
|
||||
WS._topic_signal_i2c_brkr = (char *)malloc(
|
||||
sizeof(char) * strlen(WS._username) + +strlen("/") + strlen(_device_uid) +
|
||||
strlen("/wprsnpr/") + strlen(TOPIC_SIGNALS) + strlen("broker") +
|
||||
strlen(TOPIC_I2C) + 1);
|
||||
|
||||
// Topic for i2c signals from broker to device
|
||||
// Topic for i2c signals from device to broker
|
||||
WS._topic_signal_i2c_device = (char *)malloc(
|
||||
sizeof(char) * strlen(WS._username) + +strlen("/") + strlen(_device_uid) +
|
||||
strlen("/wprsnpr/") + strlen(TOPIC_SIGNALS) + strlen("device") +
|
||||
strlen(TOPIC_I2C) + 1);
|
||||
|
||||
// Topic for servo messages from broker->device
|
||||
WS._topic_signal_servo_brkr = (char *)malloc(
|
||||
sizeof(char) * strlen(WS._username) + strlen("/") + strlen(_device_uid) +
|
||||
strlen("/wprsnpr/signals/broker/servo") + 1);
|
||||
|
||||
// Topic for servo messages from device->broker
|
||||
WS._topic_signal_servo_device = (char *)malloc(
|
||||
sizeof(char) * strlen(WS._username) + strlen("/") + strlen(_device_uid) +
|
||||
strlen("/wprsnpr/signals/device/servo") + 1);
|
||||
|
||||
// Create global registration topic
|
||||
if (WS._topic_description != NULL) {
|
||||
strcpy(WS._topic_description, WS._username);
|
||||
|
|
@ -1228,6 +1375,28 @@ bool Wippersnapper::buildWSTopics() {
|
|||
is_success = false;
|
||||
}
|
||||
|
||||
// Create device-to-broker servo signal topic
|
||||
if (WS._topic_signal_i2c_device != NULL) {
|
||||
strcpy(WS._topic_signal_i2c_device, WS._username);
|
||||
strcat(WS._topic_signal_i2c_device, TOPIC_WS);
|
||||
strcat(WS._topic_signal_i2c_device, _device_uid);
|
||||
strcat(WS._topic_signal_i2c_device, TOPIC_SIGNALS);
|
||||
strcat(WS._topic_signal_i2c_device, "broker/servo");
|
||||
} else { // malloc failed
|
||||
is_success = false;
|
||||
}
|
||||
|
||||
// Create broker-to-device i2c signal topic
|
||||
if (WS._topic_signal_i2c_device != NULL) {
|
||||
strcpy(WS._topic_signal_i2c_device, WS._username);
|
||||
strcat(WS._topic_signal_i2c_device, TOPIC_WS);
|
||||
strcat(WS._topic_signal_i2c_device, _device_uid);
|
||||
strcat(WS._topic_signal_i2c_device, TOPIC_SIGNALS);
|
||||
strcat(WS._topic_signal_i2c_device, "device/servo");
|
||||
} else { // malloc failed
|
||||
is_success = false;
|
||||
}
|
||||
|
||||
return is_success;
|
||||
}
|
||||
|
||||
|
|
@ -1249,6 +1418,12 @@ void Wippersnapper::subscribeWSTopics() {
|
|||
WS._mqtt->subscribe(_topic_signal_i2c_sub);
|
||||
_topic_signal_i2c_sub->setCallback(cbSignalI2CReq);
|
||||
|
||||
// Subscribe to servo sub-topic
|
||||
_topic_signal_servo_sub =
|
||||
new Adafruit_MQTT_Subscribe(WS._mqtt, WS._topic_signal_servo_brkr, 1);
|
||||
WS._mqtt->subscribe(_topic_signal_servo_sub);
|
||||
_topic_signal_servo_sub->setCallback(cbServoMsg);
|
||||
|
||||
// Subscribe to registration status topic
|
||||
_topic_description_sub =
|
||||
new Adafruit_MQTT_Subscribe(WS._mqtt, WS._topic_description_status, 1);
|
||||
|
|
@ -1600,9 +1775,21 @@ void Wippersnapper::connect() {
|
|||
runNetFSM();
|
||||
publishPinConfigComplete();
|
||||
WS_DEBUG_PRINTLN("Hardware configured successfully!");
|
||||
statusLEDFade(GREEN, 3);
|
||||
|
||||
// Run application
|
||||
// Register components
|
||||
WS_DEBUG_PRINTLN("Registering components...");
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
WS_DEBUG_PRINT("LEDC: ");
|
||||
WS._ledc = new WipperSnapper_Component_LEDC();
|
||||
WS_DEBUG_PRINTLN("OK!");
|
||||
#endif
|
||||
|
||||
WS_DEBUG_PRINT("SERVO: ");
|
||||
WS._servoComponent = new ws_servo();
|
||||
WS_DEBUG_PRINTLN("OK!");
|
||||
|
||||
// goto application
|
||||
statusLEDFade(GREEN, 3);
|
||||
WS_DEBUG_PRINTLN(
|
||||
"Registration and configuration complete!\nRunning application...");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,14 @@
|
|||
#include "components/digitalIO/Wippersnapper_DigitalGPIO.h"
|
||||
#include "components/i2c/WipperSnapper_I2C.h"
|
||||
|
||||
// ESP32-Specific Driver(s)
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#include "components/ledc/ws_ledc.h"
|
||||
// #include "components/ledc/drivers/ws_ledc_servo.h"
|
||||
#endif
|
||||
|
||||
#include "components/servo/ws_servo.h"
|
||||
|
||||
// External libraries
|
||||
#include "Adafruit_MQTT.h" // MQTT Client
|
||||
#include "Arduino.h" // Wiring
|
||||
|
|
@ -162,6 +170,12 @@ class Wippersnapper_FS;
|
|||
class WipperSnapper_LittleFS;
|
||||
class WipperSnapper_Component_I2C;
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
class WipperSnapper_Component_LEDC;
|
||||
#endif
|
||||
|
||||
class ws_servo;
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Class that provides storage and functions for the Adafruit IO
|
||||
|
|
@ -267,6 +281,7 @@ public:
|
|||
Wippersnapper_FS *_fileSystem; ///< Instance of Filesystem (native USB)
|
||||
WipperSnapper_LittleFS
|
||||
*_littleFS; ///< Instance of LittleFS Filesystem (non-native USB)
|
||||
ws_servo *_servoComponent;
|
||||
|
||||
uint8_t _macAddr[6]; /*!< Unique network iface identifier */
|
||||
char sUID[13]; /*!< Unique network iface identifier */
|
||||
|
|
@ -293,6 +308,10 @@ public:
|
|||
to a broker. */
|
||||
char *_topic_signal_i2c_device = NULL; /*!< Topic carries messages from a
|
||||
broker to a device. */
|
||||
char *_topic_signal_servo_brkr = NULL; /*!< Topic carries messages from a
|
||||
device to a broker. */
|
||||
char *_topic_signal_servo_device = NULL; /*!< Topic carries messages from a
|
||||
broker to a device. */
|
||||
|
||||
wippersnapper_signal_v1_CreateSignalRequest
|
||||
_incomingSignalMsg; /*!< Incoming signal message from broker */
|
||||
|
|
@ -302,12 +321,20 @@ public:
|
|||
wippersnapper_signal_v1_I2CRequest_init_zero; ///< I2C request wrapper
|
||||
///< message
|
||||
|
||||
// servo message
|
||||
wippersnapper_signal_v1_ServoRequest msgServo;
|
||||
|
||||
char *throttleMessage; /*!< Pointer to throttle message data. */
|
||||
int throttleTime; /*!< Total amount of time to throttle the device, in
|
||||
milliseconds. */
|
||||
|
||||
bool pinCfgCompleted = false; /*!< Did initial pin sync complete? */
|
||||
|
||||
// enable LEDC if esp32
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
WipperSnapper_Component_LEDC *_ledc = nullptr;
|
||||
#endif
|
||||
|
||||
private:
|
||||
void _init();
|
||||
|
||||
|
|
@ -347,6 +374,8 @@ protected:
|
|||
*_topic_signal_brkr_sub; /*!< Subscription for C2D signal topic. */
|
||||
Adafruit_MQTT_Subscribe
|
||||
*_topic_signal_i2c_sub; /*!< Subscribes to signal's I2C topic. */
|
||||
Adafruit_MQTT_Subscribe
|
||||
*_topic_signal_servo_sub; /*!< Subscribes to device's servo topic. */
|
||||
|
||||
Adafruit_MQTT_Subscribe
|
||||
*_err_sub; /*!< Subscription to Adafruit IO Error topic. */
|
||||
|
|
@ -356,7 +385,6 @@ protected:
|
|||
wippersnapper_signal_v1_CreateSignalRequest
|
||||
_outgoingSignalMsg; /*!< Outgoing signal message from device */
|
||||
};
|
||||
|
||||
extern Wippersnapper WS; ///< Global member variable for callbacks
|
||||
|
||||
#endif // ADAFRUIT_WIPPERSNAPPER_H
|
||||
|
|
|
|||
1
src/components/ledc/drivers/README.txt
Normal file
1
src/components/ledc/drivers/README.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
These files are drivers that interface directly with WipperSnapper's ESP32 LEDC peripheral manager, `ws_ledc`.
|
||||
116
src/components/ledc/drivers/ws_ledc_servo.cpp
Normal file
116
src/components/ledc/drivers/ws_ledc_servo.cpp
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/*!
|
||||
* @file ws_ledc_servo.cpp
|
||||
*
|
||||
* Driver for ESP32 servo control using the WipperSnapper
|
||||
* LEDC peripheral manager API.
|
||||
*
|
||||
* Adafruit invests time and resources providing this open source code,
|
||||
* please support Adafruit and open-source hardware by purchasing
|
||||
* products from Adafruit!
|
||||
*
|
||||
* @section author Author
|
||||
*
|
||||
* Written by Brent Rubell for Adafruit Industries, 2022.
|
||||
*
|
||||
* writeMicroseconds calculation from ESP32Servo
|
||||
* https://github.com/madhephaestus/ESP32Servo/blob/master/src/ESP32Servo.cpp
|
||||
* Copyright (c) 2017 John K. Bennett.
|
||||
*
|
||||
* @section license License
|
||||
*
|
||||
* GNU Lesser General Public License, all text here must be included in any
|
||||
* redistribution.
|
||||
*
|
||||
*/
|
||||
#include "ws_ledc_servo.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Constructor.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
ws_ledc_servo::ws_ledc_servo() {}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Destructor
|
||||
*/
|
||||
/**************************************************************************/
|
||||
ws_ledc_servo::~ws_ledc_servo() {
|
||||
detach(); // detach the active pin
|
||||
}
|
||||
|
||||
void ws_ledc_servo::setLEDCDriver(WipperSnapper_Component_LEDC *ledcManager) {
|
||||
_ledcMgr = ledcManager;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Attaches a servo object to a pin.
|
||||
@param pin Desired GPIO pin.
|
||||
@param minPulseWidth Minimum pulsewidth, in uS.
|
||||
@param maxPulseWidth Maximum pulsewidth, in uS.
|
||||
@returns Channel number if a servo is successfully attached to a pin,
|
||||
otherwise 255.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
uint8_t ws_ledc_servo::attach(int pin, int minPulseWidth, int maxPulseWidth,
|
||||
int servoFreq) {
|
||||
// Attempt to attach a pin to ledc channel
|
||||
uint8_t chan = _ledcMgr->attachPin((uint8_t)pin, (double)servoFreq);
|
||||
if (chan == 255) // error!
|
||||
return chan;
|
||||
// configure the servo object and assign it to a pin
|
||||
_servo.Pin.nbr = pin;
|
||||
_servo.Pin.isActive = true;
|
||||
_minPulseWidth = minPulseWidth;
|
||||
_maxPulseWidth = maxPulseWidth;
|
||||
return chan;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Detaches the servo (ledc timer) and de-allocates a servo
|
||||
object.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void ws_ledc_servo::detach() {
|
||||
_ledcMgr->detachPin(_servo.Pin.nbr);
|
||||
_servo.Pin.isActive = false;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Returns if the servo is attached to a ledc timer
|
||||
@returns True if the servo is attached to a timer, False otherwise.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
bool ws_ledc_servo::attached() { return _servo.Pin.isActive; }
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Writes the pulse width to the connected servo pin.
|
||||
@param value Desired pulse width, in microseconds.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void ws_ledc_servo::writeMicroseconds(int value) {
|
||||
// are we attached to a pin?
|
||||
if (!attached()) {
|
||||
Serial.println("NOT ATTACHED TO PIN!");
|
||||
return;
|
||||
}
|
||||
|
||||
// out-of-bounds check, scale value
|
||||
if (value < _minPulseWidth)
|
||||
value = _minPulseWidth;
|
||||
if (value > _maxPulseWidth)
|
||||
value = _maxPulseWidth;
|
||||
|
||||
// formula from
|
||||
// https://github.com/madhephaestus/ESP32Servo/blob/master/src/ESP32Servo.cpp
|
||||
// count = (pulse_high_width / (pulse_period/2**timer_width))
|
||||
// 50Hz servo = 20ms pulse_period
|
||||
// count = pulse_high_width /((20000/65536))
|
||||
uint32_t count = ((double)value / 0.30517578);
|
||||
_ledcMgr->setDuty(_servo.Pin.nbr, count);
|
||||
}
|
||||
70
src/components/ledc/drivers/ws_ledc_servo.h
Normal file
70
src/components/ledc/drivers/ws_ledc_servo.h
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*!
|
||||
* @file ws_esp32_ledc.h
|
||||
*
|
||||
* Driver for ESP32 servo control using the WipperSnapper
|
||||
* LEDC peripheral manager API.
|
||||
*
|
||||
* Adafruit invests time and resources providing this open source code,
|
||||
* please support Adafruit and open-source hardware by purchasing
|
||||
* products from Adafruit!
|
||||
*
|
||||
*
|
||||
* Brent Rubell for Adafruit Industries 2022
|
||||
*
|
||||
*
|
||||
* MIT license, all text here must be included in any redistribution.
|
||||
*
|
||||
*/
|
||||
#ifndef WS_ESP32_SERVO
|
||||
#define WS_ESP32_SERVO
|
||||
|
||||
#include "components/ledc/ws_ledc.h"
|
||||
|
||||
// from https://github.com/arduino-libraries/Servo/blob/master/src/Servo.h
|
||||
#define MIN_PULSE_WIDTH 544 ///< The shortest pulse sent to a servo
|
||||
#define MAX_PULSE_WIDTH 2400 ///< The longest pulse sent to a servo
|
||||
#define INVALID_SERVO 255 ///< Flag indicating an invalid servo index
|
||||
|
||||
#define DEFAULT_SERVO_FREQ 50 ///< default servo frequency
|
||||
#define MAX_SERVOS MAX_LEDC_PWMS ///< Maximum number of servo instance
|
||||
|
||||
/** Defines a servo attached to a pin */
|
||||
typedef struct {
|
||||
uint8_t nbr; ///< Servo's pin number
|
||||
uint8_t isActive; ///< True if the servo is enabled
|
||||
} ServoPin_t;
|
||||
|
||||
/** Defines a ws_ledc_servo object */
|
||||
typedef struct {
|
||||
ServoPin_t Pin; ///< Servo properties
|
||||
} servo_t;
|
||||
|
||||
class WipperSnapper_Component_LEDC;
|
||||
|
||||
/************************************************************************************************/
|
||||
/*!
|
||||
@brief High-level driver for servos for ESP32/ESP32-Sx/ESP32-Cx. This
|
||||
driver implements a subset of the functions within the Arduino
|
||||
servo library,
|
||||
(https://github.com/arduino-libraries/Servo/blob/master/src/Servo.h).
|
||||
*/
|
||||
/************************************************************************************************/
|
||||
class ws_ledc_servo {
|
||||
public:
|
||||
ws_ledc_servo();
|
||||
~ws_ledc_servo();
|
||||
void setLEDCDriver(WipperSnapper_Component_LEDC *ledcManager);
|
||||
// The functions below are compatible with
|
||||
// https://github.com/arduino-libraries/Servo/blob/master/src/Servo.h
|
||||
uint8_t attach(int pin, int minPulseWidth, int maxPulseWidth, int servoFreq);
|
||||
bool attached();
|
||||
void detach();
|
||||
void writeMicroseconds(int value);
|
||||
|
||||
private:
|
||||
servo_t _servo; ///< ws_ledc_servo object
|
||||
int _minPulseWidth; ///< Servo's minimum pulse width, in uS.
|
||||
int _maxPulseWidth; ///< Servo's maximum pulse width, in uS.
|
||||
WipperSnapper_Component_LEDC *_ledcMgr;
|
||||
};
|
||||
#endif // WS_ESP32_SERVO
|
||||
155
src/components/ledc/ws_ledc.cpp
Normal file
155
src/components/ledc/ws_ledc.cpp
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
/*!
|
||||
* @file ws_ledc.cpp
|
||||
*
|
||||
* This is the documentation for WipperSnapper's LEDC peripheral
|
||||
* management API. It is used by drivers like ledc_servo.
|
||||
*
|
||||
* Adafruit invests time and resources providing this open source code,
|
||||
* please support Adafruit and open-source hardware by purchasing
|
||||
* products from Adafruit!
|
||||
*
|
||||
* @section author Author
|
||||
*
|
||||
* Written by Brent Rubell for Adafruit Industries, 2022.
|
||||
*
|
||||
* @section license License
|
||||
*
|
||||
* MIT license, all text here must be included in any redistribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ws_ledc.h"
|
||||
|
||||
WipperSnapper_Component_LEDC::WipperSnapper_Component_LEDC() {
|
||||
// reset active pins
|
||||
for (int i = 0; i < MAX_LEDC_PWMS; i++) {
|
||||
_ledcPins[i].isActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
WipperSnapper_Component_LEDC::~WipperSnapper_Component_LEDC() {
|
||||
// detach all active pins and de-allocate them
|
||||
for (int i = 0; i < MAX_LEDC_PWMS; i++) {
|
||||
detachPin(_ledcPins[i].pin);
|
||||
_ledcPins[i].isActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Allocates a timer + channel for a pin and attaches it.
|
||||
@param pin Desired GPIO pin number.
|
||||
@param freq Desired timer frequency, in Hz.
|
||||
@return The channel number if the pin was successfully attached,
|
||||
otherwise 255.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
uint8_t WipperSnapper_Component_LEDC::attachPin(uint8_t pin, double freq) {
|
||||
// have we already attached this pin?
|
||||
for (int i = 0; i < MAX_LEDC_PWMS; i++) {
|
||||
if (_ledcPins[i].pin == pin)
|
||||
return 255;
|
||||
}
|
||||
|
||||
// allocate chanel
|
||||
uint8_t chanNum = _allocateChannel(freq);
|
||||
if (chanNum == 255)
|
||||
return chanNum;
|
||||
|
||||
// attach pin to channel
|
||||
ledcAttachPin(pin, chanNum);
|
||||
|
||||
// allocate pin in pool
|
||||
_ledcPins[chanNum].pin = pin;
|
||||
|
||||
return chanNum;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Detaches a pin and de-allocates it from the manager.
|
||||
@param pin Desired GPIO pin number.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void WipperSnapper_Component_LEDC::detachPin(uint8_t pin) {
|
||||
// find the channel corresponding to the pin
|
||||
uint8_t chan;
|
||||
for (int i = 0; i < sizeof(_ledcPins); i++) {
|
||||
if (_ledcPins[i].pin == pin) {
|
||||
chan = _ledcPins[i].chan;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// detach the pin
|
||||
ledcDetachPin(pin);
|
||||
|
||||
// de-allocate the pin and the channel
|
||||
for (int i = 0; i < sizeof(_ledcPins); i++) {
|
||||
if (_ledcPins[i].pin == pin) {
|
||||
_ledcPins[i].pin = 0;
|
||||
_ledcPins[i].chan = 255;
|
||||
_ledcPins[i].isActive = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Allocates a channel and timer.
|
||||
@param freq Desired timer frequency, in Hz.
|
||||
@return The channel number if the timer was successfully initialized,
|
||||
otherwise 255.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
uint8_t WipperSnapper_Component_LEDC::_allocateChannel(double freq) {
|
||||
// attempt to allocate an inactive channel
|
||||
uint8_t chanNum = 255;
|
||||
for (int i = 0; i < MAX_LEDC_PWMS; i++) {
|
||||
if (_ledcPins[i].isActive == false) {
|
||||
chanNum = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// did we fail to allocate?
|
||||
if (chanNum == 255)
|
||||
return 255;
|
||||
|
||||
// attempt to set up a ledc_timer on the free channel
|
||||
double rc = ledcSetup(uint8_t(chanNum), freq, 16);
|
||||
if (rc == 0)
|
||||
return 255;
|
||||
|
||||
// Assign
|
||||
_ledcPins[chanNum].chan = chanNum;
|
||||
_ledcPins[chanNum].isActive = true;
|
||||
|
||||
return chanNum;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Sets the duty cycle of a pin
|
||||
@param pin Desired GPIO pin to write to.
|
||||
@param freq Desired duty cycle.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void WipperSnapper_Component_LEDC::setDuty(uint8_t pin, uint32_t duty) {
|
||||
// find the channel corresponding to the pin
|
||||
uint8_t chan;
|
||||
for (int i = 0; i < sizeof(_ledcPins); i++) {
|
||||
if (_ledcPins[i].pin == pin) {
|
||||
chan = _ledcPins[i].chan;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// set the channel's duty cycle
|
||||
// debug...
|
||||
// Serial.print("Writing duty cycle: ");
|
||||
// Serial.print(duty);
|
||||
// Serial.print("(%) to channel#: ");
|
||||
// Serial.println(chan);
|
||||
ledcWrite(chan, duty);
|
||||
}
|
||||
63
src/components/ledc/ws_ledc.h
Normal file
63
src/components/ledc/ws_ledc.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*!
|
||||
* @file ws_ledc.h
|
||||
*
|
||||
* High-level interface for ESP32's LED Control (LEDC) peripheral,
|
||||
* to be used by PWM and Servo drivers.
|
||||
*
|
||||
* Adafruit invests time and resources providing this open source code,
|
||||
* please support Adafruit and open-source hardware by purchasing
|
||||
* products from Adafruit!
|
||||
*
|
||||
* Copyright (c) Brent Rubell 2022 for Adafruit Industries.
|
||||
*
|
||||
* BSD license, all text here must be included in any redistribution.
|
||||
*
|
||||
*/
|
||||
#ifndef WIPPERSNAPPER_COMPONENT_LEDC_H
|
||||
#define WIPPERSNAPPER_COMPONENT_LEDC_H
|
||||
|
||||
#include "Wippersnapper.h"
|
||||
|
||||
#include "esp32-hal-ledc.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#define MAX_LEDC_PWMS \
|
||||
16 ///< maximum # of LEDC channels (see: LEDC Chan to Group/Channel/Timer
|
||||
///< Mapping)
|
||||
#define LEDC_RESOLUTION 10 ///< max LEDC resolution
|
||||
#define MAX_TIMER_WIDTH 20 ///< max LEDC esp32 timer width
|
||||
|
||||
/** Defines a pin attached to an active LEDC timer group */
|
||||
typedef struct {
|
||||
uint8_t pin; // GPIO pin number
|
||||
uint8_t chan; // Channel allocated to the pin
|
||||
bool isActive; // True if the ledcPin's timer has been initialized
|
||||
} ledcPin_t;
|
||||
|
||||
// forward decl.
|
||||
class Wippersnapper;
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief High-level interface for the ESP32/ESP32-Sx/ESP32-Cx LED
|
||||
Control (LEDC) peripheral. Instead of specifying a timer or
|
||||
channel, this class automatically allocates a channel and
|
||||
associates it with a pin. Underlying esp32-hal-ledc performs
|
||||
timer management and handles the low-level LEDC peripheral API
|
||||
calls.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
class WipperSnapper_Component_LEDC {
|
||||
public:
|
||||
WipperSnapper_Component_LEDC();
|
||||
~WipperSnapper_Component_LEDC();
|
||||
uint8_t attachPin(uint8_t pin, double freq); // high-level
|
||||
void detachPin(uint8_t pin); // high-level
|
||||
void setDuty(uint8_t pin, uint32_t duty);
|
||||
private:
|
||||
uint8_t _allocateChannel(double freq);
|
||||
ledcPin_t _ledcPins[MAX_LEDC_PWMS]; ///< Pool of usable LEDC pins
|
||||
};
|
||||
extern Wippersnapper WS;
|
||||
|
||||
#endif // WIPPERSNAPPER_COMPONENT_LEDC_H
|
||||
124
src/components/servo/ws_servo.cpp
Normal file
124
src/components/servo/ws_servo.cpp
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/*!
|
||||
* @file ws_component_servo.cpp
|
||||
*
|
||||
* High-level servo manager interface for WipperSnapper.
|
||||
*
|
||||
* Adafruit invests time and resources providing this open source code,
|
||||
* please support Adafruit and open-source hardware by purchasing
|
||||
* products from Adafruit!
|
||||
*
|
||||
* @section author Author
|
||||
*
|
||||
* Written by Brent Rubell for Adafruit Industries, 2022.
|
||||
*
|
||||
*
|
||||
* @section license License
|
||||
*
|
||||
* MIT license, all text here must be included in any redistribution.
|
||||
*
|
||||
*/
|
||||
#include "ws_servo.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Constructor
|
||||
*/
|
||||
/**************************************************************************/
|
||||
ws_servo::ws_servo() {
|
||||
for (int i = 0; i < MAX_SERVO_NUM; i++) {
|
||||
_servos[i].pin = 255;
|
||||
_servos[i].servoObj = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Destructor
|
||||
*/
|
||||
/**************************************************************************/
|
||||
ws_servo::~ws_servo() {
|
||||
for (int i = 0; i < MAX_SERVO_NUM; i++) {
|
||||
// de-allocate servo pins, if attached
|
||||
if (_servos[i].servoObj->attached())
|
||||
_servos[i].servoObj->detach();
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Attaches a servo object to a pin.
|
||||
@param pin Desired GPIO pin.
|
||||
@param minPulseWidth Minimum pulsewidth, in uS.
|
||||
@param maxPulseWidth Maximum pulsewidth, in uS.
|
||||
@param freq Servo Frequency, default is 50Hz
|
||||
@returns True if a servo is successfully attached to a pin,
|
||||
False otherwise
|
||||
*/
|
||||
/**************************************************************************/
|
||||
bool ws_servo::servo_attach(int pin, int minPulseWidth, int maxPulseWidth,
|
||||
int freq) {
|
||||
// ESP32-specific
|
||||
ws_ledc_servo *servo = new ws_ledc_servo();
|
||||
servo->setLEDCDriver(WS._ledc);
|
||||
|
||||
// generalized
|
||||
uint16_t rc = servo->attach(pin, minPulseWidth, maxPulseWidth, freq);
|
||||
if (rc == 255)
|
||||
return false; // allocation or pin error
|
||||
|
||||
// Attempt to allocate an unused servo
|
||||
int servoIdx = -1;
|
||||
for (int i = 0; i < MAX_SERVO_NUM; i++) {
|
||||
Serial.println(_servos[i].pin);
|
||||
if (_servos[i].pin == 255) {
|
||||
servoIdx = i;
|
||||
Serial.print("Servos IDX:");
|
||||
Serial.println(servoIdx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// check if allocated
|
||||
if (servoIdx == 255) {
|
||||
Serial.println("ERROR: Maximum servos reached!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// create a new servo component storage struct
|
||||
_servos[servoIdx].servoObj = servo;
|
||||
_servos[servoIdx].pin = pin;
|
||||
|
||||
// call attach pin
|
||||
_servos[servoIdx].servoObj->attach(pin, minPulseWidth, maxPulseWidth, freq);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Detaches a servo from a pin, frees a servo object to a pin.
|
||||
@param pin Desired GPIO pin.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void ws_servo::servo_detach(int pin) {
|
||||
for (int i = 0; i < MAX_SERVO_NUM; i++) {
|
||||
if (_servos[i].pin == pin) {
|
||||
_servos[i].pin = 255;
|
||||
_servos[i].servoObj->detach();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Writes a pulse width to a servo pin.
|
||||
@param pin Desired GPIO pin.
|
||||
@param value Desired pulse width, in uS.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void ws_servo::servo_write(int pin, int value) {
|
||||
for (int i = 0; i < MAX_SERVO_NUM; i++) {
|
||||
if (_servos[i].pin == pin) {
|
||||
_servos[i].servoObj->writeMicroseconds(value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
64
src/components/servo/ws_servo.h
Normal file
64
src/components/servo/ws_servo.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*!
|
||||
* @file ws_component_servo.h
|
||||
*
|
||||
* High-level interface for wippersnapper to manage servo objects
|
||||
*
|
||||
* Adafruit invests time and resources providing this open source code,
|
||||
* please support Adafruit and open-source hardware by purchasing
|
||||
* products from Adafruit!
|
||||
*
|
||||
*
|
||||
* Brent Rubell for Adafruit Industries 2022
|
||||
*
|
||||
*
|
||||
* MIT license, all text here must be included in any redistribution.
|
||||
*
|
||||
*/
|
||||
#ifndef WS_SERVO
|
||||
#define WS_SERVO
|
||||
|
||||
#include "Wippersnapper.h"
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
#include "components/ledc/drivers/ws_ledc_servo.h"
|
||||
#else
|
||||
#include <Servo.h>
|
||||
#endif
|
||||
|
||||
class Wippersnapper;
|
||||
class ws_ledc_servo;
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
struct servoComponent {
|
||||
ws_ledc_servo *servoObj; ///< Servo object
|
||||
uint8_t pin; ///< Servo's pin number
|
||||
};
|
||||
#else
|
||||
struct servoComponent {
|
||||
Servo *servoObj; ///< Servo object
|
||||
uint8_t pin; ///< Servo's pin number
|
||||
};
|
||||
#endif
|
||||
|
||||
#define MAX_SERVO_NUM 16 ///< Maximum # of servo objects
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Interface for WipperSnapper servo control
|
||||
*/
|
||||
/**************************************************************************/
|
||||
class ws_servo {
|
||||
public:
|
||||
ws_servo();
|
||||
~ws_servo();
|
||||
// TODO: pin, min, max all get replaced by protobuf decoded values
|
||||
bool servo_attach(int pin, int minPulseWidth, int maxPulseWidth, int freq);
|
||||
void servo_detach(int pin);
|
||||
void servo_write(int pin, int value);
|
||||
private:
|
||||
servoComponent _servos[MAX_SERVO_NUM]; ///< Container of servo objects and
|
||||
///< their associated pin #s
|
||||
};
|
||||
extern Wippersnapper WS;
|
||||
|
||||
#endif // WS_SERVO
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.4.6 at Thu Jun 9 14:18:28 2022. */
|
||||
/* Generated by nanopb-0.4.6 at Thu Jul 28 12:28:13 2022. */
|
||||
|
||||
#include "wippersnapper/description/v1/description.pb.h"
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.4.6 at Thu Jun 9 14:18:28 2022. */
|
||||
/* Generated by nanopb-0.4.6 at Thu Jul 28 12:28:13 2022. */
|
||||
|
||||
#ifndef PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED
|
||||
#define PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.4.6 at Thu Jun 9 14:18:28 2022. */
|
||||
/* Generated by nanopb-0.4.6 at Thu Jul 28 12:28:13 2022. */
|
||||
|
||||
#include "wippersnapper/i2c/v1/i2c.pb.h"
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.4.6 at Thu Jun 9 14:18:28 2022. */
|
||||
/* Generated by nanopb-0.4.6 at Thu Jul 28 12:28:13 2022. */
|
||||
|
||||
#ifndef PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED
|
||||
#define PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.4.6 at Thu Jun 9 14:18:28 2022. */
|
||||
/* Generated by nanopb-0.4.6 at Thu Jul 28 12:28:13 2022. */
|
||||
|
||||
#include "wippersnapper/pin/v1/pin.pb.h"
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.4.6 at Thu Jun 9 14:18:28 2022. */
|
||||
/* Generated by nanopb-0.4.6 at Thu Jul 28 12:28:13 2022. */
|
||||
|
||||
#ifndef PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED
|
||||
#define PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED
|
||||
|
|
|
|||
21
src/wippersnapper/servo/v1/servo.pb.c
Normal file
21
src/wippersnapper/servo/v1/servo.pb.c
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.4.6 at Thu Jul 28 12:28:13 2022. */
|
||||
|
||||
#include "wippersnapper/servo/v1/servo.pb.h"
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(wippersnapper_servo_v1_ServoAttachReq, wippersnapper_servo_v1_ServoAttachReq, AUTO)
|
||||
|
||||
|
||||
PB_BIND(wippersnapper_servo_v1_ServoAttachResp, wippersnapper_servo_v1_ServoAttachResp, AUTO)
|
||||
|
||||
|
||||
PB_BIND(wippersnapper_servo_v1_ServoDetachReq, wippersnapper_servo_v1_ServoDetachReq, AUTO)
|
||||
|
||||
|
||||
PB_BIND(wippersnapper_servo_v1_ServoWriteReq, wippersnapper_servo_v1_ServoWriteReq, AUTO)
|
||||
|
||||
|
||||
|
||||
117
src/wippersnapper/servo/v1/servo.pb.h
Normal file
117
src/wippersnapper/servo/v1/servo.pb.h
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.4.6 at Thu Jul 28 12:28:13 2022. */
|
||||
|
||||
#ifndef PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED
|
||||
#define PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
#include "nanopb/nanopb.pb.h"
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
/* Struct definitions */
|
||||
/* *
|
||||
ServoAttachReq represents a request to attach a servo to a pin. */
|
||||
typedef struct _wippersnapper_servo_v1_ServoAttachReq {
|
||||
char servo_pin[6]; /* * The name of pin to attach a servo to. */
|
||||
int32_t servo_freq; /* * The overall PWM frequency, default sent by Adafruit IO is 50Hz. * */
|
||||
int32_t min_pulse_width; /* * The minimum pulse length in uS. Default sent by Adafruit IO is 500uS. * */
|
||||
int32_t max_pulse_width; /* * The maximum pulse length in uS. Default sent by Adafruit IO is 2500uS. * */
|
||||
} wippersnapper_servo_v1_ServoAttachReq;
|
||||
|
||||
/* *
|
||||
ServoAttachResp represents the result of attaching a servo to a pin. */
|
||||
typedef struct _wippersnapper_servo_v1_ServoAttachResp {
|
||||
bool attach_success; /* * True if a servo was attached successfully, False otherwise. * */
|
||||
} wippersnapper_servo_v1_ServoAttachResp;
|
||||
|
||||
/* *
|
||||
ServoDetachReq represents request to detach a servo from a pin and de-initialize the pin for other uses. */
|
||||
typedef struct _wippersnapper_servo_v1_ServoDetachReq {
|
||||
char servo_pin[5]; /* * The name of pin to use as a servo pin. */
|
||||
} wippersnapper_servo_v1_ServoDetachReq;
|
||||
|
||||
/* *
|
||||
ServoWriteReq represents a message to write the servo's position.
|
||||
|
||||
NOTE: Position is sent from Adafruit IO as a pulse width in uS between 500uS
|
||||
and 2500uS. The client application must convert pulse width to duty cycle w/fixed
|
||||
freq of 50Hz prior to writing to the servo pin. */
|
||||
typedef struct _wippersnapper_servo_v1_ServoWriteReq {
|
||||
char servo_pin[5]; /* * The name of pin we're addressing. */
|
||||
int32_t pulse_width; /* * The pulse width to write to the servo, in uS * */
|
||||
} wippersnapper_servo_v1_ServoWriteReq;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define wippersnapper_servo_v1_ServoAttachReq_init_default {"", 0, 0, 0}
|
||||
#define wippersnapper_servo_v1_ServoAttachResp_init_default {0}
|
||||
#define wippersnapper_servo_v1_ServoDetachReq_init_default {""}
|
||||
#define wippersnapper_servo_v1_ServoWriteReq_init_default {"", 0}
|
||||
#define wippersnapper_servo_v1_ServoAttachReq_init_zero {"", 0, 0, 0}
|
||||
#define wippersnapper_servo_v1_ServoAttachResp_init_zero {0}
|
||||
#define wippersnapper_servo_v1_ServoDetachReq_init_zero {""}
|
||||
#define wippersnapper_servo_v1_ServoWriteReq_init_zero {"", 0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define wippersnapper_servo_v1_ServoAttachReq_servo_pin_tag 1
|
||||
#define wippersnapper_servo_v1_ServoAttachReq_servo_freq_tag 2
|
||||
#define wippersnapper_servo_v1_ServoAttachReq_min_pulse_width_tag 3
|
||||
#define wippersnapper_servo_v1_ServoAttachReq_max_pulse_width_tag 4
|
||||
#define wippersnapper_servo_v1_ServoAttachResp_attach_success_tag 1
|
||||
#define wippersnapper_servo_v1_ServoDetachReq_servo_pin_tag 1
|
||||
#define wippersnapper_servo_v1_ServoWriteReq_servo_pin_tag 1
|
||||
#define wippersnapper_servo_v1_ServoWriteReq_pulse_width_tag 2
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define wippersnapper_servo_v1_ServoAttachReq_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, STRING, servo_pin, 1) \
|
||||
X(a, STATIC, SINGULAR, INT32, servo_freq, 2) \
|
||||
X(a, STATIC, SINGULAR, INT32, min_pulse_width, 3) \
|
||||
X(a, STATIC, SINGULAR, INT32, max_pulse_width, 4)
|
||||
#define wippersnapper_servo_v1_ServoAttachReq_CALLBACK NULL
|
||||
#define wippersnapper_servo_v1_ServoAttachReq_DEFAULT NULL
|
||||
|
||||
#define wippersnapper_servo_v1_ServoAttachResp_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, BOOL, attach_success, 1)
|
||||
#define wippersnapper_servo_v1_ServoAttachResp_CALLBACK NULL
|
||||
#define wippersnapper_servo_v1_ServoAttachResp_DEFAULT NULL
|
||||
|
||||
#define wippersnapper_servo_v1_ServoDetachReq_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, STRING, servo_pin, 1)
|
||||
#define wippersnapper_servo_v1_ServoDetachReq_CALLBACK NULL
|
||||
#define wippersnapper_servo_v1_ServoDetachReq_DEFAULT NULL
|
||||
|
||||
#define wippersnapper_servo_v1_ServoWriteReq_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, STRING, servo_pin, 1) \
|
||||
X(a, STATIC, SINGULAR, INT32, pulse_width, 2)
|
||||
#define wippersnapper_servo_v1_ServoWriteReq_CALLBACK NULL
|
||||
#define wippersnapper_servo_v1_ServoWriteReq_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t wippersnapper_servo_v1_ServoAttachReq_msg;
|
||||
extern const pb_msgdesc_t wippersnapper_servo_v1_ServoAttachResp_msg;
|
||||
extern const pb_msgdesc_t wippersnapper_servo_v1_ServoDetachReq_msg;
|
||||
extern const pb_msgdesc_t wippersnapper_servo_v1_ServoWriteReq_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define wippersnapper_servo_v1_ServoAttachReq_fields &wippersnapper_servo_v1_ServoAttachReq_msg
|
||||
#define wippersnapper_servo_v1_ServoAttachResp_fields &wippersnapper_servo_v1_ServoAttachResp_msg
|
||||
#define wippersnapper_servo_v1_ServoDetachReq_fields &wippersnapper_servo_v1_ServoDetachReq_msg
|
||||
#define wippersnapper_servo_v1_ServoWriteReq_fields &wippersnapper_servo_v1_ServoWriteReq_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define wippersnapper_servo_v1_ServoAttachReq_size 40
|
||||
#define wippersnapper_servo_v1_ServoAttachResp_size 2
|
||||
#define wippersnapper_servo_v1_ServoDetachReq_size 6
|
||||
#define wippersnapper_servo_v1_ServoWriteReq_size 17
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.4.6 at Thu Jun 9 14:18:28 2022. */
|
||||
/* Generated by nanopb-0.4.6 at Thu Jul 28 12:28:13 2022. */
|
||||
|
||||
#include "wippersnapper/signal/v1/signal.pb.h"
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
|
|
@ -12,6 +12,12 @@ PB_BIND(wippersnapper_signal_v1_I2CRequest, wippersnapper_signal_v1_I2CRequest,
|
|||
PB_BIND(wippersnapper_signal_v1_I2CResponse, wippersnapper_signal_v1_I2CResponse, 2)
|
||||
|
||||
|
||||
PB_BIND(wippersnapper_signal_v1_ServoRequest, wippersnapper_signal_v1_ServoRequest, AUTO)
|
||||
|
||||
|
||||
PB_BIND(wippersnapper_signal_v1_ServoResp, wippersnapper_signal_v1_ServoResp, AUTO)
|
||||
|
||||
|
||||
PB_BIND(wippersnapper_signal_v1_CreateSignalRequest, wippersnapper_signal_v1_CreateSignalRequest, AUTO)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.4.6 at Thu Jun 9 14:18:28 2022. */
|
||||
/* Generated by nanopb-0.4.6 at Thu Jul 28 12:28:13 2022. */
|
||||
|
||||
#ifndef PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED
|
||||
#define PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
#include "nanopb/nanopb.pb.h"
|
||||
#include "wippersnapper/pin/v1/pin.pb.h"
|
||||
#include "wippersnapper/i2c/v1/i2c.pb.h"
|
||||
#include "wippersnapper/servo/v1/servo.pb.h"
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
|
|
@ -59,6 +60,28 @@ typedef struct _wippersnapper_signal_v1_I2CResponse {
|
|||
} payload;
|
||||
} wippersnapper_signal_v1_I2CResponse;
|
||||
|
||||
/* *
|
||||
ServoRequest represents the broker's request across the servo sub-topic. */
|
||||
typedef struct _wippersnapper_signal_v1_ServoRequest {
|
||||
pb_callback_t cb_payload;
|
||||
pb_size_t which_payload;
|
||||
union {
|
||||
wippersnapper_servo_v1_ServoAttachReq servo_attach;
|
||||
wippersnapper_servo_v1_ServoDetachReq servo_detach;
|
||||
wippersnapper_servo_v1_ServoWriteReq servo_write;
|
||||
} payload;
|
||||
} wippersnapper_signal_v1_ServoRequest;
|
||||
|
||||
/* *
|
||||
ServoResp represents the device's response across the servo sub-topic. */
|
||||
typedef struct _wippersnapper_signal_v1_ServoResp {
|
||||
pb_callback_t cb_payload;
|
||||
pb_size_t which_payload;
|
||||
union {
|
||||
wippersnapper_servo_v1_ServoAttachResp servo_attach_resp;
|
||||
} payload;
|
||||
} wippersnapper_signal_v1_ServoResp;
|
||||
|
||||
/* *
|
||||
Response from a signal message payload (device->broker) */
|
||||
typedef struct _wippersnapper_signal_v1_SignalResponse {
|
||||
|
|
@ -76,10 +99,14 @@ extern "C" {
|
|||
/* Initializer values for message structs */
|
||||
#define wippersnapper_signal_v1_I2CRequest_init_default {{{NULL}, NULL}, 0, {wippersnapper_i2c_v1_I2CBusScanRequest_init_default}}
|
||||
#define wippersnapper_signal_v1_I2CResponse_init_default {{{NULL}, NULL}, 0, {wippersnapper_i2c_v1_I2CBusScanResponse_init_default}}
|
||||
#define wippersnapper_signal_v1_ServoRequest_init_default {{{NULL}, NULL}, 0, {wippersnapper_servo_v1_ServoAttachReq_init_default}}
|
||||
#define wippersnapper_signal_v1_ServoResp_init_default {{{NULL}, NULL}, 0, {wippersnapper_servo_v1_ServoAttachResp_init_default}}
|
||||
#define wippersnapper_signal_v1_CreateSignalRequest_init_default {{{NULL}, NULL}, 0, {wippersnapper_pin_v1_ConfigurePinRequests_init_default}}
|
||||
#define wippersnapper_signal_v1_SignalResponse_init_default {0, {0}}
|
||||
#define wippersnapper_signal_v1_I2CRequest_init_zero {{{NULL}, NULL}, 0, {wippersnapper_i2c_v1_I2CBusScanRequest_init_zero}}
|
||||
#define wippersnapper_signal_v1_I2CResponse_init_zero {{{NULL}, NULL}, 0, {wippersnapper_i2c_v1_I2CBusScanResponse_init_zero}}
|
||||
#define wippersnapper_signal_v1_ServoRequest_init_zero {{{NULL}, NULL}, 0, {wippersnapper_servo_v1_ServoAttachReq_init_zero}}
|
||||
#define wippersnapper_signal_v1_ServoResp_init_zero {{{NULL}, NULL}, 0, {wippersnapper_servo_v1_ServoAttachResp_init_zero}}
|
||||
#define wippersnapper_signal_v1_CreateSignalRequest_init_zero {{{NULL}, NULL}, 0, {wippersnapper_pin_v1_ConfigurePinRequests_init_zero}}
|
||||
#define wippersnapper_signal_v1_SignalResponse_init_zero {0, {0}}
|
||||
|
||||
|
|
@ -100,6 +127,10 @@ extern "C" {
|
|||
#define wippersnapper_signal_v1_I2CResponse_resp_i2c_device_deinit_tag 4
|
||||
#define wippersnapper_signal_v1_I2CResponse_resp_i2c_device_update_tag 5
|
||||
#define wippersnapper_signal_v1_I2CResponse_resp_i2c_device_event_tag 6
|
||||
#define wippersnapper_signal_v1_ServoRequest_servo_attach_tag 1
|
||||
#define wippersnapper_signal_v1_ServoRequest_servo_detach_tag 2
|
||||
#define wippersnapper_signal_v1_ServoRequest_servo_write_tag 3
|
||||
#define wippersnapper_signal_v1_ServoResp_servo_attach_resp_tag 1
|
||||
#define wippersnapper_signal_v1_SignalResponse_configuration_complete_tag 1
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
|
|
@ -133,6 +164,22 @@ X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_i2c_device_event,payload.resp_i
|
|||
#define wippersnapper_signal_v1_I2CResponse_payload_resp_i2c_device_update_MSGTYPE wippersnapper_i2c_v1_I2CDeviceUpdateResponse
|
||||
#define wippersnapper_signal_v1_I2CResponse_payload_resp_i2c_device_event_MSGTYPE wippersnapper_i2c_v1_I2CDeviceEvent
|
||||
|
||||
#define wippersnapper_signal_v1_ServoRequest_FIELDLIST(X, a) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (payload,servo_attach,payload.servo_attach), 1) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (payload,servo_detach,payload.servo_detach), 2) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (payload,servo_write,payload.servo_write), 3)
|
||||
#define wippersnapper_signal_v1_ServoRequest_CALLBACK NULL
|
||||
#define wippersnapper_signal_v1_ServoRequest_DEFAULT NULL
|
||||
#define wippersnapper_signal_v1_ServoRequest_payload_servo_attach_MSGTYPE wippersnapper_servo_v1_ServoAttachReq
|
||||
#define wippersnapper_signal_v1_ServoRequest_payload_servo_detach_MSGTYPE wippersnapper_servo_v1_ServoDetachReq
|
||||
#define wippersnapper_signal_v1_ServoRequest_payload_servo_write_MSGTYPE wippersnapper_servo_v1_ServoWriteReq
|
||||
|
||||
#define wippersnapper_signal_v1_ServoResp_FIELDLIST(X, a) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (payload,servo_attach_resp,payload.servo_attach_resp), 1)
|
||||
#define wippersnapper_signal_v1_ServoResp_CALLBACK NULL
|
||||
#define wippersnapper_signal_v1_ServoResp_DEFAULT NULL
|
||||
#define wippersnapper_signal_v1_ServoResp_payload_servo_attach_resp_MSGTYPE wippersnapper_servo_v1_ServoAttachResp
|
||||
|
||||
#define wippersnapper_signal_v1_CreateSignalRequest_FIELDLIST(X, a) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (payload,pin_configs,payload.pin_configs), 6) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (payload,pin_events,payload.pin_events), 7) \
|
||||
|
|
@ -154,12 +201,16 @@ X(a, STATIC, ONEOF, BOOL, (payload,configuration_complete,payload.confi
|
|||
|
||||
extern const pb_msgdesc_t wippersnapper_signal_v1_I2CRequest_msg;
|
||||
extern const pb_msgdesc_t wippersnapper_signal_v1_I2CResponse_msg;
|
||||
extern const pb_msgdesc_t wippersnapper_signal_v1_ServoRequest_msg;
|
||||
extern const pb_msgdesc_t wippersnapper_signal_v1_ServoResp_msg;
|
||||
extern const pb_msgdesc_t wippersnapper_signal_v1_CreateSignalRequest_msg;
|
||||
extern const pb_msgdesc_t wippersnapper_signal_v1_SignalResponse_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define wippersnapper_signal_v1_I2CRequest_fields &wippersnapper_signal_v1_I2CRequest_msg
|
||||
#define wippersnapper_signal_v1_I2CResponse_fields &wippersnapper_signal_v1_I2CResponse_msg
|
||||
#define wippersnapper_signal_v1_ServoRequest_fields &wippersnapper_signal_v1_ServoRequest_msg
|
||||
#define wippersnapper_signal_v1_ServoResp_fields &wippersnapper_signal_v1_ServoResp_msg
|
||||
#define wippersnapper_signal_v1_CreateSignalRequest_fields &wippersnapper_signal_v1_CreateSignalRequest_msg
|
||||
#define wippersnapper_signal_v1_SignalResponse_fields &wippersnapper_signal_v1_SignalResponse_msg
|
||||
|
||||
|
|
@ -174,6 +225,8 @@ union wippersnapper_signal_v1_CreateSignalRequest_payload_size_union {char f6[(6
|
|||
#define wippersnapper_signal_v1_I2CRequest_size (0 + sizeof(union wippersnapper_signal_v1_I2CRequest_payload_size_union))
|
||||
#endif
|
||||
#define wippersnapper_signal_v1_I2CResponse_size 725
|
||||
#define wippersnapper_signal_v1_ServoRequest_size 42
|
||||
#define wippersnapper_signal_v1_ServoResp_size 4
|
||||
#define wippersnapper_signal_v1_SignalResponse_size 2
|
||||
#if defined(wippersnapper_pin_v1_ConfigurePinRequests_size) && defined(wippersnapper_pin_v1_PinEvents_size) && defined(wippersnapper_pin_v1_ConfigurePWMPinRequests_size) && defined(wippersnapper_pin_v1_PWMPinEvents_size)
|
||||
#define wippersnapper_signal_v1_CreateSignalRequest_size (0 + sizeof(union wippersnapper_signal_v1_CreateSignalRequest_payload_size_union))
|
||||
|
|
|
|||
Loading…
Reference in a new issue