LEDs as sensors: putting it to test

There was a workshop at SIGGRAPH 2018 titled LEDs as Sensors, and I was tipped to it via the hackaday post from 2018-08-21, “A LED you can blow out” (with no added sensor it said, which is technically true if you stick to the meaning of “added” in the title).

Basically, the gist of it is to just feed an LED some DC current and watch its forward voltage drop: it varies with temperature, so if after you let it warm up a bit you blow quickly on it, you should notice a sudden change in voltage. Connect that to an analog input on your micro-controller of choice, do some averaging to smooth-out noise, and that sudden change can be used as a trigger to “blow out” the LED.

Note that for any quick voltage change to be observed, there must be minimal thermal inertia around the LED junction.  This means that “normal” LEDs with big plastic casings don’t work for this purpose. The article suggests a tiny pre-wired SMD LED.  Since I wanted to test this out without ordering (and waiting) an LED, I’ve decided to search around the junk drawer; the best candidate I could find was a scrap of LED light strip which had exposed SMD LEDs soldered to the tape and an SMD resistor thrown in for every 3 LEDs. That’s what I tested with, and I’m happy to report that it (sort of) worked.

Some references and links to more info / materials


Figuring out the wiring on an LED strip segment

First things first, I needed to figure out how the LED light strip I had lying around is wired-up. This is not always easy to see by just looking at, as paint makes the conductive tracks barely discernible and a bit hard to identify:

Segment 1

However, shining a strong light underneath the strip did the trick of exposing the copper traces, and the wiring becomes evident:

Segment 2.jpg

It turns out that each segment is wired with three LEDs and one 150-ohm resistor in series, and each of the strip segments is connected in parallel to all others.

Isolating on LED and measuring it out

I’ve decided to use one of the LEDs on the strip segment and the series resistor for this test. This would require me to just solder the three leads – ground, VCC from a digital output and the voltage sensing for the ADC.  Here’s my beautiful sketch of a plan:

WhatsApp Image 2018-08-23 at 15.03.22.jpeg

Determining the LED voltage drop and dimensioning the series resistor

With the leads soldered, I’ve measured the forward voltage drop in the resistor, 2.6v.

A meter reading 2.63v as the forward drop on an LED, shown lit above the meter

Since the series resistor on the strip is 150-ohm, a quick calculation shows that if powered from 5v, the current I=V/R over the LED would be:  (5v – 2.6v) / 150R = 16mA.  This is ok from the standpoint of running this from a digital output pin on an Arduino, but a bit more than the 12mA in the original circuit;  I’ve figured it would work.

