Skip to content

Fw 226/mppt rewrite yv #3

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

Closed
wants to merge 5 commits into from
Closed
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
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "embedded-pio"]
path = embedded-pio
url = https://github.com/badgerloop-software/embedded-pio.git
64 changes: 64 additions & 0 deletions include/IOManagement.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#ifndef __IO_MANAGEMENT_H__
#define __IO_MANAGEMENT_H__

#include "const.h"
#include "INA281.h"
#include "PID_v1.h"
#include "thermistor.h"


// Solar array and battery data
typedef struct ArrayData {
double dutyCycle = 0;
float voltage = 0;
float current = 0;
float curPower = 0;
float temp = 0;
} ArrayData;

extern volatile ArrayData arrayData[NUM_ARRAYS];
extern volatile float battVolt;

// If boost converter enabled
extern volatile bool boostEnabled;

// Charging algorithm mode
enum class ChargeMode : bool {CONST_CURR, MPPT};
extern volatile ChargeMode chargeMode;

// pack charge percentage
extern volatile float packSOC;

// pack charge current limit
extern volatile float packChargeCurrentLimit;

// net pack current (solar panel IN - motor OUT)
extern volatile float packCurrent;

// output current to battery
extern volatile float outputCurrent;

// Sets up automatic updating of IO at specified period
// New input data will automatically be written to arrayData
void initData(std::chrono::microseconds updatePeriod);

// Resets the duty cycle PID loops
void resetPID();

// Resets duty cycle PID for specified array
void resetArrayPID(int array);

// Sets voltage output for all arrays
// Value will be capped if outside V_MIN or V_MAX specified in const.h
void setVoltOut(float voltage);

// Sets voltage output for specified array
void setArrayVoltOut(float voltage, int array);

// Sets clearing of OV fault
void clearOVFaultReset(uint8_t value);

// Controls discharging of output capacitors thorugh resistor path
void setCapDischarge(uint8_t value);

#endif // __IO_MANAGEMENT_H__
44 changes: 44 additions & 0 deletions include/canmanager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#ifndef __CAN_MANAGER_H__
#define __CAN_MANAGER_H__

#include "STM32_CAN.h"

#define DEFAULT_CAN_FREQ 250000 // Match Elcon charger

class CANManager {
private:
STM32_CAN canBus; // object to interface with CAN

public:
/* Constructor initializing bus and all manager functions
*
* canPort: choose from CAN1, CAN2, CAN3 (NOTE: see STM32_CAN library for more details)
* pins: choose from DEF, ALT1, ALT2
* frequency: Baud rate of can bus
*/
CANManager(CAN_TypeDef* canPort, CAN_PINS pins, int frequency = DEFAULT_CAN_FREQ);

/* Reads input message and does any logic handling needed
* Intended to be implemented by class extension per board
*/
virtual void readHandler(CAN_message_t msg) = 0;

/* Send a message over CAN
*
* messageID: CAN ID to use to identify the signal
* data: Payload array
* length: Size of data in bytes
* timeout: in milliseconds
*/
bool sendMessage(int messageID, void* data, int length, int timeout = 10);

/* Processes CAN (read) messages stored in messageQueue for a set duration.
* THIS IS THE FUNCTION TO CALL FOR PROCESSING CAN READ MESSAGES
*
* duration: time in milliseconds
*/
void runQueue(int duration);
};


#endif
108 changes: 108 additions & 0 deletions include/const.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#ifndef CONST_H
#define CONST_H
// this header should include all relevant constant values so they can all be easily changed


// ------------- IO INPUT CONSTANTS -------------
#define IO_UPDATE_PERIOD 100
#define NUM_ARRAYS 3

// Analog input modifiers (derived from circuitry)
constexpr float V_SCALE = (103.3/3.3)*3.33;
constexpr float BATT_V_SCALE = 3.325 * 101;

//Input pins to read voltage for each solar array
#define VOLT_PIN_1 PA_6
#define VOLT_PIN_2 PA_4
#define VOLT_PIN_3 PA_1

//Input pins to read current for each solar array
#define CURR_PIN_1 PA_7
#define CURR_PIN_2 PA_5
#define CURR_PIN_3 PA_3

#define INA_SHUNT_R 0.01

// Input pin to get battery voltage
#define BATTERY_VOLT_PIN PB_0

// Output pins for voltage control of arrays via PWM
#define PWM_OUT_1 PA_9
#define PWM_OUT_2 PA_10
#define PWM_OUT_3 PA_8

// CAN triggered outputs
#define OV_FAULT_RST_PIN PB_6
#define DISCHARGE_CAPS_PIN PB_1

// Output voltage limit
#define V_MAX 110

// --------------- PID/PWM CONSTANTS -----------------
// Loop parameters
#define P_TERM -0.7 //-3.65 // -2.9
#define I_TERM -0.2 // -0.06 // -0.1
#define D_TERM 0 //-0.012 // 0

// Input range
#define PID_IN_MIN 0
#define PID_IN_MAX 115

// PID output limits (controls PWM duty cycles)
#define PWM_DUTY_MIN 0
#define PWM_DUTY_MAX 0.8
#define PWM_PERIOD_US 13

