K_b0KBsM · 6月14日 · 广东

创客项目秀 | 基于XIAO ESP32C3 的 Cyber Clock

Cyber Clock,一款带湿度温度计的物联网OLED座钟 Cyber Clock,一款带湿度温度计的物联网OLED座钟

微信图片_20240614093501.jpg

今天小编给大家带来的是来自国外的Maker Gokux 的Cyber Clock的项目。该项目由3D打印和开源硬件制作,可以在桌面上当作一个时钟摆件。Gokux 作为一名技术爱好者,喜欢了解新技术和发明。这就是为什么其是特斯拉的忠实粉丝,尤其是Cybertruck。它的设计很酷,很有未来感。Gokux 一直想3D打印一个Cybertruck的小型模型,然后把它放在自己的办公桌上。从这个小想法开始,并在此基础上进行构建。最后,结果是这样的

微信图片_20240614093533.jpg

“The Cyber Clock”,一款可充电电池供电的 1.51 英寸透明 OLED 时钟,具有准确的互联网时间和日期。它还可以通过板载传感器测量您的室温和湿度。它还可以显示电池百分比,并带有完全3D打印的Cybertruck车身。它具有可滚动的轮子,也可以通过拧紧螺丝来锁定轮子,这样它就不会意外地从桌子上掉下来!另外,我想提一下,我从Flipper Zero UI 中汲取了灵感来设计这款表盘。通过这些指导,我们将学习如何自己构建一个并根据您的时区进行定制。因此,让我们开始制作 Cyber Clock 吧。

材料清单

微信图片_20240614093610.jpg

元件列表

  • Seeed Studio XIAO ESP32C3
  • DHT11 温湿度传感器
  • 1.51英寸透明OLED您将获得JST电缆,显示器和驱动板作为套件滑动开关
  • 500mAh 3.7V电池(与600mAh电池相同)
  • 30AWG线
  • 6 * CSK内六角 M3 x 10mm 螺丝
  • B-7000 多用途胶水强力胶
  • Kapton 胶带 10mm
  • 3 * 10k电阻器(您可以使用SMD型或通孔电阻器,我使用SMD 0805电阻器作为分压器,10k通孔用于拉起DHT11信号)

工具

  • 内六角扳手烙铁套件接线钳胶枪二手3D打印机
  • Anycubic Kobra 2 Neo
  • 3D打印耗材
  • Numakers PLA+ 漆黑 Numakers PLA+ 纯白
  • Numakers PLA+ 浅灰色

步骤1. 在Fusion 360 中建模

微信图片_20240614093709.jpg

我使用 Fusion 360 来规划和设计我的项目。我在设计这个项目时考虑了两件事:易于组装和 3D 打印。为了实现这一点,我将项目主体分成了多个部分。通过导入精确的电子元件模型,我可以预先确定它们在机身上的位置。这确保了在我构建原型之前,一切都可以配合并协同工作,从而节省了大量时间和精力。下面提供了所有设计文件。

步骤2. 3D打印

将所有模型导出到。STL 文件,我使用我的 Anycubic 打印机 3D 打印它们。在这个项目中,我使用了三种不同颜色的PLA灯丝:黑色、灰色和白色。你可以找到。步骤 1 中的 STL 文件。打印时,顶部主体需要一些支撑材料。
微信图片_20240614093805.jpg

步骤3.XIAO ESP32C3 烧录代码

我总是喜欢在组装之前将代码上传到微控制器。我正在使用Arduino IDE刷新代码。按照以下教程为 Seeed Studio XIAO ESP32C3 设置 IDE,并了解有关此板的更多信息确保将所有必需的库安装到 Arduino IDE 中

DHT11的库

我们需要一个内部连接来从 NTP 服务器获取时间数据。因此,我们需要将此时钟连接到您的WiFi网络。您可以在 46,47 行上输入您的 WiFi 凭据

const char* ssid     = "ssid";
const char* password = "password"; 

如何设置时区

时区是使用 GMT 偏移量(以秒为单位)配置的。我的 GMT 偏移量是 GMT +5:30,现在我们需要将其转换为秒,即 19800 秒。只需谷歌一下即可轻松转换
微信图片_20240614093946.jpg

您可以在代码的第 65 行中以秒为单位输入您的 GMT 偏移量

NTPClient timeClient(ntpUDP, "pool.ntp.org", 19800, 0);

完整代码

#include <WiFi.h>
#include <SPI.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define ANALOG_PIN D1      // Analog pin connected to the voltage divider
#define ADC_MAX 4095      // 12-bit ADC
#define REF_VOLTAGE 2.8   // Reference voltage of ADC (3.3V for Xiao ESP32C3)
// WiFi credentials
const char* ssid     = "ssid";//your ssid
const char* password = "password";//your wifi password
// OLED display SPI pins
#define OLED_MOSI    D10
#define OLED_CLK     D8
#define OLED_DC      D4
#define OLED_CS      D7
#define OLED_RESET   D5
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
  OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
