Open-source weather station for astronomy
at main 5.1 kB view raw
1import time 2import math 3from machine import I2C, Pin, RTC, ADC 4 5try: 6 import usocket as socket 7except: 8 import socket 9 10import dht 11from mlx90640 import MLX90640, RefreshRate, init_float_array 12import tsl2591 13 14# To connect to weather station : http://astroweatherstation/index.html or http://10.42.0.126/index.html 15 16# Define time 17rtc = RTC() 18# Initialize I2C 19i2c = I2C(0, sda=Pin(22), scl=Pin(23), freq=400_000) 20# DHT22 Temperature+Humidity 21DHT22sensor = dht.DHT22(Pin(0)) 22# MLX90640 Infrared camera 23MLX90640sensor = MLX90640(i2c) 24MLX90640sensor.refresh_rate = RefreshRate.REFRESH_2_HZ 25ir_frame = init_float_array(768) 26# MH-RD Rain sensor 27MHRDsensor = ADC(Pin(1)) 28MHRDsensor.width(ADC.WIDTH_12BIT) 29MHRDsensor.atten(ADC.ATTN_11DB) 30# TSL2591 luminosity 31TSL2591 = tsl2591.TSL2591(i2c=i2c) 32TSL2591.gain = tsl2591.GAIN_HIGH 33TSL2591.integration_time = tsl2591.INTEGRATIONTIME_100MS 34 35def dew_point(tc, rh): 36 # tc: Temperature in Celsius 37 # rh: Relative humidity 38 b = 17.625 39 c = 243.04 # degC 40 gamma = math.log(rh/100) + b*tc/(c+tc) 41 td = c*gamma/(b-gamma) 42 return td 43 44def cutout_frame(data, x, y, size_x, size_y, w=32, h=24): 45 half_x = size_x // 2 46 half_y = size_y // 2 47 cut = [] 48 for i in range(-half_x, half_x + 1): 49 for j in range(-half_y, half_y + 1): 50 xi = min(max(x + i, 0), w - 1) 51 yj = min(max(y + j, 0), h - 1) 52 cut.append(data[w*yj + xi]) 53 return cut 54 55def mean(l): 56 n = len(l) 57 m = 0 58 for i in range(n): 59 m += l[i] 60 return m/n 61 62# Establish connection 63s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 64try: 65 s.bind(('', 80)) 66except OSError: 67 continue 68s.listen(5) 69 70oldsec = -1 71oldmins = -1 72while True: 73 # Get time 74 tnow = rtc.datetime() 75 year = str(tnow[0]) 76 month = str(tnow[1]) if tnow[1]>=10 else '0'+str(tnow[1]) 77 day = str(tnow[2]) if tnow[2]>=10 else '0'+str(tnow[2]) 78 hour = str(tnow[4]) if tnow[4]>=10 else '0'+str(tnow[4]) 79 minute = str(tnow[5]) if tnow[5]>=10 else '0'+str(tnow[5]) 80 sec = int(tnow[6]) if tnow[6]>=10 else '0'+str(tnow[6]) 81 str_date_time = f"{year}-{month}-{day}T{hour}:{minute}:{sec}" 82 83 # Update every 10s 84 if ((int(sec) - int(oldsec) > 10) or (minute != oldmins)): 85 oldsec = sec 86 oldmins = minute 87 88 # DHT22 Temperature+Humidity 89 DHT22sensor.measure() 90 tc = DHT22sensor.temperature() 91 rh = DHT22sensor.humidity() 92 td = dew_point(tc, rh) 93 94 # MLX90640 Infrared camera 95 MLX90640sensor.get_frame(ir_frame) 96 MLX90640sensor.get_frame(ir_frame) # Read twice to solve checkerboard issue 97 ir_center = cutout_frame(ir_frame, 16, 12, 5, 5) 98 temp_sky = mean(ir_center) 99 # Heuristic to check in real conditions 100 if (temp_sky < -8.): 101 clouds = 0 102 elif (temp_sky < 0.): 103 clouds = (temp_sky + 8.)/8 104 else: 105 clouds = 1 106 107 # MHRD Rain sensor 108 rain_sens = MHRDsensor.read() 109 if (rain_sens > 3_000): 110 rain = 0 111 elif (rain_sens > 2_800): 112 rain = -(rain_sens - 3_000)/(3_000-2_800) 113 else: 114 rain = 1 115 116 # TSL2591 luminosity 117 tsl_lux = TSL2591.lux_auto_gain 118 tsl_ir = TSL2591.infrared 119 tsl_vis = TSL2591.visible 120 tsl_full = TSL2591.full_spectrum 121 122 # Write HTML file 123 print(str_date_time) 124 file = open("index.html", "w") 125 file.write('<html>\n<head><title>AstroWeatherStation</title></head>\n<body>\n') 126 file.write('timestamp=' + str_date_time + ' <br />\n') 127 file.write(f"ir_sky={temp_sky:.2f} <br />\n") 128 file.write(f"clouds={clouds:.2f} <br />\n") # WeatherWatcher keyword 129# file.write('forecast={0:.3f}'.format(clouds) + ' <br />\n') # WeatherWatcher keyword 130 file.write(f"temperature={tc:.2f} <br />\n") # WeatherWatcher keyword 131 file.write(f"humidity={rh:.2f} <br />\n") # WeatherWatcher keyword 132 file.write(f"dew_point={td:.2f} <br />\n") 133 file.write(f"rain_sensor={rain_sens:.0f} <br />\n") 134 file.write(f"precip={rain:.2f} <br />\n") # WeatherWatcher keyword 135# file.write(f"wind={wind:.2f} <br />\n") # WeatherWatcher keyword 136# file.write(f"gust={gust:.2f} <br />\n") # WeatherWatcher keyword 137# file.write(f"pressure={pressure:.2f} <br />\n") # WeatherWatcher keyword 138 file.write(f"luminosity={tsl_lux:.5f} <br />\n") 139 file.write('</body>\n') 140 file.write('<ir_image>\n') 141 file.write(f"ir_image={str(ir_frame)} <br />\n") 142 file.write('</ir_image>\n') 143 file.write('</html>\n') 144 file.close() 145 146 # Upload file 147 file = open("index.html", "r") 148 response = file.read() 149 file.close() 150 151 conn, addr = s.accept() 152 print('Got a connection from %s' % str(addr)) 153 request = conn.recv(1024) 154 conn.send('HTTP/1.1 200 OK\n') 155 conn.send('Content-Type: text/html\n') 156 conn.send('Connection: close\n\n') 157 conn.sendall(response) 158 conn.close()