Wykonaj wentylator elektryczny z płytą FireBeetle ESP32: 8 kroków (ze zdjęciami)

Wykonaj wentylator elektryczny z płytą FireBeetle ESP32: 8 kroków (ze zdjęciami)

Spisu treści:

Anonim

Nadchodzi lato ze stale rosnącym ciepłem. Teraz jest odpowiedni czas na przygotowanie letniej rzeczy! Dlatego kupiłem mały wentylator na linii; jest dobry, z wyjątkiem tego, że nie może sterować.

Czy to jednak problem? Nie! Jako kreatywny inżynier, to mój czas na pokaz!

Kieszonkowe dzieci:

Krok 1: Sprzęt w potrzebie

Kontroler FireBeetle ESP32 × 1

FireBeetle Covers-Gravity I / O Expansion Shield × 1

Grawitacja: Wyświetlacz I2C OLED-2864 × 1

Czujnik temperatury i wilgotności BME × 1

Koder EC11J × 1

9 g mikro serwo (1,6 kg) × 1

Dupont line × 10 Crust drukowany przez drukarkę Overlord 3D × 1

* Nie ma potrzeby lutowania podczas całego procesu roboczego.

Krok 2: Połączenie sprzętowe

Podłącz interfejs I2C OLED12864 bezpośrednio do interfejsu I2C osłony Gravity Expansion i podłącz enkoder obrotowy A z EC11J do D0, B do D1, C do D8. Następnie podłącz mikro serwo do D3 i podłącz interfejs SPI BME280 bezpośrednio do interfejsu SPI Gravity Expansion shield, CS (Chip Select) do D5.

Schemat obwodu jest następujący:

Krok 3: Wydrukuj skorupę z drukarką 3D.

Kliknij tutaj, aby pobrać program i kod źródłowy do druku 3D.

Jest to drukowane przez drukarkę 3D Overlord.

Krok 4: Przymocuj Rotary Encoder do skorupy

Fix z klejem holt-topienia

Połącz EC11J z Gravity Board z Dupont

Krok 5: Napraw OLED2864 na skorupie

Podłącz wyświetlacz OLED do płyty Gravity z Dupont, a interfejsem połączenia jest I2C

Krok 6: Podłącz BME280

BME280 wykorzystuje interfejs SPI, szczegółowe informacje na temat połączenia można znaleźć w poprzednim schemacie obwodu

Krok 7: Przydziel wentylator

Wyjmij baterię litową i podłącz zasilanie wentylatora do Vcc i GND FireBeetle ESP32, krawędź łącząca baterię litową z FireBeetle ESP32. Następnie podłącz mikropomocowanie do D3.

Napraw przewody Dupont za pomocą kleju holt-topliwego

Ustaw mikro serwo z klejem holt-topliwym

Krok 8: Kompletny zespół maszyny

Przykryj spód i zamocuj klejem topliwym, a następnie pobierz program.

Kod

#include // Potrzebny tylko dla Arduino 1.6.5 i wcześniejszych

