La velocidad del ventilador cambia automaticamente segun la luz del ambiente. Aprende PWM (modulacion de ancho de pulso) y control proporcional — la base de casi toda la electronica de control moderna: motores, dimers de LED, cargadores de movil.
El ventilador requiere la placa de expansion para funcionar correctamente — el micro:bit solo no puede dar suficiente corriente. Si ya hiciste el Proyecto 05, la OLED ya deberia tener instalada su extension en MakeCode.
Tres componentes, tres grupos de conexiones. El sensor de luz y el ventilador usan pines normales. La OLED usa I2C. Conecta de uno en uno y prueba cada componente antes de pasar al siguiente.
pins.analogWritePin con valores de 0 (apagado) a 1023 (maximo) para controlar la velocidad.| Componente | Pin del componente | Pin micro:bit | Color recomendado |
|---|---|---|---|
| Sensor Luz (LDR) | Signal (analog) | P0 | 🟡 Amarillo |
| Sensor Luz (LDR) | V (VCC) | 3.3V | 🔴 Rojo |
| Sensor Luz (LDR) | G (GND) | GND | ⚫ Negro |
| Ventilador DC | Signal (PWM) | P1 (PWM) | 🟠 Naranja |
| Ventilador DC | V (VCC) | 3.3V | 🔴 Rojo |
| Ventilador DC | G (GND) | GND | ⚫ Negro |
| Pantalla OLED | CLK (SCL) | SCL / P19 | 🔵 Azul |
| Pantalla OLED | DA (SDA) | SDA / P20 | 🔳 Verde |
| Pantalla OLED | V (VCC) | 3.3V | 🔴 Rojo |
| Pantalla OLED | G (GND) | GND | ⚫ Negro |
P0, VCC a 3.3V, GND a GND. El sensor LDR es analogico — mide un rango de 0 a 1023, no solo 0 o 1.P1, VCC a 3.3V, GND a GND. El pin P1 es compatible con PWM — esto es lo que permite controlar la velocidad de forma proporcional.3.3V, GND a GND. Si ya hiciste el Proyecto 05, el proceso es identico.El codigo lee la luz cada 500ms, convierte el valor al rango de velocidad del motor con Math.map, aplica PWM al ventilador y muestra el estado en la OLED. Los botones A y B permiten control manual de emergencia.
Math.map hace la conversion matematica entre el rango del sensor (0-1023) y el rango PWM del motor (0-1023) de forma proporcional.// Abanico inteligente con control PWM // La velocidad del ventilador varía según la luz let nivelLuz = 0 let velocidadMotor = 0 // Inicializar OLED (128x64 pixels) OLED.init(128, 64) basic.forever(function () { // Leer sensor de luz (0-1023) nivelLuz = pins.analogReadPin(AnalogPin.P0) // Convertir luz a velocidad del motor (proporcional, mismo rango) velocidadMotor = Math.map(nivelLuz, 0, 1023, 0, 1023) // Controlar ventilador con PWM pins.analogWritePin(AnalogPin.P1, velocidadMotor) // Mostrar estado en OLED OLED.clear() OLED.writeString("=== ABANICO ===") OLED.writeString("Luz: " + nivelLuz) OLED.writeString("Velocidad: " + Math.round(velocidadMotor / 10) + "%") if (velocidadMotor < 300) { OLED.writeString("ESTADO: Parado") basic.showIcon(IconNames.SmallSquare) } else if (velocidadMotor < 700) { OLED.writeString("ESTADO: Medio") basic.showIcon(IconNames.Square) } else { OLED.writeString("ESTADO: Maximo") basic.showIcon(IconNames.Yes) } basic.pause(500) }) // Botón A: forzar ventilador apagado (modo manual OFF) input.onButtonPressed(Button.A, function () { pins.analogWritePin(AnalogPin.P1, 0) OLED.clear() OLED.writeString("MODO MANUAL") OLED.writeString("Ventilador: OFF") basic.pause(2000) }) // Botón B: forzar ventilador a tope (modo manual MAX) input.onButtonPressed(Button.B, function () { pins.analogWritePin(AnalogPin.P1, 1023) OLED.clear() OLED.writeString("MODO MANUAL") OLED.writeString("Ventilador: MAX") basic.pause(2000) })
from microbit import * import ssd1306 oled = ssd1306.SSD1306_I2C(128, 64, i2c) # Función para mapear un valor de un rango a otro def mapear(valor, min_ent, max_ent, min_sal, max_sal): return int((valor - min_ent) * (max_sal - min_sal) / (max_ent - min_ent) + min_sal) while True: # Leer sensor de luz (0-1023) nivel_luz = pin0.read_analog() # Calcular velocidad proporcional a la luz velocidad = mapear(nivel_luz, 0, 1023, 0, 1023) # Control PWM del ventilador pin1.write_analog(velocidad) # Mostrar en OLED oled.fill(0) oled.text("ABANICO INTEL.", 0, 0) oled.text("Luz: " + str(nivel_luz), 0, 16) porcentaje = int(velocidad / 10.23) oled.text("Vel: " + str(porcentaje) + "%", 0, 32) if velocidad < 300: oled.text("Parado", 0, 48) display.show(Image.SQUARE_SMALL) elif velocidad < 700: oled.text("Velocidad media", 0, 48) else: oled.text("Velocidad max!", 0, 48) oled.show() # Control manual con botones if button_a.was_pressed(): pin1.write_analog(0) sleep(2000) if button_b.was_pressed(): pin1.write_analog(1023) sleep(2000) sleep(500)
Comprueba cada paso. Tapa el sensor con la mano para ver el efecto — la diferencia entre mucha y poca luz debe notarse claramente en la velocidad del ventilador.
El Desafio 1 mejora la estabilidad del sistema. Los demas exploran conceptos avanzados de control: umbrales, logica inversa y memoria de maximo.
if antes de llamar a analogWritePin: si nivelLuz < 200, escribe 0 directamente sin hacer el mapeo.Math.map(nivelLuz, 0, 1023, 1023, 0).maxLuz que guarda el valor mas alto de luz que ha visto el sensor desde que arranco. Mostrala en la cuarta linea de la OLED como "Max: XXX". Para resetearla usa el boton A+B a la vez (en MakeCode: input.onButtonPressed(Button.AB, ...)).Los problemas mas comunes con el ventilador son de conexion o de rango del sensor. Lee el sintoma que reconoces.
P1 y que VCC y GND estan bien conectados. Si gira con B pero no en automatico, el problema esta en el sensor de luz — prueba a iluminarlo directamente con una linterna.P0 y no a otro pin.nivelLuz, lee el sensor 3 veces y haz la media: (pin0.readAnalog() + pin0.readAnalog() + pin0.readAnalog()) / 3. Esto reduce el ruido del sensor.Math.map es una funcion especifica de MakeCode que no existe en JavaScript estandar — funciona perfectamente en el editor de MakeCode. Si ves un subrayado rojo, prueba a hacer clic en "Descargar" igualmente; a veces el editor marca falsos errores que no impiden la compilacion.El control proporcional (PWM) es uno de los conceptos mas importantes en electronica. Ahora que lo entiendes, lo veras en todas partes.
Math.map.