Skip to content

Công nghệ 9 giây

“Website hướng dẫn, thử nghiệm và giải thích công nghệ theo cách dễ hiểu cho mọi người.”

Menu
  • Home
  • Công nghệ
  • STM32
  • ESP32
  • Altium Desinger
  • Kiến thức điện máy
Menu

BÀI 50 – ĐIỀU KHIỂN 2 MOTOR ĐỘC LẬP BẰNG ENCODER + PID TRÊN STM32F103

Posted on August 23, 2026August 23, 2026 by congnghe9s

BÀI 50 – ĐIỀU KHIỂN 2 MOTOR ĐỘC LẬP BẰNG ENCODER + PID TRÊN STM32F103

Đây là một cột mốc rất quan trọng trong chuỗi bài học của chúng ta.

Từ Bài 49, ta đã có:

Target Position
      ↓
Position Controller
      ↓
Target Speed
      ↓
Speed PID
      ↓
PWM
      ↓
Motor
      ↓
Encoder

Nhưng đó mới là 1 motor.

Trong Bài 50, chúng ta xây dựng hệ thống cho 2 motor độc lập:

                    STM32F103
                   /         \
                  /           \
             LEFT MOTOR    RIGHT MOTOR
                │               │
             Encoder L       Encoder R
                │               │
                ▼               ▼
             Speed L          Speed R
                │               │
                ▼               ▼
             PID L            PID R
                │               │
                ▼               ▼
             PWM L            PWM R

Đây chính là nền móng của robot 2 bánh vi sai – differential drive robot.


1. Tại sao phải điều khiển 2 motor độc lập?

Giả sử bạn ra lệnh:

PWM Left  = 60%
PWM Right = 60%

Bạn có thể nghĩ:

Hai bánh sẽ chạy cùng tốc độ.

Nhưng thực tế không chắc.

Ví dụ:

Left  = 105 RPM
Right = 92 RPM

Robot sẽ:

          ↗
        /
      /
    /
  START

Nó bị lệch sang một phía.


2. Tại sao cùng PWM nhưng tốc độ khác nhau?

Có rất nhiều nguyên nhân:

  • Hai motor không hoàn toàn giống nhau.
  • Ma sát hai bánh khác nhau.
  • Điện trở cuộn dây khác nhau.
  • Tải hai bên khác nhau.
  • Bánh xe có đường kính thực tế hơi khác.
  • Hộp số có sai số.
  • Điện áp motor thay đổi.
  • Mặt sàn không đồng đều.

Vì vậy:

PWM trái = PWM phải

không đồng nghĩa với:

RPM trái = RPM phải

3. Encoder giải quyết vấn đề này

Mỗi motor có một encoder:

LEFT MOTOR
    │
    ▼
ENCODER L
    │
    ▼
RPM_L

và:

RIGHT MOTOR
    │
    ▼
ENCODER R
    │
    ▼
RPM_R

Sau đó mỗi motor có một PID riêng.


4. Hai PID độc lập

Target RPM L ──► PID L ──► PWM L ──► Motor L
                    ▲                    │
                    │                    ▼
                  RPM L ◄────────── Encoder L

và:

Target RPM R ──► PID R ──► PWM R ──► Motor R
                    ▲                    │
                    │                    ▼
                  RPM R ◄────────── Encoder R

Hai vòng này hoạt động độc lập.


5. Đây là ý tưởng quan trọng nhất của Bài 50

Nếu muốn robot đi thẳng:

Target RPM L = 100
Target RPM R = 100

PID sẽ tự điều chỉnh:

PWM L
PWM R

để cuối cùng:

Actual RPM L ≈ 100
Actual RPM R ≈ 100

Cho dù:

PWM L ≠ PWM R

Điều này hoàn toàn bình thường.


6. Ví dụ thực tế

Giả sử:

Target L = 100 RPM
Target R = 100 RPM

Ban đầu:

Actual L = 80 RPM
Actual R = 70 RPM

PID tính:

Error L = 20
Error R = 30

Do đó:

PWM L = 55%
PWM R = 62%

Motor phải có thể được cấp PWM lớn hơn để bắt kịp.

Sau một thời gian:

Actual L = 100 RPM
Actual R = 100 RPM

PID sẽ giảm PWM về mức cần thiết.


