这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » Let'sDo第3期任务DIY一个电子测光表-成果帖

共2条 1/1 1 跳转至

Let'sDo第3期任务DIY一个电子测光表-成果帖

菜鸟
2024-11-20 21:07:24     打赏

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




关键词: 测光     成果     按键     屏幕     任务    

专家
2024-11-21 02:46:28     打赏
2楼

看看是怎么弄的


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]