这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 电子测光表DIY--进阶任务

共1条 1/1 1 跳转至

电子测光表DIY--进阶任务

菜鸟
2024-11-26 12:17:01     打赏

4ac7fa06de3500e027da8f3109f87ca.jpg

使用杜邦线搭好电路,其中数字光传感器U136负责测光,按键负责调整不同ISO下测光的效果。舵机负责按相机快门,感觉需要做3D打印,打印个支架才比较合适。现在用杜邦线连接,比较乱。由于ESP32-S3评估板,板子上只有一个GND排针,很不方便。这里使用了IIC扩展板,并且将扩展板上的GND焊接出来做了扩展处理,提供给舵机和按键使用。

实现了按键调整ISO值,并且进行测光获得快门值。通过蓝牙上传到手机显示,并且手机可以通过蓝牙控制舵机动作,去按下相机快门。


1、ISO的调整,不同的ISO值,对应着不同的测光模式。这里使用了最常见的几种ISO值,通过红蓝两个按键进行切换。红色按键增加ISO的值,蓝色按键减少ISO的值。

int isoLevels[5] = {100, 200, 400, 500, 1000}; // ISO等级
int offsetiso = 3;
// 两个按键 红色的控制ISO增加 蓝色的减少ISO值
void clickRed()
{
  // Serial.println("Red Button  click.");
  offsetiso = offsetiso == 4 ? offsetiso : offsetiso + 1;
  // Serial.print(offsetiso);
  // Serial.print("    ");
  // Serial.println(isoLevels[offsetiso]);
}
void clickBlue()
{
  offsetiso = offsetiso == 0 ? offsetiso : offsetiso - 1;
  // Serial.print(offsetiso);
  // Serial.print("    ");
  // Serial.println(isoLevels[offsetiso]);
}

image.png

image.png

2、蓝牙功能。将ESP32-S3设置为蓝牙服务端。建立了两个服务,一个是发送信息,通过notify方式,定时(1秒)将测光信息通过蓝牙发送出去,手机端使用的“eFR Connect”,可以从手机端读取到测光信息,并且可以控制舵机拍照。另一个服务是“write”服务,只要有消息从蓝牙上写入,则ESP32-S3端,就会驱动舵机动作,模拟按下快门。

7e86319b28fa1b621fb61154b63dc06.jpg

6d20857f6a4be01ef1bc2f2bef0f8a0.jpg

e4dba86e14575dc409adc9c669129a5.jpg

#include <SPI.h>
#include <TFT_eSPI.h>
#include "OneButton.h"
#include <Adafruit_BMP280.h>
#include <BH1750.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLECharacteristic.h>
#include <ESP32Servo.h>
#define KEYRED 17
#define KEYBLUE 18
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"           //服务UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" //特征UUID
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

BLECharacteristic *pCharacteristic; //创建一个BLE特性pCharacteristic
bool deviceConnected = false;       //连接否标志位

TFT_eSPI tft = TFT_eSPI(); ///创建屏幕对象
Adafruit_BMP280 bmp;       // I2C
BH1750 lightMeter(0x23);   //光线传感器
float lux = 0, ev = 0, fspeed = 0;

int isoLevels[5] = {100, 200, 400, 500, 1000}; // ISO等级
int offsetiso = 3;
Servo servo;            //舵机驱动
int servoPin = 13;
OneButton redButton(KEYRED, true);
OneButton blueButtton(KEYBLUE, true);

// 两个按键 红色的控制ISO增加 蓝色的减少ISO值
void clickRed()
{
  // Serial.println("Red Button  click.");
  offsetiso = offsetiso == 4 ? offsetiso : offsetiso + 1;
  // Serial.print(offsetiso);
  // Serial.print("    ");
  // Serial.println(isoLevels[offsetiso]);
}
void clickBlue()
{
  offsetiso = offsetiso == 0 ? offsetiso : offsetiso - 1;
  // Serial.print(offsetiso);
  // Serial.print("    ");
  // Serial.println(isoLevels[offsetiso]);
}

void tftInit()
{
  pinMode(21, OUTPUT); // TFT电源脚置1
  digitalWrite(21, 1);
  tft.init();                             // st7789屏幕初始化
  tft.setRotation(1);                     // 屏幕旋转90度
  tft.fillScreen(TFT_BLACK);              //全屏填充黑色(即清屏)
  tft.setTextColor(TFT_WHITE, TFT_BLACK); //设置前景色与背景色
  tft.setTextSize(2);
}

