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

共7条 1/1 1 跳转至

电子测光表过程贴

菜鸟
2024-11-02 21:40:55     打赏

本贴主要记录在完成4个基础任务过程中的一些完成细节,包括软件开发环境部署、硬线连接,调试开发过程中遇到的问题等的记录。

软件开发环境准备。打开Arduino IDE,在首选项里面,添加:

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json

image.png

之后选择TFT屏幕驱动:

image.png

之前安装的库比较旧,可以在线更新。

image.png

任务一、编程实现按键状态采集

硬线连接:

image.png

从上图可以看到,红色与蓝色按键的信号分别连接到开发板的A1与A0.

image.png

在代码中定义如下:

int buttonPinRed = 17;
int buttonPinBlue = 18;

设置为输入模式,下降沿触发中断。

  pinMode(buttonPinRed, INPUT);
  pinMode(buttonPinBlue, INPUT);
  attachInterrupt(digitalPinToInterrupt(buttonPinRed), updateScreen_BtnRedPressed, FALLING);
  attachInterrupt(digitalPinToInterrupt(buttonPinBlue), updateScreen_BtnBluePressed, FALLING);

在按键按下后,分别在彩屏上显示红色与蓝色的实心圆,这样比较直观。因此要解决TFT屏幕显示问题。这里采用的是Adafruit官方的GFX与ST7789库。包含如下头文件。

#include <Adafruit_GFX.h>     // Core graphics library
#include <Adafruit_ST7789.h>  // Hardware-specific library for ST7789


接下来是屏幕初始化:

// turn on backlite
  pinMode(TFT_BACKLITE, OUTPUT);
  digitalWrite(TFT_BACKLITE, HIGH);

  // turn on the TFT / I2C power supply
  pinMode(TFT_I2C_POWER, OUTPUT);
  digitalWrite(TFT_I2C_POWER, HIGH);
  delay(10);

  // initialize TFT
  tft.init(135, 240);  // Init ST7789 240x135
  tft.setRotation(3);
  tft.fillScreen(ST77XX_BLACK);

  Serial.println(F("Initialized"));

  tft.setTextColor(ST77XX_YELLOW);
  tft.setTextSize(2);
  tft.println("Hello EEPW & DigiKey");
  tft.setCursor(0, 0);
  delay(1000);

接下来定义按键中断回调函数:

void updateScreen_BtnRedPressed() {
  Serial.println("Inside ISR: push button down!!!");
  tft.fillRect(16 * 10, 32, 32, 16, ST77XX_BLACK);
  tft.drawBitmap(16 * 10, 32, str_f_HONG, 16, 16, ST77XX_RED);
  tft.drawBitmap(16 * 11, 32, str_f_SE, 16, 16, ST77XX_RED);
  tft.fillCircle(16 * 13, 38, 10, ST77XX_RED);
}

void updateScreen_BtnBluePressed(){
      tft.fillRect(16*10,32,32,16,ST77XX_BLACK);
      tft.drawBitmap(16*10, 32, str_f_LAN, 16, 16, ST77XX_BLUE);
      tft.drawBitmap(16*11, 32, str_f_SE, 16, 16, ST77XX_BLUE);    
      tft.fillCircle(16*13, 38, 10, ST77XX_BLUE);
}

此外,采用取字模的方式,显示汉字:

image.png

