I2C en CircuitPython

I2C es un protocolo de dos cables para comunicarse con sensores simples y dispositivos, lo que quiere decir que usa dos conexiones para transmitir y recibir datos. Existen muchos dispositivos I2C disponibles y son muy sencillos de utilizar con CircuitPython. Tenemos librerías para muchos dispositivos I2C en nuestro compilado de librerías. (Si no ves tu sensor, sigue revisando cada tanto, ¡escribimos más todo el tiempo!)

En esta sección, vamos a aprender como escanear el bus I2C para buscar dispositivos conectados. Luego vamos a aprender como interactuar con un dispositivo I2C.

Vamos a utilizar el TSL2561, un sensor de luz muy común y de bajo costo. Mientras que el código que ejecutamos es específico para el TSL2561, el proceso general es el mismo para cualquier sensor o dispositivo I2C.

¡Vas a necesitar la librería adafruit_tsl2561.mpy y la librería adafruit_bus_device en tu carpeta /lib si no los has copiado todavía! Los puedes conseguir del compilado de Librerías para CircuitPython. Si necesita ayuda instalando la librería, revise la página de Librerías para CircuitPython.

Estos ejemplos van a utilizar el sensor de lux TSL2561 versión Flora y versión breakout. Lo primero que quieres hacer es conectar el sensor I2C para que tu tarjeta tenga con quién hablar.

Cableándolo

Vas a necesitar un par de cosas para conectar el TSL2561 a tu tarjeta.

Para las Gemma M0 y las Circuit Playground Express, puede utilizar cables de lagarto para conectarse a la versión Flora del sensor de lux TSL2561.

Para las Trinket M0, Feather M0 Express, Metro M0 Express y las ItsyBitsy M0 Express, vas a necesitar una tabla de prototipo y cables para conectarse a la versión Breakout del sensor de lux TSL2561.

Hemos incluido diagramas para mostrarte como conectar la TSL2561 a tu tarjeta. En estos diagramas el color de los cables es el mismo para los pines de cualquier tarjeta.

  • El cable negro conecta entre los pines de tierra (ground).
  • El cable negro conecta entre los pines de alimentación de la TSL2561 y tu tarjeta.
  • El cable amarillo conecta del SCL de tu TSL2561 a SCL de tu tarjeta.
  • El cable azul conecta de SDA de tu TSL2561 a SDA de tu tarjeta.

¡Revisar la lista a continuación para el diagrama de tu tarjeta!

¡Tenga cuidado que las microcontroladoras de Adafruit no tienen resistencias de I2C integradas! Los breakouts si los tienen, pero si estás construyendo tu propia tarjeta o usando un breakout de otra marca que no sea Adafruit, debes agregar resistencias de 2.2K-10K ohms en función de pull-up para ambos SDA y SCL hacia 3.3V.

Circuit Playground Express y Circuit Playground Bluefruit

  • Conecte 3.3v de la CPX a 3.3v del TSL2561.
  • Conecte GND de la CPX a GND del TSL2561.
  • Conecte SCL/A4 de la CPX a SCL del TSL2561.
  • Conecte SDL/A5 de la CPX a SDA del TSL2561.

Trinket M0

  • Conecte USB de la Trinket a VIN del TSL2561.
  • Conecte Gnd de la Trinket a GND del TSL2561.
  • Conecte D2 de la Trinket a SCL del TSL2561.
  • Conecte D0 de la Trinket a SDA del TSL2561.

Gemma M0

  • Conecte 3vo de la Gemma a 3V del TSL2561.
  • Conecte GND de la Gemma a GND del TSL2561.
  • Conecte A1/D2 de la Gemma a SCL del TSL2561.
  • Conecte A2/D0 de la Gemma a SDA del TSL2561.

Feather M0 Express and Feather M4 Express

  • Conecte USB de la Feather a VIN del TSL2561.
  • Conecte GND de la Feather a GND del TSL2561.
  • Conecte SCL de la Feather a SCL del TSL2561.
  • Conecte SDA de la Feather a SDA del TSL2561.

ItsyBitsy M0 Express y ItsyBitsy M4 Express

  • Conecte USB de la ItsyBitsy a VIN del TSL2561.
  • Conecte G de la ItsyBitsy a GND del TSL2561.
  • Conecte SCL de la ItsyBitsy a SCL del TSL2561.
  • Conecte SDA de la ItsyBitsy a SDA del TSL2561.

Metro M0 Express y Metro M4 Express

  • Conecte 5V de la Metro a VIN del TSL2561.
  • Conecte GND de la Metro a GND del TSL2561.
  • Conecte SCL de la Metro a SCL del TSL2561.
  • Conecte SDA de la Metro a SDA del TSL2561.

Encontrando tu Sensor

Lo primero que quieres hacer luego de cablear tu sensor, es asegurarse que esté conectado correctamente. Vamos a realizar un escaneo del bus I2C para ver si la tarjeta está conectada, y si lo está, imprima su dirección I2C.

Copie y pegue el código hacia code.py utilizando su editor favorito, y salve el archivo.

# CircuitPython demo - I2C scan

import time

import board
import busio

