Công nghệ

Bạn có biết thuật toán firmware điều khiển của bếp từ đơn và bếp từ đôi hay bếp hồng ngoại là thế nào không?

Có. Và firmware của bếp từ thực tế còn thú vị hơn firmware nồi cơm, vì nó phải điều khiển một hệ thống công suất lớn với IGBT/MOSFET đóng cắt ở tần số cao, đồng thời liên tục theo dõi dòng điện, điện áp, nhiệt độ và trạng thái nồi.

Điểm rất hay là bếp từ đơn, bếp từ đôi và bếp hồng ngoại có chung một “bộ não” firmware ở tầng trên, nhưng tầng điều khiển công suất khác nhau.

1. Trước hết hãy nhìn toàn bộ hệ thống

Image

Image

Image

Image

Image

Image

Image

Một bếp từ có thể khái quát:

                 NGƯỜI DÙNG
                     │
              Phím / Touch
                     │
                     ▼
              ┌─────────────┐
              │     MCU     │
              └──────┬──────┘
                     │
       ┌─────────────┼──────────────┐
       │             │              │
       ▼             ▼              ▼
    Sensor        Display        Buzzer
       │
       │
       ├── Nhiệt độ
       ├── Dòng điện
       ├── Điện áp
       ├── Nhiệt IGBT
       └── Phát hiện nồi
                     │
                     ▼
              POWER CONTROL
                     │
                     ▼
                 Gate Driver
                     │
                     ▼
                    IGBT
                     │
                     ▼
               Resonant LC
                     │
                     ▼
                   Cuộn dây
                     │
                     ▼
                 Đáy nồi

Đây chính là closed-loop control.


2. Firmware bếp từ thực chất làm 6 việc lớn

Tôi thường chia nó thành:

1. USER INTERFACE
       ↓
2. STATE MACHINE
       ↓
3. PAN DETECTION
       ↓
4. POWER CONTROL
       ↓
5. SENSOR / FEEDBACK
       ↓
6. SAFETY / PROTECTION

Và tất cả chạy liên tục.


3. Khi vừa cắm điện

MCU không lập tức bật IGBT.

Nó sẽ trải qua một chuỗi kiểu:

POWER ON
   ↓
MCU INIT
   ↓
ADC INIT
   ↓
TIMER INIT
   ↓
GPIO INIT
   ↓
DISPLAY INIT
   ↓
SELF CHECK
   ↓
CHECK SENSOR
   ↓
WAIT

Sau đó:

            ┌───────────┐
            │   STANDBY │
            └─────┬─────┘
                  │
             User presses
                  │
                  ▼
             SELECT MODE
                  │
                  ▼
             CHECK PAN
                  │
          ┌───────┴────────┐
          │                │
       NO PAN            PAN OK
          │                │
          ▼                ▼
      WAIT PAN       START POWER

4. Phát hiện nồi là một phần rất quan trọng

Đây là điểm bếp từ khác bếp điện trở.

Bếp từ phải biết:

“Có nồi phù hợp đặt trên vùng nấu hay không?”

Firmware có thể kích hệ thống ở mức kiểm tra rất nhỏ, sau đó quan sát phản hồi điện:

IGBT / coil
    ↓
Tạo từ trường
    ↓
Quan sát dòng điện / đáp ứng mạch cộng hưởng
    ↓
MCU ADC
    ↓
Pan detection

Nếu:

NO PAN

thì:

IGBT = OFF

Nếu:

PAN DETECTED

thì mới cho phép quá trình điều khiển công suất tiếp tục.


5. Đây mới là “trái tim” của bếp từ

Giả sử người dùng chọn:

POWER = 1200 W

MCU không đơn giản nói:

IGBT = ON;

Bởi vì IGBT phải đóng cắt rất nhanh.

Firmware phải tạo tín hiệu điều khiển:

MCU
 ↓
Timer / PWM
 ↓
Gate Driver
 ↓
IGBT

Ví dụ khái quát:

        ┌──────────────┐
        │ Power target │
        │   1200 W     │
        └──────┬───────┘
               ↓
        Control algorithm
               ↓
        Gate drive command
               ↓
             IGBT
               ↓
            Heater
               ↓
          Measure power
               │
               └──────────► Feedback

