Geschichten um einen kleinen Weihnachtsbaum
Las historias suelen comenzar con un "Érase una vez". Sin embargo, las siguientes historias tienen lugar hoy y ahora. Hoy desarrollaremos algunos proyectos en torno a un tipo especial de árbol de Navidad.

Se trata de un pequeño árbol de aproximadamente unos 11,5 cm de altura con 36 (37) luces de colores. Parpadean en todos los colores de forma divertida, pero lo hacen más o menos siempre de la misma manera. Eso me originó la idea de poner un poco de orden en el caos añadiendo algunos componentes más. El resultado es un sistema de control con un ESP32 y varios sensores que proporcionan la iluminación de los LEDs al servicio de diversas tareas de medición, o simplemente causan asombro. En los siguientes capítulos, le presentaré algunas de las opciones posibles. Todas las aplicaciones están programadas en MicroPython. Mi colega Andreas Wolter también ha portado los programas a C++ para el Arduino IDE. Así que bienvenido a las

Historias alrededor de un pequeño árbol de Navidad

Figura 1: Las historias de los árboles.

Figura 1: Las historias de los árboles.

El contenido:

  1. La lista de piezas
  2. El software
  3. Construimos el árbol y lo cableamos
  4. Iluminación dirigida
  5. La pantalla OLED para la información de texto sin formato
  6. Iluminación escalonada
  7. El árbol encantado
  8. ¿Quién está haciendo todo ese ruido? (Adviento y Navidad, el tiempo de "staade")
  9. Tras la pista del ladrón de árboles
  10. Tener una estancia agradable ESP32 y DHT22/DHT11
  11. El sorteo de Navidad (algo diferente)
  12. La aplicación del árbol de Navidad (El árbol en LAN/WLAN)


1. La lista de piezas

1

Kit de Árbol de navidad DIY LED

1

Módulo de Sensor KY-009 RGB LED SMD o

Módulo LED RGB KY-016 FZ0455 de 3 colores

1

Pantalla OLED I2C 1,3 pulgadas de 128 x 64 píxeles compatible con Arduino y Raspberry Pi

1

Sensor de Temperatura y Humedad DHT22 AM2302

1

Módulo Interruptor Magnético KY-021 Mini Sensor

1

RFID de la Tarjeta Keycard 13,56MHz MF S50 - Tarjeta RFID 10X

1

Kit RFID RC522 con lector, chip y tarjeta para Raspberry Pi (13,56 MHz)

1

Kit de Placa de Pruebas - 3 x 65 piezas. Cable de puente M2M y 3 x Mini Breadboard de 400 Pines compatible con Arduino y Raspberry Pi

1

Módulo de detección de sonido KY-038 Micrófono Sensor de Sonido de Voz

1

Módulo ESP32 NodemCU WLAN WIFI Placa de desarrollo con CP2102

1

Sensor de giroscopio y aceleración GY-521 MPU-6050 de 3 ejes como alternativa Sensor de aceleración GY-61 ADXL335

Contacto virtual KY-020 o KY-002 (*)

1

Jumper Wire Cable de puente 3 x 40 pcs. por 20 cm M2M / F2M / F2F

3

Resistencia 1.0kΩ

(*) El uso de los contactos vibratorios o del módulo GY-51 requiere una programación diferente.

2. El software

Para flashear y programar el ESP32:

Thonny o

μPyCraft

packetsender para probar ESP32/ESP8266 como servidor UDP

Navegador: Opera o Chrome

Firmware usado:

MicropythonFirmware

Por favor, elija una versión estable

Los programas Micropython para el proyecto:

Con texto de licencia

Controlador de dispositivo:

gy521rc.py

mfrc522.py

sh1106.py

oled.py

Archivos del proyecto MicroPython:

alarm.py

noisy.py

rfid.py

roomclimate.py

increase.py

enchant.py

webcontrol.py

Archivos del proyecto Arduino IDE:

Aviso:
La versión del Arduino IDE que se utiliza aquí es la 1.8.16
La versión del núcleo del Arduino ESP32 es la 2.0.2


Para utilizar el núcleo ESP32, debe ingresar este enlace en los ajustes preestablecidos como una URL adicional del administrador de placas en las preferencias:

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json

A continuación, busque el ESP 32 a través del menú Herramientas -> Placa -> Administrador de placas e instálelo

Las bibliotecas utilizadas, como LittleFS, sólo se integraron en el núcleo en una fase tardía. Por lo tanto, es importante actualizarlo si es necesario.

I2C_Scanner.ino

oledtest.ino


alarm.ino

noisy.ino

opcional noisy_ticker_h.ino (con biblioteca Ticker.h)

rfid.ino

roomclimate.ino

increase.ino

enchant.ino

webcontrol.ino


MicroPython - Lenguaje - Módulos y programas

Para instalar Thonny encontrará a continuación las instrucciones detalladas. También contiene una descripción de cómo grabar el Firmware MicroPython en el ESP-Chip.

MicroPython es un lenguaje de interpretación. La principal diferencia con el Arduino IDE, donde siempre y exclusivamente se flashean programas completos, es que sólo tiene que flashear el firmware MicroPython una vez al principio en el ESP32 antes de que el controlador entienda las instrucciones de MicroPython. Puede utilizar Thonny, μPyCraft o esptool.py para esto. Para Thonny, he descrito aquí el proceso.

Tan pronto como se actualice el firmware, puede tener una conversación informal con su controlador, probar comandos individuales y ver inmediatamente la respuesta sin tener que compilar y transferir primero un programa completo. Eso es exactamente lo que me molesta del Arduino IDE. Simplemente se puede ahorrar una enorme cantidad de tiempo si puede comprobar la sintaxis simple y las pruebas de hardware hasta probar y perfeccionar funciones y partes enteras del programa a través de la línea de comandos por adelantado antes de tener un programa a partir del mismo. Para este propósito, también me gusta crear pequeños programas de prueba una y otra vez. Como una especie de macro, combinan los comandos recurrentes. A partir de esos fragmentos de programa, se pueden desarrollar aplicaciones completas.

Autoarranque

Si el programa se debe iniciar de forma autónoma al encender el controlador, copie el texto del programa en un archivo en blanco recién creado. Guarde este archivo en boot.py en el espacio de trabajo y cárguelo al chip ESP. La próxima vez que se reinicie o se encienda el mando, el programa se iniciará automáticamente.

Programas de pruebas

Inicie manualmente los programas desde la ventana actual del editor en el Thonny IDE pulsando la tecla F5. Esto es más rápido que un clic del ratón en el botón de inicio, o a través del menú Ejecutar. Sólo los módulos utilizados en el programa deben estar en la flash del ESP32.

¿Arduino IDE de nuevo en el medio?

Si desea volver a utilizar el controlador junto con el Arduino IDE más adelante, simplemente tiene que flashear el programa de la manera habitual. Sin embargo, el ESP32/ESP8266 habrá olvidado que alguna vez habló MicroPython. Por el contrario, cualquier chip Espressif que contenga un programa compilado del Arduino IDE o el firmware de AT o LUA o ... se puede proporcionar fácilmente con el firmware MicroPython. El proceso es siempre el que se describe aquí.

3. Construimos el árbol y lo cableamos

Está disponible un vídeo para ensamblar el árbol.

Por supuesto, después de ensamblarlo, se puede sentar, relajarse y admirar su trabajo. Es aun más divertido si modificamos el proceso de montaje en algunos puntos. En tres partes del vídeo tenemos que proceder de forma diferente para nuestro proyecto. Las resistencias de 4,7 kΩ que se mencionan allí son resistencias de 10kΩ en el paquete de piezas. Y estas tres resistencias por placa A y B sólo se sueldan en los puntos de la placa, como se presenta en las figuras 2 y 3, el otro extremo de estas resistencias permanece libre por el momento. Más tarde soldamos cables delgados (por ejemplo, de cinta plana) a estos extremos libres para la conexión con el ESP32. Esto se aplica a ambas placas, A y B. Los condensadores electrolíticos se han eliminado por completo.

Figura 2: Parte A

Figura 2: Parte A

Figura 3: Parte B

Figura 3: Parte B

El resto del montaje se puede hacer exactamante como se presenta en el video. Cuando la placa base también está encendida, soldamos los cables a los extremos libres de las resistencias de 10 kΩ. La longitud debe estar entre 25 y 30 cm. En el otro extremo del cable, soldamos un trozo de cabezal de pin para que se pueda enchufar.

Figura 4: La conexión del árbol.

Figura 4: La conexión del árbol.

La asignación de las conexiones en el árbol a los GPIOs del ESP32 se puede ver en la Tabla 1. El índice se refiere a la lista de objetos pin. Esta lista con el nombre de capa se utiliza para direccionar las capas de LEDs por bucles, como veremos más adelante. Las conexiones se distribuyen de modo que un índice par siempre va seguido de la capa de LEDs de la misma capa en la placa B. Por supuesto, cualquier reordenación es posible en cualquier momento.

