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.
Hello,
Here is a simple LED test I created to learn I2C and the PCF8574 Port Expander.
At first I just sent some simple commands to turn the LEDS on and off.
Then I ran into Hinnie's Knightrider Project and added some of his code to mine.
I'm only using 1 Port expander and 6 LEDS. It was just a test and 6 LEDS is all that was plugged into my breadboard I was using.
The code supplied will do a 6 LED version of Knightrider and holding the onboard push button will do a different pattern test I was playing with.
One thing to note, my PCF8574 had a different ID than Hinnie's. If you are problems, that could something to look at.
Also, make sure you follow this little note I found:
that chip can drive LED's directly, but you have to connect them this way:
+5V------+LED-------330Rresistor------P8574pin
(edit: make sure the resistor is at least 330R)
This is called 'sinking' current, rather than 'sourcing' it.
According to the specifications on the datasheet, the 8574 can source ( i.e. give out during high pin state) only 100uA or .1ma, but it can sink (i.e. accept during low pin state) 20 milliamps.
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;
namespace NetduinoKN
{
public class Program
{
public static void Main()
{
new Thread(() => flashOnboardLed(3000)).Start();
I2CDevice MyI2CBus = new I2CDevice(null);
I2CDevice.Configuration pcf8574_0 = new I2CDevice.Configuration(0x38, 400);
I2CDevice.I2CTransaction[] xActions = new I2CDevice.I2CTransaction[1];
InputPort button = new InputPort(Pins.ONBOARD_SW1, false, Port.ResistorMode.Disabled);
bool buttonState = false;
int val = 0x0001; //Number of bits to have always on.
bool dir = false;
byte[] cmd = new byte[1];
int Max = 0x0020; //6 LEDS =32 Dec or 20 hex
while (true)
{
buttonState = button.Read();
if (!buttonState)
{
Pattern(MyI2CBus, pcf8574_0);
Thread.Sleep(500);
}
MyI2CBus.Config = pcf8574_0;
cmd[0] = (byte)(val ^ 0xFF);
xActions[0] = I2CDevice.CreateWriteTransaction(cmd);
MyI2CBus.Execute(xActions, 1000);
if ((val & Max) > 0)
dir = true;
if ((val & 0x0001) > 0)
dir = false;
if (!dir)
val = val << 1;
else
val = val >> 1;
Thread.Sleep(50);
}
}
public static void Pattern(I2CDevice MyI2CBus, I2CDevice.Configuration pcf8574_0)
{
I2CDevice.I2CTransaction[] xActions = new I2CDevice.I2CTransaction[1];
byte[] cmd = new byte[1];
int[] vals = {0xC,0x12,0x21,0x33,0x3F};
for (int i = 0; i < vals.Length; i++)
{
MyI2CBus.Config = pcf8574_0;
cmd[0] = (byte)(vals[i] ^ 0xFF);
xActions[0] = I2CDevice.CreateWriteTransaction(cmd);
MyI2CBus.Execute(xActions, 1000);
Thread.Sleep(100);
}
MyI2CBus.Config = pcf8574_0;
cmd[0] = (byte)(0 ^ 0xFF);
xActions[0] = I2CDevice.CreateWriteTransaction(cmd);
MyI2CBus.Execute(xActions, 1000);
}
public static void flashOnboardLed(object flashTime)
{
OutputPort led = new OutputPort(Pins.ONBOARD_LED, false);
while (true)
{
led.Write(!led.Read());
Thread.Sleep((int)flashTime);
}
}
}
}
One of these days I really need to try to understand I2C addressing - the chip you reference has a "prefix" of 0111 and your 3 address bits are all 0, so, 0111000. How the heck is that address 38?
I get it - once you realize it's right to left, not left to right it makes sense. Now it does at least! I'm slow, but I'm learning! Forum has been a huge help.
Apologies to the OP I don't mean to hijack your thread.
You might want to look into binary and hexadecimal maths, both are pretty easy, just alternative ways of representing integers. Here is a quick overview (and i purposely don't muddy the waters with negative numbers, i am purely talking about unsigned integers here)
Binary Starting with the basics, binary is a positional numbering system, and simply says that 1 means add the value of the position and 0 means dont add the value of the position. Binary is also known as base 2, what this means is that each position is equal to 2n where n is the number of places from the right most digit. i.e. the right most digit's value is equal to 20 = 1, the first digit from the right is equal to 21 = 2 etc.
Hexadecimal Hex is a notation which is more compact than decimal and also lends it self to a shorthand of binary representations of numbers. Unlike decimal where you have the numerals 0-9 in hex you have 0-F. So unlike in decimal where ten is represented by two numerals (1 and 0) in hex it has a single numeral A to represent it. once you have counted up to F you "roll over" to the next column just like in decimal, so 0x10 (10 hex) is 16 in decimal.
How does this help?
Well the largest number you can represent with a single byte is 255 or 11111111 in binary, but in hex its just FF which is much easier to write/type than 11111111 and uses less characters (so less memory) than 255 in decimal does, when you are dealing with 8 bits the compactness isnt of much use, but consider 32 bit numbers where the largest number is
4294967295 in decimal, 11111111111111111111111111111111 in binary and FFFFFFFF in hex.
In .net the 0x prefix you see infront of a number means that its hex.
It dont work on my netduino.
I translated the code to VB and changed the IC-Address to &H70
Dim pcf8574_0 As New I2CDevice.Configuration(&H70, 400)
i use a PCF8574AP
VB dont show any errors :S
mfg
gfc
How are you people choosing addresses for this device?, one place it seems that you solder the adresspins to high/low, but still all of you are using quite different addresses, so how do you know if you are using the correct one? (I'm really noob at this i2c stuff, that's why I'm asking)
ah, 7.1 in the datasheet, so if a0-a2 is low, your adress is 70hex, IF you have the pcf8574A, but if you have the pcf8574, then it would be 40hex in the same condition.
So, how do one come up with 38hex, and 20-21hex as above, and the referenced article?, when 70hex and 40hex is the absolute lowest adress you can have on those two devices?
If, I understood this correctly that is... Or, on the 8574, is the adressing only 7 bits?
From figure 10 here http://www.nxp.com/d...eet/PCF8574.pdf it looks like its only 7 bit for 8574, and 8 bits on 8574A, but figure 11&12, it seems like the 8574 do have 8bit adress, so 40hex is for write, and 41hex is for read.
Ok, after reading about the i2cdevice, it seems like it takes 7bit adresses, it's masking away the r/w bit, so I guess it's shifted down one bit. That means you should try 38hex instead if you put a0-a2 low and you have the A chip.
If you have the non-A chip,it would mean 20hex as adress, and then I understand the above example, and the linked example..
Ok, after reading about the i2cdevice, it seems like it takes 7bit adresses, it's masking away the r/w bit, so I guess it's shifted down one bit. That means you should try 38hex instead if you put a0-a2 low and you have the A chip.
If you have the non-A chip,it would mean 20hex as adress, and then I understand the above example, and the linked example..
That's right. The Wire library used in Arduino does exactly that too. On a couple of boards I built where I had I2C slaves that supported A0..An pins, I put either jumpers or a DIL switch to allow me to set the address, but where you will only have a single device, hardwiring is usually easier. Some devices, like the RTC (DS1307?) don't support it anyway, although I'm not sure why you'd want more than RTC