3.1.4 Smart Fan

Introduction

In this project, we will use motors, buttons and thermistors to make a manual + automatic smart fan whose wind speed is adjustable.

Required Components

In this project, we need the following components.

../_images/4.1.10_smart_fan_list.png

Schematic Diagram

T-Board Name

physical

wiringPi

BCM

GPIO17

Pin 11

0

17

GPIO18

Pin 12

1

18

GPIO27

Pin 13

2

27

GPIO22

Pin 15

3

22

GPIO5

Pin 29

21

5

GPIO6

Pin 31

22

6

GPIO13

Pin 33

23

13

../_images/4.1.10_smart_fan_schematic.png

Experimental Procedures

Step 1: Build the circuit.

../_images/4.1.10_smart_fan_circuit.png

Note

The power module can apply a 9V battery with the 9V Battery Buckle in the kit. Insert the jumper cap of the power module into the 5V bus strips of the breadboard.

../_images/4.1.10_smart_fan_battery.jpeg

Step 2: Get into the folder of the code.

cd ~/raphael-kit/python-pi5

Step 3: Run.

sudo python3 3.1.4_SmartFan_zero.py

As the code runs, start the fan by pressing the button. Every time you press, 1 speed grade is adjusted up or down. There are 5 kinds of speed grades: 0~4. When set to the 4th speed grade and you press the button, the fan stops working with a 0 wind speed.

Once the temperature goes up or down for more than 2℃, the speed automatically gets 1-grade faster or slower.

Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like raphael-kit/python-pi5. After modifying the code, you can run it directly to see the effect.

#!/usr/bin/env python3

from gpiozero import Motor, Button
from time import sleep
import ADC0834
import math

# Initialize GPIO pins for the button and motor control
BtnPin = Button(22)
motor = Motor(forward=5, backward=6, enable=13)

# Initialize the ADC0834 module for temperature sensing
ADC0834.setup()

# Initialize variables to track the motor speed level and temperatures
level = 0
currentTemp = 0
markTemp = 0

def temperature():
    """
    Reads and calculates the current temperature from the sensor.
    Returns:
        float: The current temperature in Celsius.
    """
    # Read analog value from the ADC0834 module
    analogVal = ADC0834.getResult()
    # Convert analog value to voltage and then to resistance
    Vr = 5 * float(analogVal) / 255
    Rt = 10000 * Vr / (5 - Vr)
    # Calculate temperature in Celsius
    temp = 1 / (((math.log(Rt / 10000)) / 3950) + (1 / (273.15 + 25)))
    Cel = temp - 273.15
    return Cel

def motor_run(level):
    """
    Adjusts the motor speed based on the specified level.
    Args:
        level (int): Desired motor speed level.
    Returns:
        int: Adjusted motor speed level.
    """
    # Stop the motor if the level is 0
    if level == 0:
        motor.stop()
        return 0
    # Cap the level at 4 for maximum speed
    if level >= 4:
        level = 4
    # Set the motor speed
    motor.forward(speed=float(level / 4))
    return level

def changeLevel():
    """
    Changes the motor speed level when the button is pressed and updates the reference temperature.
    """
    global level, currentTemp, markTemp
    print("Button pressed")
    # Cycle through levels 0-4
    level = (level + 1) % 5
    # Update the reference temperature
    markTemp = currentTemp

# Bind the button press event to changeLevel function
BtnPin.when_pressed = changeLevel

def main():
    """
    Main function to continuously monitor and respond to temperature changes.
    """
    global level, currentTemp, markTemp
    # Set initial reference temperature
    markTemp = temperature()
    while True:
        # Continuously read current temperature
        currentTemp = temperature()
        # Adjust motor level based on temperature difference
        if level != 0:
            if currentTemp - markTemp <= -2:
                level -= 1
                markTemp = currentTemp
            elif currentTemp - markTemp >= 2:
                if level < 4:
                    level += 1
                markTemp = currentTemp
        # Run the motor at the adjusted level
        level = motor_run(level)

# Run the main function and handle KeyboardInterrupt
try:
    main()
except KeyboardInterrupt:
    # Stop the motor when the script is interrupted
    motor.stop()

Code Explanation

  1. Imports classes for managing a motor and a button, and the sleep function for introducing pauses. Additionally, it imports the ADC0834 library for temperature sensing and the math library for mathematical calculations.

    #!/usr/bin/env python3
    
    from gpiozero import Motor, Button
    from time import sleep
    import ADC0834
    import math
    
  2. Sets up the button on GPIO pin 22 and configures the motor with specific GPIO pins for control. Initializes the ADC0834 module for temperature measurement. Also, initializes variables to monitor the motor speed level and temperatures.

    # Initialize GPIO pins for the button and motor control
    BtnPin = Button(22)
    motor = Motor(forward=5, backward=6, enable=13)
    
    # Initialize the ADC0834 module for temperature sensing
    ADC0834.setup()
    
    # Initialize variables to track the motor speed level and temperatures
    level = 0
    currentTemp = 0
    markTemp = 0
    
  3. Defines a function to read and calculate the temperature from the sensor, converting the readout to Celsius.

    def temperature():
        """
        Reads and calculates the current temperature from the sensor.
        Returns:
            float: The current temperature in Celsius.
        """
        # Read analog value from the ADC0834 module
        analogVal = ADC0834.getResult()
        # Convert analog value to voltage and then to resistance
        Vr = 5 * float(analogVal) / 255
        Rt = 10000 * Vr / (5 - Vr)
        # Calculate temperature in Celsius
        temp = 1 / (((math.log(Rt / 10000)) / 3950) + (1 / (273.15 + 25)))
        Cel = temp - 273.15
        return Cel
    
  4. Introduces a function to adjust the motor speed according to the specified level.

    def motor_run(level):
        """
        Adjusts the motor speed based on the specified level.
        Args:
            level (int): Desired motor speed level.
        Returns:
            int: Adjusted motor speed level.
        """
        # Stop the motor if the level is 0
        if level == 0:
            motor.stop()
            return 0
        # Cap the level at 4 for maximum speed
        if level >= 4:
            level = 4
        # Set the motor speed
        motor.forward(speed=float(level / 4))
        return level
    
  5. Implements a function to change the motor speed level manually using a button, and binds this function to the button’s press event.

    def changeLevel():
        """
        Changes the motor speed level when the button is pressed and updates the reference temperature.
        """
        global level, currentTemp, markTemp
        print("Button pressed")
        # Cycle through levels 0-4
        level = (level + 1) % 5
        # Update the reference temperature
        markTemp = currentTemp
    
    # Bind the button press event to changeLevel function
    BtnPin.when_pressed = changeLevel
    
  6. The main function, designed to continually adjust the motor speed in response to temperature fluctuations, remains to be implemented.

    def main():
        """
        Main function to continuously monitor and respond to temperature changes.
        """
        global level, currentTemp, markTemp
        # Set initial reference temperature
        markTemp = temperature()
        while True:
            # Continuously read current temperature
            currentTemp = temperature()
            # Adjust motor level based on temperature difference
            if level != 0:
                if currentTemp - markTemp <= -2:
                    level -= 1
                    markTemp = currentTemp
                elif currentTemp - markTemp >= 2:
                    if level < 4:
                        level += 1
                    markTemp = currentTemp
            # Run the motor at the adjusted level
            level = motor_run(level)
    
  7. Runs the main function and ensures the motor stops if the script is interrupted.

    # Run the main function and handle KeyboardInterrupt
    try:
        main()
    except KeyboardInterrupt:
        # Stop the motor when the script is interrupted
        motor.stop()