Árboles

A1

B1

A2

B2

A3

B3

GPIO

32

26

33

27

25

12

Índice

0

1

2

3

4

5

Tabla 1: Conexiones entre árboles y ESP32

Figura 5: Cableado base

Figura 5: Cableado base

Figura 6: Resistencias básicas en la parte B - Detalle, los extremos libres están arriba

Figura 6: Resistencias de base en la parte B - detalle, los extremos libres están arriba

Figura 7: Cortometrada de la parte A

Figura 7: Conectado a la parte A

4. Iluminación dirigida

¿El cableado está terminado? Entonces encendamos los LEDs del árbol. Alimentamos el árbol a través de las baterías o a mediante el cable suministrado desde un puerto USB. Después de encenderlo, se queda a oscuras. Por supuesto, como las conexiones de base de los transistores están expuestas, no puede fluir ninguna corriente de base y como tampoco fluye ninguna corriente de colector, los LEDs permanecen oscuros.

Figura 8: Uno de los 6 niveles de transistor.

Figura 8: Una de los 6 etapas de transistor

Esto cambia cuando los GPIOs se programan como salidas y el nivel de potencial de GND se eleva a 3,3V. Esto se consigue asignando un 1 como un valor. En la terminal de Thonny ingresamos las siguientes líneas.

 >>> de máquina importar Código PIN
>>> A1=Código PIN(32,Código PIN.FUERA,valor=0)
>>> A1.valor(1)

Si el cableado es correcto, los LEDs del nivel A1 comenzarán ahora a encenderse, para apagarse después de la entrada

 >>> A1.valor(0)

salen. A diferencia de la versión anterior del kit del árbol, la nueva versión está equipada con LEDs parpadeantes. Anteriormente, eran LEDs de colores simples. Esto tiene una cierta desventaja porque ya no es posible atenuar los "LEDs parpadeantes". Sin embargo, es divertido experimentar con ellos. A través de los seis transistores, ahora podemos arrancar o apagar los 6 niveles exactamente de acuerdo con nuestros deseos. Esto también nos permite influir en la luminosidad general.

La disposición de luces se muestra en la Figura 9. Se aplica tanto a la Parte A como a la Parte B.

Figura 9: La distribución de los LED es rango.

Figura 9: Distribución de los LEDs por turnos

La disposición de los LEDs, el cableado y las conexiones al ESP32 se asumen para todos los experimentos posteriores. Por lo tanto, ya no aparecen explícitamente en las descripciones y los esquemas de los subcircuitos.

5. La pantalla OLED

La pantalla OLED puede proporcionarnos información en texto sin formato, pero también puede presentar gráficos en blanco y negro. La programación es sencilla si se utilizan los módulos de software MicroPython apropiados. El controlador de hardware SH1106 es el responsable directo de la pantalla de 1,3'' y sólo se puede utilizar para esto. El módulo framebuf integrado en el núcleo de MicroPython proporciona sencillos comandos de gráficos y texto y el módulo oled.py genera cómodos comandos para la salida de texto.

La pantalla se controla únicamente a través de las dos líneas del bus I2C. Creamos un objeto I2C y lo pasamos al constructor de la clase OLED. La dirección del dispositivo de hardware de la pantalla está fija y anclada como una constante en OLED. Sin embargo, primero comprobamos lo que se encuentra en el bus. A continuación, limpiamos la pantalla y emitimos unas líneas.

El gráfico de la Figura 10 y el siguiente programa demuestran la manipulación. Introducimos el programa en el editor de Thonny, lo guardamos y lo iniciamos con la tecla de función F5.

Figura 10: El OLED en el ESP32

Figura 10: El OLED en el ESP32

oledtest.py

 # OLED demo de la pantalla
 #
 de máquina importar Código PIN, I2C
 de tiempo importar dormir
 de oled importar OLED
 
 # Inicializar la interfaz **********************
 I2C=I2C(-1,SCL=Código PIN(22),SDA=Código PIN(21))
 impresión(I2C.escanear())
 D=OLED(I2C)
 
 D.limpiar todo()
 D.WriteAt("De El",0,0,falso)
 D.WriteAt("pequeña",0,1,falso)
 D.WriteAt("Navidad",0,2,falso)
 D.WriteAt("árbol",0,3)
 dormir(4)
 D.clearFT(0,2,15,2,falso)
 D.WriteAt("Cristiano-",0,2)


La salida:

[60]
este es el constructor de la clase OLED
Tamaño: 128x64

La dirección del dispositivo de la pantalla es decimal 60 o hexadecimal 0x3C. El constructor de la clase OLED también sabe que la pantalla tiene 128 x 64 píxeles. Después de que se hayan emitido las cuatro líneas, 4 segundos más tarde, "Christmas" se sustituye por "Chist-". Antes, tenemos que eliminar esta línea. Siéntase libre de probar los comandos individuales uno por uno a través de REPL, la consola de terminal de Thonny.

Para Arduino IDE:

Para la visualización utilizamos la biblioteca U2G8, que puede instalar a través de la gestión de bibliotecas.

Descargar oledtest.ino

6. Iluminación escalonada

Figura 11: Nivel11

Figura 11: Etapa 1

Figura 12: Nivel2

Figura 12: Etapa 2

Como podemos controlar los niveles individuales de los LEDs del árbol por separado, vamos a aprovechar para subir y bajar desde el nivel más bajo -Apagado- hasta el máximo brillo. No se necesita cambiar nada en el circuito. La pantalla nos proporciona información sobre el nivel activo actualmente.

increase.py

 # steigerung.py
 #
 importar sys
 de máquina importar Código PIN, I2C
 de oled importar OLED
 de tiempo importar dormir,ticks_ms, ticks_us, sleep_ms
 
 # La inicialización de las interfaces **********************
 I2C=I2C(-1,SCL=Código PIN(22),SDA=Código PIN(21))
 D=OLED(I2C)
 
 Configuración de capas LED # *******************************
 #schichtPin = [32,33,25,27,26,12] # especie
 schichtPin = [32,26,33,27,25,12]   # distribuido
 capa=[0]*6
 por I en trinquete(6): # Crear y salidas 0
     capa[I]=Código PIN(schichtPin[I],Código PIN.FUERA)
     capa[I].valor(0)
 
 # Funciones Defne ***********************************
 def  cambiar(norte,val):  # Nivel n de encendido / apagado
     capa[norte].valor(val)
 
 def parada():  # LED todos los niveles de
     D.WriteAt("ADIÓS",4,3)
     por I en trinquete(6):
         cambiar(I,0)
 
 def Todo el mundo():  # Todos los niveles llevaban una
     por I en trinquete(6):
         sleep_ms(300)
         cambiar(I,1)
     
 # Programa principal ******************************************
 D.limpiar todo()
 D.rect(4,16,123,40,1)  # Rectángulo en valores de píxeles
 por j en trinquete(3):
     por I en trinquete(6):
         D.WriteAt("Nivel: {} un".formato(I),2,3)
         cambiar(I,1)
         sleep_ms(3000)
     por I en trinquete(5,-1,-1):
         D.WriteAt("Nivel: {}".formato(I),2,3)
         cambiar(I,0)
         Sleep_ms(3000)
 D.Clebre(2,3,14,3,Falso)
 parada()

Definimos el orden de los niveles en la lista layerPin. De acuerdo con este patrón, los objetos pin se crean en el siguiente bucle for. Las funciones switch(), stop() y all() nos ayudan a hacer el programa más claro. También los utilizaremos varias veces en los siguientes capítulos.

En el programa principal limpiamos la pantalla y dibujamos un marco. 4 y 16 son las coordenadas de los píxeles de la esquina superior izquierda, 123 y 40 la anchura y la altura en píxeles y 1 el color blanco, no hay más colores. El bucle for externo cuenta el número total de pasdas. El primer bucle for interno cuenta hacia arriba i en intervalos de 3 segundos y enciende los niveles. El segundo bucle cuenta hacia atrás y apaga los LEDs de nuevo.

La última salida se elimina, y la función stop () borra de manera fiable todos los LEDs y se despide con un amistoso "Good bye".

Nosotros mismos podemos especificar el comportamiento de los LEDs mediante la longitud del intervalo y el número de pasadas.

Para Arduino IDE

Descargar increase.ino

7. El árbol encantado

Cualquiera puede venir y querer encender nuestro árbolito. Pero de ninguna manera, esto sólo puede ser hecho por nuestras manos mágicas. Por supuesto, no le decimos que tenemos una pequeña barra magnética de neodimio escondida en cada mano. ¿Para qué lo necesitamos? Para "magia" pura. Porque ahora hemos reconstruido nuestro circuito. Un contacto de lengüeta a tierra está conectado ahora al pin 13 de GPIO. El tubo de vidrio contiene un contacto de conmutación que se cierra cuando se acerca un imán.

