Com usar el simulador
Obre jordibinefa.github.io/iotv, escriu el codi a l'editor i prem ▶ Executar. Interactua amb els botons i sliders del bessó digital per veure com reacciona el programa.Important: no escriguis cap línia
import— al simuladoriotv,time,mathirandomja estan disponibles automàticament.Format d'adreces:
"0x0"per a la primera vèrtebra,"0x1"per a la segona (no'0000'— aquest és el format de la Raspberry Pi física).
Digitals:
iotv.dinbit("0x0", "b", N) # llegeix bit N d'entrada → 0 o 1
iotv.din("0x0", "b") # llegeix les 8 entrades → enter (0–255)
iotv.doutbit("0x0", "a", N, V) # escriu bit N de sortida (V = 0 o 1)
iotv.dout("0x0", "a", V) # escriu les 8 sortides alhora (V = 0–255)
Analògiques:
iotv.ain("0x0", "b", CH) # llegeix canal CH (1–4) → valor cru
iotv.ain2v(raw) # valor cru → volts (−10 a +10 V)
iotv.aout("0x0", "a", CH, raw) # escriu canal CH amb valor cru
iotv.v2aout(volts) # volts (0–10 V) → valor cru DAC
Temporització i consola:
time.sleep(S) # espera S segons (accepta decimals)
print("text", variable) # escriu a la consola del simulador
Fórmula de remapejat (de −10..+10 V a qualsevol rang físic):
valor = (volts + 10) / 20 * (màxim − mínim) + mínim
No es requereixen coneixements previs de Python. Cada exercici inclou totes les peces necessàries.
Objectiu: Entendre com s'activa una sortida digital.
El codi següent encén el LED DO0. Completa'l perquè encengui els LEDs DO0, DO2 i DO4 alhora, deixant els altres apagats.
Codi inicial (modifica'l):
iotv.doutbit("0x0", "a", 0, 1) # encén DO0
time.sleep(5)
Pistes:
1 = encén, 0 = apagaObjectiu: Entendre els bucles i la temporització.
Tasca: Fes que el LED DO0 parpellegi indefinidament amb 1 segon encès i 1 segon apagat.
Pistes:
while True: és un bucle que mai s'aturaObjectiu: Llegir una entrada digital i prendre decisions.
Tasca: Escriu un programa que llegeixi el botó DI0 (costat B, bit 0) i mostri per consola "Botó premut" o "Botó no premut" cada 500 ms.
Estructura (omple els buits ___):
while True:
estat = iotv.dinbit("0x0", "b", ___)
if estat == 1:
print(___)
else:
print(___)
time.sleep(___)
Extensió: Fes que el LED DO0 s'encengui quan el botó estigui premut i s'apagui quan no ho estigui.
Objectiu: Activar actuadors en ordre amb temporitzadors.
Context: Seqüència d'arrencada d'una màquina industrial: pilot lluminós → motor → ventilador.
Tasca: Escriu un programa que faci la seqüència següent, una sola vegada:
"Seqüència completada"Pista: Encendre DO1 no afecta DO0 — cada bit és independent.
Objectiu: Seqüència cíclica amb múltiples sortides i temporitzadors.
Context: Tres LEDs: vermell (DO0), ambre (DO1), verd (DO2).
Cicle:
Tasca: Escriu el codi complet del semàfor que repeteixi el cicle indefinidament. Imprimeix l'estat actiu a cada canvi.
Pista: A cada pas, apaga tots els LEDs primer amb iotv.doutbit(..., 0) i després encén els que toca.
Objectiu: Detectar el flanc de pujada d'un botó (quan passa de 0 a 1).
Context: Un comptador de peces en una cinta ha de comptar cada vegada que la peça passa pel sensor, no cada cicle que el sensor es manté actiu.
Tasca: Escriu un programa que compti quantes vegades es prem el botó DI0 i mostri el total per consola. El comptador no ha d'incrementar mentre el botó es manté premut.
Estructura (omple els buits ___):
comptador = 0
estat_anterior = ___
while True:
estat_actual = iotv.dinbit("0x0", "b", 0)
if estat_actual == 1:
if estat_anterior == ___: # flanc de pujada
comptador = comptador + ___
print("Total polsos:", ___)
estat_anterior = ___
time.sleep(0.05)
Es recomana haver completat el Nivell 0 o tenir experiència bàsica en Python.
Context: Un sistema de senyal visual ha de reflectir l'estat d'un interruptor de seguretat. La consola ha de registrar cada canvi, però no inundar-se amb missatges repetits.
Tasca: Escriu un programa que:
"Interruptor ON → LED ON" o "Interruptor OFF → LED OFF" només quan l'estat canviïPista: Inicialitza estat_anterior = -1 (valor impossible) per forçar que el primer cicle sempre imprimeixi.
Context: Panells de senyalització industrial amb efecte serpent per indicar que el sistema és actiu.
Tasca: Fes que els LEDs s'encenguin d'un en un, de DO0 a DO7, amb 200 ms entre cada un, repetint indefinidament.
Ampliació: Controla la velocitat amb el slider AI1: −10 V = lent (500 ms), +10 V = ràpid (50 ms).
Fórmula per a l'ampliació: retard = (10 - volts) / 20 * 0.45 + 0.05
Context: Un sistema d'il·luminació automàtica oscil·la si el llindar d'encesa i apagada és el mateix (chattering). L'histèresi resol això amb dos llindars diferents.
Assignació:
Tasca: Encén DO0 quan la llum baixi del 30% i apaga'l quan superi el 40%. Entre 30 i 40%, mantén l'estat actual.
Pista: Necessites una variable llum_encesa = False que recordi l'estat actual entre iteracions.
Context: Els variadors de freqüència (VFD) industrials reben 0–10 V com a consigna de velocitat. El potenciòmetre és la consigna de l'operari.
Assignació:
Tasca: Llegeix el potenciòmetre, converteix a percentatge i escriu la tensió proporcional al canal AO1. Mostra per consola: Consigna: X.X V → Velocitat: YY%
Fórmules: pct = (volts + 10) / 20 * 100 → sortida_V = pct / 100 * 10
Context: Sistemes d'il·luminació RGBW en línies de muntatge o magatzems, mode manual digital.
Tasca:
R:1 G:0 B:1 W:0Nota: El simulador no suporta and. Usa if niuats per combinar condicions.
Context: El BME280 mesura temperatura, humitat i pressió. Es simula amb tres sliders analògics amb els rangs físics reals del sensor.
Escales de conversió:
| Canal | Paràmetre | Rang físic | Fórmula |
|---|---|---|---|
| AI1 | Temperatura | −40 a +85 °C | T = (v + 10) / 20 * 125 − 40 |
| AI2 | Humitat relativa | 0 a 100 % | H = (v + 10) / 20 * 100 |
| AI3 | Pressió atmosfèrica | 300 a 1100 hPa | P = (v + 10) / 20 * 800 + 300 |
Tasca: Mostra per consola cada 500 ms: T: 23.4 °C | H: 58 % | P: 1013 hPa
Extensió: Activa alertes visuals:
Exercicis amb lògica de control real basada en els exemples del simulador.
Context: Una cinta industrial fa ping-pong automàticament entre dos extrems. Un botó d'emergència atura el motor immediatament.
Assignació (vèrtebra digital "0x1"):
| Bit | Costat | Funció |
|---|---|---|
| 0 | A (sortida) | Motor avant |
| 1 | A (sortida) | Motor endarrere |
| 2 | A (sortida) | Solenoide (dispensador de caixes) |
| 5 | B (entrada) | Sensor esquerra |
| 6 | B (entrada) | Sensor dreta |
| 7 | B (entrada) | Botó emergència |
Vèrtebra analògica "0x0": AO1 = velocitat del motor, AI1 = potenciòmetre de velocitat.
Tasca: Partint de l'exemple cinta02-v2, modifica'l perquè:
Context: Un sistema de climatització (HVAC) ha de mantenir temperatura i humitat dins d'un rang. Quan superen els llindars, activen actuadors: el ventilador i el deshumidificador.
Usa les mateixes escales de conversió de l'exercici 1F.
Tasca: Escriu un control amb histèresi per a dos paràmetres simultàniament:
Mostra per consola l'estat dels dos actuadors cada vegada que canviïn.
Context: Control d'intensitat de llum RGBW via senyals analògics. Cada canal té el seu propi slider de 0 a 10 V.
Assignació:
Tasca:
sortida = (volts_entrada + 10) / 2Extensió: Si la suma de les quatre intensitats supera el 300% del màxim total, redueix-les proporcionalment per no superar el límit de potència del driver.
Exercicis basats en exemples complets. Requereixen llegir i entendre codi existent.
Context: L'exemple elevator01 és un controlador complet d'ascensor amb màquina d'estats, encoder analògic de posició, botons de planta i cabina, seguretat de portes i parada d'emergència.
Tasca (comprensió): Executa'l al simulador i respon:
ST_WAIT, ST_MOVE, ST_OPEN, ST_OPENED, ST_CLOSE, ST_EMERG. Quina condició provoca la transició de ST_MOVE a ST_OPEN?time.sleep() de durada llarga?Tasca (modificació): Afegeix un comptador de viatges. Cada vegada que l'ascensor arribi a una planta, incrementa'l i mostra: Viatge nº X: Planta Y
Context: Continuació de 3A. Un ascensor real acumula totes les peticions rebudes i les serveix totes, no només l'última.
Tasca: El codi elevator01 ja gestiona pending_0, pending_1, pending_2. Analitza com funciona aquest sistema de cues i respon:
pending_0? Quan es posa a 1?Pendents: P0=1 P1=0 P2=1Context: El fitxer Head02TestRPi02.py és el codi que correria en una Raspberry Pi física connectada al cap IoT-Vertebrae via bus CAN. Compara'l amb els scripts del simulador.
Tasca (anàlisi):
can_on() i can_off()? Quin equivalent té al simulador?time.sleep() ni funcions bloquejants dins d'un callback?Reflexió: Completa la taula comparativa:
| Característica | Simulador (polling) | RPi real (callback) |
|---|---|---|
| Latència de resposta | depèn del time.sleep() |
? |
| Consum de CPU | alt | ? |
| Complexitat del codi | baixa | ? |
| Ús recomanat | ? | ? |