Đó chính là vòng kín.


6. MCU phải biết “thực tế đang tiêu thụ bao nhiêu công suất”

Ví dụ người dùng yêu cầu:

1200 W

nhưng hệ thống thực tế có thể đang:

1500 W

Firmware phát hiện:

P_actual > P_target

→ giảm năng lượng đưa vào.

Ngược lại:

P_actual < P_target

→ tăng.

Khái quát:

Target Power
     │
     ▼
┌──────────────┐
│ Controller   │
└──────┬───────┘
       │
       ▼
   IGBT drive
       │
       ▼
    Induction
       │
       ▼
   Actual Power
       │
       └──────► Feedback

7. Nhưng bếp từ không chỉ nhìn công suất

Nó còn nhìn rất nhiều thứ:

ADC
 │
 ├── DC bus voltage
 │
 ├── Current
 │
 ├── Coil temperature
 │
 ├── IGBT temperature
 │
 ├── Pot temperature
 │
 └── Other sensors

Ví dụ:

Temperature IGBT = 75°C

→ bình thường.

Nhưng:

Temperature IGBT = 105°C

→ giảm công suất.

Temperature IGBT = 120°C

→ shutdown.


8. Vì vậy thuật toán thực tế giống thế này

              TARGET POWER
                   │
                   ▼
             POWER CONTROL
                   │
                   ▼
             IGBT DRIVE
                   │
                   ▼
               HEATING
                   │
                   ▼
             SENSOR READ
                   │
          ┌────────┼────────┐
          ▼        ▼        ▼
        Current  Voltage  Temp
          │        │        │
          └────────┼────────┘
                   ▼
              MCU ADC
                   │
                   ▼
          CONTROL DECISION
                   │
          ┌────────┼─────────┐
          ▼        ▼         ▼
       Increase   Hold     Decrease
       power                power

9. Bếp từ đơn tương đối đơn giản

Bếp đơn:

             MCU
              │
              ▼
          Controller
              │
              ▼
            IGBT
              │
              ▼
           Coil #1

Firmware chỉ cần điều khiển:

Zone 1

Ví dụ State Machine:

OFF
 │
 ▼
STANDBY
 │
 ▼
PAN CHECK
 │
 ▼
HEATING
 │
 ├── Increase power
 ├── Maintain
 ├── Decrease
 │
 ├── No pan
 │
 ├── Over temperature
 │
 └── Over current
          │
          ▼
        ERROR

10. Bếp từ đôi thú vị hơn rất nhiều

Bếp đôi:

                 MCU
                  │
          ┌───────┴────────┐
          ▼                ▼
      Controller A     Controller B
          │                │
        IGBT A            IGBT B
          │                │
        Coil A            Coil B

Nhưng hai vùng nấu thường không hoàn toàn độc lập về nguồn điện.

Ví dụ:

AC 220V
   │
Rectifier
   │
DC BUS
   │
   ├──────────► Zone A
   │
   └──────────► Zone B

Giả sử:

Zone A = 1800 W
Zone B = 1800 W

Tổng:

3600 W

nhưng nguồn hoặc thiết kế bếp có thể không cho phép mức đó.

Firmware phải làm:

POWER MANAGEMENT

Ví dụ:

A yêu cầu 1800 W
B yêu cầu 1800 W

Total request = 3600 W

Maximum allowed = 3000 W

→ Firmware phân bổ:
A = 1800 W
B = 1200 W

Đây là một scheduler/power allocator.


11. Đây chính là lý do bếp đôi thường có “chia công suất”

Bạn có thể bắt gặp logic kiểu:

              TOTAL POWER LIMIT
                     │
                     ▼
              POWER MANAGER
                /         \
               /           \
              ▼             ▼
          Zone A          Zone B
          1800W            600W

Nếu người dùng tăng Zone B:

Zone B: 600 → 1200 W

firmware có thể giảm Zone A:

Zone A: 1800 → 1200 W

để:

A + B ≤ POWER_LIMIT

Đây là một bài toán điều khiển rất thú vị.


12. Bếp hồng ngoại thì khác

Bếp hồng ngoại không cần phát hiện nồi bằng nguyên lý cảm ứng.