#include #include "SSD1306.h" // alias dla `#include" SSD1306Wire.h "` #include "OLEDDisplayUi.h" #include "images.h" #include #include #define SEA_LEVEL_PRESSURE 1013.25f #define BME_CS D5 SimpleTimer regulator czasowy; int timeCounter = 0; boolean uiEnable = true; DFRobot_BME280 bme (BME_CS); // Wyświetlacz SPI SSD1306 (0x3c, D7, D6); Servo mymotor; OLEDDisplayUi ui (i wyświetlacz); enum model {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}; char commondModel = MODEL_NULL; char setFrameValue = SET_NULL; char motorState = MOTOR_STATIC; int encoderPinA = D0; int encoderPinB = D1; int buttonPin = D8; volatile int lastEncoded = 0; volatile long encoderValue = 0; long lastencoderValue = 0; int lastMSB = 0; int lastLSB = 0; int speedValue = 5; int angleValue = 90; boolean dir = true; int frameIndex = 0; long readEncoderValue (void) {return encoderValue / 4; } boolean isButtonPushDown (void) {if (! digitalRead (buttonPin)) {delay (5); if (! digitalRead (buttonPin)) {while (! digitalRead (buttonPin)); powrót prawda; }} return false; } void msOverlay (OLEDDisplay * display, OLEDDisplayUiState * state) {if (frameIndex == 0) zwraca; display-> setTextAlignment (TEXT_ALIGN_RIGHT); display-> setFont (ArialMT_Plain_10); display-> drawString (128, 0, String (angleValue)); } void drawFrame1 (OLEDDisplay * display, OLEDDisplayUiState * state, int16_t x, int16_t y) {display-> setTextAlignment (TEXT_ALIGN_LEFT); display-> setFont (ArialMT_Plain_24); display-> drawString (15 + x, 10+ y, „ChoCho”); } void drawFrame2 (OLEDDisplay * display, OLEDDisplayUiState * state, int16_t x, int16_t y) {float temp = bme.temperatureValue (); float pa = bme.pressureValue (); float hum = bme.altitudeValue (SEA_LEVEL_PRESSURE); float alt = bme.humidityValue (); // Pokazuje 3 załączone domyślne rozmiary. Czcionki pochodzą z pliku SSD1306Fonts.h // Oprócz domyślnych czcionek będzie program do konwersji czcionek TrueType na ten format display-> setTextAlignment (TEXT_ALIGN_LEFT); display-> 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)); } void drawFrame3 (OLEDDisplay * display, OLEDDisplayUiState * state, int16_t x, int16_t y) {// Wyświetlenie wyrównania tekstu demo-> setFont (ArialMT_Plain_16); // Współrzędne definiują lewy punkt początkowy wyświetlania tekstu-> setTextAlignment (TEXT_ALIGN_LEFT); display-> drawString (x, y, „Set Speed”); display-> drawString (40 + x, y + 17, String (speedValue)); } void drawFrame4 (OLEDDisplay * display, OLEDDisplayUiState * state, int16_t x, int16_t y) {// Wyświetlenie wyrównania tekstu demo-> setFont (ArialMT_Plain_16); // Współrzędne definiują lewy punkt początkowy wyświetlania tekstu-> setTextAlignment (TEXT_ALIGN_LEFT); display-> drawString (x, y, „FAN Model”); if (motorState == MOTOR_STATIC) {display-> drawString (40 + x, y + 27, „STATIC”); } else if (motorState == MOTOR_AUTO) {display-> drawString (40 + x, y + 27, „AUTO”); }} // Ta tablica przechowuje wskaźniki funkcji do wszystkich ramek // ramek to pojedyncze widoki, które przesuwają się w ramkach FrameCallback = {drawFrame1, drawFrame2, drawFrame3, drawFrame4}; // ile jest klatek? int frameCount = 4; // Nakładki są statycznie rysowane na górze ramki, np. zegar Nakładki OverlayCallback = {msOverlay}; int overlaysCount = 1; void ec11Init (void) {pinMode (encoderPinA, INPUT); pinMode (encoderPinB, INPUT); pinMode (buttonPin, INPUT); digitalWrite (encoderPinA, HIGH); // włącz rezystor pullup na digitalWrite (enkoderPinB, HIGH); // włącz rezystor pullup na attachInterrupt (D0, updateEncoder, CHANGE); attachInterrupt (D1, updateEncoder, CHANGE); } void displayInit (void) {ui.setTargetFPS (60); ui.setActiveSymbol (activeSymbol); ui.setInactiveSymbol (inactiveSymbol); ui.setIndicatorPosition (BOTTOM); ui.setIndicatorDirection (LEFT_RIGHT); ui.setFrameAnimation (SLIDE_LEFT); ui.setFrames (frame, frameCount); ui.setOverlays (nakładki, overlaysCount); ui.disableAutoTransition (); ui.switchToFrame (frameIndex); ui.init (); display.flipScreenVertically (); } void 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); } else if (commondModel == MODEL_LEFT) {frameIndex--; if (frameIndex <0) frameIndex = 3; ui.switchToFrame (frameIndex); } commondModel = MODEL_NULL; } void updateMotor (void) {if (motorState == MOTOR_AUTO) {if (katalog == true) {angleValue + = speedValue; } else {angleValue - = speedValue; }} if (angleValue> 180) dir = false; else if (angleValue <0) dir = true; mymotor.write (angleValue); } void doButton (void) {if (isButtonPushDown ()) {if (uiEnable == false) {commondModel = MODEL_NULL; } else {commondModel = MODEL_BUTTON; } timeCounter = 0; } if (readEncoderValue ()! = 0) {long value = readEncoderValue (); if (uiEnable == true) {if (wartość> 0) {commondModel = MODEL_RIGHT; } else {commondModel = MODEL_LEFT; }} timeCounter = 0; encoderValue = 0; } if (frameIndex == 2) {if (commondModel == MODEL_BUTTON) {if (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) {if (commondModel == MODEL_RIGHT) {speedValue ++; } else if ((commondModel == MODEL_LEFT)) {speedValue--; } if (speedValue> 20) speedValue = 20; if (speedValue <0) speedValue = 0; commondModel = MODEL_NULL; }} if (frameIndex == 3) {if (commondModel == MODEL_BUTTON) {if (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) {if ((commondModel == MODEL_RIGHT) || (commondModel == MODEL_LEFT)) {motorState = (motorState == MOTOR_AUTO)? MOTOR_STATIC: MOTOR_AUTO; } commondModel = MODEL_NULL; }}} void setup () {ec11Init (); displayInit (); motorInit (); bme.begin (); timer.setInterval (200, updateUi); timer.setInterval (50, updateMotor); } void loop () {int remainTimeBudget = ui.update (); if (remainTimeBudget> 0) {delay (remainTimeBudget); } doButton (); timer.run (); } void updateEncoder ()

LOL ~ dobrze zrobione!