• HOME
  • DỰ ÁN & MẠCH ĐIỆN
    • Lập trình
      • ARDUINO PROJECT
      • ESP8266 PROJECT
      • ESP32 PROJECT
      • RASPBERRY PI PROJECT
      • Vi điều khiển
    • Điện tử ứng dụng
      • Audio / Amplifiers
      • Nguồn điện
      • Pin sạc/Acquy và mạch sạc
      • Biến đổi AC và DC
      • Robotic
      • Cảm biến
      • LED
      • LCD
      • Động cơ bước
      • Mạch linh tinh
      • Test & Measurement
      • RF – FM
    • Nixie Clock
    • HOME AUTOMATION
    • Dân dụng
    • Công nghiệp
  • KIẾN THỨC CĂN BẢN
    • Điện tử cơ bản
    • Điện tử số
    • PCB
    • Nixie Tube
    • Raspberry Pi
    • Vi điều khiển
    • Arduino
    • IN 3D
  • DOWNLOAD
    • Phần mềm điện tử
    • Giáo trình
      • Giáo trình Điện – Điện tử
      • Giáo trình Tự Động Hóa
      • Giáo trình Viễn thông
    • Đề tài
      • Đề tài – Điện – Điện Tử
      • Đề tài – Tự Động Hóa
      • Đề tài – Viễn thông
    • Điện tử ứng dụng
    • Tài liệu nước ngoài
    • Hướng dẫn, sửa chữa
    • Sơ đồ, nguyên lý thiết bị
    • Tiêu chuẩn – Đo lường – Thử nghiệm
    • Datasheet
  • LIÊN HỆ
  • SẢN PHẨM

Mạch Điện Lý Thú

Sơ đồ nguyên lý, PCB, đồ án, tài liệu, DIY

Trang chủ » DỰ ÁN & MẠCH ĐIỆN » Lập trình » ESP8266 PROJECT » Xe hai bánh tự cân bằng dùng ESP8266

Xe hai bánh tự cân bằng dùng ESP8266

23/06/2022 by admin Để lại bình luận

Đã được đăng vào 09/09/2021 @ 12:06

Xe hai bánh tự cân bằng dùng ESP8266

Mục lục hiện
Xe hai bánh tự cân bằng dùng ESP8266
Chuẩn bị phụ tùng
1. Module để lập trình điều khiển ESP8266 nodeMCU x1
2. Cảm biến góc MPU6050 x1
3. Động cơ giảm tốc mini GA12 N20 + gá động cơ 200rpm x2
4. Bánh xe 43mm Ga12
5. Pin 18650 và khay pin nối tiếp x2
6. Driver Motor L298 mini
Thiết kế cơ khí
Lưu ý to bự cho các bạn
Đấu nối dây
Kết nối L298 mini
Kết nối MPU6050
Kết nối nguồn
Code
Đọc cảm biến MPU6050
Điều khiển tốc độ động cơ bằng PID
Cần xác định thời gian lấy mẫu
Cách điều chỉnh các giá trị Kp, Ki, Kd
Biết giới hạn giá trị Output
Code xe cân bằng
Video chạy thử
Kết luận
Tác giả

Một đề tài cũ mà mới đó chính là “Xe hai bánh tự cân bằng”. Chắc hẳn các bạn đã từng nghe nó ở đâu đó đúng không?

Mình từng làm chiếc xe này từ hồi sinh viên năm 3, năm 2013, tính ra cũng được 8 năm rồi đấy.

Hồi đấy cũng từng cúp học để ăn nằm với nó mấy tháng liền chỉ đề tìm hệ số PID.

Và cuối cùng, sau chừng đó thời gian, mình xem lại code và nhận ra rằng mình thiết kế từ cơ khí đến code nó sai bét nhè, may mà vẫn qua được đồ án :))). Nên bây giờ cùng làm để báo thù nó nào!

Xem thêm:

  • Hướng dẫn cài đặt ESP8266 và kết nối với Blynk
  • Hệ thống điều khiển thiết bị nhà thông minh sử dụng NodeMCU ESP8266 và App Blynk
  • Đo mức nước, mức nhiên liệu đang có trong bồn, bể chứa sử dụng cảm biến siêu âm SR04 và Arduino
  • Chống nhiễu cho cảm biến bằng bộ lọc Kalman

Chuẩn bị phụ tùng

