Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

Lámpara Zerynth: Control IoT de Luz Ambiental con NeoPixel y App Móvil

Componentes y materiales

Zerynth Shield (multisensor: tacto, IR, micrófono, luz, temp) 1
Placa compatible: Arduino Due, STM32 Nucleo F401RE, Particle Photon, UDOO Dual, Flip&Click 1
Módulo Wi-Fi (si la placa no lo integra): shield CC3000 (Adafruit/TI) 1
Tira/anillo NeoPixel (Adafruit) 1
Base de lámpara (vidrio o impresión 3D) 1

Software y apps

Descripción

Lámpara inteligente controlada desde móvil vía Zerynth App. Interfaz: selector de color (color picker) + menú de animaciones predefinidas (Little Snakes, Spinner, Rainbow, Pulse) + control de velocidad. Programada en Python con Zerynth Studio.

Montaje

  1. Apila (piggyback) shield Wi-Fi + Zerynth Shield sobre la placa base. Si usas Particle Photon, conéctalo directo al Zerynth Shield.
  2. Conecta NeoPixel al puerto dedicado del Zerynth Shield.
  3. Introduce todo en la base de lámpara.

Programación con Zerynth Studio

  1. Conecta placa → "Virtualiza" en Zerynth Studio.
  2. Nuevo proyecto → crea 4 archivos: main.py, animation.py, template.html, project.md.
  3. Copia el código de cada archivo (ver abajo).
  4. Uplink (flashea) → la lámpara conecta automáticamente a la Wi-Fi configurada.
  5. Abre Zerynth App → detecta "Zerynth Lamp" → controla color, animación, velocidad.

Código

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()

# Conexión 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)

# Guarda template.html en flash
new_resource("template.html")

#### ZerynthApp Setup
# Callbacks JS → 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)

# Configura app
vp = zerynthapp.ZerynthApp("Zerynth Lamp", "Try me!", "resource://template.html")
vp.on("change_color", change_color)
vp.on("change_animation", change_animation)
vp.on("change_speed", change_speed)

vp.run()  # inicia hilo app

# Inicia animación NeoPixel (pin D6, 24 LEDs)
animation.start(D6, 24)

template.html (interfaz móvil)


<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) { /* ... */ }
    $(document).ready(function () {
      $("#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 (lógica NeoPixel multicapa)


################################################################################
# Zerynth Lamp - Animation functions
################################################################################
from neopixel import ledstrips as neo
import threading

lock = threading.Lock()
color = [0x54, 0x9a, 0x97]
anim = 0
anim_speed = 50
leds = None
layer0 = layer1 = layer2 = None
npins = 0
stopped = False
stopcolor = [0xff, 0xff, 0xff]

animation_coefficients = [0, 0.2588, 0.5, 0.7071, 0.8660, 0.9659, 1,
                          0.9659, 0.8660, 0.7071, 0.5, 0.2588]

rainbow = [(0xff,0,0), (0xff,0x7f,0), (0xff,0xff,0), (0,0xff,0),
           (0,0,0xff), (0x4b,0,0x82), (0x8f,0,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:
        layer0[0]=layer0[1]=layer0[2]=(100,0,0)
        layer1[0]=layer1[1]=layer1[2]=(0,100,0)
    elif n == 1:
        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:
        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:
        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 = (step + 1) % len(animation_coefficients)
        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)  # solo donde sea transparente
        lock.release()
        leds.on()
        sleep(50)

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

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

Esquemático

Ver imagen en sección "Schematics": conexiones NeoPixel → Zerynth Shield, Wi-Fi shield, placa base.

Extensiones sugeridas

Proceso de manufactura

  1. Faroles de Gas: Evolución, Diseño y Fabricación Moderna
  2. Puntero Láser: Diseño, Fabricación y Resumen de Seguridad
  3. Linterna: de su invención a la innovación moderna
  4. Lámparas Halógenas: Tecnología, Historia y Futuro – Perspectiva Experta
  5. El Caleidoscopio: De la Ciencia de Brewster al Diseño Moderno
  6. Semáforos: Ingeniería, Historia e Innovaciones Futuras
  7. Del Fuego al Filamento: Evolución y Producción de la Bombilla Moderna
  8. Construya un Sistema de Monitorización de Temperatura y Luz Multi‑Sensor con Raspberry Pi y DS18B20
  9. Semáforo Inteligente: Iluminación Vial Adaptativa con IoT
  10. Sensor de Luz Digital – Enciende un LED con Luz Ambiental usando Windows 10 IoT Core
  11. Propagación de Señales Eléctricas a Velocidad de la Luz: Experimento Mental de 186.000 Millas