Motion tracking using IR sensor code help please

I have a Maestro 18 ch controller and 2 IR sensors from this project
pololu.com/blog/419/motion- … oween-prop

However the position always goes to one side or the other , I would like to have the head recenter IF the analog ins are within a small range ( nothing in front of the sensor or it is stable ) when there is nothing in front of the sensor the voltages are very close to each other ( like 70 and 60 on the display ) how do I in code have the head move to the center position when these numbers are within say 15 or each other ?

Here is what I have now

[code]6000 #initial position
dup 0 servo #initialize servo

2000 delay #delay for set up purposes

begin
#take the difference between the two analog signals
1 get_position 2 get_position minus

#compare the difference to a threshold and update servo
#position if it is within the limits (900us - 2200us)
dup -60 less_than if
swap dup 5000 greater_than if
5 minus
swap
endif
endif

60 greater_than if
dup 7000 less_than if
5 plus
endif
endif

dup 0 servo #update servo position

repeat[/code]

It also does not really track it goes to the MAX or MIN servo value, is there a way to make it actually track to the object position and stay there ? :mrgreen:

any info is good info

Hello.

You can probably set some secondary threshold so that if they are within 15 values of each other it recenters. However, it would not be very practical since the sensor readings being close to each other is also what indicates that the servo is centered on a person (recentering the servo in that case would be counter productive).

I’m not sure what you mean when you say that it does not really track; the system in the blog post that you referred to does track a person walking by (e.g. if they are walking by with it following them and they stop, it will stop). If yours is not tracking I suspect your sensors might be oriented in a way that does not allow them to both see the person at the same time.

This example was also used for a display at the Cedar Gables Inn Bed and Breakfast, which is shown in this blog post. For that display, Ken improved my original code by returning the servo to its starting position after some short delay. You might consider doing something like that as an alternative. Ken includes the modified code in this post on our forum.

-Brandon

My setup does not stop it just goes to one side or the other , I set up the sensors just like the skull example, I do see more sensitivity in one sensor vs the other, not sure why ?
I even tries separating them more ( bigger stereo field ) and that helped some.
I think I may need to make a op amp setup and set it to 2.5vdc then use that as ZERO position . I think this is being simulated in software correct ?

I am using a 4 turn servo ! that might be the problem ? well that helped some but it still goes all the way to one side or the other never in the middle or TRACK

I need it to stop at whatever location the object is at . Is there any code you can think of that would do this ? :mrgreen:

can you please explain the code to me clearly ?

[code]
6000 #initial position
dup 0 servo #initialize servo

2000 delay #delay for set up purposes

begin
#take the difference between the two analog signals
1 get_position 2 get_position minus

#compare the difference to a threshold and update servo
#position if it is within the limits (900us - 2200us)
dup -160 less_than if
swap dup 3600 greater_than if
5 minus
swap
endif
endif

160 greater_than if
dup 8800 less_than if
5 plus
endif
endif

dup 0 servo #update servo position

repeat[/code]

Hello.

I am not sure what you mean when you talk about using an op amp to set 2.5V as the zero position, but you should not have to do anything like that. Using a 4-turn servo could cause some problems; for example, you might need to modify the Min and Max values for that servo channel to get it to work as expected. Are you sure you are not using a continuous rotation servo? If you are, that would explain why it is not tracking.

Another thing to keep in mind is that all servos do not react the same way to the pulse width (e.g. some will turn counterclockwise when the pulse width is below 1.5ms and some will turn clockwise). If your servo is turning away from the object until it reaches the limits, your servo could function the opposite way mine does. One way to fix this would be to switch the order that you read the sensors (to invert the results when subtracting them), so “1 get_position 2 get_position minus” would become “2 get_position 1 get_position minus”.

Is there a particular part of the code that you do not understand with the comments provided? By the way, you might find the “Step Script” button in the “Script” tab of the Maestro Control Center helpful for debugging and understanding how the code works. This button will advance the script one step and you can use the pointer moving through the script and the stack displayed on the right-had side to get a better understanding of what each command is doing.

-Brandon

