Les vencimos

1º Bachillerato · TIC I

Lección 28 · C · Programación

Objetos e imágenes multimedia

1º Bachillerato · TIC I · Decreto 40/2022 CyL

Objetivos

  1. Agrupar datos relacionados en un objeto literal de JavaScript.
  2. Leer y escribir una propiedad con el punto.
  3. Distinguir el objeto (la ficha) de la imagen (lo que el canvas pinta).
  4. Dibujar en el canvas un sensor a partir de propiedades, sin un archivo remoto.
  5. Traducir la ficha a variables de un sketch y al GPIO que representa.

Explicación

Un objeto literal junta propiedades con nombre dentro de unas llaves. En JavaScript se escribe así: let sensor = { nombre: "LDR patio", pin: 18, luz: 420, umbral: 500 }. Cada propiedad es una variable pequeña que viaja con las demás. sensor.luz es la lectura. sensor.pin es el número de pin, no el voltaje. Cambiar sensor.luz = 510 no cambia sensor.umbral. Esa es la ventaja frente a cuatro variables que solo se parecen por el prefijo.

La imagen no es el objeto

El bloque C pide programas que manejen imágenes y multimedia, no un curso de retoque. Aquí la imagen es una figura que el canvas pinta a partir de datos: un círculo en (x, y), un color según el estado, un texto con el nombre. No hay PNG que descargar ni cámara. Si x o y no son números, no hay dónde pintar y el fallo es de datos, no de «el dibujo no carga». Esa frase, en este curso, casi siempre es falsa: el dibujo no carga porque no existe un archivo, o existe y está mal situado. Hoy el dibujo se genera.

Separar ficha y dibujo permite cambiar la apariencia sin tocar la regla. El color ámbar o el rojo del LED son la salida visual. La regla sigue siendo luz < umbral. Si pintas de rojo cuando el estado es LOW «porque queda más dramático», el canvas miente y la depuración de la lección siguiente será imposible: no podrás fiarte de lo que ves.

En el laboratorio de esta página

El intérprete de pseudocódigo no tiene llaves de objeto, a propósito: el pseudocódigo se mantiene corto. Guardarás las propiedades como variables con los nombres que el canvas espera: nombre, pin, x, y, umbral, luz, estado. El texto de la lección te enseña el objeto literal de JavaScript para que sepas leerlo cuando lo veas en un ejemplo de la web, y el editor te hace practicar la misma ficha despiezada. Traducir de uno a otro es el ejercicio: sensor.luz en JavaScript es luz en el pseudocódigo de hoy, y tiene que ser el mismo número.

Más de un sensor

Cuando hay dos, hacen falta dos fichas. En JavaScript, dos objetos: patio y aula. Meter luzPatio y luzAula puede valer un día y se cruza al siguiente, cuando aparece el pin de cada uno. Un vector de objetos, sensor[0].luz, junta las dos lecciones: el índice elige la ficha y el punto elige el dato. No hace falta programarlo entero hoy. Hace falta no guardar la luz del patio en la propiedad del aula «porque total es un número».

Multimedia de verdad, en local

Una imagen de mapa de bits tiene ancho, alto y píxeles. Un objeto puede guardar ese ancho y ese alto aunque no guardes los píxeles: { w: 64, h: 64 }. El canvas puede pintar un rectángulo de ese tamaño. Eso es tratar multimedia con datos, que es lo que el criterio 3.1 pide junto a la interactividad, sin abrir otro módulo de diseño. El bloque A ya hizo la página y el audio. Aquí el programa decide qué se ve.

Placa

En la UNO no hay objetos literales en el C++ que se usa en el aula, y no pasa nada: la ficha puede ser un grupo de variables con comentario, o una struct si el grupo ya puede con ella. Lo que no puede faltar es el pinMode del 13 y la lectura en A0 fuera del dibujo. En la Pi, un diccionario {"pin": 18, "luz": 420} es el primo del objeto literal. led = LED(sensor["pin"]) solo tendría sentido con placa. En la página, pin 18 significa el rótulo del interruptor y el número pintado, no un puerto abierto.

Mueve x en el editor y ejecuta: el círculo tiene que cambiar de sitio. Cambia luz a 800: estado pasa a LOW y el color deja de ser el de «encendido». Si el círculo no se mueve, el canvas no está leyendo la variable que crees. Ese es ya un ensayo de depuración, con la causa todavía a la vista.

Objeto y marco sensor luz: 420 umbral: 500 pin: 18 estado: HIGH vista, no el dato
La ficha no es el dibujo. El dibujo obedece a x, y y estado. La regla obedece a luz y umbral.

Glosas de esta lección

Objeto literal. Llaves, propiedades y valores. sensor.luz lee un campo.

Propiedad. Un dato con nombre dentro del objeto. No es una casilla numerada.

Punto. La notación sensor.luz. Equivale a abrir la ficha por esa línea.

Canvas. Lienzo de la página donde el programa pinta. No es un archivo de imagen.

Estado. HIGH o LOW, derivado de la comparación. El color lo representa, no lo decide.

Coordenada. x e y en píxeles del lienzo. Números, no «a la izquierda».

