# Portable Weather Station for Night Sky Observers

1,579

13

6

Light pollution is one of many problems in world. For solve that problem, we need to know how much is night sky polluted with artificial light. Many students with teachers in world try to measure light pollution with expensive sensors. I decided to change my portable luxmeter (for more check previous instructables project Portable Luxmeter ) to weather station with TSL2591 sensor. This sensor is sensitive enough for measure night pollution. Also, I add HTU21D for temperature and humidity measure.

### Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

## Step 1: What Is Night Pollution and How It Measure

Night pollution is light from lamps, cars, houses, huge lcd panels in city and every light made by human. That light call artificial. For observers, artificial light is main problem to see stars from city, and they must go outside city. For human, high light pollution is harmful. And also for trees, grass and animals.

For checking light pollution of your place, you can see here lightpollutionmap

It is only model, and real values can vary. That's why I created that luxmeter.

For measure light pollution, I measure only lux and calculate magnitude/ arsec2.

I can calculate from lux to candela per suqare meters :

1 cd/m2 = 1 lux

Magnitude per square arcsecond (mag/arcsec2) describe night sky background (it calls surface brightness).

More on wiki: Surface brightness

For calculating cd/m2 to mag/arcsec2 is formula:

[value in mag/arcsec2] = Log10([value in cd/m2]/108000)/-0.4

unihedron.com/projects/darksky/magconv.php

## Step 2: BOM

For this project you need:

1. WEMOS D1 Mini or any microcontroller

(I use wemos, because it is smallest one, with usb port, you can try Arduino Nano)

WEMOS D1 MINI (Yanwen Economic Air Mail)

WEMOS D1 MINI 10 pcs (China Post Registered Air Mail - free Shiping)

2. TSL2591 Sensor

TSL2591 (Yanwen Economic Air Mail)

TSL2591 (China Post Registered Air Mail)

3. HTU21D temperature and humidity sensor

HTU21D (Cainiao Super Economy)

HTU21D (Yanwen Economic Air Mail - free shipping)

4. OLED display 0.96 (128 x 64)

OLED display

OLED display

OLED display

5. 18650 battery

18650 lithium ion battery

18650 lithium ion battery

6. TP4056 charging module

tp4056

7. switch buttons or dip jumper

swtich red dip

swtichers, a lot of different

9. case, I create from wood + tape

red tape

## Step 3: Circuit

Circuit is pretty simple:

Connect all i2c modules (TSL2591, OLED, HTU21D) to SCL and SDA pins on wemos (SDA -> D2, SCL -> D1).

Power them with 3.3 V from wemos.

Connect plus terminal of battery to 5V pin on wemos and battery + pin on tp4056 charging module to plus terminal on battery.

Connect all grounds together.

## Step 4: HTU21D Sensor

I buy new temperature sensor, which measure with accuracy 0.3 °C !

• Uses the I2C interface
• Typical humidity accuracy of ±2%
• Typical temperature accuracy of ±0.3 °C
• Operates from 0 to 100% humidity but this sensor isn’t recommended for harsh environments where it could come in contact with water (such as rain).
• 3.3V sensor - use inline logic level converters or 10k resistors to limit 5V signals
• Only one HTU21D sensor can reside on the I2C bus at a time

My summary: it is good sensor, because it measure with accuracy 0.3 °C and both - temperature and humidity. Pros is I2C interference and cons 3.3V, but it doesn't matter in my case.

## Step 5: TSL2591

This sensor is good for measure night sky pollution because of it sensitivity (to 188 micro lux!).

1. are diodes with possible ir and full measure. I don't use it.

2. voltage regulator from 5V to 3.3 V

• Approximates Human eye Response
• Extremely wide dynamic range 1 to 600,000,000 Counts
• Lux Range: 188 uLux sensitivity, up to 88,000 Lux input measurements.
• Temperature range: -30 to 80 *C
• Voltage range: 3.3-5V into on board regulator
• Interface: I2C
• This board/chip uses I2C 7-bit address 0x29 (fixed)
• Dimensions: 19mm x 16mm x 1mm / .75" x .63" x .04"Weight: 1.1g
• 2 diodes for measure both - IR and Full spectrum

Summary:

188 uLux is perferct, also I2C communication is simple. Maybe problem can be fixed I2C adress (0x29). Also on board regulator is good and possible to use sensor during winter (frost).

## Step 6: Code

You need these libraries (I add them to one zip file):

Code : you can use mine, or create own. Don't forget to set maximal integration time (600 MS) and gain to max (GAIN_MAX) for night sky measure.

If you try to use my code, please download ino file. When I copy from instructable my code, something wrong with libraries.

http://javl.github.io/image2cpp/

