Светодиоды

Световая доска для удаленного проведения лекций и презентаций (он-лайн)

Автор этой самоделки является преподавателем в университете. С началом пандемии многие учебные заведения перешли на он-лайн обучение. Для проведения лекций он использовал специальное программное обеспечение, например Explain Everything. Эта программа позволяет записывать примеры, отвечать на вопросы, но это не учебная доска аудитории, а картинка в картинке. И при таком способе страдает учебный процесс.
Отличным способом проводит он-лайн лекции, являются световые доски. При их использовании и текст лекции и преподаватель находятся в кадре, оперативно могут отвечать на заданные вопросы и сразу же писать примеры.
Проблема только в том, что такие доски довольно дороги и не всем доступны.
Мастер решил сделать такую доску самостоятельно. Прежде чем мы перейдем дальше, давайте посмотрим небольшое демонстрационное видео.

Итак,для изготовления такой световой доски понадобятся следующие
Инструменты и материалы:
-Лист оргстекла 1200 мм Х 2400 мм;
-Светодиодная лента WS2812B;
-Raspberry Pi Picos — 2 шт;
-1,14-дюймовый дисплей Waveshare для Pico — 2 шт;
-Источник питания для светодиодных лент;
-Паяльные принадлежности;
-Беспроводной петличный микрофон;
-Пиломатериалы;
-Крепеж;
-Дрель;
-Сверла;
-Ножовка;
Шаг первый: рамка
Рамку мастер делает из доски. Высота рамки должна быть немного выше головы пользователя. Размер рамки — по размеру оргстекла + пару сантиметров по периметру для светодиодной ленты + стойки. Между досками рамки будет крепиться оргстекло.

Шаг второй: крепление оргстекла
Для крепления оргстекла мастер сверлит по периметру рамки ряд сквозных отверстий. Затем помещает оргстекло между досками рамки и сверлит его.

В отверстия устанавливает болты и закручивает гайки.

Шаг третий: ножки
Для устойчивости конструкции мастер прибивает внизу стоек две доски.

Шаг четвертый: светодиодная лента
Наружный край оргстекла на пару сантиметров меньше размеров рамки. Т.е. между двумя досками рамки есть двухсантиметровый паз, а затем идет торец оргстекла.
Светодиодную ленту нужно разместить в паз, слева или справа, по всей длине, светодиодами вниз. Т.е. светодиодами к торцу оргстекла. Для освещения лектора нужно закрепить на верхней и нижней части рамки светодиодные ленты обращенные светодиодами наружу. Т.е. эти ленты крепятся не в паз, а прямо на доску. Перед креплением ленты нужно припаять к ее контактным площадкам провода. Слева на раме, мастер закрепил блок питания и подключил к нему провода питания светодиодных лент.

Шаг пятый: Рассбери
Для управления светодиодными лентам мастер использует два Рассбери и два дисплея с кнопками управления. В принципе, можно было обойтись и одним комплектом, но мастер хотел, чтобы для управления светодиодными лентами освещения лектора был свой комплект, а для освещения доски — другой.
Для питания дисплеев и Рассбери мастер использует USB-кабель. Распиновку Рассбери можно посмотреть здесь.
На вывод 39 (VSYS) подается 5 Вольт для питания Pico.
Контакт 1 (GPIO 0) будет использоваться для управления светодиодными лентами (линиями передачи данных). Контакт 3 (GND) — это контакт заземления.