// 计算ev值,曝光
void calc_ev() // f:光圈
{
  float evWithISO, aperture;
  if (lightMeter.measurementReady())
  {
    lux = lightMeter.readLightLevel();                   //光强
    ev = 2.0 + log10(lux / 10.0);                        //计算曝光
    evWithISO = ev - log2(isoLevels[offsetiso] / 100.0); // 根据 ISO 调整 EV 值
    // 计算光圈和快门速度
    aperture = pow(2, evWithISO - 2); // 初始光圈为 2.8,可根据需要调整
    // Serial.print("Aperture: ");
    // Serial.println(aperture);
    fspeed = pow(2, log2(aperture * aperture) - ev); //计算快门时间
  }
}

//屏幕显示 测光值
void tft_show()
{
  char buf[120];
  snprintf(buf, sizeof(buf), "Light:%.1flux", lux);
  tft.setCursor(10, 0); //设置坐标开始位置
  tft.print(buf);
  tft.setCursor(10, 30); //设置坐标开始位置
  snprintf(buf, sizeof(buf), "ISO:%4d", isoLevels[offsetiso]);
  tft.print(buf);
  tft.setCursor(160, 30); //设置坐标开始位置
  tft.print("F:2.8");
  snprintf(buf, sizeof(buf), "EV:%.2f", ev);
  tft.setCursor(10, 60); //设置坐标开始位置
  tft.print(buf);
  snprintf(buf, sizeof(buf), "T:%f", fspeed);
  tft.setCursor(10, 90); //设置坐标开始位置
  tft.print(buf);

  //发送给蓝牙
  if (deviceConnected)
  {
    snprintf(buf, sizeof(buf), "Light:%.1flux,ISO:%d,ev:%.2f,T:%.4f", lux, isoLevels[offsetiso], ev, fspeed);
    pCharacteristic->setValue(buf);
    pCharacteristic->notify();
  }
}

//服务器回调
class MyServerCallbacks : public BLEServerCallbacks
{
  void onConnect(BLEServer *pServer)
  {
    deviceConnected = true;
  };
  void onDisconnect(BLEServer *pServer)
  {
    deviceConnected = false;
  }
};

//特性回调
class MyCallbacks : public BLECharacteristicCallbacks
{
  void onWrite(BLECharacteristic *pCharacteristic)
  {
    std::string rxValue = pCharacteristic->getValue();
    if (rxValue.length() > 0)
    {
      String rxload = "";
      for (int i = 0; i < rxValue.length(); i++)
      {
        rxload += (char)rxValue[i];
        Serial.print(rxValue[i], HEX);
        Serial.print(" ");
      }
      Serial.println("");
      // 收到消息就 驱动舵机拍照
      servo.write(90);
      delay(fspeed*1000);
      servo.write(0);
    }
  }
};
void setup(void)
{
  Serial.begin(115200);
  pinMode(KEYRED, INPUT_PULLUP);
  pinMode(KEYBLUE, INPUT_PULLUP);
  redButton.attachClick(clickRed);
  blueButtton.attachClick(clickBlue);
  servo.attach(servoPin, 500, 2500);
  servo.write(0);

  tftInit();
  Wire.begin();
  lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE);

  BLEDevice::init("BLE_ESP32S3");                              //创建设备
  BLEServer *pServer = BLEDevice::createServer();              //设置为服务器
  pServer->setCallbacks(new MyServerCallbacks());              //服务器回调函数设置为MyServerCallbacks
  BLEService *pService = pServer->createService(SERVICE_UUID); //使用上面的服务UUID创建服务
  pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY);
  pCharacteristic->setValue("");
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE);
  //创建一个(写)特征 类型是写入
  pCharacteristic->setCallbacks(new MyCallbacks());
  pService->start();
  pServer->getAdvertising()->start(); //服务器开始广播
}
uint32_t last_time = 0;
void loop(void)
{
  redButton.tick();
  blueButtton.tick();
  if (millis() - last_time > 1000)
  {
    last_time = millis();
    calc_ev();
    tft_show();
  }
}


源码及效果演示

light.zip

https://www.bilibili.com/video/BV1eVBQYzEyY/


共1条 1/1 1 跳转至

回复

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