And it did!  I do need to blow hard and quick in order to trigger the action in the software (and I had to tweak the parameters in the code a bit, but in the end I did manage to consistently turn off this LED with a quick hard blow.





Mining catcoins – an energy view

Some friends put together an initiative for a cat rescue NGO: catcoins. The premisse is simple: you visit the site, agree to donate CPU time to the cause of helping stray cats, and the site will use your browser to mine a cryptocurrency for the NGO, while showing pictures of cats up for adoption, in the hopes of finding ’em a new home.

The idea is great, as it capitalizes on the current boom in cryptocurrencies, and brings visibility to the NGO, even if the actual monetary value from the mining activity is not that great.  From my part, I wanted to use this as an experiment to get an idea about the cost involved in the mining of this currency.

The experimental setup

I’ve used two rigs for testing this: a Raspberry Pi 3 (Quad Core 1.2GHz Broadcom BCM2837 64bit CPU) and an HP ZBook 15 laptop (Intel i7-4810MQ Quad Core 2.80 GHz). Both systems ran the mining in the Chrome browser – experimentally Firefox ran about 10-20% faster than Chrome, but the numbers below were all captured running on Chrome.

The results with the Raspberry Pi

Power usage idling:    2.4W
Power usage mining:    5.5W

Results from 10min mining:
- Calculations:        2796
- Performance:         4.66 calc/s
- Amount R$:           1.1486654161781946072684642438453e-4

If this setup ran continuously for 1 year (approx):
- Calculations:        146957760
- Amount accrued:      R$  6.04
- Electricity cost:    R$ 22.64

The results with the Intel-based laptop

Power usage idling:    88W (laptop, monitor, router)
Power usage mining:    135W (mining adds roughly 47W)

Results from 10min mining:
- Calculations:        25590
- Performance:         42.65 calc/s
- Amount R$:           0.0010513

If this setup ran continuously for 1 year (approx):
- Calculations:        1345010400
- Amount accrued:      R$  55.26
- Electricity cost:    R$ 555.82
- Electricity cost:    R$ 192.68 (just the added cost of mining)


  • Using the javascript interpreter on the browser to mine cryptocurrency is not cost effective, you spend more on electricity than you accrue in coin; and that is not factoring the cost of the equipment.
  • In fact, with the cost of electricity for consumers in Brazil, the cost ratio is almost 4:1
  • In terms of the amount of coin per KWh of electricity, the Raspberry Pi may be more efficient than the laptop; this is not possible to attest with certainty from this measurements as the Pi was running barebones and headless, and the notebook had two monitors, external keyboard and mice, and an access point, all powered from the same power outlet were the measurements were taken. A comparable setup would require measuring power just for the laptop and having its LCD off during the test.
  • Finally, 10 minutes is a rather small time window for this experiment, should we want results with a higher degree of confidence.

A man with one watch knows what time it is

There is a quote I always liked, by Lee Segall, which is actually known as Segall’s law – it seems like there’s a “law” made out of every witty saying.  It goes like this:

A man with one watch knows what time it is; a man with two watches is never quite sure.

I was duly reminded of it recently: having acquired four DHT22 humidity-and-temperature sensors, I set out to comparte them and see whether they report similar results out of the same environmental conditions.  The experimental setup was simple, a NodeMCU SoC with each DHT22 connected to its own GPIO pin (this sensor module does not implement a bus and thus each require its own dedicated I/O pin).  Readings were taken every 5 seconds and output to the serial port as CSV values (one reading per line).


The results of collecting data for 15 minutes can be seen below. The first set of curves show the temperature, with starts out between 20.3 and 21.0 ºC (a disagreement of 0.7 ºC, or 3% between the sensors.


02 Temperature and humidity with air conditioning.png

The second set of curves, the humidity readings, appears more coherent, but that is a mere effect of the scale of the values being larger due to an overall larger excursion of the sampled data. The humidity starts out with the sensors reading between 66.9% and 77,5% – for a much larger 10.6% disagreement.

Overall during the 15min this test ran the maximum disagreement from the sensors on the temperature was a mild 1.1ºC, while the maximum difference in readings in the humidity was 13.1%

The drop in temperature and humidity displayed in the chart was induced by an ar-conditioned being turned on – it is interesting to note that the humidity drops at first, then start to climb back up after the temperature stabilized; this is an effect which I cannot explain, neither I can infer whether this was “real” or an artifact of the way the sensor works.  Empirically the air felt dryer, but I would not trust the feeling alone and I had no other sensors at hand.


  1. The humidity readings from the DHT22 cannot be trusted to be accurate; one is not going to make a weather station with these guys, not without some serious calibration with more accurate sensors
    1. However, the trend values were consistent – same rate of decline/climb; for the application I have in mind this is all I care about.
  2. Temperature is looking good: they all reported more or less the same values. I’m yet to check these readings against a different sensor module – I have a few DS18B20 modules, and these are fairly precise little things.

A picture is worth a thousand words

In an earlier post we’ve seen the first steps for getting a NodeMCU ESP board working with the ESP8266 Arduino Core, and in the end we made an LED blink. That’s a start, if not a terribly exciting one.  In this post we’re going to do something a bit more interesting.

There is a class of small and cheap OLED displays based on the SSD1306 controller. These displays have a resolution of 128×64 pixels and are monochrome (usually blue or white), although there are color versions as well.  The monochrome displays have a I2C serial interface, so they take only two GPIO pins (labelled SLC, for the clock signal, and SDA, for the data line) on your device (the other two pins in the board are VCC and GND).


Connecting the display to the ESP board

As mentioned earlier, only two GPIO pins are needed for an I2C bus, which is the one employed by this display. Any two pins work, but I’ll suggest using D5 for SLC and D3 for SDA; this will make it easier to play with the examples from graphics library we’re going to use later.  The connections should look something like this: (make sure your own display exposes the pins in the same order, GND, VCC, SLC, and SDA, or adapt the connections)

Mono OLED display

Note that besides the clock and data lines, it is necessary to supply power (VCC) and a ground reference (GND) to display.  This is accomplished by connecting the corresponding pins in the display and board to the top lines in the protoboard. Notice that we’re feeding 3.3v from the ESP board to the display. This particular display is “5v-ready”, and can be fed with anything from 3v to 5v.

Interfacing with the display

There are several libraries available which are capable of driving a SSD1306-based display; the most popular seem to be Adafruit_SSD1306, u8glib and esp8266-oled-ssd1306.  Any of them will do the job, and the interface has comparable methods for drawing and handling text.  For the sake of this post I’ve selected esp8266-oled-ssd1306 from Daniel Eichhorn, which by the way has a very nice weather monitor kit on his site, well worth checking out.

While you can manually download the latest version of your choice of library, most of them are available through the library manager in the Arduino IDE, which is a more convenient way of fetching libraries.

OLED library

Along with the library you’ll download a set of examples, which will be exposed in the IDE through the menu File > ESP8266 and ESP32 Oled Driver for SSD1306 display.  Open any of these entries and notice that in the beginning of the source file there is a declaration for a display variable:

// Initialize the OLED display using Wire library
SSD1306 display(0x3c, D3, D5);
// SH1106 display(0x3c, D3, D5);

There are three important things to notice about the fragment of code above:

  1. First, it is required to initialize the correct type of driver, SSD1306 or SH1106, corresponding to the controller used on your display;
  2. Having the controller defined, the next important bit is the address of the I2C device. Most SSD1306 displays seem to be configured as 0x3c, as shown above. If you’re not sure, here’s a very handy I2C scanner sketch which will probe the serial bus and report over the serial port any devices found.
  3. Finally, the last bit is making sure you get the pin assignments right. The D3/D5 shown above match the inital suggestion of connecting SLC to D5 and SDA to D3, so you should be able to open any of the libraries’ example and upload to the board them unchanged

Making sure that the basic connection is working, do explore the samples. There are some interesting examples of how to get text on the display and do some simple drawing.

Getting started with the NodeMCU dev board

After many happy years working on the Arduino platform, I’ve recently decided to migrate to the ESP8266 platform from Espressif.  The ESP8266 is a great combination of WiFi hardware with a versatile micro-controller. The most widely used embodiment of this chip is in the form of the many ESP-xx modules, such as ESP-01, ESP-12, etc.

On top of the basic ESP-xx modules there is a great many development boards available from the likes of Adafruit and ThinkGeek, to name just two. Out of the many available options I have selected NodeMCU, a name which refers to both to a firmware package with embedded scripting based on the Lua language, as well as a development module based on ESP-12.

Using the Arduino IDE for NodeMCU development

There are different ways of developing for the ESP8266 platform, raging from a full toolchain to prepare and load your firmware images, a web compiler which prepares a NodeMCU firmware for you, to which you add your own code as Lua scripts, as well as using the Arduino IDE to compile and upload your own firmware. Since I’m already familiar with the Arduino IDE, that’s the only route I’ve invested any time into so far.

ESP8266 Arduino Core

To add support to the NodeMCU board in the Arduino IDE one must use the ESP8266 Arduino Core contrib board core. No need to download it directly (unless you want the bleeding edge); you install support for this board by using the Board Manager in the IDE (Tools –> Board –> Board Manager) and selecting “esp8266 by ESP8266 Community”. At the time of this posting, version 2.3.0 was the latest available.

2017-07 Board Manager - ESP286 Core


Depending on your system, you might have to install drivers for the USB Serial adapter in the dev board. Looking at the system’s Device Manager, you should either see a new serial port appear when the board is connected or, failing that, a device unsupported due to unavailable drivers. In my dev board the UART bridge is a CP210x from Silicon Labs, and the drivers can be found here. Make sure you look into Device Manager to make sure you get the right drivers for your board.

Selecting the board and loading your first program

Once support for the board has been added to the IDE and the serial port has been detected in the OS, we are ready for loading our first program into the development board. The easiest way to begin is to select an example supplied with the board core to flash the board’s built-in LED – this is the proverbial ‘blink’ example that is the first Arduino program in every tutorial since the beginning of time.

To do that, first select the correct board: Tools –> Board –> Node MCU 1.0 (ESP-12E Module) – or pick another variant if you’re using a different ESP board. Next, select the serial port (Tools –> Port) making sure to pick the port assigned to your device by the operating system (COM5 in my example below).

2017-07 Board selection

Having selected the correct board, it is time to open the example program, found under Tools –> File –> Examples –> ESP8266 –> Blink (note that because the ESP8266 board is selected, there is a whole category of examples in the menu which are specific to this boards).   The code is rather simple and can be seen below:

 ESP8266 Blink by Simon Peter
 Blink the blue LED on the ESP-01 module
 This example code is in the public domain

 The blue LED on the ESP-01 module is connected to GPIO1
 (which is also the TXD pin; so we cannot use Serial.print() at the same time)

 Note that this sketch uses LED_BUILTIN to find the pin with the internal LED

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);     // Initialize the LED_BUILTIN pin as an output

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, LOW);   // Turn the LED on (Note that LOW is the voltage level
                                    // but actually the LED is on; this is because
                                    // it is acive low on the ESP-01)
  delay(1000);                      // Wait for a second
  digitalWrite(LED_BUILTIN, HIGH);  // Turn the LED off by making the voltage HIGH
  delay(2000);                      // Wait for two seconds (to demonstrate the active low LED)