const uint8_t PROGMEM str_f_SE[] = { 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x07, 0xC0, 0x08, 0x80, 0x01, 0x00, 0x03, 0xE0, 0x1E, 0x40, 0x12, 0x40, 0x13, 0x80, 0x1C, 0x00, 0x10, 0x04, 0x10, 0x04, 0x0C, 0x3C, 0x03, 0xC0, 0x00, 0x00 };   /*"色",0*/
const uint8_t PROGMEM str_f_HONG[] = { 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x12, 0x18, 0x34, 0xE0, 0x08, 0x20, 0x10, 0x20, 0x1E, 0x20, 0x02, 0x20, 0x04, 0x3E, 0x3B, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*"红",1*/
const uint8_t PROGMEM str_f_LAN[] = { 0x00, 0x00, 0x00, 0x40, 0x04, 0x40, 0x03, 0xF8, 0x1E, 0x80, 0x04, 0x60, 0x0A, 0x40, 0x0A, 0xB0, 0x0A, 0x20, 0x0A, 0x20, 0x00, 0xF0, 0x0F, 0xD0, 0x0A, 0xA0, 0x0A, 0xFE, 0x35, 0x00, 0x00, 0x00 };  /*"蓝",2*/

烧录到板子:

image.png

可以看到已经成功驱动屏幕函数实现字符显示“Hello EEPW & Digikey”,并且成功实现了按键状态的采集。

遇到的烧录失败:

image.png

此类问题解决办法:手动按住D0按键,然后再插上USB线缆,这样就使得ESP32S3进入BOOT模式。

DO按键在本开发板上有两个功能:1,BOOT按键;2,正常的INPUT引脚。


任务三、基于屏幕驱动函数实现字符的显示,例如显示Hello EEPW & DigiKey;也可显示自己喜欢的名言警句

这部分字符显示在任务一的展示部分已经记录,并成功展示。


任务二、编程实现数字光传感器BH1750的数据读取

根据M5stack官网介绍,其提供了Arduino的驱动库:

image.png

安装成功后会有提示:

image.png

在源代码中包含头文件:

#include <M5_DLight.h>

初始化BH1750传感器:

  Serial.println("Sensor begin.....");
  sensor.begin();
  sensor.setMode(CONTINUOUSLY_H_RESOLUTION_MODE);

在主循环中读取亮度数据:

void loop() {
  lux = sensor.getLUX();
  Serial.printf("lux: %dn", lux);
  delay(500);
}

可以看到用手挡住传感器的时候,串口打印的传感器数据值较小;手移开后,亮度值较大。

image.png

任务四、实现光强信息的屏幕显示

有了之前驱动TFT屏幕以及上一步后去光照传感器数据的代码,下面使用脏矩形填充固定区域,然后把传感器数据打印到屏幕上即可。

void loop() {
  lux = sensor.getLUX();
  Serial.printf("lux: %dn", lux);
  tft.fillRect(30, 60, 200, 50, ST77XX_BLACK);
  tft.setCursor(30, 60);
  tft.setTextSize(3);
  tft.print("lux = ");
  tft.print(lux);
  delay(500);
}

实现效果:

image.png

接下来就是根据LUX值计算出曝光值EV,这里可以参考老师提供的公式:

image.png

之后就可以利用右边的公式来根据光圈F的大小来计算出快门速度T。当前的公式是在ISO100的感光值下。更完整的公式如下:

image.png

上述公式可以进行变形:

EV = LOG2(F*F) + (-LOG2(T)) - (LOG2(ISO/100))= AV + TV - SV.

基本的实现思路就是按键控制F光圈大小,另一个按键控制调节ISO感光值,然后就可以计算出快门速度T。接下来就是把这些结果在TFT屏幕上显示出来即可。

lux = sensor.getLUX();
ev = round(2 + log(lux / 10) / log(2));
//one btn control ISO (svIdex), another button control Speed (tvIndex)
tvIdex = ev + svIdex - avIdex;

为了实现快速计算,已经预先计算好了一系列光圈值对应的曝光值,一系列快门速度对应的曝光值,一些列ISO感光等级对应的曝光值,从而实现快速计算。

const char *AV[] = { "1  ", "1.4", "2  ", "2.8", "4  ", "5.6", "8  ", "11 ", "16 ", "22 ", "32 " };

const char *TV[] = { "1     ", "1/2   ", "1/4   ", "1/8   ", "1/15  ", "1/30  ", "1/60  ", "1/125 ", "1/250 ", "1/500 ", "1/1000" };

const char *SV[] = { "100 ", "200 ", "400 ", "800 ", "1600" };

最终完整的显示效果如下:

image.png



工程师
2024-11-03 09:28:52     打赏
2楼

学习了。


专家
2024-11-03 10:07:29     打赏
3楼

谢谢分享


专家
2024-11-03 10:48:43     打赏
4楼

感谢分享


院士
2024-11-04 15:52:47     打赏
5楼

光圈 :1、1.4、2 、2.8、4 、5.6、8、11、16、22、32;

速度:1、1/2、1/4、1/8、1/15、1/30、1/60、1/125、1/250、1/500、1/1000

感光度 :100、200、400、800、1600

EV(曝光量) = LOG2(F*F) + (-LOG2(T)) - (LOG2(ISO/100))

             = AV(光圈) + TV(快门速度) - SV(感光度)

谢谢分享。


菜鸟
2024-11-05 10:33:58     打赏
6楼

感谢楼主分享,谢谢!


专家
2024-11-09 22:55:20     打赏
7楼

谢谢分享


共7条 1/1 1 跳转至

回复

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