
Chismes del Lince 22: Simón dice con gestos micro:bit
Hasta ahora la micro:bit medía cosas: pasos, inclinación, rumbo. Hoy la usamos como mando de juego. La página del móvil te enseña un gesto en grande y tú lo haces con la micro:bit: agitarla, ponerla boca abajo, inclinarla hacia un lado… Cuando lo haces bien, la página te felicita, vibra y pasa al siguiente.
Es un juego de movimiento y atención, tranquilo y sin prisas, pensado para jugar en grupo, con niños y mayores a la vez.
Lo que necesitas
- Un micro:bit V2 con su portapilas.
- Un móvil Android con Chrome, con el Bluetooth y la ubicación encendidos. En iPhone, Safari no sirve: hay que abrir la página en el navegador Bluefy.
- El ordenador con MakeCode para programar.
Los 7 gestos
| Gesto | Cómo se hace | Código |
|---|---|---|
| Agitar | Agita la micro:bit | SH |
| Logotipo arriba | De pie, con el logotipo hacia el techo | LU |
| Logotipo abajo | De pie, con el logotipo hacia el suelo | LD |
| Pantalla hacia arriba | Tumbada, con los LEDs hacia el techo | SU |
| Pantalla hacia abajo | Tumbada, con los LEDs hacia el suelo | SD |
| Inclinar a la izquierda | Baja el lado izquierdo | TL |
| Inclinar a la derecha | Baja el lado derecho | TR |
Hemos dejado fuera la caída libre y los gestos de fuerzas g (3g, 6g, 8g), que piden movimientos bruscos. Los siete que quedan son cómodos y se pueden hacer despacio.
Paso 1. Programa el micro:bit
Crea un proyecto nuevo en MakeCode y usa solo bloques.
- Añade la extensión Bluetooth (Extensiones → Bluetooth). No añadas la de Radio.
- Monta este programa:
al iniciar
bluetooth servicio uart
Y a continuación, siete bloques de gesto, sueltos y cada uno aparte. Cada uno lleva dentro un uart bluetooth escribir línea con su código:
al agitar→SHal logotipo hacia arriba→LUal logotipo hacia abajo→LDal pantalla hacia arriba→SUal pantalla hacia abajo→SDal inclinar a la izquierda→TLal inclinar a la derecha→TR
Los bloques de gesto son de Entrada (al agitar, con un desplegable para elegir el gesto). No necesitas ningún «para siempre»: los gestos son eventos y la micro:bit solo reacciona cuando ocurren. Para ir más deprisa, monta uno, haz clic derecho sobre él → Duplicar seis veces, y cambia en cada copia el gesto y el texto.
Si prefieres JavaScript, cambia al modo JavaScript, pega esto y vuelve a Bloques; MakeCode lo convierte solo:
bluetooth.startUartService()
input.onGesture(Gesture.Shake, function () { bluetooth.uartWriteLine("SH") })
input.onGesture(Gesture.LogoUp, function () { bluetooth.uartWriteLine("LU") })
input.onGesture(Gesture.LogoDown, function () { bluetooth.uartWriteLine("LD") })
input.onGesture(Gesture.ScreenUp, function () { bluetooth.uartWriteLine("SU") })
input.onGesture(Gesture.ScreenDown, function () { bluetooth.uartWriteLine("SD") })
input.onGesture(Gesture.TiltLeft, function () { bluetooth.uartWriteLine("TL") })
input.onGesture(Gesture.TiltRight, function () { bluetooth.uartWriteLine("TR") })

