Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FWT-7 I'll VCing U in court. #2

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,11 @@ add_library(${PROJECT_NAME} STATIC)

# Add sources
target_sources(${PROJECT_NAME} PRIVATE
src/dev/LED.cpp
src/VCU.cpp
src/dev/PowertrainCAN.cpp
src/models/Hardmon_Model.cpp
src/models/MCuC_Model.cpp
src/MCUC.cpp
src/Hardmon.cpp
)

###############################################################################
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

## Introduction
The Vehicle Control Unit is responsible for controlling and error-checking almost the entire bike. It acts as a bridge
between the powertrain CAN and the accessory CAN. It will have two STMs, a main one and one that exists just for error
handling. It will communicate with pretty much every board on the bike in order to make sure they are in good working
order and tell them what to do. It will run a Simulink model to handle all the application-level logic for controlling the bike.
It will primarily take input from the Handlebar Interface Board and use them to decide a torque to send to the
motor controller. It will also command the LVSS in order to the bike through its boot-up and shutdown procedures.
between the powertrain CAN and the accessory CAN. It will have two STMs, a main one (MCUC) and one that exists just for
error handling (Hardmon). It will communicate with pretty much every board on the bike in order to make sure they are in
good working order and tell them what to do. It will run a Simulink model to handle all the application-level logic for
controlling the bike. It will primarily take input from the Handlebar Interface Board and use them to decide a torque to
send to the motor controller. It will also command the LVSS in order to the bike through its boot-up and shutdown procedures.
Binary file added Schematics/HardMonPinout.png
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move these to a folder called datasheets/. This isn't a perfect solution, but it's better than having a unique folder like this

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Schematics/MCUCpinout.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
230 changes: 230 additions & 0 deletions include/Hardmon.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
#ifndef VCU_HARDMON_HPP
#define VCU_HARDMON_HPP

#include <EVT/io/CAN.hpp>
#include <EVT/io/CANDevice.hpp>
#include <EVT/io/CANOpenMacros.hpp>
#include <EVT/io/GPIO.hpp>
#include <EVT/io/pin.hpp>
#include <EVT/io/types/CANMessage.hpp>
#include <dev/PowertrainCAN.hpp>
#include <models/Hardmon_Model.hpp>

namespace IO = EVT::core::IO;