Figura 13: Los muggles no tienen imán, el árbol permanece oscuro.

Figura 13: Los muggles no tienen imán, el árbol permanece oscuro

Figura 14: En el marcador amarillo: contacto e imán

Figura 14: En el marcador amarillo: contacto e imán

Precaución:

El vidrio es muy frágil y los cables son muy rígidos. No los doble, ya que de lo contrario el cristal se romperá y podrá enterrar el componente

Figura 15: Contacto Reed ayuda a la magia

Figura 15: El contacto de la lengüeta ayuda a la magia

Hay algo más que no debemos olvidar, y es que el OLED y el árbol siguen conectados como se ha descrito anteriormente.

enchant.py

 de Os importar tu nombre
 importar Sys
 de máquina importar  Código PIN, I2C
 de Oled importar Oled
 de tiempo importar Sleep_ms
 
 # Inicializar las interfaces **********************
 I2C=I2C(-1,Scl=Código PIN(22),Sda=Código PIN(21))
 D=Oled(I2C)
 
 botón=Código PIN(0,Código PIN.EN,Código PIN.Levantar)
 Junco=Código PIN(13,Código PIN.EN,Código PIN.Levantar)
 
 # Configurar capas LED *****************************
 Pin de capa = [32,33,25,26,27,12]
 capa=[0]*6
 por I en trinquete(6):
     capa[I]=Código PIN(Pin de capa[I],Código PIN.FUERA)
     capa[I].valor(0)
 
 # Funciones define ***********************************
 def  cambiar(norte,Val):
     capa[norte].valor(Val)
 
 def parada():
     D.escribiendo("Muggle",1,3)
     por I en trinquete(6):
         cambiar(I,0)
 
 def Todo el mundo():
     D.escribiendo("DumbleDor",1,3)
     por I en trinquete(6):
         Sleep_ms(300)
         cambiar(I,1)
     
 # Programa de inicio *******************************************
 D.Limpiar todo()
 D.escribiendo("Puedes ...",0,0)
 D.escribiendo("Magia ???",0,1)
 muecero 1:
     SI Junco()==0:
         Todo el mundo()
     Demás:
         parada()

El contacto de la lengüeta debe estar sujeto de tal manera que podamos acercanos fácilmente a él con nuestro imán cuando coloquemos el árbol o la breadboard en la palma de la mano. Un guante negro fino nos ayuda a mantener el imán invisible. Lo más probable es que todos los que le rodean sean muggles.

El programa es muy sencillo. Ya conocemos todo hasta el programa principal. El bucle while se ejecuta infinitamente hasta que se desconecta la alimentación. Si el contacto cercano al imán está cerrado, GPIO13 está en potencial GND y todas las luces se encienden. De lo contrario, la resistencia incorporada en el módulo tira de GPIO13 a VCC = 3,3V y las luces se apagan.

De manera que la magia funcione mejor, el árbol con la breadboard debe ser alimentado por la batería. La conexión positiva de la batería se debe conectar al pin Vin/5V del ESP32. Además, el programa se debe cargar en el EPSP32 como boot.py para que el controladorse inicie de forma autónoma después de ser encendido. La forma de hacerlo se describe detalladamente en el Capítulo 2 - Autoarranque.

Para Arduino IDE

Descargar enchant.ino

8. Adviento y Navidad, el tiempo de "staade"

Al momento de traducir del alemán común, "Staad" significa algo así como "calma", "contemplativo". Sin embargo, la vida cotidiana nos enseña que, incluso en el período previo a la Navidad, las cosas se pueden poner bastante interesantes. Cuando las cosas se ponene demasiado turbulentas, el árbol nos recuerda que debemos bajar el volumen unos cuantos decibelios. ¿Cómo lo hacen? Bueno, hay un módulo de sonido que recoge el sonido y entrega la señal digitalizada al ESP32.

Figura 16: Volumen OK

Figura 16: Volumen OK

Figura 17: Demasiado ruidoso

Figura 17: Demasiado ruido

Figura 18: Máquina de sonido en el ESP32

Figura 18: Máquina de sonido en el ESP32

noisy.py

 # noisy.py
 importar ESP32
 de Os importar tu nombre
 de máquina importar Temporizador, Código PIN, I2C
 de Oled importar Oled
 de tiempo importar tiempo, dormir,
 
 
 I2C=I2C(-1,Scl=Código PIN(22),Sda=Código PIN(21))
 D=Oled(I2C)
 
 # IRQ de control por el módulo de sonido
 S t.=Temporizador(1)
 sonido=Código PIN(17,Código PIN.EN)
 #
 # Configurar capas LED *****************************
 Pin de capa = [32,33,25,27,26,12]
 L=len(Pin de capa)
 capa=[0]*L
 por I en trinquete(L):
     capa[I]=Código PIN(Pin de capa[I],Código PIN.FUERA)
     capa[I].valor(0)
 
 # Funciones define ***********************************
 def  cambiar(norte,Val):
     capa[norte].valor(Val)
 
 def parada():
     D.Limpiar todo()
     D.escribiendo("TODO ESTÁ BIEN",4,2)
     por I en trinquete(L):
         cambiar(I,0)
 
 def Todo el mundo():
     D.Limpiar todo()
     D.escribiendo("¡¡DEMASIADO ALTO!!",0,0)
     por I en trinquete(L):
         dormir(0.5)
         cambiar(I,1)
 
 def Sounddetected(código PIN):
     global norte
     SI código PIN==Código PIN(17):
         sonido.IRQ(manipulador=Ninguno)
         SI norte:
             regreso
         norte=Cierto
         S t..en eso(período=15000, Moda=Temporizador.Un trago, llamar de vuelta=Sounddone)
         impresión("Empezar",tiempo())
         Todo el mundo()
 
 def Sounddone(t):
     global norte
     norte=Falso
     impresión("fin",tiempo())
     parada()
     sonido.IRQ(manipulador=Sounddetected, desencadenar=Código PIN.Irq_fall)
 
 norte=Falso
 sonido.IRQ(manipulador=Sounddetected, desencadenar=Código PIN.Irq_fall)

El sonido se transmite por las rápidas fluctuaciones de presión de aire. Una señal de sonido se propaga a aproximadamente 340 m/s. En una habitación prácticamente sin ningún retraso perceptible. El micrófono del módulo de sonido convierte las fluctuaciones de presión en una señal eléctrica. Sin embargo, a diferencia del contacto de lengüeta, estas oscilaciones ya no se pueden reconocer consultando el puerto GPIO, este proceso es demasiado lento. Por lo tanto, aquí se utiliza una técnica diferente, interrumpir la programación. Una interrupción es la interrupción de un programa a través de un evento específico. Vamos a utilizar dos fuentes de interrupción diferentes. Se activa una interrupción cuando el nivel de un pin GPIO cambia de 0 a 1 o viceversa. La otra fuente de IRQ es un temporizador de hardware del ESP32. Activa la IRQ cuando la alarma suena.

Ahora ambos se turnan para pasarse el balón. El GPIO17 espera una señal del módulo de sonido. Si llega un flanco descendente, la función soundDetected() se inicia y comprueba primero si se debe al pin del parámetro pasado. Si n es True, entonces un ciclo ya está en marcha y no hay nada más que hacer. Si, por el contrario n es False, entonces se trata de una nueva orden. La IRQ de cambio de pin se desactiva y n se pone a True para suprimir los pulsos inmediatamente posteriores en GPIO17. A continuación, se inicia el temporizador, que especifica el tiempo de ejecución de la iluminación del árbol. La iluminación se enciende llamando a all().

Cuando el temporizador expira, se dispara la interrupción correspondiente, que inicia la función soundDone(). n se establece en False, las luces se apagan y la IRQ de cambio de pin se arma de nuevo.

El programa principal consiste en sólo dos líneas. n se establece en False para que la IRQ de cambio de pin activada posteriormente pueda ser disparada.

Lo interesante es que las IRQs están todavía activas, aunque el programa principal ya ha terminado. Para desactivarlo, se debe reiniciar el ESP32 con el botón STOP/RESTART.

Para Arduino IDE

Descargar noisy.ino u opcionalmente noisy_ticker_h.ino (con la biblioteca ticker.h)

Aquí se utilizaron dos variantes para implementar las interrupciones del temporizador. En el noisy.ino, sólo se comutan variables binarias en cada una de las dos rutinas de servicio de interrupción. El cambio se detecta entonces en el bucle principal normal. Como alternativa, puede incluir la biblioteca ticker.h. Sus ajustes son algo más fáciles de realizar. Está incluido en el núcleo del ESP32. No es necesario instalarlo por separado. Si no se encuentra durante la compilación, es posible que tenga que actualizar el núcleo ESP32.

9. Tras la pista del ladrón de árboles

Se supone que hay gente que roba su árbol de Navidad - del bosque. Pues bien, queridos silvicultores, ¿por qué no hacen como nosotros y construyen una guardia en sus árboles? Tal como la que se va a describir a continuación.

