News:

Let's find out together what makes a PIC Tick!

Main Menu

ARRAY Filling Question?

Started by Craig, Sep 11, 2021, 07:45 PM

Previous topic - Next topic

Craig

Pic 18F47K40 @ 64Mhz - Positron 8 Ver, 4.0.0.8

Hello

I am trying to think of the best and fastest way to fill an ARRAY on the Fly, What I mean is that I have two Sensors on a constantly Moving motorized Gimbal taking various readings. What I have done is use a Select..Case loop to look at the Correct slot Range and then use a Counter to load the readings into the WORD ARRAY, then jump out of that slot and look at the next slot to see if I need to take a Reading in that Range slot?

My Question is how can I Fill a WORD ARRAY up While the Sensor is taking readings in that Slot Range and then jump out of it and look at the next slot?
I don't want to keep it in the slot and miss other readings while the INC Counter is trying to fill up the ARRAY "Until ABCnt =  9".
If in the First Case..Select Loop eg. 35 to 39, If there are only 2 Reading to be taken in that Slot, I Do NOT Want to wait until the INC Counter "ABCnt" gets to 9 to Jump out of the Loop and look at the next Case .. Select Loop Eg. 40 to 45!

There are 0 "Zeros" Coming out of the Sensor when it is Not Detection an Object so I need a Way to Scan the ARRAY and find the end of the ARRAY with or without relying on a Null Terminated Zero "0". If there are valid Data entries in the Array, I can then find the Valid Length of the Array and load the Valid data into a "Signed Word Variable" where I can find the "Middle" or Average Reading for the valid data found in the Array?

What I have done is read the Values out of the Array and Divide it by the Array Size to get the Average but, this is not as accurate as it could be as some slots can capture much more Data than others. I need a Way to Detect the Filled Array size of Valid Data and then use that number to Divide back into the Array Value to find the Average Reading?

I can then also ignore readings that are too small and have a much more accurate Reading Average by using a much Larger Array to Capture the Data Coming in.   

What would be a better and more practical way of doing this?
Any ideas would be much appreciated!
 
Kind Regards
Craig

A Small Sample of Code to demonstrate What I am Looking at in the various Reading Ranges!!

'-------------------------------------
Loop_H:
 
 ABCnt = 0                           

Select LDist

 Case 35 To 39
 Repeat
  LArray1[ABCnt] = LDist
  DArray1[ABCnt] = Dis 
  Inc ABCnt
 Until ABCnt =  9
  If ABCnt = 9 Then ABCnt = 0


 Case 40 To 45
 Repeat
  LArray2[ABCnt] = LDist
  DArray2[ABCnt] = Dis 
  Inc ABCnt
 Until ABCnt =  9
  If ABCnt = 9 Then ABCnt = 0

 
 Case 46 to 50
 ....
 ......
 .......

Case 51 to 60
 ....
 ......
 .......


End Select

Return
'------------------------------------




Craig

#1
Hi

I am sitting with a Clients project which I must get done but am battling with this issue! Can someone Please see if they can advise me on this?

Does Anyone know how I can Load Data into an ARRAY and then JUMP Out of the CASE...SELECT Loop before waiting to run through the INC Counter to step out of that CASE..SELECT Loop as I described in the Previous Post.

The Problem is that the Sensor is looking at various objects of differing Sizes at varying Distances so I need to find a way to take a few readings (As The Sensor Detects that Object) and load them into an ARRAY and then when the Sensor sees the next object jump out of that CASE..SELECT Loop and into the Next to take some more readings and so on going Back and Forth Through the Various CASE..SELECT Loops until done, If I could find a practical way of using the BREAK Command in the ARRAY Filling Function to STEP Out of it when the Sensor has taken it's Relevant Readings.

Maybe there is a better way of doing this instead of using a CASE...SELECT Loop With a REPEAT.....UNTIL Function?

At the end when everything is done I can then go back and analyses the ARRAY's using the BOUND Command and pull the relevant data out.

Dim LArrayA [60]             As Word
Dim LArrayB [60]             As Word
Dim LArrayC [60]             As Word
.........etc.
 
I want to load data into LArrayA [60], say on the first reading positions:  LArrayA#0, LArrayA#1 ,LArrayA#2 ,LArrayA#3 , as an Example, then if an object is later seen in that Same CASE...SELECT Range
then Load the next lot of data into Positions LArrayA#4, LArrayA#5, LArrayA#6 depending how many readings are being taken by the Sensor, These Array Elements will constantly vary in size as the sensor
sees different size objects!   