7. Kiến trúc tổng thể

                         STM32F103
                             │
              ┌──────────────┴──────────────┐
              │                             │
              ▼                             ▼
         LEFT CONTROL                  RIGHT CONTROL
              │                             │
       Target RPM L                   Target RPM R
              │                             │
              ▼                             ▼
          PID LEFT                     PID RIGHT
              │                             │
              ▼                             ▼
           PWM LEFT                      PWM RIGHT
              │                             │
              ▼                             ▼
          MOTOR LEFT                    MOTOR RIGHT
              │                             │
              ▼                             ▼
         ENCODER LEFT                   ENCODER RIGHT
              │                             │
              ▼                             ▼
           RPM LEFT                      RPM RIGHT
              │                             │
              └──────────────┬──────────────┘
                             ▼
                         STM32F103

8. Phần cứng cần gì?

Một hệ thống cơ bản:

STM32F103C8T6
      │
      ├── Motor Driver
      │      ├── Left Motor
      │      └── Right Motor
      │
      ├── Encoder Left
      │
      └── Encoder Right

Ví dụ driver:

TB6612FNG

hoặc các driver H-bridge phù hợp với motor.


9. Mỗi motor cần 2 loại tín hiệu

Motor driver

PWM
DIR

Encoder

A
B

Vậy hai motor có:

Motor L:
PWM_L
DIR_L
ENC_L_A
ENC_L_B

Motor R:
PWM_R
DIR_R
ENC_R_A
ENC_R_B

10. STM32F103 có đủ Timer không?

Đây là câu hỏi rất quan trọng.

STM32F103 có nhiều timer:

TIM1
TIM2
TIM3
TIM4

và một số timer khác tùy package.

Ta có thể bố trí:

TIM2 → Encoder Left
TIM3 → Encoder Right

Còn PWM:

TIM1 / TIM4

hoặc sử dụng các channel PWM phù hợp với chân phần cứng thực tế.

Không nên chọn chân trước rồi mới kiểm tra Timer mapping.

Đối với STM32, cần kiểm tra:

Timer
  ↓
Channel
  ↓
GPIO Alternate Function

11. Hai Encoder Timer Mode

Ví dụ:

TIM2 → Encoder Left
TIM3 → Encoder Right

Cả hai đều ở:

Encoder Mode

Sau đó:

left_count  = TIM2->CNT;
right_count = TIM3->CNT;

12. Không nên dùng trực tiếp CNT làm vị trí dài hạn

Giống Bài 48, chúng ta tạo:

volatile int32_t left_position;
volatile int32_t right_position;

Sau mỗi chu kỳ:

int16_t left_now;
int16_t right_now;

int16_t left_delta;
int16_t right_delta;

rồi:

left_position += left_delta;
right_position += right_delta;

13. Cấu trúc Encoder

Ta có thể dùng:

typedef struct
{
    int16_t last_count;
    int32_t position;

    float rpm;

} Encoder_t;

Khai báo:

Encoder_t left_encoder;
Encoder_t right_encoder;

14. Cập nhật encoder

void Encoder_Update(
    Encoder_t *enc,
    volatile uint16_t *cnt)
{
    int16_t current;
    int16_t delta;

    current = (int16_t)(*cnt);

    delta =
        current - enc->last_count;

    enc->position += delta;

    enc->last_count =
        current;
}

Sau đó:

Encoder_Update(
    &left_encoder,
    &TIM2->CNT);

Encoder_Update(
    &right_encoder,
    &TIM3->CNT);

15. Tính RPM

Giả sử:

CPR = 400

và chu kỳ đo:

10 ms

Tức:

dt = 0.01 s

Nếu trong 10 ms encoder tăng:

20 counts

thì:

[
RPM =
\frac{20}{400}
\times
\frac{60}{0.01}
]

=

300 RPM

16. Hàm tính RPM

float Encoder_CalculateRPM(
    int16_t delta,
    float cpr,
    float dt)
{
    return
        ((float)delta / cpr)
        * (60.0f / dt);
}

Ví dụ:

left_encoder.rpm =
    Encoder_CalculateRPM(
        left_delta,
        400.0f,
        0.01f);

17. Bây giờ có hai PID

Ở Bài 49 chúng ta có:

PID_t speed_pid;

Bây giờ phải có:

PID_t left_pid;
PID_t right_pid;

Đây là điểm rất quan trọng.


18. Khởi tạo

