reversing and comparing 'Dynamic arrays' preform action if mismatch

Hi all,

first i dont want to be the ‘subject’ of cross-posting — but i got some help in the sensor forum, but it’s now only about programming so I thought id post a new topic here, Ill update the other topic with a link to this post. Link to old post http://forum.arduino.cc/index.php?topic=186279.0

So, im using a distance sensor, since i want to scan 180° i got some great tips of mounting the sensor on a servo, reading the sensor values to an array.

Ill quote 'groundfungus ’

‘Scan the ranges into an initial array. Save that array to oldRanges. After the next scan, newRanges, you can compare the arrays for changes. Be aware that you can’t scan very fast. Look at the servo specs and they should have a time to slew 60°. Usually on the order of 200mS so 180° is a minimum of 600mS without time to stop and get a range, ideally.’
So i want to scan from 0 to 180 for oldRanges then reverse the oldRanges array and start collecting (180 to 0) newRanges so the array indexes match. Before the next scan, copy the newRanges to oldRanges (overwrite the old oldRanges) and collect a new set of newRanges.

So if oldRanges and newRanges are different at the servo pos of 100° the servo will stop at that position and the sensor will scan, when the object is gone (without range) it the servo will start rotating again. The sonar is output as ‘sonarValue’

So i need some guidance setting up the writing to the oldRanges & newRanges array comparing revering and comparing it.

When i increased the speed of the servo it only goes to 150°.

Id be most glad for any help!
Best

 #include <NewPing.h>
    #include <VarSpeedServo.h>
 
    VarSpeedServo MyServo;        // servo objects

    #define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
    #define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
    #define MAX_DISTANCE 500 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
    NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

// Declare variables
    const unsigned long distansInterval = 50;
    const unsigned long distansTracker = 10;
    const unsigned long servoTracker = 1;

    int sonarValue;
    int uS;
 
    int servoSpeeds = 30; // sweep speed, 1 is slowest, 255 fastest)
    int servoMinPosition = 0; // the minumum servo angle
    int servoMaxPosition = 180; // the maximum servo angle
 
    unsigned long distansTimer;
    unsigned long distansTrackerTimer;
    unsigned long servoTimer;



// End vars 
 
  void setup() 
  {  
    Serial.begin(115200);    
     distansTimer = millis ();
     distansTrackerTimer = millis ();
     MyServo.attach(9);       
     MyServo.slowmove(servoMinPosition,servoSpeeds) ; // start sweeping from min position
  }

  void runServo()
  {
    if( MyServo.read() == servoMinPosition)
  {
      MyServo.slowmove(servoMaxPosition,servoSpeeds) ; 
    }       
    else if( MyServo.read() == servoMaxPosition)
  {
      MyServo.slowmove(servoMinPosition,servoSpeeds) ; 
    }    

  }
  
/* //////////////
 Update sensor every 50 ms 
*//////////////
  void distansIntervalFunction ()
  {
    unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
    sonarValue = uS / US_ROUNDTRIP_CM;
    distansTimer = millis ();  
  }

/* //////////////
Send to exbee
*//////////////

  void distansTrackerFunction ()
  {
  
  }
 
/* //////////////
START LOOOOP 
*/  
  void loop ()
  {                 
    Serial.println("MILLIS");
    if ( (millis () - distansTimer) >= distansInterval)
  {
// updates the sonar
      distansIntervalFunction ();
    }
    if ( (millis () - servoTimer) >= servoTracker)
    {  
      runServo ();
    }    
  }

So i need some guidance setting up the writing to the oldRanges & newRanges array comparing revering and comparing it.

What does this have to do with "Dynamic arrays"?

