Automated sky brightness monitoring system using the TSL2591 light sensor and INA260 power sensor with MQTT telemetry and Home Assistant integration.
PiSQM measures sky brightness in magnitudes per square arcsecond (MPSAS) using a TSL2591 digital light sensor. The system features adaptive auto-ranging for measurements from daylight conditions to dark sky readings (~22 MPSAS). It also monitors power consumption using an INA260 sensor. Measurements are published via MQTT with automatic Home Assistant discovery support.
Inspired by rabssm/Radiometer.
- Raspberry Pi (any model with I2C GPIO pins)
- TSL2591 light sensor module
- INA260 power sensor module
- Jumper wires for I2C connection
- Weatherproof enclosure (for outdoor deployment)
- Raspberry Pi OS (Raspbian Buster or later)
- Python 3.7 or higher
- I2C interface enabled
- MQTT broker (e.g., Mosquitto) accessible on the network
- systemd (for service installation)
- Active network connection
- Access to MQTT broker (default port 1883)
Enable the I2C bus on the Raspberry Pi:
sudo raspi-configNavigate to: Interface Options → I2C → Enable
Install I2C utilities:
sudo apt-get update
sudo apt-get install -y i2c-tools python3-venv gitConnect the TSL2591 and INA260 sensors to the Raspberry Pi I2C pins:
| Sensor Pin | Raspberry Pi Pin | GPIO Function |
|---|---|---|
| VIN | Pin 1 | 3.3V |
| GND | Pin 6 | Ground |
| SDA | Pin 3 | GPIO2 (SDA) |
| SCL | Pin 5 | GPIO3 (SCL) |
Verify the sensors are detected at address 0x29 (TSL2591) and 0x40 (INA260):
sudo i2cdetect -y 1Expected output shows 29 and 40 in the grid.
cd ~
git clone <repository-url> PiSQM
cd PiSQMEdit MQTT broker settings in main.py:
MQTT_SERVER = "192.168.1.250" # Replace with your MQTT broker IP
TOPIC_SUB = "Test/SQM/sub" # Topic for remote configuration
TOPIC_PUB = "Test/SQM" # Topic for MPSAS readings
TOPIC_PUB_PARAMS = "Test/SQM/Params" # Topic for detailed parametersOptionally configure Home Assistant discovery:
HA_DISCOVERY_PREFIX = "homeassistant" # Default HA discovery prefix
HA_NODE_ID = "sqm_reader" # Unique device IDRun the installation script with sudo:
sudo ./install.shThe script will:
- Fetch latest updates from git
- Create a Python virtual environment
- Install dependencies from
requirements.txt - Generate and install systemd service file
- Enable auto-start on boot
- Start the service
If you prefer manual setup:
# Create virtual environment
python3 -m venv venv
# Activate environment
source venv/bin/activate
# Install dependencies
pip install -r requirements.txtRun manually:
python3 main.pyEdit these values in main.py based on your setup:
| Parameter | Default | Description |
|---|---|---|
M0 |
-16.07 | Magnitude zero point for sensor calibration |
GA |
28.02 | Glass attenuation factor (accounts for enclosure transmission loss) |
MEASURE_INTERVAL |
10 | Seconds between measurements |
Note: GA must be calibrated for your specific enclosure. Higher values indicate more light loss through glass/acrylic.
Send a JSON payload to the subscription topic to update parameters without restarting:
mosquitto_pub -h <broker-ip> -t "Test/SQM/sub" -m '{"M0": -16.0, "GA": 28.5, "interval": 15}'Supported parameters:
M0: Magnitude zero pointGA: Glass attenuationinterval: Measurement interval in seconds
The system writes SQM data to a JSON file for Allsky integration:
/home/pi/allsky/config/overlay/extra/allskytsl2591SQM.json
Format:
{"AS_MPSAS": 21.45}Check service status:
sudo systemctl status pisqm.serviceStart the service:
sudo systemctl start pisqm.serviceStop the service:
sudo systemctl stop pisqm.serviceRestart the service:
sudo systemctl restart pisqm.serviceView real-time logs:
sudo journalctl -u pisqm.service -fConsole output during operation:
Initializing TSL2591...
Initializing INA260...
Publishing Home Assistant Auto Discovery payloads...
Connected to MQTT broker with result code 0
Starting auto-ranging measurement loop...
MPSAS: 21.34 | Time: 200ms | Gain: 16 | Interval: 10s
MPSAS: 21.38 | Time: 200ms | Gain: 16 | Interval: 10s
Published data:
| Topic | Format | Retain | Description |
|---|---|---|---|
Test/SQM |
21.34 |
Yes | Current MPSAS reading (string) |
Test/SQM/Params |
JSON | Yes | Full parameters including gain, integration time, config |
Example Test/SQM/Params payload:
{
"sqm": 21.34,
"gain": 16,
"integration_time_ms": 200,
"timestamp": "2025-12-24 14:30:45",
"config_M0": -16.07,
"config_GA": 28.02,
"ina260_current": 0.1,
"ina260_voltage": 12.1,
"ina260_power": 1.2
}The system publishes MQTT discovery messages on startup. Entities appear automatically in Home Assistant:
- SQM (mpsas) - Primary sky quality measurement
- INA260 Current (A)
- INA260 Voltage (V)
- INA260 Power (W)
- Sensor Gain (diagnostic)
- Integration Time (diagnostic)
- Config M0 (diagnostic)
- Config GA (diagnostic)
- Last Update (diagnostic)
The TSL2591 driver implements adaptive auto-ranging:
- Saturation Detection: If counts exceed 60,000, gain or integration time is reduced
- Low Signal Detection: If counts fall below 200, gain or integration time is increased
- Range Priority: Gain is adjusted before integration time
- Valid Range: System targets 200-60,000 counts for optimal precision
This enables accurate measurements from bright daylight to extremely dark skies without manual intervention.
Symptom: OSError: [Errno 121] Remote I/O error or sensor not detected
Resolution:
- Verify I2C is enabled:
sudo raspi-config - Check wiring connections
- Confirm sensor address:
sudo i2cdetect -y 1 - Test with different I2C pull-up resistors if using long cables
- Verify 3.3V power supply is stable
Symptom: Failed to connect to MQTT broker or continuous reconnection attempts
Resolution:
- Verify MQTT broker is running:
sudo systemctl status mosquitto - Test network connectivity:
ping <broker-ip> - Check firewall rules allow port 1883
- Verify
MQTT_SERVERIP address in main.py - Check broker authentication settings (anonymous access may be disabled)
Symptom: systemctl status pisqm.service shows failed state
Resolution:
- Check logs:
sudo journalctl -u pisqm.service -n 50 - Verify Python dependencies:
source venv/bin/activate && pip list - Confirm file permissions:
ls -l /home/pi/PiSQM - Ensure user
pihas I2C access:sudo usermod -a -G i2c pi - Reboot and retry:
sudo reboot
Symptom: Readings consistently too high/low or unstable
Resolution:
- Calibrate
M0andGAparameters using a reference SQM device - Ensure sensor is not obstructed or contaminated
- Verify enclosure transmission characteristics match
GAvalue - Check for nearby light sources causing interference
- Review integration time and gain in diagnostic output
Symptom: File IO Error: [Errno 2] No such file or directory
Resolution:
- Create directory manually:
sudo mkdir -p /home/pi/allsky/config/overlay/extra - Set permissions:
sudo chown -R pi:pi /home/pi/allsky - Comment out file write section in main.py if Allsky integration is not needed
Remove the service and clean up:
sudo ./uninstall.shThis will:
- Stop the service
- Disable auto-start
- Remove systemd service file
- Reload systemd daemon
The project directory and virtual environment remain intact for potential reinstallation.
PiSQM/
├── main.py # Main application entry point
├── tsl2591.py # TSL2591 sensor driver with auto-ranging
├── ina260.py # INA260 sensor driver
├── requirements.txt # Python dependencies
├── install.sh # Automated installation script
├── uninstall.sh # Service removal script
├── pisqm.service.template # systemd service template
├── README.md # This file
└── CONTEXT_DOCUMENTATION.md # Project context notes
MPSAS = M0 + GA - 2.5 × log₁₀(flux_diff)
Where:
flux_diff= Full spectrum counts - IR counts (in µW/cm²)M0= Magnitude zero point calibrationGA= Glass attenuation factor
- I2C Address:
0x29 - Gain Settings: 1×, 25×, 428×, 9876×
- Integration Times: 100ms, 200ms, 300ms, 400ms, 500ms, 600ms
- Dynamic Range: ~188,000,000:1
- Spectral Responsivity: 400-1050nm
Based on concepts from Richard's ESP-based radiometer: https://github.com/rabssm/Radiometer
- TSL2591 Datasheet: https://ams.com/documents/20143/36005/TSL2591_DS000338_6-00.pdf
- INA260 Datasheet: https://www.ti.com/lit/ds/symlink/ina260.pdf
- Sky Quality Measurement theory: https://www.mnassa.org.za/html/Oct2017/2017MNASSA..76..Oct..215.pdf