Ví dụ:

PID_Init(
    &left_pid,
    2.0f,
    0.5f,
    0.0f,
    -1000.0f,
    1000.0f);

và:

PID_Init(
    &right_pid,
    2.0f,
    0.5f,
    0.0f,
    -1000.0f,
    1000.0f);

Ban đầu có thể dùng cùng thông số.

Sau này hai motor có thể cần tuning khác nhau.


19. Target RPM

Ta tạo:

float target_left_rpm;
float target_right_rpm;

Ví dụ robot đi thẳng:

target_left_rpm  = 100.0f;
target_right_rpm = 100.0f;

20. Speed PID Left

float pwm_left;

pwm_left =
    PID_Update(
        &left_pid,
        target_left_rpm,
        left_encoder.rpm,
        0.01f);

21. Speed PID Right

float pwm_right;

pwm_right =
    PID_Update(
        &right_pid,
        target_right_rpm,
        right_encoder.rpm,
        0.01f);

Sau đó:

Motor_Left_SetPWM(
    (int16_t)pwm_left);

Motor_Right_SetPWM(
    (int16_t)pwm_right);

22. Đây chính là hai vòng kín

LEFT:

Target RPM
    ↓
 PID L
    ↓
PWM L
    ↓
Motor L
    ↓
Encoder L
    ↓
RPM L
    └──────► PID L

và:

RIGHT:

Target RPM
    ↓
 PID R
    ↓
PWM R
    ↓
Motor R
    ↓
Encoder R
    ↓
RPM R
    └──────► PID R

23. Hàm điều khiển hai motor

Ta có thể viết:

void Motors_ControlUpdate(void)
{
    float pwm_left;
    float pwm_right;

    pwm_left =
        PID_Update(
            &left_pid,
            target_left_rpm,
            left_encoder.rpm,
            0.01f);

    pwm_right =
        PID_Update(
            &right_pid,
            target_right_rpm,
            right_encoder.rpm,
            0.01f);

    Motor_Left_SetPWM(
        (int16_t)pwm_left);

    Motor_Right_SetPWM(
        (int16_t)pwm_right);
}

24. Vấn đề cực kỳ quan trọng: chiều motor

Giả sử:

PWM Left  = +
PWM Right = +

nhưng do hai motor được lắp đối xứng:

Left motor  → tiến
Right motor → lùi

thì robot sẽ quay tại chỗ.

Vì vậy cần chuẩn hóa chiều.

Ví dụ:

#define LEFT_MOTOR_INVERTED  0
#define RIGHT_MOTOR_INVERTED 1

25. Hàm xử lý chiều

void Motor_Right_SetPWM(
    int16_t pwm)
{
    if (pwm >= 0)
    {
        Motor_Right_Forward();
    }
    else
    {
        Motor_Right_Reverse();
        pwm = -pwm;
    }

    if (pwm > PWM_MAX)
        pwm = PWM_MAX;

    Motor_Right_PWM(pwm);
}

Nếu motor phải bị đảo chiều vật lý, ta đảo trong driver.


26. Encoder cũng có thể bị đảo chiều

Đây là lỗi rất thường gặp.

Bạn ra lệnh:

Motor Forward

nhưng encoder báo:

RPM = -100

Có nghĩa là:

Motor direction

và:

Encoder direction

không cùng quy ước.

Ta có thể thêm:

#define LEFT_ENCODER_INVERTED  0
#define RIGHT_ENCODER_INVERTED 1

27. Quy tắc rất quan trọng

Sau khi cấu hình:

Motor Forward

phải đảm bảo:

Encoder RPM > 0

và:

Motor Reverse

phải:

Encoder RPM < 0

Nếu không, PID sẽ hoạt động sai dấu.


28. Một lỗi nguy hiểm

Giả sử:

Target = +100 RPM
Actual = -100 RPM

PID thấy:

Error = 200 RPM

và tăng PWM.

Nhưng motor càng chạy nhanh theo chiều ngược.

→ hệ thống có thể mất ổn định.

Vì vậy phải kiểm tra dấu encoder trước khi chạy PID.


29. Test từng motor trước

Đừng lập tức chạy:

Left PID + Right PID

Hãy test:

Motor trái

PWM = +30%

Kiểm tra:

RPM > 0

Motor phải

PWM = +30%

Kiểm tra:

RPM > 0