Ficha frente a dibujo. Datos por un lado, píxeles por otro. Se pueden cambiar por separado.

struct / diccionario. La misma idea de ficha en C++ y en Python, con otra sintaxis.

Ejemplos resueltos

Ejemplo 1 — Color que miente

estado es LOW y el círculo se pinta rojo «para que se vea». Quien depura cree que el pin está en alto. El color vuelve a obedecer al estado.

Ejemplo 2 — Propiedad cruzada

La luz del aula se guarda en patio.luz porque era la variable que ya existía. El avisador del patio usa la lectura de dentro. Se crean dos objetos o, hoy, dos nombres que no se pisan: luzPatio y luzAula.

Ejemplo 3 — x como texto

let x = "120". El círculo no tiene una posición numérica. Se quitan las comillas y se ejecuta otra vez.

Decisiones de aula

Cada caso es una entrega del avisador del patio del IES Duero (Aranda de Duero). Lee la situación antes de la decisión.

1. Todo en el dibujo

Situación. La única copia del umbral es un número pintado en el canvas.

No conviene. Porque así «se ve» en la demo.

Decisión. Guardar el umbral en la variable y pintar, si hace falta, ese mismo valor como texto.

Por qué: Si la única copia del umbral es un número pintado en el canvas, no se puede comparar ni trazar: los píxeles no son el dato. El texto pintado es una vista, como el diagrama. El umbral vive en la ficha del objeto, y el canvas lo muestra.

2. Un solo objeto para dos sitios

Situación. Patio y aula comparten ficha y se va cambiando el nombre.

No conviene. Para no escribir más líneas.

Decisión. Dos fichas, aunque hoy sean dos grupos de variables.

Por qué: Patio y aula en la misma ficha, cambiando el nombre, hacen que la última escritura gane y el otro lugar se quede sin historia. El vector de lecturas de cada sitio tampoco tiene dónde vivir. Hacen falta dos fichas, aunque hoy solo se rellene una.

3. Imagen de internet

Situación. Un enlace a un icono de LED de un CDN.

No conviene. Porque es más bonito que un círculo.

Decisión. Pintar con el canvas. El curso es offline y el bloque A ya prohibió el recurso remoto como muleta.

Por qué: Un icono de LED traído de un CDN desaparece si el aula no tiene red, y con él desaparece lo que hubieras escondido en esa imagen. El curso pinta con el canvas. El círculo es suficiente, y no depende de un servidor ajeno.

4. Pin dentro del color

Situación. La propiedad pin guarda "rojo".

No conviene. Porque el LED es rojo.

Decisión. pin es 18 o 13, numérico. El color se calcula del estado.

Por qué: Guardar "rojo" en pin confunde el color con el número de pin. El día que pases el programa a gpiozero, LED con un color no existe; LED con 18 sí. El pin es 18 o 13, numérico, y el color se calcula a partir del estado.

El mismo avisador, en tres lenguajes

El problema no cambia: si la luz del patio del IES Duero baja de 500, hay que avisar. Cambia quién ejecuta. El pseudocódigo lo ejecuta el laboratorio de esta página. El sketch lo compilaría el IDE de Arduino hacia la UNO. El fragmento de Python lo ejecutaría una Raspberry Pi con gpiozero, si hubiera placa. Aquí no hay placa.

Objeto literal en JavaScript

El ternario es el si/si no en una línea. sensor.pin no enciende nada: nombra el GPIO.

let sensor = {
  nombre: "LDR patio",
  pin: 18,
  luz: 420,
  umbral: 500
};
let estado = sensor.luz < sensor.umbral ? "HIGH" : "LOW";

La ficha en el sketch

Sin objeto, las constantes hacen de ficha. estadoAlto es 1 o 0. El dibujo, en la placa, es el propio LED del pin 13.

const int PIN_LED = 13;
const int UMBRAL = 500;
int luz = analogRead(A0);
int estadoAlto = luz < UMBRAL;
digitalWrite(PIN_LED, estadoAlto ? HIGH : LOW);

Diccionario en la Pi

Las comillas de las claves son parte del diccionario de Python. No convierten la luz en texto.

sensor = {"nombre": "LDR patio", "pin": 18, "luz": 420, "umbral": 500}
estado = "HIGH" if sensor["luz"] < sensor["umbral"] else "LOW"
# LED(sensor["pin"]) solo con placa real

Traza con las lecturas del patio

Horasensor.luzestadoVistapin en la ficha
17:30420HIGHcolor de aviso18
17:32510LOWcolor apagado18
17:35390HIGHcolor de aviso18
17:41600LOWcolor apagado18
17:48500LOWcolor apagado18
18:02250HIGHcolor de aviso18
18:15880LOWcolor apagado18
18:27499HIGHcolor de aviso18

El pin de la ficha no cambia con la luz: sigue siendo 18. Cambia el estado. Si en tu tabla cambia el pin, has guardado el color en el sitio del GPIO.

Lectura guiada

Escribe en el cuaderno el objeto literal con cuatro propiedades y, al lado, las cuatro líneas let del editor. Si un número no coincide, la traducción está mal aunque el canvas «se vea bien» por casualidad con el valor viejo.