All this code is doing is to configure the pin named LED_BUILTIN (actually pin D0 on the board) as an output and then use the main loop to flash the LED with a duty cycle of 1 second OFF and 2 seconds ON. Pretty simple, but seeing the led flash on the board confirms that everything is setup correctly and you now loaded your first program into the board.

First experiments with pinhole solargraphy

Deployed three pinhole cameras loaded with B&W paper, first attempt at pinhole photography. Retrieved them after six months, one of them had water damage to the paper, which was basically unusable, the other two produced these images:


The first image shows quite a lot of detail, including a couple of cars which have a pretty stable routine, as they were in the same position for quite a number of days on these six months. That white car in the bottom actually holds the world record for consistent parking, just so you know.


On the second image we have much less fine detail on the scenery, a set of trees, but we have the sun in the picture as a set of bright curved lines. Each line represents a day and when there is a part or a whole line missing that is a day (or part of it) in which the sun wasn’t shinning. The curved line on the top-right is a VHF aerial, distorted by the perspective from the can, and the upright line connected to it is its mast.

two reasons help explain the reduced level of detail on this image: first, trees do not exactly stand still, and also their foliage cover changes a lot. But even for the static structures, this “camera” was exposed to direct sunlight and its interior was not painted black, so it is likely that internal reflections helped reduce the contrast.

Finally, here is the paper as it comes out of the pinhole camera:


It does not look like much, but invert the colors and adjust the contrast and detail level and the image at the top will pop-out.