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

More Digital I/O


  • Please log in to reply
17 replies to this topic

#1 Greg Chao

Greg Chao

    Member

  • Members
  • PipPip
  • 14 posts

Posted 28 September 2015 - 07:53 PM

Any recommendations for expanding the Netduino for more digital I/O.?  I am confused with all the Artuino shields...which one is compatible?  When will the gobus version be ready?



#2 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 29 September 2015 - 05:27 AM

I cannot comment on the Arduino Shields but if you are OK with putting your own circuit together then a driver for the MCP23s08/MCP23S17 has been released.  I think it is still draft form at the moment.

 

If you want output only then the 74H595 is popular and there are many examples on this site.  For input there is also the 74H165 (I think).

 

If you want a Go Bus example of the 74H595 output module well I put together full instructions on building a 595 output module including source code a while ago.

 

Regards,

Mark


To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#3 ShVerni

ShVerni

    Advanced Member

  • Members
  • PipPipPip
  • 138 posts
  • LocationNew York, New York

Posted 04 October 2015 - 12:19 AM

Hello,

 

I agree completely with Mark, if you just need a few extra outputs or inputs, 74H shift-registers are excellent and simple. If you want something that's a bit more capable (ports can be configured as inputs or outputs, they have pull-up resistors, and there are interrupts), I've found MCP23S08/MCP23S17 to be very useful, and they don't require any additional components, just like a 74HC595, it only needs a few extra pin connections to the Netduino, and you can add sixteen extra ports with one chip.

 

If you do use one of the expanders and have any questions let me know, and good luck!



#4 Greg Chao

Greg Chao

    Member

  • Members
  • PipPip
  • 14 posts

Posted 09 October 2015 - 05:05 AM

Do you have a schematic using MCP23S08/MCP23S17?



#5 ShVerni

ShVerni

    Advanced Member

  • Members
  • PipPipPip
  • 138 posts
  • LocationNew York, New York

Posted 12 October 2015 - 04:01 PM

I'm afraid I don't, but here's the hookups you need for the MCP23S08:

 

MCP23S08       Netduino

SCK (1)     -->  13 (SPCK)

SI (2)         -->  11 (MOSI)

SO (3)       -->  12 (MISO)

A1 (4)        -->  GND

A0 (5)        -->  GND

RESET (6) -->  3.3V

CS (7)        --> 10

INT (8) Not connected (optional)

VSS (9)      --> GND

VDD (18)   --> 3.3V

 

 

The MCP23S17 is much the same (except the pin numbers are different) but it has an additional address pin A2 that is connected to ground. The address pins (A0, A1) define the address of the chip, and are used when initializing the chip like so:

// Use "new MCP23S08(CS pin, address)" to initialize an expander 
MCP23S08 expander = new MCP23S08(Pins.GPIO_PIN_D10, 0x00);

When A0 and A1 are both connected to ground, the address is 0x00. Here's a table of addresses for the MCP23S08:

 

A0       A1      Address

GND   GND   0x00

3.3V   GND   0x01

GND   3.3V   0x02

3.3V   3.3V   0x03



#6 Greg Chao

Greg Chao

    Member

  • Members
  • PipPip
  • 14 posts

Posted 15 October 2015 - 06:39 AM

Thanks. I'll give it a try

#7 Greg Chao

Greg Chao

    Member

  • Members
  • PipPip
  • 14 posts

Posted 27 October 2015 - 04:55 AM

I am programming in vb.net.  Is it possible to use your driver without converting it?



#8 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 27 October 2015 - 06:56 AM

I am programming in vb.net.  Is it possible to use your driver without converting it?

 

I know you can do this with standard C# and VB.  I'd normally do something like:

  1. Create a new project in your VB solution with the C# code in it and compile the code to a DLL.
  2. Next make sure the C# code is CLS compliant.  I think there is an attribute for this.  Yes there is - add [assembly:CLSCompliant(true)] under your using statements.   You will get errors if the code is not compliant.
  3. Reference the DLL in your VB project.

BTW - if you really need to convert the code then Telerik have a free online converter.

 

Regards,

Mark


To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#9 Greg Chao

Greg Chao

    Member

  • Members
  • PipPip
  • 14 posts

Posted 30 October 2015 - 05:22 AM

I have another question.  I am using a Netduino 3 and am using digital I/O pins 11,12,13 for MOSI, MISO, and SPCK.  What should I use for CS??



#10 TechnoGuy

TechnoGuy

    Advanced Member

  • Members
  • PipPipPip
  • 51 posts
  • LocationCanada

Posted 30 October 2015 - 06:36 AM

Hi Greg,

 

You're talking about using SPI - the Serial Peripheral Interface.  That's an interface where you can connect up multiple slave devices in a bus-type configuration.

 

