PDA

View Full Version : data storage prior to use, whats the best way here?



enigma
- 3rd February 2007, 16:35
Hi All

Suggestions as to the best way to do this.

I`m reading in data from an A/D conversion approx once a second. I need to store these to a total of 20 readings in a way which overwrites the oldest reading as each new reading is added. Should one data element exceed a limit between two values I need to send the stored data as serial output consisting of the 10 values prior to the event and also the 10 values after the event.
Has anyone ever done anything similar?.

Cheers Pete

sayzer
- 3rd February 2007, 19:00
Questions:

1. "...total of 20 readings" : Does it mean a period of 20 seconds?

2. "...Should one data element exceed a limit between two values": Does this mean that you have a lower limit and an upper limit? What are they? constant numbers like X and Y?

If yes, when your readings are in between these two limits, no action is taken. But once one of your readings are out of these two limits,say range, whether lower or higher, then you want to send the values as you described.

3. What if the readings suddenly come back to the acceptable range just after your readings started to be outside the limits? Do you need to stop taking 10 readings?

Here is a simple example:
<img src="http://www.picbasic.co.uk/forum/attachment.php?attachmentid=1360&d=1170528979"" >

mister_e
- 3rd February 2007, 19:00
you could store them in 2 different array variable

sayzer
- 3rd February 2007, 19:52
Here I have a code for you written in quick thinking.
It should work out, if not, should give you some ideas.
As Steve mentioned, there are actually two different arrays in this code but one is hidden in for loop.




'...Do the port registers, ADC settings etc. here...

A VAR BYTE 'A loop variable.
Z var byte 'Dynamic end point for loop.
Flag var byte 'The array address where we hit the out of limit.
Dumpy VAR WORD 'A dummy variable.
X con 13 'Lower limit
Y con 25 'Upper Limit

ADCData VAR WORD[31]
Serpin VAR PORTC.0


Start:
Flag = 100 'Default value.
Z = 20 'Normally, initial reading is 20 times.


FOR A = 1 TO Z 'Take Z times readings.
ADCIN 0,adcdata[A]
IF ADCDATA[A] < X OR ADCDATA[A] > Y AND Flag = 100 THEN
Z = 30
Flag = A 'Store the array variable where we hit the reading out of the limit.
ENDIF '[ why Z = 30 ? : IF we have a reading out of the limits,
PAUSE 1000 'Wait for 1 second. '...we then add 10 more locations to our array
NEXT A '...so that we can add extra 10 readings after the event.]

'Now, readings are complete.

IF Z = 30 THEN 'if Z = 30 that means we had an "out of limit" reading.
FOR A = (Flag-10) TO (Flag+10) 'Flag is the point where we hit the first out of limit reading.
'Serout your values here.
'You need to send your values starting from -10 AND +10 of array location using Flag value.
Dumpy = ADCData[A]
SEROUT Serpin,4,[Dumpy.LowByte,Dumpy.HighByte]
NEXT A
ENDIF


GOTO Start

Dave
- 3rd February 2007, 20:47
enigma, Why do you need to store 20 readings of history if you only need to send 10 past readings after the event?

Dave Purola,
N8NTA

SteveB
- 4th February 2007, 02:06
I`m reading in data from an A/D conversion approx once a second. I need to store these to a total of 20 readings in a way which overwrites the oldest reading as each new reading is added. Should one data element exceed a limit between two values I need to send the stored data as serial output consisting of the 10 values prior to the event and also the 10 values after the event.

Pete,
You are looking for a ring or circular buffer. Sayzer gave you a bit of code to look at. Here is another approach.

;-------------------------
; PIC16F877A
High_Limit CON 196
Low_Limit CON 64

ADC_Value VAR BYTE ; Latest ADC Reading
Buff_Pointer VAR BYTE ; Current spot in Buffer
Buff_Len VAR BYTE ; Number of Values in Buffer
History VAR BYTE[10] ; Last 10 ADC Readings
Remaining_Vals VAR BYTE ; Number of Values left to send
Counter VAR BYTE
; Initialize values
Remaining_Vals = 0
Buff_Pointer = 0
Buff_Len = 0

Main:
ADCIN 0,ADC_Value

IF (ADC_Value > High_Limit) OR (ADC_Value < Low_Limit) THEN ; Check Limits
; Out-of-limits
IF Buff_Len > 0 THEN ;There is something in Buffer
; Send out Contents of Buffer Before Current Value
FOR Counter = 0 TO Buff_Len - 1
IF Buff_Pointer + Counter > 9 THEN
HSEROUT [History(Buff_Pointer + Counter - 10)] ; Output Value
ELSE
HSEROUT [History(Buff_Pointer + Counter)] ; Output Value
ENDIF
NEXT Counter
Buff_Len = 0 ; Reset Buffer
Buff_Pointer = 0
ENDIF

HSEROUT [ADC_Value] ; Send out current Value
Remaining_Vals = 10 ; Set count so next 10 Values will be sent

ELSE
' Within Limits
IF Remaining_Vals > 0 THEN ; post out-of-limit values to be sent
HSEROUT [ADC_Value] ; Send out current Value
Remaining_Vals = Remaining_Vals - 1
ELSE
;Add Value to Buffer
Buff_Len = Buff_Len + 1
IF Buff_Len = 11 THEN
Buff_Len = 10
Buff_Pointer = Buff_Pointer + 1 ; Move Pointer to 2nd oldest
If Buff_Pointer = 10 THEN Buff_Pointer = 0 ; Wrap Around
ENDIF
IF Buff_Pointer + (Buff_Len - 1) > 9 THEN
History(Buff_Pointer + Buff_Len - 11) = ADC_Value
ELSE
History(Buff_Pointer + Buff_Len - 1) = ADC_Value
ENDIF
ENDIF
ENDIF
GOTO Main

It will check each reading. If it is out of limits, it will send the contents of the buffer (which could be less than 10 if the out of limits occurs before 10 readings), then send the current ADC readings, then send the next 10 readings.

If, while sending the 10 readings after an out of limit condition, it will reset the counter and send 10 more readings.

It is set up to use HSEROUT, so you will have to change that as neede to suit your purpose. Also, you will need to setup the ADCIN as well.

You should have plenty of material to get this going.

HTH,
SteveB

enigma
- 4th February 2007, 14:31
Hi All


Firstly thanks for all the suggestions, I think I have something to go on here. To clarify the points raised:

Its approx 1 reading every seconds, actually I`m making two readings of an X and Y output of an accelerometer but for these purposes lets treat it as a single reading as its just generating two data readings which its easy to store as pairs.

The readings are a value between 0 and 1024 as expected from 10 bit A/d. The zero output is 512, and +/- 1G approximates to either 532 or 492 stored in a word variable.

So I read and store these values until its less than 492or greater than 532 (this range can alter but for the moment lets assume its this). At that point I trigger an output and then to send serially the 10 prior readings and 10 post readings from the trigger. Nothing is ever sent serially unless the limit condition fails. I am however also writing the readings once a second to a display regardless of limits but thats a separate process.

After this I wait for a period, around a minute before I start the process again.


Cheers Pete