Ok well when messing around with the code I found that putting the servo initialize (dup 0 servo #initialize servo) inside the BEGIN statement I got rid of it loosing direction ( it would go backwards after getting lost )
it also seems to be much more reliable as far a position is concerned.
FYI

[quote=“BrandonM”]Hello.

I am not sure what you mean when you talk about using an op amp to set 2.5V as the zero position, but you should not have to do anything like that. Using a 4-turn servo could cause some problems; for example, you might need to modify the Min and Max values for that servo channel to get it to work as expected. Are you sure you are not using a continuous rotation servo? If you are, that would explain why it is not tracking.
I was talking about doing it in a circuit I have put limits on the servo range

Another thing to keep in mind is that all servos do not react the same way to the pulse width (e.g. some will turn counterclockwise when the pulse width is below 1.5ms and some will turn clockwise). If your servo is turning away from the object until it reaches the limits, your servo could function the opposite way mine does. One way to fix this would be to switch the order that you read the sensors (to invert the results when subtracting them), so “1 get_position 2 get_position minus” would become “2 get_position 1 get_position minus”.
I reversed the wires several times but it would get lost , My servo is 4 turns not continuous
Is there a particular part of the code that you do not understand with the comments provided? By the way, you might find the “Step Script” button in the “Script” tab of the Maestro Control Center helpful for debugging and understanding how the code works. This button will advance the script one step and you can use the pointer moving through the script and the stack displayed on the right-had side to get a better understanding of what each command is doing.
The part of the code I do not understand is the this , please explain the #'s ? I think it is a conversion ?

dup -120 less_than if
swap dup 3600 greater_than if
5 minus
swap
endif

-Brandon[/quote]

Well I spoke to soon . it gets into a state that it reverses operation and goes all the way to one or the other extreme , I am trying moving things around at random LOL not a programmer by any means

Moving the initialization (dup 0 servo) just inside of the main loop should not have any impact on the tracking since it is the same line of code that is at the end of the loop. That line of code reads the target value stored on the stack and updates the servo with that target, so moving it inside of the loop just sends the servo the same target position twice.

Can you post a video showing the behavior of your system? Do you have a standard servo (instead of a 4-turn servo) that you could try? Do you have any speed or acceleration limits set on your servo channel? Have you changed the Min and Max pulse width values in the “Channel Settings” tab of the Maestro Control Center? Can you post your Maestro settings file? You can save your settings file by selecting the “Save settings file…” option within the “File” drop-down menu in the Maestro Configuration Utility.

To understand that part of code, it is important to know that at this point in the script, there are two values already on the stack: the target position and the error (which is the difference in the sensor readings). For example, if this is the first time through the code and the error between the sensors is -200, the stack would looks like this:

-200
6000

The dup -120 less_than if line of code is duplicating the top value of the stack (-200 in this example) and comparing it to -120. Since -200 is less than -120, the if statement will run. If it was not, it would skip down to endif. Also, since the error value was duplicated before being compared to the -120 threshold, the stack will be unchanged after running that line of code. The next line, swap dup 3600 greater_than if swaps the position of the two values on the stack, then duplicates the top value (now 6000) and compares it to 3600. If the target value (6000) is greater than 3600, it will subtract 5 from it, creating a new target value of 5995. Note that the target does not get updated if it is less than 3600, which limits the target to a minimum of 3600. This value was found experimentally to be the minimum pulse width accepted by the servo I used. Also note that the script uses units of quarter microseconds, so this translates into a pulse width of 900us.

-Brandon

[quote=“BrandonM”]Moving the initialization (dup 0 servo) just inside of the main loop should not have any impact on the tracking since it is the same line of code that is at the end of the loop. That line of code reads the target value stored on the stack and updates the servo with that target, so moving it inside of the loop just sends the servo the same target position twice.

Can you post a video showing the behavior of your system? Do you have a standard servo (instead of a 4-turn servo) that you could try? Do you have any speed or acceleration limits set on your servo channel? Have you changed the Min and Max pulse width values in the “Channel Settings” tab of the Maestro Control Center? Can you post your Maestro settings file? You can save your settings file by selecting the “Save settings file…” option within the “File” drop-down menu in the Maestro Configuration Utility.

To understand that part of code, it is important to know that at this point in the script, there are two values already on the stack: the target position and the error (which is the difference in the sensor readings). For example, if this is the first time through the code and the error between the sensors is -200, the stack would looks like this:

-200
6000

The dup -120 less_than if line of code is duplicating the top value of the stack (-200 in this example) and comparing it to -120. Since -200 is less than -120, the if statement will run. If it was not, it would skip down to endif. Also, since the error value was duplicated before being compared to the -120 threshold, the stack will be unchanged after running that line of code. The next line, swap dup 3600 greater_than if swaps the position of the two values on the stack, then duplicates the top value (now 6000) and compares it to 3600. If the target value (6000) is greater than 3600, it will subtract 5 from it, creating a new target value of 5995. Note that the target does not get updated if it is less than 3600, which limits the target to a minimum of 3600. This value was found experimentally to be the minimum pulse width accepted by the servo I used. Also note that the script uses units of quarter microseconds, so this translates into a pulse width of 900us.

-Brandon[/quote]

Thanks for explaining the code I needed it , I think I found the problem , I had set the threshold low ( -60 to -80 ) and this was causing it to move from the noise causing it to trigger , it would go to MAX or MIN then it must have gotten lost while in that position , this caused it to reverse for some reason. Probably a math in the stack issue.
After changing the threshold back to 140 , -140 it seems to be ok now , There is quite a bit of noise on the analog ch. I am going to try a cap on the sensor to smooth out the noise some. I was trying to increase the sensitivity for objects further away , the material the the sensor sees has a ALOT to do with how it functions , I am thing about getting some Ultrasonic sensors to try later .
OK I just made it go to one extreme and it sat there now it will not center now ( when triggered it goes all the way to the opposite extreme. It does this on 1 turn or 4 turn motors.
It SNAPS back and forth ,

video link
youtu.be/DDiB10qieUg

Thank you for posting the video. The threshold value is one way to help reduce the impact of the noise of the sensors. Also, when the threshold value is too low, the servo might start oscillating around the object instead of staying focused on it.

The behavior shown in your video is certainly strange. Could you post your Maestro settings file? You can save your Maestro settings file by selecting the “Save settings file…” option within the “File” drop-down menu of the Maestro Control Center.

-Brandon

[quote=“BrandonM”]Thank you for posting the video. The threshold value is one way to help reduce the impact of the noise of the sensors. Also, when the threshold value is too low, the servo might start oscillating around the object instead of staying focused on it.

The behavior shown in your video is certainly strange. Could you post your Maestro settings file? You can save your Maestro settings file by selecting the “Save settings file…” option within the “File” drop-down menu of the Maestro Control Center.

-Brandon[/quote]
Ya I got the threshold , I knew I forgot something in my post LOL

here is the script

6000 #initial position
dup 0 servo #initialize servo
 
5000 delay #delay for set up purposes
 
begin
  #take the difference between the two analog signals
  1 get_position 2 get_position minus
 
  #compare the difference to a threshold and update servo
  #position if it is within the limits (900us - 2200us)
  dup -140 less_than if
    swap dup 3600 greater_than if
      5 minus
      swap
    endif
  endif
 
  140 greater_than if
    dup 8800 less_than if
      5 plus
    endif
  endif
 
  dup 0 servo #update servo position
 
repeat

I added the setting file attachment
motion 5.txt (9.69 KB)

Thank you for posting your script and settings file. It looks like your script is nearly identical to mine except for the threshold values. However, when looking at your script, I noticed a bug (which is also in my original script). I am not entirely sure if this bug is the cause of your problem or not, but when the target value reaches the lower limit, the script was mishandling the target value in the stack (e.g. it needs to be swapped again so it is below the error value otherwise it gets compared to the threshold and lost). To fix this bug, could you try adding else swap in the part of the code commented below?

dup -200 less_than if
    swap dup 3600 greater_than if
      5 minus
      swap
    else swap  #this is the new line of code that should fix the bug
    endif
  endif

I also noticed you had some acceleration and speed limits for the servo channel set in the “Channel Settings” tab. If the servo still does not track as you expect, could you try removing these limits (e.g. setting them to 0) and seeing if the behavior improves?

-Brandon

[quote=“BrandonM”]Thank you for posting your script and settings file. It looks like your script is nearly identical to mine except for the threshold values. However, when looking at your script, I noticed a bug (which is also in my original script). I am not entirely sure if this bug is the cause of your problem or not, but when the target value reaches the lower limit, the script was mishandling the target value in the stack (e.g. it needs to be swapped again so it is below the error value otherwise it gets compared to the threshold and lost). To fix this bug, could you try adding else swap in the part of the code commented below?

dup -200 less_than if
    swap dup 3600 greater_than if
      5 minus
      swap
    else swap  #this is the new line of code that should fix the bug
    endif
  endif

I also noticed you had some acceleration and speed limits for the servo channel set in the “Channel Settings” tab. If the servo still does not track as you expect, could you try removing these limits (e.g. setting them to 0) and seeing if the behavior improves?

-Brandon[/quote]

Cool I will add this into my script , I was thinking maybe add the speed and accel into the script to set it from there instead of the controls .

Ok I added this to my script and so far it works ! Nice work ! well 5 hours and no problems GOOD JOB BUD !

is there a way in the script to reduce the noise ? or should I try to use caps on the PCB to filter it ?
If I can reduce the noise I can increase the range it will operate at by lowering the threshold values.

One other thing I had to do was to make the max-min range match in the script x4 I was setting the range in the controller software but not in the script once I matched them up I have had no issues sense then

I am glad that it is working better for you now. You might be able to reduce the impact of noise using a script by doing something like averaging the readings; however, it would be more complicated. You could try adding capacitors like you mentioned, but if you are using the same ones I used, I suspect the benefit would be minimal with those particular sensors.

One thing to note is that apparent noise in the servo’s motion when the object is stationary is somewhat expected due to the simplicity of the system. The error is calculated from subtracting two sensors, which could inherently have some variation, and the sensors have a cone shaped sensing area, so it might work differently when the object is close than it does when the object is far. You would probably see some servo oscillations or twitchy behavior even if the sensors were identical and noise-free.

-Brandon

By fine tuning the numbers in the script ( min / max and threshold ) it is really stable now , thanks for all the help , your FIX did it.