Fabriquez un ventilateur électrique avec FireBeetle Board ESP32: 8 étapes

Fabriquez un ventilateur électrique avec FireBeetle Board ESP32: 8 étapes

Table des matières:

Anonim

L'été arrive avec une chaleur de plus en plus chaude. C'est le bon moment pour préparer un truc d'été! Par conséquent, j'ai acheté une petite ferme en ligne; c'est bon sauf qu'il ne peut pas diriger.

Cependant, est-ce un problème? Non! En tant qu’ingénieur créatif, c’est mon heure de spectacle!

Provisions:

Étape 1: Matériel nécessaire

Contrôleur FireBeetle ESP32 × 1

FireBeetle Covers-Gravity Shield Expansion × 1

Gravité: Écran I2C OLED-2864 × 1

Capteur de température et d'humidité BME × 1

EC11J encodeur rotatif × 1

9g micro servo (1,6 kg) × 1

Ligne Dupont × 10 croûte imprimée avec l'imprimante 3D Overlord × 1

* Pas besoin de souder pendant tout le processus de travail.

Étape 2: Connexion du matériel

Connectez l’interface I2C de l’OLED12864 directement à l’interface I2C du blindage d’extension Gravity, puis connectez A du codeur rotatif EC11J à D0, B à D1, C à D8. Puis connectez le micro-servo à D3 et connectez l'interface SPI de BME280 directement à l'interface SPI de Gravity Expansion Shield, CS (Chip Select) à D5.

Le schéma de circuit est comme ci-dessous:

Étape 3: Imprimez la croûte avec une imprimante 3D.

Cliquez ici pour télécharger le programme et le code source pour l'impression 3D.

Ceci est imprimé par l'imprimante 3d Overlord.

Étape 4: Fixez le codeur rotatif sur la croûte

Fix avec de la colle holt-melt

Reliez l'EC11J au Gravity Board avec Dupont

Étape 5: Fixez OLED2864 sur la croûte.

Reliez l’écran OLED à Gravity Board avec Dupont et l’interface de connexion est I2C

Étape 6: connectez le BME280

Le BME280 utilise une interface SPI. Veuillez vous reporter au schéma de circuit précédent pour plus de détails sur la connexion.

Étape 7: Allouer le ventilateur

Retirez la batterie au lithium et connectez l'alimentation du ventilateur à Vcc et GND de FireBeetle ESP32, en connectant la batterie au lithium à FireBeetle ESP32. Ensuite, connectez le micro servo à D3.

Fixer les fils de Dupont avec de la colle holt-melt

Réglez le micro servo avec de la colle holt-melt

Étape 8: Assemblage complet de la machine

Couvrez le fond et fixez-le avec de la colle thermofusible, puis téléchargez le programme.

Code

#include // Nécessaire uniquement pour Arduino 1.6.5 et les versions antérieures

#include #include "SSD1306.h" // alias pour `#include" SSD1306Wire.h "` #include "OLEDDisplayUi.h" #include "images.h" #include #include #define SEA_LEVEL_PRESSURE 1013.25f minuteur; int timeCounter = 0; booléen uiEnable = true; DFRobot_BME280 bme (BME_CS); // SPI SSD1306 display (0x3c, D7, D6); Servo mymotor; OLEDDisplayUi ui (& display); modèle enum {MODEL_NULL, MODEL_LEFT, MODEL_RIGHT, MODEL_BUTTON}; énumération 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; dir booléen = true; int frameIndex = 0; long readEncoderValue (void) {return encoderValue / 4; } boolean isButtonPushDown (void) {if (! digitalRead (buttonPin)) {delay (5); if (! digitalRead (buttonPin)) {tandis que (! digitalRead (buttonPin)); retourne vrai; }} return false; } void msOverlay (affichage OLEDDisplay *, état OLEDDisplayUiState *) {if (frameIndex == 0) return; display-> setTextAlignment (TEXT_ALIGN_RIGHT); display-> setFont (ArialMT_Plain_10); display-> drawString (128, 0, String (angleValue)); } void drawFrame1 (affichage OLEDDisplay *, état OLEDDisplayUiState *, 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 (affichage OLEDDisplay *, état OLEDDisplayUiState *, 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 (); // illustre les 3 tailles par défaut incluses. Les polices proviennent du fichier SSD1306Fonts.h // Outre les polices par défaut, un programme sera utilisé pour convertir les polices TrueType dans ce 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, chaîne ("Pa:") + chaîne (pa)); } void drawFrame3 (affichage OLEDDisplay *, état OLEDDisplayUiState *, int16_t x, int16_t y) {// affichage de démonstration de l'alignement du texte-> setFont (ArialMT_Plain_16); // Les coordonnées définissent le point de départ gauche de l'affichage du texte-> setTextAlignment (TEXT_ALIGN_LEFT); display-> drawString (x, y, "définir la vitesse"); display-> drawString (40 + x, y + 17, String (speedValue)); } void drawFrame4 (affichage OLEDDisplay *, état OLEDDisplayUiState *, int16_t x, int16_t y) {// affichage de démonstration de l'alignement du texte-> setFont (ArialMT_Plain_16); // Les coordonnées définissent le point de départ gauche de l'affichage du texte-> setTextAlignment (TEXT_ALIGN_LEFT); display-> drawString (x, y, "modèle de ventilateur"); if (motorState == MOTOR_STATIC) {display-> drawString (40 + x, y + 27, "STATIC"); } else if (motorState == MOTOR_AUTO) {display-> drawString (40 + x, y + 27, "AUTO"); }} // Ce tableau conserve les pointeurs de fonction sur toutes les images // les images sont les vues uniques qui glissent dans les images FrameCallback = {drawFrame1, drawFrame2, drawFrame3, drawFrame4}; // combien y a-t-il d'images? int frameCount = 4; // Les superpositions sont statiquement dessinées au-dessus d'un cadre, par exemple. une horloge OverlayCallback recouvre = {msOverlay}; int overlaysCount = 1; void ec11Init (void) {pinMode (encoderPinA, INPUT); pinMode (encoderPinB, INPUT); pinMode (buttonPin, INPUT); digitalWrite (encoderPinA, HIGH); // tourne la résistance de rappel sur digitalWrite (encoderPinB, HIGH); // tourne la résistance de pullup sur 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 (frames, frameCount); ui.setOverlays (overlays, 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 (dir == 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) {valeur longue = readEncoderValue (); if (uiEnable == true) {if (valeur> 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; si (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 goingTimeBudget = ui.update (); if (whileTimeBudget> 0) {delay (goingTimeBudget); } doButton (); timer.run (); } void updateEncoder ()

LOL ~ bien fait!