Paso 2. Sin emparejamiento (muy importante)
Antes de descargar, hay que cambiar un ajuste para que la página pueda conectar sin pedir códigos:
- Pulsa el engranaje ⚙️ → Configuración del proyecto.
- Marca No se requiere emparejamiento (No Pairing Required: Anyone can connect via Bluetooth).
Paso 3. Pásalo al micro:bit
- Descarga el programa y cópialo a la unidad MICROBIT.
- Espera a que deje de parpadear el led amarillo de atrás.
- Reinicia el micro:bit con el botón de atrás.
Si cambias algo del programa, repite los pasos 2 y 3.
Paso 4. Prepara el móvil
- Bluetooth y ubicación encendidos.
- Si en Ajustes → Bluetooth aparece “BBC micro:bit”, pulsa Olvidar. No hay que emparejarla desde ahí.
- Cierra cualquier otra app que use el micro:bit.
Paso 5. Abre la página y conecta
- Abre en Chrome, escribiendo la dirección directamente: https://montesteam.org/app/chisme-22-simon.html
- Pulsa Conectar micro:bit.
- Elige BBC micro:bit […] en la lista.
- Cuando la página ponga Conectado, pulsa Empezar.
Paso 6. ¡A jugar!
- Elige cuántos gestos quieres en la partida (5, 10 o 15).
- Pon la micro:bit tumbada, con los LEDs hacia arriba. Si ya la tienes así, pulsa Ya está así.
- La página te enseña un gesto en grande, con el dibujo de la micro:bit y su nombre. Hazlo.
- Debajo ves siempre lo que detecta la micro:bit («Ahora detecto: …»). Se pone verde cuando coincide con el gesto pedido.
- Al acertar, el marco se pone verde, sale «¡Muy bien!», el móvil vibra y llega el siguiente.
- Si un gesto cuesta, no pasa nada: pasados 15 segundos aparece el botón Saltar este gesto. No hay cuenta atrás ni se pierde la partida.
- Al completar todos, la página te felicita. Puedes marcar «Decir los gestos en voz alta» para que además los lea.
La guía de uso plegable de la página tiene los siete gestos dibujados, por si alguien se pierde.
Retos para clase
- Jugad por parejas: uno sujeta la micro:bit y el otro, sin mirar el móvil, le dice qué gesto toca.
- Haced una partida de 10 gestos en equipo: ¿qué gestos cuestan más? Apuntadlo en una tabla.
- Probad el juego con familiares y vecinos de distintas edades. ¿Qué cambiarían?
- Inventad un gesto nuevo para añadir al juego y pensad cómo se programaría.
- Reto avanzado: que la micro:bit enseñe un icono en su matriz de LEDs (✔ al acertar) además de la página.
Pensando en otras personas
Este juego nació con una idea: poder llevárselo a una asociación para jugar juntos. Por eso la página es tranquila, con letras y botones grandes, sin prisas y sin perder por equivocarse. Si lo vais a compartir con otras personas:
- Hablad primero con ellas. Preguntad qué gestos les resultan cómodos, qué les gustaría y qué cambiarían. El mejor juego es el que se diseña con quien lo va a usar.
- Es un juego, no un aparato médico. No mide nada de salud ni guarda datos de nadie.
- Adaptadlo. Se puede jugar solo con los gestos que resulten cómodos, con partidas de 5 gestos, y sentados.
Si algo falla
- No aparece en la lista: comprueba que está encendido, que el programa está descargado y que activaste «No se requiere emparejamiento».
- Se conecta pero no reconoce los gestos: mira que debajo del juego cambie la línea «Ahora detecto». Si no cambia, revisa que cada bloque de gesto lleve su
uart bluetooth escribir líneay quebluetooth servicio uartesté en «al iniciar». - Un gesto no se detecta bien: hazlo más marcado y manteniéndolo un momento. En las inclinaciones, baja el lado con más decisión.
- El primer gesto no sale: comprueba que la micro:bit está en «pantalla hacia arriba» y pulsa «Ya está así».
- En iPhone no conecta: abre la página con Bluefy.
Qué hemos aprendido
El acelerómetro de la micro:bit no solo mide fuerzas: reconoce gestos, y cada gesto es un evento, algo que ocurre en un momento y que se avisa. La micro:bit solo manda una palabra clave («SH», «TL»…) y es la página la que lleva la cuenta y decide si lo has hecho bien. También hemos aprendido que diseñar para otras personas significa escuchar primero: letras grandes, sin prisas y sin castigos.
HTML
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Chisme 22 · Simón dice con gestos</title>
<style>
:root{
--bg:#eef2ef; --ink:#10201c; --soft:#4d625b; --card:#ffffff; --line:#cfdad5;
--pine:#1f5b4a; --slow:#2563a8; --ok:#1f7a4d; --norte:#c8321f; --oro:#b8892b;
box-sizing:border-box;
padding-top:env(safe-area-inset-top,0px); padding-bottom:env(safe-area-inset-bottom,0px);
}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
--bg:#0f1a17; --ink:#e8f1ed; --soft:#9db3aa; --card:#172622; --line:#2a3d37;
--pine:#5fc4a2; --slow:#7db3ee; --ok:#6fd89f; --norte:#ff6a55; --oro:#e0b45a;}}
:root[data-theme="dark"]{--bg:#0f1a17; --ink:#e8f1ed; --soft:#9db3aa; --card:#172622; --line:#2a3d37;
--pine:#5fc4a2; --slow:#7db3ee; --ok:#6fd89f; --norte:#ff6a55; --oro:#e0b45a;}
*{box-sizing:border-box}
html{scroll-padding-top:env(safe-area-inset-top,0px)}
body{margin:0;background:var(--bg);color:var(--ink);font:18px/1.45 "Trebuchet MS","Segoe UI",system-ui,sans-serif}
main{max-width:32rem;margin:0 auto;padding:1.2rem 1rem 2rem;text-align:center}
h1{font-size:1.4rem;margin:.2rem 0 .1rem}
.sub{color:var(--soft);margin:0 0 1rem;font-size:.95rem}
button{font:inherit;font-weight:700;border:2px solid var(--pine);background:var(--pine);color:var(--bg);
border-radius:.8rem;padding:.75rem 1.2rem;min-height:3.2rem;cursor:pointer}
button.alt{background:transparent;color:var(--pine)}
button:disabled{opacity:.5;cursor:not-allowed}
button:focus-visible,select:focus-visible,input:focus-visible{outline:3px solid var(--slow);outline-offset:2px}
[hidden]{display:none!important}
.botones{display:flex;gap:.6rem;justify-content:center;flex-wrap:wrap}
#estado{margin:.8rem 0 .2rem;color:var(--soft);min-height:1.5em}
#ayuda{margin:0 0 .4rem;color:var(--soft);font-size:.9rem;min-height:1.2em}
.juego{background:var(--card);border:4px solid var(--line);border-radius:1.2rem;padding:1rem;margin:.8rem 0;min-height:22rem;transition:border-color .25s}
.juego.bien{border-color:var(--ok)}
.juego.bien .gn{color:var(--ok)}
#prog{font-weight:700;color:var(--soft)}
.pic svg{width:min(62vw,15rem);height:auto}
.gn{font-size:2.1rem;font-weight:800;line-height:1.15;margin:.3rem 0 .1rem}
.gh{color:var(--soft);min-height:1.5em}
#dots{margin:.6rem 0;min-height:1.4rem}
.dot{display:inline-block;width:1.1rem;height:1.1rem;border-radius:50%;border:3px solid var(--pine);margin:0 .15rem;vertical-align:middle}
.dot.on{background:var(--ok);border-color:var(--ok)}
#msg{font-weight:700;font-size:1.15rem;min-height:1.6em;margin-bottom:.4rem}
#det{color:var(--soft);font-size:1rem;min-height:1.4em;margin-top:.6rem}
#det.ok{color:var(--ok);font-weight:700}
.ajustes{display:grid;gap:.6rem;text-align:left;background:var(--card);border:1px solid var(--line);border-radius:.8rem;padding:.8rem .9rem;margin:.8rem 0}
.ajustes label{display:block}
select{width:100%;font:inherit;margin-top:.3rem;padding:.5rem;border-radius:.6rem;border:2px solid var(--line);background:var(--bg);color:var(--ink)}
.guia{text-align:left;background:var(--card);border:1px solid var(--line);border-radius:.8rem;padding:.2rem .9rem;margin-top:1rem}
.guia summary{font-weight:700;cursor:pointer;padding:.6rem 0}
.guia ol{padding-left:1.3rem;margin:.2rem 0 .6rem}
.guia li{margin:.4rem 0}
.g{display:flex;gap:.7rem;align-items:center;border-top:1px solid var(--line);padding:.4rem 0}
.g .p{flex:0 0 5.5rem}.g svg{width:100%;height:auto}
.g span{color:var(--soft);font-size:.9rem}
.sacude{animation:sac .35s infinite alternate;transform-origin:60px 50px}
@keyframes sac{from{transform:rotate(-8deg)}to{transform:rotate(8deg)}}
@media (prefers-reduced-motion:reduce){.sacude{animation:none}}
</style>
</head>
<body>
<main>
<h1>Simón dice con gestos</h1>
<p class="sub">La página te enseña un gesto. Tú lo haces con la micro:bit.</p>
<div class="botones">
<button id="conectar">Conectar micro:bit</button>
<button id="ini" class="alt" disabled>Empezar</button>
</div>
<div id="estado" role="status">Sin conectar.</div>
<div id="ayuda"></div>
<div class="juego" id="juego">
<div id="prog"></div>
<div class="pic" id="pic"></div>
<div class="gn" id="gn">Pulsa Empezar</div>
<div class="gh" id="gh"></div>
<div id="dots"></div>
<div id="msg" aria-live="polite"></div>
<div class="botones">
<button id="btnSU" hidden>Ya está así</button>
<button id="btnSaltar" class="alt" hidden>Saltar este gesto</button>
</div>
<div id="det" aria-live="polite"></div>
</div>
<div class="ajustes">
<label>Cuántos gestos en cada partida
<select id="total">
<option value="5">5 gestos</option>
<option value="10">10 gestos</option>
<option value="15">15 gestos</option>
</select>
</label>
<label><input type="checkbox" id="voz"> Decir los gestos en voz alta</label>
</div>
<details class="guia">
<summary>Guía de uso</summary>
<ol>
<li><b>Conecta</b> la micro:bit y pulsa <b>Empezar</b>.</li>
<li>Primero, pon la micro:bit <b>tumbada, con los LEDs hacia arriba</b>.</li>
<li>La página te enseña <b>un gesto</b> en grande. Hazlo con la micro:bit.</li>
<li>Cuando lo hagas bien saldrá <b>«¡Muy bien!»</b> y, enseguida, el siguiente.</li>
<li>Abajo verás siempre <b>qué gesto está detectando</b> la micro:bit. Se pone verde cuando es el correcto.</li>
<li>Si un gesto cuesta, puedes <b>saltarlo</b>. No hay prisa ni se pierde nada.</li>
</ol>
<div id="leyenda"></div>
</details>
</main>
<script>
const UART_SERVICE = "6e400001-b5a3-f393-e0a9-e50e24dcca9e";
const UART_TX = "6e400003-b5a3-f393-e0a9-e50e24dcca9e";
const $ = id => document.getElementById(id);
const espera = ms => new Promise(r => setTimeout(r, ms));
const G = {
SH:["Agitar","Agita la micro:bit"],
LU:["Logotipo arriba","De pie, con el logotipo hacia el techo"],
LD:["Logotipo abajo","De pie, con el logotipo hacia el suelo"],
SU:["Pantalla hacia arriba","Tumbada, con los LEDs hacia el techo"],
SD:["Pantalla hacia abajo","Tumbada, con los LEDs hacia el suelo"],
TL:["Inclinar a la izquierda","Baja el lado izquierdo"],
TR:["Inclinar a la derecha","Baja el lado derecho"]
};
const CODES = Object.keys(G);
let n = 0, total = 5, objetivo = null, pose = null, fase = "inicio", tmrSaltar = null;
let buffer = "", conectando = false, conectado = false;
/* Dibujo de la micro:bit en cada postura */
const FLECHA = ["00100","01110","10101","00100","00100"];
function mb(c, anim){
const plana = ["SU","SD","TL","TR"].includes(c), luces = c !== "SD";
let t = "";
if (c === "LD") t = "rotate(180 60 50)";
if (plana){
t = "translate(60 66) scale(1 .34) translate(-60 -50)";
if (c === "TL") t = "rotate(-24 60 66) " + t;
if (c === "TR") t = "rotate(24 60 66) " + t;
}
let leds = "";
if (luces) FLECHA.forEach((f, j) => [...f].forEach((v, i) =>
leds += '<circle cx="' + (40 + i * 10) + '" cy="' + (36 + j * 9) + '" r="3" fill="' + (v === "1" ? "var(--norte)" : "rgba(0,0,0,.35)") + '"/>'));
const logo = luces ? '<rect x="50" y="21" width="20" height="6" rx="3" fill="var(--oro)"/>' : "";
const ondas = c === "SH" ? '<path d="M10 38q-7 12 0 24M110 38q7 12 0 24M2 44q-4 6 0 12M118 44q4 6 0 12" stroke="var(--oro)" stroke-width="3" fill="none" stroke-linecap="round"/>' : "";
return '<svg viewBox="0 0 120 100" role="img" aria-label="' + G[c][0] + '">' + ondas +
'<g' + (c === "SH" && anim ? ' class="sacude"' : "") + '><g transform="' + t + '">' +
'<rect x="18" y="17" width="84" height="66" rx="8" fill="' + (luces ? "var(--pine)" : "var(--soft)") + '" stroke="var(--ink)" stroke-width="2.5"/>' +
logo + leds + '</g></g></svg>';
}
$("leyenda").innerHTML = CODES.map(c =>
'<div class="g"><div class="p">' + mb(c, false) + '</div><div><b>' + G[c][0] + '</b><br><span>' + G[c][1] + '</span></div></div>').join("");
/* Pantalla del juego */
function tarjeta(c, titulo){
$("pic").innerHTML = c ? mb(c, true) : "";
$("gn").textContent = c ? G[c][0] : (titulo || "");
$("gh").textContent = c ? G[c][1] : "";
}
const msg = t => $("msg").textContent = t;
const vibra = p => { if (navigator.vibrate) navigator.vibrate(p); };
function decir(t){
if ($("voz").checked && window.speechSynthesis){
speechSynthesis.cancel(); const u = new SpeechSynthesisUtterance(t); u.lang = "es-ES"; speechSynthesis.speak(u);
}
}
function puntos(){
$("prog").textContent = fase === "fin" ? "" : "Gesto " + Math.min(n + 1, total) + " de " + total;
$("dots").innerHTML = Array.from({ length: total }, (_, i) => '<span class="dot' + (i < n ? " on" : "") + '"></span>').join("");
}
/* Juego: un gesto cada vez */
function empezar(){
if (!conectado) return;
clearTimeout(tmrSaltar);
total = +$("total").value; n = 0; objetivo = null; pose = null; fase = "listo";
$("juego").classList.remove("bien"); $("btnSaltar").hidden = true; $("btnSU").hidden = false;
tarjeta("SU"); puntos();
msg("Primero, pon la micro:bit así. Si ya la tienes, pulsa «Ya está así»");
$("det").textContent = ""; $("det").className = "";
}
function siguiente(){
fase = "juego"; $("btnSU").hidden = true;
const op = CODES.filter(c => c !== pose && c !== objetivo); // nunca el gesto en el que ya está
objetivo = op[Math.floor(Math.random() * op.length)];
$("juego").classList.remove("bien");
tarjeta(objetivo); puntos(); msg("Haz este gesto");
decir(G[objetivo][0]); vibra(30);
clearTimeout(tmrSaltar); $("btnSaltar").hidden = true;
tmrSaltar = setTimeout(() => {
if (fase === "juego"){ $("btnSaltar").hidden = false; msg("Con calma, sin prisa. Si quieres, puedes saltarlo"); }
}, 15000);
}
function acierto(){
fase = "pausa"; clearTimeout(tmrSaltar); $("btnSaltar").hidden = true;
n++; puntos();
$("juego").classList.add("bien"); $("gn").textContent = "¡Muy bien!"; $("gh").textContent = "";
msg(n + " de " + total); decir("Muy bien"); vibra([40, 60, 40]);
setTimeout(() => {
if (fase !== "pausa") return;
if (n >= total) fin(); else siguiente();
}, 1600);
}
function fin(){
fase = "fin"; clearTimeout(tmrSaltar);
$("juego").classList.add("bien"); puntos();
tarjeta(null, "¡Lo has conseguido!");
msg("Has completado los " + total + " gestos. ¡Enhorabuena!"); decir("Lo has conseguido, enhorabuena"); vibra([80, 60, 80, 60, 160]);
$("ini").textContent = "Jugar otra vez";
}
function gesto(c){
$("det").textContent = "Ahora detecto: " + G[c][0];
$("det").className = (fase === "juego" && c === objetivo) ? "ok" : "";
if (c !== "SH") pose = c;
if (fase === "listo" && c === "SU") siguiente();
else if (fase === "juego" && c === objetivo) acierto();
}
$("ini").onclick = empezar;
$("btnSU").onclick = () => { if (fase === "listo"){ pose = "SU"; siguiente(); } };
$("btnSaltar").onclick = () => { if (fase === "juego") siguiente(); };
/* Datos de la micro:bit: una línea con el código del gesto (SH, LU, LD, SU, SD, TL, TR) */
function recibir(ev){
buffer += new TextDecoder().decode(ev.target.value);
let i;
while ((i = buffer.indexOf("\n")) >= 0){
const c = buffer.slice(0, i).trim().toUpperCase();
buffer = buffer.slice(i + 1);
if (G[c]) gesto(c);
}
}
/* Conexión Bluetooth */
let pasoCx = "", diag = "";
function estado(t, ayuda){ if (!/^Error/.test(t)) pasoCx = t; $("estado").textContent = t; $("ayuda").textContent = ayuda || ""; }
function explicar(e){
const nombre = e && e.name ? e.name : "Error", m = e && e.message ? e.message : String(e);
let a = "";
if (nombre === "NotFoundError" && /cancel/i.test(m)) a = "No has elegido ningún dispositivo. Pulsa Conectar y elige BBC micro:bit.";
else if (nombre === "NotFoundError") a = "La micro:bit no tiene el servicio UART. Revisa el bloque «bluetooth servicio uart» y copia el .hex nuevo.";
else if (nombre === "NotSupportedError") a = "No se pudo activar el envío de datos. Olvida la micro:bit en Ajustes → Bluetooth, borra la caché de la app «Bluetooth» del sistema y reinicia el móvil y la micro:bit.";
else if (nombre === "NetworkError") a = "No se pudo abrir la conexión. Comprueba «No se requiere emparejamiento» en MakeCode, que no haya otra app conectada y reinicia la micro:bit.";
else if (nombre === "SecurityError") a = "La página debe abrirse con https://.";
else if (nombre === "NotAllowedError") a = "Permiso denegado. Permite el Bluetooth y los dispositivos cercanos para el navegador.";
estado("Error (" + nombre + "): " + m, "Falló en el paso: «" + pasoCx + "». " + a + (diag ? " Características: " + diag : ""));
}
async function conectarGatt(dev){
let ultimoError;
for (let k = 1; k <= 4; k++){
try {
estado("Conectando… (intento " + k + " de 4)");
const srv = dev.gatt.connected ? dev.gatt : await dev.gatt.connect();
await espera(600);
estado("Buscando el servicio UART…");
return await srv.getPrimaryService(UART_SERVICE);
} catch (e){
ultimoError = e;
if (e.name === "NotFoundError" || e.name === "SecurityError") break;
try { if (dev.gatt.connected) dev.gatt.disconnect(); } catch (_){}
await espera(800);
}
}
throw ultimoError;
}
$("conectar").onclick = async () => {
if (conectando) return;
if (!navigator.bluetooth){
estado("Este navegador no permite Bluetooth.", "Usa Chrome o Edge (en ordenador o en Android).");
return;
}
conectando = true; $("conectar").disabled = true;
try {
estado("Buscando micro:bit…");
const dev = await navigator.bluetooth.requestDevice({ acceptAllDevices: true, optionalServices: [UART_SERVICE] });
dev.addEventListener("gattserverdisconnected", () => {
conectado = false; $("ini").disabled = true; clearTimeout(tmrSaltar); fase = "inicio";
estado("Desconectado.", "Pulsa Conectar para volver a empezar.");
});
const svc = await conectarGatt(dev);
buffer = ""; diag = "";
estado("Leyendo las características del servicio…");
const chars = await svc.getCharacteristics();
diag = chars.map(c => c.uuid.slice(0, 8) + " [" + Object.keys(c.properties).filter(k => c.properties[k]).join(", ") + "]").join(" · ");
const cand = chars.filter(c => c.properties.notify || c.properties.indicate)
.sort((a, b) => (b.uuid === UART_TX) - (a.uuid === UART_TX));
if (!cand.length) throw new Error("El servicio UART no tiene ninguna característica que envíe datos.");
let ch = null, ultimoErr;
for (const c of cand){
c.addEventListener("characteristicvaluechanged", recibir);
for (let i = 1; i <= 2 && !ch; i++){
try {
estado("Activando notificaciones en " + c.uuid.slice(0, 8) + "… (intento " + i + ")");
await c.startNotifications(); ch = c;
} catch (e){ ultimoErr = e; await espera(1000); }
}
if (ch) break;
c.removeEventListener("characteristicvaluechanged", recibir);
}
if (!ch) throw ultimoErr;
conectado = true; $("ini").disabled = false;
estado("Conectado a " + (dev.name || "micro:bit") + ". Pulsa Empezar.");
} catch (e){
explicar(e);
} finally {
conectando = false; $("conectar").disabled = false;
}
};
puntos();
</script>
</body>
</html>



