Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

I2C Devices using the I2CBus class


  • Please log in to reply
11 replies to this topic

#1 GDSever

GDSever

    Advanced Member

  • Members
  • PipPipPip
  • 81 posts
  • LocationNewark, DE

Posted 14 December 2010 - 10:33 PM

Attached below are some classes I've been working on for the past couple of weeks. The code uses the ever-popular I2CBus class (FusionWare.SPOT.Hardware namespace) to allow multiple I2C devices on the same bus to be instantiated without having to repeatedly create and destroy them. All code has been prototyped and proven to work using a Netduino and the SparkFun protoshield.

Included classes are:

  • Microchip MCP23008 and MCP23016 digital I/O expanders
  • 24LCXXX family of EEPROMs (24LC16B and 24LC256 were specifically tested)
  • DS1307 based on code written by stacyh3 on this thread (just modified to use the I2CBus class).

The example program is currently set up to test one device at a time (by commenting / uncommenting which is being tested), however there is no reason why multiple devices couldn't be used off the same I2C bus - it's just not that easy to come up with a generic example that would apply to everyone.

Feel free to use / expand. You should be able to drop just the device .CS file (and the I2CBus.cs file) into whatever project and start using them, with the exception of the DS1307 clock that uses multiple files.

[edit]ZIP file was replaced with a newer version. The EEPROM class has been generalized and cleaned up, and the MCP230XX module now includes support for the MCP23017 digital I/O expander.[/edit]

Attached Files


Edited by GDSever, 05 January 2011 - 12:35 PM.

  • tobsen , Stefan , Olgawext and 2 others like this

#2 phantomtypist

phantomtypist

    Advanced Member

  • Members
  • PipPipPip
  • 142 posts
  • LocationNew York, NY

Posted 14 December 2010 - 10:41 PM

I've already touched on this. It can be used by pretty much any I2C device on probably any .NET Micro Framework device.

My work -> A derivative of Pavel Bansky's I2CBus class, but implements the singleton pattern (because it should be implementing the singleton pattern since you are supposed to only have one instance of the I2CDevice class.) You really might want to explore using the singleton pattern so that you guarantee that there is only one instance of the I2CDevice being used by your I2C devices.

I used this in the Bosch BMP085 Digital Pressure and Temperature Sensor

FYI my singleton implementation of the I2CBus class is being used in several projects with as many as four I2C devices on operating on the same bus.
  • SergeyNuRb likes this

#3 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 14 December 2010 - 11:08 PM

FYI my singleton implementation of the I2CBus class is being used in several projects with as many as four I2C devices on operating on the same bus.

Just out of curiosity, have you tried to simply use multiple I2CDevice instances with different configurations? I have nothing against the I2CBus implementation, but as far as I understand the current implementation of I2C, there is no need for it - multiple I2CDevice instances should work fine, as the configuration is set at the beginning of each transaction sequence (i.e. in Execute() method call, AT91_I2C_Driver::MasterXAction_Start(...) to be precise). I believe the limitation existed in the previous version of .NET MF, there is also explanatory post by Lorenzo Tessiore (the last one).

#4 phantomtypist

phantomtypist

    Advanced Member

  • Members
  • PipPipPip
  • 142 posts
  • LocationNew York, NY

Posted 14 December 2010 - 11:10 PM

Just out of curiosity, have you tried to simply use multiple I2CDevice instances with different configurations? I have nothing against the I2CBus implementation, but as far as I understand the current implementation of I2C, there is no need for it - multiple I2CDevice instances should work fine, as the configuration is set at the beginning of each transaction sequence (i.e. in Execute() method call, AT91_I2C_Driver::MasterXAction_Start(...) to be precise). I believe the limitation existed in the previous version of .NET MF, there is also explanatory post by Lorenzo Tessiore (the last one).



You can't instantiate more than one I2CDevice.

#5 GDSever

GDSever

    Advanced Member

  • Members
  • PipPipPip
  • 81 posts
  • LocationNewark, DE

Posted 15 December 2010 - 12:54 AM

I've already touched on this. It can be used by pretty much any I2C device on probably any .NET Micro Framework device.


Sorry - there are a couple of I2CBus implementations out there. I am sure yours would work just as well as the one I selected... I think I looked at both and decided to go with the other because it more closely represented the code I had gotten to work with my classes, and was the easiest to incorporate.

[edit]
I could use your I2CBus class if you included a WriteRead method similar to the one in the FusionWare class - That was the missing piece that was holding me up from using yours. Both the MCP230XX and 24LCXXX chips require combined Write and Read I2CTransactions in order to communicate.
[/edit]

Edited by GDSever, 15 December 2010 - 10:10 AM.


#6 GDSever

GDSever

    Advanced Member

  • Members
  • PipPipPip
  • 81 posts
  • LocationNewark, DE

Posted 05 January 2011 - 12:36 PM

The ZIP file has been replaced with a newer version.

#7 Luke Cummings

Luke Cummings

    Advanced Member

  • Members
  • PipPipPip
  • 38 posts
  • LocationCalgary, AB

Posted 21 January 2011 - 02:09 AM

I've already touched on this. It can be used by pretty much any I2C device on probably any .NET Micro Framework device.

My work -> A derivative of Pavel Bansky's I2CBus class, but implements the singleton pattern (because it should be implementing the singleton pattern since you are supposed to only have one instance of the I2CDevice class.) You really might want to explore using the singleton pattern so that you guarantee that there is only one instance of the I2CDevice being used by your I2C devices.

I used this in the Bosch BMP085 Digital Pressure and Temperature Sensor

FYI my singleton implementation of the I2CBus class is being used in several projects with as many as four I2C devices on operating on the same bus.