Phần nhiệt thường là:

AC
 │
 ▼
Heating element
 │
 ▼
Infrared radiation
 │
 ▼
Glass
 │
 ▼
Pot

Firmware chủ yếu điều khiển:

ON/OFF

hoặc điều khiển công suất bằng:

Triac

và zero-cross/phase control tùy thiết kế.

Ví dụ:

Target = 1200 W

100% → 1200 W
 75% →  900 W
 50% →  600 W
 25% →  300 W

Một cách đơn giản là time-proportional control:

10 giây:

██████████ = 100%

███████░░░ = 70%

█████░░░░░ = 50%

██░░░░░░░░ = 20%

13. Bếp hồng ngoại cũng có closed-loop

Ví dụ:

User selects 600°C
        ↓
MCU
        ↓
Read NTC / thermocouple
        ↓
Actual = 450°C
        ↓
Need more heat
        ↓
Heater ON

Sau đó:

Actual = 580°C
        ↓
Reduce power

và:

Actual = 610°C
        ↓
Heater OFF / reduce

14. Một điểm cực kỳ quan trọng: bảo vệ không nằm “sau” điều khiển

Nó phải hoạt động song song.

Không phải:

Control
   ↓
Protection

mà gần hơn là:

                 ┌─────────────┐
                 │             │
                 ▼             │
             CONTROL           │
                 │             │
                 ▼             │
              IGBT             │
                 │             │
                 ▼             │
              HEATER           │
                 │             │
                 ▼             │
              SENSOR           │
                 │             │
                 ▼             │
              MCU ◄─────────────┘
                 ▲
                 │
             SAFETY

Safety có quyền cắt công suất ngay lập tức.


15. Firmware có thể có các mức bảo vệ

Ví dụ:

OVP  → Over Voltage Protection
OCP  → Over Current Protection
OTP  → Over Temperature Protection
UVP  → Under Voltage Protection
OP   → Over Power
NP   → No Pan
NTC  → Sensor fault
IGBT → IGBT fault

Khi có lỗi nghiêm trọng:

ERROR
  ↓
Disable gate
  ↓
IGBT OFF
  ↓
Display error
  ↓
Buzzer
  ↓
Wait for reset/recovery

16. Firmware bếp từ có thể được tổ chức như thế này

Nếu viết theo phong cách STM32:

while (1)
{
    Key_Scan();

    ADC_Process();

    Pan_Detection();

    Power_Control();

    Temperature_Control();

    Power_Manager();

    Safety_Check();

    Display_Update();

    Buzzer_Process();
}

Nhưng phần IGBT gate drive và protection thời gian rất ngắn có thể được xử lý bằng timer/PWM, interrupt hoặc phần cứng chuyên dụng thay vì chờ vòng while(1).


17. Nếu đưa về kiến thức STM32 mà bạn đang học

Bạn sẽ thấy bếp từ là một “bài tập firmware cực lớn”:

Chức năng STM32 có thể dùng
Đọc NTC ADC
Đọc dòng ADC
Đọc điện áp ADC
Điều khiển IGBT Timer/PWM
Zero-cross GPIO/EXTI/Timer
Phát hiện nồi ADC + timer/control
Phím GPIO
Màn hình GPIO/I2C/SPI/UART
Buzzer Timer/GPIO
Timing SysTick/Timer
Watchdog IWDG/WWDG
Fault Interrupt
Power management Software
State machine C

Cho nên nếu bạn hiểu được bếp từ, bạn gần như đã chạm vào rất nhiều kiến thức cốt lõi của firmware embedded.


18. Và có một điều tôi muốn đặc biệt nhấn mạnh

Nếu chúng ta muốn học firmware bếp từ một cách bài bản, tôi không nghĩ nên bắt đầu ngay bằng code.

Ta nên đi theo đúng con đường của một kỹ sư thiết kế firmware:

                 BẾP TỪ
                    │
                    ▼
             ① YÊU CẦU SẢN PHẨM
                    │
                    ▼
             ② STATE MACHINE
                    │
                    ▼
             ③ SENSOR MODEL
                    │
                    ▼
             ④ POWER CONTROL
                    │
                    ▼
             ⑤ SAFETY MODEL
                    │
                    ▼
             ⑥ TIMING / INTERRUPT
                    │
                    ▼
             ⑦ SOFTWARE ARCHITECTURE
                    │
                    ▼
             ⑧ C CODE
                    │
                    ▼
             ⑨ TEST / FAULT INJECTION

