Components and supplies
Pushbutton switch 12mm
Resistor 10k ohm
Arduino Nano R3
BH1750FVI Digital Light Intensity Sensor Module
Breadboard (generic)
Rotary potentiometer (generic)
0.96" 128x64 OLED I2C Display
Apps and platforms
Arduino IDE
Project description
Code
ArduMeter
c_cpp
Code for ArduMeter (v2)
1/* 2 ArduMeter (Arduino incident light meter) version 2 3 by Alan Wang 4 5 BH1750/BH1750FVI digital light intensity sensor: 6 Library: https://github.com/claws/BH1750 7 VCC -> 3.3V 8 GND -> GND 9 SDA -> pin A4 10 SCL -> pin A5 11 ADD -> (none) 12 13 0.96" SSD1306 OLED 128x64 display: 14 Library: https://github.com/greiman/SSD1306Ascii 15 VCC -> 3.3V 16 GND -> GND 17 SDA -> pin A4 18 SCL -> pin A5 19 20 1x push button 21 leg 1 -> pin D2 22 leg 2 -> GND 23 24 2x 10 kOhms potentiometer (knob) 25 leg 1 -> 3.3V 26 leg 2 (middle) -> pin A0/A1 (max analog signal about 730-740) 27 leg 3 -> GND 28 29 ------------------------------ */ 30 31// Set this to true if you wish to get "standard" shutter settings 32#define STANRARD_SHUTTER_SPEED false 33 34// Calibration constant (C) for incident light meters. 35// see https://en.wikipedia.org/wiki/Light_meter#Calibration_constants 36#define INCIDENT_CALIBRATION 330 37 38// Max analog readings from potentiometers. Change it only if you are 39// using different input voltage or potentiometers that are not 10K. 40#define KNOB_MAX_ANALOG_READING 740 41 42// Define pins 43#define BUTTON_PIN 2 // D2 44#define KNOB_APERTURE_PIN 0 // A0 45#define KNOB_ISO_PIN 1 // A1 46 47// Pre-defined aperture and ISO settings. Modify them for your own preference. 48// Elements in the array have to be sorted from min to max. 49const double APERATURE_TABLE[] = {1.0, 1.4, 1.8, 2.0, 2.8, 3.5, 4.0, 4.5, 5.6, 6.3, 8.0, 11.0, 12.7, 16.0, 22.0, 32.0}; 50const int ISO_TABLE[] = {6, 12, 25, 50, 100, 160, 200, 400, 800, 1600, 3200}; 51 52// The "shutterspeed table" array is used when STANRARD_SHUTTER_SPEED is set to true. 53// 1/2 (0.5) seconds is expressed as 2, and 2 seconds is expressed as -2. 54double SHUTTERSPEED_TABLE[] = {-60, -30, -15, -8, -4, -2, -1, 2, 4, 8, 15, 30, 60, 125, 250, 500, 1000, 2000, 4000}; 55 56// If you are using older cameras which have different shutter speed settings, 57// you can switch to the folloing array: 58// double SHUTTERSPEED_TABLE[] = {-1, 2, 5, 10, 25, 50, 100, 250, 500, 1000}; 59 60/* ------------------------------ */ 61 62#include <math.h> 63#include <Wire.h> 64#include <BH1750.h> 65#include "SSD1306Ascii.h" 66#include "SSD1306AsciiAvrI2c.h" 67 68BH1750 bh1750; 69SSD1306AsciiAvrI2c oled; 70 71bool started = false; 72int EV, apertureIndex, apertureIndexOld, isoIndex, isoIndexOld; 73long lux; 74 75void setup() { 76 77 // initialize serial port 78 Serial.begin(9600); 79 Wire.begin(); 80 81 // prepare the shutterspeed table array if needed 82 if (STANRARD_SHUTTER_SPEED) { 83 for (int i = 0; i < (sizeof(SHUTTERSPEED_TABLE) / sizeof(double)); i++) { 84 if (SHUTTERSPEED_TABLE[i] < 0) { 85 SHUTTERSPEED_TABLE[i] = 1 / abs(SHUTTERSPEED_TABLE[i]); 86 } 87 } 88 } 89 90 // setup button 91 pinMode(BUTTON_PIN, INPUT_PULLUP); 92 93 // set the BH1750 in BH1750_ONE_TIME_HIGH_RES_MODE_2 94 bh1750.begin(0x21); 95 96 // "initialize" BH1750 by using it once 97 bh1750.readLightLevel(); 98 99 // initialize OLED 100 oled.begin(&Adafruit128x64, 0x3c); 101 oled.setFont(System5x7); 102 oled.set2X(); 103 104 Serial.println("ArduMeter (Arduino incident light meter for camera) READY:"); 105 Serial.println("- Press button to measure light."); 106 Serial.println("- Turn knobs to change aperature/ISO."); 107 108 oled.clear(); 109 oled.println("ArduMeter"); 110 oled.println("READY"); 111 oled.println("press"); 112 oled.println("button"); 113} 114 115void loop() { 116 117 //read status from button and potentiometers 118 getKnobIndex(); 119 120 if (buttonPressed()) { //measure light 121 if (!started) started = true; 122 displayExposureSetting(true); 123 delay(150); 124 125 } else { //change aperture/ISO settings 126 if ((apertureIndex != apertureIndexOld || isoIndex != isoIndexOld) && started) { 127 displayExposureSetting(false); 128 delay(150); 129 } 130 } 131 132 //record potentiometer previous status 133 apertureIndexOld = apertureIndex; 134 isoIndexOld = isoIndex; 135 136 delay(50); 137} 138 139// read if the button is pressed (pulled low) 140bool buttonPressed() { 141 return !digitalRead(BUTTON_PIN); 142} 143 144// map knob analog readings to array indexes 145void getKnobIndex() { 146 apertureIndex = round(map(analogRead(KNOB_APERTURE_PIN), 0, KNOB_MAX_ANALOG_READING, 0, sizeof(APERATURE_TABLE) / sizeof(float))); 147 isoIndex = round(map(analogRead(KNOB_ISO_PIN), 0, KNOB_MAX_ANALOG_READING, 0, sizeof(ISO_TABLE) / sizeof(int))); 148} 149 150// measure/calculate and display exposure settings 151void displayExposureSetting(bool measureNewEV) { 152 153 double aperature = APERATURE_TABLE[apertureIndex]; 154 int iso = ISO_TABLE[isoIndex]; 155 156 // measure light level (illuminance) and get a new lux value 157 if (measureNewEV) { 158 lux = bh1750.readLightLevel(); 159 Serial.print("Measured illuminance = "); 160 Serial.print(lux); 161 Serial.println(" lux"); 162 } 163 164 //calculate EV 165 EV = log10(lux * iso / INCIDENT_CALIBRATION) / log10(2); 166 167 if (isfinite(EV)) { //calculate shutter speed if EV is neither NaN nor infinity 168 169 // calculate shutter speed 170 double shutterspeed = (pow(2, EV) / pow(aperature, 2)); 171 172 // choose standard shutter speed if needed 173 if (STANRARD_SHUTTER_SPEED) { 174 for (int i = 0; i < (sizeof(SHUTTERSPEED_TABLE) / sizeof(double)) - 1; i++) { 175 if (shutterspeed >= SHUTTERSPEED_TABLE[i] && shutterspeed <= SHUTTERSPEED_TABLE[i + 1]) { 176 if (abs(shutterspeed - SHUTTERSPEED_TABLE[i]) <= abs(shutterspeed) - SHUTTERSPEED_TABLE[i + 1]) { 177 shutterspeed = SHUTTERSPEED_TABLE[i]; 178 } else { 179 shutterspeed = SHUTTERSPEED_TABLE[i + 1]; 180 } 181 break; 182 } 183 } 184 } 185 186 // output result to serial port 187 Serial.print("Exposure settings: EV = "); 188 Serial.print(EV); 189 Serial.print(", ISO = "); 190 Serial.print(iso); 191 Serial.print(", aperture = f/"); 192 Serial.print(aperature, 1); 193 Serial.print(", "); 194 Serial.print("shutter speed = "); 195 if (shutterspeed > 1) { 196 Serial.print("1/"); 197 Serial.print(shutterspeed); 198 } else { 199 Serial.print((1 / shutterspeed)); 200 } 201 Serial.println("s"); 202 203 // output result to OLED 204 oled.clear(); 205 oled.print("EV: "); 206 oled.println(EV, 1); 207 oled.print("ISO "); 208 oled.println(iso); 209 oled.print("-- f/"); 210 oled.println(aperature, 1); 211 oled.print("-- "); 212 if (shutterspeed > 1) { 213 oled.print("1/"); 214 oled.print(shutterspeed, 0); 215 } else { 216 oled.print((1 / shutterspeed), 0); 217 } 218 oled.println("s"); 219 220 } else { 221 Serial.println("Exposure out of bounds"); 222 oled.clear(); 223 oled.println("Exposure"); 224 oled.println("value"); 225 oled.println("out of"); 226 oled.println("bounds"); 227 } 228}
Downloadable files
ArduMeter circuit
Cleaner version by using a normal breadboard
ArduMeter circuit
ArduMeter circuit
Cleaner version by using a normal breadboard
ArduMeter circuit
Comments
Only logged in users can leave comments
alankrantas
0 Followers
•0 Projects
Table of contents
Intro
13
0