firmware defines

This commit is contained in:
2023-10-22 09:32:07 -04:00
parent 38e8ed1b51
commit 2526e44378
753 changed files with 81108 additions and 32 deletions

View File

@@ -0,0 +1,44 @@
{
"build": {
"core": "stm32",
"cpu": "cortex-m4",
"extra_flags": "-DSTM32G4xx -DSTM32G431xx",
"f_cpu": "170000000L",
"mcu": "stm32g431cbu6",
"product_line": "STM32G431xx",
"variant": "STM32G4xx/G431C(6-8-B)U_G441CBU"
},
"connectivity": [
"can"
],
"debug": {
"default_tools": [
"stlink"
],
"jlink_device": "STM32G431CB",
"openocd_target": "stm32g4x",
"svd_path": "STM32G431xx.svd"
},
"frameworks": [
"arduino",
"cmsis",
"libopencm3",
"stm32cube",
"zephyr"
],
"name": "STM32G431CB",
"upload": {
"maximum_ram_size": 32768,
"maximum_size": 131072,
"protocol": "stlink",
"protocols": [
"stlink",
"jlink",
"cmsis-dap",
"blackmagic",
"mbed"
]
},
"url": "https://www.st.com/en/microcontrollers-microprocessors/stm32g431cb.html",
"vendor": "ST"
}

39
firmware/include/README Normal file
View File

@@ -0,0 +1,39 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

View File

@@ -0,0 +1,38 @@
#pragma once
// MOTOR DRIVER L6226Q
#define U_PWM PA10
#define V_PWM PA9
#define W_PWM PA1
#define A1 PA0
#define A2 PA1
#define B1 PA9
#define B2 PA10
#define MOT_EN PB12
// ENCODER MT6835
#define ENC_A PB4
#define ENC_B PB5
#define ENC_Z PB3
#define ENC_COPI PA7
#define ENC_CIPO PA6
#define ENC_SCK PA5
#define ENC_CS PC4
#define ENC_CAL PA4
// CURRENT SENSE
#define ISENSE_U PA3
#define ISENSE_V PB13
#define ISENSE_W PB0
// COMMUNICATION
#define CAN_TX PB8
#define CAN_RX PB9
// AUX
#define LED_GOOD PB10
#define LED_FAULT PB11

185
firmware/ldscript.ld Normal file
View File

