2019年4月3日 星期三

Bridges - Pretend your PC a Raspberry Pi or an ESP32 to connect I2C/SPI/GPIO/UART peripherals

Grand Island bridges


Wei Lin
2019-4-2

[Usage Scenarios]

Read on if these scenarios suit you:

[Motivations]

  • Need to use some I2C/SPI/GPIO/UART interfaced device with my PC:    
    • One of my Python projects needs to use a SPI-interfaced device.     
    • However, there is no external SPI interface available on the PC, therefore comes the bus-converter.
  • Bus-Converters selection:
    • There are many USB to I2C/SPI/GPIO/UART converters available on the market. FT232H (1 channel) / FT2232H (2 channels) from FTDI and CH341 from WCH ... is popular. FTDI's documentation and development resources are quite complete and relatively easy to develop.     
    • PyFtdi was chosen to drive FTDI chips, it only depends on PyUSB. In addition, we nee also...
  • Drivers for the device:     
  • Requires Adapters to convert interfaces:     
  • Pretend your PC an ESP8266 / ESP32 / Raspberry Pi:     
    • As long as the device driver can run on a PC, and the SPI interface object it faces has exactly the same behavior of the SPI interface object on the ESP32, then the PC "IS" an ESP32 to the device driver. So in this cases, PC is an ESP32 simulator, at least to the device driver. So, we can...
  • Utilize powerful development resources and debugging environment from PC:    
    • For example, when developing a device driver, you can use PyCharm to set breakpoints and to inspect variables whenever needed. 
    • No more "print" to debug, no more repeatedly uploading code to the controller.
FT232HFT2232HCH341A

[Goals and Features]

  • Writing a package to simulate the I2C/SPI/GPIO/UART interface objects for MicroPython+ESP8266/ESP32 and Raspberry Pi on PC:
    • Interface objects in MicroPython + ESP8266 / ESP32 environment:
      • machine.I2C
      • machine.SPI
      • machine.Pin
      • machine.UART
    • Interface objects in the Raspberry Pi environment:
      • smbus2.SMbus
      • spidev.SpiDev
      • RPi.GPIO
      • PySerial.Serial
  • Can drive many bus-converters simultaneously:
    • Multiple bus-converters can be connected at the same time, and the number is limited only by the specification of USB and power supply capability.
  • Can function under Windows / Linux:
    • No modification is required.
  • Can be used on PC / Raspberry Pi or any machines that can run PyFtdi package:
    • No modification is required.

[How to use]

Simulating for MicroPython + ESP8266 / ESP32

# On ESP32 with MicroPython
from machine import I2C

i2c = I2C(freq = 400000)

# On PC
from bridges.ftdi.controllers.i2c import I2cController
I2C = I2cController().I2C

i2c = I2C(freq = 400000)

    
# On ESP32 with MicroPython
from machine import SPI

spi = SPI(id, baudrate = 10000000, polarity = 0, phase = 0)
spi.init()

# On PC
from bridges.ftdi.controllers.spi import SpiController
SPI = SpiController().SPI

spi = SPI(id, baudrate = 10000000, polarity = 0, phase = 0)
spi.init()
     
# On ESP32 with MicroPython
from machine import Pin

p0 = Pin(0, Pin.OUT)
p0.value(0)
p0.value(1)

p2 = Pin(2, Pin.IN, Pin.PULL_UP)
Print(p2.value())

# On PC
from bridges.interfaces.micropython.machine import Pin
from bridges.ftdi.controllers.gpio import GpioController
machine = GpioController()

p0 = machine.Pin(0, mode = Pin.OUT) 
p0.value(0)
p0.value(1)

p2 = Pin(2, Pin.IN, Pin.PULL_UP)
Print(p2.value())
  
# On ESP32 with MicroPython
from machine import UART

uart = UART(1, 9600)
uart.init(9600, bits=8, parity=None, stop=1)

# On PC
from bridges.ftdi.controllers.uart import UartController
UART = UartController().UART

uart = UART(1, 9600)
uart.init(9600, bits=8, parity=None, stop=1)

Simulating for Raspberry Pi

# On Raspberry
from smbus2 import SMBus 

bus = SMBus(1)
b = bus.read_byte_data(80, 0)
print(b) 

# On PC
from bridges.ftdi.controllers.i2c import I2cController
SMBus = I2cController().SMBus

bus = SMBus(1)  # the bus number actually doesn't matter.
b = bus.read_byte_data(80, 0)
print(b) 
# On Raspberry
import spidev

spi = spidev.SpiDev()
spi.open(bus, device)
to_send = [0x01, 0x02, 0x03]
spi.xfer(to_send)

# On PC 
from bridges.ftdi.controllers.spi import SpiController
spidev = SpiController() 

spi = spidev.SpiDev()
spi.open(bus, device)
to_send = [0x01, 0x02, 0x03]
spi.xfer(to_send)

# On Raspberry
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BOARD) 
GPIO.setup(6, GPIO.OUT)

# On PC
from bridges.ftdi.adapters.rpi.RPi import GPIO 

GPIO.setmode(GPIO.BOARD)  # mode actuall doesn't matter.
GPIO.setup(6, GPIO.OUT)

# On Raspberry
import serial
ser = serial.Serial('/dev/ttyUSB0') 

print(ser.name)        
ser.write(b'hello')     
ser.close()            

# On PC
from bridges.ftdi.controllers.uart import UartController
ser = UartController().Serial() 

print(ser.name)        
ser.write(b'hello')     
ser.close()      

[Test results]

  • Breakpoints and variables inspection 


  • Transceive LoRa packages directly from your laptop 


Notes

  • Mainly supports FTDI chips for now.
    • For CH341A:
      • Only I2C and GPIO functions are implemented, no SPI.
      • UART can be driven directly with the driver from WCH.
  • FTDI chip limitations
    • No IRQ.
      • The FT232H/FT2232H does not have endpoint of "interrupt input" type, IRQ functionality can only achieved with polling, which is too CPU intensive.
    • No PWM. PyFtdi, FT232H/FT2232H doesn't support.
    • In the same channel, the functionality of GPIO can coexist with SPI, but not with I2C/UART.
    • GPIO has no pull-up / pull-down functions.

References

沒有留言: