PDA

View Full Version : working with external memory



malc-c
- 10th September 2010, 15:50
Hi,

I'm looking at using an external Eprom (something like an 24LC256) to store time and temperatures, which can then be downloaded to a PC application via the serial port. However I need some pointers from you guys.

I currently have a RTC chip from which I use just time information at present.

I2CRead SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour,RTCWDay,RTCDay,RTCMonth,RTCY ear,RTCCtrl] ; read DS1307 chip

I then have the following routine to give me Hrs and Mins which I use in parts of the program where I need to compare the current time to pre-sets



timeH=(RTCHour>>4) 'convert the BCD format of the hours register and store in variable timeH
timeH=(timeH &$03)*10
timeH=timeH+(RTCHour&$0F)

timeM=(RTCMin>>4)
timeM=(timeM &$07)*10
timeM=timeM+(RTCMin&$0F) 'convert the BCD format of the mins register and store in variable timeM


Temperatures are read from a DS18B20 (4 off) and simply end up and an array variable - Temperatures[0] - [3], and are represented by a 3 digit decimal, so 234 would be 23.4C.

There should not be much change in the temperatures as this is for my thermostat project, so the logging interval doesn't need to be too frequent (as in realtime !) probably once per minute, maybe once every 5 min - depending on the amount of data I could store in the chip. So I guess I need to use something like



IC2write, address, timeH, timeM, temperatures[0], temperatures[1], temperatures[2], temperatures[3]


I would then have a "download data" button on the PC application which would send something like "D" to the RS232 port and then once detected jumps to a subroutine where it then reads the chips contents, sends them as a data stream back to the PC application, so a single data line would probably look like


1230300302297289


So sending that via serial


Hserout [dec TimeH, TimeM]
Hserout [DEC3 Temperatures(0)]
Hserout [DEC3 Temperatures(1)]
Hserout [DEC3 Temperatures(2)]
Hserout [DEC3 Temperatures(3)]


This is where I get stumpped !

I would probably need to use some form of delimiting character to indicate the end of a data line, or could simply send a long data stream and let the software start a new line after every 16 digits. Either way I would need to loop the above in some way for each line of data. I would also would like the memory contents cleared after the "log file" has been downloaded, so would need suggestions on how to do that.

I would welcome your ideas, and if possible some sample code.

aratti
- 10th September 2010, 16:50
I don't think one byte is enough to store your temperature . with one byte the maximum reading will be 25.5 degree then 25.6 will make your byte overflow to 0.

Al.

malc-c
- 10th September 2010, 16:52
Sorry, should of mentioned, they are words



Temperatures VAR WORD[4]
Temp1 VAR Temperatures[0]
Temp2 VAR Temperatures[1]
Temp3 VAR Temperatures[2]
Temp4 VAR Temperatures[3]


with bytes for time



TimeH var byte
TimeM var Byte

malc-c
- 10th September 2010, 18:14
One alternative (assuming I can find it in the UK) is this

http://www.jianpingusa.com/datasheet/JP%20Module%20Instruction.pdf

Basically an SD/MMC card reader that communicates via serial :)


Ouch - $50

mackrackit
- 10th September 2010, 18:34
Have you seen this?
Need an 18F with a fair amount of memory. 18F2550 works great with it.

malc-c
- 10th September 2010, 19:01
Have you seen this?
Need an 18F with a fair amount of memory. 18F2550 works great with it.

Seen what Dave .... :confused:

Currently using an 18F4580 - The current version of my code compiles to around 24K

mackrackit
- 10th September 2010, 19:23
http://melabs.com/resources/samples/pbp/sdfs3.htm
It was a hidden link :rolleyes:

malc-c
- 10th September 2010, 20:32
http://melabs.com/resources/samples/pbp/sdfs3.htm
It was a hidden link :rolleyes:

LOL - yeah right !!

Interesting and seems a simple project... the only thing is that I don't have 6 pins available, at least not without changing the package to a 44 pin package and even then I still think it would be tight or short of a pin.... not to mention the re-design of the PCB :eek:

Thanks for the link though...

I've opted to do the logging in the PC application, for now :)