Đây cũng chính là cách chúng ta có thể chuyển từ việc bạn đang học những thứ nhỏ như GPIO → Timer → ADC → UART → Interrupt sang tư duy thiết kế một firmware sản phẩm hoàn chỉnh.

Nếu bạn muốn đi sâu, tôi có thể lấy một bếp từ đơn 2000 W làm ví dụ, rồi cùng bạn từ con số 0 thiết kế một firmware hoàn chỉnh trên STM32F103: tôi sẽ vẽ cho bạn sơ đồ khối → State Machine → thuật toán phát hiện nồi → thuật toán điều khiển công suất → ADC đọc dòng/NTC → Timer tạo PWM → bảo vệ OCP/OTP/OVP → watchdog → cuối cùng mới viết main.c.

Thiết kế một firmware hoàn chỉnh trên STM32F103 từ con số 0

Được. Chúng ta sẽ làm theo kiểu một dự án firmware sản phẩm thực tế, nhưng trước tiên tôi muốn đặt một ranh giới an toàn: phần firmware dưới đây sẽ thiết kế cho mô hình học tập/bench prototype điện áp thấp. Không nên dùng STM32F103 trực tiếp để điều khiển mạch 220 VAC/IGBT công suất nếu chưa có thiết kế cách ly, gate driver, bảo vệ phần cứng và quy trình kiểm thử phù hợp.

Và vì bạn vừa nhắc đến interrupt, tôi sẽ đưa interrupt vào đúng vị trí của nó thay vì biến mọi thứ thành một vòng while(1).

1. Mục tiêu của dự án

Ta giả lập một bếp từ đơn 2000 W với STM32F103C8T6:

                    ┌──────────────────────┐
                    │       STM32F103      │
                    │                      │
 User ── Keys ─────►│ GPIO                 │
                    │                      │
 NTC ──────────────►│ ADC                  │
                    │                      │
 Current sensor ───►│ ADC                  │
                    │                      │
 Voltage sensor ───►│ ADC                  │
                    │                      │
                    │ Timer/PWM ──────────►│── Gate driver
                    │                      │
                    │ UART ───────────────►│── PC
                    │                      │
                    │ IWDG                 │
                    └──────────────────────┘

Mục tiêu phần mềm:

  • OFF
  • STANDBY
  • PAN DETECTION
  • HEATING
  • POWER CONTROL
  • OVER-TEMPERATURE
  • OVER-CURRENT
  • NO-PAN
  • ERROR
  • COOLING
  • STOP

2. Trước tiên phải hiểu một nguyên tắc

Đừng viết:

while(1)
{
    đọc nhiệt độ;
    điều khiển IGBT;
    đọc phím;
    ...
}

rồi nhét tất cả vào đó.

Firmware tốt hơn sẽ chia thành:

             HARDWARE
                 │
       ┌─────────┼─────────┐
       ▼         ▼         ▼
     Timer      ADC       GPIO
       │         │         │
       └─────────┼─────────┘
                 ▼
             INTERRUPTS
                 │
                 ▼
          DATA / EVENTS
                 │
                 ▼
          STATE MACHINE
                 │
       ┌─────────┼─────────┐
       ▼         ▼         ▼
     Control   Safety      UI

Interrupt không phải là thuật toán điều khiển.

Interrupt chỉ là cơ chế giúp MCU phản ứng đúng lúc với một sự kiện.


3. Ví dụ cực kỳ đơn giản về interrupt

Giả sử timer tạo interrupt mỗi 1 ms:

Timer
  │
  │ 1 ms
  ▼
Interrupt
  │
  ▼
System tick++

Ta có:

volatile uint32_t system_ms = 0;

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM2)
    {
        system_ms++;
    }
}

Sau đó main() không cần tự đếm thời gian bằng delay.

if (system_ms - last_time >= 10)
{
    last_time = system_ms;

    Key_Scan();
}

Như vậy:

TIM2 interrupt
       │
       ▼
   system_ms
       │
       ├── 10 ms → Key scan
       ├── 100 ms → Temperature control
       ├── 500 ms → Display
       └── 1000 ms → Cooking timer

Đây là tư duy rất quan trọng.


4. Kiến trúc firmware chúng ta sẽ xây

Tôi đề xuất cấu trúc:

Core/
│
├── Inc/
│   ├── cooker.h
│   ├── control.h
│   ├── safety.h
│   ├── sensor.h
│   ├── key.h
│   └── display.h
│
└── Src/
    ├── main.c
    ├── cooker.c
    ├── control.c
    ├── safety.c
    ├── sensor.c
    ├── key.c
    └── display.c

Đây chính là cách một project bắt đầu trở thành firmware architecture, thay vì một file main.c khổng lồ.


5. Trung tâm của firmware: State Machine

Ta định nghĩa:

typedef enum
{
    STATE_OFF = 0,
    STATE_STANDBY,
    STATE_PAN_CHECK,
    STATE_HEATING,
    STATE_COOLING,
    STATE_ERROR
} CookerState_t;

Và:

volatile CookerState_t cooker_state = STATE_OFF;

Sau đó:

void Cooker_Task(void)
{
    switch (cooker_state)
    {
        case STATE_OFF:
            Cooker_Off();
            break;

        case STATE_STANDBY:
            Cooker_Standby();
            break;

        case STATE_PAN_CHECK:
            Cooker_PanCheck();
            break;

        case STATE_HEATING:
            Cooker_Heating();
            break;

        case STATE_COOLING:
            Cooker_Cooling();
            break;

        case STATE_ERROR:
            Cooker_Error();
            break;
    }
}

Đây là trái tim của firmware.


6. Luồng trạng thái

                   POWER ON
                      │
                      ▼
                  SELF TEST
                      │
                      ▼
                  STANDBY
                      │
                  START COOK
                      │
                      ▼
                 PAN CHECK
                 /        \
             NO PAN       PAN OK
               │             │
               ▼             ▼
             WAIT          HEATING
                             │
              ┌──────────────┼───────────────┐
              │              │               │
              ▼              ▼               ▼
          Temperature      Current          User STOP
             high           high               │
              │              │                 ▼
              ▼              ▼              COOLING
            ERROR          ERROR
                             │
                             ▼
                           ERROR

7. Bây giờ đến phần Sensor

Ta có:

typedef struct
{
    uint16_t adc_ntc;
    uint16_t adc_current;
    uint16_t adc_voltage;

    float temperature;
    float current;
    float voltage;
} SensorData_t;

và:

SensorData_t sensor;

ADC sẽ cập nhật dữ liệu.

Ví dụ:

void Sensor_Process(void)
{
    sensor.adc_ntc     = ADC_Read_NTC();
    sensor.adc_current = ADC_Read_Current();
    sensor.adc_voltage = ADC_Read_Voltage();

    sensor.temperature = NTC_To_Temperature(sensor.adc_ntc);
    sensor.current     = ADC_To_Current(sensor.adc_current);
    sensor.voltage     = ADC_To_Voltage(sensor.adc_voltage);
}

8. Một điều rất quan trọng: ADC không nên được đọc tùy tiện

Với hệ thống điều khiển công suất, chúng ta có thể dùng:

ADC
 │
 ├── software polling
 │
 ├── interrupt
 │
 └── DMA

Nếu có nhiều kênh ADC, DMA rất hữu ích:

ADC
 │
 ├── Channel 1 → NTC
 ├── Channel 2 → Current
 └── Channel 3 → Voltage
          │
          ▼
         DMA
          │
          ▼
      RAM buffer

CPU không phải liên tục:

ADC_Read();
ADC_Read();
ADC_Read();

DMA làm việc đó.

Đây chính là mối liên hệ với câu hỏi trước của bạn về DMA giống như một “tay sai” cho CPU.


9. Power Controller

Giả sử người dùng yêu cầu:

Power target = 1000 W

Ta có:

typedef struct
{
    float target_power;
    float actual_power;

    uint8_t output_percent;
} PowerControl_t;

Thuật toán đơn giản ban đầu:

void Power_Control(void)
{
    float error;

    power.actual_power =
        sensor.voltage * sensor.current;

    error =
        power.target_power -
        power.actual_power;

    if (error > 100)
    {
        power.output_percent += 5;
    }
    else if (error < -100)
    {
        power.output_percent -= 5;
    }

    if (power.output_percent > 100)
        power.output_percent = 100;
}

Đây chưa phải thuật toán điều khiển bếp từ thương mại. Nó chỉ là bộ điều khiển đơn giản để chúng ta xây dựng kiến trúc.


10. Sau đó Output Controller mới điều khiển phần công suất

void Power_Output_Task(void)
{
    if (cooker_state == STATE_HEATING)
    {
        PWM_SetPower(power.output_percent);
    }
    else
    {
        PWM_SetPower(0);
    }
}

Điểm cực kỳ quan trọng:

CONTROL quyết định:
       "cần bao nhiêu công suất?"

OUTPUT quyết định:
       "phát lệnh phần cứng như thế nào?"

Hai thứ này nên tách nhau.


11. Safety phải có quyền cao hơn Control

Đây là kiến trúc rất quan trọng:

                 POWER CONTROL
                      │
                      ▼
                Requested Power
                      │
                      ▼
                 SAFETY CHECK
                      │
              ┌───────┴────────┐
              │                │
             SAFE             FAULT
              │                │
              ▼                ▼
          OUTPUT POWER       OUTPUT OFF

Ví dụ:

void Safety_Process(void)
{
    if (sensor.temperature > MAX_TEMP)
    {
        fault = FAULT_OVER_TEMP;
        cooker_state = STATE_ERROR;
    }

    if (sensor.current > MAX_CURRENT)
    {
        fault = FAULT_OVER_CURRENT;
        cooker_state = STATE_ERROR;
    }
}

Và:

void Power_Output_Task(void)
{
    if (cooker_state == STATE_ERROR)
    {
        PWM_SetPower(0);
        return;
    }

    PWM_SetPower(power.output_percent);
}

12. Nhưng bảo vệ quan trọng không nên chỉ dựa vào software

Đây là điểm rất quan trọng đối với bếp thật.

Ví dụ:

Current sensor
      │
      ├────────► ADC → Software
      │
      └────────► Hardware comparator
                         │
                         ▼
                    Gate shutdown

Nếu dòng quá lớn:

OCP
 │
 ▼
Hardware
 │
 ▼
Disable gate

không cần chờ:

ADC → CPU → while loop

Đối với mạch công suất cao, hardware protection và software protection nên tồn tại đồng thời.


13. Main loop cuối cùng sẽ rất sạch

Ví dụ:

int main(void)
{
    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();
    MX_ADC1_Init();
    MX_TIM2_Init();
    MX_USART1_UART_Init();

    Sensor_Init();
    Control_Init();
    Safety_Init();
    Cooker_Init();

    HAL_TIM_Base_Start_IT(&htim2);

    while (1)
    {
        Sensor_Task();

        Safety_Task();

        Cooker_Task();

        Control_Task();

        Power_Output_Task();

        Key_Task();

        Display_Task();

        HAL_IWDG_Refresh(&hiwdg);
    }
}

Bạn thấy điều gì?

main() không chứa thuật toán chi tiết.

Nó giống một người quản lý:

Sensor_Task()
Safety_Task()
Cooker_Task()
Control_Task()
Power_Output_Task()
Key_Task()
Display_Task()

14. Còn interrupt làm việc phía dưới

Ví dụ:

             TIM2
               │
             1 ms
               │
               ▼
       Timer Interrupt
               │
               ▼
          system_ms++

ADC DMA:

              ADC
               │
          conversion
               │
               ▼
              DMA
               │
               ▼
             RAM
               │
               ▼
        Sensor_Process()

Nút nhấn nếu cần phản ứng tức thời có thể dùng EXTI:

BUTTON
  │
  ▼
GPIO EXTI
  │
  ▼
Interrupt
  │
  ▼
Set event flag

Ví dụ:

volatile uint8_t key_event = 0;

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == KEY_START_Pin)
    {
        key_event = 1;
    }
}

Sau đó không nên xử lý cả một đống logic trong ISR.

