산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

제린스(Zerynth) 램프: 네오픽셀 LED로 구현하는 스마트 IoT 앰비언트 라이트

부품 및 소모품

제린스 실드 (Zerynth Shield) 1개
아두이노 듀 (Arduino Due) 1개
STM32 Nucleo ST NUCLEO 1개
파티클 포톤 (Particle Photon) 1개
UDOO DUAL 1개
Adafruit 네오픽셀 (NeoPixel) LED 스트립/링 1개

앱 및 온라인 서비스

프로젝트 소개

저전력 무선 표준과 초소형 저가 LED, 센서, 통신 모듈의 결합으로 스마트 조명이 IoT와 홈 오토메이션의 촉매제가 되었습니다.

이 튜토리얼에서는 제린스 앱으로 네오픽셀 LED 스트립을 모바일 제어하는 방법을 다룹니다. 앱에는 컬러 피커와 사전 구성 애니메이션 선택 메뉴가 표시됩니다.

1단계: 필요 물품

제린스(Zerynth) 램프: 네오픽셀 LED로 구현하는 스마트 IoT 앰비언트 라이트

2단계: 조립

제린스(Zerynth) 램프: 네오픽셀 LED로 구현하는 스마트 IoT 앰비언트 라이트
  1. Wi-Fi 실드와 제린스 실드를 아두이노(또는 ST Nucleo, UDOO)에 피기백. 파티클 포톤은 제린스 실드 전용 커넥터에 장착.
  2. 네오픽셀 LED를 제린스 실드 해당 포트에 연결.
  3. 모든 보드와 LED를 램프 쉐이드 안에 넣습니다.

3단계: 프로그래밍

제린스(Zerynth) 램프: 네오픽셀 LED로 구현하는 스마트 IoT 앰비언트 라이트

제린스 사용법은 아주 간단합니다!

  1. 보드 연결 및 '가상화' (과정 여기 참조)
  2. 제린스에서 새 프로젝트 생성 (여기 참조). 주의: main.py, animation.py, template.html, project.md 총 4개 파일 생성 필요
  3. 아래 코드 복사 붙여넣기
  4. 보드에 업링크하면 끝!

전원 켜면 미리 설정한 네트워크에 자동 연결. 제린스 앱 실행 → 네트워크상 제린스 오브젝트 검색 → 'Zerynth Lamp' 선택 → 컬러 피커와 애니메이션 메뉴로 제어 가능.

코드는 주석이 풍부해 이해하기 쉽습니다. 문의/제안은 제린스 커뮤니티 포럼에 남겨주세요.

4단계: IoT를 더 밝게!

제린스(Zerynth) 램프: 네오픽셀 LED로 구현하는 스마트 IoT 앰비언트 라이트

제린스 실드에는 터치 감지, 적외선 LED, 마이크, 조도 센서, 온도 센서 등 다양한 센서/액추에이터가 있습니다. 이 예제를 기반으로 원하는 동작을 개발해 보세요!

Luigi F. Cerfeda (@L_F_Cerfeda) - 제린스 팀

코드

main.py (파이썬)

################################################################################
# Zerynth Lamp
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################
import streams
from bcm43362 import bcm43362 as wifi_driver
from wireless import wifi
import animation
from toishield import toishield
from zerynthapp import zerynthapp

streams.serial()

# Wi-Fi 연결
try:
    wifi_driver.auto_init()
    print("Establishing Link...")
    wifi.link("SSID", wifi.WIFI_WPA2, "password")
    print("Ok!")
except Exception as e:
    print(e)

# template.html을 보드 플래시에 저장
new_resource("template.html")

#### ZerynthApp 설정
# JavaScript → Python 콜백 함수들
def change_color(r, g, b):
    animation.setup_color(r, g, b)

def change_animation(n):
    animation.setup_anim(n)

def change_speed(n):
    animation.setup_anim_speed(n)

# 앱 구성: 이름, 설명, 템플릿 URL
vp = zerynthapp.ZerynthApp("Zerynth Lamp", "Try me!", "resource://template.html")

# JS 이벤트 발생 시 해당 파이썬 함수 호출
vp.on("change_color", change_color)
vp.on("change_animation", change_animation)
vp.on("change_speed", change_speed)

# 앱 실행 (별도 스레드 시작)
vp.run()

# vp.run()이 스레드를 시작하므로 여기서 다른 작업 가능
# LED 제어 시작
animation.start(D6, 24)