Dave
- 11th September 2010, 22:16
malc-c , Why on earth would you need 6 pins for external eeprom storage? I currently use 4, 24LC1025's to store data for a little over a month @ 1 minute intervals. The data is stored for approx. 750 minutes a day during daylight. The data stored is 16 bits per variable of: pointer,azminuth,elevation,up,down,east west and status words. The amount of data you are trying to store isn't much. besides, I only use 2 pins for the 4, 24lc1025's giving me a little over 4 Migabits...

Dave Purola,
N8NTA

mackrackit
- 11th September 2010, 22:26
Six pins for an SD card.

BrianT
- 12th September 2010, 01:16
Your suggested data output string needs comma delimiters since you cannot be certain of the character length of each value. You could serout each word as Dec3 mYvAR to force them all to a known length but that can complicate the end use of the data. If you comma delimit each value, terminate the line with <cr><lf> and label the file as MyLog.csv then Excel can open the file and graphing the data is a breeze.

I use word variables for TemperatureLogged = 1000 + (10*MeasuredTemperature) and depending on actual temperatures the number can have two or three digits. By adding 1000 I can send negative values without needind a sign bit. e.g 890 means -1.1C and 1234 +23.4C

My data loggers record date & time, temperature, pressure, accelerometers for an activity indication and heart rate. I log the data to M25P128 serial memory chips.

HTH
BrianT

malc-c
- 12th September 2010, 12:27
Brian, thanks for the input.

As Dave has already mentioned, the 6 pins were for the SSD card shown in his link.

I gather that using I2C type memory chips I could use the same CLK and DTA lines that hook up to the DS1307 RTC chip, and just give the memory chip a different address, so that would save me a couple of pins?

Given that all I really want to store is date, time, temp1, temp2, temp3, temp4 probably every two minutes what would be the ideal memory chip to get to hold a minimum of 7 days worth of data (if longer so much the better). I was also thinking of a rolling data process, so that when full it would simply delete the oldest data to make space for the most current set, ie so it retails the past 7 days (or what every it amount to) worth. Any suggestions of code to do this would be welcome.

Ruben Pena
- 23rd September 2010, 23:49
Brian:
Do you can share the read routines for the M25P128 ?. I am using the M25P16 but my reading
is a little erratic.
Thanks in advance...
Ruben de la Pena V.

BrianT
- 24th September 2010, 01:04
Hi Ruben,

Try this. I have several methods for reading and writing to the M25Pxxx family. All work but the ones not commented out are the fastest. In some infrequent calls I have left the slow routines in place as they don't add any significan time to the download of data from the M25Pxxx memory.

[code]
ReadFromM25P128:
memclk = 0 'data change point
memclk = 1 : reply.7 = memq : memclk = 0
memclk = 1 : reply.6 = memq : memclk = 0
memclk = 1 : reply.5 = memq : memclk = 0
memclk = 1 : reply.4 = memq : memclk = 0
memclk = 1 : reply.3 = memq : memclk = 0
memclk = 1 : reply.2 = memq : memclk = 0
memclk = 1 : reply.1 = memq : memclk = 0
memclk = 1 : reply.0 = memq : memclk = 0
'takes 50 uSecs per character
debug #reply, ", " 'Debug takes 6.7 mSecs
return


RDSRWIP: 'reads the Status Register - waits for WIP bit to go low
'Data from M25P128 changes on fall of clock so sample on rise of clock.
code = $05 'Read Status Register code
gosub sendcode
WIPclr:
for shift = 7 to 0 step -1 'read 8 bit reply
high memclk : reply.0[shift] = memq : low memclk : pauseus 1
next shift
if reply.0 = 1 then wipclr
return

