---
# System prepended metadata

title: Smart Light Control System
tags: [smart light control, IoT, raspberry pi, 1dt305, pico w]

---

###### Author: `Hélder Monteiro` `(hm222jy)`


# Smart Light Control System


This tutorial will guide you through the process of creating a Simple Light Control System. This system monitors the ambient light and activates an LED when the light level is too low and deactivates it when the light level is high. It gathers information about light resistance from a sensor and the status of the LED, all of which are tracked and displayed on a dashboard. In this step-by-step guide, you will learn how to:

* use photoresistor sensors to measure light intensity;
* control a color-changing LED, toggling it ON and OFF based on the photoresistor's readings;
* visualize the collected data using Adafruit IO.
* use MQTT protocol to transmit sensor data over the internet.


**Estimated time to build:** 3-4 hours from start to completion. 


## Objective



The idea of building a smart light control system sprang from curiosity about how street lights are controlled. I always assumed it was based on some central sensors that measure outdoor light intensity and then switch the lights on and off. It wouldn't be someone manually doing it, or perhaps the timing could be automatically configured so that the lights turn on/off at specific times. Regardless, my idea was for the system to determine when the lights should be on or off and to control them accordingly, while also logging information for potential anomaly detection within the system.

The purpose of the tutorial is to introduce a smart system for controlling lights, either indoors in our homes or outdoors based on the light intensity in the area of interest. The photoresistor would measure the light intensity and report the resistance values, which can then be used to control the lights.

This tutorial will provide insights into the times at which lights are turned on or off, whether it's less during the summer period and more during the winter periods (dark days), as well as the energy efficiency of using this method to cut electricity consumption. We can set the thresholds at which lights should be turned on/off. The data would provide valuable input on the effectiveness of the system and explore different ways to also override the system, say for example, if the light is off when it should be on. That override could potentially be added, given that the MQTT not only allows for sending data but also for receiving it. Thus, controlling the IoT device should be possible.



## Bill of Materials

The list of materials for this tutorial are specified below:


