While I was making a fairy light, I realized the PWM value is non-linearly proportional to the brightness of the LED. Simply speaking, if the PWM value is double the brightness is not double; specially when PWM is close to the maximum, any change is not recognizable by my eyes. I thought it should be a simple calibration issue! and it was how I made this project! The idea is to measure the brightness of an LED with some device (luminosity sensor or photoresistor) and find a correlation between PWM value and the brightness. Then later If I set brightness to 50%, Arduino will calculate the corresponding PWM and dim the LED accordingly.
Therefore, I need a luminosity sensor and an LED to measure the brightness. Using an SD card, I will save the data for later fitting procedure. The fitting will be done in Excel (or any other program). The out put will be used in Arduino code, and that is it! It should be done once. Then you can use the calibration parameter for ever!
Step 1: Parts
Step 2: Wiring
SD card module and luminosity sensor wires should not be changed (most of them). Led should be connected to a PWM pin.
Step 3: Code
I combined three piece of codes:
SD card: used example >SD > ReadWrite in Arduino IDE
TSL 2561: used Adafruit TSL2561 Library example (sensorapi); you will find it in examples, if you install the library (I assume you know how to install a library in Arduino IDE).
LED fading: used examples > Analog > fading
The code, after initializing the modules, will dim the led and read the brightness and save it in SD card. in this way I will collect some data for calibration.
I changed each of the code according to my needs. the final code attached.
The signal should look like the attached picture. Unfortunately I forgot to take a photo so I replot it in excel to show you how it should be.
NOTE: I am using wemo mini D1 instead of Arduino. for some reason that I don't know, the PWM is between 0 and 1023. In Arduino it should be between 0-255. If you want to use the code for arduino, you should take care of it (line 90).
Step 4: Fitting, and Using
after collecting data, I opened the file in excel and plot the data (look at the picture). the first column is PWM value and the second one is lux (reading of the sensor, the unit does not matter much). Therefore, plot lux (y-axis) vs. PWM (x-axis). As you can see the brightness is linearly proportional to the PWM value. I fitted a line to it.
To fit a line follow as :
1- plot the data (insert > scatter plot) i assume you know how.
2- right click on the plotted data
3- click on trendline.
4- (in excel 2013) on the right side a panel pops up. Choose linear. At the bottom choose "display equation on chart".
The linear relation is different from my perception. Therefore I think there should be logarithmic relation between my perception and the brightness (this is the simplest way came to my mind!). So I took the slope of the fit. The intercept is not important, because it depends on the surrounding light pollution! instead, I added 1. Because Log10(0) is infinite. So I need a intercept to solve the problem. In my case the equation look like this:
y =Log10(0.08 x +1), y is the brightness and x is the PWM value (0-1023)
I normalized the equation to the maximum value. then output rang is always between 0-100. this way I can ask arduino for a certain relative brightness, without concerning the maximum absolute brightness.
y =Log10(0.08 x +1)*100/1.914
Because in arduino my input is the relative brightness, I need to re-arrange the equation for x (PWM):
x = (10^(y*1.914/100) - 1) / 0.08
using this equation in the code we are able to get a linear brightness change. So you ask arduino for a brightness (y) between 0-100, and arduino calculates the corresponding PWM value. in this way, if double the brightness, your perception is also the same.
if you want to use it in your code you better to add this lines:
brightness=50; // in percentage
PWM = pow(10,brightness*1.914/100)-1)/0.0793;
NOTE: the normalization is done for a maximum PWM of 1023 (for Wemos mini D1). For Arduino PWM is between 0-255. you need to calculate it accordingly.
NOTE2: I added a log-linear plot to show how the our perception and PWM value are related. you should not use it for fitting!
Step 5: Conclusion
the calibration works fine for me. When the PWM values is large, I can see the difference. Before as the large values I could not see the effect of dimming. Basically most of the changes were done in a small range of PWM. now it is calibratied!
each LED, specially different colors, should have it is own calibration parameters. However I calibrated a blue LED and used the parameter for a white LED and the result was acceptable. so maybe you can use my calibration parameter without bothering yourself!!