```//https://lastminuteengineers.com/oled-display-arduino-tutorial/<br>//http://javl.github.io/image2cpp/
// mcd to magnitude <a href="http://unihedron.com/projects/darksky/magconv.php?ACTION=SOLVEMAGS&txtCDM2=0.1" rel="nofollow"> http://unihedron.com/projects/darksky/magconv.php...</a>
// The HD44780 is a controller for character-based liquid crystal displays (LCDs).  <a href="https://www.quinapalus.com/hd44780udg.html" rel="nofollow"> http://unihedron.com/projects/darksky/magconv.php...</a>

int counter;

Adafruit_SSD1306 display(-1);  // - 1 for restart display with restart button on arduino board
Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591); // pass in a number for the sensor identifier (for your use later)

uint32_t lum;
uint16_t ir, full;
int ulux;
float lux;
float temp;
float rel_hum;
float mag_arcsec2; // visual mags/arcsecond² [value in mag/arcsec2]  =   Log10([value in cd/m2]/108000)/-0.4

// symbols
// degree for Celsius
const unsigned char degree [] PROGMEM =
{
0xe,0x11,0x11,0x11,0xe,0x0,0x0,0x0
};

// exponent 2
const unsigned char exponent [] PROGMEM =
{
0xe,0x1b,0x3,0x6,0xc,0x18,0x1f,0x0
};

// 'moon_logo', 128x64px
const unsigned char intro [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x03, 0xff, 0xc0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x07, 0xff, 0xe0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x07, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0f, 0xff, 0x77, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x1f, 0xbe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x1f, 0xcc, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x3f, 0xc0, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x3f, 0xc0, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x3f, 0xe0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x3f, 0x80, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xe0, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xe0, 0x60, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xe7, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc0, 0x18, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc0, 0x38, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc0, 0x48, 0x7f, 0xff, 0xff, 0xff, 0xc0, 0x1f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc0, 0x80, 0x3f, 0xff, 0xff, 0xff, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc0, 0xc4, 0x1f, 0xff, 0xff, 0xfc, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc0, 0x60, 0x0f, 0xff, 0xff, 0xff, 0x80, 0x0f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc0, 0xf0, 0x03, 0xff, 0xff, 0xff, 0xf0, 0x07, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf0, 0xe3, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x01, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x43, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x4f, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x5f, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0xff, 0xff, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x03, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x01, 0xff, 0xff, 0xb7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfc, 0x01, 0x0f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfc, 0x01, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x01, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x7f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x1f, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

void setup() {

// htu21d
htu.begin();

// tsl2591
sensor_t sensor;
tsl.getSensor(&sensor);
tsl.setGain(TSL2591_GAIN_MAX);  // MAX, HIGH MED,LOW,
tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS); // 100MS, 200 MS, 300MS, 400MS,500MS, 600MS

// setup for oled display
display.clearDisplay();
display.display();
display.drawBitmap(0, 0,  intro, 128, 64, WHITE);
display.display();
delay(1000);
display.setTextSize(1);
display.setTextColor(WHITE);
display.setFont(&FreeSerif9pt7b);
display.clearDisplay();

}

void loop() {

lux = 0;
ulux =0;
mag_arcsec2=0;
temp=0;
rel_hum=0;

delay(100);
lum = tsl.getFullLuminosity();
ir = lum >> 16;
full = lum & 0xFFFF;
delay(100);
lux = tsl.calculateLux(full, ir);  // light intensiti in microlux
ulux= lux*1000000;
if (ulux<0)
{
ulux=0;
}

mag_arcsec2 = log10(lux/108000)/-0.4;  //(log((ulux/108000) ) /(-0.4)

display_values();

}

void display_values()
{
//display.drawPixel(120, 50, WHITE);
display.clearDisplay();
display.setCursor(1, 15);
display.print(temp);
display.drawBitmap(42, 2,  degree, 8,5 , WHITE);
display.setCursor(50, 15);
display.print("C");
display.setCursor(70, 15);
display.print(rel_hum);
display.setCursor(114, 15);
display.print("%");
display.drawLine(1, 20, 127, 20, WHITE);
display.drawLine(67, 1, 67, 20, WHITE);
display.setCursor(1, 35);
display.print("ulux =");
display.setCursor(50, 35);
display.print(ulux);
display.setCursor(1, 55);
display.print("mag/arsec");
display.drawBitmap(70, 45,  exponent, 8,8 , WHITE);
display.setCursor(83, 55);
display.print(mag_arcsec2);
display.display();
}```

## Step 7: Inside

I create own case and I use breadboard with dupont cables as you can see.

I use TP4056 for charging battery with usb cable (need swtich dip jumper).

For turn on/off I use dip jumper.

For daylight, TSL2591 shows 0 and mag/arcsec2 is nan.

For night sky should TSL2591 show from 0 to 1000 000 microlux (ulux) and corresponding mag/arcsec2

(cca . 14 to 22 mag/arsec2).

For fullMoon I measured 50k ulux which is 0.05 lux.

Participated in the
Sensors Contest

## Recommendations

• ### Large Motors Class

13,255 Enrolled

## 6 Discussions

Hay,

I made it and it is a great project to learn from, for me it has certainly sense to made project like you did.
BTW i live in the Netherlands (Rotterdam) and it is unbelieveble how much artificial light we have unfortunate.
Thanks again and keep making "simple "projects.
Regards Tobo.