Sube luz a 800, ejecuta y comprueba que el estado pasa a LOW. Baja a 100 y vuelve a HIGH. Son las dos trazas mínimas de la ficha. El interruptor de GPIO 18 puede quedar en el mismo estado que estado, y si no coincide debes poder explicar cuál de los dos es el programa y cuál es la mano.

Cuando un objeto tenga a su vez un vector, sensor.lecturas[0], estarás juntando esta lección y la anterior. El índice elige la hora; el punto elige la serie. No hace falta sufrirlo hoy, pero no guardes la serie en nombre.

Errores que se repiten

Rúbrica de esta lección

CriterioAún noEn procesoConseguidoNotable
FichaDatos sueltos sin relaciónNombres confusosluz, umbral, pin, x, yObjeto JS escrito en la memoria
VistaNo hay canvasDibujo fijoEl círculo obedece a x, y y estadoEl color no miente
ReglaEl color es la reglaMezcladasLa comparación decide el estadoDos luces, dos resultados
Tiposx entre comillasSin comprobarNúmeros en luces y coordenadaspin numérico, nombre cadena
HardwareDice que abrió el puertoSolo el dibujoGPIO 18 y D13 como paraleloLa ficha no llama a LED() de verdad

Mini cierre

El objeto agrupa. El canvas obedece. La comparación manda. El pin 18 es un dato de la ficha y, en esta página, también el interruptor simulado, no un puerto.

Comprueba

Abre cada pregunta, responde en el cuaderno y después mira la solución. El párrafo «Por qué» es la parte que se estudia.

1. ¿Por qué sensor.luz = 510 no cambia sensor.umbral?

Respuesta. Porque son propiedades distintas. Asignar una no toca las otras.

Por qué: Si se cambiaran juntas, la ficha no serviría para guardar una lectura nueva sin perder el acuerdo del umbral. El error contrario, copiar la luz encima del umbral, es fácil cuando todo eran variables llamadas dato1 y dato2.

2. ¿Qué diferencia hay entre el objeto y el círculo del canvas?

Respuesta. El objeto (o las variables de la ficha) guarda números y texto. El círculo es una vista que se calcula a partir de ellos.

Por qué: Puedes cambiar el radio del dibujo sin cambiar la regla, y cambiar la luz sin tocar el programa de dibujo. Si el único sitio donde existe el estado es el color ya pintado, no queda nada que trazar cuando el color falle.

3. En la UNO no usas llaves de objeto. ¿Se ha perdido la ficha?

Respuesta. No. La ficha puede ser un grupo de const y de variables con el mismo oficio.

Por qué: El objeto literal es una herramienta de JavaScript. La idea (datos del sensor que viajan juntos y separados del dibujo) cabe en un sketch. Pretender que sin llaves no hay programa es confundir el lenguaje con el algoritmo, que es justo lo que la lección 23 quería evitar.

En la vida real

Castilla y León, sin servidor

  • La ficha de un préstamo de la biblioteca tiene título, código y fecha. No son tres montones de papeles sueltos. El objeto es esa ficha.
  • En el parte de un laboratorio de Palencia, hora y temperatura van en la misma línea. Separarlas en dos listas que se pueden desordenar es el vector mal emparejado; el objeto mantiene el par.
  • Un plano de evacuación pintado no sustituye al número de personas del aula. Vista y dato, otra vez.
  • Si el icono del LED solo existe en una web externa, el día sin red el trabajo de clase desaparece. El círculo generado no depende de eso.
Laboratorio · en esta página Abrir en pestaña →

Agrupa los datos del sensor en variables y, en JavaScript de verdad, en un objeto literal. El canvas lee x, y, luz, umbral y estado después de ejecutar y dibuja el sensor. No carga una imagen de internet.

GPIO 18

Simulación local · sin hardware

Raspberry Pi (BCM) · paralelo didáctico Arduino UNO D13 · pin GPIO 18

Estado del pin: LOW · LED apagado

OFF

estado HIGH enciende el dibujo del canvas cuando la comparación sale sí, y el interruptor de GPIO 18 sigue siendo la maqueta física del mismo hecho. HIGH enciende el LED (en la Pi, 3,3 V; en Arduino UNO el paralelo didáctico es digitalWrite HIGH en D13). No se envía nada fuera de esta página.

Pulsa Ejecutar. El resultado se queda en esta página.

Escribes y dibujas aquí mismo: no hay salto a otro módulo. La misma herramienta, a pantalla completa, está en l28-objetos-e-imagenes-multimedia.html y en el marco (útil si el navegador permite file:// en iframes).

Reto Profesor

La ficha que el canvas obedece

Deja nombre, pin, x, y, luz, umbral y un estado calculado con si / si no. Ejecuta y mueve x lo bastante para que el círculo cambie de sitio. Cambia la luz por encima y por debajo del umbral y anota los dos estados. En el cuaderno, escribe el objeto literal de JavaScript equivalente. Una buena entrega no usa una imagen remota ni pinta de «encendido» un estado LOW.

reto_id: bach1-tic-L28