@@ -0,0 +1,185 @@
/*
******************************************************************************
**
** @file : LinkerScript.ld
**
** @author : Auto-generated by STM32CubeIDE
**
** @brief : Linker script for STM32G431CBUx Device from STM32G4 series
** 128Kbytes FLASH
** 32Kbytes RAM
**
** Set heap size, stack size and stack location according
** to application requirements.
**
** Set memory bank area and size if external memory is used
**
** Target : STMicroelectronics STM32
**
** Distribution: The file is distributed as is, without any warranty
** of any kind.
**
******************************************************************************
** @attention
**
** Copyright (c) 2023 STMicroelectronics.
** All rights reserved.
**
** This software is licensed under terms that can be found in the LICENSE file
** in the root directory of this software component.
** If no LICENSE file comes with this software, it is provided AS-IS.
**
******************************************************************************
*/
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
/* Memories definition */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K
}
/* Sections */
SECTIONS
{
/* The startup code into "FLASH" Rom type memory */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data into "FLASH" Rom type memory */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
/* Constant data into "FLASH" Rom type memory */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.ARM.extab : {
. = ALIGN(4);
*(.ARM.extab* .gnu.linkonce.armextab.*)
. = ALIGN(4);
} >FLASH
.ARM : {
. = ALIGN(4);
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
. = ALIGN(4);
} >FLASH
.preinit_array :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
} >FLASH
.init_array :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
} >FLASH
.fini_array :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(4);
} >FLASH
/* Used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections into "RAM" Ram type memory */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
*(.RamFunc) /* .RamFunc sections */
*(.RamFunc*) /* .RamFunc* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
/* Uninitialized data section into "RAM" Ram type memory */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss section */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM
/* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM
/* Remove information from the compiler libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}

46
firmware/lib/README Normal file
View File

@@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

263
firmware/lib/can/can.cpp Normal file
View File

@@ -0,0 +1,263 @@
#include "can.h"
enum canAction
{
WaitForCmd,
TxDeviceInfo,
SearchForID
};
FDCAN_HandleTypeDef hfdcan1;
FDCAN_FilterTypeDef sFilterConfig;
FDCAN_RxHeaderTypeDef RxHeader;
FDCAN_TxHeaderTypeDef TxHeader;
canAction FDCAN_State = WaitForCmd;
const uint16_t FDCAN_GlobalID = 0x7CC;
uint16_t FDCAN_TempID;
uint8_t foundExtDevice = 0;
uint8_t JunkBuf[8];
uint8_t TxData[8];
uint8_t RxData[8];
extern "C" void FDCAN1_IT0_IRQHandler(void);
void FDCAN_Error_Handler(void)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET);
}
void FDCAN_Init(void)
{
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1;
hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_NO_BRS;
hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan1.Init.AutoRetransmission = ENABLE;
hfdcan1.Init.TransmitPause = DISABLE;
hfdcan1.Init.ProtocolException = DISABLE;
// transceiver and peripheral clock specific values
hfdcan1.Init.NominalPrescaler = 1;
hfdcan1.Init.NominalSyncJumpWidth = 2;
hfdcan1.Init.NominalTimeSeg1 = 21;
hfdcan1.Init.NominalTimeSeg2 = 2;
hfdcan1.Init.DataPrescaler = 1;
hfdcan1.Init.DataSyncJumpWidth = 5;
hfdcan1.Init.DataTimeSeg1 = 6;
hfdcan1.Init.DataTimeSeg2 = 5;
//
hfdcan1.Init.StdFiltersNbr = 1;
hfdcan1.Init.ExtFiltersNbr = 0;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
{
FDCAN_Error_Handler();
}
}
void FDCAN_ConfigFilter(uint16_t canID)
{
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterIndex = 0;
sFilterConfig.FilterType = FDCAN_FILTER_DUAL;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilterConfig.FilterID1 = canID;
sFilterConfig.FilterID2 = FDCAN_GlobalID;
if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
{
/* Filter configuration Error */
FDCAN_Error_Handler();
}
}
void FDCAN_ConfigTxHeader(uint16_t canID)
{
TxHeader.Identifier = canID;
TxHeader.IdType = FDCAN_STANDARD_ID;
TxHeader.TxFrameType = FDCAN_DATA_FRAME;
TxHeader.DataLength = FDCAN_DLC_BYTES_8;
TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
TxHeader.FDFormat = FDCAN_FD_CAN;
TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxHeader.MessageMarker = 0;
}
void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef *hfdcan)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
if (hfdcan->Instance == FDCAN1)
{
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN;
PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_HSE;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
__HAL_RCC_FDCAN_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**FDCAN1 GPIO Configuration
PB8-BOOT0 ------> FDCAN1_RX
PB9 ------> FDCAN1_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);
}
}
void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef *hfdcan)
{
if (hfdcan->Instance == FDCAN1)
{
__HAL_RCC_FDCAN_CLK_DISABLE();
/**FDCAN1 GPIO Configuration
PB8-BOOT0 ------> FDCAN1_RX
PB9 ------> FDCAN1_TX
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8 | GPIO_PIN_9);
HAL_NVIC_DisableIRQ(FDCAN1_IT0_IRQn);
}
}
extern "C" void FDCAN1_IT0_IRQHandler(void)
{
HAL_FDCAN_IRQHandler(&hfdcan1);
}
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET)
{
HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader, RxData);
}
if (RxHeader.RxFrameType == FDCAN_REMOTE_FRAME)
{
// Reply globally but put the replying ID in the data packet.
TxHeader.Identifier = FDCAN_GlobalID;
memset(TxData, 0x00, 8 * sizeof(uint8_t));
memcpy(&TxData, (sFilterConfig.FilterID1), sizeof(uint16_t));
FDCAN_SendMessage();
}
else
{
switch (FDCAN_State)
{
case WaitForCmd:
// Set some flag to indicate that sfoc has a new command.
if (RxHeader.Identifier = FDCAN_GlobalID)
{
}
else
{
}
break;
case SearchForID:
foundExtDevice = 1;
break;
default:
break;
}
}
}
void FDCAN_SendMessage(void)
{
switch (FDCAN_State)
{
case TxDeviceInfo:
break;
case SearchForID:
TxHeader.Identifier = FDCAN_TempID;
TxHeader.TxFrameType = FDCAN_REMOTE_FRAME;
TxHeader.DataLength = FDCAN_DLC_BYTES_0;
break;
default:
break;
}
if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData) != HAL_OK)
{
FDCAN_Error_Handler();
}
// Set the tx parameters back to normal.
TxHeader.Identifier = sFilterConfig.FilterID1;
TxHeader.TxFrameType = FDCAN_DATA_FRAME;
TxHeader.DataLength = FDCAN_DLC_BYTES_8;
}
uint16_t FDCAN_FindUniqueID(void)
{
FDCAN_TempID = 0x000;
FDCAN_State = SearchForID;
while (1)
{
foundExtDevice = 0;
FDCAN_SendMessage();
delay(100);
if (foundExtDevice)
{
// Try the next address.
FDCAN_TempID++;
}
else
{
// We found a unique device ID!
FDCAN_State = WaitForCmd;
FDCAN_ChangeID(FDCAN_TempID);
digitalWrite(PA7, HIGH);
return FDCAN_TempID;
}
}
}
void FDCAN_ChangeID(uint16_t newID)
{
// HAL_FDCAN_Stop();
FDCAN_ConfigFilter(newID);
FDCAN_ConfigTxHeader(newID);
// HAL_FDCAN_Start();
}
void FDCAN_Start(uint16_t canID)
{
FDCAN_Init();
FDCAN_ConfigFilter(canID);
FDCAN_ConfigTxHeader(canID);
if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
{
FDCAN_Error_Handler();
}
if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
{
FDCAN_Error_Handler();
}
}

17
firmware/lib/can/can.h Normal file
View File

@@ -0,0 +1,17 @@
/**
* CAN header
*/
#ifndef AIOLI_CAN_H
#define AIOLI_CAN_H
#include <Arduino.h>
#include "stm32g4xx_hal.h"
#include "stm32g4xx_hal_fdcan.h"
void FDCAN_Start(uint16_t canID);
void FDCAN_SendMessage();
void FDCAN_ChangeID(uint16_t newID);
uint16_t FDCAN_FindUniqueID(void);
#endif

26
firmware/lib/dfu/dfu.cpp Normal file
View File

@@ -0,0 +1,26 @@
#include "stm32g4xx_hal.h"
#include "stm32g4xx_hal_conf.h"
#include "stm32g4xx_hal_rcc.h"
void perform_system_reset(void){
__disable_irq();
NVIC_SystemReset();
}
// https://stm32f4-discovery.net/2017/04/tutorial-jump-system-memory-software-stm32/
void jump_to_bootloader(void){
__enable_irq();
HAL_RCC_DeInit();
HAL_DeInit();
SysTick->CTRL = SysTick->LOAD = SysTick->VAL = 0;
__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
const uint32_t p = (*((uint32_t *) 0x1FFF0000));
__set_MSP( p );
void (*SysMemBootJump)(void);
SysMemBootJump = (void (*)(void)) (*((uint32_t *) 0x1FFF0004));
SysMemBootJump();
while( 1 ) {}
}

7
firmware/lib/dfu/dfu.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef BOOTLOADER_H
#define BOOTLOADER_H
void perform_system_reset(void);
void jump_to_bootloader(void);
#endif

50
firmware/src/clock.c Normal file
View File

@@ -0,0 +1,50 @@
#include "pins_arduino.h"
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSI48
|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
RCC_OscInitStruct.PLL.PLLN = 28;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV8;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
}

163
firmware/src/main.cpp Normal file
View File

@@ -0,0 +1,163 @@
#include <Arduino.h>
#include <EEPROM.h>
#include <SPI.h>
#include <SimpleFOC.h>
#include <SimpleFOCDrivers.h>
#include "encoders/MT6835/MagneticSensorMT6835.h"
#include "stm32g4xx_hal_conf.h"
#include "stm32g4xx_hal_fdcan.h"
#include "can.h"
#include "dfu.h"
#include "lemon-pepper.h"
#define USBD_MANUFACTURER_STRING "matei repair lab"
#define USBD_PRODUCT_STRING_FS "lemon-pepper-stepper"
// board specific data
typedef struct
{
uint16_t signature;
int8_t electricalDir;
float electricalZero;
uint8_t canID;
}userData;
userData boardData;
const uint16_t magicWord = 0xAF0C;
// canbus things
extern uint8_t TxData[8];
extern uint8_t RxData[8];
// simpleFOC things
#define POLEPAIRS 7
#define RPHASE 1.4
#define MOTORKV 1000
SPISettings myMT6835SPISettings(1000000, MT6835_BITORDER, SPI_MODE3);
MagneticSensorMT6835 sensor = MagneticSensorMT6835(ENC_CS, myMT6835SPISettings);
BLDCDriver3PWM driver = BLDCDriver3PWM(U_PWM, V_PWM, W_PWM, U_EN, V_EN, W_EN);
BLDCMotor motor = BLDCMotor(POLEPAIRS, RPHASE, MOTORKV);
MagneticSensorMT6701SSI enc = MagneticSensorMT6701SSI(ENC_CS);
Commander commander = Commander(SerialUSB);
// Prototypes
void configureFOC(void);
void configureCAN(void);
void userButton_IT(void);
void setup()
{
// SCB->VTOR == 0x08000000;
pinMode(USER_LED, OUTPUT);
attachInterrupt(USER_BUTTON, userButton_IT, HIGH);
SerialUSB.begin(115200);
EEPROM.get(0, boardData);
configureCAN();
configureFOC();
if(boardData.canID == 0x000)
{
// If the can ID is not initialized, then we'll look for a free ID.
boardData.canID = FDCAN_FindUniqueID();
SerialUSB.println(boardData.canID);
}
if(boardData.signature != magicWord)
{
// If the EEPROM has not been initalized yet, save all the known data.
EEPROM.put(0, boardData);
}
}
void loop()
{
motor.loopFOC();
motor.move();
commander.run();
#ifdef HAS_MONITOR
motor.monitor();
#endif
}
void doMotor(char *cmd)
{
commander.motor(&motor, cmd);
}
void configureFOC(void){
commander.add('M', doMotor, "motor");
commander.verbose = VerboseMode::machine_readable;
#ifdef SIMPLEFOC_STM32_DEBUG
SimpleFOCDebug::enable(&SerialUSB);
#endif
// Encoder initialization.
// Encoder on SPI1
enc.init();
// Driver initialization.
driver.pwm_frequency = 32000;
driver.voltage_power_supply = 5;
driver.voltage_limit = 2.5;
driver.init();
// Motor PID parameters.
motor.PID_velocity.P = 0.2;
motor.PID_velocity.I = 3;
motor.PID_velocity.D = 0.002;
motor.PID_velocity.output_ramp = 100;
motor.LPF_velocity.Tf = 0.5;
motor.LPF_angle.Tf = 0; // try to avoid
// Motor initialization.
motor.voltage_sensor_align = 2;
motor.current_limit = 0.5;
motor.velocity_limit = 50;
motor.controller = MotionControlType::velocity;
motor.foc_modulation = FOCModulationType::SinePWM;
// Monitor initialization
#ifdef HAS_MONITOR
motor.useMonitoring(SerialUSB);
motor.monitor_start_char = 'M';
motor.monitor_end_char = 'M';
motor.monitor_downsample = 250;
#endif
motor.linkSensor(&enc);
motor.linkDriver(&driver);
motor.target = 0;
if(boardData.signature != magicWord){
// If we have not initialized the EEPROM before.
motor.init();
motor.initFOC();
boardData.signature = magicWord;
boardData.electricalZero = motor.zero_electric_angle;
boardData.electricalDir = motor.sensor_direction;
}
else{
motor.zero_electric_angle = boardData.electricalZero;
motor.sensor_direction = boardData.electricalDir;
motor.init();
motor.initFOC();
}
}
void configureCAN(void){
FDCAN_Start(0x000);
}

11
firmware/test/README Normal file
View File

@@ -0,0 +1,11 @@
This directory is intended for PlatformIO Test Runner and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PlatformIO Unit Testing:
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html