0

MPR121 and F232H board
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

MPR121 and F232H board

by Ethan0l on Fri Mar 17, 2017 10:31 am

Hello,
I was wondering if anyone has any input as to how I could make these 2 work together. The F232H board can ping my device but every time I set the i2c = ft232h I get error
File "C:/Users/T-1000/Desktop/Research/Python/Code for Pi/simpletest.py", line 204, in <module>
cap = MPR121(i2c=ft232h)
TypeError: __init__() got an unexpected keyword argument 'i2c'. Furthermore when I get past this error I get a second error

File "build\bdist.win32\egg\Adafruit_GPIO\FT232H.py", line 641, in write8
self._verify_acks(response)
File "build\bdist.win32\egg\Adafruit_GPIO\FT232H.py", line 604, in _verify_acks
raise RuntimeError('Failed to find expected I2C ACK!')
RuntimeError: Failed to find expected I2C ACK!

Any suggestions are appreciated!

Ethan0l
 
Posts: 5
Joined: Fri Mar 17, 2017 10:23 am

Re: MPR121 and F232H board

by adafruit_support_carter on Fri Mar 17, 2017 12:12 pm

cap = MPR121(i2c=ft232h)

There is no parameter i2c in the constructor. You need to pass it in via the begin() function. First, setup the ft232h for i2c:
https://learn.adafruit.com/adafruit-ft2 ... ware-usage
then pass that in:
Code: Select all | TOGGLE FULL SIZE
cap.begin(i2c=i2c)

exact syntax will depend on how you've coded things.

adafruit_support_carter
 
Posts: 1703
Joined: Tue Nov 29, 2016 2:45 pm

Re: MPR121 and F232H board

by Ethan0l on Mon Mar 20, 2017 2:32 pm

Thank you. I have fixed that problem but now the MPR121 does not initialize. It says to check my wiring but I'm sure it's correct. I have tested with a Raspberry Pi and I know for a fact it works. I have attached a picture of my wiring. Any suggestions as to what's going on?
Attachments
Capture.JPG
Wiring of FT232H and MPR121
Capture.JPG (114.53 KiB) Viewed 139 times

Ethan0l
 
Posts: 5
Joined: Fri Mar 17, 2017 10:23 am

Re: MPR121 and F232H board

by adafruit_support_carter on Mon Mar 20, 2017 5:46 pm

Try without the pullup resistors. If that doesn't work, post the full code you are using.

adafruit_support_carter
 
Posts: 1703
Joined: Tue Nov 29, 2016 2:45 pm

Re: MPR121 and F232H board

by Ethan0l on Wed Mar 22, 2017 12:17 pm

I'm just using the basic simpletest.py example to test if it works. I also copied the MPR121 module code to change some register values on the go.
Code: Select all | TOGGLE FULL SIZE
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

import sys
import time
import Adafruit_GPIO.FT232H as FT232H

FT232H.use_FT232H()
ft232h = FT232H.FT232H()

MPR121_I2CADDR_DEFAULT = 0x5A
MPR121_TOUCHSTATUS_L   = 0x00
MPR121_TOUCHSTATUS_H   = 0x01
MPR121_FILTDATA_0L     = 0x04
MPR121_FILTDATA_0H     = 0x05
MPR121_BASELINE_0      = 0x1E
MPR121_MHDR            = 0x2B
MPR121_NHDR            = 0x2C
MPR121_NCLR            = 0x2D
MPR121_FDLR            = 0x2E
MPR121_MHDF            = 0x2F
MPR121_NHDF            = 0x30
MPR121_NCLF            = 0x31
MPR121_FDLF            = 0x32
MPR121_NHDT            = 0x33
MPR121_NCLT            = 0x34
MPR121_FDLT            = 0x35
MPR121_TOUCHTH_0       = 0x41
MPR121_RELEASETH_0     = 0x42
MPR121_DEBOUNCE        = 0x5B
MPR121_CONFIG1         = 0x5C
MPR121_CONFIG2         = 0x5D
MPR121_CHARGECURR_0    = 0x5F
MPR121_CHARGETIME_1    = 0x6C
MPR121_ECR             = 0x5E
MPR121_AUTOCONFIG0     = 0x7B
MPR121_AUTOCONFIG1     = 0x7C
MPR121_UPLIMIT         = 0x7D
MPR121_LOWLIMIT        = 0x7E
MPR121_TARGETLIMIT     = 0x7F
MPR121_GPIODIR         = 0x76
MPR121_GPIOEN          = 0x77
MPR121_GPIOSET         = 0x78
MPR121_GPIOCLR         = 0x79
MPR121_GPIOTOGGLE      = 0x7A
MPR121_SOFTRESET       = 0x80

MAX_I2C_RETRIES = 5


