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.

page-gif

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