OK, es cierto que hay que admitir que esto será tan difícil como controlar otras prohibiciones si no hay personal. ¿Qué sentido tiene prohibir algo si no se puede controlar? Sea como fuere.

Nuestro árbol recibe un supervisor, es decir, él mismo. Se ayuda de un sensor que viene de una esquina totalmente diferente. El módulo GY-521 con el componente MPU6050 es un acelerómetro con giroscopio. Esto se puede utilizar para medir aceleraciones, fuerzas y rotaciones. Sí, y si quiere quitar algo, tiene que levantarlo y ponerlo en movimiento. En ambos casos, el objeto se acelera, incluso cuando se inclina.

Figura 19: La inclinación ligera es suficiente para activar la alarma.

Figura 19: Una ligera inclinación es suficiente para activar la alarma

Incluso cambios muy ligeros en la ubicación producen fuerzas y, por lo tanto, hacen que nuestro sensor responda. El resto es fácil, el disparo es seguido por la iluminación del árbol y con suerte el potencial ladrón huirá. Por cierto, una interrupción del temporizador es de nuevo responsable de la duración de la alarma.

Figura 20: Unidad antiklau

Figura 20: Unidad antirrobo

alarm.py

 # alarm.py
 # RED-ALLERT por el movimiento
 importar ESP32
 de Os importar tu nombre
 de máquina importar Temporizador, Código PIN, I2C
 de Oled importar Oled
 de tiempo importar dormir,Ticks_ms, Ticks_us, Sleep_ms
 de Gy521rc importar GY521
 
 # Inicializar las interfaces **********************
 I2C=I2C(-1,Scl=Código PIN(22),Sda=Código PIN(21))
 D=Oled(I2C)
 
 A=Temporizador(0)
 acc=GY521(I2C)
 límite=36
 duración=5000
 
 Pin de capa = [32,33,25,27,26,12]
 L=len(Pin de capa)
 capa=[0]*L
 por I en trinquete(L):
     capa[I]=Código PIN(Pin de capa[I],Código PIN.FUERA)
     capa[I].valor(0)
 
 # Funciones define ***********************************
 def Se acabó el tiempo(t):
     empezar=Ticks_ms()
     def comparar():
         regreso En t(Ticks_ms()-empezar) >= t
     regreso comparar
 
 def  cambiar(norte,Val):
     capa[norte].valor(Val)
 
 def parada():
     D.Limpiar todo()
     D.escribiendo("TODO ESTÁ BIEN",4,2)
     por I en trinquete(L):
         cambiar(I,0)
 
 def Todo el mundo():
     D.Limpiar todo()
     D.escribiendo("HURTO",0,0)
     por I en trinquete(L):
         dormir(0.5)
         cambiar(I,1)
 
 def se ha movido(demora):
     xs,ys,ZS=0,0,0
     por I en trinquete(100):
         X,y,Z=acc.getXYZ()
         xs+=X
         ys+=y
         ZS+=Z
     xs//=100
     ys//=100
     ZS//=100
     #print (xs, ys, zs)
     norte=0
     muecero 1:
         X,y,Z=acc.getXYZ()
         X=Sección(xs-X)
         y=Sección(ys-y)
         Z=Sección(ZS-Z)
         #print (x, xs // límite)
         SI X > Sección(XS//límite) :
             impresión("*******",norte)
             norte+=1
             Todo el mundo()
             # Mensaje facultativo a través de UDP
             A.en eso(período=demora, Moda=Temporizador.Un trago, llamar de vuelta=alerta a cabo)
         dormir(0.3)
 
 def alerta a cabo(t):
     parada()
 
 impresión("Antirrobo comenzó")
 se ha movido(duración)

De nuevo, hay buenos conocidos en el programa. Sin embargo, la novedad es la inicialización del GY521. Para este módulo, tenemos que subir otro módulo al ESP32, el gy521rc.py. La clase que contiene el mismo nombre que el módulo.

Al igual que la pantalla OLED, el GY521 también funciona a través del bus I2C. Pasamos el mismo objeto I2C al constructor, establecemos el umbral de activación de la alarma y su duración en milisegundos.

El umbral es la cantidad absoluta de desviación del valor medido de la medición de la aceleración en la dirección x. El sensor está alineado de manera que el eje x positivo apunta verticalmente hacia arriba. El valor medido se sitúa en torno a los 16.000 recuentos y corresponde en este caso a la aceleración debida a la gravedad g = 9,81 m/s².

La función hasMoved() representa aquí el bucle principal. Al entrar, el valor medio se determina mediante 100 mediciones. Está claro que el sensor no se debe mover.

Luego pasa al bucle principal. Se mide la aceleración actual y se calculan las desviaciones de los valores medios. Si la diferencia supera el límite predeterminado, se dispara una alarma y se activa el temporizador. La alarma significa que el árbol a alcanzado su máximo rendimiento.

La rutina de servicio de la IRQ del temporizador apaga las luces. La solución a través de la IRQ asegura que el circuito se arme de nuevo inmediatamente después de que se active la alarma. Si la duración de la alarma se especificará mediante un comando de reposo en el bucle principal, el circuito estaría muerto durante esa duración.

Los contactos vibratorios que se mencionaron en la lista de piezas se conectarían al ESP32 de forma similar al contacto de lengüeta, pero no permiten ajustar la sensibilidad.

Para Arduino IDE

Descargar alarm.ino

Para el sensor del giroscopio, se incluye la biblioteca GY521. También se puede instalar a través de la administración de la biblioteca. Además, aquí también se utiliza la biblioteca Ticker.h. A diferencia de la plantilla de MicroPython, aquí se consideran todos los ejes del sensor.

Si no está seguro de qué dirección I2C utiliza el sensor, puede cargar el programa I2C_Scanner.ino en el ESP. En este caso, deben aparecer dos direcciones en el monitor de serie (para la pantalla y el sensor). En el propio sensor tiene la posibilidad de elegir entre las direcciones 0x68 y 0x69. Tiene que conectar el pin A0 a GND o a 3,3V del ESP.

10. Tener una estancia agradable ESP32 y DHT22

Un clima agradable en la habitación forma parte del ambiente festivo. Ahora, en esta sencilla aplicación, el ESP32 no puede cambiar el clima de la habitación, pero puede informar sobre él. Los valores exactos de temperatura y humedad se muestran en la pantalla OLED, los valores aproximados los indica el árbol. En niveles de 2 grados, informa de los valores de la temperatura ambiente a través de diferentes números de niveles de LEDs encendidos.

Figura 21: Temperatura media - Media Iluminación

Figura 21: Temperatura media - media Iluminación

Figura 22: Medición de temperatura y humedad en un módulo.

Figura 22: Medición de temperatura y humedad en un solo módulo

Existen 2 variantes de DHT22, también conocido como AM2302. El módulo de la figura de la izquierda ya contiene la resistencia pull-up necesaria para el bus One-Wire, que, por cierto, no se debe confundir con el sistema del módulo Dallas DS18B20. El bus de Dallas tiene un horario completamente diferente. Para la versión desnuda de la figura de la derecha, se debe instalar una resistencia de 4,7 kΩ a 10k contra Vcc.

El funcionamiento del programa es muy sencillo. Los tres comandos necesarias los proporciona el módulo DHT ya integrado en MicroPython.

roomclimate.py

 importar ESP32, DHT
 de Os importar tu nombre
 importar sys
 de máquina importar Alfiler, I2C
 de oled importar Oled
 de tiempo importar dormir
 
 # Inicialisieren der Schnittstellen **********************
 I2C=I2C(-1,scl=Alfiler(22),sda=Alfiler(21))
 D=Oled(I2C)
 
 gusto=Alfiler(0,Alfiler.EN,Alfiler.LEVANTAR)
 dhtpin=Alfiler(13)
 DHT22=dht.DHT22(dhtpin)
 
 # LED-Schichten Einrichten *******************************
 schichtpin = [32,33,25,26,27,12]
 schicht=[0]*6
 por I en distancia(6):
     schicht[I]=Alfiler(schichtpin[I],Alfiler.FUERA)
     schicht[I].valor(0)
 
 # FUNKTIONEN DEFNIEREN ***********************************
 def  cambiar(norte,Val):
     schicht[norte].valor(Val)
 
 def parada():
     D.irritante("TEMPO A BAJO",4,2)
     por I en distancia(6):
         cambiar(I,0)
 
 def allar():
     por I en distancia(6):
         sleep_ms(300)
         cambiar(I,1)
         
 def árbol(norte):
     por I en distancia(6):
         si I <=norte:
             cambiar(I,1)
         demás:
             cambiar(I,0)
     
 # HauptProgramm ********************************************
 D.limpiar todo()
 D.irritante("*** RAUMKLIMA ***",0,0)
 tiempo Cierto:
     dormir(0.3)
     DHT22.la medida()
     t=DHT22.temperatura()
     h=DHT22.humedad()
     D.correcto(0,10,126,38,1)
     D.clebre(1,2,14,3)
     D.irritante("TEMP: {: .1F} * c".formato(t),1,2)
     D.irritante("HUM: {: .1F}%".formato(h),1,3)
     árbol(En t(((t-15)//2)%6))
     dormir(2.7)

Aparte de los sospechosos habituales, el programa sólo ofrece la importación del módulo dht, la instalación del objeto dht22 y el bucle principal con la tarea de medición dht22.measure() y la lectura de los valores de temperatura y humedad. Ya conocemos la salida en la pantalla y la visualización del árbol. Interesante y poco llamativo es quizás la conversión de la temperatura de °C al índice del nivel de iluminación.  Por el término int(((T-15) // 2)% 6). A partir del valor de la desviación de la temperatura de  15 °C hacia arriba y  2, se determina el resto de la división 6 y se representa como un número entero para estar seguros. Una vez más, muy lentamente.

Ejemplo:
t = 18 ° C
18-15 =3
3//2 = 1
1% 6 = 1 por lo tanto índice de paso 1

para 28 °C el resultado sería: 28-15 = 13; 13 // 2 = 6; 6% 6 = 0; el último paso es necesario porque no hay ninguna etapa con el número 6.

Para Arduino IDE

Descargar roomclimate.ino

Para este sensor, por favor, instale la biblioteca de sensores DHT y la biblioteca de sensores unificada de Adafruit a través de la gestión de la biblioteca. A diferencia de Python, en C/C++ hay que prestar mucha atención a los tipos de datos. Los valores medidos del sensor se devuelven de tipo float. En consecuencia, se debe configurar la salida con formato y también el cálculo para controlar los LEDs puede ser defectuoso si se omite el tipo de datos.

11. El sorteo de Navidad(algo diferente) 

Todavía lo sé de mis días de escuela. Todo el mundo trajo un paquete durante el Adviento y en la semana anterior a las vacaciones se puso en marcha la rifa: cada boleto gana.

Elegí tarjetas neutras RFID como los billetes reciclables. El sorteo lo realiza el ESP32 junto con el kit RFID. Sólo tiene que ocuparse de los premios usted mismo. Por supuesto, el árbol también está incluido. A través de la luminosidad, anuncia su premio al respectivo jugador. Para que no haya dudas sobre la interpretación, la pantalla indica de forma inequívoca la ubicación de cada sorteo: Friburgo, Berlín, Hamburgo... se necesitan 6 billetes de lotería y una tarjeta maestra.

Figura 23: La altura del número de disparo determina la fuerza luminosa.

Figura 23: La altura del número de aciertos determina la intensidad de la luz

Figura 24: Lotería

Figura 24: Lotería

Figura 25: Lector de tarjetas RFID

Figura 25: Lector de tarjetas RFID

Debido al bus SPI, el cableado es algo más complejo que con el bus I2c con sus dos líneas. Los dispositivos del bus SPI no tienen una dirección de dispositivo por hardware, pero sí tienen una conexión de selección de chip que se debe ajustar a LOW si el dispositivo va a ser direccionado. La transferencia de datos también es algo diferente; los datos siempre se envían y reciben simultáneamente. No es necesario aclarar el procedimiento aquí, porque la clase MFRC522 lo hace por nosotros. Sólo le decimos al constructor las asignaciones de los puertos y la velocidad de transferencia. La transferencia funciona con una velocidad de 3,2 MHz. A modo de comparación, I2C funciona a 400 kHz.

La función readUID() lee el identificador único de la tarjeta y lo devuelve como un valor hexadecimal y como un número decimal. Las tarjetas se solicitan a través de la pantalla OLED. Para evitar que la función bloquee todo el proceso, un tiempo de espera asegura una retirada ordenada. En este caso, se devuelve el valor Ninguno en lugar del ID de la tarjeta.

Figura 26: Tarjetas RFID y chip

Figura 26: Tarjetas y chip RFID

Para que las tarjetas de lote entren en juego, necesitamos una tarjeta maestra. Para ello, cogemos cualquier tarjeta o chip de la pila, leemos el ID y lo utilizamos para asignar la variable con el valor decimal justo al principio del programa:

MasterID = 4217116188

Cuando el ESP32 se pone a trabajar por primera vez, detecta que aun no existe un archivo con los datos de la tarjeta de lote y solicita la tarjeta maestra. Una vez reconocido esto, se solicita una tarjeta de lote. Después de leer el ID, se escribe en el archivo y se solicita de nuevo la tarjeta maestra. La lectura continúa hasta que se lee la última carta del lote. Si no se ofrece ninguna tarjeta de lote durante 10 segundos después de solicitar la tarjeta maestra, el sistema se reinicia. El requisito previo para ello es que el programa rfid.py haya sido enviado al ESP como boot.py. El Capítulo 2 - Autoarranque explica exactamente cómo hacerlo. Para empezar completamente desde cero, podemos eliminar el archivo slavecards.txt con los ID de las tarjetas de lote a través de la consola de Thonny. Después de un reinicio, las tarjetas de lote se pueden volver a leer.

rfid.py

 # rfid.py
 # Workes con RC522 13,2MHz
 importar mfrc522
 importar ESP32, DHT
 de Os importar tu nombre
 de máquina importar Temporizador, Código PIN, I2C, ADC, Reiniciar
 de Oled importar Oled
 de tiempo importar dormir,Ticks_ms, Ticks_us, Sleep_ms
 de gy521 importar GY521
 
 # Inicializar las interfaces **********************
 SI tu nombre()[0] == 'Esp32':
     # Sck, MOSI, miso, cs = SDA
     rdr = mfrc522.MFRC522(14,  16,   15,   5, velocidad de transmisión=3200000)
 elif tu nombre()[0] == 'Esp8266':
     # Sck, MOSI, miso, cs = SDA
     # D3 D4 D5 D2
     rdr = mfrc522.MFRC522(0,   2,    4,    14, velocidad de transmisión=100000)
 Demás:
     aumentar Error de tiempo de ejecución("La plataforma no compatible")
 Identificación maestra=4217116188  # 0XFB5C161C
 
 I2C=I2C(-1,Scl=Código PIN(22),Sda=Código PIN(21))
 D=Oled(I2C)
 
 Pin de capa = [32,33,25,27,26,12]
 capa=[0]*6
 por I en trinquete(6):
     capa[I]=Código PIN(Pin de capa[I],Código PIN.FUERA)
     capa[I].valor(0)
 lucro=[
         "Freiburg",
         "Berlina",
         "Hamburgo",
         "Augsburgo",
         "Ratzeburgo",
         "Erfurt",
         "Come",
         "Bonn",
        ]
 # Funciones define ***********************************
 def Se acabó el tiempo(t):
     empezar=Ticks_ms()
     def Comparar():
         regreso En t(Ticks_ms()-empezar) >= t
     regreso Comparar
 
 def readUID(monitor,boardtype,se acabó el tiempo):
     monitor.Clebre(0,1,15,show=Falso)
     monitor.escribiendo("Ponerse"+boardtype,0,1)
     leer la interrupción=Se acabó el tiempo(se acabó el tiempo)
     muecero angustia leer la interrupción():
        (stat, tag_type) = rdr.solicitud(rdr.REQIDL)
         SI stat == rdr.OK:
            (stat, raw_uid) = rdr.anticoll()
             SI stat == rdr.OK:
                 monitor.Clebre(0,2,15,show=Falso)
                 monitor.escribiendo("Tarjeta OK",0,2)
                 dormir(1)
                 ID de usuario=0
                 por I en trinquete(4):
                     ID de usuario=(ID de usuario<<8) | raw_uid[I]
                 userIds="{: # X}".formato(ID de usuario)
                 impresión(userIds)
                 regreso ID de usuario,userIds
     regreso Ninguno
 
 def adduid(monitor):
     monitor.Limpiar todo()
     metro=readUID(monitor,"Maestría",3000)
     SI metro es angustia Ninguno:
         medio,_= metro
         SI medio==Identificación maestra:
             dormir(3)
             usted=readUID(monitor,"Tarjeta del Esclavo",3000)
             SI usted es angustia Ninguno:
                 UID,UID=usted
                 SI UID es angustia Ninguno y UID != Identificación maestra:
                     con abierto("Slavecards.txt","A") como F:
                         F.escribir("{} \ N".formato(UID))
                         monitor.irritante("Nuevo esclavo escrito",0,3)
                         dormir(3)
                         regreso Cierto
             demás:
                 monitor.irritante("¡¡¡ERROR!!!",0,3)
                 monitor.irritante("¡Tarjeta no añadida!",0,4)
                 regreso Falso
         demás:
             monitor.irritante("¡¡¡ERROR!!!",0,3)
             monitor.irritante("NO MASTERCARD",0,4)
             dormir(3)
     regreso Falso
 
 def  cambiar(norte,Val):
     schicht[norte].valor(Val)
 
 def parada():
     D.irritante("ADIÓS",4,2)
     por I en distancia(6):
         cambiar(I,0)
 
 def allar():
     por I en distancia(6):
         sleep_ms(300)
         cambiar(I,1)
         
 def árbol(norte):
     por I en distancia(6):
         si I <=norte:
             cambiar(I,1)
         demás:
             cambiar(I,0)
     
 # ******************* hauptprogramm *********************
 D.limpiar todo()
 D.irritante("* Lotterie de Navidad *",0,0)
 D.correcto(0,20,127,28,1)
 tarjetas=[]
 tratar:
     con abierto("SlavoCards.txt","r") como F:
         por línea en F:
             tarjetas.adjuntar(línea.banda("\norte"))
     cerrado=Se acabó el tiempo(60000)
     tiempo no cerrado():
         usted=readuid(D,"Loskarte",5000)
         D.clebre(1,3,14,4,Falso)
         si usted es no Ninguno:
             uid,uids=usted
             tratar:
                 norte=tarjetas.índice(uids)
                 D.irritante("Treffer {}".formato(norte),1,3, Falso)
                 D.irritante(gewinn[norte],1,4)
             excepto ValueError como mi:
                 D.irritante("Trospreis",1,3)
                 norte=-1
             árbol(norte)
             cerrado=Se acabó el tiempo(60000)
             dormir(10)
             parada()
 excepto Oserror como mi:
     impresión("¡Keine Datei, Keine Daten!")
     Todo leido=Se acabó el tiempo(10000)
     tiempo no Todo leido():
         si adduid(D):
             Todo leido=Se acabó el tiempo(10000)
     impresión("Alle karten eingelesen und gespeichert")
     D.clebre(0,3,15,4,Falso)
     D.irritante("Todas las cartas leen",0,3)
     D.irritante("**REINICIAR**",0,4)
     Reiniciar()
 D.clebre(0,1,15,3,Falso)
 D.irritante("Lotterie Neu",0,2)
 D.irritante("Starten",0,3)

Para un ciclo de juego, se determinan 6 victorias, se barajan y distribuyen las 6 cartas y se inicia la nueva ronda con el botón PROG del ESP32.

Para arduino IDE

Descargar rfid.ino

Nota: en este caso se deben cambiar las conexiones a los pines del Esp32. La razón es que se utiliza. la interfaz SPI de hardware. Sus pines no se pueden cambiar.

MOSI = 23
MISO = 19
SCK = 18

SDA= 5
RST = 17

Para el escáner RFID, instale la biblitoeca MFRC522.

Para una comparación directa con MicroPython, puede cambiar esta línea para no tener que cambiar los pines cada vez:

rdr = mfrc522.Mfrc522(14,  16,   15,   5, baudiar=3200000)

en

rdr = mfrc522.Mfrc522(1823,   19,   5, baudiar=3200000)

Para almacenar el archivo de texto con las identificaciones, se crea un sistema de archivos en la memoria flash del ESP utilizando la biblioteca LittleFS (el sucesor de SPIFS). Los archivos se pueden almacenar allí. La biblioteca es ahora parte del núcleo de ESP32. Tampoco es necesario instalarlo por separado. El programa está escrito de tal manera que no es necesario editar el archivo de texto en el PC.

Si todavía quiere hacer esto, puede instalar el plugin de carga de ESP32. Sin embargo, el intercambio de datos sólo funciona en una dirección (como su nombre indica).

La estructura del programa cambiado un poco aquí. Sin embargo, el comportamiento del programa debe ser el mismo. Se han añadido algunas funciones. Se puede leer en la tarjeta maestra cuando se inicia el programa. También es posible eliminar el archivo de texto del flash. Para ello, puede conectar un cable o un botón a GND en el pin indicado (consulte código fuente). Manténgalo pulsado y reinicie el ESP. A continuación, el archivo se eliminará si existe. Después, desconecte y vuelva a leer las cartas ganadoras. El número máximo de tarjetas ganadoras corresponde a los niveles de LED del árbol de Navidad. Si desea utilizar menos tarjetas, puede esperar el tiempo de espera durante el proceso de lectura.

12. El árbol en LAN/WLAN

Hacemos la docena completa y conectamos el árbol a la red. Porque si se utiliza un ESP32 para el control, entonces también debe haber un acceso LAN o WLAN para el control. Decidí implementar un servidor web en el ESP32 porque así se pueden controlar los niveles del árbol con casi cualquier navegador. Otra posibilidad habría sido un servidor UDP en el controlador y una aplicación para el teléfono móvil. Sin embargo, esto habría ido más allá del alcance de este blog, así que me he abstenido de hacerlo. Para los interesados, ya he descrito este tipo de control en otras publicacicones, por ejemplo aquí y aquí.

Para el circuito, utilizamos la estructura del capítulo 5, a la que añadimos un LED RGB y tres resistencias de 1,0 kOhm.

Figura 27: Estructura web

Figura 27: Estructura de la web

Tras importar los módulos necesarios, definimos los pines para el LED RGB, que nos indica el estado de la red de forma visible a distancia. Luego seleccionamos el modo de red, WLAN o el punto de acceso propio del ESP32. WLAN es la configuración por defecto para acceder al router WLAN, también se debe introducir aquí los datos de acceso. La definición de los niveles se amplía con tres listas, texto plano para activar/desactivar, color de fondo para la tabla en la página web y los estados de conmutación de los niveles.

En las funciones se han eliminado las de bloqueo, swell(), swell(), wave() y tree(). Se han añadido hexMac(), blink(), ledsOff() y web_page(). hexMac emite la dirección MAC del ESP32 en modo estación, blink() señala los estados de red y servidor. ledsOff() apaga el LED RGB y web_page() recoge las solicitudes del navegador, ejecuta las órdenes y devuelve una respuesta como texto de la página web.

La solicitud del navegador va al servidor como una cadena de consulta. La cadena tiene la forma ? a, ? pag o e=x & v=y. En él, x representa el número de nivel e y el estado de conmutación, 0 o 1.

web_page() convierte la solicitud en mayúsculas, primero comprueba si hay "A" y "P". Si la solicitud contiene más de 2 caracteres, intenta determinar el nivel y el estado de conmutación. Si se produce un error, no se desencadena ninguna acción y se llama a la página de inicio desnuda. Esto también ocurre si no se ha especificado ninguna cadena de consutla. Después, la página web se construye como una cadena y se devuelve al bucle principal.

Tras las definiciones de las funciones, se establece la conexión de red, ya sea como punto de acceso independiente o como conexión al router WLAN. Esto se controla con las dos variables ownAP y WLANconnect. En ambos casos, se asigna una dirección IP fija (10.0.1.181), ya que se trata de un servidor. Las direcciones dinámicas del router WLAN no son adecuadas, ya que pueden cambiar de vez en cuadno. La conexión con el router está marcada por el parpadeo del LED azul. La pantalla nos informa de que la conexión está establecida y también de que el socket de conexión está listo para aceptar solicitudes.

En el bucle principal, el bucle de recepción de método accept() espera una solicitud. Si no llega nada antes del tiempo de espera, accept() lanza una excepción, que capturamos con el intento anterior.

Si hay una solicitud, entonces accept() devuelve un socket de comuncación C y la dirección de la máquina solicitante. C se utiliza para gestionar el intercambio de datos entre el cliente y el servidor, mientras que vuelve a estar libre para aceptar más solicitudes entrantes. El método c.recv() devuelve el texto de la solicitud, del que sólo nos interesan los primeros caracteres. En la fase de desarrollo, se pueden introducir solicitudes web_page () a mano para probar el parser. ownAP y WLANconnect deben estar ambos en False.

La solicitud del objeto byte del texto recibido se decodifica ahora en una cadena r, que es más fácil de manejar. Buscamos un "GET /" al principio de la cadena r y la posición en la que sigue "HTTP". Si se encuentran ambos, aislamos el texto después del "/" de "GET" hasta antes del espacio de "HTML" y lo enviamos como cadena de consulta al analizador web_page(). Recibimos su respuesta en la variable respuesta. A continuación, enviamos la cabecera HTML y el texto de la página HTML con la respuesta contenida de vuelta al llamante. Los siguientes dos else y el except sirven para atrapar y manejar posibles errores. La función final c.close(), que cierra el socket de comunicación c, es importante.

Después de una consulta clave para terminar el programa, el LED verde nos presenta con su breve parpadeo como un latido del corazón que el sistema sigue vivo.

webcontrol.py

 # webcontrol.py
 # Control remoto desde el navegador a través de TCP
 # (C) 2021 Jürgen Grzesina
 # Liberado bajo la Licencia-(con)
 # http://www.grzesina.de/az/wehnachtbaum/mit-license.txt
 #
 de máquina importar Código PIN, I2C
 de Oled importar Oled
 
 # ******************** materia red ********************
 de tiempo importar dormir,Ticks_ms, Sleep_ms
 tratar:
   importar aullido as enchufe
 excepto:
   importar enchufe
 importar Ubinascii
 importar la red
 
 statusLED=Código PIN(18,Código PIN.FUERA,valor=0) # 2 = azul
 onairled=Código PIN(19,Código PIN.FUERA,valor=0)  # GRUEN = 1
 Errorled=Código PIN(23,Código PIN.FUERA,valor=0)  # Rojo = 0
 dirigió=[Errorled,onairled,statusLED ]
 rojo,Verde,azul=0,1,2
 solicitante = matriz de bytes(50)
 respuesta=""
 botón=Código PIN(0,Código PIN.EN,Código PIN.Levantar)
 
 # Selección del modo de funcionamiento de la red o el teclado:
 # --------------------------------------------------------
 # Red: poner exactamente _A_! Variable sobre cierto
 Wirisconnect=Cierto  # Conexión de red a través de WLAN locales
 Ownap=Falso       # Conexión de red a través del propio accesssppoint
 Tanto # Falso - entrada >> comandos a través de la PC + USB en fase de prueba
 # Si wirisconnect = true:
 # Introduzca las credenciales de su punto de acceso Wi-Fi aquí
 mísido = 'Your_ssid'; mi hombre = "TU CONTRASEÑA"
 mi IP="10.0.1.181"
 myport=9002
 
 # Inicializar las interfaces **********************
 I2C=I2C(-1,Scl=Código PIN(22),Sda=Código PIN(21))
 D=Oled(I2C)
 
 #schlichtpin = [32,33,25,27,26,12] # ordenada
 Pin de capa = [32,26,33,27,25,12]   # distribuido
 capa=[0]*6
 por I en trinquete(6):
     capa[I]=Código PIN(Pin de capa[I],Código PIN.FUERA)
     capa[I].valor(0)
 Estado=["el fin","a "]
 color=["rojo","Verde claro"]
 inmuebles=[0,0,0,0,0,0]
 
 connectstatus = {
     1000: "Stat_idle",
     1001: "Stat_connecting",
     1010: "Stat_got_ip",
     202:  "Stat_wrong_password",
     201:  "No se encontró ap",
     5:    "GOT_IP"
    }
 
 # Funciones define ***********************************
 def Se acabó el tiempo(t):
     empezar=Ticks_ms()
     def Comparar():
         regreso En t(Ticks_ms()-empezar) >= t
     regreso Comparar
 
 def  cambiar(norte,Val):
     capa[norte].valor(Val)
 
 def parada():
     D.escribiendo("Todos los LED apagados",2,5)
     por I en trinquete(6):
         cambiar(I,0)
 
 def Todo el mundo():
     D.escribiendo("Todos los indicadores LED",2,5)
     por I en trinquete(6):
         Sleep_ms(300)
         cambiar(I,1)
         
 def árbol(norte):
     D.escribiendo("Progr árbol.",2,5)
     por I en trinquete(6):
         SI I <=norte:
             cambiar(I,1)
         Demás:
             cambiar(I,0)
 
 def hexmac(bytemac):
   """
  La función Hexmac toma la dirección MAC en el código de bytes
  y extrae una cadena para el regreso
  """
   macstring =""
   por I en trinquete(0,len(bytemac)):     # Para todos los valores de byte
     macstring += maleficio(bytemac[I])[2:]  # Desde la posición 2 hasta el final
     SI I <len(bytemac)-1 :            # delimitador
       macstring +="-"
   regreso macstring
 
 def parpadear(legumbres,Espere,color,invertida=Falso):
     SI invertida:
         DIRIGIÓ[color].apagado()
         dormir(legumbres)
         DIRIGIÓ[color].sobre()
         dormir(Espere)
     Demás:
         DIRIGIÓ[color].sobre()
         dormir(legumbres)
         DIRIGIÓ[color].apagado()
         dormir(Espere)
 
 def LEDsOFF():
     por I en trinquete(3):
         DIRIGIÓ[I].Valor(0)
 
 Elemento de decisión Página web(Q):
     Global Bienes Raíces
     Q=Q.Ascendente()
     Imprimir("Solicitud:,Q)
     Si Q=="A":
         Todo()
         Para I Y Ámbito de aplicación(6):
             Bienes Raíces[I]=1
     De lo contrario, si Q=="P":
         Stop()
         Para I Y Ámbito de aplicación(6):
             Bienes Raíces[I]=0
     De lo contrario, si Lang(Q)>2:
         3.:
             Nivel,Estado=Q[1:].División("&")
             _,Nivel= Nivel.División("=")
             _,Estado= Estado.División("=")
             Nivel=(Int(Nivel) Si 0<=Int(Nivel)<=5 Tiempo estimado de despegue 0)
             Estado=(Int(Estado) Si 0<=Int(Estado)<=1 Tiempo estimado de despegue 0)
             Conversión(Nivel,Estado)
             Bienes Raíces[Nivel]=Estado
         Excepto:
             Pasaporte
     Tiempo estimado de despegue:
         Pasaporte
     Respuesta="< tr >"
     Para I Y Ámbito de aplicación(6):
         H="< TD bgcolor = {} > < H3 > e {} {}}. < H3 > < td >".Formato(Color[Bienes Raíces[I]],I, Condición[Bienes Raíces[I]])
         Respuesta=Respuesta+H
     Respuesta=Respuesta+"< / TR >"
     Html1 = "" < html >
  < Head >
  < meta name = "ViewPort" Content = "width = device width, initial scale = 1" >
  < / head >
  < cuerpo >
  Hola, soy tu regalo de Navidad.
     Html2="" < border of table = 2 Cell Space = 2 >
    """
     Html3="""
  < tr >
  < td >
  < a href = " http://10.0.1.181:9002/?e=0&v=1 « > < H3 > e0an < / h3 > < / a >
  < / td >
  < td >
  < a href = " http://10.0.1.181:9002/?e=1&v=1 « > < H3 > e1an < / h3 > < / a >
  < / td >
  < td >
  < a href = " http://10.0.1.181:9002/?e=2&v=1 « > < H3 > E2 - an < / h3 > < / a >
  < / td >
  < td >
  < a href = " http://10.0.1.181:9002/?e=3&v=1 « > < H3 > E3A < / h3 > < / a >
  < / td >
  < td >
  < a href = " http://10.0.1.181:9002/?e=4&v=1 "> < H3 > E4A < / h3 > < / a >
  < / td >
  < td >
  < a href = " http://10.0.1.181:9002/?e=5&v=1 « > < H3 > e5a < / h3 > < / a >
  < / td >
  < td >
  < a href = " http://10.0.1.181:9002/?a "> < H3 > abrir todo < / h3 > < / a >
  < / td >
  < / TR >
  < tr >
  < td >
  < a href = " http://10.0.1.181:9002/?e=0&v=0 « > < H3 > E0 de < / h3 > < / a >
  < / td >
  < td >
  < a href = " http://10.0.1.181:9002/?e=1&v=0 « > < H3 > E1 from < / h3 > < / a >
  < / td >
  < td >
  < a href = " http://10.0.1.181:9002/?e=2&v=0 "> < H3 > E2 from < / h3 > < / a >
  < / td >
  < td >
  < a href = " http://10.0.1.181:9002/?e=3&v=0 « > < H3 > E3 from < / h3 > < / a >
  < / td >
  < td >
  < a href = " http://10.0.1.181:9002/?e=4&v=0 "> < H3 > E4 from < / h3 > < / a >
  < / td >
  < td >
  < a href = " http://10.0.1.181:9002/?e=5&v=0 « > < H3 > E5 Australia < / h3 > < / a >
  < / td >
  < td >
  < a href = " http://10.0.1.181:9002/?p Todas las regiones de Australia
  < / td >
  < / TR >
    """
     Html9 = "< TABLE > < / BODY > < / html >"
     Html=Html1+Html2+Respuesta+Html3+Html9
     Return Html
 
 Si Clave.Valor()==0:
     Imprimir("Abortar usando flashkey")
     Ledsov()
     D.Escribir("Cancelar D. Usuario,0,5)
     Sistema.Exportación()    
 
 # ********************************************************
 "35", creación de redes,
 # ********************************************************
 "35; puntos de acceso propios
 # ********************************************************
 Si Onap Y (No. Conexión inalámbrica):
     #
     Nada. = Red.Red inalámbrica(Red.AP IF)
     Nada..Activos(Sí, claro.)
     Página="Otoño"
     Passwd="No me importa"
 
     « 35; comenzando con el punto de acceso
     Nada..Orden((Myip,"255.255.255.0",Myip,\
                   Myip))
 
     Imprimir(Nada..Orden())
 
     Modo de autenticación distinto de 0 no soportado
     Nada..Configuración(Automóvil=0)
 
     Impermeable=Nada..Configuración("Mac") 35; devuelve un objeto Byte
     "35; convertir a dos dígitos
     Impermeable=Bebé.Huxley.(Impermeable,"-").Decodificar("UTF - 8")
     Imprimir(Impermeable)
     Nada..Configuración(Eid=Página, Contraseña=Passwd)
 
     Aunque No. Nada..Activos():
       Imprimir(".",Fin="")
       Dormir(0.5)
 
     Imprimir("Escucha unida")
 Establecer el final del punto de acceso
 
 # ********************************************************
 « 35; conexión WLAN
 # ********************************************************
 Si Conexión inalámbrica Y (No. Onap):
     Nada. = Red.Red inalámbrica(Red.Si el Estado) « 35; crear objetos wifi
     Nada..Activos(Sí, claro.)  "35; no abrir nada
     #
     Impermeable = Nada..Configuración(Impermeable.)  35; recuperar la Dirección MAC binaria
     McGrady=Hecksmark(Impermeable)        Convertir en secuencia hexadecimal
     Imprimir("Estación Mac: \ \ t"+McGrady+"\ n") « 35; gastos
     AP conectado a la red local
     Si no está conectado, entonces
     « 35; conectar a lan - AP
     Si No. Nada..Desconexión():
       Nada..Conexión(Paja, Mi pase)
       # bis warten mueren Verbindung zum Accesspoint steht
       impresión("Estado de conexión: ", nic.está conectado())
       tiempo no nic.está conectado():
         parpadear(0.8,0.2,0)
         impresión("{}.".formato(nic.estado()),fin='')
         dormir(1)
     # Zeige Verbindungsstatus & config-Daten
     impresión("\ Nconnected:",nic.está conectado())
     impresión("\ NVerbindungsstatus:",connectstatus[nic.estado()])
     impresión("Weise neue IP zu:",mi IP)
     nic.ifconfig((mi IP,"255.255.255.0",mi IP, \
                   mi IP))
     STAconf = nic.ifconfig()
     impresión("STA-IP: \ t \ t",STAconf[0],"\ NSTA-NETMASK: \ t",\
           STAconf[1],"\ NSTA-PUERTA DE ENLACE: \ t",STAconf[2] ,sep='')
 
 # *********** Router Setup extremo de conexión ***************
 
 # ********************************************************
 # TCP-Web - Servidor
 # ********************************************************
 # ----------------- starten servidor --------------------------
 si WLANconnect o ownAP:
     s = enchufe.enchufe(enchufe.AF_INET, enchufe.SOCK_STREAM)
     s.setsockopt(enchufe.SOL_SOCKET,enchufe.SO_REUSEADDR,1)
     s.unir(('', MyPort))
     impresión("Socket estableció, a la espera en el puerto",MyPort)
     D.limpiar todo()
     #         0123456789012345
     D.irritante("CALCETÍN DE APERTURA",0,0)
     D.irritante("Para escuchar",0,1)
     D.irritante(mi IP+":"+str(MyPort),0,2)
     s.setTimeout(0.9)
     s.escucha(2)
     
 si gusto.valor()==0:
     impresión("Abgebrochen Mit Flashtaste")
     ledsOff()
     D.irritante("Abbruch d. Usuario",0,5)
     sys.Salida()
 
 # ------------------- Serverschleife ----------------------
 tiempo Cierto:
     tratar:  # Wegen tiempo de espera
         r=""
         si WLANconnect o ownAP:
             C, addr = s.aceptar()
             impresión('¿Tiene una conexión de {} {} \ n'.\
                   formato(addr[0],addr[1]))
             solicitud=C.recv(1024)
         demás:
             solicitud=aporte("Kommando:")
             addr="999.999.999.999:99999"
         tratar:  # Decodieren und Parsen
             r=solicitud.descodificar("UTF-8")
             getPos=r.encontrar("OBTENER /")
             si r.encontrar("Favicon")==-1:
                 impresión("***********************************")
                 impresión("Posición:",getPos)
                 impresión("Solicitud:")
                 impresión(r)
                 impresión("***********************************")
                 POS=r.encontrar("HTTP")
                 si getPos == 0 y POS != -1:
                     consulta=r[5:POS] # Nach? bis HTTP
                     impresión("********* CONSULTA: {} ********* \ n \ n".\
                           formato(consulta))
                     respuesta = Página web(consulta)
                     impresión("---------------\norte",respuesta,\
                           "\norte----------------")
                     C.enviar('HTTP / 1.1 200 OK \ n'.codificar())
                     C.enviar('Content-Type: text / html \ n'.codificar())
                     C.enviar('Connection: close \ n \ n'.codificar())
                     C.Envia todo(respuesta.codificar())
                 demás:
                     impresión("########## \ Nnot HTTP \ n ###########")
                     C.enviar('HTTP / 1.1 400 Bad Request \ n'.codificar())
             demás:
                 impresión("Solicitud favicon encontró")
                 C.enviar('HTTP / 1.1 200 OK \ n'.codificar())
         excepto:  # Decodieren und Parsen
             solicitud = rawRequest
             C.enviar('HTTP / 1.1 200 OK \ n'.codificar())
         C.cerrar()
     excepto:  # Wegen tiempo de espera
         aprobar    
         
     si gusto.valor()==0:
         impresión("Abgebrochen Mit Flashtaste")
         ledsOff()
         D.irritante("Abbruch d. Usuario",0,5)
         sys.Salida()
     parpadear(0.05,0.05,1)

Figura 28: Vive desde el navegador.

Figura 28: En directo desde el navegador

Este es el aspecto real del sitio web en Google Chrome. Opera ofrece una imagen similar tras introducir la URL 10.0.1.181:9002. Firefox genera un escándalo porque a sus creadores se les ha metido en la cabeza que tienen que intimidar a los usuarios aceptando sólo direcciones https. Pero hay alternativas. Si las cosas se ponen realmente mal, podría incluso escribir su propio frontend para el PC con CPython.

Bueno, creo que ya tiene bastante con los proyectos del árbol hasta Navidad. Seguro que hay uno u otro para todos. Lo importante es que disfrute de la aplicación y que haya sido capaz de despertar su interés. En cualquier caso, le deseo un maravilloso tiempo de Adviento. 

Para Arduino IDE

Descargar webcontrol.ino

La interfaz en el navegador se ve un poco diferente aquí. La función es la misma.

Dependiendo de si quiere utilizar su propio punto de acceso o la WLAN loca, tiene que comentar la opción no utilizada en el código fuente al principio en las #defines.

// #define WLANconnect true
#define ownAP true

No olvide introducir sus datos de acceso cuando seleccione la opción WLAN.

La dirección IP del punto de acceso está aquí:

192.168.4.1

Encontrará la contraseña en el código fuente. 

En este punto deseamos un Feliz Primer Adviento. 🕯

MuestraEsp-32Proyectos para principiantesSensores

6 comentarios

Jürgen

Jürgen

@ Niko Germer
Natürlich können Sie die Flacker-LEDs gegen normale Kandidaten austauschen. Aber Sie haben recht, für unterschiedliche Farben brauchen Sie unterschiedliche Widerstände. Das liegt einerseits an den unterschiedlichen Durchlassspannungen, rote LEDs haben eine niedrigere als blaue. Aber entscheidender ist die Helligkeit der LEDs. Geringe Helligkeit bei rot und gelb steht der blendenden Helligkeit der blauen und vor allem grünen LEDs gegenüber. Ich beziehe mich hier auf auf die LED aus dem LED Assortment Kit. Für die roten schlage ich 150 Ohm vor, blau 560 Ohm und grün 1,5kOhm für jeweils sechs parallele LEDs am Bäumchen. Die normalen LEDs lassen sich dann auch dimmen, wenn an die Basiswiderstände ein PWM-Signal gelegt wird. Der ESP32 kann das Signal an allen digitalen Ausgängen zur Verfügung stellen.

Niko Germer

Niko Germer

Hallo,
ich würde das Bäumchen gerne mit normale LEDs bestücken. Kann man dann die LEDs dimmen? Was muss ich beachten, bei die Vorwiderstände? Bleiben die gleich?

Andreas Wolter

Andreas Wolter

Die Aktion für das Bundle ist leider abgelaufen. Danke für den Hinweis. Den Link haben wir entfernt.

Michael Beckmann

Michael Beckmann

Hallo
wenn man auf das Bild zur Teileliste klickt kommt ein HTTP 404 :-(

Miguel Torres

Miguel Torres

Un articulo muy bueno con muchos ejemplos con un elemento común.

bit.picker

bit.picker

Sehr schöner Artikel. Besonders interessant finde ich das Kapitel mit der Web-Steuerung. Dannke!

Deja un comentario

Todos los comentarios son moderados antes de ser publicados

Artículos de blog

  1. Ahora instalamos el esp32 a través de la administración.
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. Transporte Aéreo - programación de ESP mediante redes locales inalámbricas