本次成果帖的视频演示发布在b站:https://www.bilibili.com/video/BV1A8SKYHE7P/#reply113513150355449
EETV视频链接:https://v.eepw.com.cn/video/play/id/16190
下面是Arduino程序,需要安装两个库文件:TFT_eSPI和BH1750。
#include <SPI.h> #include <TFT_eSPI> #include <BH1750.h> // 引脚定义 const int buttonPin1 = 18; // 按键1引脚 const int buttonPin2 = 17; // 按键2引脚 TFT_eSPI tft = TFT_eSPI(); // 创建屏幕对象 BH1750 lightMeter(0x23); // 创建光强传感器对象 // 按键去抖变量 bool buttonPressed1 = false; bool buttonPressed2 = false; // 全局变量 float FV[11] = { 1, 1.4, 2, 2.8, 4, 5.6, 8, 11, 16, 22, 32 }; // 光圈值数组 float ISOV[5] = { 100, 200, 400, 800, 1600 }; // ISO值数组 byte FVIDx = 0; // 光圈索引 byte ISOIDx = 0; // ISO索引 float F = 1.0, ISO = 100.0, lux = 0, ev = 0, t = 0; // 曝光参数 // 屏幕更新缓存 float prev_lux = -1, prev_ev = -1, prev_t = -1; char buf[20]; // 按键去抖动函数 byte updateIndex(byte index, byte maxIndex, int buttonPin, bool &buttonPressed) { if (digitalRead(buttonPin) == LOW && !buttonPressed) { // 检测按键按下 index = (index + 1) % (maxIndex + 1); // 循环选择索引 buttonPressed = true; // 标记按键已按下 delay(200); // 简单去抖动延时 } else if (digitalRead(buttonPin) == HIGH) { buttonPressed = false; // 按键释放时复位标记 } return index; } // TFT初始化 void tftInit() { pinMode(21, OUTPUT); // TFT电源控制脚 digitalWrite(21, 1); tft.init(); // 初始化TFT屏幕 tft.setRotation(1); // 屏幕旋转90度 tft.fillScreen(TFT_BLACK); // 清屏 tft.setTextColor(TFT_WHITE); // 设置前景色 tft.setTextSize(2); // 设置字体大小 } // 按键初始化 void keyInit() { pinMode(buttonPin1, INPUT); // 按键1初始化 pinMode(buttonPin2, INPUT); // 按键2初始化 } // Arduino主程序初始化 void setup() { Serial.begin(115200); // 串口通信初始化 tftInit(); // 屏幕初始化 keyInit(); // 按键初始化 Wire.begin(); // I2C初始化 if (lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE)) { Serial.println(F("BH1750 Advanced begin")); } else { Serial.println(F("Error initialising BH1750")); } } // 主循环 void loop() { // 更新按键状态 FVIDx = updateIndex(FVIDx, 10, buttonPin1, buttonPressed1); // 更新光圈索引 ISOIDx = updateIndex(ISOIDx, 4, buttonPin2, buttonPressed2); // 更新ISO索引 F = FV[FVIDx]; // 当前光圈值 ISO = ISOV[ISOIDx]; // 当前ISO值 // 每秒刷新一次数据 static uint32_t last_time = 0; if (millis() - last_time > 1000) { last_time = millis(); // 获取光强值 if (lightMeter.measurementReady()) { lux = lightMeter.readLightLevel(); // 计算曝光值EV ev = 2.0 + log2(lux / 10.0); // 计算快门时间T float F2 = pow(F, 2); // 缓存 F^2 t = F2 / (pow(2, ev) * (ISO / 100.0)); // 更新屏幕显示(仅当数据变化时) if (lux != prev_lux || ev != prev_ev || t != prev_t) { tft.fillScreen(TFT_BLACK); // 清屏 // 显示欢迎语 tft.setCursor(10, 10); tft.print("Hello EEPW&DigiKey"); // 显示光强 snprintf(buf, sizeof(buf), "Light: %.1f lx", lux); tft.setCursor(10, 30); tft.print(buf); // 显示ISO snprintf(buf, sizeof(buf), "ISO: %.0f", ISO); tft.setCursor(10, 60); tft.print(buf); // 显示光圈 snprintf(buf, sizeof(buf), "F: %.1f", F); tft.setCursor(140, 60); tft.print(buf); // 显示曝光值EV snprintf(buf, sizeof(buf), "EV: %.2f", ev); tft.setCursor(10, 90); tft.print(buf); // 显示快门时间T snprintf(buf, sizeof(buf), "T: %.5f s", t); tft.setCursor(10, 120); tft.print(buf); // 更新缓存值 prev_lux = lux; prev_ev = ev; prev_t = t; } } } }
本项目通过集成 BH1750 光传感器 和 TFT 屏幕,实时测量环境光强,并结合按键选定的光圈值 F和感光度 ISO,计算曝光值 EV和快门时间T,最终将所有参数清晰地显示在屏幕上。同时对屏幕更新进行了优化,通过缓存机制,仅在参数变化时刷新屏幕,提升性能并避免屏幕闪烁。