ทำพัดลมไฟฟ้าด้วย FireBeetle Board ESP32: 8 ขั้นตอน (พร้อมรูปภาพ)

ทำพัดลมไฟฟ้าด้วย FireBeetle Board ESP32: 8 ขั้นตอน (พร้อมรูปภาพ)

สารบัญ:

Anonim

ฤดูร้อนกำลังมาพร้อมกับความอบอุ่นที่เพิ่มขึ้นอย่างต่อเนื่อง ตอนนี้เป็นเวลาที่เหมาะสมในการเตรียมสิ่งฤดูร้อน! ดังนั้นฉันจึงซื้อฟินเนอร์ขนาดเล็กออนไลน์ มันดียกเว้นว่าไม่สามารถบังคับทิศทางได้

อย่างไรก็ตามนี่เป็นปัญหาหรือไม่ No! ในฐานะวิศวกรสร้างสรรค์นี่เป็นเวลาแสดงของฉัน!

วัสดุ:

ขั้นตอนที่ 1: ฮาร์ดแวร์ที่ต้องการ

FireBeetle ESP32 คอนโทรลเลอร์× 1

FireBeetle Covers-Gravity Shield I / O Expansion × 1

แรงโน้มถ่วง: จอแสดงผล I2C OLED-2864 × 1

เซ็นเซอร์ความชื้นอุณหภูมิ BME × 1

EC11J rotary encoder × 1

9g เซอร์โวไมโคร (1.6kg) × 1

Dupont line × 10 Crust ที่พิมพ์โดย Overlord 3D printer × 1

* ไม่จำเป็นต้องบัดกรีในระหว่างกระบวนการทำงานทั้งหมด

ขั้นตอนที่ 2: การเชื่อมต่อฮาร์ดแวร์

เชื่อมต่ออินเทอร์เฟซ I2C ของ OLED12864 โดยตรงไปยังอินเทอร์เฟซ I2C ของ Gravity Expansion Shield และเชื่อมต่อ A ของ EC11J rotary encoder กับ D0, B ถึง D1, C ถึง D8 จากนั้นเชื่อมต่อ micro servo กับ D3 และเชื่อมต่ออินเตอร์เฟส SPI ของ BME280 โดยตรงไปยังอินเตอร์เฟส SPI ของ Gravity Expansion shield, CS (Chip Select) ถึง D5

แผนภาพวงจรดังต่อไปนี้:

ขั้นตอนที่ 3: พิมพ์ Crust ด้วยเครื่องพิมพ์ 3D

คลิกที่นี่เพื่อดาวน์โหลดโปรแกรมและซอร์สโค้ดสำหรับการพิมพ์ 3 มิติ

พิมพ์โดย Overlord 3d printer

ขั้นตอนที่ 4: แก้ไข Rotary Encoder เป็น Crust

แก้ไขด้วยกาวโฮลท์ - ละลาย

เชื่อมต่อ EC11J กับ Gravity Board ด้วย Dupont

ขั้นตอนที่ 5: แก้ไข OLED2864 กับ Crust

เชื่อมต่อจอแสดงผล OLED เข้ากับกระดานแรงโน้มถ่วงด้วย Dupont และส่วนต่อประสานการเชื่อมต่อคือ I2C

ขั้นตอนที่ 6: เชื่อมต่อ BME280

BME280 ใช้อินเตอร์เฟส SPI โปรดดูแผนภาพวงจรก่อนหน้าสำหรับรายละเอียดการเชื่อมต่อ

ขั้นตอนที่ 7: จัดสรรพัดลม

ถอดแบตเตอรี่ลิเธียมออกแล้วเชื่อมต่อแหล่งจ่ายไฟของพัดลมเข้ากับ Vcc และ GND ของ FireBeetle ESP32 ขอบเชื่อมต่อแบตเตอรี่ลิเธียมกับ FireBeetle ESP32 จากนั้นตั้งค่าเชื่อมต่อไมโครเซอร์โวเป็น D3

แก้ไขสาย Dupont ด้วยกาวโฮลท์ - ละลาย

ตั้งไมโครเซอร์โวด้วยกาวโฮลท์ - ละลาย

ขั้นตอนที่ 8: การประกอบเครื่องจักรให้เสร็จสมบูรณ์

ครอบคลุมด้านล่างและแก้ไขด้วยกาวร้อนละลายและดาวน์โหลดโปรแกรม

รหัส

#include // จำเป็นสำหรับ Arduino 1.6.5 และก่อนหน้าเท่านั้น