Mình lần này làm xe cân bằng với tiêu chí nhỏ gọn nên sẽ lựa chọn những phụ tùng mini hết sức có thể.

Linh kiện bao gồm:

1. Module để lập trình điều khiển ESP8266 nodeMCU x1

Các bạn nên tháo các chân hàn của module này ra nhé, sau đó sẽ hàn dây cần thiết lên các pin thì mạch sẽ nhỏ gọn hơn.

2. Cảm biến góc MPU6050 x1

3. Động cơ giảm tốc mini GA12 N20 + gá động cơ 200rpm x2

Mình khuyên các bạn nên mua loại 12V 500rpm trở xuống, vì motor này khá yếu so với trọng lượng của tất cả linh kiện.

4. Bánh xe 43mm Ga12

5. Pin 18650 và khay pin nối tiếp x2

Các bạn nên mua loại pin tốt dòng xả cao nhé (10C). Mình từng làm pin hơi dổm nên lúc chạy driver điều khiển motor khá nóng.

6. Driver Motor L298 mini

Loại driver này hơi khác so với L298N, nó chỉ điều khiển motor qua 2 chân A B, muốn quay thuận thì A xuất xung, B xuất 0, quay ngược thì A xuất 0 còn B xuất xung. Ngoài ra còn có thêm chế độ hãm và standby khi cả 2 chân A B cùng trạng thái High hoặc Low.

Thiết kế cơ khí

Show nhẹ thiết kế của mình cho mọi người xem nhé.

Nhìn gọn gàng vậy chứ lúc đi dây là thay đổi nhiều thứ lắm. Nhưng cơ bản là nó “đẹp” như vậy :))).

Lưu ý to bự cho các bạn

  • Đầu tiên là khi thiết kế cần đặt đúng tâm của cảm biến MPU6050 nằm trên trục ngang nối hai trục của motor. Làm như vậy để khi xe nghiêng góc trái hay phải thì sai số đều cho cả hai bên.
  • Thứ hai là cần cân đối tải trọng tốt nhất có thể để xe có thể tự cân bằng tĩnh (Nghĩa là chưa làm gì mà nó vẫn cân bằng ấy :D).

Đấu nối dây

Kết nối L298 mini

Tại các chân IN1, IN2, IN3, IN4 sẽ kết nối vào các IO của ESP8266.

Nhưng mà IO nào nên dùng?

Nếu các bạn thành tâm muốn biết, mình sẽ trả lời rằng: “Hãy lên google và tìm ESP8266 pin reference”.

Sau một hồi tìm kiếm thì mình đã chọn được các IO: 0, 12, 13, 14 (né các chân I2C ra nhé, nó còn giao tiếp với MPU6050 :D).

Lưu ý:

Nguyên nhân mình chỉ dùng 2 viên pin 18650 là vì nguồn vào module này chỉ từ 2 đến 10V thôi nhé.

Ai ham hố max công suất xịt khói ráng chịu.

Kết nối MPU6050

Có lẽ đây là sơ đồ kết nối các bạn thường thấy.

Chỉ cần kết nối nguồn, SCL và SDA là xong nhưng không phải là tất cả đâu nhé :D.

Trong quá trình test đọc góc, mình thấy nhiều lúc cảm biến trả về giá trị lớn hơn nhiều so với giá trị bình thường, dù mình vẫn đang để cảm biến đứng yên.

Vì vậy các bạn nên dùng thêm chân INT để nhận biết thời điểm cảm biến sẵn sàng lấy data và thời gian mỗi chu trình lấy. Điều này sẽ làm cho giá trị góc trả về ổn định hơn.

Vì vậy, hãy nối chân INT của MPU6050 với một IO của ESP8266 nhé. Mình chọn GPIO15.

Kết nối nguồn

Điện áp của hai viên pin 18650 nối tiếp là 8.5V, các bạn chia ra một nhánh cắm cấp nguồn cho driver động cơ, một nhánh cấp nguồn cho ESP8266 (chân Vin).

Lưu ý:

Cần thêm một công tắc để ngắt nguồn khi nạp code, vì điện áp cổng USB chỉ có 5V, mình từng để song song 2 nguồn một lúc nhưng vẫn không sao.

Tuy nhiên cẩn thận vẫn hơn nha các bạn !!!

Code

