• Test Execution 1

    Ghani Lawal16 hours ago 0 comments

    • Finished creating test plan and the associated test matrixes:
      • Test plan (word document) can still use some fine tuning in the procedure
      • Test matrixes (excel document) will also require some fine turning, but the skeleton is good
    • Important notes:
      • Measured the actual resistor values for the input voltage sensor, they are allowing for a much more accurate reading
      • The voltage at the output of the input power multiplexer differs from the output of the PSU, the difference is not negligible because of:
        • The voltage drops bit over the power supply lead wires, they are pretty thick so it isn't that much, maybe a few 10s of mV
        • Between the power supply lead wires and the input terminal block are ~20 awg wires, this caused the unloaded DUT to drop by over 100 mV
        • The transistors in the the power supply multiplexer also have an R-on value, causing the voltage to drop another 20mV or so
        • ***The DUT was unloaded, drawing a max of 150mA from the power supply, so for load and line regulation the voltage drop would be significant
        • Therefore, for measuring DC input voltage, will take the voltage at the output of the power multiplexer
      • Will make an LCD 'smoke test' at a later date, I know it works, but it would be good to make a test program that verifies control and that every pixel can be written to
      • Current sensor calibration might as well be part of ADC testing as I cannot directly measure the current sense resistor, and getting a constant current of any value, especially 500mA will be time consuming, might as well only do it once
      • The resistors for the output current sensor are not electrically isolated from the feedback circuitry for the buck-boost converter, so I cannot get an accurate measurement of them with the DMM
      • For the priority multiplexer, Case A :  TST-02-A3 fails.  The voltage values at the nodes between the input power multiplexer and the output of the priority multiplexer are iteresting... I will record the value of each node at every step in the case to determine what the issue is
      • Oscilloscope:
        • Will be acquiring the ripple voltage waveforms of the input output voltage in "HR" mode, voltage waveforms are more consistent in this mode than "Normal" and "Average Mode"
        • Tried using the ground spring instead of the 'long-lead probe' for higher accurate waveform measurement, doesn't seem to make a difference, will verify later

  • Prep for Testing 9

    Ghani Lawal10/22/2025 at 00:24 0 comments

    • Created pow_10 function, had to know it this because pow10 is the name of an inbuilt function in math.h
      • This function made strictly to calculate integer powers of 10
      • Doesn't take up as much space at the built in pow10 function ("I'm assuming")
    • Also ensured that ftoa 'rounds' the 'afterpoint' digit instead of just cutting off the numbers after 'afterpoint'
    • Major Update - Improved NHD_LCD screen API: 
      • files (source, header and config) no longer dependent on main.h
      • created a handle for the display, 
      • all functions contain the handle in the parameter list 
      • user initializes the handle in the beginning of the main function
    • Seems to be evidence of issue true linearity of ADC differing from actual linearity:
      • Vo set to 2.0V
        • Output Voltage - DC Power Supply Value : VVC Value 
          • 4.00V : 4.0V
          • 5.00V : 5.1V
          • 6.00V : 6.1V
          • 7.00V : 7.1V
          • 8.00V : 8.1V
          • 9.00V : 9.1V
          • 10.00V : 10.2V (infrequently goes down to 10.1V)
          • 11.00V : 11.2V
          • 12.00V : 12.2V
          • 13.00V : 13.2V
          • 14.00V : 14.2V
          • 15.00V : 15.3V (infrequently goes down to 15.2V)
          • 16.00V : 16.3V
          • 17.00V : 17.0V (ADC clips at 17.0V)

  • Important ADC notes

    Ghani Lawal10/16/2025 at 19:08 0 comments

    • What HAL_ADC_START_IT() does:
      • It doesn't directly start the ISR, instead it
        • Starts the ADC conversion in interrupt mode
        • Enables the ADC interrupt so that when the conversion completes, the ADC peripheral will trigger an interrupt
        • The ISR - specifically HAL_ADC_CONVCpltCallback() - is then called automatically by the HAL when the conversion finishes
    • Comparing it ot HAL_ADC_Start:
      • HAL_ADC_Start():
        • Starts ADC conversion in Polling Mode
        • CPU waits (blocks) until conversion is complete
        • You manually call HAL_ADC_GETValue() to retrieve the result
        • No ISR is involved
        • Must be called again after each conversion if not in continuous mode
      • HAL_ADC_START_IT():
        • Starts ADC conversion in Interrupt Mode
        • CPU continues executing other code - non-blocking
        • When converesion completes, ADC triggers an interrupt
        • HAL calls your HAL_ADC_ConvCpltCallback() ISR
        • You typically read the result insdie that callback
        • Also needs to be called again after each conversion unless continuous mode is enabled
    • Blocking Operation:
      • The CPU waits until the operation finishes
      • It does nothing else during that time
      • Example: HAL_ADC_Start() followed by HAL_ADC_PollForConversion() — the CPU sits and waits for the ADC to finish before moving on.
      • Analogy:  Like standing at a microwave waiting for your food - you're not doing anything else until it's done
    • Non-Blocking Operation:
      • The CPU starts the operation then moves on immediately
      • When the operation finishes, it notifies the CPU (via interrupt or callback)
      • Example: HAL_ADC_Start_IT() — ADC runs in the background, and the CPU keeps working until the ISR fires.
      • Analogy: Like setting atime on the oven and going to do laundry - the oven beeps when it's done, and you respond then
    • Blocking is simpler to implement, but it wastes CPU cycles
    • Non-Blocking is efficient and let's you multitask - ideal for real-time systems or juggling multiple peripherals
    • DMA: Direct Memory Access
      • hardware feature that let's peripherals (like ADCs) transfer data directly to memory - without involving the CPU
      • HAL_ADC_Start_DMA():
        • The ADC starts converting
        • DMA controller watches the ADC
        • As soon as a conversion completes, DMA automatically copies the result into a buffer in RAM
        • The CPU is never blocked, and no ISR is needed for each sample
        • When the buffer is full (or transfers completes) DMA triggers an interrupt - and you anlde it with HAL_ADC_ConvCpltCallback() or HAL_ADC_ConvHalfCpltCallback()
    • Polling: Best for simple, one shot reads
    • Interrupt: Best for event driven sampling
    • DMA: Best for high-speed, multichannel, contiuous sampling

  • Prep for Testing 8

    Ghani Lawal10/16/2025 at 18:34 0 comments

    • Gained a deeper understanding of the different modes of an ADC
    • Finally got Oversampling Mode to work
    • Helpful Resources:

    • ***After the for loop where I get the current raw ADC values for the voltages and currents, I have to add "HAL_ADC_STOP(&hadc1)" to get oversampling to work

                Apparently, "Calling HAL_ADC_Stop(&hadc1) after the entire for loop ensures that before the $100ms delay and the start of the next while(1) cycle, the ADC peripheral is completely reset and put into a clean IDLE state. This allows the very first HAL_ADC_Start() of the new cycle (for $i=0$) to initialize the sequence correctly and produce valid oversampled data again."

  • Prep for Testing 7

    Ghani Lawal10/13/2025 at 21:14 0 comments

    • Erase last page of flash memory if once there is no more space available to log new error entries, the save entry to the first double word
      • HAL_FLASHEx_Erase
      • Used FLASH_BANK_1 for FLASH_ErasteInitTypeDef.bank value
    • Learned that if you press  CTR + <Space Bar> allows for "auto-complete"
    • Figured out why the STM32G030F6Px microcontroller has 32 pages of 2kB Flash memory as opposed to 16 pages when the official FLASH size is 32Kbytes
      • Due to how STMicroelectronics manufactures and markets its chips
      • 32 KB (Total Flash Size) / 2 KB (Page Size) = 16 pages, so this expecation is that there would only be 16 pages, 0 to 15
      • Discrepency due to "die harvesting" or "untamed flash":
        • 1. Common Silicon Die
          • company often uses the same physical silicon chip (die) for an entire series of microcontrollers, such as the STM32G0 line, which can have max Flash sizes up to 64KB or 128KB
        • 2. Marketing and Testing Limits
          • STM32G030F6Px is officially specified in the datasheet to have only 32KB of Flash memory
          • ** This means that the company only guarantees that the first 32KB (Page 0 to Page 15) will work perfectly across all operating conditions
          • They may disable or not guarantee the use of the rest of Flash memory
        • 3. Untested/Unused Flash
          • Since the physcial chip is often a larger die (like the one used for teh 64KB or 128KB version), it physically contains more Flash memory thatn 32KB specified
          • Page 31 is a physically present but officially unsupported section of the chip's Flash memory
          • The fact that it worked is a very common experience
    • #2 STM32 HAL (Flash Memory (read and erase data))

  • Prep for Testing 6

    Ghani Lawal10/09/2025 at 22:02 0 comments

    • Looked into best ways to handle and log/output (HAL) errors:
      • Google Gemini: Handling HAL Error in Embedded C
        • Researched handling non-recoverable hardwre failures
        • Learned usefullness of tokens __FILE__ and __LINE__ for loggiing and debugging
      • Google Gemini: Understanding Executable Programs Sections
        • Gained deeper understanding of the <project name>.list file, as well as where and how program file (.elf file) is transfered to the microcontroller
          • Section of notice - Using Flash Memory for Persistent Logging I think this was when I confirmed I would store errors and meta data in FLASH
        • Important functions HAL_FLASH_UNLOCK(), HAL_FLASH_Program(), HAL_FLASH_ErasePage()
        • Realized I need to make a struct to combine all the data I want to log
        • First learned that I need to and how to modify the .ld (linker script) file
        • STM32CubeIDE user guide - User manual also contained info on modifying Linker script to reserve sections of Flash memory
      • Google Gemini: STM32 HAL Flash Programming Explained
        • Helped me address issues with storing data in Flash
        • Gave me a fix on how to re-order elements in my log_struct to avoid padding with member values, allowing all of the data to fit within 8 bytes
    • ***For a long time my original completed program size was nearly 32KB, due to that there wasn't enough space for me to reserve the last page for error logging.  Then I removed the pow(...) function from the math.h library from my float2string API, and the size of the program reduced by about 10kB, allowing me to reserve the last page of FLASH**
      • Google Gemini: Debugging Flash Erase Error
        • Learned I could look and modify the memory of the microcontroller with the STM32CubeProgrammer
      • Target not halted error:
        • Once I realized I had 10kB of space to work with I tried to debug with openOCD
        • unfortunately, due to the fact that "STM32G030/G031/G041 family multiplexes BOOT0 with SWCLK (PA14) to save pins on smaller packages" ... "That means every time the debugger toggles SWCLK (PA14), it risks altering BOOT0’s logic level during reset or startup."
          • So even though the ST-LINK successfully connected to the microcontroller,  OpenCD and CubeIDE couldn't halt the microcontroller
          • a Grounding Resistor at Boot0/SWCLK could solve the problem, but it is not guaranteed
    • Page 8 of stm32g030c6 data sheet stated that " Information on memory mapping and control registers is object of reference manual RM0454"
    • From RM0454 learned/confirmed that that:
      • Flash memory size: 32 KB, page size: 2KB
      • Flash memory starts at 0x08000000
      • Last page of Flash memory: 0x0800F800
      • One 'word' is 32 bits, 4 bytes
      • It is only possible to program Flash memory with a double word (2x32 bits = 64 bits = 8 bytes) at a time
        • Also, each double word must be aligned with a double word address
    • Made new structure - typedef struct log_struct_t
      • char b0: will always equal 'I' indicates that this double word Index of Flash does store an error log, also to show then the next value will be the log index
      • uint8_t error_count: 2KB/ 8 bytes = 256 possible indexes, value should match the index long is stored at
      • char source: 'M' for taking place in beginninig of main function, 'O' if error takes place during 'regular operation', possible values are subject to changed
      • char b2: will always be 'T', indicates that the next value will be the code for the type of error that is stored
      • uint8_t err_type: One of the possible NHD_LCDstatus_t values
      • char b1: will always be 'L' indicates that the next value will be the line number
      • uint16_t: the value of __LINE__ where the error took place

  • Prep for Testing 5

    Ghani Lawal10/09/2025 at 20:52 0 comments

    • Went into Properties->C/C++ General->Formatter, created new formatter sytle called "My 2-Space Tab Style": replaces 'Tab' with 2 spaces to better match STM32 code style
    • Modified code to be more inline with the 'Embedded C Coding Standard' by Micahel Barr

  • Prep for Testing 4

    Ghani Lawal10/09/2025 at 20:07 0 comments

    • Flash overflow fix
    • Attempted to concatent strings with snprintf:
      • was orignally using strcat:
        • strcat has no way of anding buffer overflow
        • also, strcat finds where to add new string to the buffer by starting at the first index of the buffer and increasing the index until it finds a cell with a NULL character, this is inefficient
      • snprintf keeps track of last non-NULL index and protects agains buffer overflow, but iin order to not cause Flash to overflow by 624 bytes, needed to change MCU/MPU GCC Compiler->Optimization->Optimization level from None (-O0) to Optimize for size (-Os), but this "optimizes out" some of the outputs in debug mode, making it difficult to use
    • Combined string using memcpy, before doing so I check that the lenght of the combined string will fit into the buffer, and keep track of the index of the last non-NULL value to increase efficiency

  • Prep for Testing 3

    Ghani Lawal10/09/2025 at 19:50 0 comments

    • Added NHD_LCDstatus_t enum to NHD_LCD API:
      • Google Gemini: Handling HAL status in STM32
      • data_write and cmd_write, both of which call HAL_SPI_transmit(..) which returns HAL_StatusTypeDef, associate all of the possible HAL_statusTypeDef codes with a NHD_LCDstatus_t
      • all functions within this API will have a return type of NHD_LCDstatus_t
    • Changed name of comm_write() funtion in NHD_LCD to cmd_write (short for command) to reduce confusion
    • Improved erase_trails() function logic:
      • defined number of bytes needed to represent a character, number of columns in in the LCD screen and the number of character rows in the LCD screen
    • Made erase trails a helper function of print_data, no longer directly callable from the mai function

  • Prep for Testing 2

    Ghani Lawal10/09/2025 at 18:15 0 comments

    • All int-type variables are now implemented with appropriate fixed-width data types
    • Changed 'char *array' data type in printdata(...) and erasetrails(...) their parameter list to 'const char* array' because the values in those arrays or not to be modified
    • Updated ftao function to:
      • to be able to handle negative numbers, nan and inf conditions, and to convert negative numbers into strings
      • place '0' infront of decimal point if abs(number) < 1
    • changed the name of stringtofloat source and header files to float2string - accuratly reflects purpose of the library