Шаг шестой: программное обеспечение
Для управления светодиодными лентами мастер использовал довольно простой код MicroPython. Чтобы заставить Pico запускать код MicroPython, вам необходимо установить на него прошивку. Это довольно просто и описано здесь или ниже.
Удерживая кнопку BOOTSEL на Pico (см. Схему здесь)подключите его к своему компьютеру. Pico должен обозначится, как USB-накопитель.
Последний образ прошивки можно скачать здесь. Загрузите последнюю версию и перетащите файл uf2 на USB-накопитель Pico. Как только это будет сделано, Pico автоматически отключит USB-соединение.
Следующим шагом будет установка редактора Thonny. Thonny — интегрированная среда разработки для Python, и в ней есть встроенная библиотека для подключения к Pico. После установки программы нажимаем «Run» и «Select Interpreter». Выбираем MicroPython (Raspberry Pi Pico). Подключаемся к Pico. Дальше нужно будет написать код для управления светодиодами.
Мастер адаптировал код отсюда. Скачать отредактированный код можно ниже.

 Показать / Скрыть текст@asm_pio(sideset_init=PIO.OUT_LOW, out_shiftdir=PIO.SHIFT_LEFT,
autopull=True, pull_thresh=24)
def ws2812():
T1 = 2
T2 = 5
T3 = 3
label("bitloop")
out(x, 1) .side(0) [T3 — 1]
jmp(not_x, "do_zero") .side(1) [T1 — 1]
jmp("bitloop") .side(1) [T2 — 1]
label("do_zero")
nop() .side(0) [T2 — 1]

# Create the StateMachine with the ws2812 program, outputting on Pin(0).
sm = StateMachine(0, ws2812, freq=8000000, sideset_base=Pin(0))
# Start the StateMachine, it will wait for data on its FIFO.
sm.active(1)<br>
ЖК-дисплей имеет свой собственный код. Код можно скачать ниже.

 Показать / Скрыть текст## Code to control lightboard. Configure using the right number of LEDS is NUM_LEDS,
## and change the text for the LCD display below.
## Uses Pi Pico microcontroller
## https://www.raspberrypi.org/products/raspberry-pi-pico/
## Uses Waveshare 1.14 inch LCD display for Pico
## https://www.waveshare.com/pico-lcd-1.14.htm
## (there are different versions, the one used here is the one with 4 buttons,
## 2 to each side, you may have to change the code for different configurations)
## Waveshare wiki for display: https://www.waveshare.com/wiki/Pico-LCD-1.14
## has sample code which is adapted here.
## Other code for LED controls from
## https://core-electronics.com.au/tutorials/how-to-use-ws2812b-rgb-leds-with-raspberry-pi-pico.html
## Unless otherwise enoted in other code, this is licensed Creative Commons
## Attribution NonCommercial ShareAlike
## https://creativecommons.org/licenses/by-nc-sa/4.0/
##
## Version 0.1, pretty basic!
## Steve Marsh, 2021: stephen.marsh.2008@gmail.com

from machine import Pin,SPI,PWM
import framebuf
import array, time
import rp2
from rp2 import PIO, StateMachine, asm_pio

# Configure the number of WS2812 LEDs.
NUM_LEDS = 287 ## You need to change this for the number of LEDS in your own strip
# LED brightness from 0 to 1
brightness=1

@asm_pio(sideset_init=PIO.OUT_LOW, out_shiftdir=PIO.SHIFT_LEFT,
autopull=True, pull_thresh=24)
def ws2812():
T1 = 2
T2 = 5
T3 = 3
label("bitloop")
out(x, 1) .side(0) [T3 — 1]
jmp(not_x, "do_zero") .side(1) [T1 — 1]
jmp("bitloop") .side(1) [T2 — 1]
label("do_zero")
nop() .side(0) [T2 — 1]

# Create the StateMachine with the ws2812 program, outputting on Pin(0).
sm = StateMachine(0, ws2812, freq=8000000, sideset_base=Pin(0))
# Start the StateMachine, it will wait for data on its FIFO.
sm.active(1)

# Display a pattern on the LEDs via an array of LED RGB values.
pixel_array = array.array("I", [0 for _ in range(NUM_LEDS)])

############################################
# Functions for RGB Coloring
############################################

def updatePixel(brightness): # dimming colors and updating state machine (state_mach)
dimmer_array = array.array("I", [0 for _ in range(NUM_LEDS)])
for ii,cc in enumerate(pixel_array):
r = int(((cc >> 8) & 0xFF) * brightness)
g = int(((cc >> 16) & 0xFF) * brightness)
b = int((cc & 0xFF) * brightness)
dimmer_array[ii] = (g<<16) + (r<<8) + b
sm.put(dimmer_array, 8) # update the state machine with new colors

def set_led_color(color):
for ii in range(len(pixel_array)):
pixel_array[ii] = (color[1]<<16) + (color[0]<<8) + color[2]

