Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FastPWM mbed FastIO MODSERIAL
main.cpp
- Committer:
- dzoni
- Date:
- 2018-03-28
- Revision:
- 9:486eeba3950f
- Parent:
- 8:5ce5fe1ce503
- Child:
- 10:c28d133a1408
File content as of revision 9:486eeba3950f:
/**
* @brief Basic DC motor control test, rpm feedback by simple impulse signal, PID speed control.
* @file main.cpp
* @author Jan Tetour <jan.tetour@gmail.com>
*
* Test application for STM32F4 for small DC motor control. Main specifications:
* - DC motor controlled by PWM
* - Motor driver used L298N
* - RPM evaluated via simple impulse sensor
* - Speed (RPM) controlled by PID controller
*/
#include "mbed.h"
#include "FastPWM.h"
#include "FastIO.h"
#include "PID.h"
// Define MODSERIAL buffer sizes
#define MODSERIAL_DEFAULT_RX_BUFFER_SIZE 16
#define MODSERIAL_DEFAULT_TX_BUFFER_SIZE 64
#include "MODSERIAL.h"
// Pin defintions
#define IMPULSE_SENSOR_R_PIN (PA_9)
#define PWM_OUT_R_PIN (PA_6)
// Serial port definitions
MODSERIAL pcLink(SERIAL_TX, SERIAL_RX);
// Tasks timming definitions
static const us_timestamp_t periodImpSens = 125000; // 125 msec
static const us_timestamp_t periodLEDBlink = 100000; // 100 msec
static const us_timestamp_t periodPWMWrite = 250000; // 250 msec
static const us_timestamp_t periodRPMSetpoint = 10000000; // 10 sec
static us_timestamp_t tStampImpSens = 0;
static us_timestamp_t tStampLEDBlink = 0;
static us_timestamp_t tStampPWMWrite = 0;
static us_timestamp_t tStampRPMSetpoint = 0;
static us_timestamp_t tStamp = 0;
static Timer myTimer;
// RPM Sensor module level variables
static unsigned int uiImpSens = 0U;
static unsigned int uiImpSensTemp = 0U;
static int iImpSensLastState = 0;
// PWM Generator module level variables
static float fPwmDuty = 0.0f;
// RPM Controller module level variables
static float fRPMSetpoint = 0.0f;
// LOCAL MODULE VARIABLES
// I/O pins related
FastPWM mypwm(PWM_OUT_R_PIN);
FastIn<IMPULSE_SENSOR_R_PIN> pinImpulseSensorIn;
FastIn<USER_BUTTON> pinUserButtonIn;
DigitalOut myled(LED1);
// Controllers
PID pid_RPM_Right_motor(1.0f, 0.0f, 0.0f, (((float)periodPWMWrite)/1000000.0f));
// LOCAL FUNCTION DECLARATIONS
// Task worker functions
static void tskImpSens(void);
static void tskLEDBlink(void);
static void tskPWMWrite(void);
static void tskRPMSetpoint(void);
static void tskBackground(void);
// Inititalization
static void setup(void);
// Task management functions
static inline void DO_TASK(us_timestamp_t tskPeriod, us_timestamp_t &tskTimer, us_timestamp_t timeStamp, void (*tskFunction)(void))
{
if (tskPeriod < (timeStamp - tskTimer))
{
tskTimer = timeStamp;
(*tskFunction)();
}
}
static inline void BACKGROUND(void (*tskFunction)(void))
{
(*tskFunction)();
}
// Main function definition
int main(void)
{
setup();
while(1)
{
tStamp = myTimer.read_high_resolution_us();
DO_TASK(periodLEDBlink, tStampLEDBlink, tStamp, &tskLEDBlink);
DO_TASK(periodPWMWrite, tStampPWMWrite, tStamp, &tskPWMWrite);
DO_TASK(periodImpSens, tStampImpSens, tStamp, &tskImpSens);
DO_TASK(periodRPMSetpoint, tStampRPMSetpoint, tStamp, &tskRPMSetpoint);
BACKGROUND(&tskBackground);
}
}
// LOCAL MODULE DEFINITIONS
// Initialization
void setup(void)
{
pcLink.baud(115200);
pcLink.format(8, SerialBase::None, 1);
mypwm.period_us(2000);
mypwm.write(0.5);
myTimer.start();
//Analog input from 0.0 to 100.0 impulses per measurement period
pid_RPM_Right_motor.setInputLimits(0.0f, 100.0f);
//Pwm output from 0.0 to 1.0
pid_RPM_Right_motor.setOutputLimits(0.0f, 1.0f);
//If there's a bias.
pid_RPM_Right_motor.setBias(0.0f);
pid_RPM_Right_motor.setMode(AUTO_MODE);
//We want the process variable to be 0.0 RPM
pid_RPM_Right_motor.setSetPoint(0.0f);
}
// Task worker functions definitions
/**
* @brief RPM calculation.
* @note Needs refactoring to implement #ifdef for 2 different implementation (with/without PID).
*
* Stores impulse count per measurement period and clears impulse counter.
*/
void tskImpSens(void)
{
uiImpSens = uiImpSensTemp;
uiImpSensTemp = 0U;
// pcLink.printf("IMP: %u imp. \r", uiImpSens);
}
/**
* @brief User LED flashing.
*
* Implements User LED flashing.
*/
void tskLEDBlink(void)
{
myled = !myled;
}
/**
* @brief Writes new duty cycle value into PWM generator.
* @note Needs refactoring to implement #ifdef for 2 different implementation (with/without PID).
* @warning Not finished.
*
* Calculates new dyty cycle and writes the value into PWM generator.
*/
void tskPWMWrite(void)
{
// fPwmDuty = fPwmDuty + 0.1;
// if (1.0 < fPwmDuty)
// {
// fPwmDuty = 0.0;
// }
//Update the process variable.
pid_RPM_Right_motor.setProcessValue((float)uiImpSens);
//Set the new output.
fPwmDuty = pid_RPM_Right_motor.compute();
mypwm.write(fPwmDuty);
pcLink.printf("PWM: %.2f %%\tIMP: %u imp.\tSET: %.2f imp.\t\r", mypwm.read() * 100, uiImpSens, fRPMSetpoint);
// pcLink.printf("\r\nPWM: %.2f %% \r\n", mypwm.read() * 100);
}
/**
* @brief Implementation of periodic change of RPM Setpoint. Simulates setpoint changes to asses dynamic behaviour.
* @note For test purposes.
*
* Increases Setpoint value step by step with every invocation.
*/
void tskRPMSetpoint(void)
{
fRPMSetpoint += 10.0f;
if (100.0f < fRPMSetpoint)
{
fRPMSetpoint = 0.0f;
}
pid_RPM_Right_motor.setSetPoint(fRPMSetpoint);
}
/**
* @brief Implementation of background task. Periodically called from main loop without delay.
* @note These actions are candidates for refactoring to event based implementation.
* @warning Initial implementation. Simple and easy.
*
* This function implements actions, which needs to be processed with high priority.
* Is intended to be called in every pass of main loop.
*/
void tskBackground(void)
{
// Impulse sensor - pulse counting
int iTemp = pinImpulseSensorIn.read();
if (iTemp != iImpSensLastState)
{
iImpSensLastState = iTemp;
uiImpSensTemp++;
}
}