External eeprom read/write problem

#1
I'm blundering my way through writing data to a 24LC256 eeprom then retrieving the data but finding I have corruption issues.
The data is currently sampled by a 20M2 from two sources and written in real time into the eeprom as two 'tracks' of data.
Track 1 data (used to control a servo motor) originates with a potentiometer which is read then scaled to keep within servo control range. This scaled value is recorded into eeprom address 1. Next time it is sampled it is recorded to eeprom address 5, subsequently to addresses 9, 13, 17, 21... etc. Recording this Track 1 data and replaying it to a servo works just fine.

Track 2 data (used to capture control code numbers in the range 0 = 255) is received from time to time, through an Interrupt/serin function connected to a control bus (called TSB2) to which various bits of Picaxe-operated equipment are connected. When a non-0 code number is detected on this TSB serial control bus this number is written into Track 2 of the eeprom at addresses 2, 6, 10, 14, 18, 22... etc. When no control code number is being received a default 0 value is recorded into Track 2 addresses. On playback of Track 1 data to the servo the Track 2 code numbers are outputted back to the TSB2 bus to trigger some of the other pieces of equipment. This Track 2 playback function is working just fine.

THE PROBLEM I am stumped by is that if I then go back and re-record the Track 1 servo data (eg. to refine the servo movement) the Track 2 data becomes corrupted, with the occasional 0 -255 code numbers previously recorded now being replaced by a constantly changing stream of numbers in the tens of thousands range.

(Please ignore provision in the posted code for Tracks 3 and 4 which essentially will work identically to the Track 1 pot/servo arrangement... it was only as I started to introduce and fine-tune the Track 3 write/record and read/replay coding that I ran into this mini-disaster which no end of trial and error, reading, searching, strong tea, etc over several weeks has helped resolve.)

Currently I am only using enough eeprom to record about 15 seconds of data, it should be capable of recording a couple of minutes or more once I get things running. The occasional large pauses in the code are a way of synchronising the record and playback processes so the real-time data as replayed more or less matches the real time data as captured. The 'Mimic' and 'Startpos' functions built into the code are to assist the operator and should have no bearing on this issue. Ditto the detection of operator control pushbuttons via a resistor ladder and serial outputting to an indicator LED controller (IC4).

If anyone has time to help I'd appreciate it hugely and will check this thread several times a day to answer any questions or clarify what I'm trying to do, etc.

I've had to put the code in an attached file as is seems this message plus the length of the code is to long for the Forum system to accept.

Jay.
 

Attachments

hippy

Technical Support
Staff member
#2
Looking at your code it is not clear exactly what data you are writing to your EEPROM. From -
Code:
readadc C.7, b4
w3=150*b4/255+75
servopos B.1, w3
hi2cout w5, (b6, b7)
You appear to have four tracks of byte data but are writing word values ( as two bytes ) per track.
 

AllyCat

Senior Member
#3
Hi,

I have to confess that I've not looked at your code, as I don't fancy wading through 61k Bytes of Program Code. ;)

However, a well-known "gotcha" when using these EEPROMs is that their memory map is "paged": If you try to write a series of bytes past the end of a page, then they are wrapped back into the start of the page. I believe the page size of the 24LC256 is 64 bytes.

You appear to be writing bytes at some odd-numbered locations and your comment that you sometimes read "values in the tens of thousands range " suggests that you are using (some) word values? Therefore, your data sometimes might be crossing a page boundary.

For now, I suggest writing the data at simple "power of two" addresses (e.g. multiples of 4 or 8, etc.) to avoid the risk of crossing any page boundaries. If that cures the problem, then you will know that you need to careful with the way the data is mapped into the memory.

Cheers, Alan.
 
#4
Hi guys, thanks for your prompt replies! I'm very new to eeprom stuff and have just scaled up some basic trials I did which seemed to work ok... but maybe those early successes were only the result of ignorance disguised by dumb luck!

