I2C Interfacing

8/12/09

I have a need to get I2C interfacing working. For my first attempt at I2C interfacing, I'm going to attempt to interface between two microcontrollers.

In the "final" application I'm shooting towards, I'm going to have an 18f4610 MCU interfacing with another I2C device that will be acting as a master. Does my MCU have to act as a slave? From the AN734 document from Microchip, they say that there can be multiple masters, or my MCU can act as a slave. They say that the master I2C device generates a clock signal for the slave devices. All data transfers are initiated by the master.

It seems I will have four wires connecting the SPI master to SPI slave: SDA (data), SCL (clock), and +5V and GND. However, if I share +5V and GND across the boards, it seems I can get away with just two wires (SDA, SCL).

The AN734 document gives an example in assembly code, for PIC16's. I'd rather not wrangle with assembly code and changes needed for PIC18's, so I'm going to see if the example here can help.

My 18f4610 will be the slave, and an 18f4550 will be the master. The 18f4550 is going to be the "stand in" for the target I2C device I'm using in my second I2C application.

I'm first getting "skeleton" MPLAB projects ready for the slave and for the master. I've created a (fresh) full set of configuration settings for the 18f4550 (master). I'll see if I can get an LED to turn on on both of the skeleton projects.

OK. So, I've got a blank C language project working with the master (18f4550) that turns on the LED. And I've got a blank C language project working with the slave (18f4610 that turns on the LED. For hardware boards, I'm using the master CUI/perf board from here. The slave board is the CUI (no USB interface this time)/perf board with SD card from here.

Next, I need to (a) add wiring to these boards for SDA/SCL interfacing, and (b) add some basic I2C master and slave program code.

On the master (18f4550):

SCL: pin 34
SDA: pin 33

On the slave (18f4610):

SCL: pin 18
SDA: pin 23

On the master, I'm going to use a 2 pin AMP MTA connector. On the slave I'm going to use a 6 pin AMP MTA connector. For this initial test, I'll only use 2 of the pins.

8/20/09

Here's the connection scheme I'm going to use with the 2 pin AMP MTA connector:

AMP MTA pin Master (18f4550); pin Slave (18f4610 -- board with SD card); pin
1 SCL: pin 34 (also RB1) SCL: pin 18
2 SDA: pin 33 (also RB0) SDA: pin 23

I'm working on the code for the master, to get some basic I2C communication working. I'm following the example here. Apparently, the SSPADD register of the 18f4550 has to be initialized based on the clock speed of the chip and the data rate speed I would like. TABLE 19-3: I2C™ CLOCK RATE W/BRG of the 18f4550 manual gives values for the initialization of the SSPADD register. Section 19.4.7 “Baud Rate” of the 18f4550 manual has more detail.

The internal clock rate of the MCU is 48 MHz.The highest clock rate listed in Table 19-3 is 10 MHz.

8/21/09

The C18 I2C library is lacking in usage documentation. I'm reading the 18f4550 MCU datasheet on I2C operation to try to glean some information. It says in section 19.4.2, "To ensure proper operation of the module, pull-up resistors must be provided externally to the SCL and SDA pins".

On my 18f4550 board, i.e., the master, I'm going to put 1K resistors between the SDA and +5V. I'll do the same thing with the SCL. This is how pull up resistors were used in the tutorial I'm following.

Also: In slave mode. the SCL and SDA pins must be configured as inputs. The MSSP module will override the input state with the output data when required.

OK. I just ran my first test. It attempts to write the I2C address to the slave device, and read the I2C address on the slave device. I'm still not fully sure if the address byte will be received at the slave device as a separate byte, or will just be dealt with on the slave device by the I2C module.

In AN734, they say that the value of slave addresses are always even on writes from master (lower order bit of address indicates read or write from master, and 0 in lower order bit indicates write from master to slave), so I'll make that change in my code. I'm also going to go ahead and use the SLEW_ON parameter in OpenI2C on both master & slave because it seems related to high clock speed, and we have a relatively high clock speed. Also in AN734, they say that the address byte must be read by the slave (the only sensible intepretation of this is in the slave) even though it will be discarded.

My second test also failed. On the slave, I'm not getting by the DataRdyI2C() library call. I.e., DataRdyI2C() is not returning true, and I'm not getting the LED turned on in the slave, which happens after DataRdyI2C() returns true.

OK. So, I had a problem with my cable connecting the master and the slave. I've just fixed that. Now, when I power up the master & slave sometimes the LED on the slave quickly flashes on, and then turns off. I'm not seeing how the slave LED could turn off.

When I comment out the code that turns on the LED in the slave, the LED no longer turns on & off. So, my only reasonable conclusion here is that the slave is receiving the I2C data, turning on the LED, but for some reason the LED is then again turning off.

Now, I put a loop in the slave code that continuously sets the LED to "1", and the slave LED now stays on. Now, I've changed it back so that there's only a single assignment that changes the LED to "1" before the infinite loop at the end of the slave. Hmmm. The LED stays on! Why? I'm going to take all code setting the LED to 1 out of the slave. Thankfully, the LED no longer turns on. I'm going to archive this code, with LED set to 1 in the slave when it receives I2C data (i.e., presumably the address). Here's the current master and slave. Here's some pictures of the set up (ignore the dates on the images, I'm using a different camera and didn't set the date):

Next: To only turn the LED on if the correct address of the slave is being received. Wow! That's working. I'm going to try a double-check, and send a bad address from the master to double-check that the LED on the slave should then NOT turn on. GREAT! I'm sending address=4 on the master and expecting address=2 on the slave, and the slave LED does NOT turn on, as I wanted!!!!

Hmmm. I'm now back to a previous condition: The LED on the slave turns on only briefly. I'm wondering if this is either a clock or timing (e.g., race condition) issue. For example, how do we know if the slave finishes its initalizations in time to be ready for the master. I'm going to try powering the master on after the slave this time. My reasoning is that the slave should be ready, waiting for the master before the master tries to initialize. That did it!!! The LED on the slave lights correctly! So, how do we do this systematically? How do I have the slave start first? Well. For these tests, I can just continue as I just did-- manually power the master on second. As an alternate, I could connect another pin of the slave to a pin on the master, and wait for that pin of the slave to go high before starting up the I2C on the master.

I think I should use this second approach. The backstory to my I2C work is to develop a data logger for the Tasman vario on my glider. Malcom Crampton at Tasman has told me that the Tasman V1000 (with firmware/processor level higher than 3.1) has the following data port pins:

The V1000 data port has pin 1 on the left looking at the back:

pin 1 +5V (20mA max)
pin 2 SCL
pin 3 EXT (a low level is answered by a STOP and I2C idle)
pin 4 SDA
pin 5 0V
pin 6 gnd

Also from Malcom, "The Vario uses EXT as a request from an external [I2C slave] device.

Hold EXT low then wait for a I2C stop. Then you may request data from the Vario [which is I2C master]."

So, if I connected one more pin from my slave to the master, and its state before powering up the slave was logic high (+5V), then I could use the slave to change that pin to logic low (0V).

I have now expanded my connection wires between the master & slave to 3 wires. It is now:

AMP MTA pin Master (18f4550); pin Slave (18f4610 -- board with SD card); pin
1 SCL: pin 34 (also RB1) SCL: pin 18
2 SDA: pin 33 (also RB0) SDA: pin 23
3 "EXT": pin 38 (RB5) pin 38 (RB5)

On the master, pin 3 of the AMP MTA header is also connected to a 4.7K "pullup" resistor. My idea here is that I'm trying to make the default state of "EXT" logic 1 (+5V).

Now, to run a test to see if I can detect when the slave is ready. I won't use the I2C communication. I just want to see if I can detect when the EXT line is dropped to low logic by the slave. Hmmm. By setting RB5 to 0 on the slave, I'm not changing EXT on the master. Hmmm. But, how could it? If the incoming connection from the slave isn't connected, what voltage level would it have? 0V?

OK. So, I've got this working now. I've added a transistor into the circuit of the slave, connected into the output of pin RB5 from the slave. This appears to be necessary to cause the change in pin RB5 on the slave (high logic in this case) to cause the EXT line of the master to go low. This is what the schematic looks like:

Here are some pictures:

Note that I used pin RB5 for EXT on both the slave and master. To use RB5 as a general purpose I/O pin, you have disable the PGM function by turning LVP off in the configuration settings. This caused some problems! Ahem! The transistor part of this circuit was not necessary!!!! It was just the PGM issue that was causing my problem!!

The master and slave code examples are given in those links. Note that this is just showing that the slave can drop the EXT line of the master to low.

Next time: Combine the usage of EXT with the I2C so that when the EXT line drops low on the master, the slave reads data at an address similar to that in the Tasman vario. From Malcom Crampton:

Address of slave is 04, and four bytes are written by the master. The first two bytes are CV (Current Value), and the second two are AV (Average Value).

CV and AV are each 2's compliment two-byte integer values, with apparently LSB first.

9/3/09

OK. I'm back on the job. (A massive break to tile my bathroom!). First, I want to get that transistor off of the board I'm using as the slave and try my code again, with the sense of the "EXT" line inverted. Pin RB5 of the slave is now connected directly to the "EXT" pin of the AMP MTA (pin 3), and the transistor and associated resistor have been removed.

In my program on the slave, I'll set the EXT line to logic-low. Logic-low from the slave is the signal from the slave for the "Tasman" (simulated by my board right now) to write data to the slave. On the slave, I will light the LED if address 4 is obtained. On the master, I light the LED if the address was sent to the slave. OK! Both master and slave LED's are lighting! Here's my current code for master and slave.

Moving on. I want to send a byte of data from master to slave. From the tutorial, you just write another byte at the master end, and (I'm assuming) receive it at the slave end. I'm going to modify the master and slave accordingly. I'll send data byte value 0xFE from master to slave. Great! That turned both LED's on (master & slave). One further test-- I'll expect a different byte at the slave (0xFd) and see if that still lights both LED's. Hmmm. The slave LED is still turning on. What's up with that? It seems I had an error in my previous version. I was just generally turning on the slave LED.

Good. When I expect 0xFD on the slave, I don't get the LED on the slave turned on. When I expect 0xFE, I am getting the slave LED turned on. Excellent! Here's my current code for master and slave that (a) uses address 04 for slave, and (b) receives a byte of data (0xFE) at the slave and only turns on the LED on the slave when all goes well.

Next: I want to send four bytes of data to the slave to simulate the two 2-byte integers sent from the Tasman. My first question is: Is an "int" in C with my master (18f4550) a 2 byte value? To some extent this really doesn't matter. It matters more on the slave. However, I want to write these values to my SD card a little later, so let's make sure we're getting good data sent from the master.

I'll run a little test on my master, and on the slave to see if the C18 compiler "int" is 2 bytes at both ends. OK. We're good to go. "int"s are two bytes.

Ok. Now, I'm running a test to send 2 int's from master to slave. My first test indicates the data is being transferred correctly. Now, I'm going to try to write the data to the SD card. Wish me luck!!

I've plugged my I2C code into my SD card example. I've turned LVP OFF in the configuration settings, to allow use of RB5 ("EXT"). I going to reformat the SD card I'm using, on Windows Vista: a 1 GB card, formatted with 512 byte blocks in FAT32. The first test didn't work. The LED didn't light up on the slave.

I'm going to try just getting the I2C communication going first in this example. That's the first part of the code. I'm turning on the LED if the I2C communication succeeds. OK. That's working again. It's also getting by the CloseI2C() call. It's also getting by the MDD_MediaDetect() call. It is not, however, getting by the FSInit() call. What happens if I remove the I2C code? Does that fix the problem? Yes. Lovely. I can get the I2C interface to work and the SD card to work, but not together. I've now tried setting TRISC5 and TRISC3 to 0 as part of the SD card initialization, but this doesn't help. It would seem that some state (of the MCU, I assume) has changed, and is disallowing proper initialization of the SD card.

OK. Here's something interesting. If I just do the OpenI2C and then CloseI2C calls, followed by the SD card interfacing (i.e., don't do any of the data receiving using I2C), then the FSInit() call works. Why is this? Am I not closing up or releasing the I2C interface properly?

OK. I may have solved this!!!! I put in an CloseI2C() in the master. That had the slave make it by the FSInit() call!!

I'm having some intermittent results. I just plugged the 1 GB SD card into Windows Vista. It indicated I needed to reformat the card. Possibly my testing has corrupted the file system? And again. I ran a few tests, and when I plugged the SD card back into Windows Vista, it said I needed to reformat the card. Lovely. I reformatted it again, and when I immediately plug it back into Windows, it's OK. So, it's not a completely bad SD card.

OK, so I took out the code in the slave that's creating the file on the SD card, and am just doing the FSInit(). We're getting past the FSInit(), and that is not corrupting the file system.

In my next test, I'm going to open the file, and close it, but not do any of the time stuff, and I'm not going to write to the file. That works on the first test! But, it doesn't work on the 2nd test. After the second test, when I put the SD card into Windows Vista, it's still OK. It has out file "FILE1.TXT" with zero bytes (as expected). On the third test, the LED also doesn't light. Is the card corrupted? Yes. The third time was the charm. It's corrupted.

I'm going to try a mini-SD card in an adapter. It's formatted with FAT (16 I think) and 512 byte blocks. That doesn't work. But, I' not sure if the min-SD card is an issue or not.

In my next test, I'm going to (a) reformat the card, and (b) write to the fresh card (not only open the file but try to write the data from the I2C connection). No go. It would appear part of the problem is in writing data to the card.

9/4/09

I just put the SD card into Windows Vista, and the file name is "FILD1.TXT". Yes, there's a "D" in there. What's up with that? How would the file name get corrupted? I've deleted that file, and in my next test I'm taking out two lines of code that I had put in my SD card setup-- to set TRISC3 and TRISC5 to 0. I had been hacking around and put those in, but I think the real thing that made progress yesterday, and enabled me to work with the SD card, was closing the I2C connection on the master. I've also put the date/time setting code back in the file system code. Well, that didn't work.

And interesting, this time-- there is no file on the SD card when I check it after!

Back to basics. Do we get by FSInit()? Yes! And that time, there is a file present: "FILE1.TXT" (0 bytes). That's not consistent. The only thing I changed in the code was where the LED got turned on.

This time: Do we get by the first call to FSfwrite? I have removed the file on the SD card for this test again. OK, so the light turns on. We get by the first call to FSfwrite. The file name is odd again. This time it appears to be a blank where the "E" should be. The file is 1 KB! The file has 4 bytes!!! Ok, so this is intermittent, but we seem to have our data! I plugged the SD card into my Mac system, and it's having fits. From the command line, I get the following:

Crspybits:NO NAME chris$ ls
FIL.TXT ÿÀ␀␀€␀␀␀.␀␀␀
Crspybits:NO NAME chris$ ls -l
ls: FIL.TXT: No such file or directory
ls: ÿÀ␀␀€␀␀␀.␀␀␀: File name too long
Crspybits:NO NAME chris$ cp F* ~/Desktop/first.txt
cp: FIL.TXT: No such file or directory

Back on the Windows system, I do see another file entry, and it's given as having a large file size (4,194,240 KB), and the file name is an odd symbol. I'm going to reformat the SD card and try the test again. I've managed to copy the .TXT file off of the SD card. On my mac, the file name is "FIL 1.TXT", with a blank where there "E" should be.

I wrote a program on my Mac to read the four bytes from the file. Here is the output of the program:

Crspybits:Desktop chris$ ./a.out
byte= 34
byte= 12
byte= 68
byte= 24

Ta Da! Well, things are far from perfect, this is the correct data! 2-byte int's are being stored in MSB-first order on my MCU. Not only is the data being sent from master (simulated Tasman) to slave (data logger), it's being written correctly too. Now, to figure out why the sporadic problems are happening.

I'm going to run the same test (same code on MCU's), but with a reformatted SD card. LED lit up. Let's check the SD card on Vista. It says the SD card has no files. Same deal on my Mac.