// ------------- MPPT ALGO CONSTANTS -------------
// Initial voltage
#define INIT_VOLT 9

// initial step size for MPPT updates
#define INIT_VOLT_STEP 0.5

// Maximum voltage the algo loop can target (want safe offset under danger V_MAX)
#define V_TARGET_MAX 105

//Maximum current the algo loop can target would be the pack charge current limit
#define I_TARGET_MAX 20

// Frequency of MPPT algo updates
#define MPPT_UPDATE_PERIOD 10 * IO_UPDATE_PERIOD

// Current threshold to switch to constant current
#define CONST_CURR_THRESH packChargeCurrentLimit

// Current threshold to switch to MPPT
#define MPPT_THRESH packChargeCurrentLimit-0.7

#define CONST_CURR_SAFETY_MULT 0.9

// used for variable step size
#define MAX_VOLT_STEP 4
#define MIN_VOLT_STEP 0.5

// try moving targetVoltage when PWM is stuck at either limit
#define MOVE_VOLTAGE 5
#define MAX_STUCK_CYCLES 5

// ------------- TESTING/OTHER CONSTANTS -------------
// Whether to log data and steps in file. Should only be enabled
// when microcontroller outputting via serial
// 1 for human readable mode
// 2 for logging/csv mode
// 3 for showing array 0 values only
#define DEBUG_PRINT 1

// How fast to transmit data over CAN (and debug prints if on)
#define DATA_SEND_PERIOD 50ms

// CAN Pins
#define CAN_RX PA_11
#define CAN_TX PA_12

// Duration undervoltage fault reset asserted on command
#define OV_FAULT_RST_PERIOD 250ms



#endif // CONST_H
43 changes: 43 additions & 0 deletions include/ina281.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#ifndef _INA281_H_
#define _INA281_H_

#include <Wire.h>

/*
A class which represents an instance of an INA281 Driver for measuring current across a
shunt resistor. The analog output pin of the INA gives the voltage across the shunt resistor
multiplied by a scale factor (default 20). Current is calculated from voltage and resistance
using V = IR.
*/
class INA281Driver {
private:
int analogPin;
float resistance;
float scaleFactor;

public:

/*
Creates a new INA281 Driver

Constructor expects 2 arguments:
analogPin - name of analog pin the INA is wired to
resistance - resistance of the shunt resistor associated with the INA

Optional argument:
scaleFactor - the factor by which to divide the pin reading to get the correct voltage
*/
INA281Driver(int analogPin, float resistance, float scaleFactor = 20);

/*
Retrieves the current current reading
*/
float readCurrent();

/*
Retrieves the current voltage reading
*/
float readVoltage();
};

#endif
12 changes: 12 additions & 0 deletions include/mppt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef __MPPT_H__
#define __MPPT_H__

#include "const.h"
#include "IOManagement.h"
#include "Ticker.h"

extern volatile float targetVoltage[NUM_ARRAYS];
extern volatile float targetVoltage_C[NUM_ARRAYS];


#endif // __MPPT_H__
59 changes: 59 additions & 0 deletions include/thermistor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#ifndef __THERMISTOR_H__
#define __THERMISTOR_H__

#include <Wire.h>

/*
Thermistor voltage reading is converted to temperature in a two step process

1. Thermistor voltage must be converted into thermistor resistance.
This is done by solving the voltage divider equation (VCC and other resistor R are
fixed by hardware) for the thermistor voltage

Measured Voltage = VCC * (Thermistor_Resistance) / (Thermistor_Resistance + R)

2. Thermistor resistance is converted to temperature through a best fit
log curve built using the specific thermistor model's electrical characteristics.
This will involve a pair of magic numbers (mult_const and add_const) generated by
fitting a curve to a series of (resistance, temperature) points provided by manufacturer

Temperature = mult_const * log(Thermistor Resistance) + add_const
*/

typedef struct{
float mult_const;
float add_const;
} Thermistor_Constants;

const Thermistor_Constants NCP21XM472J03RA_Constants = {
.mult_const = -27.06,
.add_const = 253.11
};

class Thermistor{
private:
float mult_const;
float add_const;
float vcc;
float R;
int thermVoltPin;

public:
/*
Constructor expects at least 2 arguments
constants: Struct of log translation function constants from structs above
therm_pin: Analog pin the thermistor is wired to

Optional arguments
R: Resistance of resistor in series with thermistor
vcc: Total voltage across R and thermistor
*/
Thermistor(const Thermistor_Constants constants, int therm_pin, float R = 4700, float vcc = 3.3);

/*
Retrives current thermistor reading
*/
float get_temperature();
};

#endif
6 changes: 6 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,9 @@
platform = ststm32
board = nucleo_l432kc
framework = arduino
build_flags = -DHAL_CAN_MODULE_ENABLED
lib_extra_dirs = ./embedded-pio
lib_deps =
br3ttb/PID@^1.2.1
pazi88/STM32_CAN@^1.1.2
sstaub/Ticker@^4.4.0
Loading