DIY Arduino 入射式测光表

Whr 35cm2020-11-291294 次点击1 人感谢
> A Lightmeter/Flashmeter for photographers, based on Arduino.
>
> Components:
> 1. Arduino NANO v.3
> 2. BH1750 light sensor
> 3. SSD1306 128*96 OLED SPI Display
> 4. Buttons
>
> Thanks @morozgrafix[ https://github.com/morozgrafix](https://github.com/morozgrafix) for creating schematic diagram for this device.
>
> The lightmeter based on Arduino as a main controller and BH1750 as a metering cell. Information is displayed on SSD1306 OLED display. The device is powered by 2 AAA batteries.
>
> Functions list:
>
> * Ambient light metering
> * Flash light metering
> * ND filter correction
> * Aperture priority
> * Shutter speed priority
> * ISO range 8 - 4 000 000
> * Aperture range 1.0 - 3251
> * Shutter speed range 1/10000 - 133 sec
> * ND Filter range ND2 - ND8192
> * Displaying amount of light in Lux.
> * Displaying exposure value, EV
> * Recalculating exposure pair while one of the parameter changing
> * Battery information
> * Power 2xAAA LR03 batteries
> Detailed information on my site:[ https://www.pominchuk.com/lightmeter/](https://www.pominchuk.com/lightmeter/)
<!--more-->

<span style="font-size: 12pt;">**_!!!此简易测光表对付负片足以!!!_**</span>

<span style="font-size: 12pt;">**_!!!如果用于正片或是需要精确曝光的环境请使用商业测光表!!!_**</span>

 

* * *

# 所需元件

* 主机

1. Arduino nano
2. BH1750光强度模块
3. 0.96寸 7针SPI接口oled屏幕(SSD1306)
4. 微动开关

* 供电

1. 3v升压5v模块

* 如果用锂电池供电的话记得换成充电宝升压模块

2. 电池

* 可以用两节AAA电池
* 或者使用CR123等一次性锂电池
* 或者用锂电池

3. 拨动开关
[![](https://cdn.rec709.cf/imgs/2020/11/b9f6cd1dc4f2a9bf.png)](https://cdn.rec709.cf/imgs/2020/11/b9f6cd1dc4f2a9bf.png)[![](https://cdn.rec709.cf/imgs/2020/11/b8309eb963aba09c.png)](https://cdn.rec709.cf/imgs/2020/11/b8309eb963aba09c.png)

# 设计PCB

* ☑ 尺寸5*5
* ☑ 独立供电模块
* ☑ 独立开关
* ❎ CR2032供电

* 供电不足

* 改用CR123A供电

* 🔄 设计底板

* * *

# 源码&&焊接

<pre class="prettyprint">#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <BH1750.h>
#include <EEPROM.h>
#include <avr/sleep.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for SSD1306 display connected using software SPI (default case):
#define OLED_DC 11
#define OLED_CS 12
#define OLED_CLK 8 //10
#define OLED_MOSI 9 //9
#define OLED_RESET 10 //13
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

BH1750 lightMeter;

#define DomeMultiplier 2.17 // Multiplier when using a white translucid Dome covering the lightmeter
#define MeteringButtonPin 2 // Metering button pin
#define PlusButtonPin 3 // Plus button pin
#define MinusButtonPin 4 // Minus button pin
#define ModeButtonPin 5 // Mode button pin
#define MenuButtonPin 6 // ISO button pin
#define MeteringModeButtonPin 7 // Metering Mode (Ambient / Flash)
//#define PowerButtonPin 2

#define MaxISOIndex 57
#define MaxApertureIndex 70
#define MaxTimeIndex 80
#define MaxNDIndex 13
#define MaxFlashMeteringTime 5000 // ms

float lux;
boolean Overflow = 0; // Sensor got Saturated and Display "Overflow"
float ISOND;
boolean ISOmode = 0;
boolean NDmode = 0;

boolean PlusButtonState; // "+" button state
boolean MinusButtonState; // "-" button state
boolean MeteringButtonState; // Metering button state
boolean ModeButtonState; // Mode button state
boolean MenuButtonState; // ISO button state
boolean MeteringModeButtonState; // Metering mode button state (Ambient / Flash)

boolean ISOMenu = false;
boolean NDMenu = false;
boolean mainScreen = false;

// EEPROM for memory recording
#define ISOIndexAddr 1
#define apertureIndexAddr 2
#define modeIndexAddr 3
#define T_expIndexAddr 4
#define meteringModeAddr 5
#define ndIndexAddr 6

#define defaultApertureIndex 12
#define defaultISOIndex 11
#define defaultModeIndex 0
#define defaultT_expIndex 19

uint8_t ISOIndex = EEPROM.read(ISOIndexAddr);
uint8_t apertureIndex = EEPROM.read(apertureIndexAddr);
uint8_t T_expIndex = EEPROM.read(T_expIndexAddr);
uint8_t modeIndex = EEPROM.read(modeIndexAddr);
uint8_t meteringMode = EEPROM.read(meteringModeAddr);
uint8_t ndIndex = EEPROM.read(ndIndexAddr);

int battVolts;
#define batteryInterval 10000
double lastBatteryTime = 0;

#include "lightmeter.h"

void setup() {‌
pinMode(PlusButtonPin, INPUT_PULLUP);
pinMode(MinusButtonPin, INPUT_PULLUP);
pinMode(MeteringButtonPin, INPUT_PULLUP);
pinMode(ModeButtonPin, INPUT_PULLUP);
pinMode(MenuButtonPin, INPUT_PULLUP);
pinMode(MeteringModeButtonPin, INPUT_PULLUP);

//Serial.begin(115200);

battVolts = getBandgap(); //Determins what actual Vcc is, (X 100), based on known bandgap voltage

Wire.begin();
lightMeter.begin(BH1750::ONE_TIME_HIGH_RES_MODE_2);
//lightMeter.begin(BH1750::ONE_TIME_LOW_RES_MODE); // for low resolution but 16ms light measurement time.

display.begin(SSD1306_SWITCHCAPVCC, 0x3D);
display.setTextColor(WHITE);
display.clearDisplay();

// IF NO MEMORY WAS RECORDED BEFORE, START WITH THIS VALUES otherwise it will read "255"
if (apertureIndex > MaxApertureIndex) {‌
apertureIndex = defaultApertureIndex;
}

if (ISOIndex > MaxISOIndex) {‌
ISOIndex = defaultISOIndex;
}

if (T_expIndex > MaxTimeIndex) {‌
T_expIndex = defaultT_expIndex;
}

if (modeIndex < 0 || modeIndex > 1) {‌
// Aperture priority. Calculating shutter speed.
modeIndex = 0;
}

if (meteringMode > 1) {‌
meteringMode = 0;
}

if (ndIndex > MaxNDIndex) {‌
ndIndex = 0;
}

lux = getLux();
refresh();
}

void loop() {‌
if (millis() >= lastBatteryTime + batteryInterval) {‌
lastBatteryTime = millis();
battVolts = getBandgap();
}

readButtons();

menu();

if (MeteringButtonState == 0) {‌
// Save setting if Metering button pressed.
SaveSettings();

lux = 0;
refresh();

if (meteringMode == 0) {‌
// Ambient light meter mode.
lightMeter.configure(BH1750::ONE_TIME_HIGH_RES_MODE_2);

lux = getLux();

if (Overflow == 1) {‌
delay(10);
getLux();
}

refresh();
delay(200);
} else if (meteringMode == 1) {‌
// Flash light metering
lightMeter.configure(BH1750::CONTINUOUS_LOW_RES_MODE);

unsigned long startTime = millis();
uint16_t currentLux = 0;
lux = 0;

while (true) {‌
// check max flash metering time
if (startTime + MaxFlashMeteringTime < millis()) {‌ break; } currentLux = getLux(); delay(16); if (currentLux > lux) {‌
lux = currentLux;
}
}

refresh();
}
}
}</pre>
 

* [lightmeter.ino](https://od.rec709.cf/%F0%9F%8D%8CArduino%E6%B5%8B%E5%85%89%E8%A1%A8/%E6%BA%90%E7%A0%81/lightmeter/)
* [Adafruit_Circuit_Playground](https://od.rec709.cf/%F0%9F%8D%8CArduino%E6%B5%8B%E5%85%89%E8%A1%A8/%E5%BA%93%E6%96%87%E4%BB%B6/Adafruit_Circuit_Playground.zip)
* [Adafruit_Sensor-master](https://od.rec709.cf/%F0%9F%8D%8CArduino%E6%B5%8B%E5%85%89%E8%A1%A8/%E5%BA%93%E6%96%87%E4%BB%B6/Adafruit_Sensor-master.zip)
* [Adafruit_SSD1306-master](https://od.rec709.cf/%F0%9F%8D%8CArduino%E6%B5%8B%E5%85%89%E8%A1%A8/%E5%BA%93%E6%96%87%E4%BB%B6/Adafruit_SSD1306-master.zip)
* [Adafruit-GFX-Library-master](https://od.rec709.cf/%F0%9F%8D%8CArduino%E6%B5%8B%E5%85%89%E8%A1%A8/%E5%BA%93%E6%96%87%E4%BB%B6/Adafruit-GFX-Library-master.zip)
* [BH1750-master](https://od.rec709.cf/%F0%9F%8D%8CArduino%E6%B5%8B%E5%85%89%E8%A1%A8/%E5%BA%93%E6%96%87%E4%BB%B6/BH1750-master.zip)

* * *

[![](https://cdn.rec709.cf/imgs/2020/11/ea5d819c1594b056.jpg)](https://cdn.rec709.cf/imgs/2020/11/ea5d819c1594b056.jpg)

[![](https://cdn.rec709.cf/imgs/2020/11/a67161e94bfcbf8f.jpg)](https://cdn.rec709.cf/imgs/2020/11/a67161e94bfcbf8f.jpg)

[![](https://cdn.rec709.cf/imgs/2020/11/8e8f31e17e16778c.jpg)](https://cdn.rec709.cf/imgs/2020/11/8e8f31e17e16778c.jpg)
[![](https://cdn.rec709.cf/imgs/2020/11/84c4e9e1489c57b9.jpeg)](https://cdn.rec709.cf/imgs/2020/11/84c4e9e1489c57b9.jpeg)
DIY测光表测光模式相当于相机内中央平均测光。在大多数拍摄情况下中央平均测光是一种非常实用的测光模式,在拍摄人像旅游照等对于中央亮度起到决定性作用的拍摄场景时,应用广泛。

* * *

# Bugs

❌ 大E了

1. ❌板子上画的是CR2032的电池尺寸,装起来发现带不动测光表
2. ❌ 供电模块画反了

* * *

# 样片

<del><span style="font-size: 8pt; font-family: 'arial black', sans-serif;">_咕咕咕_</span></del>

 

[转载自自己的博客](https://www.whrblog.online/archives/1657)
收藏 ♥ 感谢
Spoony 小组长 2020-11-29 
blog 不错,加油

登录注册 后可回复。




› 相关内容关注微信公众号