#define DHTPIN D0
#define DHTTYPE    DHT11
DHT dht(DHTPIN, DHTTYPE);
// NTP client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 19800, 0);
//bit ui bitmap
static const unsigned char PROGMEM image_paint_1_bits[] = {0x60,0xf0,0x90,0x90,0x90,0x90,0xf0};
static const unsigned char PROGMEM image_paint_0_bits[] = {0x7e,0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0xfc,0x7e,0xc1,0x3e,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x7c,0x83,0xd5, float readBatteryVoltage() {
  int analogValue = analogRead(ANALOG_PIN);
  float voltage = (analogValue / (float)ADC_MAX) * REF_VOLTAGE;
  // Voltage divider scaling
  voltage = voltage * (10.5 + 10) / 10.0; // (R1 + R2) / R2
  return voltage;
}
// Function to calculate battery percentage float calculateBatteryPercentage(float voltage) {
  float percentage;
  // Assuming a linear relationship between voltage and percentage
  if (voltage >= 4.2) {
    percentage = 100.0;
  } else if (voltage <= 2.5) {
    percentage = 0.0;
  } else {
    percentage = (voltage - 2.5) / (4.2 - 2.5) * 100.0;
  }
  return percentage;
}
void setup() {
  // Start serial communication
  Serial.begin(115200);
  dht.begin();
  analogReadResolution(12); // Set ADC resolution to 12-bit
  // Initialize OLED display
  if(!display.begin(SSD1306_SWITCHCAPVCC)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever;
  }
  //display.display();
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");
  // Initialize time client
  timeClient.begin(); }
void loop() {
  
  // Update time from NTP server
  timeClient.update();
  unsigned long epochTime = timeClient.getEpochTime();
  struct tm *ptm = gmtime ((time_t *)&epochTime);
  int monthDay = ptm->tm_mday;
  int currentMonth = ptm->tm_mon+1;
  int currentYear = ptm->tm_year+1900;
  int currentHour = ptm->tm_hour;
  int currentMinute = ptm->tm_min;   int currentSecond = ptm->tm_sec;
 float batteryVoltage = readBatteryVoltage();
  float batteryPercentage = calculateBatteryPercentage(batteryVoltage);
  // Get temperature and humidity float t = dht.readTemperature();
  float h = dht.readHumidity();
  // Convert time to 12-hour format
  String period = "AM";
  if (currentHour >= 12) {
    period = "PM";
    if (currentHour > 12) {
      currentHour -= 12;
    }
  } else if (currentHour == 0) {
    currentHour = 12;   }
  // Display data on OLED   display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  // Display time
  display.setCursor(19,6);
  display.setTextSize(3);
  if (currentHour < 10) display.print('0');
  display.print(currentHour);
  display.print(':');
  if (currentMinute < 10) display.print('0');
  display.print(currentMinute);
  display.setTextSize(1);
  display.setCursor(108, 39);
  display.print(period);
  // Display date
  display.setCursor(36, 39);
  if (monthDay < 10) display.print('0');
  display.print(monthDay);
  display.print('/');
  if (currentMonth < 10) display.print('0');
  display.print(currentMonth);
  display.print('/');
  display.print(currentYear);
  // Display temperature
  display.setCursor(79, 53);
  display.print(t);
  display.print("C");   // Display humidity
  display.setCursor(22, 53);
  display.print(h);
  display.print("%");
  display.drawBitmap(0, 0, image_paint_0_bits, 128, 64, 1);
  display.setCursor(14, 39);
  display.print(batteryPercentage,0);
  display.drawBitmap(8, 39, image_paint_1_bits, 4, 7, 1);   display.display();
  // Delay before the next update
  delay(1000);
}

步骤4. 接线示意图

微信图片_20240614094102.jpg
好像接线有点复杂吧?但只需遵循电线连接的颜色和端点上的标签即可。此外,驱动板和原理图上使用的线材颜色是相同的,所以拿起你的工具,让我们开始构建吧

XIAO ESP32C3 支持锂电池充放电管理。这意味着 BMS 是内置的。因此,不需要外部BMS。您可以通过 USB 端口为电池充电

步骤5. 组装和接线

我们可以先在 Xiao 的背面创建一个分压器
微信图片_20240614094141.jpg

步骤 5.1

首先,我们需要在 Xiao 电池端接下放一些 Kapton 胶带
微信图片_20240614094141.jpg

步骤 5.2

将 10k SMD 电阻焊接到两个电池输入端。然后,使用小规格线将电阻器的另一端连接到 D1 引脚以测量电池电压。
微信图片_20240614094222.jpg

步骤 5.3

将电池的正极端子连接到电源开关的一个端子,并将开关的另一个端子连接到 Xiao 的 BAT+。此外,将电池的负极端子直接连接到 Xiao 的 BAT-。此外,将所有电线放在底架中,确保所有电线的长度都合适
微信图片_20240614094348.jpg