Sau đó mới bật PID.


30. Test PID từng bên

Trước tiên:

Left:
Target = 50 RPM
Right:
Target = 0

Kiểm tra motor trái.

Sau đó:

Left:
Target = 0
Right:
Target = 50 RPM

Kiểm tra motor phải.

Chỉ khi hai PID đều hoạt động ổn định, mới chạy đồng thời.


31. Đi thẳng bằng hai PID

Bây giờ:

Target Left  = 100 RPM
Target Right = 100 RPM

Giả sử motor trái khỏe:

PWM L = 45%

motor phải yếu:

PWM R = 55%

Nhưng:

RPM L ≈ 100
RPM R ≈ 100

Robot sẽ đi thẳng tốt hơn rất nhiều so với PWM cố định.


32. Nhưng vẫn có thể lệch

Encoder PID chỉ đảm bảo:

RPM L ≈ RPM R

Không đảm bảo tuyệt đối:

Distance L = Distance R

vì:

  • encoder sai số;
  • bánh trái/phải khác đường kính;
  • encoder CPR khác nhau;
  • bánh trượt;
  • mặt sàn không đều.

Do đó robot thực tế có thể cần thêm:

Differential correction


33. Hiệu chỉnh chênh lệch hai bánh

Giả sử:

RPM L = 100
RPM R = 95

ta tính:

[
Error_{sync}=RPM_L-RPM_R
]

=

5

Sau đó:

Correction = Ksync × ErrorSync

Ví dụ:

Ksync = 0.2

thì:

Correction = 1

34. Tạo tốc độ mục tiêu hiệu chỉnh

Nếu tốc độ cơ bản:

100 RPM

thì:

Left target  = 100 - Correction
Right target = 100 + Correction

hoặc ngược lại tùy quy ước.

Ví dụ:

Left  = 99
Right = 101

để hai bánh đồng bộ hơn.


35. Nhưng chưa nên thêm correction ngay

Ở Bài 50, ta nên làm theo thứ tự:

1. Encoder Left
2. Encoder Right
3. RPM Left
4. RPM Right
5. PID Left
6. PID Right
7. Hai motor chạy cùng RPM
8. Sau đó mới thêm synchronization

Đây là cách debug dễ nhất.


36. Kiến trúc phần mềm

Một project sạch có thể:

Core/
│
├── motor.c
├── motor.h
│
├── encoder.c
├── encoder.h
│
├── pid.c
├── pid.h
│
└── robot.c
    robot.h

37. motor.h

Ví dụ:

#ifndef MOTOR_H
#define MOTOR_H

void Motor_Left_SetPWM(int16_t pwm);
void Motor_Right_SetPWM(int16_t pwm);

void Motor_Left_Stop(void);
void Motor_Right_Stop(void);

#endif

38. encoder.h

#ifndef ENCODER_H
#define ENCODER_H

typedef struct
{
    int16_t last_count;
    int32_t position;
    float rpm;

} Encoder_t;

void Encoder_Init(void);

void Encoder_Update(void);

int32_t Encoder_LeftPosition(void);
int32_t Encoder_RightPosition(void);

float Encoder_LeftRPM(void);
float Encoder_RightRPM(void);

#endif

39. pid.h

#ifndef PID_H
#define PID_H

typedef struct
{
    float kp;
    float ki;
    float kd;

    float integral;
    float previous_error;

    float output_min;
    float output_max;

} PID_t;

void PID_Init(
    PID_t *pid,
    float kp,
    float ki,
    float kd,
    float min,
    float max);

float PID_Update(
    PID_t *pid,
    float target,
    float actual,
    float dt);

void PID_Reset(PID_t *pid);

#endif

40. robot.h

#ifndef ROBOT_H
#define ROBOT_H

void Robot_Init(void);

void Robot_SetSpeed(
    float left_rpm,
    float right_rpm);

void Robot_Stop(void);

void Robot_ControlUpdate(void);

#endif

41. robot.c

static PID_t left_pid;
static PID_t right_pid;

static float target_left_rpm;
static float target_right_rpm;

Khởi tạo:

void Robot_Init(void)
{
    PID_Init(
        &left_pid,
        2.0f,
        0.5f,
        0.0f,
        -1000.0f,
        1000.0f);

    PID_Init(
        &right_pid,
        2.0f,
        0.5f,
        0.0f,
        -1000.0f,
        1000.0f);
}