I'm going to change the file mode to "w" to see if this does anything. I'm also going to remove the power from the master while I'm programming the slave MCU. I was a little concerned that the test was starting immediately after programming the slave, and that I was actually running the test twice. Test result: LED does not light up. File system on SD card: OK. That's new. Vista comes up and says "Do you want to scan and fix Removable Disk (E:)? There might be a problem with some of the files on this device or disc..." After this process, there is a file on the SD card-- "FILE1.TXT", that Windows says has 512 bytes. My program from above tells me the first 4 bytes of this file are all 0's.

This problem is intermittent. What if it's a timing issue? What if some (more) delay is needed between closing the I2C connection and opening the SD card connection? I'm going to insert a delay of 1s after the call to CloseI2C() and before starting any SD card interfacing, with a call to Delay10KTCYx(20).

It should be noted that I'm having ongoing difficulty reformatting my SD card. Sometimes Windows Vista fails in its reformatting.

That test failed: No LED lit up. On Vista, the file systems shows no immediate signs of corruption (Vista prompts to Open folder to view files). Vista shows no files present. That's confirmed on my Mac-- no files present.

Do I get these same problems with the SD card interface, but no I2C connection preceding it? I'm going to comment out that code again, and see what happens in multiple tests of writing to the SD card.

Test 1: No LED lights on slave. A file named "FILE1.TXT" is present on the SD card. Vista says: 0 bytes size. That's confirmed on my Mac. When I put the SD card back into Vista, it comes up the the "scan and fix" prompt again.