For example you'd use the Netduino as MASTER (controller) and you could have (say) 3 devices as SLAVES.

 

To hook everything together, you'd make the connections as follows:

  • Connect MOSI (Digital 11) on Netduino to the MOSI pins on each of the slaves  "Master Output / Slave Input"
  • Connect MISO (Digital 12) on Netduino to the MISO pins on each of the slaves  "Master Input / Slave Output"
  • Connect SPCK (Digital 13) on Netduino to the clock pins on each of the slaves  "SPI Clock"
  • Connect power & ground as well

Then you'd need to use 1 additional Digital Pin on the Netduino as "Slave Select" (SS) for EACH of the 3 slaves.  You'd connect a separate wire from the Netduino to EACH of the 3 slaves.  On the SPI devices that I have, the corresponding pin on the slave is marked "CS" (chip select).

 

For "Slave Select", you can just use any digital pin (on the Netduino) that isn't already being used for something else.  There is not a specific pin to be used.  I have seen in the Arduino world that they have suggested pins to be used for different things - e.g. SD Card Reader, TFT Display, etc.  That's just a convention.  It's basically to avoid conflicts when stacking ready-made shields & to reduce the need to have to go into canned code & customize values.

 

I found an interesting SPI & I2C tutorial on Youtube the other day that was created by Pete Dokter of SparkFun Electronics.  He's very knowledgeable on these things.  You might want to check it out.

 

SparkFun According to Pete:  SPI & I2C

 

Lastly, I've found that the there are sometimes alternative names used on devices (both slaves & masters) for the pins.  I've seen "DOUT" used (for example) as an alternative name for MOSI and "DIN" as an alternate name for "MISO".  There's a good conversion table on Wikipedia, here.

 

Good luck.


- Ian

 

My Current Dev Boards:

  • 3 x Netduino Plus 2
  • 1 x Netduino 3 WiFi

#11 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 30 October 2015 - 07:36 AM

Also, if you only have one device then you can tie the CS pin to either high or low to permanently select the device.  Similarly, if you have a chain of devices where the serial out of one goes to the serial in of the next then these could all have the CS pin set to permanently select the device chain,  The 74595 is a good example of this.

 

Regards,

Mark


To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#12 Greg Chao

Greg Chao

    Member

  • Members
  • PipPip
  • 14 posts

Posted 02 November 2015 - 06:49 PM

Thanks Mark, the VB converter is fantastic.  It is the route I am using since I am making modifications to the original driver by ShVerni.  His code is very impressive.  I will post again when I get it working.



#13 ShVerni

ShVerni

    Advanced Member

  • Members
  • PipPipPip
  • 138 posts
  • LocationNew York, New York

Posted 02 November 2015 - 10:25 PM

Please do keep us posted, I'd be interested to see what changes you make to the driver, as I'm certain it could use some improvements!



#14 Greg Chao

Greg Chao

    Member

  • Members
  • PipPip
  • 14 posts

Posted 03 November 2015 - 09:51 PM

Does anyone have any recommendations for producing a board?  what are some good board manufactures and what kind of board layout software should I use?



#15 ShVerni

ShVerni

    Advanced Member

  • Members
  • PipPipPip
  • 138 posts
  • LocationNew York, New York

Posted 03 November 2015 - 10:23 PM

I really like to use OSH Park, and have had excellent results from them. They prefer you use Eagle from Cadsoft, but they accept gerber files from any PCB design program. You can find details here:

 

https://oshpark.com/guidelines



#16 Greg Chao

Greg Chao

    Member

  • Members
  • PipPip
  • 14 posts

Posted 04 November 2015 - 12:48 AM

Success!  I have 16 additional digital I/O per MCP23S17 chip.  Since there is a three bit address, I can multiply that by 8.  Very cool...

 

Thank you ShVerni and Mark....

 

I used the Telerik converter to get the code to VB.net.  Worked great.  I ran into two issues.  First, for some reason, the version of .NET that I have does not support shift operation so I had to write my own subroutine.  Second, ShVerni's original code had some addressing issues with MCP23S17 since he was using a different chip for his project.  I had to modify the addressing to track the 16 bits.  Other than that, it works great.

 

Here is the code for anyone interested.  You can copy it into a class module and call it from your main module as recommended by ShVerni.

Imports System
Imports Microsoft.SPOT
Imports Microsoft.SPOT.Hardware

