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

Controlling multiple LEDs with a few outputs as possible


  • Please log in to reply
18 replies to this topic

#1 Basiclife

Basiclife

    Member

  • Members
  • PipPip
  • 27 posts

Posted 02 January 2011 - 09:03 PM

Hi all,

I'm running through some possible projects and one question which sprang to mind is how many status LEDs can I support easily without using up too many outputs.

One idea which feels a little bit hacky is to use a single output wired into a 4- or 8-bit counter. Wire the LEDs/resistors up to the outputs and pulse the counter enough times to get the desired LED combination.

I could ignore the reset pin and keep an internal track of the current count - then just keep counting until the counter rolls over to 0 and then set the new status as appropriate.

Something Like:

public class Status
{


//Bit 0
	private bool _ReadingData = false;
	public bool ReadingData {
		get { return _ReadingData; }
		set {
			_ReadingData = value;
			UpdateDisplay();
		}
	}

//Bit 1
	private bool _Working = false;
	public bool Working {
		get { return _Working; }
		set {
			_Working = value;
			UpdateDisplay();
		}
	}


	private int CurrentCount = 0;

	private int CounterLimit = 15;
	private void UpdateDisplay()
	{
		dynamic DesiredCount = 	(_ReadingData ? 1 : 0) +
					(_Working ? 	2 : 0);
		while ((CurrentCount != DesiredCount)) {
			IncrementDiplayCount();
		}

	}

	private void IncrementDiplayCount()
	{
		CurrentCount += 1;
		if (CurrentCount > CounterLimit) {
			CurrentCount = 0;
		}

		//Toggle Output Bit here to actually increment the counter

	}

}

I'm not sure whether the intermediate states while counting would make the LEDs flicker noticeably.

Has anyone tried this before or have any suggestions? Is there a standard way of doing this that I'm not aware of (I'd initially thought of some sort of shift register - but that would require both an input and a clock - so 2 outputs)

Perhaps I need some form of multiplexing so I can double-up (or more) what my outputs control?

#2 Luke

Luke

    Member

  • Members
  • PipPip
  • 18 posts

Posted 05 January 2011 - 08:55 PM

A shift register would probably be preferable, but it would actually require 3 lines: input, clock, and latch. There wouldn't be flickering though because you wouldn't latch until the register was loaded. You can also daisy chain multiple registers without using any more pins so 3 pins could drive many LEDs. There's a good discussed with sample code and wiring here: http://forums.netdui...gister-example/

#3 AlfredBr

AlfredBr

    Advanced Member

  • Members
  • PipPipPip
  • 138 posts
  • LocationConnecticut, USA

Posted 06 January 2011 - 02:46 PM

The EZ-Expander works great with the Netduino. Provides a net gain of 13 more output-only pins. (There are 16 output pins, but you lose three driving the two 74HC595 shift registers.) http://nootropicdesi...om/ez-expander/

#4 Luke

Luke

    Member

  • Members
  • PipPip
  • 18 posts

Posted 06 January 2011 - 03:27 PM

The EZ-Expander works great with the Netduino. Provides a net gain of 13 more output-only pins. (There are 16 output pins, but you lose three driving the two 74HC595 shift registers.)

http://nootropicdesi...om/ez-expander/


Your link doesn't work, but I think this is what you're talking about:
http://nootropicdesi...om/ez-expander/

That looks nice and is basically what I was getting at.

#5 Charles

Charles

    Advanced Member

  • Members
  • PipPipPip
  • 192 posts

Posted 06 January 2011 - 04:14 PM

You could also use Charlieplexing, though it is a bit of a hack IMHO.

Wikipedia on Charlieplexing

The Arduino LoL Shield uses it:

SparkFun LoL Shield

#6 GDSever

GDSever

    Advanced Member

  • Members
  • PipPipPip
  • 81 posts
  • LocationNewark, DE

Posted 06 January 2011 - 04:56 PM

I am a big fan of the MCP23008 and MCP23017 digital I/O expander chips. They only use the two I2C pins, and you can put up to eight of them on the same I2C bus. The MCP23016 can also work, but the MCP23017 is much better IMO.

2 pins for I2C + 8 MCP23017s = 128 new digital I/O pins, for a net increase of 126 pins... not too shabby.

-Garrett

#7 fitims