42. Đặt tốc độ

void Robot_SetSpeed(
    float left_rpm,
    float right_rpm)
{
    target_left_rpm =
        left_rpm;

    target_right_rpm =
        right_rpm;
}

Ví dụ:

Robot_SetSpeed(
    100.0f,
    100.0f);

→ đi thẳng.


43. Quay tại chỗ

Nếu:

Robot_SetSpeed(
    80.0f,
    -80.0f);

thì:

Left  → tiến
Right → lùi

Robot quay tại chỗ.


44. Quay trái

Ví dụ:

Robot_SetSpeed(
    40.0f,
    100.0f);

Kết quả:

Left  chậm
Right nhanh

Robot quay trái.


45. Quay phải

Robot_SetSpeed(
    100.0f,
    40.0f);

→ robot quay phải.


46. Lùi

Robot_SetSpeed(
    -80.0f,
    -80.0f);

→ cả hai bánh lùi.


47. Robot Control Update

void Robot_ControlUpdate(void)
{
    float pwm_left;
    float pwm_right;

    pwm_left =
        PID_Update(
            &left_pid,
            target_left_rpm,
            left_encoder.rpm,
            0.01f);

    pwm_right =
        PID_Update(
            &right_pid,
            target_right_rpm,
            right_encoder.rpm,
            0.01f);

    Motor_Left_SetPWM(
        (int16_t)pwm_left);

    Motor_Right_SetPWM(
        (int16_t)pwm_right);
}

48. Tần số điều khiển

Một lựa chọn tốt ban đầu:

Timer = 1 ms

Sau đó:

10 ms → Speed PID

Tức:

100 Hz

Đây là tần số khá phù hợp cho bài học motor DC nhỏ.


49. main.c

Về logic:

int main(void)
{
    System_Init();

    Encoder_Init();

    Motor_Init();

    Robot_Init();

    Robot_SetSpeed(
        100.0f,
        100.0f);

    while (1)
    {
        if (control_flag)
        {
            control_flag = 0;

            Encoder_Update();

            Robot_ControlUpdate();
        }
    }
}

Trong project thực tế, control_flag có thể được set bởi Timer interrupt.


50. Không nên tính RPM bằng delay

Tránh kiểu:

while(1)
{
    delay_ms(100);

    read_encoder();

    calculate_rpm();
}

Vì sau này robot còn phải xử lý:

Encoder
PID
Ultrasonic
UART
Bluetooth
OLED/LCD
State Machine

Dùng Timer tick sẽ tốt hơn.


51. Luồng điều khiển chuẩn

Timer 1 ms
    │
    ├── Encoder sampling
    │
    └── 10 ms
           │
           ▼
      Calculate RPM
           │
           ▼
       PID Left
           │
       PID Right
           │
           ▼
      Update PWM

52. Một bài test rất quan trọng

Đặt:

Target L = 100 RPM
Target R = 100 RPM

Ghi lại:

Time | RPM_L | RPM_R | PWM_L | PWM_R

Ví dụ:

0 ms    0      0       0      0
100     70     65      60     65
200     92     88      52     57
300     99     98      48     51
400     100    100     47     50

Đây là kết quả tốt.


53. Nếu thấy

RPM_L = 100
RPM_R = 85

mặc dù:

Target L = Target R = 100

thì:

PID R

cần được tuning lại.

Không nên sửa bằng:

Target R = 110

ngay lập tức.

Bởi vì mục tiêu của PID là làm:

Actual R → Target R

chứ không phải bù sai số bằng tay.


54. Tuning hai PID

Một quy trình tốt:

Motor trái

Target = 50 RPM

tune:

Kp
Ki
Kd

Motor phải

Target = 50 RPM

tune riêng.

Sau đó:

Target L = 100
Target R = 100

test đồng thời.


55. Một lưu ý về Kd

Ở motor DC nhỏ, encoder thường tạo RPM dạng:

80
100
80
100

thay vì:

90
91
92
93

Nếu Kd quá lớn:

Derivative

sẽ khuếch đại nhiễu.

Vì vậy ban đầu:

kd = 0;

thường dễ tune hơn.

Sau đó mới thử:

Kd > 0

nếu thực sự cần.


56. Bài tập thực hành

Bài tập 1

Cho:

Target L = 100 RPM
Target R = 100 RPM