Any Help is very much appreciated.
Kind Regards
Craig
 

charliecoutas

It sounds as though you need to break out of the Select Case loop because something of higher priority needs it. What about using interrupts, if this is possible in your design?

I just did a telephone pulse-dialling system where all the pulse generation was done using interrupts, works a treat.

Charlie

top204

As Charlie suggests, you could do it within an interrupt so that the scan values are held in buffer arrays, then placed in their working arrays when things are stable.

Or within a state-machine mechanism so that the sensor scans are always carried out, but the indexes to the arrays are kept in sequence. No individual loops and no delays.


Stephen Moss

Are you sampling LDist and Dis outside the loop for inside it before Select-Case? As that could affect if ADCnt is always rest to 0 or not. Either way I don't think
Case 35 To 39
 Repeat
  LArray1[ABCnt] = LDist
  DArray1[ABCnt] = Dis
  Inc ABCnt
 Until ABCnt =  9
  If ABCnt = 9 Then ABCnt = 0
will work, wouldn't that just fill all 9 array elements with the same value?


Sounds like you are trying to create a sort of 2 dimensional array (Dimension X is Size Range, Dimension Y is Range value). I have not tried it but I think perhaps something like this...
'Start_Loop
Read LDist

Select LDist
 Case 35 to 39
   Case35(LDist, Dis)

 Case 40 to 45
   Case40(LDist, Dis)
EndSelect

'End_Loop

Goto Main:

Proc Case35(ByVal LDist As Word, ByVal Dis as Word) 
LarrayA[xA] = LDist
DarrayA[xA] = Dis
inc xA
If xA > 60 then xA = 0
End Proc

Proc Case40(ByVal LDist As Word, ByVal Dis as Word) 
LarrayB[xB] = LDist
DarrayB[xB] = Dis
inc xB
If xB > 60 then xB = 0
End Proc

I have used a loop to get LDist data but you could alter that to an interrupt or other method as necessary. Unlike the method above there is no loop to fill the array, instead it fills it one element at a time so should respond better to changes in LDist.

Could not a possible Solution to "There are 0 "Zeros" Coming out of the Sensor when it is Not Detection an Object so I need a Way to Scan the ARRAY and find the end of the ARRAY with or without relying on a Null Terminated Zero "0"." be to not add the data to the array if it is a "Zero". That way you could scan the array until until it contains a 0, assuming.
The problem with that or any other approach looking for how many elements are in the array by examining the contents of the array using the contents of the array is that it only works if you clear the entire array contents to the "end of data" value at regular intervals otherwise you just cyclically overwrite the existing data and will never find the "end of data" value.

However, if using Procedures as in my example you could return the array index value (xA, xB) as a Result and therefore know how many elements data elements are in the array.

Craig

Thank you Charlie,Les and Stephen for your Help and advice it is very much appreciated!

I will look at using an Interrupt if possible or try and manage it better with a State machine but, I was trying to find a better way to load the data into the Arrays.
I am trying to make a sort of Two Dimensional Array as you are Suggesting Stephen.
I have Two Sensors That are both taking Readings on Two Axis's and are both married to each other.
When the one takes a reading of the X-Axis so does the other on the Y-Axis.
I use this data of both the sensors captured at the same time to determine the X and Y AX-eez at each specific point.

Thank you Stephen for your Code example it looks far more practical than what I am doing and I will start to implement some changes.

Kind Regards
Craig

Stephen Moss

In my example I passed parameters to the Procedures, if you make the LDist, Dis, xA, xB variable etc globals then you wouldn't have to pass parameters to/from them and you could use subroutines instead of Procedures if you prefer those.

Thinking about it, it may be better if the they were globals as at some point you might want to reset xA, xB etc, if using a loop to get the samples as in my example a good point to reset them would be just before entering the loop.
Then at the end of the loop the current xA, xB values can be used as the upper limit for the respective For-Next loops in the get lowest sample example I posted in reply to that question, and/or as the divider if finding the average length which is useful if you only want to process the samples taken in the last loop as opposed to the last Z samples (where Z = the array size) taken if cyclically filling the array (If xA > 60 then xA = 0).

Craig

Thanks Stephen

I think in this instance it would be better If I kept them as globals as they are used in other Loops.
I like your idea of resetting them (xA,Xb etc) before entering the loop and using them at a later stage.

Thank you Stephen for your kindness and Help, I appreciate it very much.

Kind Regards
Craig