fitims

    Member

  • Members
  • PipPip
  • 11 posts

Posted 24 February 2011 - 04:07 AM

Hi,

I am trying to connect netduino to an MCP23017, but without success. The attached picture shows the connection. I just want to be able to turn on a LED on one of the pins on MCP23017. The software I used is below:

   public class Program
    {
        const byte IOCON = 0x0a;
        const byte IODIRA = 0x00;
        const byte GPIOA = 0x12;
        const byte GPPUA = 0x0c;

        public static void Main()
        {
            I2CDevice.Configuration cfg = new I2CDevice.Configuration(0x20, 100);

            I2CDevice d = new I2CDevice(cfg);

            var setIOCON = I2CDevice.CreateWriteTransaction(new byte[] { IOCON, 0xA4 });
            var setIODIRA = I2CDevice.CreateWriteTransaction(new byte[] { IODIRA, 0x00 });

            var result = d.Execute(new I2CDevice.I2CTransaction[] { setIOCON }, 1000);
            var result2 = d.Execute(new I2CDevice.I2CTransaction[] { setIODIRA }, 1000);


            var resetGPIOA = I2CDevice.CreateWriteTransaction(new byte[] { GPIOA, 0x00 });
            var result3 = d.Execute(new I2CDevice.I2CTransaction[] { resetGPIOA }, 1000);

            Thread.Sleep(500);

            var setGPIOA = I2CDevice.CreateWriteTransaction(new byte[] { GPIOA, 0xff });
            var result4 = d.Execute(new I2CDevice.I2CTransaction[] { setGPIOA }, 1000);

            Thread.Sleep(500);
        }
    }


But, unfortunately it is not working. If someone can help me, I would be grateful.

Regards

Fitim

Attached Files



#8 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 24 February 2011 - 04:20 AM

Fitim, It looks like you've put pull-down resistors on your I2C line instead of pull-up resistors. I2C requires pull-up resistors instead (since the I2C protocol only "pulls down" the voltage, the I2C lines need to have default pull-ups). Chris

#9 fitims

fitims

    Member

  • Members
  • PipPip
  • 11 posts

Posted 24 February 2011 - 08:15 AM

Hi Chris, Thanks very much for the prompt reply. The resistors are actually connected to +5V and not GND (as in a picture). Sorry I made a mistake on the picture. The right connection (as I was using it) is on the new picture attached. But even with the right connection to the resistors, still not working. I event bought the second netduino thinking that I might have fried the first one. Regards Fitim

Attached Files



#10 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 24 February 2011 - 08:30 AM

But, unfortunately it is not working. If someone can help me, I would be grateful.

IMHO the device address should be 0x40. What are the values of result# variables (number of written bytes)?

#11 fitims

fitims

    Member

  • Members
  • PipPip
  • 11 posts

Posted 24 February 2011 - 12:03 PM

Hi, I have actually tried it with the address of 0x40, but still same problem. The result# values are 1, which means it is only sending 1 byte of data.

#12 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 24 February 2011 - 12:20 PM

I have actually tried it with the address of 0x40, but still same problem. The result# values are 1, which means it is only sending 1 byte of data.

Could you please try using pull-up resistors with higher value, like 1k, 2k2 or 4k7?

Note: You should use a current limiting resistor for the LED, MCP23017 absolute max current per output pin is only 25 mA.

#13 Tecchie

Tecchie

    Member

  • Members
  • PipPip
  • 23 posts
  • LocationGermany

Posted 24 February 2011 - 12:25 PM

    var setIOCON = I2CDevice.CreateWriteTransaction(new byte[] { IOCON, 0xA4 });


You're setting the IOCON.BANK Bit to 1, but you're using the register addresses for IOCON.BANK=0. So either don't set the BANK bit or use the correct register addresses for BANK=1.

#14 fitims

fitims

    Member

  • Members
  • PipPip
  • 11 posts

Posted 24 February 2011 - 08:06 PM

Hi Guys,

