diff --git a/software/dumber3/.cproject b/software/dumber3/.cproject
index 55b763a..adf1094 100644
--- a/software/dumber3/.cproject
+++ b/software/dumber3/.cproject
@@ -74,54 +74,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -341,7 +293,7 @@
-
+
diff --git a/software/dumber3/.settings/language.settings.xml b/software/dumber3/.settings/language.settings.xml
index 05e2c6b..3deb75d 100644
--- a/software/dumber3/.settings/language.settings.xml
+++ b/software/dumber3/.settings/language.settings.xml
@@ -5,7 +5,7 @@
-
+
@@ -16,7 +16,7 @@
-
+
@@ -27,7 +27,7 @@
-
+
diff --git a/software/dumber3/Application/messages.c b/software/dumber3/Application/messages.c
index 40a72d9..541b953 100644
--- a/software/dumber3/Application/messages.c
+++ b/software/dumber3/Application/messages.c
@@ -1,13 +1,49 @@
-/*
- * messages.c
+/**
+ ******************************************************************************
+ * @file messages.c
+ * @brief messages handler body
+ * @author S. DI MERCURIO (dimercur@insa-toulouse.fr)
+ * @date December 2023
*
- * Created on: 14 sept. 2022
- * Author: dimercur
+ ******************************************************************************
+ * @copyright Copyright 2023 INSA-GEI, Toulouse, France. All rights reserved.
+ * @copyright This project is released under the Lesser GNU Public License (LGPL-3.0-only).
+ *
+ * @copyright This file is part of "Dumber" project
+ *
+ * @copyright This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * @copyright This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * @copyright You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ ******************************************************************************
*/
#include "messages.h"
#include "stdlib.h"
+/** @addtogroup Application_Software
+ * @{
+ */
+
+/** @addtogroup MESSAGES
+ * Messages module handles mailbox and messages communication support between tasks
+ * @{
+ */
+
+/** @addtogroup MESSAGES_Private Private
+ * @{
+ */
+
#define QUEUE_SIZE 5
QueueHandle_t LEDS_Mailbox;
@@ -15,6 +51,12 @@ QueueHandle_t MOTORS_Mailbox;
QueueHandle_t APPLICATION_Mailbox;
QueueHandle_t XBEE_Mailbox;
+/**
+ * @brief Function for initializing messaging system
+ *
+ * @param None
+ * @return None
+ */
void MESSAGE_Init(void) {
LEDS_Mailbox = xQueueCreate(QUEUE_SIZE, sizeof(MESSAGE_Typedef));
MOTORS_Mailbox = xQueueCreate(QUEUE_SIZE, sizeof(MESSAGE_Typedef));
@@ -22,6 +64,15 @@ void MESSAGE_Init(void) {
XBEE_Mailbox = xQueueCreate(QUEUE_SIZE, sizeof(MESSAGE_Typedef));
}
+/**
+ * @brief Return first message a given mailbox
+ *
+ * @param[in] mbx Mailbox reference
+ * @return First message in mailbox
+ *
+ * @remark This function is blocking until a message is received.
+ * If mailbox is not empty when calling the function, return immediatly with first message in mailbox
+ */
MESSAGE_Typedef MESSAGE_ReadMailbox(QueueHandle_t mbx) {
MESSAGE_Typedef msg= {0};
char msg_received =0;
@@ -37,6 +88,16 @@ MESSAGE_Typedef MESSAGE_ReadMailbox(QueueHandle_t mbx) {
return msg;
}
+/**
+ * @brief Return first message a given mailbox (non blocking)
+ *
+ * @param[in] mbx Mailbox reference
+ * @return First message in mailbox
+ *
+ * @remark This function is non blocking.
+ * If mailbox is empty when calling the function, a message structure is still returned with \ref MSG_ID_NO_MESSAGE
+ * in message id field
+ */
MESSAGE_Typedef MESSAGE_ReadMailboxNoDelay(QueueHandle_t mbx) {
MESSAGE_Typedef msg= {0};
@@ -46,6 +107,18 @@ MESSAGE_Typedef MESSAGE_ReadMailboxNoDelay(QueueHandle_t mbx) {
return msg;
}
+/**
+ * @brief Post a message in a mailbox with given id and data
+ *
+ * @param[in] mbx_dest Destination mailbox
+ * @param[in] id id of message (as found in \ref msg_id_def "Message ID definitions")
+ * @param[in] mbx_sender Sender mailbox (may be null if no answer is expected)
+ * @param[in] data Reference to data to store in message structure
+ * @return None
+ *
+ * @remark This function is non blocking.
+ * If mailbox is full when calling the function, error will be ignored silently
+ */
void MESSAGE_SendMailbox(QueueHandle_t mbx_dest, uint16_t id, QueueHandle_t mbx_sender, void *data){
MESSAGE_Typedef msg;
@@ -58,6 +131,19 @@ void MESSAGE_SendMailbox(QueueHandle_t mbx_dest, uint16_t id, QueueHandle_t mbx_
}
}
+/**
+ * @brief Post, from an ISR, a message in a mailbox with given id and data
+ *
+ * @param[in] mbx_dest Destination mailbox
+ * @param[in] id id of message (as found in \ref msg_id_def "Message ID definitions")
+ * @param[in] mbx_sender Sender mailbox (may be null if no answer is expected)
+ * @param[in] data Reference to data to store in message structure
+ * @param[in] xHigherPriorityTaskWoken Reference to flag indicating if a context switch is to be done at end of ISR
+ * @return None
+ *
+ * @remark This function is non blocking.
+ * If mailbox is full when calling the function, error will be ignored silently
+ */
void MESSAGE_SendMailboxFromISR(QueueHandle_t mbx_dest, uint16_t id, QueueHandle_t mbx_sender, void *data, BaseType_t *xHigherPriorityTaskWoken) {
MESSAGE_Typedef msg;
@@ -70,5 +156,14 @@ void MESSAGE_SendMailboxFromISR(QueueHandle_t mbx_dest, uint16_t id, QueueHandle
}
}
+/**
+ * @}
+ */
+/**
+ * @}
+ */
+/**
+ * @}
+ */
diff --git a/software/dumber3/Application/messages.h b/software/dumber3/Application/messages.h
index c78e10e..bac51fb 100644
--- a/software/dumber3/Application/messages.h
+++ b/software/dumber3/Application/messages.h
@@ -1,8 +1,31 @@
-/*
- * messages.h
+/**
+ ******************************************************************************
+ * @file messages.h
+ * @brief messages handler header
+ * @author S. DI MERCURIO (dimercur@insa-toulouse.fr)
+ * @date December 2023
*
- * Created on: 14 sept. 2022
- * Author: dimercur
+ ******************************************************************************
+ * @copyright Copyright 2023 INSA-GEI, Toulouse, France. All rights reserved.
+ * @copyright This project is released under the Lesser GNU Public License (LGPL-3.0-only).
+ *
+ * @copyright This file is part of "Dumber" project
+ *
+ * @copyright This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * @copyright This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * @copyright You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ ******************************************************************************
*/
#ifndef INC_MESSAGES_H_
@@ -11,10 +34,23 @@
#include "application.h"
#include "queue.h"
+/** @addtogroup Application_Software
+ * @{
+ */
+
+/** @addtogroup MESSAGES
+ * @{
+ */
+
+/** @addtogroup MESSAGES_Public Public
+ * @{
+ */
+
+/** Structure storing messages to be posted in mailbox */
typedef struct {
- uint16_t id;
- QueueHandle_t* sender;
- void *data;
+ uint16_t id; /**< Id of message, as found in \ref msg_id_def "Message ID definitions" */
+ QueueHandle_t* sender; /**< reference to sender mailbox, in case of expected answer */
+ void *data; /**< reference to data */
} MESSAGE_Typedef;
extern QueueHandle_t LEDS_Mailbox;
@@ -22,6 +58,12 @@ extern QueueHandle_t MOTORS_Mailbox;
extern QueueHandle_t APPLICATION_Mailbox;
extern QueueHandle_t XBEE_Mailbox;
+/**
+ * @anchor msg_id_def
+ * @name Message ID definitions
+ * List of message identifiers
+ */
+///@{
#define MSG_ID_NO_MESSAGE 0x00
#define MSG_ID_LED_ETAT 0x10
@@ -40,7 +82,6 @@ extern QueueHandle_t XBEE_Mailbox;
//#define MSG_ID_BAT_CHARGE_ON 0x23
//#define MSG_ID_BAT_CHARGE_OFF 0x24
-
#define MSG_ID_BUTTON_PRESSED 0x30
#define MSG_ID_MOTORS_STOP 0x40
@@ -50,6 +91,7 @@ extern QueueHandle_t XBEE_Mailbox;
#define MSG_ID_XBEE_CMD 0x50
#define MSG_ID_XBEE_ANS 0x51
+///@}
void MESSAGE_Init(void);
MESSAGE_Typedef MESSAGE_ReadMailbox(QueueHandle_t mbx);
@@ -57,4 +99,16 @@ MESSAGE_Typedef MESSAGE_ReadMailboxNoDelay(QueueHandle_t mbx);
void MESSAGE_SendMailbox(QueueHandle_t mbx_dest, uint16_t id, QueueHandle_t mbx_sender, void *data);
void MESSAGE_SendMailboxFromISR(QueueHandle_t mbx_dest, uint16_t id, QueueHandle_t mbx_sender, void *data, BaseType_t *xHigherPriorityTaskWoken);
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
#endif /* INC_MESSAGES_H_ */
diff --git a/software/dumber3/Application/motors.c b/software/dumber3/Application/motors.c
index a10e907..335587a 100644
--- a/software/dumber3/Application/motors.c
+++ b/software/dumber3/Application/motors.c
@@ -62,29 +62,35 @@ extern TIM_HandleTypeDef htim3;
#define MOTORS_MAX_COMMAND 200
#define MOTORS_MAX_ENCODER USHRT_MAX
-/** Structure for storing motore (left or right) regulation state
- * Used during regulation task for controlling motor */
+/** Structure for storing motors (left or right) control state
+ * Used during control loop task for controlling motor
+ */
typedef struct {
- int16_t output; /**< */
- int16_t set_point; /**< Xbee RF quality (not used)*/
- uint16_t encoder; /**< Xbee RF quality (not used)*/
- uint16_t encoderEdge; /**< Xbee RF quality (not used)*/
- uint8_t slowMotor; /**< Xbee RF quality (not used)*/
+ int16_t output; /**< Output value to send to motor. Positive values for forward and negative values for backward
+ +/- 65535 for full power and 0 for motor stop */
+ int16_t setpoint; /**< Set point value for motor control*/
+ uint16_t encoder; /**< Number of encoder pulse acquired between last control loop iteration*/
+ uint16_t encoderEdge; /**< Delta T between two encoders pulse (the fastest the motor goes, the lowest the value is.
+ 65536 means motor is stopped */
+ uint8_t slowMotor; /**< Flag for indicating that motor has stopped */
} MOTORS_MotorState;
-/** Structure storing counters used for watchdog and system inactivity.
- * Used notably to check if watchdog reset was missed or power down system because of inactivity */
+/** Structure for storing differential control state.
+ * Used during top differentiel control loop, to ensure trjactory is strait */
typedef struct {
- uint8_t type; /**< Xbee RF quality (not used)*/
- int16_t output; /**< Xbee RF quality (not used)*/
- int16_t set_point; /**< Xbee RF quality (not used)*/
- int32_t distance; /**< Xbee RF quality (not used)*/
- int32_t turns; /**< Xbee RF quality (not used)*/
+ uint8_t type; /**< not used */
+ int16_t output; /**< not used */
+ int16_t setpoint; /**< not used */
+ int32_t distance; /**< Distance to move on */
+ int32_t turns; /**< Number of turns to apply */
} MOTORS_DifferentialState;
MOTORS_MotorState MOTORS_LeftMotorState, MOTORS_RightMotorState = { 0 };
MOTORS_DifferentialState MOTORS_DiffState = { 0 };
+/**
+ * Proportionnal constant for motor control loop
+ */
#define MOTOR_Kp 300
/***** Tasks part *****/
@@ -159,7 +165,7 @@ void EndMeasure(void) {
* @brief Function for initializing motors driver
*
* @param None
- * @retval None
+ * @return None
*/
void MOTORS_Init(void) {
/* Désactive les alimentations des moteurs */
@@ -194,10 +200,15 @@ void MOTORS_Init(void) {
}
/**
- * @brief Function for initializing motors driver
+ * @brief Request a movment in strait line
*
- * @param None
- * @retval None
+ * @remark This function wrap a message sending to motors mailbox.
+ * In case of multiple call, only last one will be applied,
+ * with potentially some spurious movement when processing previous messages
+ *
+ * @param[in] distance Distance to move on, in mm.
+ * Positive values for forward movements and negative values for backward movements
+ * @return None
*/
void MOTORS_Move(int32_t distance) {
static int32_t dist;
@@ -213,15 +224,20 @@ void MOTORS_Move(int32_t distance) {
}
/**
- * @brief Function for initializing motors driver
+ * @brief Request a movement in rotation
*
- * @param None
- * @retval None
+ * @remark This function wrap a message sending to motors mailbox.
+ * In case of multiple call, only last one will be applied,
+ * with potentially some spurious movement when processing previous messages
+ *
+ * @param[in] rotations Angle of rotation to do in degree.
+ * Positive values for clockwise rotations and negative values for counterclockwise rotations
+ * @return None
*/
-void MOTORS_Turn(int32_t tours) {
+void MOTORS_Turn(int32_t rotations) {
static int32_t turns;
- turns = tours;
+ turns = rotations;
if (turns) {
MOTORS_PowerOn();
@@ -232,10 +248,14 @@ void MOTORS_Turn(int32_t tours) {
}
/**
- * @brief Function for initializing motors driver
+ * @brief Request for stopping any movement
*
- * @param None
- * @retval None
+ * @remark This function wrap a message sending to motors mailbox.
+ * In case of multiple call, only last one will be applied,
+ * with potentially some spurious movement when processing previous messages
+ *
+ * @param None
+ * @return None
*/
void MOTORS_Stop(void) {
MOTORS_PowerOff();
@@ -243,10 +263,12 @@ void MOTORS_Stop(void) {
APPLICATION_Mailbox, (void*) NULL);
}
-/*
- * @brief Tache de supervision des moteurs
- * Gestion de la boite aux lettres moteurs, et supervision generale
- * @param params non utilisé
+/**
+ * @brief Handler task for motor control
+ * Manage mailbox et overall management
+ *
+ * @param[in] params Initial task parameters
+ * @return None
*/
void MOTORS_HandlerTask(void *params) {
MESSAGE_Typedef msg;
@@ -262,11 +284,11 @@ void MOTORS_HandlerTask(void *params) {
MOTORS_DiffState.turns = 0;
if (distance > 0) {
- MOTORS_LeftMotorState.set_point = 50;
- MOTORS_RightMotorState.set_point = 50;
+ MOTORS_LeftMotorState.setpoint = 50;
+ MOTORS_RightMotorState.setpoint = 50;
} else {
- MOTORS_LeftMotorState.set_point = -50;
- MOTORS_RightMotorState.set_point = -50;
+ MOTORS_LeftMotorState.setpoint = -50;
+ MOTORS_RightMotorState.setpoint = -50;
}
vTaskResume(xHandleMotorsControl);
@@ -278,11 +300,11 @@ void MOTORS_HandlerTask(void *params) {
MOTORS_DiffState.turns = tours;
if (tours > 0) {
- MOTORS_LeftMotorState.set_point = -50;
- MOTORS_RightMotorState.set_point = 50;
+ MOTORS_LeftMotorState.setpoint = -50;
+ MOTORS_RightMotorState.setpoint = 50;
} else {
- MOTORS_LeftMotorState.set_point = 50;
- MOTORS_RightMotorState.set_point = -50;
+ MOTORS_LeftMotorState.setpoint = 50;
+ MOTORS_RightMotorState.setpoint = -50;
}
vTaskResume(xHandleMotorsControl);
@@ -292,8 +314,8 @@ void MOTORS_HandlerTask(void *params) {
MOTORS_DiffState.distance = 0;
MOTORS_DiffState.turns = 0;
- MOTORS_LeftMotorState.set_point = 0;
- MOTORS_RightMotorState.set_point = 0;
+ MOTORS_LeftMotorState.setpoint = 0;
+ MOTORS_RightMotorState.setpoint = 0;
if ((MOTORS_EncoderCorrection(MOTORS_LeftMotorState) == 0)
&& (MOTORS_EncoderCorrection(MOTORS_RightMotorState) == 0)) {
// Les moteurs sont déjà arrêtés
@@ -311,10 +333,15 @@ void MOTORS_HandlerTask(void *params) {
}
}
-/*
- * @brief Tache d'asservissement, périodique (10ms)
+/**
+ * @brief Control loop task
+ * Periodic task (3ms) for motor control loop
*
- * @param params non utilisé
+ * @remark This task is started by \ref MOTORS_HandlerTask when receiving a movement message
+ * but task kill by itself when movement has finished
+ *
+ * @param[in] params Initial task parameters
+ * @return None
*/
void MOTORS_ControlTask(void *params) {
TickType_t xLastWakeTime;
@@ -343,11 +370,11 @@ void MOTORS_ControlTask(void *params) {
* erreur est entre -32768 et 32767 selon la difference à apporter à la commande
*/
- leftError = MOTORS_LeftMotorState.set_point - leftEncoder;
- rightError = MOTORS_RightMotorState.set_point - rightEncoder;
+ leftError = MOTORS_LeftMotorState.setpoint - leftEncoder;
+ rightError = MOTORS_RightMotorState.setpoint - rightEncoder;
- if (((MOTORS_RightMotorState.set_point == 0)
- && (MOTORS_LeftMotorState.set_point == 0))
+ if (((MOTORS_RightMotorState.setpoint == 0)
+ && (MOTORS_LeftMotorState.setpoint == 0))
&& ((rightError == 0) && (leftError == 0))) {
MOTORS_PowerOff();
@@ -356,14 +383,14 @@ void MOTORS_ControlTask(void *params) {
vTaskSuspend(xHandleMotorsControl);
}
- if (MOTORS_LeftMotorState.set_point == 0)
+ if (MOTORS_LeftMotorState.setpoint == 0)
MOTORS_LeftMotorState.output = 0;
else {
if (leftError != 0) {
//locCmdG = (int32_t)MOTEURS_EtatMoteurGauche.commande + ((int32_t)MOTEUR_Kp*(int32_t)erreurG)/100;
locCmdG = ((int32_t) MOTOR_Kp * (int32_t) leftError) / 100;
- if (MOTORS_LeftMotorState.set_point >= 0) {
+ if (MOTORS_LeftMotorState.setpoint >= 0) {
if (locCmdG < 0)
MOTORS_LeftMotorState.output = 0;
else if (locCmdG > SHRT_MAX)
@@ -381,14 +408,14 @@ void MOTORS_ControlTask(void *params) {
}
}
- if (MOTORS_RightMotorState.set_point == 0)
+ if (MOTORS_RightMotorState.setpoint == 0)
MOTORS_RightMotorState.output = 0;
else {
if (rightError != 0) {
//locCmdD = (int32_t)MOTEURS_EtatMoteurDroit.commande + ((int32_t)MOTEUR_Kp*(int32_t)erreurD)/100;
locCmdD = ((int32_t) MOTOR_Kp * (int32_t) rightError) / 100;
- if (MOTORS_RightMotorState.set_point >= 0) {
+ if (MOTORS_RightMotorState.setpoint >= 0) {
if (locCmdD < 0)
MOTORS_RightMotorState.output = 0;
else if (locCmdD > SHRT_MAX)
@@ -416,13 +443,29 @@ void MOTORS_ControlTask(void *params) {
}
}
+/** Structure for encoder convertion
+ * The structure store a equivalent state point, associating a raw encoder value to a linearized corrected value
+ */
typedef struct {
- uint16_t encoder;
- uint16_t correction;
+ uint16_t encoder; /**< Raw encoder value*/
+ uint16_t correction; /**< Corrected, linearized value, equivalent to raw encoder*/
} MOTORS_CorrectionPoint;
+/**
+ * Number max of correction points for encoder
+ */
#define MOTORS_MAX_CORRECTION_POINTS 16
+/**
+ * Array of correction points, associating a raw encoder value and a linearized correction.
+ *
+ * Basically, encoders return delay between two signal edges. If motor is stopped, encoder return 65535 (\ref MOTORS_MAX_ENCODER).
+ * Then value tends towards zero as the motor accelerates. Resulting encoder output is not linear and
+ * reversed with respect to the setpoint.
+ *
+ * This table give several corresponding points, associating a raw, non linear and inverted encoder value to a linerized,
+ * corrected value that can be compared to setpoint
+ */
const MOTORS_CorrectionPoint MOTORS_CorrectionPoints[MOTORS_MAX_CORRECTION_POINTS] =
{ { MOTORS_MAX_ENCODER - 1, 1 }, { 42000, 100 }, { 22000, 2500 }, {
18000, 5000 }, { 16500, 7500 }, { 15500, 10000 },
@@ -432,11 +475,13 @@ const MOTORS_CorrectionPoint MOTORS_CorrectionPoints[MOTORS_MAX_CORRECTION_POINT
SHRT_MAX } // 32767
};
-/*
- * @brief Fonction de conversion des valeurs brutes de l'encodeur en valeur linearisées
+/**
+ * @brief Function for converting raw encoder values to linearized values
*
- * @param encodeur valeur brute de l'encodeur
- * @return valeur linéarisée (entre -32768 et 32767)
+ * @remark This function use \ref MOTORS_CorrectionPoints for its conversion
+ *
+ * @param[in] state Current state of a motor, including raw encoder value
+ * @return Linearized value, from -32768 (full backward) to 32767 (full forward)
*/
int16_t MOTORS_EncoderCorrection(MOTORS_MotorState state) {
int16_t correction = 0;
@@ -474,17 +519,17 @@ int16_t MOTORS_EncoderCorrection(MOTORS_MotorState state) {
/*
* Selon le sens de rotation du moteur (commande > 0 ou < 0), on corrige le signe du capteur
*/
- if (state.set_point < 0)
+ if (state.setpoint < 0)
correction = -correction;
return correction;
}
/**
- * @brief Function for initializing motors driver
+ * @brief Power off motor, disabling power regulator
*
* @param None
- * @retval None
+ * @return None
*/
void MOTORS_PowerOff(void) {
LL_TIM_DisableCounter(TIM3);
@@ -508,10 +553,10 @@ void MOTORS_PowerOff(void) {
}
/**
- * @brief Function for initializing motors driver
+ * @brief Power on motor, enabling power regulator
*
* @param None
- * @retval None
+ * @return None
*/
void MOTORS_PowerOn(void) {
LL_TIM_EnableCounter(TIM3);
@@ -535,16 +580,21 @@ void MOTORS_PowerOn(void) {
}
/**
- * @brief Active les encodeurs et le régulateur des moteur si nécessaire et
- * règle la commande du moteur (entre -MOTEURS_MAX_COMMANDE et +MOTEURS_MAX_COMMANDE)
- * On applique une "regle de 3"
- * pour SHRT_MAX -> MOTEURS_MAX_COMMANDE
- * pour 0 -> 0
- * pour une commande C dans l'interval [0 .. 32767], la commande est
- * commande = (C * MOTEURS_MAX_COMMANDE)/32767
+ * @brief Set command to motor
*
- * @param[in] cmdGauche blablabla
- * @param[in] cmdDroit blablabla
+ * This function drive motors directly. Values applied are output from regulation law.
+ * If power supply is not enabled (for motor and encoders), the function will enable it.
+ *
+ * Values provided are in the range [-SHRT_MAX; SHRT_MAX] and motor command must be
+ * in the range [-MOTORS_MAX_COMMAND et +MOTORS_MAX_COMMAND].
+ * The corresponding rule is used :
+ * - for SHRT_MAX -> MOTORS_MAX_COMMAND
+ * - for 0 -> 0
+ * - for a request R in range [0 .. SHRT_MAX], command = (R * MOTEURS_MAX_COMMANDE)/SHRT_MAX
+ *
+ * @param[in] leftMotor Request command for left motor
+ * @param[in] rightMotor Request command for right motor
+ * @return None
*/
void MOTORS_Set(int16_t leftMotor, int16_t rightMotor) {
int32_t leftValue, rightValue;
@@ -576,10 +626,15 @@ void MOTORS_Set(int16_t leftMotor, int16_t rightMotor) {
}
}
-/*
- * @brief Recupere les mesures brutes des encodeurs et les enregistre dans la structure moteur correspondante
+/**
+ * @brief Get raw values from encoders and store them in corresponding motor state
*
- * @param[in] htim pointeur sur la reference du timer qui generé l'interruption
+ * @remark Encoder values are in fact timer counting time between to encoder pulses
+ *
+ * Also, manage distance and turn counter used for overall motor control
+ *
+ * @param[in] htim Pointer to timer reference that trigger interrupt
+ * @return None
*/
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
if (htim->Instance == TIM21) { /* moteur gauche */
@@ -604,8 +659,8 @@ void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
else MOTORS_DiffState.distance++;
if (MOTORS_DiffState.distance==0) {
- MOTORS_LeftMotorState.set_point=0;
- MOTORS_RightMotorState.set_point=0;
+ MOTORS_LeftMotorState.setpoint=0;
+ MOTORS_RightMotorState.setpoint=0;
}
}
@@ -614,8 +669,8 @@ void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
else MOTORS_DiffState.turns++;
if (MOTORS_DiffState.turns==0) {
- MOTORS_LeftMotorState.set_point=0;
- MOTORS_RightMotorState.set_point=0;
+ MOTORS_LeftMotorState.setpoint=0;
+ MOTORS_RightMotorState.setpoint=0;
}
}
@@ -640,13 +695,15 @@ void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
}
}
-/*
- * @brief Gestionnaire d'interruption "overflow"
- * Lorsque deux interruptions "overflow" sont arrivées sans que l'interruption capture n'arrive,
- * cela signifie que le moteur est à l'arret.
- * On met la valeur de l'encodeur à MOTEURS_MAX_ENCODEUR
+/**
+ * @brief "overflow" interrupt handler
*
- * @param[in] htim pointeur sur la reference du timer qui generé l'interruption
+ * When two "overflow" interrupts occure without an encoder interrupt happened,
+ * this means motor is halted.
+ * So, we set encoder value to MOTEURS_MAX_ENCODEUR
+ *
+ * @param[in] htim Pointer to timer reference that trigger interrupt
+ * @return None
*/
void MOTORS_TimerEncodeurUpdate(TIM_HandleTypeDef *htim) {
if (htim->Instance == TIM21) { /* moteur gauche */
diff --git a/software/dumber3/Application/motors.h b/software/dumber3/Application/motors.h
index 62012f4..b8e7d8f 100644
--- a/software/dumber3/Application/motors.h
+++ b/software/dumber3/Application/motors.h
@@ -1,6 +1,6 @@
/**
******************************************************************************
- * @file motors.c
+ * @file motors.h
* @brief motors driver header
* @author S. DI MERCURIO (dimercur@insa-toulouse.fr)
* @date December 2023
diff --git a/software/dumber3/Application/panic.c b/software/dumber3/Application/panic.c
index 6d9eaf8..8f308a0 100644
--- a/software/dumber3/Application/panic.c
+++ b/software/dumber3/Application/panic.c
@@ -1,8 +1,31 @@
-/*
- * panic.c
+/**
+ ******************************************************************************
+ * @file panic.c
+ * @brief panic handler body
+ * @author S. DI MERCURIO (dimercur@insa-toulouse.fr)
+ * @date December 2023
*
- * Created on: Oct 11, 2023
- * Author: dimercur
+ ******************************************************************************
+ * @copyright Copyright 2023 INSA-GEI, Toulouse, France. All rights reserved.
+ * @copyright This project is released under the Lesser GNU Public License (LGPL-3.0-only).
+ *
+ * @copyright This file is part of "Dumber" project
+ *
+ * @copyright This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * @copyright This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * @copyright You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ ******************************************************************************
*/
#include "application.h"
@@ -11,8 +34,24 @@
#include "panic.h"
#include "leds.h"
+/** @addtogroup Application_Software
+ * @{
+ */
+
+/** @addtogroup PANIC
+ * Panic module handles non recoverable error and display an error message on leds
+ * @{
+ */
+
+/** @addtogroup PANIC_Private Private
+ * @{
+ */
+
void PANIC_StopTasksAndWait(void);
+
+/** @cond DOXYGEN_IGNORE_REF */
void MOTORS_PowerOff(void);
+/** @endcond */
extern TaskHandle_t xHandleLedsHandler;
extern TaskHandle_t xHandleLedsAction;
@@ -25,6 +64,14 @@ extern TaskHandle_t xHandleMotorsControl;
extern TaskHandle_t xHandleXbeeTXHandler;
extern TaskHandle_t xHandleXbeeRX;
+/**
+ * @brief Handle an unrecoverable error and display corresponding error on leds
+ *
+ * @param[in] panicId Panic error (as found in \ref PANIC_Typedef)
+ * @return None
+ *
+ * @remark This function will never return (as it calls \ref PANIC_StopTasksAndWait).
+ */
void PANIC_Raise(PANIC_Typedef panicId) {
switch (panicId) {
case panic_adc_err:
@@ -44,6 +91,17 @@ void PANIC_Raise(PANIC_Typedef panicId) {
PANIC_StopTasksAndWait();
}
+/**
+ * @brief Stop all task and stop system
+ *
+ * All tasks are stopped except led animation (otherwise animation will stop)
+ * and, at end, system enter power saving mode.
+ *
+ * @param None
+ * @return None
+ *
+ * @remark This function will never return (as it calls \ref PANIC_StopTasksAndWait).
+ */
void PANIC_StopTasksAndWait(void){
TaskHandle_t currentTask;
currentTask = xTaskGetCurrentTaskHandle();
@@ -92,3 +150,15 @@ void PANIC_StopTasksAndWait(void){
__WFE(); /* Attente infinie */
}
}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/software/dumber3/Application/panic.h b/software/dumber3/Application/panic.h
index 36366e2..da8a6f6 100644
--- a/software/dumber3/Application/panic.h
+++ b/software/dumber3/Application/panic.h
@@ -1,19 +1,67 @@
-/*
- * panic.h
+/**
+ ******************************************************************************
+ * @file panic.h
+ * @brief panic handler header
+ * @author S. DI MERCURIO (dimercur@insa-toulouse.fr)
+ * @date December 2023
*
- * Created on: Oct 11, 2023
- * Author: dimercur
+ ******************************************************************************
+ * @copyright Copyright 2023 INSA-GEI, Toulouse, France. All rights reserved.
+ * @copyright This project is released under the Lesser GNU Public License (LGPL-3.0-only).
+ *
+ * @copyright This file is part of "Dumber" project
+ *
+ * @copyright This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * @copyright This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * @copyright You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ ******************************************************************************
*/
#ifndef PANIC_H_
#define PANIC_H_
+/** @addtogroup Application_Software
+ * @{
+ */
+
+/** @addtogroup PANIC
+ * @{
+ */
+
+/** @addtogroup PANIC_Public Public
+ * @{
+ */
+
+/** Enumeration class defining possible panic sources */
typedef enum {
- panic_charger_err=1, // erreur 1
- panic_adc_err, // erreur 2
- panic_malloc // erreur 3
+ panic_charger_err=1, /**< error related to battery charging */
+ panic_adc_err, /**< error related to battery voltage conversion */
+ panic_malloc /**< memory allocation failed (memory exhausted) */
} PANIC_Typedef;
void PANIC_Raise(PANIC_Typedef panicId);
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
#endif /* PANIC_H_ */
diff --git a/software/dumber3/Application/xbee.c b/software/dumber3/Application/xbee.c
index c35e1d8..d52a8ba 100644
--- a/software/dumber3/Application/xbee.c
+++ b/software/dumber3/Application/xbee.c
@@ -1,10 +1,32 @@
-/*
- * xbee.c
+/**
+ ******************************************************************************
+ * @file xbee.c
+ * @brief xbee driver body
+ * @author S. DI MERCURIO (dimercur@insa-toulouse.fr)
+ * @date December 2023
*
- * Created on: Sep 12, 2022
- * Author: dimercur
- */
+ ******************************************************************************
+ * @copyright Copyright 2023 INSA-GEI, Toulouse, France. All rights reserved.
+ * @copyright This project is released under the Lesser GNU Public License (LGPL-3.0-only).
+ *
+ * @copyright This file is part of "Dumber" project
+ *
+ * @copyright This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * @copyright This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * @copyright You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ ******************************************************************************
+ */
#include "xbee.h"
#include "semphr.h"
@@ -12,17 +34,43 @@
#include
#include "stm32l0xx_ll_usart.h"
+/** @addtogroup Application_Software
+ * @{
+ */
+
+/** @addtogroup XBEE
+ * Xbee driver handles RF communications with supervisor
+ * @{
+ */
+
+/** @addtogroup XBEE_Private Private
+ * @{
+ */
+
extern UART_HandleTypeDef hlpuart1;
extern DMA_HandleTypeDef hdma_lpuart1_tx;
extern DMA_HandleTypeDef hdma_lpuart1_rx;
-/***** API2 escaped char *****/
+/**
+ * @anchor xbee_api2_escape_chars
+ * @name XBEE API2 Escape characters
+ * List of escaped characters, not used yet (transparent mode)
+ */
+///@{
#define XBEE_API_ESCAPE_CHAR 0x7D
#define XBEE_API_START_OF_FRAME 0x7E
#define XBEE_API_XON 0x11
#define XBEE_API_XOFF 0x13
+///@}
+/**
+ * @anchor xbee_ending_char
+ * @name XBEE command ending char
+ * Ending character used in protocol between supervisor and robot
+ */
+///@{
#define XBEE_ENDING_CHAR '\r'
+///@}
/***** TX part *****/
void XBEE_TxHandlerThread(void* params);
@@ -66,6 +114,12 @@ SemaphoreHandle_t xHandleSemaphoreTX = NULL;
StaticSemaphore_t xSemaphoreTX;
//StaticSemaphore_t xSemaphoreTX_ACK;
+/**
+ * @brief Function for initializing xbee system
+ *
+ * @param None
+ * @return None
+ */
void XBEE_Init(void) {
xHandleSemaphoreTX = xSemaphoreCreateBinaryStatic( &xSemaphoreTX );
//xHandleSemaphoreTX_ACK = xSemaphoreCreateBinaryStatic( &xSemaphoreTX_ACK );
@@ -103,7 +157,13 @@ void XBEE_Init(void) {
/**** Support functions ****/
/**** TX Part *****/
-
+/**
+ * @brief Handler task for message to transmit (send to supervisor)
+ * Manage XBEE mailbox and send messages
+ *
+ * @param[in] params Initial task parameters
+ * @return None
+ */
void XBEE_TxHandlerThread(void* params) {
MESSAGE_Typedef msg;
@@ -119,12 +179,19 @@ void XBEE_TxHandlerThread(void* params) {
}
/**
- * Send data. Create a transmission frame, add escape char to data and send it over UART
+ * @brief Send data.
*
- * \param data raw data to send
- * \return status of decoding: XBEE_OK if decoding is successful,
- * XBEE_TX_ERROR in case of sending error,
- * XBEE_TX_TIMEOUT in case semaphore takes too long
+ * Create a transmission frame, add escape char to data and send it over UART
+ *
+ * @remark Function is non blocking unless another transmission is still in progress
+ *
+ * @todo Change return status type from "int" to "\ref XBEE_Status"
+ *
+ * @param[in] data reference to raw data to send
+ * @return status of decoding (see \ref XBEE_Status)
+ * - XBEE_OK if decoding is successful,
+ * - XBEE_TX_ERROR in case of sending error,
+ * - XBEE_TX_TIMEOUT in case semaphore takes too long
*/
int XBEE_SendData(char* data) {
BaseType_t state;
@@ -157,6 +224,15 @@ int XBEE_SendData(char* data) {
return status;
}
+/**
+ * @brief Transmission interrupt handler
+ *
+ * This ISR is called when USART transmit register is empty, ready for a new char to be sent
+ * A Semaphore is used to signal end of transmission to \ref XBEE_SendData function
+ *
+ * @param None
+ * @return None
+ */
void XBEE_TX_IRQHandler(void) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
@@ -181,9 +257,12 @@ void XBEE_TX_IRQHandler(void) {
/***** Rx Part *****/
/**
- * Reception thread. Wait for incoming frame, process it and send message to application
+ * @brief Handler task for message reception (received from supervisor)
*
- * \param params not used
+ * Wait for incoming message and send them to application mailbox
+ *
+ * @param[in] params Initial task parameters
+ * @return None
*/
void XBEE_RxThread(void* params) {
char* incomingData;
@@ -213,6 +292,15 @@ void XBEE_RxThread(void* params) {
}
}
+/**
+ * @brief Reception interrupt handler
+ *
+ * This ISR is called when USART reception register is full, containing a newly received char
+ * A Semaphore is used to signal end of frame reception to \ref XBEE_RxThread function
+ *
+ * @param None
+ * @return None
+ */
void XBEE_RX_IRQHandler(void) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
uint8_t data;
@@ -243,9 +331,10 @@ void XBEE_RX_IRQHandler(void) {
}
/**
- * DMA IRQ handler for reception. Receive a complete frame send send event to sending frame in case of acknowledge frame or to receive task otherwise
+ * @brief IRQ handler for UART.
+ *
+ * Dispatch IRQ event to transmission ISR (\ref XBEE_TX_IRQHandler), reception ISR (\ref XBEE_RX_IRQHandler) or clear errors flags
*
- * \param UartHandle not used
*/
void LPUART1_IRQHandler(void) {
@@ -268,3 +357,16 @@ void LPUART1_IRQHandler(void) {
}
}
}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
diff --git a/software/dumber3/Application/xbee.h b/software/dumber3/Application/xbee.h
index feee3a6..dc92f72 100644
--- a/software/dumber3/Application/xbee.h
+++ b/software/dumber3/Application/xbee.h
@@ -1,8 +1,31 @@
-/*
- * xbee.h
+/**
+ ******************************************************************************
+ * @file xbee.h
+ * @brief xbee driver header
+ * @author S. DI MERCURIO (dimercur@insa-toulouse.fr)
+ * @date December 2023
*
- * Created on: Sep 12, 2022
- * Author: dimercur
+ ******************************************************************************
+ * @copyright Copyright 2023 INSA-GEI, Toulouse, France. All rights reserved.
+ * @copyright This project is released under the Lesser GNU Public License (LGPL-3.0-only).
+ *
+ * @copyright This file is part of "Dumber" project
+ *
+ * @copyright This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * @copyright This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * @copyright You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ ******************************************************************************
*/
#ifndef INC_XBEE_H_
@@ -10,17 +33,36 @@
#include "application.h"
+/** @addtogroup Application_Software
+ * @{
+ */
+
+/** @addtogroup XBEE
+ * @{
+ */
+
+/** @addtogroup XBEE_Public Public
+ * @{
+ */
+
+/** Enumeration class defining status code (only used by \ref XBEE_SendData)*/
typedef enum {
- XBEE_OK=0,
- XBEE_CONFIG_ERROR=-1,
- XBEE_TX_ACK_ERROR=-2,
- XBEE_RX_TIMEOUT=-3,
- XBEE_RX_ERROR=-4,
- XBEE_TX_ERROR=-5,
- XBEE_INVALID_FRAME=-6,
- XBEE_TX_TIMEOUT=-7,
+ XBEE_OK=0, /**< Function is successful */
+ XBEE_CONFIG_ERROR=-1, /**< Configuration of XBEE gets an error (not used) */
+ XBEE_TX_ACK_ERROR=-2, /**< Tx transmission doesn't received acknowledgment (not used in transparent mode) */
+ XBEE_RX_TIMEOUT=-3, /**< Rx frame doesn't complete in time (not used in transparent mode) */
+ XBEE_RX_ERROR=-4, /**< Rx frame error while receiving (not used in transparent mode) */
+ XBEE_TX_ERROR=-5, /**< Tx frame error while sending */
+ XBEE_INVALID_FRAME=-6, /**< Rx frame is invalid (not used in transparent mode) */
+ XBEE_TX_TIMEOUT=-7, /**< Tx frame not sent in time */
} XBEE_Status;
+/**
+ * @anchor xbee_frame_type
+ * @name XBEE API mode frame type
+ * List of message frame used in API mode (not used now)
+ */
+///@{
#define XBEE_RX_PACKET_TYPE 0x90
#define XBEE_RX_EXPLICIT_TYPE 0x91
#define XBEE_TX_STATUS_TYPE 0x89
@@ -51,16 +93,30 @@ typedef enum {
#define XBEE_RX_OPTIONS_PAN_BROADCASTED 0x04
#define XBEE_FRAME_SOF_CHAR 0x7E // '~'
+///@}
+/** Structure class defining received frame (only for API mode, not used now)*/
typedef struct {
- uint8_t type;
- uint16_t source_addr;
- uint8_t length;
- char ack;
- char modem_status;
- char data[];
+ uint8_t type; /**< Frame type (see \ref xbee_frame_type "XBEE API mode frame type") */
+ uint16_t source_addr; /**< Address of sender */
+ uint8_t length; /**< Length of data part */
+ char ack; /**< ?? */
+ char modem_status; /**< ?? */
+ char data[]; /**< Data buffer */
} XBEE_INCOMING_FRAME;
void XBEE_Init(void);
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
#endif /* INC_XBEE_H_ */
diff --git a/software/dumber3/Doxyfile b/software/dumber3/Doxyfile
index d915477..914cf02 100644
--- a/software/dumber3/Doxyfile
+++ b/software/dumber3/Doxyfile
@@ -996,13 +996,14 @@ RECURSIVE = YES
# Note that relative paths are relative to the directory from which doxygen is
# run.
-EXCLUDE = /home/dimercur/Documents/Travail/Depots-Git/dumber/software/dumber3/Drivers \
- /home/dimercur/Documents/Travail/Depots-Git/dumber/software/dumber3/Tests \
- /home/dimercur/Documents/Travail/Depots-Git/dumber/software/dumber3/TestsPlans \
- /home/dimercur/Documents/Travail/Depots-Git/dumber/software/dumber3/Debug \
- /home/dimercur/Documents/Travail/Depots-Git/dumber/software/dumber3/Release \
- /home/dimercur/Documents/Travail/Depots-Git/dumber/software/dumber3/workspace \
- Middlewares
+EXCLUDE = Drivers \
+ Tests \
+ TestsPlans \
+ Debug \
+ Release \
+ workspace \
+ Middlewares \
+ Application/Xbee-API
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
diff --git a/software/dumber3/Dumber3 Debug.cfg b/software/dumber3/Dumber3 Debug.cfg
new file mode 100644
index 0000000..2fca4be
--- /dev/null
+++ b/software/dumber3/Dumber3 Debug.cfg
@@ -0,0 +1,44 @@
+# This is an genericBoard board with a single STM32L071CBTx chip
+#
+# Generated by STM32CubeIDE
+# Take care that such file, as generated, may be overridden without any early notice. Please have a look to debug launch configuration setup(s)
+
+source [find interface/stlink-dap.cfg]
+
+
+set WORKAREASIZE 0x5000
+
+transport select "dapdirect_swd"
+
+set CHIPNAME STM32L071CBTx
+set BOARDNAME genericBoard
+
+# Enable debug when in low power modes
+set ENABLE_LOW_POWER 1
+
+# Stop Watchdog counters when halt
+set STOP_WATCHDOG 1
+
+# STlink Debug clock frequency
+set CLOCK_FREQ 8000
+
+# Reset configuration
+# use hardware reset, connect under reset
+# connect_assert_srst needed if low power mode application running (WFI...)
+reset_config srst_only srst_nogate connect_assert_srst
+set CONNECT_UNDER_RESET 1
+set CORE_RESET 0
+
+# ACCESS PORT NUMBER
+set AP_NUM 0
+# GDB PORT
+set GDB_PORT 3333
+
+
+
+
+
+# BCTM CPU variables
+
+source [find target/stm32l0x.cfg]
+
diff --git a/software/dumber3/Dumber3 Debug.launch b/software/dumber3/Dumber3 Debug.launch
index ec8e61b..d7cc674 100644
--- a/software/dumber3/Dumber3 Debug.launch
+++ b/software/dumber3/Dumber3 Debug.launch
@@ -1,5 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -20,11 +35,25 @@
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -32,7 +61,7 @@
-
+
@@ -41,7 +70,7 @@
-
+
@@ -51,9 +80,9 @@
-
+
-
+