''' <summary>
''' Driver for a MCP23S17 I/O expander (http://www.microchip.com/wwwproducts/Devices.aspx?product=MCP23S17)
''' </summary>

Public Class MCP23S17
    ' Enumeration of the GPIOs: 0-7 (GPA0-GPA7), 8-15 (GPB0-GPB7)
    Public Enum ports As Byte
        GP0 = &H0   ' GPA0
        GP1 = &H1
        GP2 = &H2
        GP3 = &H3
        GP4 = &H4
        GP5 = &H5
        GP6 = &H6
        GP7 = &H7    ' GPA7
        GP8 = &H8    ' GPB0
        GP9 = &H9
        GP10 = &HA
        GP11 = &HB
        GP12 = &HC
        GP13 = &HD
        GP14 = &HE
        GP15 = &HF   ' GPB7
    End Enum
    ' <summary>
    ' Device configuration settings
    ' </summary>
    Public Enum settings As UShort
        ' gc, to get logic right
        ' gc, if bit needs to be a 1, then all other bits are 0
        ' gc, if bit needs to be a 0, the all other are 1
        ' Set to two 8-bit banks
        BANK_SEP = &H8080
        ' Set to one 16-bit bank (this driver is configured for 16-bit use)
        BANK_SAME = &H7F7F
        ' Enable mirroring of interrupt ports
        MIRROR_ENABLE = &H4040
        ' Disable mirroring of interrupt ports
        MIRROR_DISABLE = &HBFBF
        ' Enable sequential operation mode (not recommended)
        SEQOP_ENABLE = &HDFDF
        ' Disable sequential operation mode
        SEQOP_DISABLE = &H2020
        ' Enable slew control for SDA pins
        DISSLW_ENABLE = &HEFEF
        ' Disable slew control for SDA pins
        DISSLW_DISABLE = &H1010
        ' Enable hardware address pins (allows multiple MCP23S17 on one chip select pin)
        HAEN_ENABLE = &H808
        ' Disable hardware address pins
        HAEN_DISABLE = &HF7F7
        ''' Set the interrupt pin to be open-drain
        ODR_OPEN_DRAIN = &H404
        ' Set the interrupt pin to active driver
        ODR_ACTICE_DRIVER = &HFBFB
        ' Set interrupt pin to active high when in active driver mode
        INTPOL_ACTIVE_HIGH = &H202
        ' Set interrupt pin to active low when in active driver mode
        INTPOL_ACTIVE_LOW = &HFDFD
    End Enum
    ' Port configuration settings
    Public Enum portConfig As Byte
        ' gc, assigned additional valus for B side
        ' set port as output
        OUTPUT = &H0
        ' Set port as input
        INPUT = &H1
        ' Set the polarity of the input to the same as the port state (i.e. a high port state is reported as 1, and vice versa)
        INPUT_POLARITY_SAME = &H2
        ' Set the polarity of the input to the opposite as the port state (i.e. a high port state is reported as 0, and vice versa)
        INPUT_POLARITY_OPP = &H3
        ' Enable interrupt on port
        ENABLE_INTERRUPT = &H4
        ' Disable interrupt on port
        DISABLE_INTERRUPT = &H5
        ' Set the port interrupt state to low
        INTTERUPT_LOW = &H6
        ' Set the port interrupt state to high
        INTTERUPT_HIGH = &H7
        ' Set the port interrupt state to both (i.e. change)
        INTERRUPT_BOTH = &H8
        ' Enable port pull-up resistor (input only)
        PULL_UP_ENABLE = &H9
        ' Disable port pull-up resistor (input only)
        PULL_UP_DISABLE = &HA
    End Enum

    ' Register map, see the data sheet for details
    Private Enum register As Byte
        IODIRA = &H0
        IPOLA = &H2
        GPINTENA = &H4
        DEFVALA = &H6
        INTCONA = &H8
        IOCONA = &HA
        GPPUA = &HC
        INTFA = &HE
        INTCAPA = &H10
        GPIOA = &H12
        OLATA = &H14
        'gc, added for addressing B side
        IODIRB = &H1
        IPOLB = &H3
        GPINTENB = &H5
        DEFVALB = &H7
        INTCONB = &H9
        IOCONB = &HB
        GPPUB = &HD
        INTFB = &HF
        INTCAPB = &H11
        GPIOB = &H13
        OLATB = &H15
    End Enum

    ' Store some settings
    Private _MCP23S17 As SPI
    ' MultiSPI can be swapped with regular SPI if using one device
    Private _opcodeW As Byte, _opcodeR As Byte

    ''' <summary>
    ''' Constructs a MCP23S17 object
    ''' </summary>
    ''' <param name="cs">The chip select pin used</param>
    ''' <param name="address">The address defined by pins A0, A1, and A2</param>
    Public Sub New(cs As Cpu.Pin, address As Byte)
        ' Can be replaced with regular SPI if using one device
        _MCP23S17 = New SPI(New SPI.Configuration(ChipSelect_Port:=cs, ChipSelect_ActiveState:=False, ChipSelect_SetupTime:=0, ChipSelect_HoldTime:=0, Clock_IdleState:=False, Clock_Edge:=True, Clock_RateKHz:=4800, SPI_mod:=SPI.SPI_module.SPI1))

        ' The opcode is a combination 4 bit fix 0100 code plus a 3 bit address and 1 bit = 0 (write) or 1 (read)
        '_opcodeW = CByte((&H4 << 4) Or (address << 1))
        'gc, hardcoded since this will never change.
        _opcodeW = &H40
        ' address set by hardware
        '_opcodeR = CByte(_opcodeW + 1)
        _opcodeR = &H41
        '
        ' 0 - gc, set up the 16 bits
        configure(MCP23S17.settings.BANK_SAME, 0)
        ' 1 -gc, mirror enables - int bit tied together - I am not using interrupts so it doesn't matter
        configure(MCP23S17.settings.MIRROR_ENABLE, 0)
        ' 1 -Disable sequential operation mode as this driver is not configured to use it
        configure(MCP23S17.settings.SEQOP_DISABLE, 0)
        ' 1 -gc, disable the slew rate
        configure(MCP23S17.settings.DISSLW_DISABLE, 0)
        ' 1 -Set up the expander to use its address by default
        configure(MCP23S17.settings.HAEN_ENABLE, 0)
        ' 0 gc, interrupt active driver, don't care
        configure(MCP23S17.settings.ODR_ACTICE_DRIVER, 0)
        ' 1 -gc, interrupt polarity as active high
        configure(MCP23S17.settings.INTPOL_ACTIVE_HIGH, 0)
        ' 0 - gc, set up the 16 bits
        configure(MCP23S17.settings.BANK_SAME, 1)
        ' 1 -gc, mirror enables - int bit tied together - I am not using interrupts so it doesn't matter
        configure(MCP23S17.settings.MIRROR_ENABLE, 1)
        ' 1 -Disable sequential operation mode as this driver is not configured to use it
        configure(MCP23S17.settings.SEQOP_DISABLE, 1)
        ' 1 -gc, disable the slew rate
        configure(MCP23S17.settings.DISSLW_DISABLE, 1)
        ' 1 -Set up the expander to use its address by default
        configure(MCP23S17.settings.HAEN_ENABLE, 1)
        ' 0 gc, interrupt active driver, don't care
        configure(MCP23S17.settings.ODR_ACTICE_DRIVER, 1)
        ' 1 -gc, interrupt polarity as active high
        configure(MCP23S17.settings.INTPOL_ACTIVE_HIGH, 1)
    End Sub
    '
    Public Function bsu(ByVal value As UShort, ByVal shiftvalue As UShort) As UShort
        For i As Integer = 0 To CInt(shiftvalue) - 1
            value = CUShort(value) * CUShort(2)
        Next i
        Return value
    End Function
    ' Configure settings for the MCP23S17
    ' <param name="set">The setting to apply</param>
    Public Sub configure(sett As settings, AorB As Integer)
        Dim config As UShort
        If AorB = 0 Then
            config = read(register.IOCONA)
        Else
            config = read(register.IOCONB)
        End If
            Select Case CUShort(sett)
                Case &H8080
                    If CUShort(sett) = &H8080 Then
                        config = config Or CUShort(sett)
                    Else
                        config = config And CUShort(sett)
                    End If
                Case Else
                    If CUShort(sett) < &H8080 Then
                        ' gc, clever trick to distinguish setting a 1 or 0
                        ' gc, works for all cases except 8080
                        config = config Or CUShort(sett)
                    Else
                        config = config And CUShort(sett)
                    End If
            End Select
        If AorB = 0 Then
            write(register.IOCONA, config)
        Else
            write(register.IOCONB, config)
        End If
    End Sub

    ' Configure the settings of a port
    ' <param name="port">The port to configure</param>
    ' gc, port is a single bit that you want to change
    ' gc, this technique will change only one bit amoung 8 bits
    ' <param name="config">The setting to apply</param>
    Public Sub setupPort(port As ports, config As portConfig)
        Dim buffer As UShort
        Dim offsetport As UShort
        Select Case config
            Case portConfig.OUTPUT
                If port < &H8 Then
                    buffer = read(register.IODIRA)
                    offsetport = &H0
                    'buffer = buffer And CUShort(Not (1 << CByte(port)))
                    buffer = buffer And (Not bsu(1, CUShort(port) - offsetport + CUShort(&H8)))
                    write(register.IODIRA, buffer)
                Else
                    buffer = read(register.IODIRB)
                    offsetport = &H8
                    'buffer = buffer And CUShort(Not (1 << CByte(port)))
                    buffer = buffer And (Not bsu(1, CUShort(port) - offsetport + CUShort(&H8)))
                    write(register.IODIRB, buffer)
                End If
            Case portConfig.INPUT
                If port < &H8 Then
                    buffer = read(register.IODIRA)
                    offsetport = &H0
                    'buffer = buffer Or CUShort(1 << CByte(port))
                    buffer = buffer Or bsu(1, CUShort(port) - offsetport + CUShort(&H8))
                    write(register.IODIRA, buffer)
                Else
                    buffer = read(register.IODIRB)
                    offsetport = &H8
                    'buffer = buffer Or CUShort(1 << CByte(port))
                    buffer = buffer Or bsu(1, CByte(port) - offsetport + CUShort(&H8))
                    write(register.IODIRB, buffer)
                End If
            Case portConfig.PULL_UP_DISABLE
                If port < &H8 Then
                    buffer = read(register.GPPUA)
                    offsetport = &H0
                    'buffer = buffer And CUShort(Not (1 << CByte(port)))
                    buffer = buffer And (Not bsu(1, CUShort(port) - offsetport + CUShort(&H8)))
                    write(register.GPPUA, buffer)
                Else
                    buffer = read(register.GPPUB)
                    offsetport = &H8
                    'buffer = buffer And CUShort(Not (1 << CByte(port)))
                    buffer = buffer And (Not bsu(1, CUShort(port) - offsetport + CUShort(&H8)))
                    write(register.GPPUB, buffer)
                End If
            Case portConfig.PULL_UP_ENABLE
                If port < &H8 Then
                    buffer = read(register.GPPUA)
                    offsetport = &H0
                    'buffer = buffer Or CUShort(1 << CByte(port))
                    buffer = buffer Or bsu(1, CUShort(port) - offsetport + CUShort(&H8))
                    write(register.GPPUA, buffer)
                Else
                    buffer = read(register.GPPUB)
                    offsetport = &H8
                    'buffer = buffer Or CUShort(1 << CByte(port))
                    buffer = buffer Or bsu(1, CUShort(port) - offsetport + CUShort(&H8))
                    write(register.GPPUB, buffer)
                End If
            Case portConfig.INPUT_POLARITY_SAME
                If port < &H8 Then
                    buffer = read(register.IPOLA)
                    offsetport = &H0
                    'buffer = buffer And CUShort(Not (1 << CByte(port)))
                    buffer = buffer And (Not bsu(1, CUShort(port) - offsetport + CUShort(&H8)))
                    write(register.IPOLA, buffer)
                Else
                    buffer = read(register.IPOLB)
                    offsetport = &H8
                    'buffer = buffer And CUShort(Not (1 << CByte(port)))
                    buffer = buffer And (Not bsu(1, CUShort(port) - offsetport + CUShort(&H8)))
                    write(register.IPOLB, buffer)
                End If
            Case portConfig.INPUT_POLARITY_OPP
                If port < &H8 Then
                    buffer = read(register.IPOLA)
                    offsetport = &H0
                    'buffer = buffer Or CUShort(1 << CByte(port))
                    buffer = buffer Or bsu(1, CUShort(port) - offsetport + CUShort(&H8))
                    write(register.IPOLA, buffer)
                Else
                    buffer = read(register.IPOLB)
                    offsetport = &H8
                    'buffer = buffer Or CUShort(1 << CByte(port))
                    buffer = buffer Or bsu(1, CUShort(port) - offsetport + CUShort(&H8))
                    write(register.IPOLB, buffer)
                End If
            Case portConfig.DISABLE_INTERRUPT
                If port < &H8 Then
                    buffer = read(register.GPINTENA)
                    offsetport = &H0
                    'buffer = buffer And CUShort(Not (1 << CByte(port)))
                    buffer = buffer And (Not bsu(1, CUShort(port) - offsetport + CUShort(&H8)))
                    write(register.GPINTENA, buffer)
                Else
                    buffer = read(register.GPINTENB)
                    offsetport = &H8
                    'buffer = buffer And CUShort(Not (1 << CByte(port)))
                    buffer = buffer And (Not bsu(1, CUShort(port) - offsetport + CUShort(&H8)))
                    write(register.GPINTENB, buffer)
                End If
            Case portConfig.ENABLE_INTERRUPT
                If port < &H8 Then
                    buffer = read(register.GPINTENA)
                    offsetport = &H0
                    'buffer = buffer Or CUShort(1 << CByte(port))
                    buffer = buffer Or bsu(1, CUShort(port) - offsetport + CUShort(&H8))
                    write(register.GPINTENA, buffer)
                Else
                    buffer = read(register.GPINTENB)
                    offsetport = &H8
                    'buffer = buffer Or CUShort(1 << CByte(port))
                    buffer = buffer Or bsu(1, CUShort(port) - offsetport + CUShort(&H8))
                    write(register.GPINTENB, buffer)
                End If
            Case portConfig.INTTERUPT_LOW
                If port < &H8 Then
                    buffer = read(register.DEFVALA)
                    offsetport = &H0
                    'buffer = buffer And CUShort(Not (1 << CByte(port)))
                    buffer = buffer And (Not bsu(1, CUShort(port) - offsetport + CUShort(&H8)))
                    write(register.DEFVALA, buffer)
                    buffer = read(register.INTCONA)
                    'buffer = buffer Or CUShort(1 << CByte(port))
                    buffer = buffer Or bsu(1, CUShort(port) - offsetport + CUShort(&H8))
                    write(register.INTCONA, buffer)
                Else
                    buffer = read(register.DEFVALB)
                    offsetport = &H8
                    'buffer = buffer And CUShort(Not (1 << CByte(port)))
                    buffer = buffer And (Not bsu(1, CUShort(port) - offsetport + CUShort(&H8)))
                    write(register.DEFVALB, buffer)
                    buffer = read(register.INTCONB)
                    'buffer = buffer Or CUShort(1 << CByte(port))
                    buffer = buffer Or bsu(1, CUShort(port) - offsetport + CUShort(&H8))
                    write(register.INTCONB, buffer)
                End If
            Case portConfig.INTTERUPT_HIGH
                If port < &H8 Then
                    buffer = read(register.DEFVALA)
                    offsetport = &H0
                    'buffer = buffer Or CUShort(1 << CByte(port))
                    buffer = buffer Or bsu(1, CUShort(port) - offsetport + CUShort(&H8))
                    write(register.DEFVALA, buffer)
                    buffer = read(register.INTCONA)
                    'buffer = buffer Or CUShort(1 << CByte(port))
                    buffer = buffer Or bsu(1, CUShort(port) - offsetport + CUShort(&H8))
                    write(register.INTCONA, buffer)
                Else
                    buffer = read(register.DEFVALB)
                    offsetport = &H8
                    'buffer = buffer Or CUShort(1 << CByte(port))
                    buffer = buffer Or bsu(1, CUShort(port) - offsetport + CUShort(&H8))
                    write(register.DEFVALB, buffer)
                    buffer = read(register.INTCONB)
                    'buffer = buffer Or CUShort(1 << CByte(port))
                    buffer = buffer Or bsu(1, CUShort(port) - offsetport + CUShort(&H8))
                    write(register.INTCONB, buffer)
                End If
            Case portConfig.INTERRUPT_BOTH
                If port < &H8 Then
                    buffer = read(register.INTCONA)
                    offsetport = &H0
                    'buffer = buffer And CUShort(Not (1 << CByte(port)))
                    buffer = buffer And (Not bsu(1, CUShort(port) - offsetport + CUShort(&H8)))
                    write(register.INTCONA, buffer)
                Else
                    buffer = read(register.INTCONB)
                    offsetport = &H0
                    'buffer = buffer And CUShort(Not (1 << CByte(port)))
                    buffer = buffer And (Not bsu(1, CUShort(port) - offsetport + CUShort(&H8)))
                    write(register.INTCONB, buffer)
                End If
        End Select
    End Sub

    ' Set the states of the port latches, which correspond to the states of the ouput ports
    ' <param name="portSettings">The latch settings to apply to the ports</param>
    Public Sub writePorts(portSettings As UShort, AorB As Integer)
        If AorB = 0 Then
            write(register.OLATA, portsettings)
        Else
            write(register.OLATB, portsettings)
        End If
    End Sub

    ' Read the states of all the GPIO ports or the port latches
    ' <param name="latch">If true, returns the latch states for the ports instead of the port states</param>
    ' <returns>A ushort where each bit repersents the state of the corresponding port</returns>
    Public Function readPorts(Optional latch As Boolean = False, Optional AorB As Integer = 0) As UShort
        If AorB = 0 Then
            If latch Then
                Return read(register.OLATA)
            Else
                Return read(register.GPIOA)
            End If
        Else
            If latch Then
                Return read(register.OLATB)
            Else
                Return read(register.GPIOB)
            End If
        End If
    End Function

    '' Retrieves the parameters related to an interrupt event
    '' <returns>A ushort array containing two ushorts corresponding to the INTF and INTCAP registers respectively. See the data sheet for details</returns>
    'Public Function checkInterrupt() As UShort()
    '    Dim buffer As UShort() = New UShort(1) {}
    '    buffer(0) = read(register.INTFA)
    '    buffer(1) = read(register.INTCAPA)
    '    Return buffer
    'End Function

    ' Reads the data from a register
    ' <param name="reg">The register to read</param>
    ' <returns>The data in the register</returns>
    Private Function read(reg As register) As UShort
        'Dim bufferW As UShort() = {CUShort((_opcodeR << 8) Or CByte(reg))}
        Dim bufferW As UShort() = {CUShort(&H4100 Or CByte(reg))}
        Dim bufferR As UShort() = New UShort(0) {}
        ' Need to wait for the opcode and register address to be sent before beginning to read data
        _MCP23S17.WriteRead(bufferW, bufferR, 1)
        Return bufferR(0)
    End Function

    ' Writes data to a register
    ' <param name="reg">The register to write</param>
    ' <param name="data">The data to write</param>
    Private Sub write(reg As register, data As UShort)
        'If reg = register.INTCAP OrElse reg = register.INTF Then
        '    Throw New System.ArgumentException("INTCAP and INTF are read-only", "reg")
        'End If
        'Dim opcode As UShort = CUShort((_opcodeW << 8) Or CByte(reg))
        Dim opcode As UShort = CUShort(&H4000 Or CByte(reg))
        Dim buffer As UShort() = {opcode, data}
        _MCP23S17.Write(buffer)
    End Sub
    '

End Class

' Class for using the MCP23S17 ports like native input ports 
Public Class ExpandedInputPort
    ' Store some settings
    Private _port As UShort
    Private _expander17 As MCP23S17 = Nothing
    Private portAB As Byte

    ' Creates an input port on a MCP23S17 expander
    ' </summary>
    ' The port to use</param>
    '<param name="resistor">Enable the 100kOhm pull-up resistor</param>
    ' <param name="expander">The MCP23S17 with the port</param>
    Public Sub New(port__1 As MCP23S17.ports, resistor As Port.ResistorMode, expander As MCP23S17)
        '_port = CUShort(1 << CByte(port__1))
        Dim portoffset As UShort
        If port__1 < &H8 Then
            portoffset = &H0
        Else
            portoffset = &H8
        End If
        _port = bsu(1, CUShort(port__1) - portoffset + CUShort(&H8))
        _expander17 = expander
        _expander17.setupPort(port__1, MCP23S17.portConfig.INPUT)
        portAB = port__1
        Select Case resistor
            Case Port.ResistorMode.Disabled
                _expander17.setupPort(port__1, MCP23S17.portConfig.PULL_UP_DISABLE)
                Exit Select
            Case Port.ResistorMode.PullUp
                _expander17.setupPort(port__1, MCP23S17.portConfig.PULL_UP_ENABLE)
                Exit Select
            Case Else
                Throw New System.NotSupportedException("Pull-down resistors not supported")
        End Select
    End Sub
    '
    Public Function bsu(ByVal value As UShort, ByVal shiftvalue As UShort) As UShort
        For i As Integer = 0 To CInt(shiftvalue) - 1
            value = CUShort(value) * CUShort(2)
        Next i
        Return value
    End Function
    ' Read the state of the port
    ' </summary>
    ' <returns>The state of the port</returns>
    Public Function Read() As Boolean
        Dim buffer As UShort
        If portAB < &H8 Then
            buffer = _expander17.readPorts(False, 0)  'very important to use false to set reading GPIO rather than Latches
        Else
            buffer = _expander17.readPorts(False, 1)
        End If
        Return _port = (buffer And _port)
    End Function
    '
    Public Sub tester1()
        _expander17.setupPort(MCP23S17.ports.GP7, MCP23S17.portConfig.INPUT)
    End Sub
    ' Disposes of the port
    Public Sub Dispose()
        _expander17 = Nothing
    End Sub

    Protected Overrides Sub Finalize()
        Try
            Dispose()
        Finally
            MyBase.Finalize()
        End Try
    End Sub
End Class

' Class for using the MCP23S08/MCP23S17 ports like native output ports 
Public Class ExpandedOuputPort
    ' Store some settings
    Private _port As UShort
    Private _expander17 As MCP23S17 = Nothing
    Private portAB As Byte

    ' Creates an output port on a MCP23S17 expander
    ' <param name="port">The port to use</param>
    ' <param name="initialState">The initial state of the port</param>
    ' <param name="expander">The MCP23S08 with the port</param>
    Public Sub New(port As MCP23S17.ports, initialState As Boolean, expander As MCP23S17)
        _expander17 = expander
        _expander17.setupPort(port, MCP23S17.portConfig.OUTPUT)
        portAB = port
        Dim buffer As UShort
        Dim portoffset As UShort
        If port < &H8 Then
            portoffset = &H0
            '_port = CUShort(1 << CByte(port))
            _port = bsu(1, CUShort(port) - portoffset + CUShort(&H8))
            buffer = _expander17.readPorts(True, 0)
            If initialState Then
                buffer = buffer Or _port
            Else
                buffer = buffer And CUShort(Not _port)
            End If
            _expander17.writePorts(buffer, 0)
        Else
            portoffset = &H8
            '_port = CUShort(1 << CByte(port))
            _port = bsu(1, CUShort(port) - portoffset + CUShort(&H8))
            buffer = _expander17.readPorts(True, 1)
            If initialState Then
                buffer = buffer Or _port
            Else
                buffer = buffer And CUShort(Not _port)
            End If
            _expander17.writePorts(buffer, 1)
        End If
    End Sub
    '
    Public Function bsu(ByVal value As UShort, ByVal shiftvalue As UShort) As UShort
        For i As Integer = 0 To CInt(shiftvalue) - 1
            value = CUShort(value) * CUShort(2)
        Next i
        Return value
    End Function
    ' Read the state of the port
    ' <returns>The state of the port</returns>
    Public Function Read() As Boolean
        Dim buffer As UShort
        If portAB < &H8 Then
            buffer = _expander17.readPorts(True, 0)
        Else
            buffer = _expander17.readPorts(True, 1)
        End If
        Return _port = (buffer And _port)
    End Function

    ' Write the state of the port
    ' <param name="state">The state to write</param>
    Public Sub Write(state As Boolean)
        Dim buffer As UShort
        If portAB <= &H8 Then
            buffer = _expander17.readPorts(True, 0)
            If state Then
                buffer = buffer Or _port
            Else
                buffer = buffer And CUShort(Not _port)
            End If
            'buffer = _port
            _expander17.writePorts(buffer, 0)
        Else
            buffer = _expander17.readPorts(True, 1)
            If state Then
                buffer = buffer Or _port
            Else
                buffer = buffer And CUShort(Not _port)
            End If
            'buffer = _port
            _expander17.writePorts(buffer, 1)
        End If
    End Sub

    ' Disposes of the port
    Public Sub Dispose()
        _expander17 = Nothing
    End Sub

    Protected Overrides Sub Finalize()
        Try
            Dispose()
        Finally
            MyBase.Finalize()
        End Try
    End Sub
    '
    Public Sub tester()
        '_expander17.configure(MCP23S17.settings.BANK_SAME, 0)
        '1 -gc, mirror enables - int bit tied together - I am not using interrupts so it doesn't matter
        '_expander17.configure(MCP23S17.settings.MIRROR_ENABLE, 1)
        ' 1 -Disable sequential operation mode as this driver is not configured to use it
        '_expander17.configure(MCP23S17.settings.SEQOP_DISABLE, 0)
        ' 1 -gc, disable the slew rate
        '_expander17.configure(MCP23S17.settings.DISSLW_DISABLE, 0)
        ' 1 -Set up the expander to use its address by default
        '_expander17.configure(MCP23S17.settings.HAEN_ENABLE, 0)
        ' 0 gc, interrupt active driver, don't care
        '_expander17.configure(MCP23S17.settings.ODR_ACTICE_DRIVER, 0)
        ' 1 -gc, interrupt polarity as active high
        '_expander17.configure(MCP23S17.settings.INTPOL_ACTIVE_HIGH, 0)
    End Sub
End Class

'=======================================================
'Service provided by Telerik (www.telerik.com)
'Conversion powered by NRefactory.
'Twitter: @telerik
'Facebook: facebook.com/telerik
'=======================================================


?



#17 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 04 November 2015 - 06:23 AM

Does anyone have any recommendations for producing a board?  what are some good board manufactures and what kind of board layout software should I use?

 

I use iTead, their service is cheap but takes about two weeks, one week for production and then another week for shipping.  They are good at processing the gerbers when they arrive though.  I have previously submitted boards with issues and they have told me about it within 24 hours.

 

For board design I have used Designspark on the PC but I have recently moved to a Mac and so I am now using KiCAD.  Both are free and reasonably easy to use.  Unlike Eagle, they are free for boards of any size.  Eagle has limits for the free version but most hobbyists are producing boards within the free limits.

 

Hope this helps,

Mark


To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#18 JoopC

JoopC

    Advanced Member

  • Members
  • PipPipPip
  • 148 posts

Posted 04 November 2015 - 07:45 AM

Note: in earlier versions of .netMF the normal syntax << and >> were fully supported, but somehow there is an error in the latest .netMF I have report this bug several times.

bit shifting in VB:

' X * 2 ^ Y for << left shifting
' X / 2 ^ Y for >> right shifting

'so 4 << 7 = new syntax 4 * 2 ^ 7
'so 5 >> 3 = new syntax 5 / 2 ^ 3

(a positive note, the workaround is much faster)




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.