The pull-up resistors are on 1k5, and I have changed the code to look like:
public class Program
    {
        const byte IOCON = 0x0a;
        const byte IODIRA = 0x00;
        const byte GPIOA = 0x12;
        const byte GPPUA = 0x0c;

        public static void Main()
        {
            I2CDevice.Configuration cfg = new I2CDevice.Configuration(0x20, 100);

            I2CDevice d = new I2CDevice(cfg);

            var setIOCON = I2CDevice.CreateWriteTransaction(new byte[] { IOCON, 0x24 });
            var setIODIRA = I2CDevice.CreateWriteTransaction(new byte[] { IODIRA, 0x00 });

            var result = d.Execute(new I2CDevice.I2CTransaction[] { setIOCON }, 1000);
            var result2 = d.Execute(new I2CDevice.I2CTransaction[] { setIODIRA }, 1000);


            var resetGPIOA = I2CDevice.CreateWriteTransaction(new byte[] { GPIOA, 0x00 });
            var result3 = d.Execute(new I2CDevice.I2CTransaction[] { resetGPIOA }, 1000);

            Thread.Sleep(500);

            var setGPIOA = I2CDevice.CreateWriteTransaction(new byte[] { GPIOA, 0xff });
            var result4 = d.Execute(new I2CDevice.I2CTransaction[] { setGPIOA }, 1000);

            Thread.Sleep(500);
        }
    }

but still no success :(

#15 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 24 February 2011 - 08:35 PM

but still no success

You still have the device address wrong (should be 0x40). Then I would focus on getting the correct number of written bytes, comment out everything except one transaction, try using lower clock rates. If it does not work, then there is problem with the I2C communication. If it works, focus on the correct sequence and configuration. BTW, there is a missing connection on the lower breadboard ground rail (connected to the LED), this type of breadboard has separated left and right halves - but you may have it wired differently...

#16 klotz

klotz

    Advanced Member

  • Members
  • PipPipPip
  • 60 posts

Posted 24 February 2011 - 09:34 PM

I have had some success using I2C and I have the data sheet for the MCP23017 here in front of me so I think you are doing things right. I will have to get my hands on one the the chips to be sure.

First, the address should be in the range of 0x20 - 0x27. With the way it is wired, assuming the drawing is correct, the address of the configuration should be 0x20.
It appears that you have this right, but let me explain for those who may not be aware. The I2C address as used by the I2CDevice.Configuration is the 7-bit address. With some other interfaces for I2C, it is common to list two addresses for a device, one write address and one read address. The two addresses differ only in the lsb, where an even number is the write address and an odd number is the read. In the case of those interfaces, the address would be 0x40 for Write and 0x41 for Read.
This gets more confusing since some datasheets list the addresses as the Read/Write address, for instance Newhaven displays and the Sparkfun MPR121 use this method. In those cases to use the device you will often see
new I2CDevice.Configuration(ADDR >> 1, 100);

Second, according to the data sheet, when using the I2C device the speeds are 100kHz, 400kHz and 1.7 MHz so that is correct.

Now for the final point. I will admit that at this time I am just a compitent C# programmer. But I generally avoid using "var" when I know the data type. So, I would avoid using:
var setIOCON = I2CDevice.CreateWriteTransaction(new byte[] { IOCON, 0x24 }); 
instead I would have used:
I2CDevice.I2CTransaction setIOCON = I2CDevice.CreateWriteTransaction(new byte[] { IOCON, 0x24 }); 

Other than that I will see what I can do about duplicating you hardware and see if I can find something else.

#17 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 24 February 2011 - 10:12 PM

First, the address should be in the range of 0x20 - 0x27. With the way it is wired, assuming the drawing is correct, the address of the configuration should be 0x20.

You are right, the address does not include R/W bit. I am sorry for the confusion.

#18 klotz

klotz

    Advanced Member

  • Members
  • PipPipPip
  • 60 posts

Posted 25 February 2011 - 04:24 AM

I got your latest code to work by adding a pull-up resister on ~RESET(pin18). Not too obvious in the description in table 1-1 "Hardware reset. Must be externally biased" I sort-of had it working without the pull up but it was not reliable. Once I put the resister in there, it became extreemly reliable. Sorry I didn't notice this before. And by the way, I had it working without any of the code changes I suggested. http://www.vimeo.com/20357391

#19 fitims

fitims

    Member

  • Members
  • PipPip
  • 11 posts

Posted 25 February 2011 - 11:06 PM

Gentlemen ! Thank you very much for all your help. I finally got it working !!! I think my problem was that I didn't connect the RESET pin, as klotz kindly pointed out. Thanks again guys. I really appreciate your help. Regards Fitim




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.