Test 2: I've reformatted the SD card again (FAT32, and 512 byte blocks). Well I'm trying. The first attempt to reformat failed. The second reformat succeeded. But, when testing on the board, no LED lights up. No file is present on the SD card.

So, in conclusion, these problems are not connected, to the I2C interfacing.

I'm going to go back to the last working SD card code, and try that. One difference between my present code (with the I2C) and the last working SD card code is that the data being written is in a global variable in the working code, as opposed to a stack variable.

Things are not looking good with my test of the previous working SD card code. I've started the test with a freshly formatted SD card. The LED is not flashing, as it should be. So, it would STRONGLY appear that the problem I'm having is in the SD card interfacing, and it starts to seem that it's with the specific SD card. Unless something has changed in my other hardware. After my test, there is no file present on the SD card when I connect it to Windows. It seems I need get a new SD card. One that's as small as possible. 16MB would be just fine, thank you. I could format it with FAT16 that way, I believe.

Next test: I've obtained a 32MB SD card. I've now reformatted it as FAT16, with 512 byte blocks. That test produced no LED lighting, with the old SD card code. Tried it a second time. That test failed too. No LED lights up. Hmmm. This time, the code is not getting by the FSInit() call. Hmmm. I wonder if FAT16 has to be specifically configured? From what I'm reading in the code, the library dynamically determines if the file system is FAT12, FAT16, or FAT32. Configuring FAT32 like I have right now doesn't exclude FAT12 or FAT16.

