cmsis car
TLDR -> Source Code
My Nucleo car in C++ CMSIS
This project had the goal to drive the nucleo car with the following challenges.
using 2 servos (using pwm) pid controller (distance control) ultra sonic distance sensing (using i2c) MCP (manual control pannel) uart control
de intent behind this project is to learn CMSIS level programming on Arm Cortex cores. this was done as part of my HBO-ICT tech embedded systems developer. it continuously drives forward until it detects a obstacle with the distance sensor.
class diagram
all diagrams can be found here (github also allows you to zoom in on each diagram)
classDiagram class CarSystem { <<active>> +CarSystem(osMessageQueueId_t id, IDistanceSensor& sensor, ManualControlPanel& MCP, MotorController& controller) +Setup() bool +Update() -osMessageQueueId_t queueId //distance queueId -SensorMsgData data } class MotorController { <<active>> +MotorController(osMessageQueueId_t id, uint8_t minDist, IMotor& leftMotor, IMotor& rightMotor, IFeedbackSensor& leftSense, IFeedbackSensor& rightSense) +Setup() +Loop() +SetSpeed(uint16_t speed) +SetDistance(uint8_t distance) -osMessageQueueId_t queueId -uint8_t minDetectDistance -IMotor* motorLeft -IMotor* motorRight -IFeedbackSensor* senseLeft -IFeedbackSensor* senseRight -Pid pid } class IMotor { +Setup() bool +IsReversed() bool +SetSpeed(int8_t value) } class ServoMotor { +ServoMotor(NucleoPin pinMotor, HardwareTimer& timer, uint8_t ccChannelNum, bool reversed) -NucleoPin motorInputPin -HardwareTimer tim -bool isReversed -uint8_t ccrChannel -uint8_t maxSetSpeed = 100 -uint8_t servoIdleValue = 1500 } class ManualControlPanel { <<active>> +ManualControlPanel(osMessageQueueId_t btnId, IButton& btn0, IButton& btn1) +Setup() +Loop() +SetPid(Pid& p) -HandleSelectedBtn(BtnMsgData data) -CallBtnAction(BtnMsgData data, IButton btn) -osMessageQueueId_t queueId -IButton but1 -IButton but2 -Pid* pid } class IBtnIRQ { +HandleIRQ() +SetupIrq() } class IButton { +shortPress() action +LongPress() action } class Button { +Button(NucleoPin inputPin, IRQn_Type irq, osMessageQueueId_t id, Action actionShort, Action actionLong) -NucleoPin btnPin -osMessageQueueId_t id -IRQn_Type irq -volatile bool triggered -volatile uint32_t startTime -volatile BtnMsgData data -Action shortPressCallback -Action longPressCallback } class IDistanceSensor { +GetDistance() uint8_t } class HC_SR04_DistSensor { +HC_SR04_DistSensor(NucleoPin& echo, NucleoPin& trigger, HardwareTimer tim) +Setup(uint32_t prescaler, uint32_t arrValue, uint32_t outputCCValue, const uint8_t outputChannel, const uint8_t inputChannel1, const uint8_t inputChannel2) bool -NucleoPin* echoPin -NucleoPin* triggerPin -HardwareTimer timer } class Pid { +PID(int16_t min, int16_t max, float kp = 8.1f, float ki = 10.71428571f, float kd = 1.5309f) +Calculate(float target, float lastTarget) int16_t +ResetValues() void +updateKP(float val) void +updateKI(float val) void +updateKD(float val) void +GetKP() float +GetKI() float +GetKD() float -int16_t min -int16_t max -float tau -int16_t error -int16_t prevError -int16_t prevMeasurement -float timeSec -float proportionalOut -float integratorOut -float differentiatorOut -float output -float kp -float ki -float kd -float defaultKp -float defaultKi -float defaultKd } class IFeedbackSensor { +Setup() bool +Update() +GetSpeed() float } class FeedbackSensor { +FeedbackSensor(NucleoPin& inputSignal, HardwareTimer timer) -CalcDeg(int32_t curDuty) int32_t -CalcRpm(float delta, int32_t time) float -NucleoPin InputSignalPin -float speed -float delta -uint32_t curTime -uint32_t curDuty -uint32_t angleCur -uint32_t angleLast } class PinMode { <<enum>> digital_input digital_input_pullup digital_output altMode } class NucleoPin { +NucleoPin(GpioTypedef* block, uint8_t pinNr, PinMode mode) +NucleoPin(GPIO_TypeDef* block, uint8_t pinNr, AltModeValue val) +SetAltMode(AltModeValue value) +Setup() bool +Write() +Read() bool +GetPinNr() uint8_t +GetPinBlock() GPIO_TypeDef* -GpioTypedef block -uint8_t pin -PinMode mode } class AltModeValue { uint64_t value; uint32_t low; uint32_t high; } class HardwareTimer { +HardwareTimer(TIM_TypeDef* timer); +Init(uint32_t prescaler, uint32_t arrValue, uint32_t outputCCValue, const uint8_t outputChannel, const uint8_t inputChannel1, const uint8_t inputChannel2) bool +SetTimerEnable() void +SetPrescaler(const uint8_t prescalerDivider) void +SetEnablePeripheralClock() void +SetEnableCCModex(const uint8_t channel, const uint8_t ccxs, const uint8_t ocxm) void +SetEnableCCx(const uint8_t channel, const uint8_t ccxe, const uint8_t ccxp, const uint8_t ccxnp) void +SetCCRxRegister(const uint32_t CCRvalue, const uint8_t registerNo) void +SetAutoReload(const uint32_t ARRvalue) void +SetSlaveModeResetFP1() void +GetCaptureCompareRegister1() uint32_t +GetCaptureCompareRegister2() uint32_t +GetCaptureCompareRegister3() uint32_t +GetCaptureCompareRegister4() uint32_t +GetTimerCount() uint32_t -TIM_TypeDef* timer; } class BtnMsgData { +int butNr +int duration } class SensorMsgData { +uint8_t distance } ManualControlPanel o-- BtnMsgData BtnMsgData --o Button CarSystem o-- MotorController NucleoPin o-- AltModeValue CarSystem o-- ManualControlPanel ManualControlPanel o-- "2" IButton IBtnIRQ <|.. IButton IButton <|.. Button CarSystem o-- SensorMsgData MotorController o-- "2" IMotor MotorController o-- "2" IFeedbackSensor MotorController o-- Pid MotorController o-- SensorMsgData IMotor <|.. ServoMotor CarSystem o-- IDistanceSensor IDistanceSensor <|.. HC_SR04_DistSensor IFeedbackSensor <|.. FeedbackSensor HC_SR04_DistSensor o-- NucleoPin FeedbackSensor o-- NucleoPin ServoMotor o-- NucleoPin Button o-- NucleoPin NucleoPin o-- PinMode FeedbackSensor o-- HardwareTimer HC_SR04_DistSensor o-- HardwareTimer ServoMotor o-- HardwareTimer