template.html (HTML/JS)

<html>
<head>
<zerynth/> <zerynth-jquery/> <zerynth-jquery-mobile/> <zerynth-jqwidgets/>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div data-role="page">
<div data-role="header"><h1>Zerynth Lamp</h1></div>
<div role="main" class="ui-content" style="text-align:center">
<div style="margin: 3px; float: left;" id="dropDownButton">
<div style="padding: 3px;">
<div id="colorPicker"></div>
</div>
</div>
<button class="ui-btn ui-btn-inline ui-shadow" onclick="ZerynthApp.call('change_color',cur_color.r,cur_color.g,cur_color.b)">Colorize!</button>
<form>
<div data-role="fieldcontain">
<label for="animselect">Animation:</label>
<select name="animselect" id="animselect">
<option value="0">Little Snakes</option>
<option value="1">Spinner</option>
<option value="2">Rainbow</option>
<option value="3">Pulse</option>
</select>
</div>
</form>
<form>
<label for="speedslider">Animation Speed:</label>
<input type="range" name="speedslider" id="speedslider" data-highlight="true" min="0" max="100" value="50">
</form>
</div>
<div data-role="footer">Powered by Zerynth (www.zerynth.com)</div>
</div>
<script>
var cur_color = {r: 0x54, g: 0x9a, b:0x97};
function getTextElementByColor(color) {
    if (color == 'transparent' || color.hex == "") {
        return $("<div style='text-shadow: none; position: relative; padding-bottom: 2px; margin-top: 2px;'>transparent</div>");
    }
    var element = $("<div style='text-shadow: none; position: relative; padding-bottom: 2px; margin-top: 2px;'>#" + color.hex + "</div>");
    var nThreshold = 105;
    var bgDelta = (color.r * 0.299) + (color.g * 0.587) + (color.b * 0.114);
    cur_color.r = color.r; cur_color.g = color.g; cur_color.b = color.b;
    var foreColor = (255 - bgDelta < nThreshold) ? 'Black' : 'White';
    element.css('color', foreColor);
    element.css('background', "#" + color.hex);
    element.addClass('jqx-rc-all');
    return element;
}
$(document).ready(function () {
    console.log("ready!")
    $("#colorPicker").on('colorchange', function (event) {
        $("#dropDownButton").jqxDropDownButton('setContent', getTextElementByColor(event.args.color));
    });
    $("#colorPicker").jqxColorPicker({ color: "5a9a97", colorMode: 'saturation', width: 220, height: 220});
    $("#dropDownButton").jqxDropDownButton({ width: 150, height: 22});
    $("#dropDownButton").jqxDropDownButton('setContent', getTextElementByColor(new $.jqx.color({ hex: "549a97" })));
    ZerynthApp.jquerymobile_scalecontent();
    $("#animselect").change(function() {
        ZerynthApp.call('change_animation',parseInt($('#animselect').val()));
    });
    $("#speedslider").on('slidestop',function() {
        ZerynthApp.call('change_speed',parseInt($('#speedslider').val()));
    });
});
</script>
</body>
</html>

animation.py (파이썬)

################################################################################
# Zerynth Lamp - 애니메이션 함수들
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################
from neopixel import ledstrips as neo
import threading

lock = threading.Lock()
color = [0x54,0x9a,0x97]  # 제린스 기본 색상
anim = 0
anim_speed = 50
leds = None
layer0 = None
layer1 = None
layer2 = None
npins = 0
stopped = False
stopcolor = [0xff,0xff,0xff]

# 부드러운 애니메이션용 계수 (반 사인파)
animation_coefficients = [
    0, 0.2588190451, 0.5, 0.7071067812, 0.8660254038, 0.9659258263,
    1, 0.9659258263, 0.8660254038, 0.7071067812, 0.5, 0.2588190451
]

rainbow = [
    (0xff,0x00,0x00), (0xff,0x7f,0x00), (0xff,0xff,0x00),
    (0x00,0xff,0x00), (0x00,0x00,0xff), (0x4b,0x00,0x82), (0x8f,0x00,0xff)
]