#include #include "SSD1306.h" // นามแฝงสำหรับ `#include" SSD1306Wire.h "` #include "OLEDDisplayUi.h" #include "images.h" #include #dincine SEA_LEVEL_PRESSURE 1013.25f #define BME_CS 5 เรียบง่าย จับเวลา; int timeCounter = 0; บูลีน uiEnable = true; DFRobot_BME280 bme (BME_CS); // SPI SSD1306 จอแสดงผล (0x3c, D7, D6); เซอร์โว mymotor; OLEDDisplayUi ui (& แสดง); enum รุ่น {MODEL_NULL, MODEL_LEFT, MODEL_RIGHT, MODEL_BUTTON}; enum setFrame {SET_NULL, SET_FRAME_2_ON, SET_FRAME_2_OFF, SET_FRAME_3_ON, SET_FRAME_3_OFF}; enum motorModel {MOTOR_AUTO, MOTOR_STATIC}; ถ่าน commondModel = MODEL_NULL; ถ่าน setFrameValue = SET_NULL; ถ่าน motorState = MOTOR_STATIC; int encoderPinA = D0; int encoderPinB = D1; int buttonPin = D8; ระเหย int lastEncoded = 0; ตัวเข้ารหัสแบบยาวที่มีความผันผวนค่า = 0; lastencoderValue ที่ยาวนาน = 0; int lastMSB = 0; int lastLSB = 0; int speedValue = 5; int angleValue = 90; บูลีนผบ = จริง; int frameIndex = 0; long readEncoderValue (เป็นโมฆะ) {return encoderValue / 4; } บูลีน isButtonPushDown (เป็นโมฆะ) {ถ้า (! digitalRead (buttonPin)) {ล่าช้า (5); ถ้า (! digitalRead (buttonPin)) {while (! digitalRead (buttonPin)); กลับจริง }} คืนค่าเท็จ } void msOverlay (จอแสดงผล OLEDDisplay *, OLEDDisplayUiState * state) {ถ้า (frameIndex == 0) ส่งคืน; จอแสดงผล> setTextAlignment (TEXT_ALIGN_RIGHT); จอแสดงผล> setFont (ArialMT_Plain_10); display-> drawString (128, 0, String (angleValue)); } เป็นโมฆะ drawFrame1 (จอแสดงผล OLEDDisplay *, OLEDDisplayUiState * สถานะ, int16_t x, int16_t y) {display-> setTextAlignment (TEXT_ALIGN_LEFT); จอแสดงผล> setFont (ArialMT_Plain_24); display-> drawString (15 + x, 10+ y, "ChoCho"); } ถือเป็นโมฆะ drawFrame2 (จอแสดงผล OLEDDisplay, OLEDDisplayUiState * สถานะ, int16_t x, int16_t y) {float temp = bme.temperatureValue (); ลอย pa = bme.pressureValue (); float hum = bme.altitudeValue (SEA_LEVEL_PRESSURE); float alt = bme.humidityValue (); // แสดงขนาดเริ่มต้นที่รวม 3 รายการ แบบอักษรมาจากไฟล์ SSD1306Fonts.h // นอกเหนือจากแบบอักษรเริ่มต้นจะมีโปรแกรมที่แปลงฟอนต์ TrueType เป็นรูปแบบนี้ display-> setTextAlignment (TEXT_ALIGN_LEFT); จอแสดงผล> setFont (ArialMT_Plain_16); display-> drawString (x, y, String ("Temp:") + String (temp)); display-> drawString (x, 17 + y, String ("Hum:") + String (alt)); display-> drawString (x, 34 + y, String ("Pa:") + String (pa)); } เป็นโมฆะ drawFrame3 (จอแสดงผล OLEDDisplay, OLEDDisplayUiState * สถานะ, int16_t x, int16_t y) {// สาธิตการจัดเรียงข้อความแสดง -> setFont (ArialMT_Plain_16); // พิกัดกำหนดจุดเริ่มต้นด้านซ้ายของข้อความที่แสดง -> setTextAlignment (TEXT_ALIGN_LEFT); display-> drawString (x, y, "Set Speed"); display-> drawString (40 + x, y + 17, String (speedValue)); } ถือเป็นโมฆะ drawFrame4 (OLEDDisplay * display, OLEDDisplayUiState * state, int16_t x, int16_t y) {// สาธิตการจัดเรียงข้อความแสดง -> setFont (ArialMT_Plain_16); // พิกัดกำหนดจุดเริ่มต้นด้านซ้ายของข้อความที่แสดง -> setTextAlignment (TEXT_ALIGN_LEFT); display-> drawString (x, y, "FAN Model"); if (motorState == MOTOR_STATIC) {display-> drawString (40 + x, y + 27, "STATIC"); } ถ้า if (motorState == MOTOR_AUTO) {display-> drawString (40 + x, y + 27, "AUTO"); }} // อาร์เรย์นี้เก็บพอยน์เตอร์ของฟังก์ชั่นไว้ที่ frames ทั้งหมด // frames เป็นมุมมองเดียวที่เลื่อนใน FrameCallback frames = {drawFrame1, drawFrame2, drawFrame3, drawFrame4}; // มีเฟรมกี่เฟรม? int frameCount = 4; // ภาพซ้อนทับถูกวาดแบบคงที่ที่ด้านบนของเฟรมเช่น โอเวอร์เลย์นาฬิกาซ้อนทับ = {msOverlay}; int overlaysCount = 1; โมฆะ ec11Init (โมฆะ) {pinMode (encoderPinA, INPUT); pinMode (encoderPinB, INPUT); pinMode (buttonPin, INPUT); digitalWrite (encoderPinA, HIGH); // turn pullup resistor บน digitalWrite (encoderPinB, HIGH); // เปิดตัวต้านทาน pullup บน attachInterrupt (D0, updateEncoder, CHANGE); attachInterrupt (D1, updateEncoder, CHANGE); } void displayInit (void) {ui.setTargetFPS (60); ui.setActiveSymbol (activeSymbol); ui.setInactiveSymbol (inactiveSymbol); ui.setIndicatorPosition (ล่าง); ui.setIndicatorDirection (LEFT_RIGHT); ui.setFrameAnimation (SLIDE_LEFT); ui.setFrames (เฟรม, frameCount); ui.setOverlays (การซ้อนทับ, overlaysCount); ui.disableAutoTransition (); ui.switchToFrame (frameIndex); ui.init (); display.flipScreenVertically (); } โมฆะ motorInit (void) {mymotor.attach (D3); mymotor.write (speedValue); } void updateUi (void) {if (timeCounter> 50) {display.displayOff (); uiEnable = false; } else {display.displayOn (); uiEnable = true; timeCounter ++; } if (commondModel == MODEL_RIGHT) {frameIndex ++; if (frameIndex> 3) frameIndex = 0; ui.switchToFrame (frameIndex); } อื่น ๆ ถ้า (commondModel == MODEL_LEFT) {frameIndex--; if (frameIndex <0) frameIndex = 3; ui.switchToFrame (frameIndex); } commondModel = MODEL_NULL; } เป็นโมฆะ updateMotor (เป็นโมฆะ) {ถ้า (motorState == MOTOR_AUTO) {ถ้า (dir == จริง) {angleValue + = speedValue; } else {angleValue - = speedValue; }} if (angleValue> 180) dir = false; อื่นถ้า (angleValue <0) dir = จริง mymotor.write (angleValue); } เป็นโมฆะ doButton (เป็นโมฆะ) {ถ้า (isButtonPushDown ()) {ถ้า (uiEnable == false) {commondModel = MODEL_NULL; } else {commondModel = MODEL_BUTTON; } timeCounter = 0; } if (readEncoderValue ()! = 0) {long value = readEncoderValue (); if (uiEnable == true) {if (value> 0) {commondModel = MODEL_RIGHT; } else {commondModel = MODEL_LEFT; }} timeCounter = 0; encoderValue = 0; } if (frameIndex == 2) {if (commondModel == MODEL_BUTTON) {ถ้า (setFrameValue == SET_FRAME_2_ON) {setFrameValue = SET_FRAME_2_OFF; } else {setFrameValue = SET_FRAME_2_ON; } commondModel = MODEL_NULL; } if (setFrameValue == SET_FRAME_2_ON) {ถ้า (commondModel == MODEL_RIGHT) {speedValue ++; } อื่น ๆ ถ้า ((commondModel == MODEL_LEFT)) {speedValue--; } if (speedValue> 20) speedValue = 20; if (speedValue <0) speedValue = 0; commondModel = MODEL_NULL; }} if (frameIndex == 3) {if (commondModel == MODEL_BUTTON) {ถ้า (setFrameValue == SET_FRAME_3_ON) {setFrameValue = SET_FRAME_3_OFF; } else {setFrameValue = SET_FRAME_3_ON; } commondModel = MODEL_NULL; } if (setFrameValue == SET_FRAME_3_ON) {ถ้า ((commondModel == MODEL_RIGHT) || (commondModel == MODEL_LEFT)) {motorState = (motorState == MOTOR_AUTO)? } commondModel = MODEL_NULL; }}} void setup () {ec11Init (); displayInit (); motorInit (); bme.begin (); timer.setInterval (200 updateUi); timer.setInterval (50, updateMotor); } void loop () {int leftTimeBudget = ui.update (); if (leftTimeBudget> 0) {delay (leftTimeBudget) } doButton (); timer.run (); } void updateEncoder ()

ฮ่าฮ่าทำได้ดีมาก!