Trước khi lập trình, ta cần phải hiểu nguyên lý của xe cân bằng trước.

Khi đã hiểu rồi thì chia nhỏ từng nhiệm vụ để code, sau đó ghép code sao cho pờ rồ tí là nó chạy ấy mà :))).

Hãy tưởng tượng mình đang đứng yên, người thẳng đứng, nếu có một người đẩy mình theo một hướng nhất định thì mình có xu hướng di chuyển về hướng đó để lấy lại trọng tâm cân bằng.

Xe cân bằng cũng vậy, nó dựa trên cảm biến MPU6050 để nhận biết được trạng thái góc nghiêng hiện tại của nó.

Xem như 0 là góc thẳng đứng mà nó cần duy trì để cân bằng thì đây được gọi là Setpoint.

Khi một lực tác động vào xe cân bằng, trạng thái góc sẽ thay đổi, tùy vào âm hay dương để xe biết di chuyển về hướng nào.

Tuy nhiên di chuyển với tốc độ như thế nào, vận tốc bao nhiêu để làm cho xe cân bằng nhanh nhất, không bị rung lắc thì bộ PID sẽ đảm nhiệm vai trò này.

Kết luận:

Code xe cân bằng sẽ có hai phần chính là đọc giá trị góc cảm biến MPU6050 và điều khiển tốc độ động cơ bằng PID.

Đọc cảm biến MPU6050

Để đọc giá trị góc gửi về từ cảm biến, mình dùng thử viện “MPU6050/MPU6050_6Axis_MotionApps20.h”.

Các bạn có thể tải tại đây. (Hoặc có thể tải trực tiếp trên Arduino IDE)

Cách thêm thư viện: Hướng dẫn thêm mới thư viện trong Arduino IDE

Để đọc giá trị góc chính xác thì ta cần calib cảm biến. Tại Arduino IDE, các bạn chọn Example “IMU_ZERO”.

Sau đó để cảm biến ở vị trí cố định, upload code và lấy các giá trị trong serial tương ứng copy vào code của mình ở các dòng sau:

mpu.setXGyroOffset(xxx);
mpu.setYGyroOffset(xxx);
mpu.setZGyroOffset(xxx);
mpu.setZAccelOffset(xxx);

Điều khiển tốc độ động cơ bằng PID

Mình sử dụng thư viện PID_v2 để điều khiển tốc độ động cơ

Các bạn có thể tải thư viện này ở Arduino IDE mục Library Manager.

Nói qua một chút về: PID là gì?

Các bạn có thể hiểu rằng PID sẽ xuất ra giá trị Output ứng với giá trị Input, sao cho hệ thống đáp ứng ở trạng thái mà các mong muốn (được gọi là Setpoint) một cách nhanh nhất mà không xảy ra các hiện tượng vọt lố, dao động quá lớn.

Đối với trường hợp xe cân bằng:

Các bạn muốn xe cân bằng ở vị trí 0º thì đây chính là Setpoint.

Xe sẽ đọc các giá trị Input đó chính là giá trị góc mà MPU6050 gửi về, sau đó dựa vào sai số mà chương trình tính toán ra giá trị Output để điều khiển tốc độ động cơ.

Vậy khi sử dụng một bộ điều khiển PID các bạn cần phải lưu ý:

Cần xác định thời gian lấy mẫu

void loop(void)
{
  cycle = millis();
  mpu_loop();//chương trình chạy xe cân bằng
  Blynk.run();//chương trình chạy blynk
  Serial.println(millis() - cycle);//xuất ra màn hình thời gian xử lý toàn bộ chương trình để xác định thời gian lấy mẫu
}

Cách điều chỉnh các giá trị Kp, Ki, Kd

Cho tất cả các giá trị Kp, Ki, Kd bằng 0, tăng dần giá trị Kp sao cho xe có thể lắc lư qua về mà vẫn cân bằng được.

Hoặc các bạn có thể test giá trị Kp sao cho khi tác động lực vào xe về một phía, xe có thể chạy về phía đó nhưng một thời gian ngắn lại bị ngã về hướng ngược lại

=> Cần giảm lại giá trị Kp một ít.

Tăng dần giá trị Kd đến khi nào xe không còn lắc lư qua về nữa.

Nhận biết tăng quá lố là khi xe từ trạng thái lắc lư nhiều (Kd nhỏ) sang lắc lư ít (Kd vừa phải) rồi chuyển sang lắc lư nhiều (Kd lớn) lại.

