---
title: 'Light sensor for working room'
---
# Light Sensor For Home Studio Using Raspberry Pi Pico WH (Aiming for higher grade)
**Author**: Mohammad Reza Nazeri, mn224pn
This project is a part of the summer course 2025 **Applied Internet of Things** at Linnaeus University.
# Short Project Overview
This project is about to building a light sensor for studio room with using Raspberry Pi Pico WH, an LED (to represent the light or lamp in the studio), a photoresistor(LDR) to measure light level of the room, two buttons (one for toggle the LED ON/OFF and other one for switching between auto & manual mode) and a potentiometer to adjust the light level of LED.The system sends data of LDR to adafruit platform to visualize it in dashhboard & can trigger the LED remotely by using options from the dashboard & get notified via discord server about component status.
# Estimated Time to Complete
Basically it takes around **10 hours** or even less to implement the code, connect the pico to adafruit and test all features.
# Why This Project?
To find out which project I should do, I was thinking about my daily life routine and because of my programm that I'm studying and my hobbies that force me to seat behind my PC and spend several hours at my home studio area which is usually quite dark, I thought about to do something cool & at the same time practical.
Then I decided to make a light Sensor with controling it in both auto & manual so I still can have turn on some LED to have a bit of light and also make the studio more cozy & nice.
# Purpose
The main purpose of this device is to turn on the LED automatically when the sensor detects too much darkness and have an option to manual mode to switch it ON & OFF and adjust the brightness in both modes.
In addtion to that, it will send the data to a dashboard which can control the LED remotely from there.
# Insights
Learn about how to bridge hardware and software, local control and remote management and read and write the data.
## Bill of Materials
| Item | Picture | Specifications | Cost | Where to Buy |
|---------------------------------|----------|----------------------------------------------------------|---------------------|--------------|
| 1x Raspberry Pi Pico WH | <img src="https://hackmd.io/_uploads/H1kwz8qrgg.jpg" width="120"/> | Raspberry Pi Pico Microcontroller board with Wi-Fi and Bluetooth with Soldered pins | 99 SEK | [Electro:kit](https://www.electrokit.com/raspberry-pi-pico-wh) |
| Solderless Breadboard 840 tie-points | <img src="https://hackmd.io/_uploads/ByceZLcBge.jpg" width="120"/> | Standard breadboard | 69 SEK | [Electro:kit](https://www.electrokit.com/kopplingsdack-840-anslutningar) |
| 1x USB cable A-male to micro B-male 1m | <img src="https://hackmd.io/_uploads/rkJ_G8cBeg.png" width="120"/> | USB cable for connecting Pico WH to PC | 35 SEK | [Electro:kit](https://www.electrokit.com/usb-kabel-a-hane-micro-b-5p-hane-1m) |
| 1x Photoresistor CdS 4-7 kohm | <img src="https://hackmd.io/_uploads/Bk5Zl85Bxg.jpg)" width="120"/> | Light dependent resistor (LDR), the resistance decreases as the light increases. | 9.50 SEK | [Electro:kit](https://www.electrokit.com/fotomotstand-cds-4-7-kohm) |
| 2x Push button PCB black | <img src="https://hackmd.io/_uploads/rymdzU9Heg.jpg" width="120"/> | Tact switch for PCB mounting with black plastic button | 6.40 SEK | [Electro:kit](https://www.electrokit.com/en/tryckknapp-pcb-12x12x5mm?srsltid=AfmBOoqN2IleHFHfWvnIGwGf_Iq4ATWuwci7lN8Co8Of317J0wGprrhQkRg&gQT=1) |
| 1x LED 5mm red diffuse 1500mcd | <img src="https://hackmd.io/_uploads/SkRybIcBel.jpg" width="120"/> | Red LED | 1.4 SEK | [Electro:kit](https://www.electrokit.com/lysdioder-rod-5mm-ca-10-st?gad_source=1&gad_campaignid=21123236116&gclid=CjwKCAjw4K3DBhBqEiwAYtG_9HYSOVdkmKnzPEga7FlEDf_ejn6pbWxAkBS9qUHtR-cqpmTbPXJCDxoC7jYQAvD_BwE) |
| 1x Resistor 0.25W 330ohm (330R) | <img src="https://hackmd.io/_uploads/SyrxWLqBlx.png" width="120"/> | 330 ohm resistor | 2 SEK | [Electro:kit](https://www.electrokit.com/motstand-1w-5330ohm-330r) |
| 1x Resistor 0.25W 10kohm (10KR) | <img src="https://hackmd.io/_uploads/ByQgZLcSge.png" width="120"/> | 10 Kilo ohm resistor | 2 SEK | [Electro:kit](https://www.electrokit.com/motstand-kolfilm-0.25w-10kohm-10k) |
| 1x Pot 10kohm lin (B10K) | <img src="https://hackmd.io/_uploads/rJmDGUcBlx.jpg" width="120"/> | 10K potentiometer to adjust the resistance | 9.90 SEK | [Electro:kit](https://www.electrokit.com/pot-10kohm-lin-pcb-b10k) |
| 1 pack of wires | <img src="https://hackmd.io/_uploads/rJ9vGU9Sll.jpg" width="120"/> | Flat cable with mounted Dupont connectors. | 55 SEK | [Electro:kit](https://www.electrokit.com/labbsladd-40-pin-30cm-hane/hane) |
**Total Cost: 289.2 SEK**
**Note**: Most of the components used in this project were already in my possession.
## Computer Setup
- **Thonny**: In this project Thonny IDE (Windows version) was used which works perfectly with pico device.
- **Steps to Set Up the PC**
1. **Step 1**: Download **Thonny** based on your OS from the links in below & install it:Download
- **[Windows](https://github.com/thonny/thonny/releases/download/v4.1.7/thonny-4.1.7.exe)**
- **[Mac](https://github.com/thonny/thonny/releases/download/v4.1.7/thonny-4.1.7.pkg)**
- **[Linux](https://thonny.org/)**
2. **Step 2:** When you open & run the program, from topbar menu, click on `View >> Files`
to open the file manager panel.
3. **Step 3:** Again from topbar menu open interpreter selection from `Run >> Configuration interpreter...`
4. **Step 4:** Connect your RP pico device with USB cable while you are holding the **BOOTSEL** button & then you can release it after few seconds.
5. **Step 5:** From the window, go to **Interpreter** and choose your interpreter for using from dropdown list & choose the port of your pico.
6. **Step 6:** Before hitting OK, there is an option to install or update Micropython for your device **Install or update MicroPython**, By clicking that you can choose your RP pico model and the latest version & hit ok to update your RP pico firmware.
7. **Step 7:** After you are done with connection, you should see something similar to this in your Thonny terminal:
**MicroPython v1.20.0 on 2025-06-26; Raspberry Pi Pico W with RP2040
Type "help()" for more information.
`>>>`**
8. **Step 8:** Write down the code (avaible in code section)and after saving them as .py file, right click on files in Thonny & upload them to pico.
**Conragtulations! You are done with your setup & ready to test the project!**
## Putting Everything Together
**Circuit Diagram**

**Warning!!
Before connecting the components, please be sure that the pico is disconnected from power source so in case of short circuiting on board, it won't damage your components or RP Pico!!!**
-**Step 1:** Connect the pico to the breadboard by pressing it carefully down so the pins will be locked inside.
-**Step 2:** Connect one pin of first button to **GPIO17** & other pin to **GND**.
-**Step 3:** Connect one pin of second button to **GPIO16** & other pin to **GND**.
-**Step 4:** Connect one leg of photoresistor to **3V3(OUT)** & other leg to **GPIO28** & to one leg of **10K resistor** & from other leg of resistor to **GND**.
-**Step 5**: Connect one **330 ohm resistor** to **GPIO 0** & other leg should be connected to **Positive(+) leg of the LED** & from **Negative(-)** leg to **GND**.
-**Step 6:** Connect the left leg of potenriometer to **3V3(OUT)**, middle leg to **GPIO27** & the right leg to **GND**.
**Note:** To avoid messy wiring & mistakes, I used only one **GND** pin from pico & in the figure above I used **blue** cable for **GND**, **red** cable for **3V3(OUT)** & **green** cable for **GPI/O** and as long as the connections are right, you can change the design of wiring.
**Electrical Calculations**
Here is the table of all components used in this project with their voltage & current usage:
| Component | Voltage | Estimated Current |
| ---------------------------------- | ---------------------------------- | ----------------------------------- |
| **Raspberry Pi Pico WH** | 5V USB in, 3.3V logic | \~100 mA (idle to light usage) |
| **LED (5mm red diffuse)** | \~2.0V (forward drop) | \~10 mA (limited by 330 Ω resistor) |
| **Push buttons (x2)** | GPIO input (3.3V, pulldown to GND) | \~0 mA (negligible) |
| **Photoresistor (CdS)** | Analog input divider (3.3V) | Few µA to <1 mA |
| **Potentiometer 10 kΩ** | Analog input divider (3.3V) | \~0.33 mA max |
| **Resistors (passive components)** | N/A | N/A |
| **Breadboard** | Passive | N/A |
**Total Power Budget Estimation**
Based on my power suply I use 5V 1.0A and Pico's 3.3V regulator is powering components.
- **Raspberry Pi Pico WH**
Current draw: ~100-200 mA (Wi-Fi idle, some GPIO activity)
Voltage: USB 5V input, regulated down to 3.3V for IO
- **LED + 330Ω Resistor**
Voltage drop across LED: ~2.0V
Resistor drop: 3.3V – 2.0V = 1.3V
Current:
I=1.3V330 Ω≈3.9mA
I=330Ω1.3V≈3.9mA
- **Photoresistor with 10kΩ Pull-down**
Assume a voltage divider between:
Photoresistor (variable: 4–7 kΩ) and10kΩ resistor
**Max current:**
Imax=3.3V4 kΩ+10 kΩ≈0.24mA
Imax=4kΩ+10kΩ3.3V≈0.24mA
- **Potentiometer (10 kΩ between 3.3V and GND)**
Acts as a voltage divider:
I=3.3V10 kΩ=0.33mA
I=10kΩ3.3V=0.33mA
- **Push buttons (connected between GPIO and GND)**
Only conduct when pressed. Even then, current is negligible (just pulling down GPIO pin).
**Total Maximum Current Draw**
In Worst case the total current draw can be around 205 mA(105 mA in above calculation) which is safe for my case that I'm using 5V 1.0 Amp power supply. So it is still has room for adding more components in future.
## Platform
For this project I used Adafruit platform(free version) and I used cloud based server version of it which was enough for my project requirements.
**Why Adafruit?**
Adafruit provides easy UI to work with & configure the dashboard easily. It gives option to the user to create feeds, control & monitor IoT device vis dashboard or even create some actions like sending notifications but of course it has some limitation like low data rate sending (30 messages in a minute) so if the project is transmitting more than 30 data messages to Adafruit, it can not be a real time device & it will have few seconds delay to take action.
In that case I would prefer to use **TIG-stack** as a self hosted solution so I can have more flexiblity but based on my short time, I decided to stay with Adafruit.
## Code
**Project Folder structure**
<pre>
├── keys.py
├── main.py
├── mqtt.py
├── wifiConnection.py </pre>
**GitHub link for whole source code:**
https://github.com/mn224pn/Light-Sensor-project-For-Home-Studio-Using-Raspberry-Pi-Pico-WH.git
The codes are divided to four python files:
- keys.py: contains Adafruit IO (AIO) configuration & wifi configuration.
- main.py: has all core functions & the main loop.
In below, there is one of the functions about updating the LED and potentiometer status, how Auto mode should work(the LED will be turn on below 20000 based on my experience):
```python
def update_led():
"""Update LED state/brightness immediately based on mode and inputs"""
global last_pot_value, use_remote_brightness, remote_brightness
local_brightness = pot.read_u16()
# Check if pot value changed significantly
pot_changed = False
if last_pot_value is None or abs(local_brightness - last_pot_value) > POT_TOLERANCE:
pot_changed = True
last_pot_value = local_brightness
if pot_changed:
# Pot moved - switch control to physical pot
use_remote_brightness = False
remote_brightness = local_brightness # Sync remote_brightness internally for LED
brightness = remote_brightness if use_remote_brightness else local_brightness
if auto_mode:
ldr_val = ldr.read_u16()
if ldr_val < 20000:
set_led_brightness(brightness)
else:
set_led_brightness(0)
else:
if manual_led_state:
set_led_brightness(brightness)
else:
set_led_brightness(0)</pre>
```
In below code there is a function to use onboard LED for the user to know the current status:
```python
def update_onboard_led():
"""Turn ON internal Pico LED if auto mode, OFF if manual"""
onboard_led.value(1 if auto_mode else 0)
```
- mqtt.py: is a library of mqtt that is used in main.py.
- wifiConnection.py: has functions to connect the pico to wifi which you can find it in below:
```python
import keys
import network
from time import sleep
def connect():
wlan = network.WLAN(network.STA_IF) # Put modem on Station mode
if not wlan.isconnected(): # Check if already connected
print('connecting to network...')
wlan.active(True) # Activate network interface
# set power mode to get WiFi power-saving off (if needed)
wlan.config(pm = 0xa11140)
wlan.connect(keys.WIFI_SSID, keys.WIFI_PASS) # Your WiFi Credential
print('Waiting for connection...', end='')
# Check if it is connected otherwise wait
while not wlan.isconnected() and wlan.status() >= 0:
print('.', end='')
sleep(1)
# Print the IP assigned by router
ip = wlan.ifconfig()[0]
print('\nConnected on {}'.format(ip))
return ip
def disconnect():
wlan = network.WLAN(network.STA_IF) # Put modem on Station mode
wlan.disconnect()
wlan = None
```
## Transmitting the Data / Connectivity
**Data Transmission Frequency**
- **Design Choice:**
The Pico transmits all data (LDR value, mode state, LED state, and potentiometer value) every 12 seconds.
- **Impact on Design Goals**
**Real-Time Limitation:**
While real-time data updates are ideal for responsiveness, the 12-second interval strikes a compromise between performance and Adafruit IO’s free tier rate limits.
**Device Control Flexibility:**
By spacing out telemetry updates, you preserved bandwidth for remote control commands, which enhances the system’s responsiveness to user inputs despite reduced data frequency.
- **Impact on System Metrics**
**Battery Consumption:**
Less frequent data transmission helps conserve power, which is especially important if the device is battery-powered. Transmitting every 12 seconds versus continuously significantly reduces Wi-Fi radio activity, a major power drain.
**Network Load:**
Reduces load on the MQTT(Adafruit IO), ensuring more reliable operation within platform limitations.
---
**Protocols Used**
**Wi-Fi (for network communication)**
**Design Choice:**
Chosen wifi for its ease of setup, availability in most environments, and better bandwidth compared to alternatives like Bluetooth or LoRa for this specific project.
- **Impact**
**Range:**
Wi-Fi offers a moderate range (around 10–30 meters indoors, depending on obstacles) which makes it sufficient for most home or lab settings.
**Battery Consumption:**
Wi-Fi is power-hungry compared to Bluetooth Low Energy (BLE) or LoRa. However, since transmissions are infrequent, the device can enter low-power modes between intervals to mitigate this.
**Security:**
Wi-Fi provides strong security features (WPA2/WPA3), but only if configured properly. For example, an insecure or open Wi-Fi network exposes the device to potential intrusions.
**MQTT (for data transmission)**
- **Design Choice:**
MQTT is lightweight, ideal for IoT due to its low bandwidth usage and support for publish/subscribe patterns.
- **Impact**
**Battery Consumption:**
MQTT is optimized for low-overhead communications, minimizing packet size and energy use.
**Scalability & Flexibility:**
It allows multiple clients to subscribe or publish which is great for expanding the system with more sensors or actuators.
**Security:**
MQTT itself lacks built-in encryption—security depends on the broker. Since I am using Adafruit IO, which supports TLS encryption, data-in-transit is protected. However, credentials must be managed securely to avoid breaches.
**Webhook (for notifications to Discord server)**
**Design Choice:**
Webhooks from Adafruit trigger external actions (e.g., sending notification messages to Discord server).
- **Impact**
**Battery & Resource Use:**
Since webhooks are triggered server-side, the device doesn't spend extra power to notify Discord, keeping consumption low.
**Security:**
Security depends on the Discord webhook URL privacy. If leaked, anyone can post to your Discord channel. Best practice includes regenerating URLs periodically and avoiding exposure in public repos and keep the discord server private.
## Presenting the Data
**Adafruit Dashboard**

This project uses adafruit dashboard for visualizaton of the data which send each 12 seconds from RP pico to adafruit platform. As it shown in above screen shots, there are two line charts of **Studio Light Level** which is about the measuring value of LDR from the area & **LED Brightness** which is the value of how bright is the LED based on last change of potentiometer. There is a LED Status there which you can see if the LED is ON(Green) or OFF(Black).
- **Automation/triggers of the data**
Also there are some control panel like changing the mode between Auto/Manual, Turn ON/OFF LED (works only in Manual mode) & it's possible to adjust the brightness level of LED with the slider. So the user can control the device remotely as long as he/she has access to adafruit dashboard.
In general all buttons & potentiometer(physical or virtual on dashboard) will do same thing & no matter which one is used, pico will update the current value of them so it won't have any interfier with eachother. Due to data limitation of Adafruit, the dashboard will recevie update from pico each 12 seconds.
- **Data saving**

In general it will be saved each 12 seconds that Adafruit receives new data & automatically will be kept on Adafruit cloud databse for month with option of downloading the data in JSON and CSV format.
In addtion to that there is a filter option to select a specific date & time period to get data.
**Why this database?**
Based on my short time to implement everything for this project, I decided to go with adafruit which has cloud-based database server & did not need to configure the database at all but other than that I prefer to migrate to self-hosted solutions like TIG-stack or Mosquitto & Node-Red to have more control on my own data & be secured with not sharing data with third party company. Also I have to mention that I can have more flexiblity with my own database server with self-hosted solutions.
- **Notification**

In above screenshot, you can see the notifications that are sent to my discord server with using webhooks & making some actions from adafruit. So in case that the user is not home & doesn't have any access to adafruit dashboard, with any changes of LED state or mode state, notifications will be send to discord server.
It is posible also to create notification & send it via email or SMS.
## Finalizing the design

You can find the final result in the above photo which is a light sensor for home studio with options of having it in Auto/Manual mode & adjust the brightness of the LED. It can be controlled either by person or remotely via Adafruit dashboard with notification service.
I wanted to add another photoresistor & one dht11 sensor for plants or flowers but beacause of not having enough scenarios & not be able to fulfill the core functionality, I decided to remove it for now.
This device could be used in anywhere in the house or even outside(with a proper box based on the weather). The LED could be a light, decoration things or inside a bulb.
**Note:** The photoresistor(LDR) is from different manufacturer & the legs of it are extended with solder machine. Also at the end I added the internal LED of Pico to show the status of the mode (Auto mode = LED On, Manual Mode = LED Off).
The device is powered by a power bank (5V, 1.0A) for now but it could be powered by PC USB port or right powersupply.
## Short video demonstrating the light sensor
You can find the video by clicking the link below:
[Youtube link](https://www.youtube.com/watch?v=4WcBCZnwk5w)
## Final thoughts
- The project has the core functionality but I want to extend it with a small LCD to monitor the values, add one relay to control other things with higher power like a fan.
- To be able to have the product look better & easy to move, creating box or some holder for buttons & sensor by using 3d printing will be the next steps. At the end my wish is to make it more complete & be close to a smart home automation device.
- Visualization could look better & have faster data transfer by using self hosted solutions like TIG-stack which I will probably will migrate to this platform in future.
- The notification system could be improved as well to have more flexibility to send data anywhere user wants.
##