#Color based on RGB (R,G,B)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
white = (255,255,255)

#########################################
# Class for the Waveshare display
#########################################
BL = 13
DC = 8
RST = 12
MOSI = 11
SCK = 10
CS = 9

LEDPIN=25

KEY_PRESSED=0

led_onboard = machine.Pin(LEDPIN, machine.Pin.OUT)

class LCD_1inch14(framebuf.FrameBuffer):
def __init__(self):
self.width = 240
self.height = 135

self.cs = Pin(CS,Pin.OUT)
self.rst = Pin(RST,Pin.OUT)

self.cs(1)
self.spi = SPI(1)
self.spi = SPI(1,1000_000)
self.spi = SPI(1,10000_000,polarity=0, phase=0,sck=Pin(SCK),mosi=Pin(MOSI),miso=None)
self.dc = Pin(DC,Pin.OUT)
self.dc(1)
self.buffer = bytearray(self.height * self.width * 2)
super().__init__(self.buffer, self.width, self.height, framebuf.RGB565)
self.init_display()

self.red = 0x07E0
self.green = 0x001f
self.blue = 0xf800
self.white = 0xffff

def write_cmd(self, cmd):
self.cs(1)
self.dc(0)
self.cs(0)
self.spi.write(bytearray([cmd]))
self.cs(1)

def write_data(self, buf):
self.cs(1)
self.dc(1)
self.cs(0)
self.spi.write(bytearray([buf]))
self.cs(1)

def init_display(self):
"""Initialize dispaly"""
self.rst(1)
self.rst(0)
self.rst(1)

self.write_cmd(0x36)
self.write_data(0x70)

self.write_cmd(0x3A)
self.write_data(0x05)

self.write_cmd(0xB2)
self.write_data(0x0C)
self.write_data(0x0C)
self.write_data(0x00)
self.write_data(0x33)
self.write_data(0x33)

self.write_cmd(0xB7)
self.write_data(0x35)

self.write_cmd(0xBB)
self.write_data(0x19)

self.write_cmd(0xC0)
self.write_data(0x2C)

self.write_cmd(0xC2)
self.write_data(0x01)

self.write_cmd(0xC3)
self.write_data(0x12)

self.write_cmd(0xC4)
self.write_data(0x20)

self.write_cmd(0xC6)
self.write_data(0x0F)

self.write_cmd(0xD0)
self.write_data(0xA4)
self.write_data(0xA1)

self.write_cmd(0xE0)
self.write_data(0xD0)
self.write_data(0x04)
self.write_data(0x0D)
self.write_data(0x11)
self.write_data(0x13)
self.write_data(0x2B)
self.write_data(0x3F)
self.write_data(0x54)
self.write_data(0x4C)
self.write_data(0x18)
self.write_data(0x0D)
self.write_data(0x0B)
self.write_data(0x1F)
self.write_data(0x23)

self.write_cmd(0xE1)
self.write_data(0xD0)
self.write_data(0x04)
self.write_data(0x0C)
self.write_data(0x11)
self.write_data(0x13)
self.write_data(0x2C)
self.write_data(0x3F)
self.write_data(0x44)
self.write_data(0x51)
self.write_data(0x2F)
self.write_data(0x1F)
self.write_data(0x1F)
self.write_data(0x20)
self.write_data(0x23)

self.write_cmd(0x21)

self.write_cmd(0x11)

self.write_cmd(0x29)

def show(self):
self.write_cmd(0x2A)
self.write_data(0x00)
self.write_data(0x28)
self.write_data(0x01)
self.write_data(0x17)

self.write_cmd(0x2B)
self.write_data(0x00)
self.write_data(0x35)
self.write_data(0x00)
self.write_data(0xBB)

self.write_cmd(0x2C)

self.cs(1)
self.dc(1)
self.cs(0)
self.spi.write(self.buffer)
self.cs(1)

def show_LED(value):
led_onboard.value(value)

def hide_LED():
led_onboard.value(0)

if __name__=='__main__':
pwm = PWM(Pin(BL))
pwm.freq(1000)
pwm.duty_u16(32768)#max 65535