9/8/09

I just tried a 256 MB SD card, formatted as FAT32, with 512 byte blocks. Same result. No LED flashes.

9/10/09

Something appears flakey with the power busses/connectors to my board. I changed the firmware to just turning on an LED. With my homebrew power supply, I couldn't get the LED to light. And with Scott's power supply, I can't keep the LED lit. Jostling the board causes the LED to go out. Now, I'm getting a complete failure to light up the LED's. Plus, when I measure voltage across the + and GND of the board, with NO SUPPLY connected, I measure .5V or .4V. It was .5V right after I removed the supply, then .4V after waiting 20 minutes. WEIRD.

I just took the 18f4610 MCU out of this circuit and put it on a basic breadboard supplying power and pin 20 into an LED through a resistor. ODD effects. When I move the breadboard, I get intermittent lighting of the LED. It could be the power wires, but when I move the power wires, but hold the breadboard stable, I can't get the LED to turn off. It is as if the MCU itself is being motion sensitive. I just put the MCU on a different breadboard, with the same components, and I get the same basic effect, though it seemed that the motion sensitivity seemd to start occuring after 30s or so with the MCU powered up.

Next: I need to try a different 18f4610 MCU in the circuit.

I just swapped in a different 18f4610, and it runs my SD card-only example just fine thank you.

I'm now trying my I2C master/slave example with SD card writing. It doesn't make it through to the end of the code. No file was written to the SD card. It does make it through to the end of the I2C communication-- i.e., the slave is getting the data from the master. Hmmm. There is a file "FILE1.TXT" this time, however, on the SD card. It contains 4 bytes! And the data is as expected from the I2C communication! I'm now going to light the LED when it gets by both writes to the SD card. This time, no LED lights up. And there is no file on the SD card. A second trial with the same code also shows no LED lighting. And no file on the SD card. Hmmm. I'm going to put the LED lighting back, just before the SD card code. No go. No file on SD card.

9/15/09

Things are getting curiouser and curiouser. Using my 2nd 18f4610, as in the last bit of testing, I just flashed the MCU with my SD card-only example again as in my testing last day. That example no longer works. Hmmm. The LED does not flash. No file gets written to the SD card. I'm going to try reformatting the SD card (it's my 32 MB card). And I re-flashed the MCU without the SD card in place in the SD card holder. Now, I'll apply external 5V power without the PicKit2 attached. No flashing LED. And no file results on the SD card.

