NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.
Project Help and Ideas » Access Serial EEPROM using I2C on the Nerdkit
NerdKits » Forums » Project Help and Ideas » Access Serial EEPROM using I2C on the Nerdkit (117 posts)
|
|
March 18, 2011 by Noter |
This is an example of using I2C to access a serial eeprom with the nerdkit. The eeprom used is the 24LC256 with a capacity of 32k bytes. I'm not sure yet of a real project where I will use it but maybe archiving data on a weather station so it can be uploaded from time to time. Or perhaps a min/max thermomitor that saves temp every minute and later can be uploaded for analysis. I'd like to know about your projects that will make use of external eeproms. Anyway, there are 3 components to download -
If you have the earlier versions of TWI.c & TWI.h then replace them with these updated files. Several enhancements have been completed to make use easier. About the program: 24LC256_eeprom.c uses pointers and structures quite a bit. If they are new to you, it's a good time to become familiar with both as they are a two of the most powerful features of the C language. There are many tutorials on the web on pointers and structures and I will be glad to answer questions too. For a start, here are links to my favorite explainations of structures, pointers, typedefs, and cast operators. The program will make much more sense once you know a little about these. Pointers, Structures, Typedef, Cast Operator Source code will be posted next and in leiu of a schematic, here is my nerdkit setup - |
---|---|
March 18, 2011 by Noter |
|
March 18, 2011 by Noter |
|
March 18, 2011 by Noter |
|
March 18, 2011 by Ralphxyz |
Noter, thank you so much XOXOXOXO, oops sorry didn't mean to slobber, but this is really going to help me. I immediately need the EEPROM for my weather station for data storage. I also need to store a look up table for my Humidity sensor. I "might" be able to fit the humidity sensor look up table into the mcu's 512 Byte internal EEPROM but definitely will need the external EEPROM for data storage. When I started looking at using a EEPROM I realized that I have absolutely no idea of how to do memory management using a mcu. Using my computer the memory is managed by the OS but since there is no OS on a mcu the memory management has to be done in code. I will go through your code in depth. I have been studying this How To blog. I think this is one of Rick's references or at least the blog is. I almost can comprehend how the Array is being used but I do not see how a string of data would be addressed or retrieved. So for my weather station I will have these data points: (I've never laid this out before so definitely subject to change)
So if I was doing this on my computer I would have a .CSV file that would look like this:
I will be using ZigBee (which I do not know) to download the entire data drop or just asking for the Max wind speed or probable asking for the "current conditions" (which might come from the sensors directly instead of reading the EEPROM). The window probable could be one hour instead of 15 minutes but we will see. Like I said I haven't laid this out before, but just had it floating around in my head, so this is a good exercise just to see it out of my mind, wrong term I been going out of my mind trying to get Rick's DS3232 I2C (TWI) code working, this is actually starting to make sense. Thanks for the Pointers, Structures, Typedef, Cast Operator links, I am familiar with all of these but as I am not a "programmer" I have rarely ever actually used them. So I will definitely be needing your help, and everybody else's contributions here in/on the Nerdkit's forum. Oh just to get it down I am also looking at "Power Harvesting" from RF to power my Nerdkit. I've got some Boost chips from TI on sample so I'll be playing around with that in another thread. I have so many ideas going that I really need you and Rick and others to post working projects so that I can put them together. I really do not have the ability nor time to work all of these things out from scratch. I am so thankful to/for the Nerdkit guys for putting the Nerdkit and this forum together. I've had my Nerdkit for a little more then a year and I am so amazed at what I have learned so far, I probable have not accomplished a whole lot but I certainly have learned a lot. The Nerdkit really enables me to learn, now isn't that amazing. If they ever need to change their name they could call it the AmazeKit. Thanks, Ralph |
March 18, 2011 by Noter |
Wow, you do have a lot going on! I don't know how you keep it all straight in your mind and manage to any of it done. I'm also interested in the ZigBee but don't know when I'll get going on it. I'm sure it needs a I2C interface if there isn't already one. And your RF Power Harvesting sounds really interesting too. Storing weather data for retrieval later is a perfect application of the external eeprom. My sample program doesn't provide for spanning pages in the eeprom. To do that while writing fairly small chunks will require another function to write the eeprom randomly a byte at a time. Here's that function and it's pieces ready for integration into the sample program:
Also notice that the bitmask for the low byte above is 0xFF. The other low byte bitmasks in the sample program need to be changed from 0x0F to 0xFF for it to work with a non zero address. |
March 18, 2011 by Ralphxyz |
Actually my Water Curtain project is probable going to be up and running before the Weather Station, it also will use a external EEPROM. I will feed the EEPROM from a UART connection to a PC which will have a script (Python) running that will parse a file and feed it to the mcu then to the EEPROM the mcu will read the EEPROM and output what it sees to a Shift Register(s) that controls the solenoid valves. So starting with a "Fill" and then my letter H and O, this would come from a file on the PC using UART:
With a Read from the EEPROM of Fill,H,Fill,O,Fill should give me a solid curtain of water followed by the letter H then a solid curtain of water then the letter O followed by a curtain of water. Basically I would have a binary number and a delay_ms() factor. I would probable need to break it up into distinguished components such as a Fill component, a H component and a O component, so that I could show the H for a certain length of time. Currently I am thinking I will have a 500ms window of display time. That is just a guess for how long it takes a drop of water to fall 60". Once I get the water flowing (dripping) I'll know better what the display window is. This flow has to write into the EEPROM and then read out on demand either serially or by component call. Of course the whole alphabet will be needed plus there could be some custom figures (dolphins, smiley face etc.) added. It would be nice to be able to enter "HELLO" on a keyboard and have it output to the curtain. Ultimately I want to be able to make a sketch on a tablet and have the image appear in the curtain. Now if I can get your code for I2C EEPROM programming to work I have a lot of work to do. Ralph |
March 18, 2011 by Noter |
What eeprom are you planning to use? |
March 18, 2011 by Ralphxyz |
The ZigBee modules I have (ATmega128RFA1-EK1, DIGI XSTICK and DIGI ZigBee Modules) use UART for communications from a microprocessor or sensor. Believe me I cannot keep it straight in my mind, besides being afflicted with the AGE virus I just never was that sharp to begin with. I tend to have to redo things a number of times. I have always had a curious mind (people have always wondered about that) but never had any education or more so any encouragement and guidance. Luckily I am on unemployment, for the first time in 50 years, so I do have time (when I am not diligently sending out my resume). Ralph |
March 18, 2011 by Ralphxyz |
I have two EEPROMs, a ATmel AT24C1024B (1 meg) and a Microchip 24AA128 (128KB). I'll get some 24LC256 to match you if needed. I have had trouble understanding the Device Addressing, in fact I was going to ask you about that. In your code you have:
And in you LCD shot you have on line one: Darn, figured it out as I was asking and checking my numbers, you are showing the hex value (50) on the LCD not decimal (80). Rick uses 8 bit addressing and most of my devices reference a 8 bit number, A0 (A1, A2 etc) for EEPROMs. I do not have a good handle on device addressing and then with the EEPROM you get memory addressing and my head really starts to spin. Especially when I was playing around with the 1 meg EEPROM. Ralph |
March 18, 2011 by Noter |
I2C devices have 7 bit addresses. This is because the 8th bit in the TWI or I2C slave address byte is the read/write flag. If you were writing your own I2C code, you would take the 7 bit device address and shift it left one bit and then the rightmost bit would be the read/write flag. After that's done it's harder to recognize the address if you see it in hex because of the shift but the device address is always 7 bits, no alternatives to that. Most devices will hardcode most of the address bits and then let you jump a few pins for the remainder of the address bits. They do that so you can have more than one of that type of device on the buss. The 24LC256 is hardcoded 1010xxx where the x's are pins I can ground or Vcc for 0's or 1's. I grounded all of them and that's where the 0x50 comes from. Tomorrow I'll take a look at the datasheets on your eeproms and see if they are compatible with the sample program. Memory addressing is easier, starts at zero and goes to the max. Paging is more difficult but we won't deal with that if we don't have to. Probably your eeproms have byte mode like the 24LC256 which is slower than page mode but I think still fast enough to meet your needs. |
March 19, 2011 by Noter |
The demo program will work with the Microchip 24AA128 (128KB) so start with that one. A few modifications to the addressing will be necessary to use the ATmel AT24C1024B (1 meg) but it is certainly doable. After you get it working with the 128k byte chip we'll move on to the 1 meg. |
March 19, 2011 by Noter |
Oops, I mean the 128k bit chip - 16k bytes. I'd better get another cup of coffee before I do any programming this morning. ;-) |
March 19, 2011 by Ralphxyz |
Thanks Noter, I am setting up a new Nerdkits bread board so I will match your setup. Some of your comments reference a 328 but it appears this code is for a 168, correct? Ralph |
March 19, 2011 by Noter |
Yes, I used the basic Nerdkit for this project with the 168 and a 14754600 crystal. You can run on a 328 if you wish, the 168 and 328 are functionally the same except the 328 has twice the amount of flash and eeprom. |
March 19, 2011 by Noter |
I've been studying Eagle and I completed the schematic this evening ... please let me know if you spot any errors in the hookups shown here. |
March 20, 2011 by Ralphxyz |
Man, I have tried to get to learning Eagle about three times this past year but have not gotten very far. Please post your .sch file as that would be a good start for other projects. In fact I really like working from a schematic, it is just so much clearer that working from my mind. Shouldn't that be a 10k resistor on pin 1 (reset)? Ralph |
March 20, 2011 by Noter |
Eagle is a tough one to get a handle on. I continously have to reference tutorials when I want to do anything but the simplest of procedures. Like everything else, only practice will make it easier. I zipped up my Eagle lib for you too because I've made a couple of devices like the LCD display that I couldn't find anywhere else and have modified a few others. One of the 1st things I did with eagle was modify an existing ATmega328 symbol to use the pin names from the datasheet because that is what I was used to seeing. And it took a while the first time too. eagle sch and lbr download. The resistor value on pin 1 for the reset switch is not critical. Just about anything that will not draw too much current when the switch is pressed will be fine. I have a bunch of 1k's so that's why I used it. Using Ohm's Law, the 1k draws 5ma when the switch is closed vs .5ma if using a 10k resistor. |
March 21, 2011 by Ralphxyz |
Noter, I made up a new breadboard and tested it so it runs programs and loads programs. I setup a eeprom128 folder with the 24LC256_eeprom.c file renamed eeprom128.c. I setup a libNoter folder in the Code folder and added twi.h and twi.c. I used a generic Nerdkit MakeFile. When I try to compile the program I get this:
I have never seen /var/folders/gC/gCP9dLxxHKqW1I8ZoJmaME+++TI/ It does exist:
I cannot view -Tmp- Do I need to put a reference to twi.h in the MakeFile? I'll try tomorrow on my Windows 7 x64 machine. Ralph Ralph |
March 21, 2011 by Noter |
Hi Ralph, Yes, you need to reference the TWI.h file in libNoter in the same way you reference include files that are in libnerdkits. Likewise on the object files, they will have to be included in the linker options to be found and eliminate the undefined references. Or, you could copy the TWI files to libnerdkits directory and then not have to change your make file. What was the resolution to the black bar problem you were having on the new setup? Paul |
March 21, 2011 by Noter |
But if you do move the files to libnerdkits, you'll need to update the include statements in the program to reference them there. Here's the make file I use ... It should work for you too. Copy it to the 24LC256_eeprom directory.
|
March 21, 2011 by Noter |
Heck, I forgot that I changed device def's in avrdude.rs so I guess my makefile won't work for you after all without changes - sorry about that. |
March 22, 2011 by Ralphxyz |
Darn, now you are complicating it for me forcing me to think. Instead of just being able to do step1, step2, step3 then RUN. I prefer step1 step2 etc. I have the reference to twi.h in the libNoter library (I have the libNoter library). No twi.o file is being made so I do not know what changes I might make to the MakeFile. I will go over your MakeFile. When I try my Windows computer I can use AVR Studio and build a new Makefile automatically. My "resolution" to the Black Bar problem was to put together a new breadboard. I needed more space than the Nerdkit's breadboard provides so with my handy dandy Dremel I modified some other breadboard pieces to put this together! The other components are for my Weather Station, all I2C modules. There is a Compass for Wind Direction, a DS3232 RTC (Real Time Clock) and a Barometric Pressure sensor. Also a Humidity sensor that uses ADC, and of course my modified Dremel Anemometer for Wind Speed will be added, that uses PB0 with a timmer interrupt for wind speed. Oh the Shift Register for the Water Curtain Project is also there. Also there will be a ZigBee module and hopefully a "RF Power Harvesting" module to power all of this, otherwise I'll need to add a Generator and power management modules or a Solar Cell with power management. The expandable breadboard is rather neat (if I may say so myself) as it is expandable I can easily put more rows to the top or the bottom. Other commercial expandable breadboards, I have only allow one direction expansion either to the top or bottom and some of them only allow adding one more row. With my modifications I can add any number of rows to the top or bottom. Obviously I will need more rows. I am using my tablet with XP to view my oscilloscope (attempting to that is), so I'll use that for testing your I2C-TWI code instead of using my Mac. It helps to have common environments when asking/answering questions. Ralph |
March 22, 2011 by Noter |
As you see, my makefile scans the directory for all files with c in the extension and then builds them. So to keep things simple, be sure you only have one .c file in your program directory. The reason I like it that way is I don't have to edit the makefile when I copy it to a new directory where the program has a different name. My lib build makefile is similar but instead of making the hex file it inserts the .o into a lib file. Again, it scans for c files and does them all. If I edit one of the c files in the lib, it is the only one to be recompiled and updated in the library. But if a clean is done first then all of the c's are compiled and inserted into the lib.
|
March 22, 2011 by Ralphxyz |
Comprehending a MakeFile is slooowly coming through but at the moment no I do not see your makefile scanning the directory for all files with c in the extension. But the more I look at your makefile with that exact directive then I can start to see which sections are "not" the ones to build files with .c extensions. I tried building the project (without modifying my MakeFile, using the same as I used on my Mac)in Programmers Notepad on my XP computer. I think it gets the same equivalent error as I got on my Mac:
So I guess I need to learn more about the MakeFile. I'll also try moving twi.h into the Project Root. Ralph |
March 22, 2011 by Noter |
The "undefined reference" means that the linker cannot fine the TWI.o file. At the end of your arv-gcc line where the libnerdkits stuff is, add " ../libNoter/libNoter.a" and then it will find TWI.o in the libNoter.a library.
When you see "$(patsubst %.c,%.o,$(wildcard .c))" on the "all:" line of my makefile, that is where the directory is scanned for .c and then the list of file names changed to .o. Later the .o's are used to invoke steps of the build. It takes hours to get through the make GNU manual but that is where I learned how to do it. If you have trouble getting to sleep at night, try reading the GNU make manual. |
March 22, 2011 by Ralphxyz |
libNoter.a is not found. Where/what is the libNoter.a library. I have actually gone through the make manual but did not come away with much. Ralph |
March 22, 2011 by Noter |
Oh, I though you had the lib. I guess I posted that somewhere else. Anyway, in leiu of using the lib, change that last entry from libNoter.a to TWI.o and you should be fine as long as the TWI.o file exists where you say it does. If the TWI.o is in libNoter then, ../libNoter/TWI.o. If it's in your program directory then just plain TWI.o. |
March 22, 2011 by Ralphxyz |
twi.o does not exist either. Ralph |
March 22, 2011 by Noter |
Did you compile and link TWI.c? The output of a compile and link is an object (.o) file. If not, copy TWI.c and TWI.h from the initial code post in the begining of this thread into the libNoter directory. Then copy the libNoter makefile to the libNoter directory and run it to compile and link TWI.c into the TWI.o file. Or you can create your own makefile and use it. If you use mine then you should have both TWI.o and libNoter.a created in the directory. Here is the libNoter makefile:
Put all three files in libNoter directory and run the makefile. There should be no errors but let me know if problems. |
March 23, 2011 by Ralphxyz |
I figured that would be my next step. I thought that any involved program would get compiled if it was not already, automatically. Thanks, Ralph |
March 23, 2011 by Ralphxyz |
Noter, I tried making up a MakeFile from what said and posted:
I am getting this error:
Ralph |
March 23, 2011 by Ralphxyz |
Foret my last thread, I used your Makefile from yourMaster/Slave project and it works right out of the box, I have twi.o now. Now to try the EEPROM build again!! Ralph |
March 23, 2011 by Noter |
Great! Getting close now! |
March 23, 2011 by Ralphxyz |
Well I tried making the EEPROM project now that I have my twi.o file. I get the biggest error I have ever gotten. It is even complaining about lcd.h, now that's a first:
|
March 23, 2011 by Noter |
What is eeprom128.c? I've got to go right now but will be back in a couple of hours. |
March 23, 2011 by Ralphxyz |
re: the lines 3 -8 in the above error code. I can build other projects without errors calling avr/interrupt.h,avr/pgmspace.h and lcd.h. This was on my mac I will switch over to XP and Programmers Notepad. This is progress so I am encouraged :-) Ralph |
March 23, 2011 by Ralphxyz |
Here is my error when trying to compile the EEPROM program in Windows XP using Programmers Notepad:
It doesn't even get started. What program is it looking for? eeprom128.c certainly is there, there is no eeprom128.o file of course. Ralph |
March 23, 2011 by Ralphxyz |
eeprom128.c is my file name your 24LC256_eeprom.c file. Here is the error I get when using the Command Line:
This is using your Makefile. What is the best environment to be using? I'll stick to just one so as to not be too confusing. Ralph |
March 23, 2011 by Ralphxyz |
Well now I get the same error in Programmers Notepad so I guess that at least levels the playing field. Ralph |
March 23, 2011 by Noter |
I think you're almost there. The problem is that the linker can't fine the TWI functions so we have to tell it where they are. Add ../libNoter/TWI.o to the end of the line after the libnerdkits objects. (I assume TWI.o is in the libNoter directory?). |
March 23, 2011 by Noter |
As far as the best environment ... if you mean windows or mac, I don't know, I never had an apple computer. |
March 24, 2011 by Ralphxyz |
WhoooWheeee!!! :-) I did it, I actually have the same output on the LCD as your example. Plus each time I hit the reset switch the READ COUNT increments by one. Hot Dog, It Works. I could not get your Makefile to work, so I used a generic Nerdkits Makefile (which leads to another forum question):
Of course now I am really going to load on the questions. First of which will be getting my ATMEL AT24C1024B EEPROM working. I have not even thought of this for a couple of weeks. Then of course I need to get the DS3232 Real Time Clock working and then my other I2C modules. This is great, now I can take a breath and go have a cup of coffee and relax, they rest of this will be a cake walk, right. Thanks Noter, and thanks Rick for getting me going. Ralph |
March 24, 2011 by Ralphxyz |
Well that was easy I just replaced the Microchip 24AA128 with the ATmel AT24C1024B and it works right out of the box. I did not have to do anything. The pinout is the same so I did not even need to change the wiring. The output on the LCD was kinda messy the first time turning it on (same as happend with the 24AA128) but after a reset it cleared right up. Noter I believe you had some error code which would have appeared if the chip was not actually working. Wow this is so cool. Now to really study yours and Rick's code to get the other modules working. I can also start to play (learn) around with multiple device addressing which I will need. Man I got a lot of work to do. Ralph |
March 24, 2011 by Noter |
Good news Ralph! Now, don't forget to put in the patches for non-zero addresses and spanning pages. That is the next step. Implement the change (earlier post) to the program and then change the memory address from 0 to 0x00FF and verify it still works. After those changes are working, another minor change to be able to use the full address range of the 1m bit chip is needed. I'll hold off on that until you get the first set of changes working. |
March 24, 2011 by Ralphxyz |
I would like to get your Makefile to work but it doesn't even try. Of course I would like to understand the Makefile better so I started this thread. By non-zero addresses you mean using the A1, A2 etc pins? This whole device addressing is going to take some work but at least now I can make changes and have a working base line to return to. I am having trouble comprehending "use the full address range of the 1m bit chip". But I am working on it. I am trying to understand the structuring of the data stored on the EEPROM, I can see how a program writes to the EEPROM using a struct as you did but I do not understand how a different program would be able to read the EEPROM. This goes back to not having a file system to manage memory I believe. It's not required that a different mcu and program be able to access a EEPROM but say we had your Master/Slave setup could both mcus access the same EEPROM? And then but again not important at the moment how do you delete data from the EEPROM? Well like I said now I am going to be able to ask a lot of questions. Ralph |
March 24, 2011 by Noter |
By non-zero addresses I mean the eeprom memory address. If you examine the program closely you will see that the test data is currently written and read from eeprom address 0. If you change to use an address that is not 0, the program will not work correctly as will be evident by the display showing trash all the time like it did the very first time on a new chip. That is why the changes are necessary before going any further. None of that other stuff matters until the test program works correctly for the entire memory address range of your 1m bit chip. If you go back to the early part of this thread you will find the post where I gave some changes to deal with the memory address of zero problem. Implement those changes into the test program and we'll go from there. |
March 24, 2011 by Ralphxyz |
I added your code from 5 days ago starting at line 42 in the main program or does this need to go in the twi.c program? I also changed the low_byte in the main program to 0x00FF, in three places. This of course broke the working code:
Should this go in your "// Define eeprom commands according to 24LC256 datasheet" Section instead? Line 131. Thanks so much for your patience I sure hope others are getting benefit from this thread, I do not like hogging all of your time but this really should be usable in so many situations. I had looked at using a SD card but using a EEPROM just made more sense (I'll do the SD card later on). Is anyone else reading this thread, I'd like to hear your comments. Ralph |
March 24, 2011 by Noter |
Time to put on your programmer hat. It doesn't all got together in the same place. The "..." divide the new parts that stay together. You're right on the new typedef, it goes in with the eeprom commands. |
March 25, 2011 by Noter |
Hey Ralph, I ordered a 1mb eeprom so I can test and be sure it works before posting an updated test program. In the mean time, I'll explain my approach. The AT24C1024B is 1m bit in a single package but logically it is two 512k bit devices. By I2C definition each device has a unique 7 bit address and the AT24C1024B has two device addresses, one for the lower 512k bit memory and another for the upper 512k bit memory. Therefore, logically it must be two devices. The I2C does not know or care that these two devices are in a single package. I believe the reason behind having the two devices is to remain compatible with smaller eeprom chips where the complete memory range can be addressed with two bytes. So, the test program must be modified to handle multiple 512k bit devices and when done will be able to address and use the maxium number of these devices which logically is 8 or physically 4 of the AT24C1024B. Here's my approach to change the test program to support the AT24C1024B:
Hopefully I've explained it well enough that you can follow what I mean. Of course there's always more than one way to do things so this may not be the best approach but I think it will work. Maybe I'll have my chip next week and can get the program tested/posted. |
March 26, 2011 by Ralphxyz |
Noter, thank you so much. wow that really clarifies things. The two device addressing makes sense (finally). Claiming my ignorance I was going to ask you to start over begging at square one to explain the memory addressing but I think you just did, fascinating. I am taking a day or two and re-reading the AT24C1024B spec sheet a few more times. I also printed out your code and Rick's DS3232 RTC code and this code from ermicro. The ermicro code does largely what I need to do, it feeds binary numbers into the EEPROM and reads them back. That is almost explicitly what I need for for my Water Curtain project. That plus having a potentiometer to vary the timing is just what I need for initial timing since I have no idea what timing factors I will be needing. The ermicro code uses an array instead of your struct so that gives me another perspective. Of course all three code methods are using different libraries, well the ermicro has the twi commands inline, which will complicate my comparisons but should lead to a better understanding. And then I am really intrigued with Rick's I2C LCD project and the work you and Eric did with the I2C Master/Slave. I haven't yet printed the Master/Slave code (but will). To bad winter is all most over, I have a lot of projects to be working on outside so I'll be slowed down a little but I 'll keep plugging ahead. Thanks again this has really been a great thread I hope others have found it useful. Ralph |
March 26, 2011 by Noter |
Hi Ralph, I'm glad you made sense of my explaination and approach to the 1m bit eeprom addressing solution. If you get it working first, post your code otherwise I'll post mine once I receive the chip and get it tested. Paul |
March 29, 2011 by Ralphxyz |
Well I have been modifying my breadboard. I also retried using Rick's I2C Real Time Clock (RTC) and ta dah it works. Here is some test code that ATmel puts out for testing the AT24C1024. It is for a different class of mcus but I figured the C code might help to illustrate programming/using the AT24C1024. Here is the link for the whole project. It covers a number of I2C devices including the AT24C1024 EEPROM and a RTC. Here is a ATmel Application Note outlining the code use. Now how would I write the clock output to the EEPROM? For the weather station I will also need the other devices (barometric pressure, relative humidity, temperature, wind direction and wind speed) data. But it seems like a god place to start wit a Date Time Stamp. Ralph |
March 29, 2011 by Rick_S |
I'm so happy to hear you finally got the I2C RTC going. Did you nail down the exact cause of the problem or just do a rebuild of the breadboard? Now you can get on to even more fun stuff :D Rick |
March 29, 2011 by Ralphxyz |
It was just a complete new breadboard, I had gone from not being able to run your code to having the two black bars in run mode so I just said the heck with it and started over. Plus I needed more room for all of the components. I'd like to get all of the components running off the same bus instead of doing them separately as I have read that having multiple devices on the same bus changes the capacitance which can effect timing. So if there is going to be a problem I would rather it rear it's ugly head rather during development time than having everything run independently and then fail when I put them together. Ralph |
April 06, 2011 by Ralphxyz |
Paul, did you get your big I2C EEPROM? What do you think of the ATmel method of addressing the 1 meg EEPROM? That whole Application Note project is interesting with the TWI LCD, TWI EEPROM and TWI RTC all of which have been hashed out here in the Nerdkits forums, most recently thanks to you, Rick and Eric. Ralph |
April 06, 2011 by Noter |
Yes, I have four of them and they are installed on my TWI master breadboard but I've been working on the DOW (Dallas One Wire) interface and haven't made it back to the eeprom code yet. I figure I'll be finished with the DOW this week and get back to the eeprom next week. I'm using the DOW to access multiple DS18B20's for temperature readings. I think they will be much more accurate and stable than the ADC variety used with the nerdkit plus I can string a lot of them on a single buss which will be great for my ground temp project where I measure temp every 6 inches up to a 6 foot depth. I'll have DOW results in another day or so and then get back to the eeprom code. Paul |
April 06, 2011 by Noter |
I hadn't looked at the ATmel Application Note but just did and I see that they also refer to the 1mb eeprom as being addressed by 17 bits with the overflow in the I2C address bit. Same as the spec sheet but not as clear to me as viewing the 1mb chip to be two 512 devices. The results are the same but I like to stick with the I2C definition of device addresses which means the 1mb eeprom is really two 512kb devices because there are two I2C device addresses. |
April 06, 2011 by Ralphxyz |
Damm, I almost (finally) am actually following what you are saying. Possible it is because I actually looked at the ATmel code and saw the reference to the 17bit address and almost understood what they were doing. I agree with you treating the device as two separate devices makes sense. But,but what about having multiple devices I think the specsheet says you can have four on the same I2C buss. How does that work with the device split in two? Does that mean you only can have two 1meg eeproms instead of 4? Ralph |
April 06, 2011 by Noter |
If you have 4 of something and you split them in two then you have 8 halves. Up to 8 of the 512k bit devices can be on the same IC2 buss. If you look at the 512k bit eeprom spec sheet you will see that you can have max of 8. That's the three address pins on the eeprom chip - 2^3 = 8 ... 0 thru 7. |
April 06, 2011 by Ralphxyz |
Here is what I am hung up on:
There are only two address pins (additional) on the AT24C1024B (A1 and A2). For the first device you are not using the address pins correct, pin A1 and pin A2 are either floating or at ground? So what is the address of the second 1/2 512k bit device? The first device is 10100000 so what is the the second (1/2) device? A1 is my logical answer 10100001 but that does not work form my understanding of what you have said so far. Strange I almost understand but but ... Ralph |
April 06, 2011 by Noter |
Look at the top of page 11 in the datasheet. It shows that the 7 bit device address is 1 0 1 0 A2 A1 P P is the address bit that selects one or the other 512k bit bank of eeprom. So your answer is correct, the 2nd bank on the 1st device is 1010001. Just as a note, don't let the A's float, connect either to GND or Vcc. |
April 07, 2011 by Ralphxyz |
Thanks Paul, wow my heaad is sloowly staarting to spin less. I really do not need multiple 1meg eeproms but it would be nice to understand this (at least functionally). Ok new subject(s). How do you erase a memory location or does just overwriting without a delete work? I am starting to think about putting actual data into the eeprom. First I need to input the alphabet using something like the H I have shown in the Water Curtain thread and else where (March 18 in this thread) As of the moment the H looks something like this:
I guess I am essentially building a font table that in code I would like to be able to call with a "H" and feed the binary bit pattern to my solenoids with the timing factor determining how long to turn the solenoids on. Would each letter be a struct? And then I need to do a lookup table for my Relative Humidty sensor. Glad you have a truckload of patience, thanks. What a interesting thread, I am sure glad you wanted to share your experience. Ralph |
April 07, 2011 by Noter |
I guess you could write 0xFF's and consider that erasing the eeprom but there is really no need, just overwrite with new data. You could use a struct to define each character but you will still need to have a method to figure the address in eeprom where any given struct is located. Think of it as an array and define the order of characters in your array. Then use the character value to calc the eeprom address of the data. Let's say the order of structs in eeprom is 0, 1, 2, ... 9, A, B, B ... Z and the struct is defined as:
Just calculate the eeprom address where the data is stored based on the character value: '5' - '0' = 5, 5 * sizeof(struct) = 40, 40 is the eeprom address of the '5' struct data. Same for alpha but add 10 to account for the digits. ('H' - 'A' + 10) * sizeof(struct) = 136 is the eeprom address of the 'H' struct data. This is just one method of many but I tend to like calculating addresses when I can instead of using some sort of look up or search. |
April 07, 2011 by Noter |
I missed the other number in the struct ...
and using the sizeof(struct) in code saves a lot of editing as changes to the struct are applied. So the answers I came up with above will be different now because of the size of the new struct. |
April 07, 2011 by bretm |
Wouldn't the "H" just be
So you'd need one table with the "data offset" for each letter, and the number of pattern entries for each symbol would be variable, so you have to look up the next symbol's offset to know when to stop.
I'd use uint16_t instead of float for the duration, e.g. 187.5 would be 1875. Takes half the space and is faster to compute with. |
April 07, 2011 by Noter |
Or perhaps use a fixed duration for each line in the original array and not include the float/int16 at all. If you're low on memory then a scheme like bretm suggests is one way to reduce usage. Given plenty of memory, I'd opt for the simpler approach. Have you done an estimate of how much memory you need? |
April 07, 2011 by Ralphxyz |
Paul said "Have you done an estimate of how much memory you need?" Gee a quote mechanism would be nice in the forum. All of what I have done so far is really off the top of my head, I can picture my H structure working as such. I can picture 8 solenoids in a row simultaneously turning on for a split second and a drip falling. But I do not know how practical or feasible that schema might be. So NO I have not done any memory analysis. This is all speculation I do not know if it will even remotely work or how feasible it will be. Possible I will need a lot more computing power than a ATmega mcu can provide. That is why I am really counting on the feedback from the forum to help me work this through. If someone would only say "Ralph this will not work, because ..." then I could get on with my life and get back to my Weather Station which probable is a lot more feasible (easy) project. bretm said: Wouldn't the "H" just be
Yes that would work for a H, but I believe for other letters and shapes (diving dolphin) or the letter O or X I think it needs to be broken up into segments. Plus there might be a ripple in the visual effect making it more readable (recognizable). I am close to actually trying to do this, once I get the water flowing (dripping) I probable will discover that I have to do major revisions to my implementation. Paul said "Or perhaps use a fixed duration for each line in the original array " I am sorry I thought my timing scheme was implicit with a fixed duration designated, I suppose I failed to say that recently sorry.
Line one 00111100,37.5 is made up as:
Possible I will have to time the OFF but for now it is just assumed. Line two would be:
This "assumes" it takes a drop of water 500ms to fall 5 feet. So once I get water dripping I'll have to refine my timings. I have been devising a drip timer in my spare time. Ok now for a hard question: How would I read/write the eeprom with multiple devices? I know for some computing devices a eeprom is used to load the operating system or program. I just got a device that uses a 8051 mcu and it's bootloader looks into a eeprom to load the program that is to be run. But I am thinking of using one mcu to load (write) the eeprom with another mcu to read the eeprom. With a DOS (disk operating system) as used in a pc there is a file system operator (OS) to read files from a specified folder (directory). Without a OS how does the reader mcu know where to look for the "H". Ralph |
April 07, 2011 by Noter |
Ralph, I described a simple method of addressing the eeprom for you data in my posts prior to bretm's method. Take another look at those and see if you can make sense of it. |
April 08, 2011 by Ralphxyz |
Paul from your programing example above:
Why are you using arrays? Wouldn't uint8_t row[8] take up 8 bytes(+) to hold a 8 bit binary number. And why a float for duration it seems a uint8_t would hold any of my timing values. Or is uint8_t row[8]; saying make 8 "rows"? I am back to studying up on structs. Remember I do not consider myself to be a "programmer". I used to have a Signature on AVRfreaks that said:
Ralph |
April 08, 2011 by Ralphxyz |
Ok, I went back and read your suggested Structures reading And I see that:
Would make one line of my letter character. So for my letter H I would need 7 of these structs. Now I am working on populating each row with it's duration. My current H has 7 rows and my O has 10 rows.
Could I do something like this:
Assuming that my largest letter would occupy 10 rows I can adjust the H to use 10 rows by modifying the timing:
Of course this is all a work in progress. Ralph |
April 08, 2011 by Noter |
I didn't look closely at your design before keying in that example. With only 7 rows, you only need 7 items in the array. I thought you were going to keep the duration in the array too but after your last email I guess not so 7 rows, 8 bits each is all you need - right? The specific structure doesn't matter so much when working out the method of addressing your eeprom. I am focused on the method so I miss some of your project detail in my examples.
Using a struct for a simple table seems like overkill but I think it allows for more readable code. And if you ever do add another element, the struct is definately and advantage. using a 2 dimensional array it looks like this -
The method of calculating the eeprom address works about the same with either one. You need to consider being a programmer to go much beyond the nerdkit examples since the majority of effort on these projects is programming. Maybe you would like taking a few programming courses at a local community college? |
April 08, 2011 by Ralphxyz |
Ooops, got to maintain 500 ms total for the entire letter exposure so that should be:
Ralph |
April 08, 2011 by Noter |
Why not stick to a fixed number of rows like regular fonts do? Otherwise for a variable number of rows you'll have to use something like bretm's scheme. |
April 08, 2011 by Ralphxyz |
Are you kidding, at 63 I am not likely to "go to college" (notice I did not say "go back" to college) even though I really would love to take some programming classes. I tried to get into the local community college (local being a hour away) a few years back to take a JAVA course but they could not get enough students. Besides I am learning so much from your instruction and that of others like Rick and bretm and so many more. I will get this, it might take a while but I can see that I am really making progress. I am almost ready to "try" to put some data into the eeprom. Well first I will hardcode H E L L O and light some leds and Dean Camera has such a excellant tutorial on programing the internal EEPROM over at AVRfreaks that I'll use the internal eeprom and then graduate up to using the external eeprom the smaller one and then the 1 meg. Are you ready to start a new thread about using the DOW (Dallas One Wire) interface for your ground measurement project? I have thought about doing a ground temperature project such as you have described. Of course my biggest deterrent to getting things done or effectively (quickly) learning something is that I keep adding more things to do. Besides my mcu programming projects you ought to see my list of projects to do around the house this summer but hey I have lots of time and probable another 50 - 60 years. Ralph |
April 08, 2011 by Noter |
You might see if there is an online course that you'd like. You will likely learn faster and learn more if in a structured environment compared to hit and miss on forums. I am happy with the DS18B20 temp sensor. Three out of the box and they all measure within .2 degree F of each other and are very stable. There's a lot of example code on the net and Maxim has an application note with source code so I don't know if I will start another thread on DOW. I had it all working in a couple of days. Less than 1 minute to hook up the wires and probably 10 hours of programming. I like to rewrite all the code in my own fashion to be sure I have learned it. Otherwise figure maybe an hour or so to get one of the samples to work ... if they work. |
April 08, 2011 by Ralphxyz |
Wow .2 degree of each other is good. The LM34 that comes with the Nerdkit has three or four batch groupings with accuracy determining the grouping. The ones that come with the NerdkitI are guaranteed for are something like + - 4 degrees while the LM34CZ is much more refined (accurate). Of course the LM34CZ cost four times as much. I think it is great to have these different projects and device utilizations published here in the Nerdkits forum, you just never know who might come along and be searching the forum and find your thread and maybe all of these tutorial type thread will get consolidated into a repository here on the Nerdkits forum so they will be an easy reference. I now I can and will search the web for the Dallas One Wire interface but I really like the discussion and the perspectives that get introduced. Ralph |
April 08, 2011 by bretm |
-> Why not stick to a fixed number of rows like regular fonts do? I would imagine, once he's got it working for text, the next stage would be arbitrary symbols or patterns. With a million bits and a cunning arrangement of data I would imagine you could store a day-long water extravaganza. A megabit is a lot of data for something like this. |
April 08, 2011 by Noter |
Probably could send the each row of the pattern from the PC via the rs232 line and never have to store anything with at mcu. It could come off disk, over the internet, or from anywhere. |
April 08, 2011 by Ralphxyz |
I might not have a computer at the Water Curtain display certainly not at the at the Weather Station. Of course the font table is for the Water Curtain not the Weather Station. It seems like using something like a font table is what I want to do. For programming the eeprom with the font table I would like to use a PC. In fact I mentioned the other day that I had gotten a device using the 8051 mcu with the bootloader loading the application from a eeprom. That device is a USB I2C bridge. That is why I was wondering/asking about having multiple I2C device accessing one eeprom one to read and one to write. So anybody use a USB I2C bridge? Hey bretm, yeah you are getting the picture. Here is the link to my inspiration again it is from Canal City in Japan. Right now I am just experimenting with 8 solenoids or about a 6" display. If this works and I can get recognizable letters I would like to expand the display to 32 solenoids 24" display. So I definitely am thinking of arbitrary symbols and patterns. Of course it would be unreal to do a really big display but if I can make recognizable objects then there is no reason I couldn't do a big one. Of course someone would have to pay for it. This could be a another water fountain career for someone. I already made one career for one guy building animated (to music) water fountains. I came up with the water flow formulas that he uses. Plus Singlecoilx3 has just given me a new idea (inspiration) with his Higher Resolution Large LED Display text messaging. Now that would be cool imagine sending a text message from your phone and having the message come out in/on the water curtain. I also am thinking about being able to draw a image on a tablet computer and have it replicated in/on the water curtain. Both of those ideas would really differentiate my Water Curtain from others. I could probable hire it out for wedding receptions or parties and store openings where ever there are people. So I want/need static displays but I really want dynamic displays. That will differentiate my Water Curtain Ralph |
April 08, 2011 by Noter |
Here is the megabit eeprom demo. It uses the latest TWI master/slave code which I will post next.
|
April 08, 2011 by Noter |
|
April 08, 2011 by Noter |
|
April 09, 2011 by Ralphxyz |
Wow, Paul that is fantastic. And thanks so much for the PATTERN. I'll need a couple of days (weeks) to really digest this. Thanks for the informative comments they really help. Ralph |
April 12, 2011 by Zachariah |
I ordered some 24LC256 so I could learn what this form as been talking about. I got everything working as advertized. Well then I decided to start learning more by changing little things in the programming to see what happens. Using two EEPROM chips I changed the code to get both to count up in the same way that was demonstrated for one. I tried to then change the code so that it would save the read count to the EEPROM LOCATION 00001… Ok so I screwed something up. I only changed line 47 of 24LC256_eeprom.c
Changed to :
As some might expect I got the DATA ERROR message on the LCD. I pushed rest button a few times and still got it. Then changed the code back to exactly how examples show. Then removed second 24LC256 chip. Now I am still getting Error code as follows:
I am sorry if this is a bit lengthy. I want to be clear on what happen. Anyone have any ideas of what I did by changing that one number? Then anyone know how to fix this? |
April 12, 2011 by Noter |
24LC256.c needs the changes shown in the 5th post from the top of the thread to work with non-zero locations. You might want to get AT24C1024B_eeprom.c above along with the latest version of the TWI master/slave code and go with it. For a single chip all you would need to do is limit your eeprom addresses to a max of 0x31 since you have only 256k bits. Otherwise the 24LC256 is pin/command compatible with the AT24C1024B. |
June 09, 2011 by carlhako |
Thanks a heap Noter. I purchased a 24lc64 with 64k of storage for my weather station. So far my weather station is reading temps and dumping the data to a mysql db and graphing. ill post all my code and everything when done. Im now working on storing the data so if for example my pc is off the data is stored into the eeprom, 64k will let me store months of data. My plan this weekend was get this chip working, I think you have saved me alot of time! Im pretty sure your code will work without much modification. |
June 13, 2011 by carlhako |
Hi Noter I am running into similar problems as Ralphxyz where I cannot get a TWI.o file compiled and am not sure how he fixed it. Maybe Ralphxyz could you post your Makefile you used for this one? I realized reading through this thread that the chips are rated in bits not bytes so my 64K chip actually only holds 8KB which is not enough for my needs. Ill upgrade to a 1024kbit one but I still should be able to get this running with my current one. The error I am getting when compiling error:
Dropbox is handy for this stuff btw I can sync my code folder with any of my windows/linux machines floorlessly. This is what i have done: in main.c i have tried "#include ../libnerdkits/TWI.h" and ./TWI.h with the 2 files copied to appropriate locations. I have edited my Makefile to include a ../libnerdkits/TWI.o this just give the error that the .o file is missing. What i am not understanding is if i delete ../libnerdkits/lcd.o and then rerun the make file lcd.o is regenerated but TWI.h does not operate the same way? I have gone through lcd.h and lcd.c comparing to TWI.h and TWI.c and cant see what its missing to auto generate the .o file? |
June 13, 2011 by Noter |
Hi Carl, With twi.c and twi.h files in your libnerdkits directory then you need a little change to the libnerdkits makefile to do the compile. Add twi.o to the "all:" line and two lines at the end to create the twi.o file.
|
June 13, 2011 by Ralphxyz |
I used a [Code/libNoter] library. I "think" I compiled twi.c and twi.h to make the twi.o file. Here is the libNoter folder: Here is my EEPROM Makefile:
Notice the LINKOBJECTS line ends with ../libNoter/TWI.o. Ralph |
June 13, 2011 by carlhako |
Awesome thanks Guys Thanks what i was missing! I didn't notice the makefile in the libnerdkits folder ill make that change. Ralphxyz have you managed to get full access to the 1024Kbit on your chip? |
June 14, 2011 by carlhako |
Made the changes to libnerdkits/Makefile as Noters suggestion and added "#define F_CPU 14745600" to the start of 24LC256_eeprom.c it then compiled straight off the bat :). Just not sure what the 0 and the 33 are on line 3. |
June 14, 2011 by Noter |
Line 3 shows the data after it is read back from eeprom. According to the format in the structure, the 0 is the need_initialization variable value and the 33 is the brightness variable value.
|
June 14, 2011 by Ralphxyz |
Hi carlhako, I have not gone further than to get Noter's code and suggestions working. I'am having a hard time understanding accessing stored data on the EEPROM. I think I understand writing serial data but am lost when it comes to accessing random data. I know I can look at a specific address but how would I know what address to look for. I can calculate the address when I am doing a write but where would I store that information for reference the next day or month after the mcu has been turned off. Paul did a nice job of explaining writing to memory which I "think" I understand but I am lost on reading stored data. Short of doing a serial read every time I turn the mcu on. Also I would like to be able to access the EEPROM from other devices, using I2C. Part of my problem is I am still thinking of a computer with a OS reading the EEPROM. I am used to using a EEPROM burner to fill a EEPROM with data and then being able to access that EEPROM from various different devices (all with the same OS). I need to adjust my thinking. My specific data might look something like this.
I am thinking of writing this data to the EEPROM every 15 minutes so the values are actually averages (over 15 minutes) with the high and low temperature and high and low wind speed for that period. So how would I view a random date's high wind speed? I am in the occasional thinking about this stage while working on other projects. Ralph |
June 14, 2011 by Noter |
If I was going to store weather station type data I think I would just write records one after the other to the eeprom. I might use a few bytes in the begining of the eeprom to save a count of records so I would be able to calculate where the end is and where to put the next one. Then if I had to randomly find a particular one by timestamp I would do a binary search which should work fine since they will be written in chronological order anyway. |
June 14, 2011 by Ralphxyz |
Oh that's interesting (as usual) thanks Paul. Like I said I only am occasionally thinking about this mode so we will see what happens when I actually try to write and read data. There are different scenarios thatI I have pictured. The most likely is that I would never need to to read anything using the AVR mcu but everything would be transferred to a PC for any possible display. This is referencing my weather station project which will be mounted up on a pole so I certainly will not have a LCD or other display device directly attached. I am picturing doing a Wireless (ZigBee) read of the EEPROM data so I would just be doing a serial read and would not care where any particulars might be stored. Of course this is just for my weather station for other projects I might want to access a particular piece of data directly. This is all so fascinating and so much fun, Thanks again for your help. Ralph |
June 15, 2011 by carlhako |
I am using this for my weather station too which will be temps/humidity/rain. If i know the time interval between recorded records (5min) i can use the first 8 or 16 bits to keep a record of how many records there are. My setup is only going to store data into the eeprom when communication between the pc and mcu is broken say if i switch the pc off or loose power last year we had a cyclone and lost power for a week. Otherwise every 5min the data is stored into a mysql database. I have that all working and even graphing with php. Ill post all my code php and perl scripts in a separate thread when i have it complete, hopefully someone might find it useful Carl |
July 25, 2011 by Ralphxyz |
Carl I'd really like to see more about your Weather Station! Ok, now I have a great (my humble opinion of course) "Pattern Generator" thanks to Cliff over on AVRFreaks. Now "we" need to have a discussion about putting these patterns onto the EEPROM. I really have no idea of where to start, well I do we have this thread and Paul has mentioned a couple of methods. My head is just not clear on exactly what it is I should do and exactly how. My pattern generator is using a single Struct with a number of patterns in arrays: Here is the code sorry it's a bit long because of the patterns.
That NUM_ELEMENTS macro is really clever it enables me to have different sized arrays (patterns). The thing I do not know about the EEPROM is how will I find the patterns? I was thinking maybe I would have a lookup table in the first 5k(?) of memory where I could store the memory address and what ever else was needed. Is that feasible. Would that be a good/acceptable way? I have no idea how many patterns I will have. I picture at least a hundred and probable lots more once I start doing images. So if not a lookup table than how else would I find my way around? So I am open to any and all suggestions. What is the advantage to using a Struct versus just storing the binary data inline? I will need to serially read the eeprom to serially feed it to the the Shift Register so if I know where to start reading and how many bytes to read what is the advantage to have the data stored in a structure? All of your help is really appreciated and obviously needed! Ralph |
September 06, 2011 by Ralphxyz |
Hey Paul, I am ready to "think" about EEPROM storage of my patterns for my Water Curtain. I have started a new thread. I sure appreciate all of your help so far and am looking forward to your insight and knowledge. Ralph |
October 20, 2012 by esoderberg |
Noter et al., The TWI code you posted (and that I modified and put in the NK library) works great 99.9% of the time. The problem I'm having trouble overcoming with the modified code is that when it doesn't work, my code hangs. I'm trying to make it a little more robust so that if there is some temporary glitch, it may miss a few communication cycles, but will eventually pick back up and keep running. I've tried several various bit of code in the ISR(TWI_vect) "default" and other switch cases indicating a disruption, but with no luck; once it stops working, it never recovers. Any pointers on where I should focus my attention would be appreciated. Eric |
October 20, 2012 by esoderberg |
More info on the question above - I have one TWI Master communicating with one MPU-6050 gyro/accel and one slave 328P. The slave code seems to continue running regardless of TWI bus status and the Master hanging up. Eric |
October 20, 2012 by Noter |
I haven't had problems with the interface yet but when I came across the following in the DS3232 spec I2c section I thought it would be a good feature to add to the TWI code at some point.
|
October 20, 2012 by esoderberg |
Noter, My multi-meter showed SDA and SCL being held low when the original code hung up, so my problem may be as suggested in your post.
The additional code below is one of many attempts to fix this; now when the code hangs it shows a steady 5v on SCL vice something closer to 3v that I see when it's running normally. SDA is still being held low. Obviously more work required.
|
October 21, 2012 by Noter |
Better detail is in this document. It says a NAK is in order to stop the slave from transmitting the next byte if a multi byte stream. Worse case, build a circuit to reset the slave. I code my master to always reset slaves when it initializes and that is probably why I have not seen this problem. |
May 13, 2013 by dvdsnyd |
All, This may be a silly question, but what is the difference between your TWI code and Peter Fleury's library for TWI? I am trying to get back into my altimeter project, and am in the process of rewriting the entire project. If there are benefits to changing, now is a good time to commit. Thanks, Dave |
May 14, 2013 by pcbolt |
Dave - I think the Fleury code is poll driven so it sits in a "while" loop until completed and therefore it blocks execution. Noter's code is interrupt driven so it won't block. It is more complicated so you might want to stick to the Fleury code, but it is very flexible and will report very helpful error codes when things aren't working. It also handles many error situations in the ISR. I re-wrote the Fleury code so it used polling but with timeouts so the program wouldn't lock up. I was tempted to use the interrupt driven library but my program wasn't doing anything but waiting for data from the I2C lines. In other words, unless I got the data I needed there wasn't anything else the program needed to do. I was able to report error codes based on R/W errors, timeouts, init problems, etc. so it helped in debugging problems. I guess it boils down to what type of program you are running. |
May 15, 2013 by dvdsnyd |
pcbolt, Thanks for your reply. I have a pressure sensor that uses I2C for communication. I tried using the Fleury code about a year ago, with some success. However, it was very prone to freezing. With just the altimeter, all I need to do is continually read the pressure sensor, once the highest point is reached, save that value and we are done. Could I use your polling code with timeouts to see why the program is locking up? It runs just fine sitting on my desk, but if I blow over the sensor, or shake it sometimes it will lock up. Any suggestions for I2C debugging? The second iteration of my altimeter has plans for eeprom data storage of the pressure values for later analysis. Would something like that require an interrupt driven I2C protocol? Thanks, Dave |
May 15, 2013 by pcbolt |
I think in both cases you could use the timeout version. You programs depend on getting good data before testing it (1st iteration) or saving it (2nd iteration). The code I adapted isn't exactly compatible with the Fleury code, so you'd have to change function calls with different parameters. An easier way would be to just change the Fleury code yourself (save the original first). Using the "i2c_start()" function as an example:
You can see at lines 9 and 20 the program stops here and waits forever if it has to. Line 9 is less likely of a concern but line 20 could be. You can add a timeout to both wait points by modifying it to read:
You just have to remember to add the "delay.h" header file to this source file before you can use the delay functions. (You won't need to add it to your main code after that). You can do this to the "i2c_write()" code as well but the "i2c_readAck()" and "i2c_readNak()" are slightly different since they return the data read and not an error code like the other functions. You can modify those to return an error code and send a pointer as a function parameter that will hold the data to be read out (or use a global variable). |
May 16, 2013 by dvdsnyd |
pcbolt, Thanks for your help again. You said: " The code I adapted isn't exactly compatible with the Fleury code, so you'd have to change function calls with different parameters" Silly question, but what do you mean by this? Why would you have different parameters? I understood the timeout in the i2c_start() function, however, when you started talking about returning error codes and sending pointers as function parameters, I am lost. for i2c_readAck() and i2c_readNak(), you modify these, to return an error code when the the transmission gets hung up in one of these routines? But, the data is still held to be read out after the timeout has occurred? Sorry, I am just trying to figure out the logic behind how this works... Let me know if I am even close to the target. Thanks, Dave |
May 16, 2013 by pcbolt |
It's been a little while since I made the code library for I2C so I'm not exactly positive why I made all the changes I did. That said, I think I changed the "i2c_start()" function so it would tell me which of the 2 "while()" loops got hung up. Looking back, it most likely wasn't needed but it still works. I combined the two "i2c_readAck()/i2c_readNak()" functions into one by sending a flag to the function indicating which sequence of code to run. This is what I meant by changing the function parameters. In the "i2c_readAck()/i2c_readNak()" functions, if the timeout occurs, the function will return immediately with an error code of 2. The data isn't held since it never was received. If all went correctly, the function should return an error code of 0 and the data will be available. The problem is how to get that data back to your main program, since you can only return one value. The way I do it is to send the address of a variable from your main program as a function parameter. The function puts the data in that address and your main program can now access it. For example, if I were to re-write the "i2c_readAck()" I'd change the original...
To something like this...
Now in your main code you can call the function like this
I usually end up chaining a bunch of calls together like this...
|
May 18, 2013 by dvdsnyd |
pcbolt, Thanks for explaining how that works. I am going to have to brush up on pointers. What is the main function of the timeout? To notify you that an error occurred in the data transmission? Like I mentioned, I had issues with the i2c interface. It would start up and run, return data and then stop. Once it froze up, I had do a power reset for it to work again. This won't work for an altimeter that I am going to be relying on to help recover a rocket. What are some potential causes of a freezing i2c data transfer? Are there ways to make it more robust? Will adding the timeout help? Let me know if I should make this a new thread...? Thanks again! David |
May 18, 2013 by pcbolt |
David - I was thinking of starting a new thread as well. This one is pretty long but fortunately doesn't have too many photos which can be a hassle when it first loads. The major benefit of the timeouts is to be able to report errors. Without them the program just gets stuck and you have no idea what went wrong. You could report your progress in the program to the LCD before each call to an I2C procedure. That will also tell you where things went wrong. The other advantage of timeouts is if an I2C command times out, you can try it again and again just in case it was a one time fail. Most of the I2C errors I've dealt with are bad connections to the sensor chips. Sometimes just a nudge can make the connectors fail. I've ended up actually soldering the so-called "solderless" crimp connectors. The other problem is in programming, by not resetting the I2C by issuing "i2c_stop()" after a fail. Usually if it works a few times I go back to trying to bulletproof the connections and checking power to the sensor chip. |
May 20, 2013 by dvdsnyd |
pcbolt, I just recently bought some crimp connectors and a pair of crimping pliers. I have definitely noticed that the connection sometimes are not very reliable. I have had to redo a fair share of cables. I think I am going to focus on getting my code back up and running, and see what kind of issues I begin to have. I'll try to get the connections as solid as I can first. What do you mean by "The other problem is in programming, by not resetting the I2C by issuing "i2c_stop()" after a fail." Thanks for helping me understand by answering all my silly questions! Dave |
May 20, 2013 by pcbolt |
Sometimes the sensor chips on the I2C bus get caught in a "waiting for command or data" state. Usually sending the "i2c_stop()" resets everything to a known state. I would try adding a tiny bit of solder to you connectors. Too much and the pin won't fit in the housing. If you are using ribbon wires, you also have to be careful not to melt the insulator jacket. |
May 30, 2013 by MaxWolfMarrin |
This thread seems the most relevant to what I am trying to do- I would like to make a sound effect device using an external eeprom with the ATtiny85- I saw some code for converting a wave file into 8kbps nibbles, but my question is how to get the data onto the eeprom in the first place- how do I initialize the eeprom with the sound data if it exceeds the memory of the AVR chip? |
May 30, 2013 by pcbolt |
Hi Max - I started a new thread for this topic HERE. This thread is just getting too fat :-) |
November 17, 2013 by photofoo |
Hi I have done some hacking on Noter's 24LC256 I2C code in order to communicate with a DS1307 Real Time Clock. apologize for the long post but just trying to give max info. My hack sort of works but I seem to be off one address location in my data retrieval from the DS1307. I think I have looked too long at the code and probably overlooking something obvious. Trying to pull data from clock into this struct
I get this on LCD Display DS1307 ADDR: 68 31 49 01 17 11 13 03 92 Two minutes later I get: 32 49 01 17 11 13 03 92 Note that the first byte seems to be minutes when I expect Seconds All of the other fields offset by one byte are consistent with the actual time & date Here is the entire hacked file
|
Please log in to post a reply.
Did you know that you can input numbers in binary via a DIP switch, and output them to the LCD? Learn more...
|