class MPR121(object):
    """Representation of a MPR121 capacitive touch sensor."""

    def __init__(self):
        """Create an instance of the MPR121 device."""
        # Nothing to do here since there is very little state in the class.
        pass

    def begin(self, address=MPR121_I2CADDR_DEFAULT, i2c=ft232h, **kwargs):
        """Initialize communication with the MPR121.

        Can specify a custom I2C address for the device using the address
        parameter (defaults to 0x5A). Optional i2c parameter allows specifying a
        custom I2C bus source (defaults to platform's I2C bus).

        Returns True if communication with the MPR121 was established, otherwise
        returns False.
        """
        # Assume we're using platform's default I2C bus if none is specified.
        if i2c is None:
            import Adafruit_GPIO.I2C as I2C
            i2c = I2C
            # Require repeated start conditions for I2C register reads.  Unfortunately
            # the MPR121 is very sensitive and requires repeated starts to read all
            # the registers.
            I2C.require_repeated_start()
        # Save a reference to the I2C device instance for later communication.
        self._device = ft232h.get_i2c_device(address, **kwargs)
        return self._reset()

    def _reset(self):
        global CDT
        global CDC
        # Soft reset of device.
        self._i2c_retry(self._device.write8, MPR121_SOFTRESET, 0x63)
        time.sleep(0.001) # This 1ms delay here probably isn't necessary but can't hurt.
        # Set electrode configuration to default values.
        self._i2c_retry(self._device.write8, MPR121_ECR, 0x00)
        # Check CDT, SFI, ESI configuration is at default values.
        c = self._i2c_retry(self._device.readU8, MPR121_CONFIG2)
        if c != 0x24:
           return False
        # Set threshold for touch and release to default values.
        self.set_thresholds(12, 6)
        # Configure baseline filtering control registers.
        self._i2c_retry(self._device.write8, MPR121_MHDR, 0x01)
        self._i2c_retry(self._device.write8, MPR121_NHDR, 0x01)
        self._i2c_retry(self._device.write8, MPR121_NCLR, 0x0E)
        self._i2c_retry(self._device.write8, MPR121_FDLR, 0x00)
        self._i2c_retry(self._device.write8, MPR121_MHDF, 0x01)
        self._i2c_retry(self._device.write8, MPR121_NHDF, 0x05)
        self._i2c_retry(self._device.write8, MPR121_NCLF, 0x01)
        self._i2c_retry(self._device.write8, MPR121_FDLF, 0x00)
        self._i2c_retry(self._device.write8, MPR121_NHDT, 0x00)
        self._i2c_retry(self._device.write8, MPR121_NCLT, 0x00)
        self._i2c_retry(self._device.write8, MPR121_FDLT, 0x00)
        # Set other configuration registers.
        self._i2c_retry(self._device.write8, MPR121_DEBOUNCE, 0)
        self._i2c_retry(self._device.write8, MPR121_CONFIG1, 24)  # FFI, CDC (00 000000) default, 16uA charge current
        self._i2c_retry(self._device.write8, MPR121_CONFIG2, 96)  # CDT, SFI, ESI (000 00 000) register
        # Enable all electrodes.
        self._i2c_retry(self._device.write8, MPR121_ECR, 0x8F) # start with first 5 bits of baseline tracking
        # All done, everything succeeded!
        return True

    def _i2c_retry(self, func, *params):
        # Run specified I2C request and ignore IOError 110 (timeout) up to
        # retries times.  For some reason the Pi 2 hardware I2C appears to be
        # flakey and randomly return timeout errors on I2C reads.  This will
        # catch those errors, reset the MPR121, and retry.
        count = 0
        while True:
            try:
                return func(*params)
            except IOError as ex:
                # Re-throw anything that isn't a timeout (110) error.
                if ex.errno != 110:
                    raise ex
            # Else there was a timeout, so reset the device and retry.
            self._reset()
            # Increase count and fail after maximum number of retries.
            count += 1
            if count >= MAX_I2C_RETRIES:
                raise RuntimeError('Exceeded maximum number or retries attempting I2C communication!')

    def set_thresholds(self, touch, release):
        """Set the touch and release threshold for all inputs to the provided
        values.  Both touch and release should be a value between 0 to 255
        (inclusive).
        """
        assert touch >= 0 and touch <= 255, 'touch must be between 0-255 (inclusive)'
        assert release >= 0 and release <= 255, 'release must be between 0-255 (inclusive)'
        # Set the touch and release register value for all the inputs.
        for i in range(12):
            self._i2c_retry(self._device.write8, MPR121_TOUCHTH_0 + 2*i, touch)
            self._i2c_retry(self._device.write8, MPR121_RELEASETH_0 + 2*i, release)

    def filtered_data(self, pin):
        """Return filtered data register value for the provided pin (0-11).
        Useful for debugging.
        """
        assert pin >= 0 and pin < 12, 'pin must be between 0-11 (inclusive)'
        return self._i2c_retry(self._device.readU16LE, MPR121_FILTDATA_0L + pin*2)

    def baseline_data(self, pin):
        """Return baseline data register value for the provided pin (0-11).
        Useful for debugging.
        """
        assert pin >= 0 and pin < 12, 'pin must be between 0-11 (inclusive)'
        bl = self._i2c_retry(self._device.readU8, MPR121_BASELINE_0 + pin)
        return bl << 2

    def touched(self):
        """Return touch state of all pins as a 12-bit value where each bit
        represents a pin, with a value of 1 being touched and 0 not being touched.
        """
        t = self._i2c_retry(self._device.readU16LE, MPR121_TOUCHSTATUS_L)
        return t & 0x0FFF

    def is_touched(self, pin):
        """Return True if the specified pin is being touched, otherwise returns
        False.
        """
        assert pin >= 0 and pin < 12, 'pin must be between 0-11 (inclusive)'
        t = self.touched()
        return (t & (1 << pin)) > 0

    def read_register(self, register):
        reg = self._i2c_retry(self._device.readU8, register)
        return reg


