Giter VIP home page Giter VIP logo

easymcp2221's Introduction

Easy MCP2221

Easy MCP2221 is a Python module to interface with Microchip MCP2221 and MCP2221A.

Connected to the USB port, this 14 pin chip part can provide a normal computer with the capabilities of a basic microcontroller.

MCP2221's peripherals:

  • 4 GPIO
  • 3 channel ADC
  • DAC
  • I2C
  • UART
  • Clock Output
  • USB Wake-up via Interrupt Detection.

So you can practice the basics of digital electronics, microcontrollers, and robotics using nothing more than a regular computer, a breadboard, a few parts, and Python.

Quick start

Install:

$ pip install EasyMCP2221

First run:

>>> import EasyMCP2221
>>> mcp = EasyMCP2221.Device()
>>> print(mcp)
{
    "Chip settings": {
        "Power management options": "enabled",
        "USB PID": "0x00DD",
        "USB VID": "0x04D8",
        "USB requested number of mA": 100
    },
    "Factory Serial": "01234567",
    "GP settings": {},
    "USB Manufacturer": "Microchip Technology Inc.",
    "USB Product": "MCP2221 USB-I2C/UART Combo",
    "USB Serial": "0000000000"
}

GUI

EasyMCP2221 Workbench is a GUI to play with MCP2221 and MCP2221A chips based on EasyMCP2221 library.

https://github.com/electronicayciencia/EasyMCP2221-GUI

Documentation

Read the Install Guide, Examples and full API Reference here: https://easymcp2221.readthedocs.io/

Illustrative blog post with examples, pictures and schematics (spanish): El integrado MCP2221(A)

Author

Reinoso Guzman (https://www.electronicayciencia.com).

Initially based on PyMCP2221A library by Yuta Kitagami (https://github.com/nonNoise/PyMCP2221A).

License

The MIT License (MIT).

easymcp2221's People

Contributors

ddubbledd avatar electronicayciencia avatar jremmet avatar k4zuki avatar nonnoise avatar rickeywang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

easymcp2221's Issues

unsaved_SRAM and status dicts are shared by all instances

The Device.unsaved_SRAM and Device.status dictionaries are class attributes shared by all instances. Since they're mutable, this means multiple instances are actually modifying and reading the same dictionaries, leading to incorrect behaviour when talking to two MCP2221s from the same Python process.

This can be fixed by simply by assigning these two dicts as instance attributes self.unsaved_SRAM and self.status in __init__ instead of at the class level.

The library does not work on Raspberry Pi with the Raspbian operating system

When creating an instance with mcp = EasyMCP2221.Device(), an error occurs:

`import EasyMCP2221

mcp = EasyMCP2221.Device()
print(f"mcp: {mcp}")

Traceback (most recent call last):
File "/home/pi/CamPanel2/mcpTest.py", line 3, in
mcp = EasyMCP2221.Device()
File "/home/pi/.local/lib/python3.9/site-packages/EasyMCP2221/MCP2221.py", line 106, in init
self.hidhandler.open_path(hid.enumerate(self.VID, self.PID)[self.devnum]["path"])
File "hid.pyx", line 157, in hid.device.open_path
OSError: open failed`

The same script works correctly on Windows.

Distinguishing between multiple connected MCP2221s

It looks like there isn't a reliable way to distinguish multiple connected MCP2221s without a bit of extra work. The devnum parameter allows one to connect to several MCP2221s, but is not guaranteed to be stable. I'm doing something like the below (which is a bit hacky) to distinguish MCP2221s by serial number, but identifying them by their USB address could also be good (that should be stable as long as the devices remain plugged into the same USB ports).

class MCP2221(EasyMCP2221.Device):
    """Subclass that allows finding device by serial number instead of the unstable
    `devnum`, which is just based on the order hidapi enumerates devices."""
    device_open_timeout = 0
    def __init__(self, serial_number=None):
        self.hidhandler = hid.device()
        devnum = None
        if serial_number is None:
            devnum = 0
        else:
            for i, dev in enumerate(hid.enumerate(self.VID, self.PID)):
                try:
                    self.hidhandler.open_path(dev["path"])
                except OSError:
                    # Probably already in use
                    pass
                else:
                    usb_serial = self.read_flash_info()['USB_SERIAL']
                    if usb_serial == serial_number:
                        devnum = i
                        self.hidhandler.close()
                        break
        if devnum is None:
            raise ValueError(f"No MCP2221 with serial number {serial_number} found")

        super().__init__(devnum=devnum)

Get assigned serial port name

Hello, I want to know if there is a way to detect the serial port name assigned by the system to the mcp2221.
I used to work with some ftdi modules whose library have that feature.
It would make easier to use both interfaces, i2c and uart, in the same python script.
Now I have to detect which port was assigned by checking the device manager (windows) and changing the port name in the script.

Is it possible to add that feature to the library or any hints on how to manage that?
Thanks in advance

`I2C_write` got stuck in a loop

Hi! First of all, thanks for this library and for its documentation, I like it a lot.

I have a script that writes 128 pages of an EEPROM in a loop. For each page it writes 257 bytes at once using I2C_write.

Everything works wellmost of the times, however, it got stuck in this loop sometimes. The root cause are severe signal intergrity issues on the I2C bus.

To avoid getting stuck in there, I added these lines of code that raise an exception. My script can then retry to write the whole 257 bytes packet.

while last_byte < len(data) and self._i2c_buffer_counter() > 0:
    #time.sleep(1e-6)
    if not self._i2c_ack():
        self.I2C_cancel()
        raise RuntimeError("I2C got stuck")
        pass

You also may have noticed that I commented time.sleep(1e-6). On Windows (but I think on any non-realtime OS) I think it's impossible to ask for such a short sleeping time, in fact, I noticed the shortest sleep time on my machine is ~12 ms, which slows down a lot the process of writing the whole EEPROM. In any case I don't see the need for any sleep time in that loop, but I may be wrong.

What do you think?

Long time between i2c calls

I connected an MCP2221A board to an i2c slave (implemented in FPGA, using clock stretching).
Then I made a simple test program:

mcp = EasyMCP2221.Device()
addr = 0xB0 // 2
mcp.I2C_write(addr, [0x00, 0x00], kind='nonstop', timeout_ms=1000)
result = mcp.I2C_read(addr, 8, kind='restart', timeout_ms=1000)

The code works, but slowwww... There's a long time between the i2c start, the write and the read. See oscilloscope diagram.
First you see the start (halfway the first division), then after ~440 ms the write is done, then after 330 ms the read and stop are executed.
My PC runs Windows 11 and Python 3.12.
On the same PC, the PyMCP2221A driver, does not show this delay. However, this driver has other issues (it hangs the bus when reading > 40 bytes) and I like the API of EasyMCP2221 more ๐Ÿ˜„.

On another Windows 11 PC, this all runs without the weird delays!

Any idea? Thanks in advance!

SDS2104X Plus_PNG_4

Python script takes long time to terminate

When a simple python script(see below) is terminated in linux, it takes 11 seconds for the script to actually terminate when it's done.

In windows this is almost instantly. Why would this be?

import EasyMCP2221
from time import sleep

# Connect to the device
mcp = EasyMCP2221.Device()

# Reclaim GP0 for General Purpose Input Output, as an Output.
mcp.set_pin_function(gp0 = "GPIO_OUT")
mcp.GPIO_write(gp0 = False)
#mcp.save_config()


for x in range(0,4):
    mcp.GPIO_write(gp0 = True)
    sleep(0.5)
    mcp.GPIO_write(gp0 = False)
    sleep(2)

print("done")

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.