---
# System prepended metadata

title: Product design
tags: [product design]

---

[toc]
## Test stand 影片介紹
[類似的1](https://www.youtube.com/watch?v=-yq1EmTkBCs&t=271s&pp=ygUXcm9ja2V0IG1vdG9yIHRlc3Qgc3RhbmQ%3D)
[類似的2](https://www.youtube.com/watch?v=LyU8Yo3oiW4&t=447s&pp=ygUXcm9ja2V0IG1vdG9yIHRlc3Qgc3RhbmQ%3D)
## Progress/ Difficulty
### 結構
訂單皆已送出 2023/7/22
完成組裝 2023/7/27
### PCB
PCB1 送出 2023/7/22
### Code
[Github](https://github.com/Herokroos/Product-design)
檔案建立 2023/7/22
### Integrated Test
[Video](https://youtu.be/qLWEzkJWCpg)
### Difficulty
2023/7/23
原本選的`STM32L010F4P6`的 **`Flash(16KB)`** 跟 **`RAM(2KB)`** 不夠，因此需要先把程式完成，查看所需大小再替換換新的MCU。後來決定使用STM32F103C8這款MCU。他有

## 組別
- 工程組

    設計、製作test stand
- 公關組

    IG帳號經營
    shopee帳號建立(目前不確定)
    與其他團體接洽(目前已知 ISP 屏中社團 台東高中生 建中航空社)
- 美宣組
    
    製作相關介紹影片(以全英文為主)
    產品介紹影片製作
    Fusion 360 Animation + 實際測試影片
    產品使用影片製作 
    Fusion 360 Animation + 操作步驟 
## 發想
Amateur rocketeers要自己做出穩定的推力量測裝置實屬不容易，因此想開發一款可靠性高且平價的test stand 
:::warning
:warning: [Warning, do not click this, Pls](https://youtu.be/bhh-pXDzqJA)
:::
![](https://hackmd.io/_uploads/HykLAOfMa.jpg)
## Requirements/ Limitations
設計一款test stand，適用於小型motor，具 **推力量測及資料紀錄功能**
推力範圍限制:最大不可超過10KG

## Specification
DAQ
- MCU
- AD-DC (HX711)
- SD Card connector
- Reset button
- Tare button
- Start button
- Power Supply Indicator
- SD Card Status Indicator
- Buzzer

## Architecture
### Flow chart
![](https://hackmd.io/_uploads/ByA_FQtF3.png)


## Operating steps 
|時間戳記|         實體操作         |   MCU事件控制    | 蜂鳴器狀態指示 | LED指示燈 |
|:---:|:------------------------:|:----------------:|:--------------:|:---------:| 
|     |         硬體組裝         |       ---        |      ---         |    ---    |
|     |        記憶卡插入        |       ---        |      ---         |   ---    |
|     |         電池上電         |       ---        |      ---         |   ---      |
|     | 系統測試(測試sd卡讀的到)   | SD卡寫入測試訊息   |       Pattern 0         |---|
|     |        motor置入        | Load cell測試     |       ---        |      LED blinks     | 
|     |        點火頭置入        |       ---        |     ---          |     ---      |
|     |           扣重           |  HX711讀值歸零   |--- |     LED blinks and off      |
|T-10 |       倒數計時開始       |       Timer initialize        |      Pattern 1    |    ---         |
|T-0  |           點火          |   MOSFET高電平/資料記錄開始|    Pattern 2      |     ---      | 
|T+2  |           ---          |    MOSFET低電平 |  ---  |   ---        | 
|T++  |           ---          |   資料寫入SD卡    |       ---          |   ---        | 
|T+10 |           ---          |   資料記錄結束     |     Pattern 3      |   ---        | 
|T+20 |       系統結束操作       |       ---         |     Pattern 4     |   ---        | 
|     |         電池移除         |       ---        |      ---           |  ---         |
|     |           收拾          |       ---        |      ---           |  ---         |

## Component development
### Thrust range 
> 10kg 

### Load cell 
> [10kg load cell](https://cdn.sparkfun.com/datasheets/Sensors/ForceFlex/TAL220M4M5Update.pdf?_gl=1*1rga2nj*_ga*MTA0NTA0NjkzOS4xNjg3NzkwNDcy*_ga_T369JS7J9N*MTY4ODg5ODYxNS4xLjAuMTY4ODg5ODYxNS4wLjAuMA..)


### Hardware Development
結構件:
>2020鋁型材 (3DPRT-MAKER創客專賣店)
>160mm 數量4
>木芯板 (木百貨) 
>200 * 300 * 18 mm 數量1

3D列印件:
> 固定件 * 2

固定件:
>Hex Head Screws (3DPRT-MAKER創客專賣店)
>內六角 M5 * 40 數量8
>
>Phillips Screws/ Rounded Head Screws (商品不含運滿50元才出貨)
>十字 M4 * 6  數量2
>十字 M4 * 20 數量2
>十字 M5 * 30 數量4
>
>Socket Head Cap Screw (3DPRT-MAKER創客專賣店)
>內六角螺絲 M4 * 8 數量16
>
>T-slot Nut (3DPRT-MAKER創客專賣店)
>T型螺母 M4 數量16
>
>Hex Standoff, Male-Female
>六角黃銅螺柱 M4 * 10(內牙螺) * 6(外螺牙) 數量4
>
>---
>Spacer Support for PCB (商品不含運滿50元才出貨)
>六角黃銅螺柱 M3 * 10 數量4
>十字 M3 * 8 數量4
## DAQ Software&Hardware Configuration 
### Private user code
```c
/*  create a function in order to delay  */
void delay_ms(uint32_t target) {
	__HAL_TIM_SET_COUNTER(&htim2, 0);
	while(__HAL_TIM_GET_COUNTER(&htim2) < target) {
		// waiting counter to count to target
	    }
}
/*  create a function in order indicate the stauts of the loadcell  */
void LC_func(uint32_t times){
	for (int i =0;i<= times;i++ ){
		HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);// high level
		delay_ms(200);
		HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);// low level
		delay_ms(200);
	}
	HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);// low level
	delay_ms(1800);
}
```
### Timer
#### Timer Configuration
:::info
:bulb:
Using Timer2; APB1 timer clocks
記數單位設定為1000ms
![](https://hackmd.io/_uploads/BJFY6_L5h.png)

Timer clock frequency(Hz) = 8MHz
Prescaler = 8000 - 1
Counter Period = 10000

    8MHz/8000 * 1000 = 1Hz = 1000ms
:::
#### Basic code
```c
/* create a function to count time*/
void delay_ms(int target) {
	__HAL_TIM_SET_COUNTER(&htim2, 0);
	HAL_TIM_Base_Start(&htim2);
	while(__HAL_TIM_GET_COUNTER(&htim2) < target) {
		// waiting counter to count to target
	    }
}
/*  init the TIM  */
static void MX_TIM2_Init(void){
    /* USER CODE BEGIN TIM2_Init 2 */
    HAL_TIM_Base_Start(&htim2); // start the TIM
    /* USER CODE END TIM2_Init 2 */
 }

```
---
### printf
```c
/* USER CODE BEGIN 4*/
int __io_putchar(int ch) {
    ITM_SendChar(ch);
    return ch;
}
```
---
### LED
#### GPIO Configuration
:::info
:bulb: 
GPIO **`GPIO_Output`**
GPIO output level **`Low`**
GPIO mode **`Output Push Pull`** 
GPIO Pull-up/ Pull-down **`No push-up and no pull-down`**
Maximum output speed **`Low`**
User Lable **`LED`**
:::
#### Basic Code
```c
/* in main.h */
#define LED_Pin GPIO_PIN_2
#define LED_GPIO_Port GPIOA 

/*  in main.c  */
while(1){
    HAL_GPIO_TogglePin(LED_GPIO_Port, LED_PIN);// 翻轉狀態
    HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);// high level
    HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);// low level
}
```
### Buzzer
#### GPIO Configuration
:::info
:bulb: 
GPIO **`GPIO_Output`**
GPIO output level **`Low`**
GPIO mode **`Output Push Pull`** 
GPIO Pull-up/ Pull-down **`No push-up and no pull-down`**
Maximum output speed **`Low`**
User Lable **`Buzzer`**
:::
|            時間戳記              | Pattern | High level |Low level|extra|
|:-------------------------------:|:-------:|:----------:|:------:|:---:|
| When the SD Card can't be read  |    0    |   400ms    | 200ms |High level 400ms|
| At T-10(Start button is pressed) |    1    |   500ms    | 500ms |10times|
|             At T-0             |    2    |   1000ms   | 9000ms|     |
|             At T=10             |    3    |   200ms    | 800ms |     |
|             At T=20             |    4    |   2000ms   |       |     |

#### Code
```c
/*  in main.h  */
#define Buzzer_Pin GPIO_PIN_0
#define Buzzer_GPIO_Port GPIOB

/*  in main.c  */
while(1){
    /*  pattern 0  */
    HAL_GPIO_WritePin(Buzzer_GPIO_Port, Buzzer_Pin, GPIO_PIN_SET);// high level
    delay_ms(400);
    HAL_GPIO_WritePin(Buzzer_GPIO_Port, Buzzer_Pin, GPIO_PIN_RESET);// low level
    delay_ms(200);
    HAL_GPIO_WritePin(Buzzer_GPIO_Port, Buzzer_Pin, GPIO_PIN_SET);// high level
    delay_ms(400);
    HAL_GPIO_WritePin(Buzzer_GPIO_Port, Buzzer_Pin, GPIO_PIN_SET);// low level    
    
    /*  pattern 1  */
    for(int p1 = 0; p1 < 10; p1++){// repeats 10 times
        HAL_GPIO_WritePin(Buzzer_GPIO_Port, Buzzer_Pin, GPIO_PIN_SET);// high level
        delay_ms(500);
        HAL_GPIO_WritePin(Buzzer_GPIO_Port, Buzzer_Pin, GPIO_PIN_RESET);// low level
        delay_ms(500);
    }
    
    /*  pattern 2  */
    HAL_GPIO_WritePin(Buzzer_GPIO_Port, Buzzer_Pin, GPIO_PIN_SET);// high level
    delay_ms(1000);
    HAL_GPIO_WritePin(Buzzer_GPIO_Port, Buzzer_Pin, GPIO_PIN_RESET);// low level
    delay_ms(9000);

    /*  pattern 3  */
    HAL_GPIO_WritePin(Buzzer_GPIO_Port, Buzzer_Pin, GPIO_PIN_SET);// high level
    delay_ms(200);
    HAL_GPIO_WritePin(Buzzer_GPIO_Port, Buzzer_Pin, GPIO_PIN_RESET);// low level
    delay_ms(800);
    
    /*  pattern 4  */
    HAL_GPIO_WritePin(Buzzer_GPIO_Port, Buzzer_Pin, GPIO_PIN_SET);// high level
    delay_ms(2000);
    HAL_GPIO_WritePin(Buzzer_GPIO_Port, Buzzer_Pin, GPIO_PIN_RESET);// low level
    
}
```
---

### Button
#### Configuration 
:::info
:bulb:
1. **Tare button**
GPIO **`GPIO_Input`**
GPIO mode **`Input mode`** 
GPIO Pull-up/ Pull-down **`No push-up and no pull-down`**
User Lable **`Tare`**
2. **Start button**
GPIO **`GPIO_Input`**
GPIO mode **`Input mode`** 
GPIO Pull-up/ Pull-down **`No push-up and no pull-down`**
User Lable **`SWpin`**
:::
#### Code
```c
/*  in main.h  */
#define Tare_Pin GPIO_PIN_10 //tare button
#define Tare_GPIO_Port GPIOA 
#define SWpin_Pin GPIO_PIN_1 // start button
#define SWpin_GPIO_Port GPIOA

/*  in main.c  */
/* USER CODE BEGIN PV */
int Tare_button_state = 0;
int Start_button_state = 0;
/* USER CODE END PV */
while(1){
    Tare_button_state = HAL_GPIO_ReadPin(Tare_GPIO_Port, Tare_Pin);
    if(Tare_button_state == GPIO_PIN_RESET){// low level
        //tare
        }
    Start_button_state = HAL_GPIO_ReadPin(SWpin_GPIO_Port,SWpin_Pin);
    if(Start_button_state == GPIO_PIN_RESET){// low level
        //sequence start
    }
}
```
---
### SD CARD
#### Configuration 
:::info
:bulb: **SD CARD configuration**
1.  Set the SD CARD `format` to **FAT32**, `allocation unit size` **4096**
![](https://hackmd.io/_uploads/rk9Nc6g33.png)
if the allocation unit size does not have the option `4096`, you may follow steps below to change it
- Win+R, enter `diskmgmt.msc`
- Select and right click the micro sd card, click the **Format**  
- Select the `file system` **FAT32**, `allocation unit size` **4096**
- Apply
:::
:::info

1.  SPI1 Mode **`Full duplex Master`**
2.  select one pin
    GPIO **`GPIO_Output`**    
    GPIO mode **`Push-Pull`**
    User_Lable: **`SD_CS`**
3.    **MIddleware** >>FAT32
    --> User define
    --> Enable **`USE_LFN`** with `Enabled with static working buffer on the BSS`
    --> Set **`MAX_SS`** `4096`
    --> Generate Code
4.  Include **Library** into STM32CUBEIDE
[fatfs_sd.h](https://raw.githubusercontent.com/eziya/STM32_SPI_SDCARD/master/Old_STM32F1/Inc/fatfs_sd.h)
[fatfs_sd.c](https://raw.githubusercontent.com/eziya/STM32_SPI_SDCARD/master/Old_STM32F1/Src/fatfs_sd.c)
6. **Modifications**
    Modify the File
    **`stm32l0xx.it.c`**
    **`user_diskio.c`**
    See the code at [here](https://embetronicx.com/tutorials/microcontrollers/stm32/stm32-sd-card-interfacing-with-example/)
:::

#### Code in main.c
```c
#include "fatfs.h"
#include "fatfs_sd_card.h"
#include "string.h"
#include "stdio.h"
#include "stdbool.h"

float Thrust;

int main(void){
    process_SD_card();
    while(1){
        ...
        /* SD writing */
        fres = f_mount(&FatFs, "", 1);    //1=mount now
        if (fres != FR_OK)
        {
          printf("No SD Card found : (%i)\r\n", fres);
          break;
        }
        printf("SD Card Mounted Successfully!!! data coming in!!!\r\n");
        fres = f_open(&fil, "data.txt", FA_WRITE | FA_READ | FA_CREATE_ALWAYS);
        if(fres != FR_OK)
        {
          printf("File creation/open Error : (%i)\r\n", fres);
          break;
        }
        //write the data
        printf("Writing data!!!\r\n");
        
        f_puts("Confirmation SD card open successfully", &fil);

        
        
        //close your file
        f_close(&fil);
        printf("Closing File!!!\r\n");
        /* unmount SD card*/
        f_mount(NULL, "", 0);
        printf("SD Card Unmounted Successfully!!!\r\n");
    
    }
}

void process_SD_card( void ){
  FATFS       FatFs;                //Fatfs handle
  FIL         fil;                  //File handle
  FRESULT     fres;                 //Result after operations
  char        buf[100];

  do
  {
    //Mount the SD Card
    fres = f_mount(&FatFs, "", 1);    //1=mount now
    if (fres != FR_OK)
    {
      printf("No SD Card found : (%i)\r\n", fres);
      break;
    }
    printf("SD Card Mounted Successfully!!!\r\n");

    //Read the SD Card Total size and Free Size
    FATFS *pfs;
    DWORD fre_clust;
    uint32_t totalSpace, freeSpace;

    f_getfree("", &fre_clust, &pfs);
    totalSpace = (uint32_t)((pfs->n_fatent - 2) * pfs->csize * 0.5);
    freeSpace = (uint32_t)(fre_clust * pfs->csize * 0.5);

    printf("TotalSpace : %lu bytes, FreeSpace = %lu bytes\n", totalSpace, freeSpace);

    //Open the file
    fres = f_open(&fil, "data.txt", FA_WRITE | FA_READ | FA_CREATE_ALWAYS);
    if(fres != FR_OK)
    {
      printf("File creation/open Error : (%i)\r\n", fres);
      break;
    }

    printf("Writing data!!!\r\n");
    //write the data
    f_puts("Confirmation SD card open successfully", &fil);

    //close your file
    f_close(&fil);
    printf("Closing File!!!\r\n");
    
  } while( false );
  //We're done, so de-mount the drive
  f_mount(NULL, "", 0);
  printf("SD Card Unmounted Successfully!!!\r\n");
}
```
#### Reference
[Reference](https://embetronicx.com/tutorials/microcontrollers/stm32/stm32-sd-card-interfacing-with-example/)
[FAT32 functions](http://elm-chan.org/fsw/ff/00index_e.html)


---

### HX711
[Github](https://github.com/PCov3r/HX711-STM32-Library/tree/main)
[flaot to string](https://www.796t.com/content/1541228343.html)
[enable the printf in stm32CubeIDE](https://blog.csdn.net/sudaroot/article/details/105099807)
#### Configuration 
:::info
:bulb:q
1.  GPIO **`GPIO_Output`**  
    GPIO mode **`No push-up and no pull-down`**
    User_Lable: **`PD-SCK`**
2.  GPIO **`GPIO_Input`**  
    GPIO mode **`No push-up and no pull-down`**
    User_Lable: **`DAT`**
:::
#### Calibration
:::info
:bulb:
calibrate the coef by adjusting the x in
**`hx711_coef_set(&loadcell, x);`**
that **hx711_weight** = 0
:::
```C
/* in main.c*/
#include "hx711.h"
hx711_t loadcell;
float Thrust;
.
.
int main()
{
  hx711_init(&loadcell, PD-SCK_GPIO_Port, PD-SCK_Pin, DAT_GPIO_Port, DAT_Pin); 
  hx711_coef_set(&loadcell, x); // read afer calibration, x varies with different loadcell
  hx711_tare(&loadcell, 10); // tare the value
  while (1)
  {  
    HAL_Delay(500);
    Thrust = hx711_weight(&loadcell, 10);
  }
}
```
#### Code
```C
/* in hx711.c*/
/* add code below before hx711_delay_us */
static inline void __nop(void)
{
    __asm__ __volatile__("nop");
}

/* in main.c*/
#include "hx711.h"
hx711_t loadcell;
float Thrust;
.
.
int main()
{
  hx711_init(&loadcell, PD-SCK_GPIO_Port, PD-SCK_Pin, DAT_GPIO_Port, DAT_Pin); 
  hx711_coef_set(&loadcell, x); // read afer calibration, x varies with different loadcell
  hx711_tare(&loadcell, 10); // tare the value
  while (1)
  {
    /*  use it only when adjusting the coef  
    HAL_Delay(500);
    */
    Thrust = hx711_weight(&loadcell, 10);
  }
}
```

## PCB Design


PCB (DAQ)
~~STM32L010F4P6~~
[STM32F103C8T6 datasheet](https://www.st.com/resource/en/datasheet/stm32f103c8.pdf)
[STM32F103C8T6 schematic reference1](https://stm32-base.org/assets/pdf/boards/original-schematic-STM32F103C8T6-Blue_Pill.pdf)
[STM32F103C8T6 schematic reference2](https://kicad-info.s3.dualstack.us-west-2.amazonaws.com/original/3X/e/4/e4c88b48af7bf832b11c87d979695b311abeaeb4.svg)
[STM32F103C8T6 schematic reference3](https://i.stack.imgur.com/db32S.png)
[HX711 datasheet](https://cdn.sparkfun.com/datasheets/Sensors/ForceFlex/hx711_english.pdf)
[HX711 schematic](https://image.easyeda.com/components/5a7e011054ba4e0d9779a664469bc3ab.png)
[SD CARD schematic](https://i.stack.imgur.com/mRfRK.jpg)
[Voltage Regulator](https://img-blog.csdnimg.cn/20190225095242384.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1hMX19NQVg=,size_16,color_FFFFFF,t_70)
[CH340 schematic reference(web)](http://nicecircuits.com/ch340g-usb-to-rs232-ttl-module-schematic-d-sun-v3-0/)
[CH340 schematic reference(github)](https://github.com/NiceCircuits/modules_from_china/tree/master/CH340G_D-SUN-V3.0)
## Debug
[terminal](http://www.embedded-communication.com/en/misc/printf-with-st-link/)
[float printf](https://forum.digikey.com/t/easily-use-printf-on-stm32/20157)
## System integration test
測試自製motor

## 已知支出 / 產品內容物
|     品項名稱     | 數量 | 價錢 | 小計 |
|:----------------:|:----:|:----:|:----:|
|   18mm 木芯板    |  1   |  71  |  71  |
|    2020鋁型材    |  4   |  62    |   248   |
| 3D列印件(固定板) |  2   |      |      |
|    M4 T型螺母    |  16  |   3   |   48   |
|  M4*8內六角螺絲  |  16  |  2    |    32  |
| M5*40內六角螺絲  |  8   |  5    |   40   |
|   M4*6十字螺絲   |  2   |  1    |  2    |
|  M4*20十字螺絲   |  2   |   2   |   4   |
|  M5*30十字螺絲   |  4   |   3   |   12   |
|  M4六角黃銅螺柱  |  4   |  3   |  12  |
|   M3六角黃銅螺柱   |  4   |      |      |
|   M3*6十字螺絲   |  4   |      |      |
|       PCB        |  1   |      |      |
|    Load cell     |  1   |      |      |

## 未來規劃
短期目標(9月前): 功能測試
中期目標(學測前): 產品試用 
最終目標(學測前): 進行販售