Hãy đo:

RPM L
RPM R
PWM L
PWM R

Bài tập 2

Cho:

Left = 100 RPM
Right = 50 RPM

Robot sẽ quay về phía nào?

→ Về phía bánh chậm hơn, tức phía trái nếu Left = 50 và Right = 100; với Left = 100, Right = 50 thì robot quay phải.


Bài tập 3

Cho:

Left = 80
Right = -80

Robot làm gì?

→ Quay tại chỗ.


57. Bài tập quan trọng nhất

Hãy làm robot chạy:

100 RPM

trong:

5 giây

Sau đó:

STOP

Đọc:

Left Position
Right Position

Nếu:

Left  ≈ Right

thì hệ thống rất tốt.


58. Từ đây chúng ta đã có nền móng của robot thật

Ta đã có:

             STM32F103
                  │
       ┌──────────┴──────────┐
       │                     │
       ▼                     ▼
   PID LEFT              PID RIGHT
       │                     │
       ▼                     ▼
   PWM LEFT              PWM RIGHT
       │                     │
       ▼                     ▼
 MOTOR LEFT             MOTOR RIGHT
       │                     │
       ▼                     ▼
ENCODER LEFT           ENCODER RIGHT

Đây chính là hệ thống điều khiển 2 bánh độc lập.


59. Nhưng vẫn còn một tầng rất thú vị

Hiện tại ta mới nói:

Left RPM
Right RPM

Nếu muốn robot:

Đi thẳng 1 mét

thì không thể đơn giản nói:

100 RPM trong 5 giây

bởi vì tốc độ không đảm bảo chính xác tuyệt đối.

Ta cần:

Distance Target
       ↓
Encoder Position
       ↓
Position Control
       ↓
Left/Right Target Speed
       ↓
2 Speed PID
       ↓
2 Motor

Và còn phải đảm bảo:

Left distance ≈ Right distance

60. Đây là bước sang Bài 51

BÀI 51 – ROBOT 2 BÁNH ĐI THẲNG CHÍNH XÁC BẰNG 2 ENCODER + PID

Ở Bài 51 chúng ta sẽ xây dựng:

             TARGET DISTANCE
                    │
                    ▼
             POSITION CONTROL
                    │
             ┌──────┴──────┐
             ▼             ▼
       LEFT TARGET      RIGHT TARGET
          SPEED             SPEED
             │               │
             ▼               ▼
          PID LEFT         PID RIGHT
             │               │
             ▼               ▼
          PWM LEFT         PWM RIGHT
             │               │
          MOTOR L          MOTOR R
             │               │
          ENC L            ENC R
             └──────┬────────┘
                    ▼
              DISTANCE

và quan trọng hơn, chúng ta sẽ học cách dùng chênh lệch Encoder trái/phải để tự sửa robot đang lệch khỏi đường thẳng.

Đây chính là bước nối trực tiếp từ kiến thức STM32 Timer/Encoder/PID sang robot 2 bánh thực tế.

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • Bạn có thể hướng dẫn tôi quy trình sửa chữa một mainboard laptop cũng như mainboard của máy tính để bàn không?
  • Có những mức nguồn DC nào trên một bo mạch mainboard laptop?Kỹ thuật đốt dòng để kiểm tra nguồn laptop được thực hiện như thế nào?
  • bài tiếp theo hợp lý là: BÀI 63 – SENSOR FUSION THỰC CHIẾN: ENCODER + IMU MPU6050 + EKF + ODOMETRY X,Y,θ TRÊN STM32F103
  • BÀI 62 – EKF (EXTENDED KALMAN FILTER) CHO ROBOT 2 BÁNH: FUSION ENCODER + IMU + ƯỚC LƯỢNG X, Y, θ, V, ω
  • BÀI 61 – KALMAN FILTER CHO ENCODER + IMU: ƯỚC LƯỢNG TỐC ĐỘ, GÓC θ VÀ SENSOR FUSION

Recent Comments

No comments to show.

Archives

  • September 2026
  • August 2026
  • July 2026
  • June 2026
  • May 2026
  • February 2026

Categories

  • Altium Desinger
  • Công nghệ
  • ESP32
  • Khác
  • Kiến thức điện máy
  • STM32
Live 3D Globes Visitor
©2026 Công nghệ 9 giây | Design: Newspaperly WordPress Theme