The variable seems to be the MCU. Somehow the state of the MCU is changing as a result of my I2C master/slave example. What could be changing? How can I reset the MCU somehow to the starting state? Oddly, when I use my voltmeter to measure voltage across the +/- rails of my SD card board, I get about .45 volts. It's not connected to power, and hasn't been for a while. Popping the SD card out gives the same results. Popping the MCU out gives the same results. ODD!!! The SD card has a voltage regulator. Plus there are a couple of capacitors on the board. Could these be retaining a voltage potential for such a relatively long interval? I tried my LED/resistor circuit across the +/- rails of the SD card board, and the 0.45V is still there. I shorted the + to - rail, and the potential went away. Perhaps the wrong thing to do? I don't know.

I have the MCU back in now. I'll reflash it, and see what happens. Still no go. No LED flashing. And we're back to .6V across the +/- rails of the SD card board with NO power attached.

OK. Back to basics. I've beheaded my SD card example by just turning on the LED at the very start of it, and going into an infinite loop after that. The LED turns on, but only dimly!! What's up with that? When I touch the ground lead of the board with my volt-meter ground probe, the LED turns off!!! Hmmm. When I use the configuration settings to power the board from the PicKit2, the LED comes on brightly.

OK. Something new. I'm using the configuration settings to power the board from the PicKit2. And I was using my full SD card example which, in a loop, accesses the SD card. And that works again. And when I use the MPLAB IDE to set Vdd off and then set Vdd on, the example works again. The SD card has the expected data in "FILE1.TXT" too.

OK. I'm going to go back to my SD card/I2C example, with the I2C code commented out and see if I can get the SD card writing to work on multiple test runs. I wonder if my problem has to do with not powering the tests down appropriately or not supplying power appropriately. I'm using MCLRE = OFF in the configuration settings in this test as I was just doing with my SD card-only example.

It works! Here was the test sequence. With the SD card out of the board, I programmed the MCU. Then, with the PicKit2 still attached, I inserted the SD card. The SD card indicated powered state, and momentarily, the LED on the MDU (RD1) came on indicating (in this case) that the SD card test had worked. Now, I power down with MPLAB, and check the SD card. The file is there and it has four bytes. GREAT!!! Let's try to replicate this a couple of times!

Erase file from SD card. Reconnect PicKit2, and set it as programmer. I'll turn Vdd off with MPLAB this time. Vdd on with MPLAB and the SD card board LED (RD1) comes on again!!! Vdd off with MPLAB, and does the SD card have the expected four bytes? YES!!!

And a third time, it works!!! And the SD card has four bytes in the file!!! Yeah!!! Let's celebrate!!!

I'm going to put the I2C back into the slave and see if I can get the boards talking to each other. With no SD card in the slave, and without the master attached, I'm going to flash it with the code that includes the I2C communication with the master. I then have turned Vdd off using MPLAB. My procedure will then be as follows:

a) connect master power to slave power bus.

b) connect master to slave via my three wire MTA cable.

c) insert SD card.

d) power up boards using MPLAB.

WOWOWOWOW! The LED comes on on the slave!!! I then did:

e) use MPAB to power down boards.

The resulting file has four bytes (I'll look at the specific data in a bit).

Let's try that test a few more times. This will be my procedure:

a) connect PicKit2 to Vista system (it's connected to slave), select PicKit 2 with MPLAB, and turn Vdd off.

b) connect master power to slave power bus.

c) connect master to slave via my three wire MTA cable.

d) insert SD card.

e) power up boards using MPLAB.

f) use MPAB to power down boards.

Test 2: YES!! LED comes on on slave!!! (Interestingly, the file that results is named "FILE3.TXT").

Let's try one more time. This will be my procedure. I'll leave bus power connectors on and MTA cable on this time:

a) SD card is out of slave; Vdd was still off when it was removed.

b) connect PicKit2 to Vista system (it's connected to slave), select PicKit 2 with MPLAB, and turn Vdd off.

c) insert SD card.

d) power up boards using MPLAB.

e) use MPLAB to power down boards.

Test 3: YES!!!!!!!! LED comes on on slave!!! (File name is again "FILE1.TXT").

Here's my current code for master and slave. And here are three data files that resulted: FILE1, FILE2, FILE3 from the test. They are identical, which is good! The bytes are as expected from the I2C communication:

Crspybits:NewTest chris$ ./a.out
byte= 34
byte= 12
byte= 68
byte= 24

It would seem that my problem was power/procedural related. YIPPEEEEE!!!!

What next? Right now, my master is closing the I2C communication. I don't see any reason to think that the Tasman vario does this. Also, it would be good to try several iterations of receiving data from my master. This should involve having slave set the the EXT line high again. In my master I'm just going to have an infinite loop of waiting for the EXT to go low, then sending the CV and AV data to the slave. I've changed the slave so that it iterates successively setting EXT low then high, reading I2C data, and writing it to the SD card (appending) on each iteration for 5 iterations. I'm following my procedure as above:

a) SD card is out of slave.

b) connect PicKit2 to Vista system (it's connected to slave), select PicKit 2 with MPLAB, and turn Vdd off.

c) insert SD card.

d) power up boards using MPLAB.

e) use MPLAB to power down boards.

The test is not working. No LED's are flashing as expected. I'm going to try closing I2C on the master on each iteration.

Same deal on 2nd test. The master LED flashed a bit at the start, but then turned off and stayed off. There is no file on the SD card.

It's odd to me that I don't get one iteration of writing to the SD card. OK. I had an error. The EXT pin of the master was not getting setup as an input.

Still no LED's flashing. No file written to SD card. (That time, I powered the setup from the master, but wires were connecting busses to each other).

