Diferència entre revisions de la pàgina «API de Python per a l'IoT-Vertebrae»
| m (→canOff()) | |||
| (Hi ha 66 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: [https://www.binefa.cat/IoT/IoT-Vertebrae/api/python/i2c_iotv.py '''i2c_iotv.py'''] (abans ''iotv.py'') i [https://www.binefa.cat/IoT/IoT-Vertebrae/api/python/can_iotv.py '''can_iotv.py''']. | 
| − | '''can_iotv.py''': funciona a partir de la  | + | [https://www.binefa.cat/IoT/IoT-Vertebrae/api/python/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. | + | [https://www.binefa.cat/IoT/IoT-Vertebrae/api/python/i2c_iotv.py '''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 = | ||
| + | == /boot/firmware/config.txt == | ||
| + |  '''dtparam=i2c_arm=on''' | ||
| + |  #dtparam=i2s=on | ||
| + |  '''dtparam=spi=on''' | ||
| + | |||
| + |  # CAN Bus: https://domoticx.com/raspberry-pi-can-bus-communicatie-gpio/ | ||
| + |  '''dtoverlay=mcp2515-can0,oscillator=8000000,interrupt=6,spimaxfrequency=1000000''' | ||
| + |  '''dtoverlay=spi-bcm2835-overlay''' | ||
| == Ú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). | 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). | ||
| + | |||
| + |  sudo apt install -y python3-can | ||
|   pi@raspberrypi:~ $ '''python''' |   pi@raspberrypi:~ $ '''python''' | ||
| Línia 64: | Línia 74: | ||
| 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 71: | Línia 82: | ||
|   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 21:17, 18 abr 2025
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
/boot/firmware/config.txt
dtparam=i2c_arm=on #dtparam=i2s=on dtparam=spi=on # CAN Bus: https://domoticx.com/raspberry-pi-can-bus-communicatie-gpio/ dtoverlay=mcp2515-can0,oscillator=8000000,interrupt=6,spimaxfrequency=1000000 dtoverlay=spi-bcm2835-overlay
Ú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).
sudo apt install -y python3-can
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