/* //////////////
Void LOOOOP 
*/  void loop (){

Knock this shit off right now. Hiding the start of a function after a comment is just plain stupid. Don't do that again.

The curly brace that starts the function doesnotbelongjammedupagainstthefunctionargumentlist, either.

Scan the ranges into an initial array.

Where is this array? Where is the scanning done?

Some reasonable names for your functions would help. The placement of the function in the code, and the way that it is called, defines that the block of code is a function. There is no reason to use Function in the name of a function. Using it is a sure sign that you don't understand what the function does. Which generally means that it is doing to much.

Think about what analogRead() does. It verifies that the pin number is reasonable, determines which pin on the chip you mean to read, and reads that pin. What it does NOT do is convert the reading to a voltage, print to the serial port, send the value via XBee to Jupiter, send the value to the Ethernet card, or a host of other things. It does one thing, and the name of the function clearly reflects what it does.

Your function names should, too.

I don’t see any arrays there, or is that what you are asking about? Maybe Google “C array”.

An array looks like this:

int distance [20];

That’s an array of int type, with 20 elements.

I though that continuously adding numbers to an array ment that it was a dynamic array.

'Hiding the start of a function after a comment is just plain stupid. Don't do that again.' It's a typo from coping the code …
'The curly brace that starts the function doesnotbelongjammedupagainstthefunctionargumentlist, either.'

Please see the updated code with a line break.

'Where is this array? Where is the scanning done?'
This is what i need help with, perhaps i wrote what i needed help with in a complex way.

SO i need help and guidance of how to put all readings from the sensor in to an array (oldReadings) which is later inverted and compared (at servo pos 180°) with an new array (newReadings). At servo pos 0° newReadings is put in to oldReadings and reversed. The process restarts.

So the length of the array is always in relation to the positon of the servo.

If there's a mismatch of oldReadings and newReadings the servo stops and the sonar scans until the object is without of range.

I hope this i more understandable now.

Ahh, so if id put

int distance [20] = sonarValue;

I'd fill distance with 20 elements of sonarValue?

SO i need help and guidance of how to put all readings from the sensor in to an array (oldReadings) ...

I suggest you read a tutorial on arrays, or look at some of the code in the various examples in the IDE which use them. Then post your code if you have problems.

You have a sensor reading, I showed you what an array is, now you just have to combine them.

gerbsi:
Ahh, so if id put

int distance [20] = sonarValue;

I'd fill distance with 20 elements of sonarValue?

No.

I though that continuously adding numbers to an array ment that it was a dynamic array.

No. A dynamic array is one that you can, at run time, change the size of. That is NOT what you want.

A static array has a constant size. You are (supposed to be) taking distance readings at fixed intervals (so many degrees between readings), resulting in a fixed number of values to store in an array. Therefore, a static array IS what you want.

Please see the updated code with a line break.

Now that I've complained about the code, you've changed the code, so now I look like an idiot. Thanks and good luck. I'm out of here.

@OP: If you change things, post them in a new post (except for spelling mistakes which you immediately detect yourself).

Changing a post, after someone comments on it, makes the comments look strange, and people wonder "what is he talking about?". So it is courteous to leave the post alone and post revised code in a new post.

Please see the updated code with a line break.

Now that I've complained about the code, you've changed the code, so now I look like an idiot. Thanks and good luck. I'm out of here.
[/quote]

You must be joking?! As I receive an complaint about the way im learning to program, I also make changes to improve my learning. How can you take that as an insult? As you understand — im new to this and I embrace all help i can get. Or is there something I missed?
Anyway.

Ill try to understand how to update/add elements an array.

Ahh, i really didnt think of that. Im sorry and I just tried to adapt myself.

I think that you are making things too complicated. Why reverse the array and copy it ?

How about something like this ?

declare leftRight array with enough elements to hold the readings
declare rightLeft array with enough elements to hold the readings
set firstSweep true
move servo to left position

start of loop
  for position 0 to 180 in steps of 5
  move servo to position
    read distance
    leftRight[position] = distance
    if firstSweep is false
      if leftRight[position] != rightLeft[position]
      //distance at this angle has changed
      //put actions here
      end of if
    end of if
  end of for
  set firstSweep false

  for position 180 to 0 in steps of -5
    move servo to position
    read distance
    rightLeft[position] = distance
    if rightLeft[position] != leftRight[position]
      //distance at this angle has changed
      //put actions here
    end of if
  end of for
end of loop

This assumes that readings are taken every 5 degrees. During the first sweep the comparison is disabled because there is no previous value.

The sweeps could be made into a function as they are very similar but I suggest that you get the basics working first. The action(s) taken when the distances are different should definitely be a function.

UKHeliBob:
I think that you are making things too complicated. Why reverse the array and copy it ?

Hey, i think this looks super, and i also understand how to construct it! Thanks. Ill be digging into arrays now!

/G

UKHeliBob:
I think that you are making things too complicated. Why reverse the array and copy it ?

How about something like this ?

hi, ive been trying to put this together, still not 100%,

so what im trying is:
make one sweep ( 180/5) and fill the array
go back to 0
if rightLeft POS is different from leftRight POS stop and scan
I guess i need to make a new array referencePoint which will store the values from the first scan, then I id be able to trigger the servo once the object is gone
(if sonarValue == referencePoint[POS]) trigger servo…

now it gets stuck after one scan, there are probobly tones of strange things in the code, one thing is
if( leftRight[pos/5] == 0 )
Where id like to see if a element in the array is empty or not…

    #include <NewPing.h>
    #include <Servo.h> 
 
    Servo myservo;  // create servo object to control a servo 
    int pos = 0;    // variable to store the servo position 

    #define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
    #define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
    #define MAX_DISTANCE 500 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
    NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

// Declare variables
    const unsigned long distansInterval = 50;
    const unsigned long distansTracker = 10;
    const unsigned long servoTracker = 10;

    int sonarValue;
    int uS;
    int i;
 
    double leftRight[36];
    double rightLeft[36];
 
    unsigned long distansTimer;
    unsigned long distansTrackerTimer;
    unsigned long servoTimer;

// End vars 
 
  void setup() {  
    Serial.begin(115200);    
     distansTimer = millis ();
     distansTrackerTimer = millis ();
     myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
  }

  void runServo(){
    for(pos = 0; pos < 180;)          // goes from 0 degrees to 180 degrees 
    {                                 
      myservo.write(pos);              // tell servo to go to position in variable 'pos' 
      delay(50);                       // delay between scanning
      distansIntervalFunction();
      if( leftRight[pos/5] == 0 )
      {
        leftRight[pos/5] = sonarValue;
        rightLeft[pos/5] = sonarValue;
        pos += 5;
       }
       else if(rightLeft[pos] < leftRight[pos/5] - 25 )
       {
         distansIntervalFunction();
         rightLeft[pos/5] = sonarValue;
       }
       else
       {
         pos += 5;
       }
       Serial.println(pos);
       Serial.println(leftRight[pos/5]);
     } 
    for(pos = 180; pos>=1;)           // goes from 180 degrees to 0 degrees 
    {                                
      myservo.write(pos);              // tell servo to go to position in variable 'pos' 
      delay(50);                        
      distansIntervalFunction();
      if(leftRight[pos/5] == 0){      //If array POS is empty
        leftRight[pos/5] = sonarValue;
        rightLeft[pos/5] = sonarValue;
        pos -= 5;
       }
       else if(rightLeft[pos/5] < leftRight[pos/5] - 25 ){
         distansIntervalFunction();
         rightLeft[pos/5] = sonarValue;
       }
       else{
         pos -= 5;
       }
       for(i=0;i<36;i+=1){
       Serial.print(leftRight[i]);
     }
    } 
  }
  
/* //////////////
 Update sensor 
*//////////////
  void distansIntervalFunction (){
    unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
    sonarValue = uS / US_ROUNDTRIP_CM;
  }

/* //////////////
Send to exbee
*//////////////

  void distansTrackerFunction ()
  {
  
  }
 
/* //////////////
 LOOOOP 
*/  void loop ()
     {                 
      if ( (millis () - servoTimer) >= servoTracker){  
        runServo ();
      }    
    }

I have only had time for a quick look but  for(pos = 180; pos>=1;)          // goes from 180 degrees to 0 degrees is missing a third parameter
and     if(leftRight[pos/5] == 0){      //If array POS is emptywill probably not work because the array is defined as a float and its value may not equal exactly zero.

UKHeliBob:
I have only had time for a quick look but  for(pos = 180; pos>=1;)           // goes from 180 degrees to 0 degrees is missing a third parameter
and     if(leftRight[pos/5] == 0){      //If array POS is emptywill probably not work because the array is defined as a float and its value may not equal exactly zero.

Ahh i suppose i should define the amount of degrees within the ‘setup’ of the for-statement instead of in the end in the if condition

    for(pos = 0; pos < 180;  pos += 5 )          // goes from 0 degrees to 180 degrees

Wouldn’t this mean that it starts to measure at 5 degrees?
What i want to do here is to see if the element is empty, as i understand it im only looking if the element is 0 but how can i see if it’s empty?

      if( leftRight[pos/5] == 0 )

Alright!

I made some changes to simplyfi more like UKHeliBob suggested. I think it works!! :%

But i think I need to make somekind of math.abs solution in the!?

if (leftRight[pos/5] != rightLeft[pos/5])

since the arrays sometimes are +1 or - 3 …
So if leftRight[pos/5] != rightLeft[pos/5] and the difference is bigger than 10…

    #include <NewPing.h>
    #include <Servo.h> 
 
    Servo myservo;  // create servo object to control a servo 
    int pos = 0;    // variable to store the servo position 

    #define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
    #define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
    #define MAX_DISTANCE 500 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
    NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

// Declare variables
    long previousMillis = 0;
    long interval = 2; 

    int sonarValue;
    int uS;
    int i;
 
    int leftRight[36];
    int rightLeft[36];
    
    boolean firstSweep = true;
// End vars 
 
  void setup() {  
    Serial.begin(115200);    
     myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
  }

  void runServo(){
    for(pos = 0; pos < 180; pos += 5)          // goes from 0 degrees to 180 degrees 
    {                                 
      myservo.write(pos);                      // tell servo to go to position in variable 'pos'                       
      delay(50);                               // delay so ping can update
      distansIntervalFunction();               // get tracker value
      leftRight[pos/5] = sonarValue;            // write value to position in array
      if( firstSweep == false )
      {
        if (leftRight[pos/5] != rightLeft[pos/5])
        {
          Serial.print("theres a differance");
          delay(1000);
         }
      }
    }
    if( firstSweep == true )
    {
      firstSweep = false;
    } 

      for(pos = 180; pos>=1; pos-=5)            // goes from 180 degrees to 0 degrees 
    {                                
      Serial.println("secondRun");
      myservo.write(pos);              // tell servo to go to position in variable 'pos' 
      delay(50);
      distansIntervalFunction();
      rightLeft[pos/5] = sonarValue;
          Serial.print("rightLeft ");
          Serial.println(rightLeft[pos/5]);
          Serial.print("leftRight ");
          Serial.println(leftRight[pos/5]);
      if (rightLeft[pos/5] != leftRight[pos/5])
      {
        Serial.println("theres a differance");
        Serial.println(rightLeft[pos/5] - rightLeft[pos/5] );

        delay(1000);
       }
    }
  }
  
/* //////////////
 Update sensor 
*//////////////
  void distansIntervalFunction (){
    unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
    sonarValue = uS / US_ROUNDTRIP_CM;
  }

/* //////////////
Send to exbee
*//////////////

  void distansTrackerFunction ()
  {
  
  }
 
/* //////////////
 LOOOOP 
*/  void loop ()
     {                 
      unsigned long currentMillis = millis(); 
       if(currentMillis - previousMillis > interval) 
       { 
          previousMillis = currentMillis;
          runServo ();
      }    
    }

This is great,

i'v added the abs-function in the if statement

      if (abs(rightLeft[pos/5] - leftRight[pos/5]) > arrayDiff)

One problem i do have now is that There's always a diff at position 0 and position 180!? Any suggestions of how i can solve that?

/C :astonished:

It looks like you are nearly there. What values do you get if you print them at 0 and 180 degrees ? Does the problem persist if you reduce the range of the sweep to 10 to 170 as a test, ie is the problem with the edge cases whatever their value ?

In my pseudo code, when the firstSweep variable was true, I suggested making the values held in the two arrays equal as otherwise they will all be different until the servo has swept both ways and both arrays have been populated with real values but I don’t see that in your code. You could do this initial population of the arrays in the setup function so that it only happens once, and do away with the firstSweep variable and the tests on its value in the main program.

Hey, i just realized that the array needs 37 elements, it doesnt save the 180° now, i guess that is a problem. As i understood it you cant copy a array to another, or should i just add an else statement?

      if( firstSweep == false )
      {
        if (leftRight[pos/5] != rightLeft[pos/5])
        {
          Serial.print("theres a differance");
          delay(1000);
         }
      }else{
leftRight[pos/5] = sonarValue;

}