9/22/09

I just replicated my version 6 master/slave test. All is good. Except the file name on the SD card is mangled. It does have four bytes. And I can't transfer the file off the SD card on Windows Vista. The same thing occurs on Mac OS. I expect I could write a program that accesses the directory at the system level and copies off the file, but I'm not sure it's worth it. I'm going to reformat the SD card.

That second test didn't work. No LED is on on the slave. There is no file on the SD card.

The third test worked. The LED came on on the slave. And the data in the file is right (the file name is FILE1.TXT).

I'm going to change my strategy. I'm not going to try multiple cycles of opening the SD card file, but rather going to (a) send multiple data items from the master to slave, then (b) write those multiple data items to the file. Since the 18f4610 is limited to having I/O pins shared across the I2C and SPI this might be the better initial testing strategy.

I modified the master and slave in this way, and in my first test, the slave LED did not light up. And there is no file on the SD card.

Same deal with the second test.

Presently, on my slave, initializations occur, EXT is set to 0, and it immediately starts waiting on the I2C address byte from the master.

On the master, initializations occur and the master waits until EXT goes low.

There is something wrong on the master. The LED lights up when the slave is not connected. This indicates that all of the commnication has occured. BUT, if we have done things properly, the EXT should be tied high on the master and should not go low until we connect the slave.

9/24/09

I currently have LVP = OFF in the config.h file for my master (18f4550). This seems odd because I am using ICSP. I have LVP = OFF because this is what gives general purpose I/O pin access to RB5. I made an odd choice of pin for the EXT pin.

When I just measured the voltage on RB5, it was approximately 0V, which is odd. I thought I had a "pull up resistor" on RB5. I do have a pullup resistor on RB5!

I'm guessing that some conflict is going on with RB5. I'm going to try switching EXT to another pin on the 18f4550. I'm going to try pin RB4.

WHOA! I just noticed that in my master code change to put in a loop, to have multiple data items sent to the slave, that I changed the sense of I/O on RB5. It was setup as an output pin, not an input pin. I've now switched it back to being an input pin.

YES! After reprogramming the master, when I switch Vdd off and then Vdd on, the LED does not turn on-- indicating that it is waiting for EXT to go low! Great! There is still something odd here, however. I probably should not be using RB5 as EXT. My configuration bits, in theory, should be disabling ICSP. Perhaps because I have a pullup resistor on RB5, ICSP is working?

WE JUST GOT A SUCESSFUL TEST! The master LED went on, and then after several seconds, the slave LED went on! There is 20 bytes in a file named FILE1.TXT on the SD card. Since the master iterated for 5 times, sending four bytes each iteration, this is what we expected! Now to see if the bytes are having the right values. Here are the data values:

Crspybits:Desktop chris$ ./a.out
Iteration 1
byte= 34
byte= 12
byte= 68
byte= 24
Iteration 2
byte= 34
byte= 12
byte= 68
byte= 24
Iteration 3
byte= 34
byte= 12
byte= 68
byte= 24
Iteration 4
byte= 34
byte= 12
byte= 68
byte= 24
Iteration 5
byte= 34
byte= 12
byte= 68
byte= 24

Good deal!!

Let's try a second and third test.

Second test results: master LED on, slave LED on! Bytes are good! Success!

Third test results: master LED on, slave LED on! Bytes are good! Success!

YIPPEEEEE! Here is the current master and slave code, and the readfile2.c file for reading the data files, and an example data file.

What next? Since the Tasman vario will likely not close the I2C connection, I need to see if I can have successful operation without closing the I2C connection on the master, and just have it infinitely loop, sending data to the slave each time the slave requests data using EXT.

9/26/09

Here is my current master and current slave (just the C code for the main).

To make my code more similar to what Malcom (at Tasman) says about the Tasman, I've inserted a StopI2C and an Idle before the StartI2C in the master. This seems to have killed my I2C communication to my slave. Lovely. I just tried that a second time, and again the slave isn't writing data to the SD card. Just to make sure that's what killed things, I've taken out the Stop/Idle pair from the master. Ooops. That would have been too easy. Something else is broken too. It wasn't (just) the Stop/Idle.

OK. We're back in the game. I just took a break for an hour or so, and came back to it and all is working. I had previously left the SD card in when I programmed one of the boards, which I usually don't do. I think this may have somehow put one or both of the MCU's into a state. (When I measured voltage across + and - of the slave, with no power applied, it was about .35V.).

I am now getting the system working even with the Stop/Idle in the master.

I've now modified my master so it doesn't close the I2C connection, but just infinitely loops. OK. That test failed. It appears that on the slave, I can't open the SPI connection with the SD card while the master has not yet closed the I2C connection. This occurs even when the Stop/Idle starts the EXT low condition on the master.

It would appear that I've reached a dead end with my current MCU, and that I need separate SPI and I2C pins.

9/29/09

I'm on the market for other MCU's. The PIC18f26j11 has: 64K program RAM, 2 I2C/SPI modules, and is a 28 pin, 3V part. I can do a build with this MCU with my program and the MPLAB IDE.

One next question is: Do I need a separate voltage regulator for this new board? The SD card voltage regulator can supply up to 250 mA @ 3.3V. The electrical specs say that the max current into Vdd of the MCU is 250 mA. This seems too near the max amperage output of the SD card, and I'd like to get the MCU operating (for testing purposes) independently of the SD card, so I'm going to go with a voltage regulator.

10/8/09

