Netduino home hardware projects downloads community

Jump to content


Photo

Extensive driver for the MCP23S17 I/O expander


  • Please log in to reply
43 replies to this topic

#21 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 23 February 2014 - 09:05 PM

Yes it is because you are passing in the same SPI module to multiple driver instances.

 

As I said earlier, the driver does not yet support the same SPI module being shared among multiple driver instances.

 

I have to make a few adjustments for that first.

 

Also, I think your pin numbering might still be wrong - you must use values that are integer power of two, e.g. 1,2,4,8,16, etc. Have a look at the example I provided in post #15 above where I'm bit shifting like this "1 << Counter".

 

While waiting for me to update the code, you'd probably benefit more from verifying the driver works in getting a single single chip up and running.



#22 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 23 February 2014 - 09:08 PM

ok.. another great work Andy. so... actually i dont need to drive LCD display using M74HC595. I think it should be easier to drive it using MCP2317.... :rolleyes: thanks in advance for hanz and andy.

Yes, that's an excellent idea - and it would be really cool to see the software being used to drive an LCD too! TIP: Try using BurstWrite on a bus... Thanks to the pins A0,A1,A2 of each chip (reflected through the hwAddr constuctor parameter), you can cascade up to 8 chips on the same SPI bus producing a maximum of 128 GPIOs all with the same CS line - but, I need to make a few adjustments to allow the same SPI module to be shared among multiple driver instances. At present, such an attempt would result in an exception of type "resource already in use" or something like that - just like mcinnes01 just experienced. NOTE: The driver is for the SPI version, e.g. the MCP23S17 with an "S" in the middle - not the regular MCP23017 which runs on I2C.

#23 Fahdil

Fahdil

    Advanced Member

  • Members
  • PipPipPip
  • 59 posts
  • LocationJakarta, Indonesia

Posted 23 February 2014 - 09:56 PM

It's clear enough for me... God thanks....

 

so.. for the LCD display,, there is no easier way to mix it with microLiquidCristal class.