led_val = 0
brightness = 1 ## As bright as it can be
set_led_color(white) ## The white LED is best for the lightboard
updatePixel(brightness) ## Turn on the LED strip for the lightboard

## Set up the LCD display
LCD = LCD_1inch14()
#color BRG
LCD.fill(LCD.white)

LCD.show()
## Simple user instructions.
## Each key does a separate thing — tun on or off, increase or decrease brightness
LCD.text("Lightboard!",25,40,LCD.red)
LCD.text("Key 0=Off Key 1=On",25,60,LCD.green)
LCD.text("Key 2=Dim Key3=Brighten",25,80,LCD.blue)

LCD.hline(10,10,220,LCD.blue)
LCD.hline(10,125,220,LCD.blue)
LCD.vline(10,10,115,LCD.blue)
LCD.vline(230,10,115,LCD.blue)

LCD.rect(12,12,20,20,LCD.red)
LCD.rect(12,103,20,20,LCD.red)
LCD.rect(208,12,20,20,LCD.red)
LCD.rect(208,103,20,20,LCD.red)

LCD.show()

## The Keys are connected to the following pins
key0 = Pin(15,Pin.IN)
key1 = Pin(17,Pin.IN)
key2 = Pin(2 ,Pin.IN)
key3 = Pin(3 ,Pin.IN)

## The main loop.
while(1):
if(key0.value() == KEY_PRESSED): ## Turn off the LED strips (0 brightness)
LCD.fill_rect(12,12,20,20,LCD.red)
brightness = 0
updatePixel(brightness)
else :
LCD.fill_rect(12,12,20,20,LCD.white)
LCD.rect(12,12,20,20,LCD.red)

if(key1.value() == KEY_PRESSED): ## Max brightness for LEDs
LCD.fill_rect(12,103,20,20,LCD.red)
brightness = 1
updatePixel(brightness)
else :
LCD.fill_rect(12,103,20,20,LCD.white)
LCD.rect(12,103,20,20,LCD.red)

if(key2.value() == KEY_PRESSED): ## Decrease brightness by 10%
LCD.fill_rect(208,12,20,20,LCD.red)
brightness -= 0.1
if brightness < 0:
brightness = 0
updatePixel(brightness)
else :
LCD.fill_rect(208,12,20,20,LCD.white)
LCD.rect(208,12,20,20,LCD.red)

if(key3.value() == KEY_PRESSED): ## Increase brightness by 10%
LCD.fill_rect(208,103,20,20,LCD.red)
brightness = brightness + 0.1
if brightness > 1 :
brightness = 1
updatePixel(brightness)
else :
LCD.fill_rect(208,103,20,20,LCD.white)
LCD.rect(208,103,20,20,LCD.red)
LCD.show()
## end of main loop. Basically, unplugging everything turns it all off
## A proper on/off switch would be nice, for sure…

time.sleep(1)
LCD.fill(0xFFFF) ## clear the screen<br>
Для второго Рассбери установка кода практически такая же. Обязательно нужно для обеих устройство указать, в функции NUM_LED, количество светодиодов.
Шаг седьмой: корпус для дисплеев
Для установки дисплеев мастер использует коробку из картона. В коробке вырезается два окошка и отверстие для проводов. Затем нужно подключить провода (красные провода к контакту 39, белые — к контакту 3, а данные (зеленые) — к контакту 1 (GPIO 0). Установить и закрепить экраны.

Шаг восьмой: оборудование
В качестве камеры мастер использует камеру своего Айфона. Для его крепления прикручивает держатель к стене.

Лектор стоит за стеклом и пишет на доске слова и символы как привык писать. Но дело в том, что камера стоит за стеклом и символы отображаются зеркально. Исправить это можно с помощь программы OBS. Программа бесплатна и имеет множество настроек.
Для передачи звука мастер использует беспроводной петличный микрофон.
И камера и микрофон настраиваются через программу OBS.
При трансляции нужно сделать сзади темный фон. В принципе, темный фон можно сделать и с помощью программы OBS, но текст, написанный на доске, в этом случае видно плохо.
Для письма на доске мастер использует маркеры Expo Neon. Для стирания маркеров использует салфетки для очистки ЖК-экранов.

Источник

Похожие статьи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть
Закрыть