phantom I just finished reworking my quad project to including your I2CBus, works fantastic! I really like this approach, elegant and simple.

Cheers!
Cheap, Fast, Good... Pick two

#8 fitims

fitims

    Member

  • Members
  • PipPip
  • 11 posts

Posted 23 February 2011 - 05:40 PM

Guys, Can anybody please post a schematics of how to connect MCP23017 to netduino? I am just worried that I will burn my netduino board. Regards Fitim

#9 GDSever

GDSever

    Advanced Member

  • Members
  • PipPipPip
  • 81 posts
  • LocationNewark, DE

Posted 24 February 2011 - 10:37 PM

I'll see if I can work up a Fritzing diagram in the next couple days. It's really simple - and the 23017 runs at both 5V and 3.3V, so it doesn't matter which you power it from... [edit]Fritzing diagram should be correct, although I didn't test it out. All address pins are pulled to GND (000).[/edit]

Attached Files


Edited by GDSever, 25 February 2011 - 01:53 PM.


#10 EvanLaske

EvanLaske

    New Member

  • Members
  • Pip
  • 6 posts

Posted 16 May 2011 - 04:57 PM

Feel free to use / expand. You should be able to drop just the device .CS file (and the I2CBus.cs file) into whatever project and start using them, with the exception of the DS1307 clock that uses multiple files.

[edit]ZIP file was replaced with a newer version. The EEPROM class has been generalized and cleaned up, and the MCP230XX module now includes support for the MCP23017 digital I/O expander.[/edit]


Have you tested this with any more EEPROMs?

I am currently working on an update to this which cleans the class up a little more and adds a lot of documentation that I figured may be useful to anyone using it. I'll post it here when I'm done.

#11 tobsen

tobsen

    New Member

  • Members
  • Pip
  • 4 posts

Posted 11 September 2011 - 01:57 PM

Have you tested this with any more EEPROMs?

I am currently working on an update to this which cleans the class up a little more and adds a lot of documentation that I figured may be useful to anyone using it. I'll post it here when I'm done.

I have just tested it with 24LC256 from Microchip. Thanks for providing the class, it saved me some time.

#12 Spork

Spork

    Advanced Member

  • Members
  • PipPipPip
  • 105 posts

Posted 19 December 2011 - 06:02 AM

G.D. Sever's class has served me well for months, but I finally ran into a bug, so I thought I'd document it here.

The 24LCxxx EEPROMs have page write buffers (PWB). The PWB size varies from model to model and is not necessarily the same for all models with the same capacity:

    24LC16B:  16 bytes
    24LC32A:  32 bytes
    24LC64:   32 bytes
    24LC128:  64 bytes
    24LC256:  64 bytes
    24LC512: 128 bytes
    24LC515:  64 bytes

Here's what the data sheet says about pages:

Page write operations are limited to writing bytes within a single physical page, regardless of the number of bytes actually being written. Physical page boundaries start at addresses that are integer multiples of the page buffer size (or ‘page size’) and end at addresses that are integer multiples of [page size – 1]. If a Page Write command attempts to write across a physical page boundary, the result is that the data wraps around to the beginning of the current page (overwriting data previously stored there), instead of being written to the next page, as might be expected. It is, therefore, necessary for the application software to prevent page write operations that would attempt to cross a page boundary.


It seems as though there are two situations where you can run into trouble when writing to EEPROM with the _24LC01 class:
  • Writing any value longer than the page size.
  • Writing any value (even short ones) across page boundaries.

This is a quick and dirty fix, but I thought I better post something if I was going to point out the problem. I've tested this by writing a long string value (several pages long) to a starting address that's not a page boundary. I'm not sure how much this can be cleaned up without modifying the underlying I2CBus case so that it allows writing of specific data out of buffers (i.e. by start index and length) instead of assuming that the entire buffer should be sent. Any clean up suggestions will be welcome.

public int WriteBytes(UInt16 writeAddress, byte[] data)
{
    if (writeAddress + data.Length - 1 <= MaxSize)
    {
        int result = 0;
        int offset = 0;
        int availableInPage = PageWriteBufferSize - (writeAddress % PageWriteBufferSize);
        while (offset < data.Length)
        {
            int bytesRemaining = data.Length - offset;
            int bytesToWrite = bytesRemaining > availableInPage ? availableInPage : bytesRemaining;
            byte[] pageData = new byte[bytesToWrite];
            for (int i = 0; i < bytesToWrite; i++) pageData[i] = data[i+offset];
            // Grab the low byte.
            byte addrLow = (byte)((writeAddress + offset) & 0xFF);
            if (MaxSize > 0xFF)
            {
                // double byte address.
                byte addrHigh = (byte)(((writeAddress + offset) >> 8) & 0xFF);
                result += Write(new byte[] { addrHigh, addrLow }, pageData);
            }
            else
            {
                // single byte address
                result += Write(new byte[] { addrLow }, pageData);
            }
            offset += bytesToWrite;
            availableInPage = PageWriteBufferSize; // After start page, all of page is available.
        }
        return result;
    }
    else
    {
        throw new Exception("Address too high and/or value too long.");
    }
}

It depends on the following... A cleaned up version would save the PWB size instead of switching for it every time.

public ushort PageWriteBufferSize
{
    get
    {
        // Note: PWB size is NOT a function of capacity. 
        // E.g. 24LC512 and 24LC515 are both 512 kbit, but have PWB sizes of 64 and 128 bits, respectively. 
        switch (ic)
        {
            case IC._24LC16B: return 16;
            case IC._24LC32A: return 32;
            case IC._24LC64: return 32;
            case IC._24LC128: return 64;
            case IC._24LC256: return 64;
            case IC._24LC512: return 128;
        }
        throw new Exception(); 
    }                
}





0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.