Pantalla, sonido, SD y red
La pantalla, el sonido, la tarjeta SD y la red de tu placa se configuran en ESP32 Tools, en la placa del proyecto, y viajan a la placa en el boot.cfg (ver Perfiles de placa). La VM los prepara al arrancar, y tu programa los usa con los módulos de siempre. Esta página cuenta lo que cambia en la placa.
Pantalla
La pantalla de tu programa es la de la placa: su tamaño y su giro salen del perfil, de la página Display de ESP32 Tools. Los de cada perfil están en Placas soportadas, y lo que hace cada función de Display en cada chip, en la tabla de Display.
Al abrir la pantalla con Display.open, la VM pinta durante un segundo su rótulo, «JARU VM» con su versión, y después la deja en negro.
Los modos de dibujo
Los dos modos de Display.mode funcionan así en la placa:
- Doble buffer (
Display.mode(2), el de serie).- En el ESP32 y el ESP32-S3, pintas en un fotograma del tamaño del view, con 8 bits por píxel, y
update()lo envía al panel. Si la placa tiene PSRAM y el view mide un múltiplo de 8 de ancho y de alto, envía solo los trozos de 8 × 8 píxeles que han cambiado, salvo que cambien casi todos. - En el ESP32-P4 y el ESP32-S31, pintas en uno de los dos fotogramas del panel, con 16 bits por píxel, y
update()lo presenta.
- En el ESP32 y el ESP32-S3, pintas en un fotograma del tamaño del view, con 8 bits por píxel, y
- Directo (
Display.mode(1)). Pintas en lo que se ve, con 16 bits por píxel, y ves cómo se pinta cada cosa. En el ESP32 y el ESP32-S3 no gasta memoria para el fotograma.
Los colores de cada modo y lo que ocupa el doble buffer están en Memoria y límites.
Un juego más pequeño que la pantalla
Si tu juego mide menos que el panel, se pinta en una zona del centro de la pantalla, el view, a su tamaño: no se estira ni se escala. Alrededor, la pantalla se queda en negro.
- En el ESP32-P4 y el ESP32-S31,
Display.open(320, 240)ya pone un view de 320 × 240 en el centro del panel. - En el ESP32 y el ESP32-S3,
Display.openno usa sus argumentos: si no dices nada, el view es la pantalla entera.
Para que el juego mida lo mismo en todas las placas, y en Windows, pon el tamaño del view antes de abrir la pantalla:
use Display
// La misma zona de juego en todas las placas: 320 x 240, en el centro
Display.viewWidth = 320
Display.viewHeight = 240
Display.open(320, 240)
println(Display.width, " x ", Display.height) // el tamaño de la pantalla
En Windows imprime 320 x 240. En la Waveshare ESP32-P4-WIFI6-Touch-LCD-4B, que mide 720 × 720, imprime 720 x 720, y el juego queda en el centro, con 200 píxeles negros a cada lado y 240 arriba y abajo.
- Para llenar el borde, pinta una imagen fija con
Display.loadTFT, fuera del doble buffer. SpaceIntruders pone así un marco alrededor de su view de 240 × 240. - Si el panel está en vertical y tu juego es apaisado, gíralo en el perfil: Offset Rotation, en la página Display. En el ESP32 y el ESP32-S3,
Display.orientationgira el panel, pero no vuelve a centrar el view.
El refresco en el ESP32-P4 y el ESP32-S31
En el ESP32-P4 y el ESP32-S31, el panel lee la imagen de la memoria por su cuenta, y Display.update() presenta cada fotograma cuando el panel acaba de pintar el anterior. Tu juego no va más deprisa que el panel: el de la Korvo-1, la placa del ESP32-S31, refresca unas 35 veces por segundo.
Sonido
El sonido de la placa se configura en la página Audio de ESP32 Tools. Enable audio hardware lo enciende, y Backend dice por dónde sale:
| Backend | Qué es |
|---|---|
i2s | Un bus I2S hacia un amplificador o un códec. Pines en I2S pins: MCLK, BCLK, WS/LRCK, DOUT y DIN. |
buzzer | Un zumbador en un pin, con una señal cuadrada. El pin va en Buzzer, GPIO; si es -1, la VM usa DOUT. |
null | Sin salida: las funciones de Sound no fallan, pero no suena nada. |
Rate es la frecuencia de mezcla, 22050 o 44100 Hz, y Frames, Stereo output, MCLK multiple y Render task ajustan la salida I2S. Lo que es cada campo del boot.cfg está en Sound.
El sonido no sale hasta que tu programa llama a Sound.init(). Devuelve false si no ha arrancado, por ejemplo con Enable audio hardware apagado o sin el pin de la salida. Llamarlo otra vez no hace nada.
Qué placas suenan
- La JaruCade y la Waveshare ESP32-S3-Touch-LCD-2.8 traen el sonido I2S en el perfil. Basta
Sound.init(). - La Freenove FNK0104 y la Waveshare ESP32-S3-Touch-AMOLED-1.8 traen el I2S en el perfil, pero suenan a través de un códec ES8311 que tu programa tiene que arrancar antes (ver Las placas con códec).
- La LILYGO T4 lo trae apagado.
- Los demás perfiles, también los del ESP32-P4 y el del ESP32-S31, no traen sonido:
Sound.init()devuelvefalsehasta que lo configures en la página Audio. - En el ESP32-S31, el sonido está sin probar: el códec de la Korvo-1, un ES8389, usa un modo del bus I2S (TDM) que la VM no tiene.
Zumbador o I2S
Con un zumbador, la VM no mezcla: hace sonar una sola nota con una señal cuadrada en el pin.
i2s | buzzer | |
|---|---|---|
| Notas a la vez | Las de los 7 canales: 4 de tono, el de ruido y 2 de muestras | Una: la del canal más bajo que esté sonando |
| Forma de onda | La que pidas | Cuadrada. Con PULSE, con su ancho de pulso |
| Ruido | Ruido | Un tono cuadrado, de 80 a 4000 Hz según el periodo |
| Volumen | El de cada canal y el general | Cambia el ancho del pulso |
Muestras (loadSample, playSample) | Sí | No: devuelven false |
Música (loadMusic, playMusic) | Sí | No: devuelven false |
Envolventes, vibrato, pwm y tremolo | Sí | Se aceptan y no hacen nada |
fade y los slide | Deslizan poco a poco | Saltan al valor final |
Las placas con códec
Un códec ES8311 se configura por I2C, y la VM no lo hace: lo arranca tu programa con el driver ES8311 del gestor de drivers I2C, categoría Audio (ver Drivers I2C), antes de Sound.init(). Sin eso, la placa no suena.
| Placa | Bus I2C del códec | Amplificador | De dónde sale |
|---|---|---|---|
| Freenove FNK0104 | SDA 16 y SCL 15, dirección 0x18 | GPIO 1, se enciende con LOW | El ejemplo JaruTypeII |
| Waveshare ESP32-S3-Touch-AMOLED-1.8 | SDA 15 y SCL 14, dirección 0x18 | GPIO 46, se enciende con HIGH | Su perfil, que lo lleva aunque ni el IDE ni la VM lo usan |
| Waveshare ESP32-P4-WIFI6-Touch-LCD-4B | SDA 7 y SCL 8, dirección 0x18 | GPIO 53, se enciende con HIGH | El ejemplo SoundLab |
En la del ESP32-P4, pon antes en la página Audio: Enable audio hardware, Backend i2s, Port 0, MCLK 13, BCLK 12, WS/LRCK 10, DOUT 9 y DIN 11, los de Config/esp32p4.cfg del ejemplo SoundLab. En la Waveshare ESP32-P4-WIFI6-Touch-LCD-4.3 no está comprobado.
use I2C
use Sound
import "Drivers/DRV_ES8311.aru"
// En la Waveshare ESP32-P4-WIFI6-Touch-LCD-4B, el códec va en el bus I2C 0 (SDA 7, SCL 8)
if (platform() == HW_ESP32P4) then
I2C.init(0, 7, 8, 400000)
var codec = ES8311(0)
codec.configurePA(53, true) // el amplificador: GPIO 53, se enciende con HIGH
if (not codec.begin(70)) then
println("El códec no contesta: error ", codec.getLastError())
end
end
var hayAudio = Sound.init()
Aunque el códec no conteste, llama a Sound.init(): así el mismo programa suena en las demás placas. En un juego de salas con el mando I2C, enciende The game opens the bus en Game controls: tu código ya abre el bus (ver El mando I2C).
Tarjeta SD y ficheros
La placa tiene dos sitios para ficheros, que tu programa ve como dos unidades del módulo File:
| Unidad | Dónde está | Qué tiene |
|---|---|---|
flash: | La memoria de ficheros (LittleFS), un trozo de la flash de la placa | El programa, sus recursos y el boot.cfg. Es la unidad de serie. |
sd: | La tarjeta SD, si la placa tiene lector y lo enciendes | Lo que pongas tú en ella |
La memoria de ficheros
Run y Upload Program la graban con lo que hay en la carpeta Build/flash del proyecto: el programa compilado (.jxr), el boot.cfg y los recursos que prepara la compilación, como las imágenes, los sprites, los mapas y la música. Los .aru no van: la placa solo necesita el programa compilado (ver Grabar el firmware y ejecutar).
Cada Run y cada Upload Program graban de nuevo la memoria de ficheros entera, con lo que hay en Build/flash. Lo que tu programa haya escrito en flash:, como una tabla de récords o una partida guardada, se pierde.
Esos ficheros sí sobreviven a apagar y encender la placa, y a Flash Firmware, que no toca la memoria de ficheros. Para guardar algo que dure, usa la tarjeta SD: el IDE no la toca nunca.
En Windows, flash: es la carpeta Build/flash del proyecto, y sd:, la carpeta Build/sd. Lo que tu programa escribe en flash: mientras lo pruebas en Windows se queda en Build/flash, y el siguiente Run en la placa lo graba con lo demás. Build/sd no va nunca a la placa.
Cuánto cabe en la memoria de ficheros depende del chip y de la flash de la placa: ver Memoria y límites.
La tarjeta SD
La tarjeta se configura en la página Storage de ESP32 Tools, grupo SD Card: la casilla Enable SSD la enciende, y MISO, MOSI, SCLK y CS son sus pines. En el ESP32-S31 hay además Power pin, el GPIO que le da corriente (-1, siempre encendida), y Power on, el nivel que la enciende. Todos los perfiles la traen apagada.
- Va por SPI en los cuatro chips, y tiene que estar formateada en FAT. La VM no la formatea.
- Con la tarjeta encendida, la VM la monta al arrancar, antes que el programa. Si la monta, el monitor serie dice «SDCard Mount OK», con su tamaño.
- Si no la encuentra, porque no está, no tiene formato o los pines no son los suyos, la placa la espera: el monitor serie dice «Please insert an SD card to boot.» cada 2 segundos, y tu programa no arranca.
- El IDE no escribe en la tarjeta. Lo que necesite tu programa, cópialo tú desde el ordenador.
- Para usarla, pon
sd:en la ruta ("sd:/records.txt") o cambia la unidad conFile.setUnit("sd:"). Sin la tarjeta montada,File.setUnit("sd:")lanzaERR_FILE_NOT_FOUND. - Primary, en el mismo grupo, no cambia nada en la placa: la unidad de serie es siempre
flash:.
WiFi, MQTT y NTP
La red de la placa se configura en la página Network de ESP32 Tools. Tu programa no la configura: no hay módulo WiFi. La VM conecta la placa al arrancar, con lo que diga el boot.cfg, y tu programa usa la red con los módulos Http y MQTT.
Las contraseñas de la WiFi y de MQTT se guardan tal cual en el proyecto y en la placa (ver Perfiles de placa).
WiFi
| Campo | Qué es |
|---|---|
| Enable WiFi | Conecta la placa a una red WiFi al arrancar. Sin ella, la placa no tiene red: ni Http, ni MQTT, ni hora por NTP. |
| SSID y Password | El nombre y la contraseña de la red. |
| IP Static | Una dirección fija, en vez de la que da el router: IPv4, Subnet, Gateway, DNS 1 y DNS 2. |
El nombre de la placa en la red es Device Name, de la página Hardware.
La VM conecta antes de empezar tu programa. El monitor serie dice «Connecting to SSID», con tu red, y escribe un punto cada medio segundo mientras espera, 30 segundos como mucho. Si conecta, dice «WiFi connected» y la dirección IP de la placa; si no, el programa empieza igualmente, sin red. Si no conecta al arrancar, o si la red se cae después, la placa lo sigue intentando sola (el ESP32 y el ESP32-S3, cada 30 segundos), y cuando la red vuelve, MQTT conecta también.
- En el ESP32-P4, la WiFi va por un segundo chip de la placa, un ESP32-C6. Con IP Static, el ESP32-P4 y el ESP32-S31 no usan DNS 1 ni DNS 2: si tu programa llama a un servidor por su nombre, deja IP Static apagado.
- En el ESP32-S31, la WiFi no se ha probado en la placa.
MQTT
| Campo | Qué es |
|---|---|
| Enable | Conecta la placa a un broker MQTT. Necesita la WiFi. |
| Broker y Port | El broker y su puerto. De serie, test.mosquitto.org y 1883, sin cifrar. |
| User y Password | El usuario y la contraseña del broker, si los pide. |
| Client ID | El nombre con el que la placa se presenta al broker. Dos aparatos con el mismo nombre se echan el uno al otro. Si sigue el de serie, o está vacío, Get Info, Generate y Get MAC ponen el Device Name de la placa, que es distinto en cada una; uno que hayas puesto tú se queda. |
| Retain y QoS | Cómo publica la placa lo que manda tu programa: si el broker guarda el último mensaje (Retain) y con qué calidad de servicio (QoS). En el ESP32 y el ESP32-S3, QoS es siempre 0. |
| Clean Sessions | Si el broker olvida la sesión anterior al conectar. |
| Will Topic, Will Message, Will QoS y Will Retain | El mensaje que publica el broker si la placa se desconecta sin avisar. De serie, {"connected": false}. |
| Send Status | Al conectar, la placa publica {"connected": true} en Will Topic. |
| Interval ms | Cada cuánto, como mucho, avisa la placa al broker de que sigue conectada (el keepalive de MQTT), en milisegundos. De serie, 60000. Por debajo de 1000, la placa usa 60 segundos. |
| Time Send | No hace nada. |
La placa conecta con el broker por su cuenta, después de empezar tu programa. Mientras no conecta, MQTT.publish y MQTT.subscribe no hacen nada y devuelven true. Espera a MQTT.isConnect() antes de suscribirte:
use MQTT
// La placa conecta con el broker después de empezar tu programa
var espera = 0
while (not MQTT.isConnect() and espera < 30)
pause(100)
espera++
end
if (MQTT.isConnect()) then
MQTT.subscribe("casa/luz")
else
println("Sin MQTT")
end
Si se pierde la conexión, la placa vuelve a conectar: el ESP32 y el ESP32-S3, sin parar durante el primer minuto después de arrancar y después cada 2 minutos; el ESP32-P4 y el ESP32-S31, cada 10 segundos. No repite tus suscripciones: cuando MQTT.isConnect() vuelva a dar true, suscríbete otra vez.
Todos los problemas conocidos de JARU, juntos, están en Problemas conocidos.
NTP
Con Enable NTP, la placa pone su reloj en hora al arrancar, con el servidor de Server (de serie, time.google.com). Necesita la WiFi. El monitor serie dice «Synchronizing NTP» y, después, la fecha y la hora.
Con NTP, time() da la fecha y la hora de verdad. La zona horaria va fija en la VM y no se cambia desde el IDE: en el ESP32-P4 y el ESP32-S31 es la hora de Europa central, con su horario de verano; en el ESP32 y el ESP32-S3, una hora más que UTC, con horario de verano. Sin NTP, la VM no pone en hora el reloj de la placa, y time() no da la hora de verdad. time() está en la librería estándar.