| item                                                                                                           | Description                                                                                                                                | Price (SEK) |
| ------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| [Raspberry Pi Pico WH](https://www.electrokit.com/en/product/raspberry-pi-pico-wh/) | Raspberry Pi Pico wireless (WiFi) version | 109.00     |
| [Breadboard (small)](https://www.electrokit.com/produkt/kopplingsdack-400-anslutningar/)|    Small breadboard to make the connections|49.00  
| [Lab cables (m/m)](https://www.electrokit.com/produkt/labbsladd-20-pin-15cm-hona-hane/)|    Lab cable 40-pin 30cm male/male|49.00  
| [Lab cables (f/m)](https://www.electrokit.com/produkt/labbsladd-20-pin-15cm-hona-hane/)|    Lab cable 20-pin 15cm female/male|29.00  
| [Light sensor](https://www.electrokit.com/produkt/ljussensor/)|    Module with a photosensitive resistor to measure light intensity|39.00  
| [Color changing LED](https://www.electrokit.com/produkt/led-modul-fargskiftande/)|    Module with a color changing LED that will be controlloed by the light sensor|15.00  


::: info
Each datasheet is available in the hyperlink of each item on the table, besides their price and other technical information.
:::



## Computer Setup

### Thonny as IDE

To install Thonny IDE on Windows, macOS, or Linux, follow these steps:

* Open a web browser and go to thonny.org.
* Locate the download links for your operating system.
* Download  and install Thonny.

:::success
:thumbsup: Now ready for the next step: **Preparing the Pico W!**
:::

### Preparing the Pico W

* Download the latest version of the firmware at https://rpf.io/pico-w-firmware
* Connect the micro USB cable to the Pico W
* Enable Pico W as external drive by:
    *  pressing **BOOTSEL** button as the USB cable is connected to the computer.
<p align="center">
  <img src="https://hackmd.io/_uploads/S1t4lP7K3.png">
  <br>
  <span style="text-align: center; display: block;">
    (Image: Raspberry Pi Foundation)
  </span>
</p>

* Drag and drop the downloaded firmware into the Pico W.
* The device will restart automatically.

  
:::success
:thumbsup: Now the Pico W is ready to be used in Thonny.
:::

### Upload and run code

The first step to take is to select the right device from Thonny IDE. At the bottom right corner of Thonny, we select `MicroPython (Raspberry Pi Pico)`.

<p align="center">
  <img src="https://hackmd.io/_uploads/r173MD7Y3.png">
</p>

Then, we can start a new window and save the code to `Raspberry Pi Pico` as shown below:

![](https://hackmd.io/_uploads/HkPUmPXF3.png)

This will allow the code to be uploaded and ran directly from the Pico W. We can also test the REPL by typing on the shell:

```>>> print("Hello from Pico W!")```


## Putting everything together


> **Disconnect device from the computer before proceeding with the next steps**


The schematics below show how the connections are made in the breadboard. 

![](https://hackmd.io/_uploads/HJEdLOmt3.png)



As per the schematics, the first line in the photo resistor is the *data* line which connects to ADC0 (GP26) Pin on the Pico W. The middle is the power line which conects to 3V3(OUT) and the right most line is ground which connects to GND. The Color Changing LED has 3 lines but the middle one is not connected (as per the datasheet), so the first line connects to GP16 on the Pico W, and the last line connects to GND.

> Please note that both the sensor and the LED modules are coupled with the respective resistors, thus it is not necessary to connect one separately. However, the circuit is still in development and cannot be directly used in production. We would have to account for more requires to power and control large switches that control different light sources.



## Platform
### Adafruit IO
In this project, [Adafruit IO](https://io.adafruit.com/) is usedd. Adafruit provides an easy way to connect to the Pico W and transmit and receive data via MQTT protocol.
There are plenty of online tutorials on using and connecting to the Pico W and thus, it was a natural choice to select Adafruit. I also found that the free subscription was quite good to test the project and collect the data needed for showcase its functionality.

![](https://hackmd.io/_uploads/SyJ-tuQt3.jpg)

Above, we can see that the free plan of adafruit provides upto 2 devices and upto 10 feeds. It also allows for upto 5 separate dashboards and data rate of 30 per minute. The platform is quite intuitive to use.

## The Code

The code for the project is highlighted below:

```python=import network
import socket
from machine import ADC, Pin
from time import sleep
from umqtt.simple import MQTTClient

############### Configuration and Connections ##############

# WiFi network name(ssid) and password
wifi_ssid = "<wifi_ssd>"
wifi_password = "<wifi_password>"

# Adafruit IO Authentication and Feed
mqtt_host = "io.adafruit.com"
mqtt_username = "<adafruit_username>"
mqtt_password = "<adafruit_api_key>"
mqtt_publish_topic = "<adafruit_username>/feeds/light-photoresistor"
mqtt_led_publish_topic = "<adafruit_username>/feeds/led-feed"
mqtt_led_log_publish_topic = "<adafruit_username>/feeds/led-log"

# random ID for the MQTT client
mqtt_client_id = "hm_vt23_iot_lnu_project123"

# Function to connect to WiFi
def connect():
    #Connect to WLAN
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    wlan.connect(wifi_ssid, wifi_password)
    while wlan.isconnected() == False:
        print('Waiting for connection...')
        sleep(1)
    print("Connected to WiFi.")
    print(wlan.ifconfig())
    ip = wlan.ifconfig()[0]
    return ip

# Initialize MQTTClient and connect to the MQTT server
mqtt_client = MQTTClient(
        client_id=mqtt_client_id,
        server=mqtt_host,
        user=mqtt_username,
        password=mqtt_password)

# connect to WiFi and MQTT
_ = connect()
mqtt_client.connect()

############### Sensor Data Gathering and Publishing ##############

# One of the ADC pin of Pico W to connect the photo resistor
photoPIN = 26

# The LED will be connected to pin 16
led = Pin(16, Pin.OUT)
led.off()  # Turn off the LED initially

def readLight(photoGP):
    photoRes = ADC(Pin(26))
    light = photoRes.read_u16()  # 16 bits which means 2 bytes. The range of 2 bytes is from 0 to 65535.
    # light = round(light/65535*100,2)  # show the result in percentage
    return light

# read sensor data and publish every 3 seconds
try:
    while True:
        light = readLight(photoPIN)
        print("Light resistance: " + str(light))
        
        # publish the light resistance to the topic
        mqtt_client.publish(mqtt_publish_topic, str(light))
        
        # here it turns on/off the LED depending on the resistor value
        if light >= 1000 or light == 0: # high resistance i.e. time to turn on the LEDs
            # publish the LED status to the topic
            mqtt_client.publish(mqtt_led_publish_topic, str(light))
            mqtt_client.publish(mqtt_led_log_publish_topic, "Light Turned ON")
            # turn on the LED connected to the pico W
            led.on()
        else:
            # publish the LED status to the topic
            mqtt_client.publish(mqtt_led_publish_topic, str(light))
            mqtt_client.publish(mqtt_led_log_publish_topic, "Light Turned OFF")
            # turn off the LED connected to the pico W            
            led.off()
        
        # set a delay between readings
        sleep(5)

except KeyboardInterrupt:
    led.off()  # Turn off the LED before exiting

```


## Transmitting the data / Connectivity

* The data is transmitted every 5 seconds. Adafruit limits the transmission to 3 seconds at a time on the free account. But decision was made to have it send every 5 seconds as it captures enough context to understand the light resistance values over time. 
* WiFi is used as wireless protocols to take advantage of the on-board WiFi module and the ease of connectivity for most home networks.
* For transport protocols, MQTT is used as it intuitive and seamlessly supported by Adafruit IO.
* One limitation with the WiFi protocol is the range and the fact that Pico W can only connect to 2.4 Ghz frequency. Also, running the python script with WiFi password in it presents a security risk if such device is accessed by threat actors. As for MQTT for data transport, I did not notice any delays in the transmission. But could not test running the Pico W on battery as such module was not available.


## Presenting the data

There are 3 blocks in the DashBoard:
* The Line Chart with Light Intensity
* The LED Indicator
* LED Log Stream

The screenshot below shows when the LED is triggered to ON i.e. when light intensity is low as measured by high resistance greater than or equal to 1000 (or equal to 0 i.e. suddenly becomes dark when hands cover the sensor.)

![](https://hackmd.io/_uploads/HJiDauXY3.jpg)

And below we can see when the LED turns OFF, when light resistence is below 1000 but not equal to 0:

![](https://hackmd.io/_uploads/HJAFT_7Fh.jpg)


The database to store the data is within Adafruit itself. The choice was driven by the practicality of the project and the duration of the same. As proof-of-concept, it worked perfectly to run the project within Adafruit and have the data stored there for 30 days for free.

Currently, the data is automatically pushed when the raspberry pi pico is connected to the computer and the script manually started, then the code executes indefinetely. However, due to rate per minute limitations on free accounts, Adafruit IO temporarily stalls data transfers when the rates are exceed, but proceeds immediately after a short pause (usually 4 seconds).



## Conclusion

Below are some selected pictures of the assembled components.


![](https://hackmd.io/_uploads/BkCxZtXt2.jpg)

![](https://hackmd.io/_uploads/HkkWZtmK2.jpg)

![](https://hackmd.io/_uploads/BygWbYmF3.jpg)

Below shows the LED light on with 3 different color patterns

![](https://hackmd.io/_uploads/BkrEQKmt2.jpg)





### Reflections

In general the project went well for me. There were some confusions in beginning on meeting the requirements, for instance whether LoRa was a must or not. But these were cleared during the workshops. Also, I find it easier to work with Adafruit although I did not test other similar systems due to time constraints. But the seamless integration with Pico W was what wowed me to use the platform. 

In the future, I might explore controlling the Pico W directly from Adafruit IO Dashbord to further make use of the MQTT data transmission not only for sending but also for receiving data.
