本次成果帖的视频演示发布在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,最终将所有参数清晰地显示在屏幕上。同时对屏幕更新进行了优化,通过缓存机制,仅在参数变化时刷新屏幕,提升性能并避免屏幕闪烁。
我要赚赏金
