diff --git a/MMC5983MA.c b/MMC5983MA.c new file mode 100644 index 0000000..135e5a2 --- /dev/null +++ b/MMC5983MA.c @@ -0,0 +1,262 @@ +/** + * @file mag.c + * @brief Implementation of magnetometer driver + * + * This file contains the implementation of the magnetometer driver + * using the MMC5983MA sensor. It includes functions for initializing, + * configuring, and reading data from the magnetometer. + * + * @authors Eric Chiang + * @date 2025-10-18 + * @version 0.1 + * @bug No known bugs. + */ +#include "MMC5983MA.h" +#include "sensors_defs.h" + +/* + * [0] = Bandwidth + * [1] = Continous Mode Measurement Freq + * [2] = Set Count + */ +uint8_t MMC5983MA_SETTINGS[3]; + +// Calibration Values +float hard_iron[3] = {0}; +float soft_iron[3][3] = { + {1,0,0}, + {0,1,0}, + {0,0,1} +}; + +uint8_t MMC5983MA_Init(void) { + HAL_StatusTypeDef status = HAL_OK; + uint8_t whoami = MMC5983MA_ReadRegister(MMC5983MA_WHO_AM_I); + if (whoami != MMC5983MA_WHO_AM_I_VALUE) { + printf("Initialization failed, incorrect whoami value. Expected: %x, Received: %x", MMC5983MA_WHO_AM_I_VALUE, whoami); + return 1; + } + + // Enable Auto_SR_en + uint8_t reg_val = 1 << 1; + MMC5983MA_WriteRegister(MMC5983MA_CTRL0, reg_val); + + // Set bandwidth of sensor to be 100hz (default) (measurement time = 8ms) +// reg_val = 0b00000000; +// MMC5983MA_WriteRegister(MMC5983MA_CTRL1, reg_val); + MMC5983MA_SETTINGS[0] = MMC5983MA_BANDWIDTH_100HZ; + + // Set measurement mode to be continuous @ 100Hz. + // Set auto SET operation of magnetometer/1000 measurement (realigns the mag??) + reg_val = 0b11101101; + MMC5983MA_WriteRegister(MMC5983MA_CTRL2, reg_val); + MMC5983MA_SETTINGS[1] = MMC5983MA_MEASUREMENT_100HZ; + MMC5983MA_SETTINGS[2] = MMC5983MA_SET_1000; + + // Nothing to modify on CTRL3 register + + return 0; +} + +uint8_t MMC5983MA_ReadRegister(uint8_t addr) { + HAL_StatusTypeDef status = HAL_OK; + + // MSB = 1 for read, 5 bit register addresses starts at Bit 2 + uint8_t txData = addr | 0x80; + uint8_t rxData; + + // Set CS Pin Low + status = HAL_SPI_GetState(&hspi1); + HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_12); + HAL_GPIO_WritePin(MMC5983MA_CS_PORT, MMC5983MA_CS_PIN, GPIO_PIN_RESET); + status = HAL_SPI_Transmit(&hspi1, &txData, 1, SENSORS_SPI_TIMEOUT); + if (status != HAL_OK) { + printf("Error writing to MMC5983MA register 0x%02X: %d\n", addr, status); + if (status == HAL_TIMEOUT) { + printf("MMC5983MA SPI write timeout\n"); + } else if (status == HAL_ERROR) { + printf("MMC5983MA SPI write error\n"); + } else if (status == HAL_BUSY) { + printf("MMC5983MA SPI is busy\n"); + } + } + status = HAL_SPI_Receive(&hspi1, &rxData, 1, SENSORS_SPI_TIMEOUT); + if (status != HAL_OK) { + printf("Error reading from MMC5983MA register 0x%02X: %d\n", addr, status); + if (status == HAL_TIMEOUT) { + printf("MMC5983MA SPI read timeout\n"); + } else if (status == HAL_ERROR) { + printf("MMC5983MA SPI read error\n"); + } else if (status == HAL_BUSY) { + printf("MMC5983MA SPI is busy\n"); + } + } + + // Set CS Pin High + HAL_GPIO_WritePin(MMC5983MA_CS_PORT, MMC5983MA_CS_PIN, GPIO_PIN_SET); + + return rxData; +} + +void MMC5983MA_ReadRegisters(uint8_t addr, uint8_t *buffer, uint8_t length) { + HAL_StatusTypeDef status = HAL_OK; + + // MSB = 1 for read, 5 bit register addresses starts at Bit 2 + uint8_t txData = addr | 0x80; + + // Set CS to Low + HAL_GPIO_WritePin(MMC5983MA_CS_PORT, MMC5983MA_CS_PIN, GPIO_PIN_RESET); + status = HAL_SPI_Transmit(&hspi1, &txData, 1, SENSORS_SPI_TIMEOUT); + if (status != HAL_OK) { + printf("Error writing to MMC5983MA register 0x%02X: %d\n", addr, status); + if (status == HAL_TIMEOUT) { + printf("MMC5983MA SPI write timeout\n"); + } else if (status == HAL_ERROR) { + printf("MMC5983MA SPI write error\n"); + } else if (status == HAL_BUSY) { + printf("MMC5983MA SPI is busy\n"); + } + } + + status = HAL_SPI_Receive(&hspi1, buffer, length, SENSORS_SPI_TIMEOUT); + if (status != HAL_OK) { + printf("Error reading from MMC5983MA register 0x%02X: %d\n", addr, status); + if (status == HAL_TIMEOUT) { + printf("MMC5983MA SPI read timeout\n"); + } else if (status == HAL_ERROR) { + printf("MMC5983MA SPI read error\n"); + } else if (status == HAL_BUSY) { + printf("MMC5983MA SPI is busy\n"); + } + } + + // Set CS Pin High + HAL_GPIO_WritePin(MMC5983MA_CS_PORT, MMC5983MA_CS_PIN, GPIO_PIN_SET); +} + +void MMC5983MA_WriteRegister(uint8_t addr, uint8_t value) { + HAL_StatusTypeDef status = HAL_OK; + uint8_t buffer[2] = { addr, value }; + + // Set CS to Low + HAL_GPIO_WritePin(MMC5983MA_CS_PORT, MMC5983MA_CS_PIN, GPIO_PIN_RESET); + status = HAL_SPI_Transmit(&hspi1, buffer, 2, SENSORS_SPI_TIMEOUT); + if (status != HAL_OK) { + printf("Error writing to MMC5983MA register 0x%02X: %d\n", addr, status); + if (status == HAL_TIMEOUT) { + printf("MMC5983MA SPI write timeout\n"); + } else if (status == HAL_ERROR) { + printf("MMC5983MA SPI write error\n"); + } else if (status == HAL_BUSY) { + printf("MMC5983MA SPI is busy\n"); + } + } + + // Set CS to High + HAL_GPIO_WritePin(MMC5983MA_CS_PORT, MMC5983MA_CS_PIN, GPIO_PIN_SET); +} + +void MMC5983MA_ReadMagneticField16(vector_t* mag_data) { + uint8_t buffer[6]; + MMC5983MA_ReadRegisters(MMC5983MA_XOUT_H, buffer, 6); + + uint16_t x_raw = (uint16_t)(buffer[0] << 8 | buffer[1]); + uint16_t y_raw = (uint16_t)(buffer[2] << 8 | buffer[3]); + uint16_t z_raw = (uint16_t)(buffer[4] << 8 | buffer[5]); + + mag_data->v[0] = MMC5983MA_16Bits_to_mGauss(x_raw); + mag_data->v[1] = MMC5983MA_16Bits_to_mGauss(y_raw); + mag_data->v[2] = MMC5983MA_16Bits_to_mGauss(z_raw); +} + +void MMC5983MA_ReadMagneticField18(vector_t* mag_data) { + uint8_t buffer[7]; + MMC5983MA_ReadRegisters(MMC5983MA_XOUT_H, buffer, 7); + + // buffer[6] contains two additional bits of x, y, z mag readings + uint32_t x_raw = (uint32_t)(buffer[0] << 10 | buffer[1] << 2 | buffer[6] >> 6); + uint32_t y_raw = (uint32_t)(buffer[2] << 10 | buffer[3] << 2 | (buffer[6] & 0x30) >> 4); + uint32_t z_raw = (uint32_t)(buffer[4] << 10 | buffer[5] << 2 | (buffer[6] & 0x0C) >> 2); + + mag_data->v[0] = MMC5983MA_18Bits_to_mGauss(x_raw); + mag_data->v[1] = MMC5983MA_18Bits_to_mGauss(y_raw); + mag_data->v[2] = MMC5983MA_18Bits_to_mGauss(z_raw); +} + +float MMC5983MA_Get_Temp(void) { + HAL_StatusTypeDef status = HAL_OK; + uint8_t raw_temp = MMC5983MA_ReadRegister(MMC5983MA_TOUT); + return (float)raw_temp * 0.8 - 75.0; +} + +void MMC5983MA_SW_Reset(void) { + MMC5983MA_WriteRegister(MMC5983MA_CTRL1, 0x80); // SW Reset is the MSB + // TODO: Maybe use a timer instead so we don't block + HAL_Delay(10); // 10ms power-up time +} + +float MMC5983MA_16Bits_to_mGauss(uint16_t mag_val) { + float mag_val_mgauss = (float)mag_val - 65536.0; + mag_val_mgauss /= 65536.0; + mag_val_mgauss *= 8; // Get full range of +-8 Gauss + return mag_val_mgauss * 1000; // Get milligauss +} + +float MMC5983MA_18Bits_to_mGauss(uint32_t mag_val) { + float mag_val_mgauss = (float)mag_val - 131072.0; + mag_val_mgauss /= 131072.0; + mag_val_mgauss *= 8; // Get full range of +-8 Gauss + return mag_val_mgauss * 1000; // Get milligauss +} + +/* + * More in depth explanation of this function: + * We are using MotionCal (https://github.com/PaulStoffregen/MotionCal) to calibrate the magnetometer. + * MotionCal reads in sensor data over UART in a very specific format, and then automatically performs + * calibration and outputs calibration values for the magnetometer. + * Required output format for MotionCal: "Raw:{accX},{accY},{accZ},{gyrX},{gyrY},{gyrZ},{magX},{magY},{magZ}\r\n" + * + * Either way, these calibrations need to happen after the magnetometer has been installed onto the rocket system for accurate + * bias values. + */ +void MMC5983MA_Calibrate_MotionCal(vector_t* mag_data) { + char raw_data[] = "Raw:0,0,0,0,0,0,"; // Currently only require calibration for mag values + char new_line[] = "\r\n"; + char comma = ','; + + // Inputted mag values must be in units of milligauss + char x_buffer[8] = ""; + char y_buffer[8] = ""; + char z_buffer[8] = ""; + sprintf(x_buffer, "%d", (int16_t)mag_data->v[0]); + sprintf(y_buffer, "%d", (int16_t)mag_data->v[1]); + sprintf(z_buffer, "%d", (int16_t)mag_data->v[2]); + + HAL_UART_Transmit(&huart2, (uint8_t*)raw_data, sizeof(raw_data)-1, HAL_UART_TIMEOUT_VALUE); + HAL_UART_Transmit(&huart2, (uint8_t*)x_buffer, strlen(x_buffer), HAL_UART_TIMEOUT_VALUE); + HAL_UART_Transmit(&huart2, (uint8_t*)&comma, 1, HAL_UART_TIMEOUT_VALUE); + HAL_UART_Transmit(&huart2, (uint8_t*)y_buffer, strlen(y_buffer), HAL_UART_TIMEOUT_VALUE); + HAL_UART_Transmit(&huart2, (uint8_t*)&comma, 1, HAL_UART_TIMEOUT_VALUE); + HAL_UART_Transmit(&huart2, (uint8_t*)z_buffer, strlen(z_buffer), HAL_UART_TIMEOUT_VALUE); + HAL_UART_Transmit(&huart2, (uint8_t*)new_line, sizeof(new_line), HAL_UART_TIMEOUT_VALUE); +} + + + +// Hard iron offsets are biases in the magnetometer that are created by magnetic + // fields emitted by permanent magnets (motors, inductors, etc) +// Soft iron offsets are biases caused by materials near the magnetometer that + // warp/disturb the surrounding magnetic fields +void MMC5983MA_Calibrate_Data(vector_t* mag_data) { + float mag_temp[3] = {0}; + for (uint8_t i = 0; i < 3; i++) { + mag_temp[i] = mag_data->v[i] - hard_iron[i]; + } + + for (uint8_t i = 0; i < 3; i++) { + mag_data->v[i] = + soft_iron[i][0] * mag_temp[0] + + soft_iron[i][1] * mag_temp[1] + + soft_iron[i][2] * mag_temp[2]; + } +} diff --git a/MMC5983MA.h b/MMC5983MA.h new file mode 100644 index 0000000..a4aebe8 --- /dev/null +++ b/MMC5983MA.h @@ -0,0 +1,171 @@ +/** + * @file mag.h + * @brief Header file for magnetometer driver + * + * This file contains the definitions and function prototypes for + * initializing and reading data from the magnetometer. It includes + * the necessary structures, function prototypes, and constants + * required for the magnetometer driver. + * + * @authors Eric Chiang + * @date 2025-10-18 + * @version 0.1 + * @bug No known bugs. + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef MMC5983MA_DRIVER_H_ +#define MMC5983MA_DRIVER_H_ + +// Includes +#include "stm32g0xx_hal.h" +#include "sensors_defs.h" +#include +#include +#include + +// SPI Handle +extern SPI_HandleTypeDef hspi1; +extern UART_HandleTypeDef huart2; + +// Pin Definitions +#define MMC5983MA_CS_PORT GPIOA +#define MMC5983MA_CS_PIN GPIO_PIN_0 + +// Register Addresses +#define MMC5983MA_WHO_AM_I 0x2F +#define MMC5983MA_XOUT_H 0x00 +#define MMC5983MA_XOUT_L 0x01 +#define MMC5983MA_YOUT_H 0x02 +#define MMC5983MA_YOUT_L 0x03 +#define MMC5983MA_ZOUT_H 0x04 +#define MMC5983MA_ZOUT_L 0x05 +#define MMC5983MA_XYZOUT 0x06 // If in 18 bit mode, this register contains the last two bits of each orientation +#define MMC5983MA_TOUT 0x07 +#define MMC5983MA_STATUS 0x08 +#define MMC5983MA_CTRL0 0x09 +#define MMC5983MA_CTRL1 0x0A +#define MMC5983MA_CTRL2 0x0B +#define MMC5983MA_CTRL3 0x0C + +// WHO_AM_I Expected Value +#define MMC5983MA_WHO_AM_I_VALUE 0x30 + +// Magnetometer Settings +typedef enum { + MMC5983MA_BANDWIDTH_100HZ = 0b00, + MMC5983MA_BANDWIDTH_200HZ = 0b01, + MMC5983MA_BANDWIDTH_400HZ = 0b10, + MMC5983MA_BANDWIDTH_800HZ = 0b11 +} mmc5983ma_bandwith_t; + +typedef enum { + MMC5983MA_MEASUREMENT_OFF = 0b000, + MMC5983MA_MEASUREMENT_1HZ = 0b001, + MMC5983MA_MEASUREMENT_10HZ = 0b010, + MMC5983MA_MEASUREMENT_20HZ = 0b011, + MMC5983MA_MEASUREMENT_50HZ = 0b100, + MMC5983MA_MEASUREMENT_100HZ = 0b101, + MMC5983MA_MEASUREMENT_200HZ = 0b110, + MMC5983MA_MEASUREMENT_1000HZ = 0b111 +} mmc5983ma_measurement_freq_t; + +typedef enum { + MMC5983MA_SET_1 = 0b000, + MMC5983MA_SET_25 = 0b001, + MMC5983MA_SET_75 = 0b010, + MMC5983MA_SET_100 = 0b011, + MMC5983MA_SET_250 = 0b100, + MMC5983MA_SET_500 = 0b101, + MMC5983MA_SET_1000 = 0b110, + MMC5983MA_SET_2000 = 0b111, +} mmc5983ma_set_count_t; + +// Function Prototypes +/** + * @brief Write a single byte to a MMC5983MA register. + * @param addr: Register address to write. + * @param value: Value to write. + */ +void MMC5983MA_WriteRegister(uint8_t addr, uint8_t value); + +/** + * @brief Read a single byte from a MMC5983MA register. + * @param addr: Register addres to read. + * @return The byte value of the register + */ +uint8_t MMC5983MA_ReadRegister(uint8_t addr); + +/** + * @brief Read a single byte from a MMC5983MA register. + * @param addr: Register addres to read. + * @param buffer: The buffer to write returned values to. + * @param length: The length of the input buffer. + */ +void MMC5983MA_ReadRegisters(uint8_t addr, uint8_t *buffer, uint8_t length); + +/** + * @brief Initializes the magnetometer. + * + * This function configures the SPI communication and sets up the GPIO pins + * for the magnetometer. It also performs a self-test to ensure the sensor is + * functioning correctly. + * + * @return Status of the initialization (0 for success, 1 for failure). + */ +uint8_t MMC5983MA_Init(void); + +/** + * @brief Read the output of the magnetometer and stores it into the output data container. + * Resolution of the output is 16 bits/0.25 mG + * @param mag_data: The container for the data + */ +void MMC5983MA_ReadMagneticField16(vector_t* mag_data); + +/** + * @brief Read the output of the magnetometer and stores it into the output data container + * Resolution of the output is 18 bits/0.0625 mG + * @param mag_data: The container for the data + */ +void MMC5983MA_ReadMagneticField18(vector_t* mag_data); + +/** + * @brief Change the functionality of the magnetometer + * @param ctrl_reg: One of four CTRL register addreses for the MMC5983MA + * @param val: The byte to be writtern to the CTRL registers + */ + +float MMC5983MA_16Bits_to_mGauss(uint16_t mag_val); + +/** + * @brief Convert the 18 bit output of the magnetometer to mGauss + * @param ctrl_reg: One of the X, Y, Z magnetometer outputs + * @return The value of the magnetometer output in mGauss + */ +float MMC5983MA_18Bits_to_mGauss(uint32_t mag_val); + + +/** + * @brief Get the die temperature of the MMC5983MA + * @return The temperature in celsius + */ +float MMC5983MA_Get_Temp(void); + +/** + * @brief Software Reset of the magnetometer. Clears all registers and self-tests on reset. + */ +void MMC5983MA_SW_Reset(void); + +/** + * @brief Transmits out the x, y, z values of the magnetometer to externally calibrate with MotionCal + * @param mag_data: The output data container for the magnetometer in milligauss + */ +void MMC5983MA_Calibrate_MotionCal(vector_t* mag_data); + +/** + * @brief Applies calibration values to the magnetometer data + * @param mag_data: The output data container for the magnetometer in milligauss + */ +void MMC5983MA_Calibrate_Data(vector_t* mag_data); + +#endif // MMC5983MA_DRIVER_H_ diff --git a/MMC5983MC.ioc b/MMC5983MC.ioc new file mode 100644 index 0000000..d9a6500 --- /dev/null +++ b/MMC5983MC.ioc @@ -0,0 +1,191 @@ +#MicroXplorer Configuration settings - do not modify +CAD.formats= +CAD.pinconfig= +CAD.provider= +File.Version=6 +GPIO.groupedBy=Group By Peripherals +KeepUserPlacement=false +Mcu.CPN=STM32G0B1RET6 +Mcu.Family=STM32G0 +Mcu.IP0=NVIC +Mcu.IP1=RCC +Mcu.IP2=SPI1 +Mcu.IP3=SYS +Mcu.IP4=USART2 +Mcu.IPNb=5 +Mcu.Name=STM32G0B1R(B-C-E)Tx +Mcu.Package=LQFP64 +Mcu.Pin0=PC13 +Mcu.Pin1=PC14-OSC32_IN (PC14) +Mcu.Pin10=PA7 +Mcu.Pin11=PB12 +Mcu.Pin12=PA13 +Mcu.Pin13=PA14-BOOT0 +Mcu.Pin14=VP_SYS_VS_Systick +Mcu.Pin15=VP_SYS_VS_DBSignals +Mcu.Pin2=PC15-OSC32_OUT (PC15) +Mcu.Pin3=PF0-OSC_IN (PF0) +Mcu.Pin4=PA0 +Mcu.Pin5=PA1 +Mcu.Pin6=PA2 +Mcu.Pin7=PA3 +Mcu.Pin8=PA5 +Mcu.Pin9=PA6 +Mcu.PinsNb=16 +Mcu.ThirdPartyNb=0 +Mcu.UserConstants= +Mcu.UserName=STM32G0B1RETx +MxCube.Version=6.15.0 +MxDb.Version=DB.6.0.150 +NVIC.ForceEnableDMAVector=true +NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.SVC_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true +NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:false +PA0.GPIOParameters=PinState,GPIO_PuPd,GPIO_Label +PA0.GPIO_Label=SPI1-CS +PA0.GPIO_PuPd=GPIO_NOPULL +PA0.Locked=true +PA0.PinState=GPIO_PIN_SET +PA0.Signal=GPIO_Output +PA1.Mode=Full_Duplex_Master +PA1.Signal=SPI1_SCK +PA13.GPIOParameters=GPIO_Label +PA13.GPIO_Label=TMS +PA13.Locked=true +PA13.Mode=Serial_Wire +PA13.Signal=SYS_SWDIO +PA14-BOOT0.GPIOParameters=GPIO_Label +PA14-BOOT0.GPIO_Label=TCK +PA14-BOOT0.Locked=true +PA14-BOOT0.Mode=Serial_Wire +PA14-BOOT0.Signal=SYS_SWCLK +PA2.GPIOParameters=GPIO_Label +PA2.GPIO_Label=USART2_TX [STLK_TX] +PA2.Locked=true +PA2.Mode=Asynchronous +PA2.Signal=USART2_TX +PA3.GPIOParameters=GPIO_Label +PA3.GPIO_Label=USART2_RX [STLK_RX] +PA3.Locked=true +PA3.Mode=Asynchronous +PA3.Signal=USART2_RX +PA5.GPIOParameters=GPIO_Speed,GPIO_Label +PA5.GPIO_Label=LED_GREEN +PA5.GPIO_Speed=GPIO_SPEED_FREQ_HIGH +PA5.Locked=true +PA5.Signal=GPIO_Output +PA6.Mode=Full_Duplex_Master +PA6.Signal=SPI1_MISO +PA7.Mode=Full_Duplex_Master +PA7.Signal=SPI1_MOSI +PB12.Locked=true +PB12.Signal=GPIO_Output +PC13.GPIOParameters=GPIO_Label +PC13.GPIO_Label=B1 [blue push button] +PC13.Locked=true +PC13.Signal=GPXTI13 +PC14-OSC32_IN\ (PC14).Locked=true +PC14-OSC32_IN\ (PC14).Mode=LSE-External-Oscillator +PC14-OSC32_IN\ (PC14).Signal=RCC_OSC32_IN +PC15-OSC32_OUT\ (PC15).Locked=true +PC15-OSC32_OUT\ (PC15).Mode=LSE-External-Oscillator +PC15-OSC32_OUT\ (PC15).Signal=RCC_OSC32_OUT +PF0-OSC_IN\ (PF0).GPIOParameters=GPIO_Label +PF0-OSC_IN\ (PF0).GPIO_Label=MCO +PF0-OSC_IN\ (PF0).Locked=true +PF0-OSC_IN\ (PF0).Mode=HSE-External-Clock-Source +PF0-OSC_IN\ (PF0).Signal=RCC_OSC_IN +PinOutPanel.RotationAngle=0 +ProjectManager.AskForMigrate=true +ProjectManager.BackupPrevious=false +ProjectManager.CompilerLinker=GCC +ProjectManager.CompilerOptimize=6 +ProjectManager.ComputerToolchain=false +ProjectManager.CoupleFile=false +ProjectManager.CustomerFirmwarePackage= +ProjectManager.DefaultFWLocation=true +ProjectManager.DeletePrevious=true +ProjectManager.DeviceId=STM32G0B1RETx +ProjectManager.FirmwarePackage=STM32Cube FW_G0 V1.6.2 +ProjectManager.FreePins=false +ProjectManager.HalAssertFull=false +ProjectManager.HeapSize=0x200 +ProjectManager.KeepUserCode=true +ProjectManager.LastFirmware=true +ProjectManager.LibraryCopy=1 +ProjectManager.MainLocation=Core/Src +ProjectManager.NoMain=false +ProjectManager.PreviousToolchain= +ProjectManager.ProjectBuild=false +ProjectManager.ProjectFileName=MMC5983MC.ioc +ProjectManager.ProjectName=MMC5983MC +ProjectManager.ProjectStructure= +ProjectManager.RegisterCallBack= +ProjectManager.StackSize=0x400 +ProjectManager.TargetToolchain=STM32CubeIDE +ProjectManager.ToolChainLocation= +ProjectManager.UAScriptAfterPath= +ProjectManager.UAScriptBeforePath= +ProjectManager.UnderRoot=true +ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_USART2_UART_Init-USART2-false-HAL-true,4-MX_SPI1_Init-SPI1-false-HAL-true +RCC.AHBFreq_Value=16000000 +RCC.APBFreq_Value=16000000 +RCC.APBTimFreq_Value=16000000 +RCC.CECFreq_Value=32786.88524590164 +RCC.CortexFreq_Value=16000000 +RCC.EXTERNAL_CLOCK_VALUE=12288000 +RCC.FCLKCortexFreq_Value=16000000 +RCC.FDCANFreq_Value=16000000 +RCC.FamilyName=M +RCC.HCLKFreq_Value=16000000 +RCC.HSE_VALUE=8000000 +RCC.HSI48_VALUE=48000000 +RCC.HSI_VALUE=16000000 +RCC.I2C1Freq_Value=16000000 +RCC.I2C2Freq_Value=16000000 +RCC.I2S1Freq_Value=16000000 +RCC.I2S2Freq_Value=16000000 +RCC.IPParameters=AHBFreq_Value,APBFreq_Value,APBTimFreq_Value,CECFreq_Value,CortexFreq_Value,EXTERNAL_CLOCK_VALUE,FCLKCortexFreq_Value,FDCANFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI48_VALUE,HSI_VALUE,I2C1Freq_Value,I2C2Freq_Value,I2S1Freq_Value,I2S2Freq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPUART1Freq_Value,LPUART2Freq_Value,LSCOPinFreq_Value,LSI_VALUE,MCO1PinFreq_Value,MCO2PinFreq_Value,PLLPoutputFreq_Value,PLLQoutputFreq_Value,PLLRCLKFreq_Value,PWRFreq_Value,SYSCLKFreq_VALUE,TIM15Freq_Value,TIM1Freq_Value,USART1Freq_Value,USART2Freq_Value,USART3Freq_Value,USBFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value +RCC.LPTIM1Freq_Value=16000000 +RCC.LPTIM2Freq_Value=16000000 +RCC.LPUART1Freq_Value=16000000 +RCC.LPUART2Freq_Value=16000000 +RCC.LSCOPinFreq_Value=32000 +RCC.LSI_VALUE=32000 +RCC.MCO1PinFreq_Value=16000000 +RCC.MCO2PinFreq_Value=16000000 +RCC.PLLPoutputFreq_Value=64000000 +RCC.PLLQoutputFreq_Value=64000000 +RCC.PLLRCLKFreq_Value=64000000 +RCC.PWRFreq_Value=16000000 +RCC.SYSCLKFreq_VALUE=16000000 +RCC.TIM15Freq_Value=16000000 +RCC.TIM1Freq_Value=16000000 +RCC.USART1Freq_Value=16000000 +RCC.USART2Freq_Value=16000000 +RCC.USART3Freq_Value=16000000 +RCC.USBFreq_Value=48000000 +RCC.VCOInputFreq_Value=16000000 +RCC.VCOOutputFreq_Value=128000000 +SH.GPXTI13.0=GPIO_EXTI13 +SH.GPXTI13.ConfNb=1 +SPI1.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_64 +SPI1.CLKPhase=SPI_PHASE_1EDGE +SPI1.CLKPolarity=SPI_POLARITY_LOW +SPI1.CalculateBaudRate=250.0 KBits/s +SPI1.DataSize=SPI_DATASIZE_8BIT +SPI1.Direction=SPI_DIRECTION_2LINES +SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,CLKPhase,CLKPolarity,BaudRatePrescaler +SPI1.Mode=SPI_MODE_MASTER +SPI1.VirtualType=VM_MASTER +USART2.IPParameters=VirtualMode-Asynchronous +USART2.VirtualMode-Asynchronous=VM_ASYNC +VP_SYS_VS_DBSignals.Mode=DisableDeadBatterySignals +VP_SYS_VS_DBSignals.Signal=SYS_VS_DBSignals +VP_SYS_VS_Systick.Mode=SysTick +VP_SYS_VS_Systick.Signal=SYS_VS_Systick +board=NUCLEO-G0B1RE +boardIOC=true +isbadioc=false diff --git a/README.md b/README.md deleted file mode 100644 index 1eccce7..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Discovery-Dev -Development repo for Discovery avionics system. diff --git a/main.c b/main.c new file mode 100644 index 0000000..6b4a1f7 --- /dev/null +++ b/main.c @@ -0,0 +1,338 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + * @attention + * + * Copyright (c) 2025 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. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include +#include "main.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#include +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ +SPI_HandleTypeDef hspi1; + +UART_HandleTypeDef huart2; + +/* USER CODE BEGIN PV */ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +static void MX_GPIO_Init(void); +static void MX_USART2_UART_Init(void); +static void MX_SPI1_Init(void); +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + + /* USER CODE BEGIN 1 */ + vector_t mag_data = { .v = {0} }; + extern uint8_t MMC5983MA_SETTINGS[3]; + + /* USER CODE END 1 */ + + /* MCU Configuration--------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ + HAL_Init(); + + /* USER CODE BEGIN Init */ + + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* USER CODE BEGIN SysInit */ + + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_USART2_UART_Init(); + MX_SPI1_Init(); + /* USER CODE BEGIN 2 */ + MMC5983MA_SW_Reset(); + MMC5983MA_Init(); + + /* USER CODE END 2 */ + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) + { + MMC5983MA_ReadMagneticField18(&mag_data); + printf("x:%f y:%f z:%f", mag_data.v[0], mag_data.v[1], mag_data.v[2]); + HAL_Delay(5); + /* USER CODE END WHILE */ + + /* USER CODE BEGIN 3 */ + } + /* USER CODE END 3 */ +} + +/** + * @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); + + /** Initializes the RCC Oscillators according to the specified parameters + * in the RCC_OscInitTypeDef structure. + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; + 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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) + { + Error_Handler(); + } +} + +/** + * @brief SPI1 Initialization Function + * @param None + * @retval None + */ +static void MX_SPI1_Init(void) +{ + + /* USER CODE BEGIN SPI1_Init 0 */ + + /* USER CODE END SPI1_Init 0 */ + + /* USER CODE BEGIN SPI1_Init 1 */ + + /* USER CODE END SPI1_Init 1 */ + /* SPI1 parameter configuration*/ + hspi1.Instance = SPI1; + hspi1.Init.Mode = SPI_MODE_MASTER; + hspi1.Init.Direction = SPI_DIRECTION_2LINES; + hspi1.Init.DataSize = SPI_DATASIZE_8BIT; + hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; + hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; + hspi1.Init.NSS = SPI_NSS_SOFT; + hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; + hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; + hspi1.Init.TIMode = SPI_TIMODE_DISABLE; + hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + hspi1.Init.CRCPolynomial = 7; + hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE; + hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE; + if (HAL_SPI_Init(&hspi1) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN SPI1_Init 2 */ + + /* USER CODE END SPI1_Init 2 */ + +} + +/** + * @brief USART2 Initialization Function + * @param None + * @retval None + */ +static void MX_USART2_UART_Init(void) +{ + + /* USER CODE BEGIN USART2_Init 0 */ + + /* USER CODE END USART2_Init 0 */ + + /* USER CODE BEGIN USART2_Init 1 */ + + /* USER CODE END USART2_Init 1 */ + huart2.Instance = USART2; + huart2.Init.BaudRate = 115200; + huart2.Init.WordLength = UART_WORDLENGTH_8B; + huart2.Init.StopBits = UART_STOPBITS_1; + huart2.Init.Parity = UART_PARITY_NONE; + huart2.Init.Mode = UART_MODE_TX_RX; + huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart2.Init.OverSampling = UART_OVERSAMPLING_16; + huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; + huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1; + huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; + if (HAL_UART_Init(&huart2) != HAL_OK) + { + Error_Handler(); + } + if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK) + { + Error_Handler(); + } + if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK) + { + Error_Handler(); + } + if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN USART2_Init 2 */ + + /* USER CODE END USART2_Init 2 */ + +} + +/** + * @brief GPIO Initialization Function + * @param None + * @retval None + */ +static void MX_GPIO_Init(void) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + /* USER CODE BEGIN MX_GPIO_Init_1 */ + + /* USER CODE END MX_GPIO_Init_1 */ + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOF_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET); + + /*Configure GPIO pin : B1_Pin */ + GPIO_InitStruct.Pin = B1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct); + + /*Configure GPIO pin : SPI1_CS_Pin */ + GPIO_InitStruct.Pin = SPI1_CS_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(SPI1_CS_GPIO_Port, &GPIO_InitStruct); + + /*Configure GPIO pin : LED_GREEN_Pin */ + GPIO_InitStruct.Pin = LED_GREEN_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(LED_GREEN_GPIO_Port, &GPIO_InitStruct); + + /*Configure GPIO pin : PB12 */ + GPIO_InitStruct.Pin = GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* USER CODE BEGIN MX_GPIO_Init_2 */ + + /* USER CODE END MX_GPIO_Init_2 */ +} + +/* USER CODE BEGIN 4 */ + +/* USER CODE END 4 */ + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return state */ + __disable_irq(); + while (1) + { + } + /* USER CODE END Error_Handler_Debug */ +} +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t *file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line number, + ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ diff --git a/main.h b/main.h new file mode 100644 index 0000000..5ef0cd6 --- /dev/null +++ b/main.h @@ -0,0 +1,85 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.h + * @brief : Header for main.c file. + * This file contains the common defines of the application. + ****************************************************************************** + * @attention + * + * Copyright (c) 2025 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. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __MAIN_H +#define __MAIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32g0xx_hal.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Exported types ------------------------------------------------------------*/ +/* USER CODE BEGIN ET */ + +/* USER CODE END ET */ + +/* Exported constants --------------------------------------------------------*/ +/* USER CODE BEGIN EC */ + +/* USER CODE END EC */ + +/* Exported macro ------------------------------------------------------------*/ +/* USER CODE BEGIN EM */ + +/* USER CODE END EM */ + +/* Exported functions prototypes ---------------------------------------------*/ +void Error_Handler(void); + +/* USER CODE BEGIN EFP */ + +/* USER CODE END EFP */ + +/* Private defines -----------------------------------------------------------*/ +#define B1_Pin GPIO_PIN_13 +#define B1_GPIO_Port GPIOC +#define MCO_Pin GPIO_PIN_0 +#define MCO_GPIO_Port GPIOF +#define SPI1_CS_Pin GPIO_PIN_0 +#define SPI1_CS_GPIO_Port GPIOA +#define USART2_TX_Pin GPIO_PIN_2 +#define USART2_TX_GPIO_Port GPIOA +#define USART2_RX_Pin GPIO_PIN_3 +#define USART2_RX_GPIO_Port GPIOA +#define LED_GREEN_Pin GPIO_PIN_5 +#define LED_GREEN_GPIO_Port GPIOA +#define TMS_Pin GPIO_PIN_13 +#define TMS_GPIO_Port GPIOA +#define TCK_Pin GPIO_PIN_14 +#define TCK_GPIO_Port GPIOA + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +#ifdef __cplusplus +} +#endif + +#endif /* __MAIN_H */ diff --git a/sensors_defs.h b/sensors_defs.h new file mode 100644 index 0000000..57e7633 --- /dev/null +++ b/sensors_defs.h @@ -0,0 +1,58 @@ +/** + * @file sensors.h + * @brief Header file for sensor initialization and data reading functions. + * + * This file contains the definitions for initializing and reading data from + * various sensors including IMU, Barometer, Magnetometer, Accelerometer, + * and GPS. It also includes function prototypes for temperature sensors. + * + * @authors Amelia Ellis + * @date 2025-04-10 + * @version 0.1 + * @bug No known bugs. + * + * @todo Remove fake_hal.h and replace with actual HAL header. + * @todo Add error handling for sensor initialization and data reading. + */ +#ifndef SENSORS_H +#define SENSORS_H + +#include +#include +#include +#include +#include "stm32g0xx_hal.h" + + +#define SENSORS_MAGFIELD_EARTH_MAX \ + (60.0F) /**< Maximum magnetic field on Earth's surface */ +#define SENSORS_MAGFIELD_EARTH_MIN \ + (30.0F) /**< Minimum magnetic field on Earth's surface */ +#define SENSORS_PRESSURE_SEALEVELHPA \ + (1013.25F) /**< Average sea level pressure is 1013.25 hPa */ +#define SENSORS_DPS_TO_RADS \ + (0.017453293F) /**< Degrees/s to rad/s multiplier */ +#define SENSORS_RADS_TO_DPS \ + (57.29577793F) /**< Rad/s to degrees/s multiplier */ +#define SENSORS_GAUSS_TO_MICROTESLA \ + (100) /**< Gauss to micro-Tesla multiplier */ +#define SENSORS_MICROTESLA_TO_GAUSS \ + (0.01F) /**< Micro-Tesla to Gauss multiplier */ +#define SENSORS_MG_TO_MS2 \ + (0.00980665F) /**< mg to m/s^2 multiplier */ +#define SENSORS_MS2_TO_MG \ + (101.971621F) /**< m/s^2 to mg multiplier */ + +#define SENSORS_GRAVITY_STANDARD (9.80665F) /**< Standard gravity in m/s^2 */ + + +#define SENSORS_SPI_TIMEOUT 2000 /**< SPI timeout in milliseconds */ + +// SPI Handle +extern SPI_HandleTypeDef hspi1; + +typedef struct { + float v[3]; // 0 - X, 1 - Y, 2 - Z +} vector_t; + +#endif // SENSORS_H