Tại giá trị Kd vừa phải, khi tác động lực nhẹ để xe về một phía, xe sẽ di chuyển theo hướng đó. Sau đó xe quay về gần với vị trí ban đầu.

Tăng dần giá trị Ki đến khi nào xe có biểu hiện rung lắc thì dừng lại.

Nhận biết bằng cách khi tác động lực nhẹ để xe di chuyển về một phía, xe sẽ nhanh chóng lấy lại được vị trí cân bằng Setpoint mà không xảy ra hiện tượng rung lắc.

Biết giới hạn giá trị Output

ESP8266 khác với Arduino, chân output xuất xung PWM lớn nhất là 1023.

Vì vậy Output được giới hạn từ -1023 đến 1023.

Code xe cân bằng

#if defined(ESP8266)
#include <ESP8266WiFi.h>
#else
#include <WiFi.h>
#endif
#include <DNSServer.h>
#include <WiFiClient.h>
#include <WiFiUdp.h>
#include "I2Cdev.h"
#include <ESP8266WiFi.h>
#include <PID_v2.h>
#include <BlynkSimpleEsp8266.h>
#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
MPU6050 mpu;
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q;           // [w, x, y, z]         quaternion container
VectorInt16 aa;         // [x, y, z]            accel sensor measurements
VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
VectorFloat gravity;    // [x, y, z]            gravity vector

float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

#define INTERRUPT_PIN 15 // use pin 15 on ESP8266

char ssid[] = "";
char pass[] = "";
char auth[] = "";

unsigned long cycle = 0;
unsigned long last_current = 0;
unsigned long setdelay = 0;
unsigned long makecycle = 10;

float Kp = 16;
float Ki = 0.2;
float Kd = 0;
float offset = 0;
float last_value = 0;
bool forward = false;
bool initial = false;
double Setpoint, Input, Output, Angle, temp_setpoint, rotate;
PID_v2 myPID(Kp, Ki, Kd, PID::Direct);

volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void ICACHE_RAM_ATTR dmpDataReady() {
  mpuInterrupt = true;
}

void mpu_setup()
{
  // join I2C bus (I2Cdev library doesn't do this automatically)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
  Wire.begin();
  Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
  Fastwire::setup(400, true);
#endif
  Serial.println(F("Initializing I2C devices..."));
  mpu.initialize();
  pinMode(INTERRUPT_PIN, INPUT);
  Serial.println(F("Testing device connections..."));
  Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
  Serial.println(F("Initializing DMP..."));
  devStatus = mpu.dmpInitialize();
  mpu.setXGyroOffset(317);
  mpu.setYGyroOffset(-57);
  mpu.setZGyroOffset(41);
  mpu.setZAccelOffset(1042);
  if (devStatus == 0) {
    // turn on the DMP, now that it's ready
    Serial.println(F("Enabling DMP..."));
    mpu.setDMPEnabled(true);

    // enable Arduino interrupt detection
    Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
    attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);
    mpuIntStatus = mpu.getIntStatus();

    // set our DMP Ready flag so the main loop() function knows it's okay to use it
    Serial.println(F("DMP ready! Waiting for first interrupt..."));
    dmpReady = true;
    packetSize = mpu.dmpGetFIFOPacketSize();
  } else {
    Serial.print(F("DMP Initialization failed (code "));
    Serial.print(devStatus);
    Serial.println(F(")"));
  }
}
BLYNK_WRITE(V6)
{
  float pinValue = param.asFloat(); // assigning incoming value from pin V1 to a variable
  rotate = pinValue;
}
BLYNK_WRITE(V5)
{
  float pinValue = param.asFloat(); // assigning incoming value from pin V1 to a variable
  offset = pinValue;
  Setpoint = temp_setpoint - offset;
  myPID.Start(Input,  // input
              0,                      // current output
              Setpoint);
  Serial.println(Setpoint);
}
BLYNK_WRITE(V1)
{
  float pinValue = param.asFloat(); // assigning incoming value from pin V1 to a variable
  Kp = pinValue;
  myPID.SetTunings(Kp, Ki, Kd);
}
BLYNK_WRITE(V2)
{
  float pinValue = param.asFloat(); // assigning incoming value from pin V1 to a variable
  Ki = pinValue;
  myPID.SetTunings(Kp, Ki, Kd);
}
BLYNK_WRITE(V3)
{
  float pinValue = param.asFloat(); // assigning incoming value from pin V1 to a variable
  Kd = pinValue;
  myPID.SetTunings(Kp, Ki, Kd);
}
BLYNK_WRITE(V4)
{
  float pinValue = param.asFloat(); // assigning incoming value from pin V1 to a variable
  Setpoint = pinValue;
  temp_setpoint = Setpoint;
  myPID.Start(Input,  // input
              0,                      // current output
              Setpoint);
}
void setup(void)
{
  pinMode (0, OUTPUT);
  pinMode (14, OUTPUT);
  pinMode (12, OUTPUT);
  pinMode(13, OUTPUT);
  analogWrite(14, 1023);
  analogWrite(0, 1023);
  analogWrite(12, 1023);
  analogWrite(13, 1023);
  Serial.begin(115200);
  Serial.println(F("\nOrientation Sensor OSC output")); Serial.println();
  Serial.print(F("WiFi connected! IP address: "));
  Serial.println(WiFi.localIP());
  Blynk.begin(auth, ssid, pass, "sv.bangthong.com", 8080);
  analogWriteRange(1023);
  Blynk.syncAll();
  last_current = millis();
  mpu_setup();
  Setpoint = 0;
  myPID.Start(Input,  // input
              0,                      // current output
              Setpoint);

  myPID.SetSampleTime(15);
  myPID.SetOutputLimits(-1023, 1023);
}