I'm working on interfacing the 18f26J11 MCU to the Tasman simulation (18f4550).

On the 18f4550, pin RB5 is being used as "EXT". The minimum input high voltage (VIH) on I/O pins that don't have a TTL buffer or Schmitt trigger buffer is 2V. However, it turns out that RB5 has a TTL buffer, which indicates that

VIH = .25VDD + .8V = .25*5V + .8V = 1.25V +.8V=2.05V.

Since, on RA3 (planned EXT output on the 18f26J11), the VOH is ≥ 2.4V, we should be good.

It would appear we need a pull up resistor on this line (EXT) also (see section 9.1.3 on 18f26J11 data sheet, p. 126). But, EXT on the 18f4550 already has a pull up resistor, so we're good.

Now, moving on to the I2C clock (RC5) on the 18f26J11, this will be a 5V output from the 18f4550. How do we deal with the lower voltage of the 18f26J11? Do we just use a voltage divider like we were planning on interfacing to the 3V MEMS pressure sensors?

From Figure 9-2 in the 18f4550 data sheet, it would appear that if we add pull up resistors on the 18f4550 for the two I2C lines connecting to the 18f26J11, we should be good to go. I have a couple of concerns with this, however. First, the information in the 18f26J11 data sheet doesn't talk about the 5V device sending information to the 3V device. Second, it appears to constrain *how* the 3V device sends information to the 5V device. Third, I'm not sure if the Tasman itself is a 3V or 5V device. Fourth, this makes the assumption the Tasman would have pull up resistors on the I2C lines.

Also, I'm assuming that the EXT line out of the Tasman has a pull up resistor on the Tasman. This would seem to be the case since you have to pull the EXT line low to tell the Tasman you are ready for data.

10/15/09

From MalC at Tasman: "EXT has 10k, SDA/SCL have 6k8 pullup to 5v". So, we seem to be good. If I use a 6.8K pullup resistor on the SDA/SCL that should be reasonably approximating the Tasman.

I can now start wiring up my next version of the data logger board. Here is the Eagle schematic.

First, I'm going to connect the voltage regulator, power for the MCU, and the ICSP.

I've got this version working! Here is the code: SDcardI2CSlave18f26j11.zip. I have a LED turning on! The SD card is not yet wired in and the I2C is not yet wired in. My next step will be to wire in the SD card. I have some trepidation about that device because I had to do some surgery to it. I knocked one of the surface mounted parts off it, and had to resolder it on. I hope it is still working. I'm not getting this board to work with power via the PicKit2, but it is working when I power it from my main bus through the voltage regulator, which is OK.

10/22/09

Actually, my next step in this project is to get the SD card and other pin configuration done in the program code, and then to wire in the SD card. The pin configuration programming has some new aspects because of the reconfigurable pins on the 18f26j11 MCU.

For the I2C interface, I'm going to use fixed function pins:

SCL1: Pin 14

SDA1: Pin 15

For the SPI interface, I'm going to use remappable pins:

SDO2: RP18-- output from MCU to SD card

SCK2: RP17-- output to SD card

SDI2: RP16-- input to the MCU

I'm making changes to the file HardwareProfile.h. As far as I can tell, the 18f26j11 has a 4MHz clock rate, by default (see p. 38 of the datasheet).

What are the SPI control, status, and buffer registers for SDO2, SCK2, and SDI2? (i.e., the 2nd SPI module). I'm believing they are: SSP2CON1, SSP2STAT, and SSP2BUF. OK. I seem to have those setup. I need to make sure that I have the remappable pin configuration set up appropriately.

From p. 148 of the datasheet: "The assignment of a peripheral to a particular pin does not automatically perform any other configuration of the pin's I/O circuitry... To be safe, fixed digital peripherals that share the same pin should be disabled when not in use." So, it would assume I need to disable the default functions of pins 18, 17, and 16, which are RX1/DT1 (pin 18), TX1/CK1 (pin 17), and SDO1 (pin 16).

EUSART function (RX1/DT1;TX1/CK1) needs to be specificially configured, so I think I'm OK there.

OK. So, I've got the SD card wired in. And I've run some tests. I'm getting by the MDD_MediaDetect() call in the SD card library, but I'm not getting past the FSInit() call in the SD card library. Note that MediaDetect() just polls one pin (CD), and so isn't doing any SPI interfacing.

So, where are things going haywire? The possibilities as I see it are:

1) The SD card is fried: From when I knocked that part off and put it back on.

I have now replaced the SD card with a new one. And I'm having the same problem.

10/29/09; I just rewired the new SD card back (using a socket) into the old circuit with the 5V MCU, and things are fine!!! The SD card gets written!! Also, I just put the OLD SD card back into place on the 5V MCU and things are fine!!! The SD card gets written!!

2) I'm not configuring the remappable pins correctly.

By default is the IOLOCK unlocked when the MCU starts? Yes. The IOLOCK bit resets in the unlocked state. I just looked this over again, and it seems OK. However, there's all sorts of statements in the remappable pin section about disabling unused pin selectable peripherals. See p. 148 of the datasheet.

I've now modified my remappable pin configuration to use the style recommended in the datasheet, complete with unlocking IOLOCK and relocking it. No change, however. I'm still not getting by FSInit() in the SD card library.

3) I've got the SD card interface (e.g., SPI) pins wired incorrectly.

I just double checked this and it seems correct.

In the old design, SDO on the MCU goes to DI on the SD card. In the new design, pin 18 is remapped to SDO, and this connects to DI on the SD card.

