День #6 Адвент-календаря мейкера: В поисках света!
Добро пожаловать в шестой день вашего адвент-календаря «12 проектов Кодмаса». Сегодня мы будем использовать датчик света, который — как вы уже догадались — может определять количество света вокруг него и предоставлять нам значение показания, которое мы можем использовать в нашем коде.
Датчик света, который мы используем — ещё один аналоговый компонент, а это значит, что он способен выдавать широкий диапазон значений, обеспечивая по-настоящему детальные показания освещённости для наших проектов.
Поехали!
Содержимое коробки #6
В этой коробке вы найдёте:
1x Фототранзистор
1x Резистор 10 кОм
3x Провода типа «папа — папа»
Сегодняшний проект
Сегодня мы научимся считывать аналоговые показания с датчика света и преобразовывать их во что-то более полезное, а также освоим несколько новых приёмов для работы с данными и строками. Кроме того, мы создадим проект световой индикации с помощью светодиодов.
Датчики, похожие на этот, используются повсюду в окружающем нас мире — в уличных фонарях, транспортных средствах, системах освещения помещений и не только. Они определяют количество света, и это определяет величину электрического тока, который проходит через их ножки (и соответственно поступает в наш Pico в качестве входного сигнала).
Отличный компонент для изучения и применения во многих проектах!
Собираем схему
Мы снова будем использовать светодиоды и зуммер, поэтому оставьте их на месте и уберите всё остальное. Для начала ваша схема должна выглядеть вот так:
Прежде чем приступить к сегодняшней схеме, необходимо подчеркнуть, что вам нужно очень внимательно следить за ножками датчика света — если вы неправильно подключите провода, ваши показания света будут довольно бессмысленными!
Имея это в виду, возьмите мини-макетную плату и установите датчик так, чтобы длинная ножка находилась слева. Это должно выглядеть вот так:
Теперь нам нужно добавить три провода и резистор:
Подключите правую (короткую) ножку к пину 3,3 В (_физический пин 36_)
Подключите левую (длинную) ножку к GPIO 26 (_физический пин 31_)
Добавьте резистор, соединив левую ножку с другой свободной дорожкой на макетной плате
Подключите второй конец резистора к пину GND на вашем Pico (мы используем синюю дорожку, так как она уже подключена к GND для наших светодиодов)
Ваша схема должна выглядеть вот так:
Задание 1: Простое считывание освещённости
Начнём с простой стартовой программы, которая получает для нас показание освещённости.
Это минимальная программа для однократного получения аналогового значения — не очень полезная для человека в таком виде, но в следующем задании мы преобразуем его во что-то более практичное.
Код
В этом примере мы:
Импортируем ADC для использования функции ADC
Настраиваем пин GPIO датчика как пин ADC
Создаём переменную под названием „light“, которая считывает значение датчика
Выводим значение переменной (показание датчика)
Скопируйте код ниже в Thonny и попробуйте:
# Imports
from machine import ADC, Pin
# Define pin for our sensor
lightsensor = ADC(Pin(26))
# Read sensor value and store it in a variable called 'light'
light = lightsensor.read_u16()
# print the value
print(light)
Задание 2: Делаем показания освещённости удобными
Мы знаем, что можем получить одиночное показание от датчика с помощью очень короткой программы, но нам действительно нужно, чтобы это показание было в формате, который мы можем использовать и понимать.
В примере ниже мы преобразуем показание в проценты с помощью несложной математики. Это пригодится нам в одной из следующих коробок, когда мы… _ой, чуть не проговорились о спойлере!_
Рассмотрим несколько примеров, так как есть другие приёмы, которые мы можем использовать, чтобы сделать выводимые значения ещё более удобными…
Пример 1:
Этот пример берёт показание и превращает его в процент.
Он делит наше показание на 65535 (максимум диапазона аналогового считывания), затем умножает на 100, чтобы получить наше процентное значение:
# Imports
from machine import ADC, Pin
from time import sleep
# Define pin for our sensor
lightsensor = ADC(Pin(26))
# Read sensor value and store it in a variable called 'light'
light = lightsensor.read_u16()
# Turn our reading into a percentage of the analogue range
lightpercent = light/65535*100
print(lightpercent)
Пример 2:
Этот пример развивает предыдущий, ограничивая количество знаков после запятой, так как нам не нужна такая точность для чего-то вроде показания освещённости.
Для этого мы используем встроенную функцию round в нашем вычислении процента. Вы увидите её ниже, где мы используем round(light/65535*100,1).
Она берёт показание освещённости, применяет то же процентное вычисление, и последнее число (1) определяет, сколько знаков после запятой использовать.
Попробуйте пример ниже, затем попробуйте изменить это последнее число на 2 или 3, чтобы увидеть что произойдёт (а затем попробуйте убрать запятую и число совсем — это уберёт десятичную часть):
# Imports
from machine import ADC, Pin
from time import sleep
# Define pin for our sensor
lightsensor = ADC(Pin(26))
# Read sensor value and store it in a variable called 'light'
light = lightsensor.read_u16()
# Use the round function to limit the decimal places to 1
lightpercent = round(light/65535*100,1)
print(lightpercent)
Пример 3:
Наш последний пример добавляет символ % после показания. Мы делаем это, добавив некоторые части к нашей строке вывода.
Обычно, когда мы выводим показание, значение является числом (в нашем примере это float если быть точным, так как оно содержит десятичную часть). Однако если мы хотим вывести это значение вместе с текстом одновременно (символ %), нам нужно преобразовать всё в строку (текст). Функция print не позволяет нам смешивать и то, и другое!
Мы можем сделать это с помощью встроенной функции str, которая преобразует значения в строки.
Мы используем str(lightpercent) для преобразования нашего показания освещённости в строку, затем добавляем к ней ещё одну строку с помощью +»%». Вы можете видеть это в примере ниже — попробуйте:
# Imports
from machine import ADC, Pin
from time import sleep
# Define pin for our sensor
lightsensor = ADC(Pin(26))
# Read sensor value and store it in a variable called 'light'
light = lightsensor.read_u16()
# Use the round function to limit the decimal places to 1
lightpercent = round(light/65535*100,1)
# Print our reading and the % symbol
# Convert the reading to a string first using str
print(str(lightpercent) +"%")
Задание 3: Световые индикаторы на светодиодах
Мы разобрались с получением показаний и преобразованием значений, так что давайте применим это в небольшом проекте световой индикации с нашими светодиодами.
Мы запустим пример, где будем постоянно проверять показания освещённости и назначим нашим трём светодиодам диапазоны показаний — красный будет указывать на низкий уровень освещённости, оранжевый — на нормальный, зелёный — на высокий уровень освещённости.
Код
В примере ниже мы снова добавляем наши светодиоды в код и определяем номера пинов. Мы также определяем пин датчика света перед запуском цикла while.
Цикл while считывает показание с датчика и преобразует его в процент, как мы делали ранее, затем использует операторы if для включения разного светодиода в зависимости от процентного показания (аналогично тому, что мы делали в день #4).
Скопируйте это в Thonny, запустите код, затем используйте фонарик камеры вашего телефона, фонарь или просто выключите свет, чтобы увидеть изменения в программе.
После завершения, почему бы не добавить код зуммера из вчерашней коробки обратно, чтобы получать оповещение, когда освещённость опускается ниже 30%?
# Imports
from machine import ADC, Pin
import time
# Set up the LED pins
red = Pin(18, Pin.OUT)
amber = Pin(19, Pin.OUT)
green = Pin(20, Pin.OUT)
# Define pin for our sensor
lightsensor = ADC(Pin(26))
while True: # Run forever
# Read sensor value and store it in a variable called 'light'
light = lightsensor.read_u16()
# Use the round function to limit the decimal places to 1
lightpercent = round(light/65535*100,1)
# Print our reading percentage with % symbol
print(str(lightpercent) +"%")
# 1 second delay between readings
time.sleep(1)
if lightpercent <= 30: # If percentage is less than or equal to 30
red.value(1) # Red LED on
amber.value(0)
green.value(0)
elif 30 < lightpercent < 60: # If percentage is between 30 and 60
red.value(0)
amber.value(1) # Amber LED on
green.value(0)
elif lightpercent >= 60: # If percentage is greater than or equal to 60
red.value(0)
amber.value(0)
green.value(1) # Green LED on
День #6 завершён!
Отличная работа, мейкеры! Сегодня мы научились использовать ещё один датчик, а также познакомились с новыми способами обработки значений и строк.
Мы ещё воспользуемся этим датчиком до конца календаря, так как он отлично сочетается с компонентом, спрятанным в одной из других коробок…
Итак, что мы узнали сегодня? Сегодня мы:
Узнали, как подключить схему с датчиком света
Узнали, как обрабатывать данные, чтобы сделать их более удобными для нас и наших программ
Узнали, как преобразовывать значения в строки с помощью функции str
Узнали, как использовать функцию round для ограничения знаков после запятой
Узнали, как объединять несколько строк при выводе
Как всегда, пожалуйста, оставьте схему как есть и дождитесь завтрашней коробки, прежде чем убирать какие-либо детали. Спокойной ночи!
Для создания схем на макетной плате использовался Fritzing.