void mpu_loop()
{
  if (!dmpReady)
  {
    return;
  }
  while (!mpuInterrupt && fifoCount < packetSize) {
    if (abs(Input) < 40)
    {
      Output = myPID.Run(Input);
      if (Output <= 0)
      {
        analogWrite(0, abs(Output));
        analogWrite(14, 0);
        analogWrite(12, abs(Output));
        analogWrite(13, 0);
      }
      else
      {
        analogWrite(14, abs(Output));
        analogWrite(0, 0);
        analogWrite(13, abs(Output));
        analogWrite(12, 0);
      }
      Angle = Input;
    }
    else
    {
      Output = 0;
      analogWrite(0, abs(Output));
      analogWrite(14, 0);
      analogWrite(13, abs(Output));
      analogWrite(12, 0);
    }
  }
  mpuInterrupt = false;
  mpuIntStatus = mpu.getIntStatus();
  fifoCount = mpu.getFIFOCount();
  if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
    // reset so we can continue cleanly
    mpu.resetFIFO();
    //Serial.println(F("FIFO overflow!"));
  } else if (mpuIntStatus & 0x02) {
    while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
    mpu.getFIFOBytes(fifoBuffer, packetSize);
    fifoCount -= packetSize;
    mpu.dmpGetQuaternion(&q, fifoBuffer);
    mpu.dmpGetGravity(&gravity, &q);
    mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
    Input = ypr[1] * 180 / M_PI;
  }
}
void loop(void)
{
  cycle = millis();
  mpu_loop();
  Blynk.run();
  Serial.println(millis() - cycle);//comment nó khi đã xác định được sample time
}

Các bạn cần phải thay đổi code nay tùy thuộc vào trường hợp mà các bạn gặp phải:

  • Về kiến thức cơ bản về Blynk, các bạn có thể tìm hiểu trên mạng hoặc thông qua các ví dụ để hiểu code của mình.
  • char ssid[] = “”; //SSID wifi
  • char pass[] = “”; //Password wifi
  • char auth[] = “”; //Auth token blynk
  • myPID.SetSampleTime(15); //Xác định thời gian lấy mẫu là 15ms
  • myPID.SetOutputLimits(-1023, 1023); //giới hạn Output
  • Setpoint ; Được xác định bằng cách: đọc giá trị góc của xe khi xe ở vị trí thẳng đứng với mặt bàn.
  • V1, V2, V3: Setting Kp, Ki, Kd từ Blynk gửi về.
  • V4: Setting Setpoint.
  • V5: Được dùng là Joystick trên Blynk để điều khiển xe di chuyển tới và lui. Xe xe tiến tới và lùi khi thay đổi giá trị Setpoint.

Video chạy thử

Kết luận

Vậy là mình đã hoàn thành xe cân bằng trong một khoảng thời gian ngắn tầm 2 ngày thay vì gần tốn gần hết 2 tháng ăn nằm với nó từ hồi sinh viên.