In the old design, SDI on the MCU goes to DO on the SD card. In the new design, pin 16 is remapped to SDI, and this connects to DO on the SD card.

So, this seems that we've got the SD card interface wired correctly.

4) I've not specified the clock rate for this MCU correctly in HardwareProfile.h.

Looking again at p. 38 of the datasheet, it appears the default rate of INTOSC is 4MHz, and the configuration bits in config.h have selected INTOSC.

5) I've specified some pins incorrectly in HardwareProfile.h.

I've looked these over again, and they seem right. However, I'm not 100% certain. There's a certain amount of guesswork going on here.

LATA0 is specified for CS (Chip Select) output bit, and TRISA0 for its TRIS bit.

RA2 is specified for CD (Card Detect) input bit, and TRISA2 for its TRIS bit.

RA1 is specified for WP (Write Protect) input bit, and TRISA1 for its TRIS bit.

SSP2CON1 is being specified as the main SPI control register (SPICON1 in the defines). What is meant by "main"? I'm taking "main" means first.

SSP2STAT is being specified as SPISTAT in the defines.

SSP2BUF is being specified as SPIBUF in the defines.

SSP2STATbits.BF is being specified as SPISTAT_RBF in the defines.

SSP2CON1bits is being specified as SPICON1bits in the defines.

SSP2STATbits is being specified as SPISTATbits in the defines.

PIR3bits.SSP2IF is being specified as SPI_INTERRUPT_FLAG in the defines.

SSP2CON1bits.SSPEN is being specified as SPIENABLE.

This all looks good.

6) The SDI/SDO orientation of the pins are wrong.

In my design with the 18f4610 MCU, I had pin 24 (SDO) leading to DI on the SD card, and pin 23 (SDI) going to DO on the SD card. In my current design, pin 18 (planned as SDO2) goes to DI on the SD card, and pin 16 (planned as SDI2) goes to DO on the SD card. So, all seems well with this issue.

7) This is the first time I've used this type of SD card interface with a 3V MCU. Could that be an issue?

8) Do I need to program the remappable pins for I/O direction?

I just programmed the SPI I/O pins with direction, and that didn't change the results. Still not getting by FSInit().

9) Possibly, I was having problems with my cheap power supply (i.e., the hacked USB supply) before. Is this a problem?

I just tried another output of the same power supply (6V), and same problem.

I could try my old SD card design with the 5V MCU and see if that works with the cheap power supply. Aha! This is the first sign of solidness I have. I just tested this, and my cheap power supply is NOT working with the old SD card design with the 5V MCU!!! This is good news!!! (Curiously though, even though the LED did not come on, the file FILE1.TXT was created on the SD card and it had 0 bytes). I just tried it a second time, with the new SD card interface (old, 5V, MCU board), and again the LED did not come on!! This time, the file was not created on the SD card!!! So, I have evidence to believe that this is a power supply issue.

OK. I just tried powering my new board with the PicKit2 with an adapter on the front of the PicKit2, so I can hook into the power inputs (which lead to the voltage regulator) of my new board. I tried the test twice, and in neither case does my LED light. The same situation as before. The PicKit2 is what I've been using to power my old design.

10) This is the first time I've tried using the voltage regulator I'm using. Is this causing a problem for the SD card?

The MCU seems to be working OK. I can turn on a LED with the MCU.

11) My voltage regulator is putting out slightly less than 3.3V (about 3.25V) and the spec for the SD card says it needs at least 3.3V input. Could this be causing a problem?

10/29/09; I've emailed the supplier of the SD card about this issue, and shall see what they say.

11/3/09; I just tried using 3.4V (from my PicKit2) into the 3.3V + and - rails of my board (not the voltage regulator power inputs). It successfully drives the LED on the board, but the SD card shows no file written to it-- we don't get by FSInit() in the code.

12) Check the errata datasheet for my MCU to see about potential issues with the remappable pins.

I can't see any relevant issues here.

13) The MCU datasheet talks about disabling other perpipherals when using the remappable pins. I couldn't see anything I needed to do with this on pins 16, 17, and 18, but I could be wrong. If I ask a question on the Microchip forums, ask about this issue too.

11/18/09; I have confirmation from Microchip that the relevant peripherals are disabled initially.

14) I could try using the other 3 SPI pin on the MCU that are not remappable pins. That would take the remappable pin issue out of the equation. (Of course, since the I2C cannot be interfaced using remappable pins, this would mean that if I get the SD card working on the other 3 pins, I'd eventually have to switch back to using the remappable pins for SPI).

10/29/09

I'm running out of ideas. Here's my current code for this project. Next day, I'll post a question to Microchip forums asking if I'm doing something wrong with the remappable pins.

Here is the board schematic as a JPEG image.

Here is the main C program code, without the other files.

11/5/09

No word back from the Microchip forum. I'm trying to make sure the clock rate I have is correct. I've adjusted the clock rate in HardwareProfile.h to 48MHz as a test. That seems to be what the Microchip web site says for the 18f26j11 MCU. Now, when I try this, the LED lights immediately when I power the board on, even with the SD card absent. OK. Now, when I initially program the pin I'm using for the LED as an output, I'm setting that pin's output value to 0. And now, I'm gettng the LED off. Somehow it would seem that the state of the LED pin was becoming high by default.

11/19/09

I have confirmation from Microchip that a clock rate of 4MHz is correct. Putting that into HardwareProfile.h doesn't fix my problem.