var lcdProvider = new GpioLcdTransferProvider(MCP23S17.Pins.GPIO_12, // RSMCP23S17.Pins.GPIO_11, // enableMCP23S17.Pins.GPIO_PIN_10, // d4MCP23S17.Pins.GPIO_PIN_9, // d5MCP23S17.Pins.GPIO_PIN_8, // d6MCP23S17.Pins.GPIO_PIN_7); // d7var myLcd = new Lcd(lcdProvider);myLcd.begin(16,2);

and..... maybe a little modification on LcdProvider Class....  ^_^

but First thing to do is lookin for the chip on the market. hepfh.... :blink:



#24 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 23 February 2014 - 10:04 PM

Cool, so you "only" need to write your own LcdProvider class where you would then make internal use of the MCP23S17 driver in creating and using a bus from the pins you supply in the parameter list above - correct?



#25 Fahdil

Fahdil

    Advanced Member

  • Members
  • PipPipPip
  • 59 posts
  • LocationJakarta, Indonesia

Posted 23 February 2014 - 10:17 PM

exactly..... :D...  thanks to you.... 

 

I hope to see that chip on the market. Last time i looked for 74HC595, it takes 2hours before i found 2 of it on the  market!!! :lol:

 

cheers



#26 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 23 February 2014 - 10:24 PM

....Any ideas?...

I just updated the driver code in post #1 - it now contains an internal light weight multiple SPI manager so you shouldn't be getting that exception anymore. Please try it when you can and report back since I haven't actually tested it myself yet :unsure: because all my Netduinos are occupied :) This also means sharing a single SPI bus among multiple driver instances should work, both when cascading using a shared CS line and when using separate per chip CS lines. EDIT: Sorry for messing with your code, but may I suggest:
for (int ic = 0; ic < icCnt; ic++){    chip[ic] = new MCP23S17(SPI_Devices.SPI1, Pins.GPIO_PIN_D10, Pins.GPIO_NONE, ic, 7000);    // Define all outputs    for (int pin = 0; pin < pinCnt; pin++)        Outs[16 * ic + pin] = chip[ic].CreateOutputPort((MCP23S17.Pins)(1 << pin), false);}
Really anxious to know if the driver works with your board!

#27 mcinnes01

mcinnes01

    Advanced Member

  • Members
  • PipPipPip
  • 325 posts
  • LocationManchester UK

Posted 24 February 2014 - 07:51 AM

Hi Hanz,

 

That is much clearer, thanks and I welcome any constructive criticism :)

 

I am getting this error:

A first chance exception of type 'MCP23S17Lib.MCP23S17.MCP23S17Exception' occurred in Testspi1.exeAn unhandled exception of type 'MCP23S17Lib.MCP23S17.MCP23S17Exception' occurred in Testspi1.exeAdditional information: MCP23S17: Pin already in use: Port0000 Uncaught exception 

On the throw exception in the code:

        private void _RegisterPort(_Port pin)        {            int idx = (int)pin.Pin;            if (_pins.Contains(idx))                throw new MCP23S17Exception("Pin already in use: " + pin.Name);            // store it            _pins[idx] = pin;        }

Not sure what I am missing?

 

Also I don't seem to be getting any output on the board? I can see there is power there, but in all my tests so far I have not lit an LED. The LED is connected to one of the digital pins on chip 1 and is then connected to the ground on the board. My first test to define and switch one port on constantly resulted in no output on chip one on any pin and there was out put on a few pins on chip 2. I will see if I can recreate that scenario.

 

I wonder if there hardware address isn't set correctly in my code?

 

Does this need to be a hex value and where would I set it?

 

Many thanks

 

Andy



#28 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 24 February 2014 - 08:46 AM

I'm sorry it's not working out as hoped. It's a bit strange since "port0000" would be the GPIO_NONE pin and that an attempt has been made to use it more than once. I'm thinking maybe the cast returns zero for some reason? This occurs while in the loop creating one of the output ports right? EDIT #1: Pin numbers can be given in any numeric format, the binary value will be the same either way.

 

EDIT #2: Made a few small updates to the code, probably nothing but you could try updating.

 

EDIT #3: What does your main chip and port creation code look like at this point?



#29 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 24 February 2014 - 10:16 AM

Regarding LEDs of Bank 1 lighting up unexpectedly, I went back to the information you got about your board:

 

..."[color=rgb(0,0,0);font-family:arial, sans-serif;font-size:13px;]On the left-hand chip (Bank 0) A0 is pulled to ground through 10K?. On the right hand chip (Bank 1) A0 is pulled up to Vcc.[/color]

[color=rgb(0,0,0);font-family:arial, sans-serif;font-size:13px;]On both chips A1 and A2 are both pulled down to ground through 10K?, and the two solder jumpers BA0 and BA1 can be shorted to link A1 and A2 to Vcc respectively"....[/color]

 

As the board manufacturer describes it, this would result in the first chip (Bank 0) getting {A0,A1,A2} = {0,0,0} corresponding to hwAddr 0 (zero) which would be correct in reference to your code.

 

It shouldn't matter if I have got the bit order wrong in my code because we're dealing with all zeroes for Bank 0.

 

However, I think we should concentrate on getting rid of any exceptions first before investigating this any further.



#30 mcinnes01

mcinnes01

    Advanced Member

  • Members
  • PipPipPip
  • 325 posts
  • LocationManchester UK

Posted 24 February 2014 - 06:32 PM

Hi Hanz,

 

Firstly thanks for taking the time to help :)

 

I have updated to your latest code and still get the problem with the same pin being in use. I was a little unsure on what I needed to do in terms of pin number (point 1). Also I'm not sure what I need to do with the hardware address, does this need to be 0 for the creation of both MCP23S17s?

The thread '<No Name>' (0x2) has exited with code 0 (0x0).A first chance exception of type 'MCP23S17Lib.MCP23S17.MCP23S17Exception' occurred in Testspi1.exeAn unhandled exception of type 'MCP23S17Lib.MCP23S17.MCP23S17Exception' occurred in Testspi1.exeAdditional information: MCP23S17: Pin already in use: Pin_0x0

Many thanks,

 

Here is my current code:

using System.Threading;using SecretLabs.NETMF.Hardware.Netduino;using MCP23S17Lib;namespace Testspi1{    public class Program    {        // Number of registers        private static uint icCnt = 2;        // Pins per register        private static uint icPins = 16;        //Total pins        private static uint pinCnt = icCnt * icPins;        // Sleep        private static int sleep = 200;        public static MCP23S17.OutputPort[] Outs = new MCP23S17.OutputPort[pinCnt];        public static MCP23S17[] chip = new MCP23S17[icCnt];        public static void Main()        {            // create a new instance of the driver class using pin 17 for !CS and pin 18 for IRQ            for (int ic = 0; ic < icCnt; ic++)            {                chip[ic] = new MCP23S17(SPI_Devices.SPI1, Pins.GPIO_PIN_D10, Pins.GPIO_NONE, (byte)ic, 7000);                // Define all outputs                for (int pin = 0; pin < pinCnt; pin++)                    Outs[16 * ic + pin] = chip[ic].CreateOutputPort((MCP23S17.Pins)(1 << pin), false);            }            while(true)            {                foreach (MCP23S17.OutputPort o in Outs)                {                    o.Value = true;                    Thread.Sleep(sleep);                    o.Value = false;                }            }        }    }


#31 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 24 February 2014 - 07:02 PM

Ah, I see it now, in the inner for loop, you should replace pinCnt with icPins. Sorry, I think that was my fault, I misinterpreted your variable naming. Hopefully, it will work after that mod.

#32 mcinnes01

mcinnes01

    Advanced Member

  • Members
  • PipPipPip
  • 325 posts
  • LocationManchester UK

Posted 24 February 2014 - 07:12 PM

I should have spotted that, my bad.

 

I updated the code but get a new error on the AddSPI:

The thread '<No Name>' (0x2) has exited with code 0 (0x0).A first chance exception of type 'System.ArgumentException' occurred in mscorlib.dllAn unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dllAdditional information: key exists

It occur on the line _cfg.Add(key, cfg);

            public void AddSPI(int key, SPI.Configuration cfg)            {                lock (_cfg)                    _cfg.Add(key, cfg);            }


#33 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 24 February 2014 - 07:16 PM

Hmm, thats odd - it's the multi SPI mgr reporting an attempt to add the same object twice. Let me get back to you shortly...

#34 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 24 February 2014 - 07:31 PM

Problem ought to be the Object.GetHashCode method returning the same value for two different instances which I never anticipated in the context of how it's being used here. Among other things, MSDN says this about GetHashCode:

...The GetHashCode method can be overridden by a derived type. If GetHashCode is not overridden, hash codes for reference types are computed by calling the Object.GetHashCode method of the base class, which computes a hash code based on an object's reference; for more information, see RuntimeHelpers.GetHashCode. In other words, two objects for which the ReferenceEquals method returns true have identical hash codes...

I'll figure something out - meanwhile you could try using only Bank 0 and see if you can get that working.

#35 mcinnes01

mcinnes01

    Advanced Member

  • Members
  • PipPipPip
  • 325 posts
  • LocationManchester UK

Posted 24 February 2014 - 07:38 PM

Ok will do, I will give it a spin now.

 

Cheers,

 

Andy



#36 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 24 February 2014 - 08:10 PM

Found an embarrassing bug in the multi SPI mgr - code is updated and hopefully problem is gone now...

 

Btw, your blinker loop looks suspicious - shouldn't you have a delay during the OFF period as well?



#37 mcinnes01

mcinnes01

    Advanced Member

  • Members
  • PipPipPip
  • 325 posts
  • LocationManchester UK

Posted 24 February 2014 - 08:12 PM

Success on 1 chip :)

 

 

 

 



#38 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 24 February 2014 - 08:28 PM

That is truly great news Andy, I'm really glad to hear that - wonderful !! Perhaps photos or even a short video clip later when you got both banks running on the (hopefully) corrected version now available? Way da go - persistance pays!

#39 mcinnes01

mcinnes01

    Advanced Member

  • Members
  • PipPipPip
  • 325 posts
  • LocationManchester UK

Posted 24 February 2014 - 10:01 PM

Yes and multi spi works too. Slight issue to work out with my code. The idea of a continuous array of output ports span multiple ics is great, but I'm not sure how I would access the relevant pins for example:

 

(Left power 2 value, right array position)

 

1 - 1
2 - 2
4 - 3
8 - 4
16 - 5
32 - 6
64 - 7
128 - 8
256 - 9
512 - 10
1024 - 11
2048 - 12
4096 - 13
8192 - 14
16384 - 15
32768 - 16
1 - 17
2 - 18
4 - 19
8 - 20
16 - 21
32 - 22
64 - 23
128 - 24
256 - 25
512 - 26
1024 - 27
2048 - 28
4096 - 29
8192 - 30
16384 - 31
32768 - 32
 


#40 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 24 February 2014 - 11:07 PM

That's great too and thanks for sharing the photos and everything on your blog. From what I understand, you now got 32 digital ports all nicely lined up in a single array that you can index from 0 to 31. If you'd want to light up, say pin at index 23, you'd just go like so:
Outs[23].Value = true;
Am I right? In the context of this example, you don't have to care about the internal pin numbers being 2's complement. However, when working with buses, it's very conveniant becuase bit masking then becomes very easy. Note that buses cannot span multiple chips and also note that your array is not a bus, it's an array of pins which is not quite the same thing.




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.