Diferència entre revisions de la pàgina «API de Python per a l'IoT-Vertebrae»
m |
|||
(Hi ha 73 revisions intermèdies del mateix usuari que no es mostren) | |||
Línia 1: | Línia 1: | ||
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'''. | 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 [[Cap (Head v2.0) - IoT-Vertebrae|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. |
= Ús de les biblioteques des del terminal = | = Ús de les biblioteques des del terminal = | ||
== Ús de ''can_iotv.py'' 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''' | pi@raspberrypi:~ $ '''python''' | ||
Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux | Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux | ||
Línia 19: | Línia 20: | ||
>>> | >>> | ||
pi@raspberrypi:~ $ | pi@raspberrypi:~ $ | ||
+ | |||
== Ús de ''i2c_iotv.py'' des del terminal == | == Ú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. | + | 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''' | pi@raspberrypi:~ $ '''python''' | ||
Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux | Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux | ||
Línia 33: | Línia 35: | ||
>>> | >>> | ||
pi@raspberrypi:~ $ | 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'') = | = 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'[[Vertebra_digital_(dvert2_v2.1)_-_IoT-Vertebrae#Configuracions |explicació de les adreces de la vèrtebra digital]]. | 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'[[Vertebra_digital_(dvert2_v2.1)_-_IoT-Vertebrae#Configuracions |explicació de les adreces de la vèrtebra digital]]. | ||
Línia 49: | Línia 64: | ||
Retorna la '''versió de microprogramari (''firmware'') de la vèrtebra amb l'adreça passada com a argument'''. | Retorna la '''versió de microprogramari (''firmware'') de la vèrtebra amb l'adreça passada com a argument'''. | ||
+ | |||
* can_iotv: | * can_iotv: | ||
>>> '''iotv.aversion("0000")''' | >>> '''iotv.aversion("0000")''' | ||
Línia 56: | Línia 72: | ||
Analog rib version: 1.3 | Analog rib version: 1.3 | ||
'0000000100000011' | '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'[[Vertebra_digital_(dvert2_v2.1)_-_IoT-Vertebrae#Configuracions |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'[[Vertebra analògica (avert2 v2.1) - IoT-Vertebrae#Configuracions |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'[[Vertebra_digital_(dvert2_v2.1)_-_IoT-Vertebrae#Configuracions |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'[[Vertebra_digital_(dvert2_v2.1)_-_IoT-Vertebrae#Configuracions |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'[[Vertebra_digital_(dvert2_v2.1)_-_IoT-Vertebrae#Configuracions |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'[[Vertebra_digital_(dvert2_v2.1)_-_IoT-Vertebrae#Configuracions |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'[[Vertebra_digital_(dvert2_v2.1)_-_IoT-Vertebrae#Configuracions |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'[[Vertebra analògica (avert2 v2.1) - IoT-Vertebrae#Configuracions |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'[[Vertebra analògica (avert2 v2.1) - IoT-Vertebrae#Configuracions |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 (0010010'''1'''). 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 (0010010'''0'''). 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 |
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