def setup_anim(n):
    global layer0,layer1,layer2,anim
    lock.acquire()
    leds.clear(); layer2.clear(); layer0.clear(); layer1.clear()
    n = n % 4
    if n == 0:  # Little Snakes
        layer0[0]=(100,0,0); layer0[1]=(100,0,0); layer0[2]=(100,0,0)
        layer1[0]=(0,100,0); layer1[1]=(0,100,0); layer1[2]=(0,100,0)
    elif n == 1:  # Spinner
        for x in range(npins//2):
            layer0[x]=(100//(2*x+1),0,0)
            layer1[npins-x-1]=(0,100//(2*x+1),0)
        layer2.clear()
    elif n == 2:  # Rainbow
        layer1.clear()
        pstep = 0
        for x in range(npins):
            step = x * len(rainbow) / npins
            rx = (rainbow[int(step)][0] + rainbow[int(pstep)][0]) // 4
            gx = (rainbow[int(step)][1] + rainbow[int(pstep)][1]) // 4
            bx = (rainbow[int(step)][2] + rainbow[int(pstep)][2]) // 4
            layer0[x] = (rx, gx, bx)
            pstep = step
    elif n == 3:  # Pulse
        layer0.clear(); layer1.clear()
    anim = n
    lock.release()

def setup_anim_speed(n):
    global anim_speed
    anim_speed = n

def setup_color(r,g,b):
    global color
    color[0]=r; color[1]=g; color[2]=b

# 배경 애니메이션 스레드
def animate_background(delay):
    global color
    step = 0
    while True:
        if (anim == 3 or anim == 0) and not stopped:
            lock.acquire()
            layer2.setall(int(color[0]*animation_coefficients[step]/2),
                         int(color[1]*animation_coefficients[step]/2),
                         int(color[2]*animation_coefficients[step]/2))
            lock.release()
            step += 1
            if step >= len(animation_coefficients): step = 0
        else:
            lock.acquire()
            layer2.clear(); layer2.setall(stopcolor[0],stopcolor[1],stopcolor[2])
            lock.release()
        sleep(delay + 500 - 5*anim_speed)

# 전경 애니메이션 스레드
def animate_foreground(delay):
    while True:
        if not stopped:
            lock.acquire()
            if anim == 0:
                layer0.lshift(); layer1.rshift()
            elif anim == 1:
                layer0.rshift(); layer1.rshift()
            elif anim == 2:
                layer0.rshift(); layer1.rshift()
            elif anim == 3:
                layer0.lshift(); layer1.lshift()
            lock.release()
        else:
            lock.acquire()
            layer0.clear(); layer1.clear()
            lock.release()
        sleep(delay + 100 - anim_speed)

def start(pin, numpins):
    global leds, layer0, layer1, layer2, npins
    npins = numpins
    leds = neo.LedStrip(pin, numpins)
    layer0 = neo.LedStrip(pin, numpins)
    layer1 = neo.LedStrip(pin, numpins)
    layer2 = neo.LedStrip(pin, numpins)
    setup_anim(0)
    setup_anim_speed(50)
    thread(animate_background, 500)
    thread(animate_foreground, 50)
    
    while True:
        leds.clear()
        lock.acquire()
        leds.merge(layer0)
        leds.merge(layer1)
        leds.merge(layer2, neo.first_color)  # 투명(0,0,0)인 곳에만 배경 합성
        lock.release()
        leds.on()
        sleep(50)

def stop(r,g,b):
    global stopped, stopcolor
    stopcolor[0]=r; stopcolor[1]=g; stopcolor[2]=b
    stopped = True

def resume():
    global stopped
    stopped = False
    setup_anim(anim)

회로도

제린스(Zerynth) 램프: 네오픽셀 LED로 구현하는 스마트 IoT 앰비언트 라이트

제조공정

  1. 광속 전기 신호 전파: 186,000마일 사고 실험
  2. 가스 랜턴: 진화, 디자인, 현대 제조 공정
  3. 레이저 포인터: 설계, 제조, 안전성 개요
  4. 손전등: 탄생부터 현대 혁신까지
  5. 할로겐 램프: 기술, 역사, 그리고 미래 - 전문가 통찰
  6. 교통신호: 공학, 역사, 미래 혁신
  7. 불에서 필라멘트로: 현대 전구 진화와 생산
  8. 라즈베리 파이 & DS18B20으로 다중 센서 온도 & 조도 모니터링 시스템 구축
  9. 스마트 트래픽 라이트: IoT로 구동되는 적응형 가로등 시스템
  10. 디지털 조도 센서 – 윈도우 10 IoT Core로 주변광에 따라 LED 제어하기