步骤 5.4

用胶水粘住电池、小和电源开关。我已经为组件设计了插槽以适应。确保将 xiao 下方的电线穿过缝隙。
微信图片_20240614094417.jpg

步骤 5.5

将 DHT11 的端子切割成适当的长度。在 DTH10 的 VCC 和 DATA 线之间焊接一个 11k 电阻器。此外,将 3 根电线焊接到 VCC、GND 和 DATA,长度可以到达 Xiao 引脚。我在这里使用通孔 10k 电阻器
微信图片_20240614094437.jpg
微信图片_20240614094441.jpg

步骤 5.6

将 DHT11 倒置放入小窗口中。现在,使用我们的 B-11 多用途胶水粘合 DHT7000。(我们在这里不使用热胶,因为热量可能会损坏传感器。
微信图片_20240614094540.jpg

步骤 5.7

将 DHT11 传感器线焊接到 Xiao 中,我还用 Kapton 胶带进行了一些线材管理。现在我们已经完成了下架的大部分工作,让我们继续上半身
微信图片_20240614094707.jpg

步骤 5.8

在此步骤中要非常小心,因为我们将OLED屏幕安装到主体中。处理显示器时不要施加太大的压力,因为它很容易损坏。我们将使用 B-7000 多用途胶水将显示器连接到 3D 打印上。确保显示器的方向正确。
微信图片_20240614094733.jpg

使用驱动板测试显示器时,请务必检查柔性电缆的方向。
微信图片_20240614094801.jpg

在框架的内角、底部和左右角涂上胶水。不要使用过多的胶水,它会从边缘溢出
微信图片_20240614094822.jpg

现在小心地将显示器放入框架中,并确保方向正确。
微信图片_20240614094858.jpg

让胶水干燥 20 分钟。
微信图片_20240614094917.jpg

步骤 5.9

将汽车内部放在主体内,并用强力胶粘合
微信图片_20240614094936.jpg
微信图片_20240614094940.jpg

步骤 5.10

将OLED驱动板粘在车身背面,连接助焊剂电缆
微信图片_20240614095013.jpg

步骤 5.11

现在将灯条推入前面的小缝隙中 3D 打印。如果需要,可以粘上它
微信图片_20240614095034.jpg

步骤 5.12

将 Xiao esp32 天线粘在机身内
微信图片_20240614095057.jpg

步骤 5.13

连接 JST 连接器并将显示驱动器线切割成适当的长度,然后将它们焊接到 Xiao.还要连接天线端口。
微信图片_20240614095119.jpg
微信图片_20240614095141.jpg
微信图片_20240614095155.jpg

步骤 5.14

将上半身放入底架并用两个 M3 螺钉拧紧。
微信图片_20240614095228.jpg
微信图片_20240614095232.jpg

步骤 5.15

使用 m3 螺钉将所有四个车轮拧入前后轴向。如果您的车轮需要旋转,请不要拧紧螺丝。如果您需要锁定车轮,只需拧紧螺丝即可

微信图片_20240614095302.jpg
微信图片_20240614095307.jpg

步骤 5.16

接下来,使用一些强力胶,我们将在底架下方粘合前后轴向
微信图片_20240614095333.jpg
微信图片_20240614095336.jpg

步骤 5.17

这将是建造的最后一步,将两个屋顶组件粘合在主体顶部
微信图片_20240614095407.jpg
微信图片_20240614095411.jpg

是的,项目的组装已经完成现在使用背面的滑动开关打开时钟电源。您也可以通过Xiao USB为电池充电
微信图片_20240614095436.jpg

等待几秒钟。它将通电。时间将自动更新。如果没有,请检查您输入的 WiFi 密码和 SSID 是否正确
微信图片_20240614095455.jpg

步骤6. 故障排除

车轮不能自由旋转:检查车轮螺钉是否不太紧。此外,车轮的孔需要比螺钉大。尝试在3D打印后清除轮孔

时间不更新:在启动过程中,系统最初可能会显示不正确的时间,例如 1971 年,但它会迅速更新到正确的时间。如果它不起作用,这将是网络问题,还要检查您在编程过程中输入的Wi-Fi密码和SSID 电池不充电:电池只能在电源开关打开时充电。通过Xiao内部的BMS管理的电池

关于传感器数据:如果电池电量低于 20%,传感器可能无法提供数据tage 低,因此请为电池充电

关于Cyber Clock 的其他想法

微信图片_20240614095530.jpg

Gokux相信这个项目非常适合汽车爱好者。您可以轻松构建并赠送给热爱汽车的朋友和家人。它是任何办公桌设置的绝佳补充,从黄昏提供梦幻般的视角。这个项目确实是独一无二的,他认为市场上没有类似的东西。如果您需要其他车型,请告诉Gokux,这个项目有很大的潜力。

推荐阅读
关注数
6505
内容数
38
深度服务产业的国际化双创平台
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息