El simulador web executa codi Python que escrius directament al navegador. Per fer-ho possible, un transpilador converteix el teu codi Python a JavaScript abans d'executar-lo. Aquesta conversió no és perfecta: hi ha construccions de Python que funcionen normalment en un ordinador però que el simulador no sap convertir.
Aquesta pàgina explica exactament què pots i no pots fer, amb exemples de com reescriure el codi per que funcioni.
Al simulador no existeix import. No pots importar cap mòdul extern. Els únics objectes disponibles automàticament (sense cap import) són:
| Disponible | Descripció |
|---|---|
iotv |
Control de vèrtebres digitals i analògiques |
time |
Només time.sleep(s) |
math |
Funcions matemàtiques bàsiques (math.sqrt, math.sin, etc.) |
random |
Números aleatoris (random.random(), random.randint()) |
PLCMemory |
Memòria clau-valor persistent entre execucions |
Qualsevol altra línia import (incloent import iotv o import time) generarà un error o simplement s'ignorarà.
# ❌ NO funciona al simulador
import iotv
import time
import math
# ✅ Correcte — res d'imports, tot ja està disponible
while True:
v = iotv.ain2v(iotv.ain("0x0", "b", 1))
time.sleep(0.1)
and, or, notEls operadors lògics and, or i not no funcionen al transpilador. Si els uses, el programa es comportarà de manera inesperada o donarà error.
Solució: substitueix cada condició composta per if niuats.
# ❌ NO funciona
if r == 1 and g == 1 and b == 1:
iotv.doutbit("0x0", "a", 3, 1)
# ✅ Correcte — if niuats
if r == 1:
if g == 1:
if b == 1:
iotv.doutbit("0x0", "a", 3, 1)
# ❌ NO funciona
if emergencia == 1 or alarma == 1:
aturar_motor()
# ✅ Correcte — comprova cada condició per separat
if emergencia == 1:
aturar_motor()
if alarma == 1:
aturar_motor()
class)La definició de classes amb class no és suportada.
# ❌ NO funciona
class Motor:
def __init__(self, addr):
self.addr = addr
def encendre(self):
iotv.doutbit(self.addr, "a", 0, 1)
Solució: usa funcions simples de primer nivell (def) i passa les variables com a paràmetres.
# ✅ Correcte
def encendre_motor(addr):
iotv.doutbit(addr, "a", 0, 1)
def aturar_motor(addr):
iotv.doutbit(addr, "a", 0, 0)
encendre_motor("0x0")
Pots definir funcions amb def, però sempre al primer nivell del programa — mai dins d'una altra funció.
# ❌ NO funciona — funció niuada
def gestionar_motor():
def encendre(): # ← niuada dins gestionar_motor
iotv.doutbit("0x0", "a", 0, 1)
encendre()
# ✅ Correcte — totes les funcions al primer nivell
def encendre():
iotv.doutbit("0x0", "a", 0, 1)
def gestionar_motor():
encendre()
Les expressions de llista en una línia (list comprehensions) no funcionen.
# ❌ NO funciona
valors = [iotv.ain("0x0", "b", ch) for ch in range(1, 5)]
# ✅ Correcte — bucle for explícit
valors = []
for ch in range(1, 5):
valors.append(iotv.ain("0x0", "b", ch))
Les f-strings simples poden funcionar en alguns casos, però les que contenen expressions o càlculs fallen. És més segur usar concatenació de strings o print() amb múltiples arguments.
# ❌ Arriscat — pot fallar
print(f"Temperatura: {int(temp * 10) / 10} °C")
# ✅ Correcte — múltiples arguments a print
print("Temperatura:", int(temp * 10) / 10, "°C")
# ✅ Correcte — concatenació amb str()
print("Temperatura: " + str(int(temp * 10) / 10) + " °C")
try / except / finally)Els blocs de gestió d'errors no funcionen al simulador.
# ❌ NO funciona
try:
valor = iotv.ain("0x0", "b", 1)
except:
valor = 0
# ✅ Correcte — comprova el valor directament
valor = iotv.ain("0x0", "b", 1)
if valor == "Error":
valor = 0
lambda, *args, **kwargsLes funcions anònimes lambda i els arguments variables no estan suportats.
# ❌ NO funciona
doble = lambda x: x * 2
# ✅ Correcte — funció normal
def doble(x):
return x * 2
global i nonlocalLes paraules clau global i nonlocal no funcionen. Totes les variables del programa es comparteixen automàticament entre funcions al simulador.
# ❌ NO funciona (i no cal)
comptador = 0
def incrementar():
global comptador # ← el transpilador no ho suporta
comptador = comptador + 1
# ✅ Correcte — usa la variable directament, sense global
comptador = 0
def incrementar():
comptador = comptador + 1 # funciona perquè les vars són globals al sim
yield i generadorsLes funcions generadores amb yield no estan suportades.
round()La funció round() pot tenir comportaments inesperats al transpilador. Per arrodonir a N decimals usa la divisió entera:
# ❌ Pot donar resultats estranys
valor = round(temperatura, 1)
# ✅ Correcte — arrodoniment manual a 1 decimal
valor = int(temperatura * 10) / 10
# ✅ Correcte — arrodoniment a enter
valor = int(temperatura)
Al simulador s'usa el format hexadecimal en string: "0x0", "0x1", "0x2"...
A la Raspberry Pi real s'usa el format binari en string: '0000', '0001', '0010'...
# Simulador web
iotv.dinbit("0x0", "b", 0)
# Raspberry Pi real (can_iotv_v2_1)
iotv.dinbit('0000', 'B', 0)
| Construcció | Simulador | RPi real |
|---|---|---|
import |
❌ no cal (ja tot disponible) | ✅ necessari |
and / or |
❌ usa if niuats |
✅ funciona |
class |
❌ | ✅ |
def primer nivell |
✅ | ✅ |
def niuada |
❌ | ✅ |
| List comprehension | ❌ usa for explícit |
✅ |
try / except |
❌ usa if |
✅ |
f-string simple |
⚠ arriscat | ✅ |
f-string amb càlcul |
❌ usa print(a, b, c) |
✅ |
lambda |
❌ | ✅ |
global / nonlocal |
❌ no cal | ✅ necessari |
yield |
❌ | ✅ |
round() |
⚠ usa int(x*10)/10 |
✅ |
| Adreça vèrtebra | "0x0" |
'0000' |