Diferència entre revisions de la pàgina «API de Python per a l'IoT-Vertebrae»
(Hi ha 7 revisions intermèdies del mateix usuari que no es mostren) | |||
Línia 260: | Línia 260: | ||
9.29 | 9.29 | ||
= Recepció asíncrona de dades = | = Recepció asíncrona de dades = | ||
− | Codi d'exemple: | + | * Codi d'exemple: |
#!/usr/bin/env python | #!/usr/bin/env python | ||
+ | # can_async.py | ||
import can_iotv as iotv | import can_iotv as iotv | ||
− | import can | + | '''import can''' |
def decodeCanMsg(md): | def decodeCanMsg(md): | ||
Línia 288: | Línia 289: | ||
vertCfg += "B touch sensors " | vertCfg += "B touch sensors " | ||
bVal = "0x%X"%(md[4]) | bVal = "0x%X"%(md[4]) | ||
− | print("Digital vertebra 0x%X has '%s'. Firmware version %d.%d"%(arb_id&0xFF,vertCfg,md[1],md[2])) | + | print("Digital vertebra 0x%X (can ID: 0x%X) has '%s'. Firmware version %d.%d"%(arb_id&0xFF,arb_id,vertCfg,md[1],md[2])) |
print("A: %s, B: %s"%(aVal,bVal)) | print("A: %s, B: %s"%(aVal,bVal)) | ||
iotv.canOn() | iotv.canOn() | ||
try: | try: | ||
− | bus = can.interface.Bus(channel = 'can0', bustype = 'socketcan') | + | '''bus = can.interface.Bus(channel = 'can0', bustype = 'socketcan')''' |
while True: | while True: | ||
− | message = bus.recv(10.0) # 10.0 seconds timeout | + | '''message = bus.recv(10.0)''' # 10.0 seconds timeout |
if message is None: | if message is None: | ||
# print('Timeout occurred, no message received.') | # print('Timeout occurred, no message received.') | ||
Línia 301: | Línia 302: | ||
else: | else: | ||
arb_id = message.arbitration_id | arb_id = message.arbitration_id | ||
− | if arb_id & 0x400: # Async data is sent with this mask | + | if arb_id & '''0x400''': # Async data is sent from digital vertebra with this mask |
− | decodeCanMsg(message.data) | + | '''decodeCanMsg(message.data)''' |
except KeyboardInterrupt: | except KeyboardInterrupt: | ||
iotv.canOff() | iotv.canOff() | ||
− | Execució del codi: | + | * Execució del codi: |
− | pi@raspberrypi:~ $ python | + | pi@raspberrypi:~ $ '''python can_async.py''' |
− | Digital vertebra 0x20 has 'A output B input '. Firmware version 1.5 | + | Digital vertebra 0x20 (can ID: 0x420) has 'A output B input '. Firmware version 1.5 |
+ | A: 0xFF, B: 0x25 | ||
+ | Digital vertebra 0x20 (can ID: 0x420) has 'A output B input '. Firmware version 1.5 | ||
A: 0xFF, B: 0x24 | A: 0xFF, B: 0x24 | ||
− | + | * Interpretació de l'execució: | |
− | |||
− | Interpretació de l'execució: | ||
− | Cada cop que hi ha un canvi a una costella d'entrada es tramet un missatge pel bus CAN. El missatge ens identifica de quina | + | Cada cop que hi ha un canvi a una costella d'entrada es tramet un missatge pel bus CAN. El missatge ens identifica de quina vèrtebra prové, la configuració de la vèrtebra, la versió del microprogramari i el valor a les dues costelles. |
− | La primera recepció ens diu que a la costella d'entrada B hi ha hagut un canvi i ara hi ha | + | La primera recepció ens diu que a la costella d'entrada B hi ha hagut un canvi i ara hi ha 0x25 (0010010'''1'''). Mentre que a la costella A de sortida tot són 1: 0xFF (11111111): |
− | Digital vertebra 0x20 has 'A output B input '. Firmware version 1.5 | + | Digital vertebra 0x20 (can ID: 0x420) has 'A output B input '. Firmware version 1.5 |
− | A: 0xFF, | + | A: 0xFF, B: 0x25 |
− | A la segona execució ens diu que a la costella d'entrada B hi ha hagut un canvi i ara hi ha | + | A la segona execució ens diu que a la costella d'entrada B hi ha hagut un canvi i ara hi ha 0x24 (0010010'''0'''). Mentre que a la costella A de sortida tot són 1: 0xFF (11111111): |
− | Digital vertebra 0x20 has 'A output B input '. Firmware version 1.5 | + | Digital vertebra 0x20 (can ID: 0x420) has 'A output B input '. Firmware version 1.5 |
− | A: | + | A: 0xFF, B: 0x24 |
Revisió de 11:08, 22 ago 2024
Hi ha dues biblioteques per a interactuar en Python des de la Raspberry Pi amb l'IoT-Vertebrae: i2c_iotv.py (abans iotv.py) i can_iotv.py.
can_iotv.py: funciona a partir de la versió 2.0 del cap. Es comunica mitjançant el bus CAN, això permet controlar vèrtebres connectades remotament a una cua.
i2c_iotv.py: funciona amb qualsevol versió de cap. Es comunica mitjançant el bus I2C.
Contingut
- 1 Ús de les biblioteques des del terminal
- 2 canOn()
- 3 canOff()
- 4 dversion(addr)
- 5 aversion(addr)
- 6 getdsetup(addr)
- 7 getasetup(addr)
- 8 dsetup(addr,modeA,modeB)
- 9 dout(addr,side,value)
- 10 din(addr, side)
- 11 doutbit(addr, side, posbyte, value)
- 12 doutbitpwm(addr, side, posbyte, value)
- 13 v2aout(voltage0_10)
- 14 ain2v(ainValue)
- 15 aout(addr, side, ndac, value)
- 16 ain(addr, side, nadc)
- 17 Recepció asíncrona de dades
Ús de les biblioteques des del terminal
Ús de can_iotv.py des del terminal
Cal obrir el bus CAN cal al principi del codi i podem tancar-ho al final. L'obertura i tancament del bus CAN es fa mitjançant ordres de terminal (molt més lentes d'executar que les instruccions Python).
pi@raspberrypi:~ $ python Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import can_iotv as iotv >>> iotv.canOn() >>> iotv.dversion("0000") '1.2' >>> iotv.aversion("0000") '1.3' >>> iotv.canOff() >>> pi@raspberrypi:~ $
Ús de i2c_iotv.py des del terminal
No cal obrir el bus I2C al principi i tancar-ho al final perquè cada funció l'obre i el tanca mitjançant instruccions de Python.
pi@raspberrypi:~ $ python Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import i2c_iotv as iotv >>> iotv.dversion("0000") Digital rib version: 1.2 '0000000100000010' >>> iotv.aversion("0000") Analog rib version: 1.3 '0000000100000011' >>> pi@raspberrypi:~ $
canOn()
Obertura del bus CAN (tan sols té sentit amb el paquet can_iotv. No pas amb el paquet i2c_iotv):
>>> iotv.canOn()
Es posa a l'inici de qualsevol programa que vulgui fer servir el paquet can_iotv. Aquesta funció tramet al sistema aquesta ordre de terminal:
sudo ip link set up can0 type can bitrate 100000
canOff()
Tancament del bus CAN (tan sols té sentit amb el paquet can_iotv. No pas amb el paquet i2c_iotv):
>>> iotv.canOff()
Es pot posar al final de qualsevol programa que vulgui fer servir el paquet can_iotv. Aquesta funció tramet al sistema aquesta ordre de terminal:
sudo ifconfig can0 down
dversion(addr)
L'argument addr és l'adreça de la vèrtebra digital expressada com un text de quatre zeros i uns. Aquí hi ha un enllaç a l'explicació de les adreces de la vèrtebra digital.
Retorna la versió de microprogramari (firmware) de la vèrtebra amb l'adreça passada com a argument.
- can_iotv:
>>> iotv.dversion("0000") '1.2'
- i2c_iotv:
>>> iotv.dversion("0000") Digital rib version: 1.2 '0000000100000010'
aversion(addr)
L'argument addr és l'adreça de la vèrtebra analògica expressada com un text de quatre zeros i uns. Aquí hi ha un enllaç a l'explicació de les adreces de la vèrtebra analògica.
Retorna la versió de microprogramari (firmware) de la vèrtebra amb l'adreça passada com a argument.
- can_iotv:
>>> iotv.aversion("0000") '1.3'
- i2c_iotv:
>>> iotv.aversion("0000") Analog rib version: 1.3 '0000000100000011'
getdsetup(addr)
L'argument addr és l'adreça de la vèrtebra digital expressada com un text de quatre zeros i uns. Aquí hi ha un enllaç a l'explicació de les adreces de la vèrtebra digital.
Retorna la configuració de la vèrtebra digital amb l'adreça passada com a argument. Les vèrtebres digitals s'han de configurar amb la funció dsetup(addr, modeA, modeB) per a indicar que es connecta a cada costat.
- can_iotv:
>>> iotv.getdsetup("0000") 'A:dout, B:din'
- i2c_iotv:
>>> iotv.getdsetup("0000") A digital output, B digital input '00010010'
Configuracions possibles als dos costats (A i B):
ain: Entrades digitals al costat A
aout: Sortides digitals al costat A
aoutpwm: Sortides digitals per modulació de pols (PWM) al costat A. Si hi ha aoutpwm no pot haver boutpwm (limitació pròpia de l'ESP32-S3).
bin: Entrades digitals al costat B
bout: Sortides digitals al costat B
boutpwm: Sortides digitals per modulació de pols (PWM) al costat B. Si hi ha boutpwm no pot haver aoutpwm (limitació pròpia de l'ESP32-S3).
bintouch: Entrades tàctils al costat B. No existeix aintouch perquè el maquinari no ho permet.
getasetup(addr)
L'argument addr és l'adreça de la vèrtebra analògica expressada com un text de quatre zeros i uns. Aquí hi ha un enllaç a l'explicació de les adreces de la vèrtebra analògica.
Retorna la configuració de la vèrtebra analògica amb l'adreça passada com a argument. Les vèrtebres analògiques no cal configurar-les, després del reset fan la lectura del que hi ha connectat a cada costat (ADC i/o DAC).
- can_iotv:
>>> iotv.getasetup("0000") 'A:ain, B:aout'
- i2c_iotv:
>>> iotv.getasetup("0000") respA: 0x1, respB: 0x2 A rib is ADC, B rib is DAC. '00010010'
dsetup(addr,modeA,modeB)
L'argument addr és l'adreça de la vèrtebra digital expressada com un text de quatre zeros i uns. Aquí hi ha un enllaç a l'explicació de les adreces de la vèrtebra digital.
L'argument modeA pot ser: ain, aout o aoutpwm
L'argument modeB pot ser: bin, bout, boutpwm o bintouch
- can_iotv: <-- CAL VERIFICAR SI FUNCIONA COM S'ESPERA
>>> iotv.dsetup('0000','aout','bin') a: aout, b: bin 'A:dout, B:din'
- i2c_iotv:
>>> iotv.dsetup('0000','ain','bout') ain, bout True
Configuracions possibles als dos costats (A i B):
ain: Entrades digitals al costat A
aout: Sortides digitals al costat A
aoutpwm: Sortides digitals per modulació de pols (PWM) al costat A. Si hi ha aoutpwm no pot haver boutpwm (limitació pròpia de l'ESP32-S3).
bin: Entrades digitals al costat B
bout: Sortides digitals al costat B
boutpwm: Sortides digitals per modulació de pols (PWM) al costat B. Si hi ha boutpwm no pot haver aoutpwm (limitació pròpia de l'ESP32-S3).
bintouch: Entrades tàctils al costat B. No existeix aintouch perquè el maquinari no ho permet.
dout(addr,side,value)
Funció a les dues biblioteques i2c_iotv i can_iotv. La configuració de la vèrtebra ha de ser coherent (el costat i el tipus han de coincidir: aout pel costat A o bout pel costat B).
L'argument addr és l'adreça de la vèrtebra digital expressada com un text de quatre zeros i uns. Aquí hi ha un enllaç a l'explicació de les adreces de la vèrtebra digital.
L'argument side és 'A' o 'B'.
L'argument value és 0 o 1.
>>> iotv.dout('0000','A',0xFF) # Es tramet 0xFF (11111111) al costat A de la vèrtebra digital amb adreça '0000' >>> iotv.dout('0000','A',0x5A) # Es tramet 0x5A (01011010) al costat A de la vèrtebra digital amb adreça '0000' >>> iotv.dout('0000','A',0xA5) # Es tramet 0xA5 (10100101) al costat A de la vèrtebra digital amb adreça '0000' >>> iotv.dout('0000','A',0x00) # Es tramet 0x00 (00000000) al costat A de la vèrtebra digital amb adreça '0000'
din(addr, side)
Funció a les dues biblioteques i2c_iotv i can_iotv. La configuració de la vèrtebra ha de ser coherent (el costat i el tipus han de coincidir: ain pel costat A o bin pel costat B).
L'argument addr és l'adreça de la vèrtebra digital expressada com un text de quatre zeros i uns. Aquí hi ha un enllaç a l'explicació de les adreces de la vèrtebra digital.
L'argument side és 'A' o 'B'.
>>> iotv.din('0000','B') '00100100'
doutbit(addr, side, posbyte, value)
Funció a les dues biblioteques i2c_iotv i can_iotv. La configuració de la vèrtebra ha de ser coherent (el costat i el tipus han de coincidir: aout pel costat A o bout pel costat B).
L'argument addr és l'adreça de la vèrtebra digital expressada com un text de quatre zeros i uns. Aquí hi ha un enllaç a l'explicació de les adreces de la vèrtebra digital.
L'argument side és 'A' o 'B'.
L'argument posbyte és un valor entre 0 i 7.
L'argument value és 0 o 1.
Un exemple d'ús:
for i in range(10): for bit in range(8): iotv.doutbit('0000','A',bit,1) sleep(.05) iotv.doutbit('0000','A',bit,0)
doutbitpwm(addr, side, posbyte, value)
Funció de la biblioteca i2c_iotv. La configuració de la vèrtebra ha de ser coherent (el costat i el tipus han de coincidir: aoutpwm pel costat A o boutpwm pel costat B).
L'argument addr és l'adreça de la vèrtebra digital expressada com un text de quatre zeros i uns. Aquí hi ha un enllaç a l'explicació de les adreces de la vèrtebra digital.
L'argument side és 'A' o 'B'.
L'argument posbyte és un valor entre 0 i 7.
L'argument value és un valor entre 0 i 255.
v2aout(voltage0_10)
Funció convertidora de tensió del ventall de 0V a 10V al ventall de 0 a 4095 per al convertidor digital a analògic (DAC) de 12 bits. En cas que el valor a retornar sigui superior a 4095 retorna 4095. En cas que el valor a retornar sigui inferior a 0 retorna 0. Aquesta protecció es fa servir perquè trametre un valor superior a 4095 al DAC farà que la tensió quedi registrada a llur EEPROM al valor tramès menys 4095.
>>> iotv.v2aout(10) 4095 >>> iotv.v2aout(10.5) 4095 >>> iotv.v2aout(5) 2048 >>> iotv.v2aout(0) 0 >>> iotv.v2aout(-0.2) 0
ain2v(ainValue)
Funció convertidora de tensió a partir del resultat del convertidor analògic a digital (ADC) de 16 bits retornant valors de -10V a +10V.
>>> iotv.ain2v(26624) 10.0 >>> iotv.ain2v(0) -10.0 >>> iotv.ain2v(13312) 0.0 >>> iotv.ain2v(20000) 5.02
aout(addr, side, ndac, value)
Funció d'escriptura d'un valor analògic value (entre 0 i 4095) al convertidor digital analògic ndac (entre 1 i 4) del costat side (A o B) de l'adreça addr (entre 0000 i 1111) de la vèrtebra analògica.
L'argument addr és l'adreça de la vèrtebra analògica expressada com un text de quatre zeros i uns. Aquí hi ha un enllaç a l'explicació de les adreces de la vèrtebra analògica.
L'argument side és 'A' o 'B'.
L'argument ndac és 1, 2, 3 o 4.
L'argument value és un valor entre 0 i 4095 (o 0x0000 i 0x0FFF). 0 és 0 volts. 4095 és 10 volts.
>>> iotv.ain2v(iotv.ain('0000','A',4)) # Lectura de l'entrada 4 de la costella analògica d'entrades connectada (amb adreça 0000) al costat A 4.98 >>> iotv.aout('0000','B',4,iotv.v2aout(9.3)) # Per a escriure 9.3 volts a la sortida 4 de la costella analògica de sortides connectada (amb adreça 0000) al costat B >>> iotv.ain2v(iotv.ain('0000','A',4)) # Lectura de l'entrada 4 de la costella analògica d'entrades connectada (amb adreça 0000) al costat A 9.29
És convenient fer servir un limitador de valor (màxim de 4095) com la funció v2aout() per a evitar enregistrar l'EEPROM quan no es vulgui.
Enregistrar el valor d'aout() a l'EEPROM del DAC
Per a tenir un valor concret a un DAC entre 0V i 10V quan s'engega l'IoT-Vertebrae (per exemple si interessa arrencar amb el llum apagat en el cas de fer controls de llum 0/1-10V), sense esperar que el cap o la Raspberry Pi s'iniciïn, cal escriure el valor desitjat de 12 bits sumant-li 4096. Això farà que el valor quedi enregistrat per defecte a l'EEPROM del DAC.
>>> iotv.aout('0000','B',4,4096+iotv.v2aout(9.3)) # Per a escriure a l'EEPROM del DAC 9.3 volts a la sortida 4 de la costella analògica de sortides connectada (amb adreça 0000) al costat B
És convenient fer aquesta operació de manera excepcional, no fer-ho de manera contínua. Es recomana no fer més de 20000 escriptures a l'EEPROM.
Aquesta solució és la que està implementada al microprogramari de la vèrtebra analògica i així no haver de posar més arguments a la funció aout(). Per això és convenient fer servir un limitador de valor (màxim de 4095) com la funció v2aout() per a evitar enregistrar l'EEPROM quan no es vulgui.
ain(addr, side, nadc)
Funció de lectura d'un valor analògic de 16 bits (representant un valor entre -10V i +10V) al convertidor analògic digital nadc (entre 1 i 4) del costat side (A o B) de l'adreça addr (entre 0000 i 1111) de la vèrtebra analògica.
L'argument addr és l'adreça de la vèrtebra analògica expressada com un text de quatre zeros i uns. Aquí hi ha un enllaç a l'explicació de les adreces de la vèrtebra analògica.
L'argument side és 'A' o 'B'.
L'argument nadc és 1, 2, 3 o 4.
Retorna un valor de 16 bits com a lectura d'un valor analògic entre -10V i +10V. Per a convertir-ho a tensió podeu emprar la funció ain2v().
>>> iotv.ain2v(iotv.ain('0000','A',4)) # Lectura de l'entrada 4 de la costella analògica d'entrades connectada (amb adreça 0000) al costat A 4.98 >>> iotv.aout('0000','B',4,iotv.v2aout(9.3)) # Per a escriure 9.3 volts a la sortida 4 de la costella analògica de sortides connectada (amb adreça 0000) al costat B >>> iotv.ain2v(iotv.ain('0000','A',4)) # Lectura de l'entrada 4 de la costella analògica d'entrades connectada (amb adreça 0000) al costat A 9.29
Recepció asíncrona de dades
- Codi d'exemple:
#!/usr/bin/env python # can_async.py import can_iotv as iotv import can def decodeCanMsg(md): if len(md) == 5: vertCfg = "" aVal = bVal = "" if md[0] & 0x01: vertCfg += "A input " aVal = "0x%X"%(0xFF&~md[3]) if md[0] & 0x02: vertCfg += "A output " aVal = "0x%X"%(md[3]) if md[0] & 0x04: vertCfg += "A pwm " if md[0] & 0x10: vertCfg += "B input " bVal = "0x%X"%(0xFF&~md[4]) if md[0] & 0x20: vertCfg += "B output " bVal = "0x%X"%(md[4]) if md[0] & 0x40: vertCfg += "B pwm " if md[0] & 0x80: vertCfg += "B touch sensors " bVal = "0x%X"%(md[4]) print("Digital vertebra 0x%X (can ID: 0x%X) has '%s'. Firmware version %d.%d"%(arb_id&0xFF,arb_id,vertCfg,md[1],md[2])) print("A: %s, B: %s"%(aVal,bVal)) iotv.canOn() try: bus = can.interface.Bus(channel = 'can0', bustype = 'socketcan') while True: message = bus.recv(10.0) # 10.0 seconds timeout if message is None: # print('Timeout occurred, no message received.') pass else: arb_id = message.arbitration_id if arb_id & 0x400: # Async data is sent from digital vertebra with this mask decodeCanMsg(message.data) except KeyboardInterrupt: iotv.canOff()
- Execució del codi:
pi@raspberrypi:~ $ python can_async.py Digital vertebra 0x20 (can ID: 0x420) has 'A output B input '. Firmware version 1.5 A: 0xFF, B: 0x25 Digital vertebra 0x20 (can ID: 0x420) has 'A output B input '. Firmware version 1.5 A: 0xFF, B: 0x24
- Interpretació de l'execució:
Cada cop que hi ha un canvi a una costella d'entrada es tramet un missatge pel bus CAN. El missatge ens identifica de quina vèrtebra prové, la configuració de la vèrtebra, la versió del microprogramari i el valor a les dues costelles.
La primera recepció ens diu que a la costella d'entrada B hi ha hagut un canvi i ara hi ha 0x25 (00100101). Mentre que a la costella A de sortida tot són 1: 0xFF (11111111):
Digital vertebra 0x20 (can ID: 0x420) has 'A output B input '. Firmware version 1.5 A: 0xFF, B: 0x25
A la segona execució ens diu que a la costella d'entrada B hi ha hagut un canvi i ara hi ha 0x24 (00100100). Mentre que a la costella A de sortida tot són 1: 0xFF (11111111):
Digital vertebra 0x20 (can ID: 0x420) has 'A output B input '. Firmware version 1.5 A: 0xFF, B: 0x24