ISR chỉ:

Hardware event
     ↓
Set flag
     ↓
Exit interrupt

Còn:

if (key_event)
{
    key_event = 0;
    Process_Start_Key();
}

được xử lý trong main loop.

Đây là một nguyên tắc firmware rất quan trọng:

ISR càng ngắn càng tốt; ISR báo sự kiện, còn application xử lý sự kiện.


15. Toàn bộ firmware lúc này có thể hình dung như một hệ thống

                         STM32F103
                            │
        ┌───────────────────┼────────────────────┐
        │                   │                    │
        ▼                   ▼                    ▼
     INTERRUPT            MAIN LOOP            DMA
        │                   │                    │
   ┌────┼────┐       ┌──────┼──────┐             │
   │    │    │       │      │      │             │
 Timer EXTI ADC     Sensor Safety Control       ADC
   │    │    │       │      │      │             │
   └────┴────┘       └──────┴──────┘             │
        │                   │                    │
        ▼                   ▼                    │
      Events          State Machine ◄────────────┘
                            │
                            ▼
                       Power Control
                            │
                            ▼
                         PWM/TIMER
                            │
                            ▼
                       Gate Driver
                            │
                            ▼
                       Power Stage

Đây chính là kiến trúc firmware mà tôi muốn chúng ta xây.


16. Và tôi đề xuất chúng ta không viết toàn bộ code ngay

Nếu viết ngay vài nghìn dòng code thì bạn sẽ rất khó hiểu.

Chúng ta sẽ xây giống như xây một sản phẩm thật:

Giai đoạn 1 — MCU foundation

STM32F103
│
├── GPIO
├── Timer
├── Interrupt
├── ADC
├── DMA
├── UART
└── Watchdog

Giai đoạn 2 — Firmware framework

main loop
   ↓
scheduler
   ↓
tasks

Giai đoạn 3 — Sensor

NTC
Current
Voltage

Giai đoạn 4 — State Machine

OFF
STANDBY
PAN CHECK
HEATING
COOLING
ERROR

Giai đoạn 5 — Control

Target
 ↓
Controller
 ↓
PWM

Giai đoạn 6 — Safety

OTP
OCP
OVP
Sensor fault
Watchdog

Giai đoạn 7 — Test

Normal
 ↓
No pan
 ↓
NTC disconnected
 ↓
Over temperature
 ↓
Over current
 ↓
MCU hang

Và đặc biệt, tôi muốn chúng ta làm từng bước trên chính STM32F103C8T6 của bạn

Bước đầu tiên tôi đề nghị chưa đụng đến 220 V, IGBT hay cuộn dây.

Chúng ta sẽ tạo một “bếp từ giả lập” trên Blue Pill:

                    STM32F103
                       │
        ┌──────────────┼──────────────┐
        │              │              │
       ADC            GPIO           UART
        │              │              │
        ▼              ▼              ▼
  Potentiometer     Buttons          PC
   = Nhiệt độ       = START          Monitor
   = Dòng           = STOP
   = Điện áp        = POWER
                       │
                       ▼
                  State Machine
                       │
                       ▼
                    PWM LED
                       │
                       ▼
                 "Heater giả"

Sau đó trên UART bạn sẽ nhìn thấy kiểu:

[BOOT]
SELF TEST OK
STATE = STANDBY

START
PAN DETECTED
STATE = HEATING

TEMP = 45.2 C
POWER TARGET = 800 W
OUTPUT = 42 %

TEMP = 63.8 C
POWER TARGET = 800 W
OUTPUT = 31 %

TEMP = 95.4 C
SAFETY: OK

TEMP = 120.5 C
FAULT: OVER TEMPERATURE
OUTPUT = 0 %
STATE = ERROR

Khi mô hình này chạy đúng, chúng ta mới thay “heater giả + potentiometer” bằng các khối cảm biến/công suất thực tế.

Như vậy bạn sẽ hiểu được toàn bộ chuỗi:

Interrupt → Timer → ADC → DMA → State Machine → Control Algorithm → PWM → Safety → Watchdog

thay vì chỉ copy một đoạn main.c rồi không hiểu tại sao nó hoạt động.

About the author

lbtmicr06

Leave a Comment