SendCode: 'Serial MSB first sends the CODE byte from PIC to M25P128
TRISE.0 = 0 : PortE.0 = 0 : memclk = 0 'MemClk
TRISC.0 = 0 : PortC.0 = 0 : memd = 0 'MemD
' for shift = 7 to 0 step -1 'send MSB first
' memclk = 0 : memd = code.0[shift] : memclk = 1: pauseus 1 : memclk = 0
' next shift 'this is SLOW ~500 uSecs per character
memclk = 0
memclk = 0 : memd = code.7 : memclk = 1
memclk = 0 : memd = code.6 : memclk = 1
memclk = 0 : memd = code.5 : memclk = 1
memclk = 0 : memd = code.4 : memclk = 1
memclk = 0 : memd = code.3 : memclk = 1
memclk = 0 : memd = code.2 : memclk = 1
memclk = 0 : memd = code.1 : memclk = 1
memclk = 0 : memd = code.0 : memclk = 1
' much faster, takes about 52 uSecs per character
return
/[code]

You can see here I have several methods for reading from the M25P128. The decrementing loop "... for shift = 7 to 0 step -1..." works and is simple BUT it takes about 500 uSecs per character.

HTH
BrianT

Ruben Pena
- 24th September 2010, 21:08
Brian:
Thanks for your fast response...
I am reading wav files stored in the M25P, and using this to send the address:
cs1 = 0 'SEND COMMAND AND ADDRESS
SHIFTOUT MOSI,SCK,1,[$03\8] 'read command $03
SHIFTOUT MOSI,SCK,1 ,[PAGE.BYTE1\8,PAGE.BYTE0\8,00\7]'addr 000000
I send the command and then the 24 bits address,but note in the last address byte I send
only 7 bytes. then I go to a loop to read the data and send it to the port to convert to
analog with a R2R network,until I find a special end of file char to stop the reading.
If I send the 8 bits, I get shifted data. With 7 bits I got the correct data and I can identify
the end of file byte. I do not know why.
the read routine is this:
ASM
MOVLW 8
MOVWF _CNT
SIGUE
BTFSS _MISO ;MOV BIT TO CHR,0
BCF _CHR,0
BTFSC _MISO
BSF _CHR,0
BSF _SCK ;READ AFTER SENDING THE CLOCK
RLF _CHR,1
BCF _SCK
NOP
NOP
NOP
NOP
NOP
DECFSZ _CNT,1
GOTO SIGUE
ENDASM

Am I missing some previous command to set up the chip for reading..?

I will test your routines to see if I got an improvement.
Thanks again...
Ruben de la Pena V.

Ruben Pena
- 24th September 2010, 23:35
Brian:
I only use the read routines for a little wav player. I use a 16F1826 at 16 mhz.(Internal Osc).
The working routines:
'************************************************* *****
TESTREAD:
CS1 = 1
PAUSEUS 200
CS1= 0
code = 03 'read command
gosub sendbyte
code = 0 'higher add.
gosub sendbyte
code = 00 'high add.
gosub sendbyte
code = 0 'low add.
gosub sendbyte
nextread:
GOSUB READBYTE
SEROUT2 LED,32,[HEX2 REPLY," "]
'PORTB = REPLY
PAUSEUS 50
GOTO nextread

sendbyte:
sclk = 0
sclk = 0 : memd = code.7 : sclk = 1
sclk = 0 : memd = code.6 : sclk = 1
sclk = 0 : memd = code.5 : sclk = 1
sclk = 0 : memd = code.4 : sclk = 1
sclk = 0 : memd = code.3 : sclk = 1
sclk = 0 : memd = code.2 : sclk = 1
sclk = 0 : memd = code.1 : sclk = 1
sclk = 0 : memd = code.0 : sclk = 1
return
Readbyte:
sclk = 0 'data change point
sclk = 1 : reply.7 = memq : sclk = 0
sclk = 1 : reply.6 = memq : sclk = 0
sclk = 1 : reply.5 = memq : sclk = 0
sclk = 1 : reply.4 = memq : sclk = 0
sclk = 1 : reply.3 = memq : sclk = 0
sclk = 1 : reply.2 = memq : sclk = 0
sclk = 1 : reply.1 = memq : sclk = 0
sclk = 1 : reply.0 = memq : sclk = 0
return
'*********************************************
I conected the M25P in port A and send the data to the PortB.
It works up to 48 Mhz(audio), but I am using it at 16 KHZ.
The M25P does not need anything aditional to work...
Greetings and thanks again...
Ruben de la Pena V.