Nhưng mà nhờ 2 tháng vật vã đó mà mình biết khá nhiều ấy:

  • Biết sử dụng Solidworks,
  • Bắt đầu biết thế nào là lập trình,
  • Biết đến đồ điện tử vì nó bốc khói khá nhiều,
  • Bắt đầu biết tư duy phân tích vấn đề…

Hy vọng bài này sẽ giúp một phần nào đó cho các bạn.

Nếu có gì thắc mắc hãy comment, mình sẽ sẵn sàng giải đáp. Cảm ơn các bạn!

Tác giả

Nguyễn Hữu Phước

Zalo: 0905.021.462

Nguồn: iotproject.tech

 

5/5 - (1 bình chọn)
  • Share on Facebook
  • Tweet on Twitter

Bài viết liên quan

Điều khiển thiết bị thông qua Cayenne Mydevices và NodeMCU ESP8266
Giám sát nhiệt độ, độ ẩm (DHT11) thông qua Thingspeak bằng NodeMCU ESP8266
Phát hiện mưa (Rain Sensor) sử dụng NodeMCU ESP8266

Thuộc chủ đề:Cảm biến, ESP8266 PROJECT Tag với:esp8266, tự cân bằng, xe hai bánh

Bài viết trước « P1 – Smart Home – Ổ điện thông minh
Bài viết sau Phím tắt trên Altium thường dùng »

Reader Interactions

Trả lời Hủy

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Sidebar chính

Zalo hỏi đáp 24/7

Theo dõi qua mạng xã hội

  • Facebook
  • RSS

Bạn đang tìm gì?

Bài viết mới nhất

Hệ sinh thái STM32 Cube trong Lập trình STM32 với HAL

26/06/2022

Cài đặt STM32 CubeMX và Keil C lập trình STM32

26/06/2022

Đèn năng lượng mặt trời dùng Arduino

26/06/2022

Nguồn tuyến tính là gì

26/06/2022

Cách cài đặt và sử dụng ST LINK Utility

26/06/2022

Chuyên mục

  • DỰ ÁN & MẠCH ĐIỆN (245)
    • Công nghiệp (16)
    • Dân dụng (28)
    • Điện tử ứng dụng (178)
      • Audio / Amplifiers (34)
      • Biến đổi AC và DC (23)
      • Cảm biến (43)
      • Động cơ bước (6)
      • Kiểm thử và đo đạc (23)
      • LCD (15)
      • LED (19)
      • Mạch linh tinh (27)
      • Nguồn điện (39)
      • Pin sạc/Acquy và mạch sạc (22)
      • RF – FM (5)
      • Robotic (2)
    • HOME AUTOMATION (27)
    • Lập trình (92)
      • ARDUINO PROJECT (39)
      • ESP32 PROJECT (6)
      • ESP8266 PROJECT (29)
      • RASPBERRY PI PROJECT (9)
      • Vi điều khiển (22)
    • Nixie Clock (3)
  • Kiến thức căn bản (163)
    • Arduino (36)
    • Điện tử cơ bản (72)
    • Điện tử số (9)
    • IN 3D (9)
    • Nixie Tube (13)
    • PCB (18)
    • Raspberry Pi (10)
    • Vi điều khiển (14)

Footer

Bài viết mới nhất

  • Hệ sinh thái STM32 Cube trong Lập trình STM32 với HAL
  • Cài đặt STM32 CubeMX và Keil C lập trình STM32
  • Đèn năng lượng mặt trời dùng Arduino
  • Nguồn tuyến tính là gì
  • Cách cài đặt và sử dụng ST LINK Utility
  • Cài đặt Package cho CubeMX và Keil C

Bình luận mới nhất

  • Ernesto trong Nguyên lý cảm biến siêu âm chống nước JSN-SR04T và sơ đồ mạch
  • admin trong Mạch Ampli 19W dùng IC LA4440
  • Hoài trong Cách thay thế transistor tương đương
  • Dương trong Mạch Ampli 19W dùng IC LA4440

Tìm kiếm

Tất cả nội dung trên website chỉ dùng để tham khảo. Chúng tôi không chịu trách nhiệm về thông tin thành viên đăng tải lên website và xóa bài viết khi có vi phạm bản quyền tác giả.