i2c = busio.I2C(board.SCL, board.SDA)

while not i2c.try_lock():
    pass

while True:
    print("I2C addresses found:", [hex(device_address)
                                   for device_address in i2c.scan()])
    time.sleep(2)

Primero creamos un objeto i2c y le enviamos los pines I2C: board.SCL y board.SDA.

Para poder escanearlo, debemos amarrar a I2C para que la única cosa que lo acceda sea este código. Luego incluimos un ciclo que se espera hasta que I2C esté amarrado y luego continúa a la función de escaneado.

Por último, tenemos un ciclo que ejecuta el escaneo como tal, i2c_scan(). Dado que I2C normalmente se refiere a sus direcciones en formato hexadecimal, hemos incluido un poco de código para retornar los resultados en este formado:[hex(device_address) for device_address in i2c.scan()].

¡Abra la consola serial para ver los resultados! El código imprime un arreglo de direcciones. Hemos conectado el TSL2561 el cual tiene una dirección de 7-bits de I2C de 0x39. El resultado para este sensor es I2C addresses found: ['0x39']. Si no retornan direcciones, revise los diagramas de cableado para verificar que ha cableado su sensor de forma correcta.

Datos del Sensor I2C

Ahora tenemos certeza de que nuestro sensor se encuentra conectado y listo para usar. ¡Ahora vamos a aprender como leer los datos del sensor!

Copie y pegue este código dentro de code.py utilizando su editor favorito y salve el archivo.

# CircuitPython Demo - I2C sensor

import time

import adafruit_tsl2561
import board
import busio

i2c = busio.I2C(board.SCL, board.SDA)

# Lock the I2C device before we try to scan
while not i2c.try_lock():
    pass
# Print the addresses found once
print("I2C addresses found:", [hex(device_address)
                               for device_address in i2c.scan()])

# Unlock I2C now that we're done scanning.
i2c.unlock()

# Create library object on our I2C port
tsl2561 = adafruit_tsl2561.TSL2561(i2c)

# Use the object to print the sensor readings
while True:
    print("Lux:", tsl2561.lux)
    time.sleep(1.0)

Este código comienza de la misma forma que el código de escaneo. Hemos incluido el código de escaneo para que tengas verificación de que tu sensor está conectado correctamente y es detectado. Imprime su dirección una vez. Luego del escaneo, deamarramos el bus I2C con i2c_unlock() para que podamos usar el sensor para datos.

Creamos un objeto sensor utilizando la librería del sensor. Lo llamamos tsl2561  y nos provee el objeto i2c.

Luego tenemos un simple ciclo que imprime la lectura de lux usando el objeto de sensor que hemos creado. Agregamos un time.sleep(1.0), para que solo imprima una vez por segundo.  Saque la consola serial para ver los resultados. Trate alumbrando una luz al sensor para que vea como cambian los resultados.

¿Donde está mi I2C?

En las SAMD21, SAMD51 y nRF52840, tenemos la flexibilidad de poder usar una gama de pines para I2C. En las nRF52840, ¡cualquier pin puede ser usado para I2C! Algunos chips como las ESP8266, requieren uso de bitbangio, pero también puedes usar cualquier pin para I2C. Algunos otros chips tienen sus pines de I2C fijos.

La buena noticia es que puedes usar muchos, pero no todos los pines. Por la gran cantidad de tarjetas SAMD que tenemos, es imposible garantizar con otros pines que no sean los etiquetados como 'SDA' y 'SCL'.  Así que si desea otra configuración o múltiples interfaces I2C, ¿como encontramos esos pines? ¡Sencillo! Hemos escrito un script bien útil.

Todo lo que tiene que hacer es copiar este archivo a su tarjeta, renombrarlo como code.py, conectarse a la consola serial y ver el resultado. En la salida vemos una bonita lista con los pares de pines de SCL y SDA que puede utilizar.

Esto son los resultados para una ItsyBitsy M0 Express. Tu salida puede variar y puede ser muy larga. Para más detalles sobre I2C y comunicaciones seriales, revise nuestra guía detallada, aquí.

import board
import busio
from microcontroller import Pin

def is_hardware_I2C(scl, sda):
    try:
        p = busio.I2C(scl, sda)
        p.deinit()
        return True
    except ValueError:
        return False
    except RuntimeError:
        return True


def get_unique_pins():
    exclude = ['NEOPIXEL', 'APA102_MOSI', 'APA102_SCK']
    pins = [pin for pin in [
        getattr(board, p) for p in dir(board) if p not in exclude]
            if isinstance(pin, Pin)]
    unique = []
    for p in pins:
        if p not in unique:
            unique.append(p)
    return unique


for scl_pin in get_unique_pins():
    for sda_pin in get_unique_pins():
        if scl_pin is sda_pin:
            continue
        else:
            if is_hardware_I2C(scl_pin, sda_pin):
                print("SCL pin:", scl_pin, "\t SDA pin:", sda_pin)
            else:
                pass
This guide was first published on Jun 24, 2020. It was last updated on Jun 24, 2020.
This page (I2C en CircuitPython) was last updated on Jul 08, 2020.