HIPPY:
In my early fumbling attempts with eeproms I seemed to have very patchy success writing then reading data as words. But things seemed to work much better when I treated each piece of data when writing or reading as two bytes instead of one word. At the time it did seem an odd thing to have to do but I could 'sense' a kind of logic to it akin to sending a string of bytes when using i2c. Perhaps this misled my skimpy understanding of how this eeprom communication process works?
In the example you single out the data I am attempting to write is an ADC value 0 - 256 (b4) which is then scaled to confine it within my servo range 75 - 225 (w3). This scaled value w3 is then applied to the servo and then written into the next chosen eeprom address (w5) as two bytes (b6, b7).
As the programme runs, in either recording or replaying mode, eeprom address w5 is incremented. Eg. when recording onto track 2 the programme first reads and displays (via a servo) already recorded data from eeprom first track 1 address (#1) It then writes either any received TSB control code number or a default of 0 into first track 2 address (#2) then reads and displays track 3 (#3) and then track 4 (#4). Then it cycles through again, displaying next track 1 address (#5), writes into the next track 2 address (#6), then reads and displays track 3 (#7) and track 4 (#8) then cycles through again track 1 (#9), track 2 (#10), track 3 (#11), track 4 (#12), track 1 (#13), track 2 (#14), track 3 (#15), etc, etc, etc,.

ALLYCAT/ALAN:
I can understand you glazing over at the amount of code, my eyes are permanently glazed from searching through it (the most complex code I've ever written, and I haven't written all that much) again and again and again to try to figure out what might be causing my problem.
In the back of my mind I did wonder at some stage about the page aspect (which I Ioosely understand - I think) but as I am just sending a single word (albeit as two bytes, which I see Hippy is hinting may be an odd/wrong thing to do) to a single address at a time I felt ok dismissing page considerations which seemed to relate to writing a string of words all at once.
I can see what you are exploring with your 'power of two' thought, that providing more space for each word of data would make any overflow way less likely and therefore point to what the issue might be. I'll try that this evening (NZ time).

Tks guys!

J.
 
#5
Hi guys, thanks for your prompt replies! I'm very new to eeprom stuff and have just scaled up some basic trials I did which seemed to work ok... but maybe those early successes were only the result of ignorance disguised by dumb luck!

HIPPY:
In my early fumbling attempts with eeproms I seemed to have very patchy success writing then reading data as words. But things seemed to work much better when I treated each piece of data when writing or reading as two bytes instead of one word. At the time it did seem an odd thing to have to do but I could 'sense' a kind of logic to it akin to sending a string of bytes when using i2c. Perhaps this misled my skimpy understanding of how this eeprom communication process works?
In the example you single out the data I am attempting to write is an ADC value 0 - 256 (b4) which is then scaled to confine it within my servo range 75 - 225 (w3). This scaled value w3 is then applied to the servo and then written into the next chosen eeprom address (w5) as two bytes (b6, b7).
As the programme runs, in either recording or replaying mode, eeprom address w5 is incremented. Eg. when recording onto track 2 the programme first reads and displays (via a servo) already recorded data from eeprom first track 1 address (#1) It then writes either any received TSB control code number or a default of 0 into first track 2 address (#2) then reads and displays track 3 (#3) and then track 4 (#4). Then it cycles through again, displaying next track 1 address (#5), writes into the next track 2 address (#6), then reads and displays track 3 (#7) and track 4 (#8) then cycles through again track 1 (#9), track 2 (#10), track 3 (#11), track 4 (#12), track 1 (#13), track 2 (#14), track 3 (#15), etc, etc, etc,.

ALLYCAT/ALAN:
I can understand you glazing over at the amount of code, my eyes are permanently glazed from searching through it (the most complex code I've ever written, and I haven't written all that much) again and again and again to try to figure out what might be causing my problem.
In the back of my mind I did wonder at some stage about the page aspect (which I Ioosely understand - I think) but as I am just sending a single word (albeit as two bytes, which I see Hippy is hinting may be an odd/wrong thing to do) to a single address at a time I felt ok dismissing page considerations which seemed to relate to writing a string of words all at once.
I can see what you are exploring with your 'power of two' thought, that providing more space for each word of data would make any overflow way less likely and therefore point to what the issue might be. I'll try that this evening (NZ time).

Tks guys!

J.
I think you guys' suggestions and questions have pointed me towards where I got all mixed up regarding eeprom addresses, bytes, words, etc. I'm currently re-doing how I assemble data for writing into the eeprom addresses and being more thoughtful regarding how I assign addresses to 'tracks', and already it's looking and feeling much better. Will report back when there is more to report!
 

hippy

Technical Support
Staff member
#6
In the example you single out the data I am attempting to write is an ADC value 0 - 256 (b4) which is then scaled to confine it within my servo range 75 - 225 (w3). This scaled value w3 is then applied to the servo and then written into the next chosen eeprom address (w5) as two bytes (b6, b7).
You could do that all with byte variables as maths allows 16-bit calculations and only needs to be 255 or less when written to the byte the value is stored in. This should work ...
Code:
readadc C.7, b4
b6 = 150*b4/255+75
servopos B.1, b6
hi2cout w5, (b6)
 
#7
Thanks guys, my problem seems to have been more or less along the lines of where you both were asking questions and making suggestions. I have tidied up the mix of bytes and words etc. and everything is running now as I had hoped. The lesson learned is to be much more careful and knowledgeable when shuttling data between byte and word variables, both within the PIC and also to and from the eeprom.

I really do appreciate your support!

Jay
 
Top