namespace VCU {

/**
* Driver for the Hardware Monitor
*/

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

class Hardmon : public CANDevice {
public:
/**
* Struct that contains all the GPIOs that an instance of this class requires.
*/
struct reqGPIO {
//model input pins
IO::GPIO& ignitionCheckGPIO;
IO::GPIO& ignition3V3GPIO;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are there two ignition GPIOs? Is one of them for self test?

IO::GPIO& lvssStatus3V3GPIO;
IO::GPIO& mcStatusGPIO;

IO::GPIO& ucStateZeroGPIO;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An array of GPIOs would be better here

IO::GPIO& ucStateOneGPIO;
IO::GPIO& ucStateTwoGPIO;
IO::GPIO& ucStateThreeGPIO;

IO::GPIO& eStopCheckGPIO;
IO::GPIO& watchdogGPIO;
IO::GPIO& eStop3V3GPIO;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, why duplicates?


//model outputs pins
IO::GPIO& lvssEnableOverrideGPIO;
IO::GPIO& mcToggleNegativeGPIO;
IO::GPIO& mcTogglePositiveGPIO;
IO::GPIO& mcToggleOverrideGPIO;
IO::GPIO& ucResetGPIO;
IO::GPIO& lvssEnableHardmonGPIO;
IO::GPIO& hmFaultGPIO;
};

/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The double asterisk indicates this is a comment you want Doxygen to pick up. Here, the comment is meant to help understand the code but likely not for Doxygen

Suggested change
/**
/*

* Hardmon Pinout
*/

/** UART Pins */

/** UART TX pin */
static constexpr IO::Pin UART_TX_PIN = IO::Pin::PA_0;
/** UART RX pin */
static constexpr IO::Pin UART_RX_PIN = IO::Pin::PA_1;

/** LVSS Enable Pin */
static constexpr IO::Pin LVSS_EN_PIN = IO::Pin::PA_8;
/** LVSS Enable Override Pin */
static constexpr IO::Pin LVSS_EN_OVERRIDE_PIN = IO::Pin::PC_9;
/** LVSS Status Pin */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of putting this documentation on the constexprs, can you put it on the pins in the struct? Also, can you move this up to the top of the class? Most of the time, people are going to skip over this, so it would be nice if it was out of the way

static constexpr IO::Pin LVSS_STATUS_3V3_Pin = IO::Pin::PC_11;

/** MicroController State Pins */
static constexpr IO::Pin UC_STATE_ZERO_PIN = IO::Pin::PA_9;
static constexpr IO::Pin UC_STATE_ONE_PIN = IO::Pin::PA_15;
static constexpr IO::Pin UC_STATE_TWO_PIN = IO::Pin::PC_2;
static constexpr IO::Pin UC_STATE_THREE_PIN = IO::Pin::PC_10;
/** Microcontroller Fault Status Pin */
static constexpr IO::Pin UC_FAULT_PIN = IO::Pin::PC_1;

/** Motor Controller Status Pin */
static constexpr IO::Pin MOTOR_CONTROLLER_STATUS_PIN = IO::Pin::PA_10;
/** Motor Controller Toggle Negative Pin */
static constexpr IO::Pin MOTOR_CONTROLLER_TOGGLE_NEG_PIN = IO::Pin::PC_6;
/** Motor Controler Toggle Positive Pin */
static constexpr IO::Pin MOTOR_CONTROLLER_TOGGLE_POS_PIN = IO::Pin::PC_7;
/** Motor Controller Toggle Override Pin */
static constexpr IO::Pin MOTOR_CONTROLLER_TOGGLE_OVERRIDE_PIN = IO::Pin::PC_8;

/** Accessory CAN RX Pin */
static constexpr IO::Pin ACCESSORY_CAN_RX_PIN = IO::Pin::PA_11;
/** Accessory CAN TX Pin */
static constexpr IO::Pin ACCESSORY_CAN_TX_PIN = IO::Pin::PA_12;

/** Powertrain Network CAN RX Pin */
static constexpr IO::Pin POWERTRAIN_CAN_RX_PIN = IO::Pin::PB_12;
/** Powertrain Network CAN TX Pin */
static constexpr IO::Pin POWERTRAIN_CAN_TX_PIN = IO::Pin::PB_13;

/** Watchdog Pin */
static constexpr IO::Pin WATCHDOG_PIN = IO::Pin::PB_4;
/** Hardmon Fault Pin */
static constexpr IO::Pin HM_FAULT_PIN = IO::Pin::PB_5;

/** Ignition "12v" Pin */
static constexpr IO::Pin IGNITION_CHECK_PIN = IO::Pin::PB_6;
/** Ignition 3V3 Pin */
static constexpr IO::Pin IGNITION_3V3_PIN = IO::Pin::PC_12;

/** Estop "12v" Pin */
static constexpr IO::Pin ESTOP_CHECK_PIN = IO::Pin::PB_7;
/** Estop 3V3 Pin */
static constexpr IO::Pin ESTOP_3V3_PIN = IO::Pin::PD_2;

/** MicroController Reset Pin */
static constexpr IO::Pin UC_RESET_PIN = IO::Pin::PB_8;
/** CAN Selftest Pin */
static constexpr IO::Pin CAN_SELFTEST_PIN = IO::Pin::PB_9;
/** MCUC CAN Override Pin */
static constexpr IO::Pin CAN_OVERRIDE_PIN = IO::Pin::PC_13;

/**
* Constructor for Hardmon object
*/
Hardmon(reqGPIO gpios, IO::CAN& ptCAN);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should discuss with the VCU team about creating a consistent naming scheme here: is the correct adjective powertrain or motor controller?


/**
* Get a pointer to the start of the object dictionary
*
* @return Pointer to the start of the object dictionary
*/
CO_OBJ_T* getObjectDictionary() override;

/**
* Get the number of elements in the object dictionary.
*
* @return The number of elements in the object dictionary
*/
uint8_t getNumElements() override;

/**
* Handles the passed in Powertrain CAN message.
*
* @param message message to handle
*/
void handlePowertrainCanMessage(IO::CANMessage& message);

/**
* Get the device's node ID
*
* @return The node ID of the can device.
*/
uint8_t getNodeID() override;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put the overrides together. Also, I think it inherits the docs, so you don't have to copy the documentation here, but I'm not certain


/**
* Returns a pointer to the queue for Powertrain CANopen messages
* @return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finish this documentation

*/
EVT::core::types::FixedQueue<POWERTRAIN_QUEUE_SIZE, IO::CANMessage>* getPowertrainQueue();

void process();

private:
/**
* Local instance of PowertrainCan (handles PowertrainCAN messages
*/
DEV::PowertrainCAN powertrainCAN;

/**
* The model that is determining our control flow
* Automatically constructed here (not to be passed in)
*/
Hardmon_Model model;

//TODO: ask EEs about initial values (i.e. if they should be 0 or whatever)

//Model input data

bool forwardEnable;///< CAN (HIB): handlebar forward enable
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is our standard for documenting this kind of thing

Suggested change
bool forwardEnable;///< CAN (HIB): handlebar forward enable
/** CAN (HIB): handlebar forward enable */
bool forwardEnable;

bool ignitionCheck;///< GPIO: whether the ignition is on or off on 12v line
bool ignition3v3; ///< GPIO: whether the ignition is on or off on 3.3v line
bool lvssStatus; ///< GPIO: whether the lvss is on or not
bool mcStatus; ///< GPIO: whether the Motor Controller is on or off
bool ucState[4]; ///< CAN (MC): what state the microcontroller is in
bool eStopCheck; ///< GPIO: whether the estop is on or off on 12v line
uint8_t discharge; ///< CAN (MC): current state of the Motor Controller's discharge state machine
bool watchdog; ///< GPIO: alternating on and off signal from the MCUC to the Hardmon
bool eStop3v3; ///< GPIO: whether the estop is on or off on 3.3v line
bool lvssEnableUC; ///< GPIO: whether or not the MCUC is telling the LVSS to be enabled

//Model output data

bool mcSwitchEnable; ///< GPIO: whether or not the Hardmon is taking over mcEnable control from the MCUC
bool lvssSwitchEnable; ///< GPIO: whether or not the Hardmon is taking over lvssEnable control from the MCUC
bool inverterDischarge;///< CAN (MC): whether or not the Motor Controller is commanded to discharge
bool mcToggleNeg; ///< GPIO: Together with MCTogglePos commands the Motor Controller being on or not
bool mcTogglePos; ///< GPIO: Together with MCToggleNeg commands the Motor Controller being on or not
bool ucReset; ///< GPIO: Whether or not the Hardmon is commanding the MCUC to reset (0 = reset)
bool lvssEnableHardMon;///< GPIO: Whether or not the Hardmon is commanding the LVSS to be enabled
bool hmFault; ///< GPIO: Whether or not the Hardmon is commanding the MCUC to go into a fault state
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having all these local variables like this is likely going to have to change when we introduce the RTOS, but this is ok for now


///The gpios
reqGPIO gpios;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this makes more sense up under the model instance instead of here, so it's easier to see


/**
* The node ID used to identify the device on the CAN network.
*/
static constexpr uint8_t NODE_ID = 254;//TODO set node ID

/**
* The size of the Object Dictionary
*/
static constexpr uint8_t OBJECT_DICTIONARY_SIZE = 51;//TODO set size of object dictionary

/**
* The object dictionary itself. Will be populated by this object during
* construction.
*
* The plus one is for the special "end of dictionary" marker.
*/
CO_OBJ_T objectDictionary[OBJECT_DICTIONARY_SIZE + 1] = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're going to want identical object dictionaries for the MCUC and Hardmon, so we'll need some way of sharing the code between them at some point. I'm not sure what the best way to do that will be, but it's something to keep in mind

MANDATORY_IDENTIFICATION_ENTRIES_1000_1014,
IDENTITY_OBJECT_1018,
SDO_CONFIGURATION_1200,

// End of dictionary marker
CO_OBJ_DICT_ENDMARK,
};
};

}// namespace VCU

#endif//VCU_HARDMON_HPP
Loading