print('Adafruit MPR121 Capacitive Touch Sensor Test')

# Create MPR121 instance.
cap = MPR121()

# Initialize communication with MPR121 using default I2C bus of device, and
# default I2C address (0x5A).  On BeagleBone Black will default to I2C bus 0.
if not cap.begin():
    print('Error initializing MPR121.  Check your wiring!')
    sys.exit(1)

# Main loop to print a message every time a pin is touched.
print('Press Ctrl-C to quit.')
last_touched = cap.touched()
while True:
    current_touched = cap.touched()
    # Check each pin's last and current state to see if it was pressed or released.
    for i in range(12):
        # Each pin is represented by a bit in the touched value.  A value of 1
        # means the pin is being touched, and 0 means it is not being touched.
        pin_bit = 1 << i
        # First check if transitioned from not touched to touched.
        if current_touched & pin_bit and not last_touched & pin_bit:
            print('{0} touched!'.format(i))
        # Next check if transitioned from touched to not touched.
        if not current_touched & pin_bit and last_touched & pin_bit:
            print('{0} released!'.format(i))
    # Update last state and wait a short period before repeating.
    last_touched = current_touched
    time.sleep(0.1)

Ethan0l
 
Posts: 5
Joined: Fri Mar 17, 2017 10:23 am

Re: MPR121 and F232H board

by adafruit_support_carter on Wed Mar 22, 2017 1:08 pm

Might have something to do with the MPR121 wanting repeated starts on the I2C comm.

Have you removed the pull up resistors? Also curious why you are taking the library source and modifying it. In theory, should be able to use library code as is and just pass in the return from ft232h.get_i2c_device().

adafruit_support_carter
 
Posts: 1703
Joined: Tue Nov 29, 2016 2:45 pm

Re: MPR121 and F232H board

by Ethan0l on Wed Mar 22, 2017 1:14 pm

I did remove the pull up resistors and same results. I'm doing a project testing different register values for the filter and sensitivity settings. I already had it open and just changed the code to use the simpletest.py example. It all works in a raspberry pi but when i try using the FT232H in windows it just won't initialize.

Ethan0l
 
Posts: 5
Joined: Fri Mar 17, 2017 10:23 am

Re: MPR121 and F232H board

by adafruit_support_carter on Wed Mar 22, 2017 1:17 pm

It all works in a raspberry pi but when i try using the FT232H in windows it just won't initialize.

Using hardware I2C on the pi? i.e. without the ft232h involved.

adafruit_support_carter
 
Posts: 1703
Joined: Tue Nov 29, 2016 2:45 pm

Re: MPR121 and F232H board

by Ethan0l on Wed Mar 22, 2017 1:26 pm

The MPR121 works with the Pi I2C interface. Similar code just without the FT232H. When I try it on windows with the FT232H it gives me that initialization error

Ethan0l
 
Posts: 5
Joined: Fri Mar 17, 2017 10:23 am

Re: MPR121 and F232H board

by adafruit_support_carter on Wed Mar 22, 2017 1:32 pm

So it's probably the repeated start thing. You can see this being enabled in the constructor when no i2c interface is passed in:
Code: Select all | TOGGLE FULL SIZE
            # Require repeated start conditions for I2C register reads.  Unfortunately
            # the MPR121 is very sensitive and requires repeated starts to read all
            # the registers.
            I2C.require_repeated_start()

So that happens when running it on the Pi. Not sure what the default behavior for the FT232H is, or whether this is even supported.

Unfortunately, this may be a currently unsupported combo.

Possibly relevant:
viewtopic.php?f=19&t=99492#p500414

adafruit_support_carter
 
Posts: 1703
Joined: Tue Nov 29, 2016 2:45 pm

Please be positive and constructive with your questions and comments.