Tracking a servo/stepper position based on a sensor reading

Morning everyone,

I'm doing a project where i have an analog sensor rotating back and forth. What i would like to do is record some type of position data, where the sensor has the highest reading. For some reason i'm having a really hard time coming up with a good way to do this from a code structure stand-point. I was thinking some type of array might work?

More info; sensor works from analog input(basic 0-5v reading) sensor is going to pan back and forth from say 0-359 degrees, and back 359-0. I'm not set on any particular driver, stepper at this point.

Super happy with any input just to jog me

I was thinking some type of array might work?

For what? You have a current reading and a maximum (or minimum) previous reading. The current reading is either higher (or lower) than the previous maximum (or minimum), so it becomes the new maximum (or minimum), or it isn't, in which case it is ignored.

Do the readings increase linearly from 0 to some point and then decrease linearly to 360?

Note: A typical servo won't go 360 degrees.

To keep track of where the signal was highest:

int highest = 0, highestPosition = 0;
  for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
    int reading = analogRead(A0);
    if (reading >= highest) {
      highest = reading;
      highestPosition = pos;
    }
  }

hanslanda:
What i would like to do is record some type of position data, where the sensor has the highest reading. For some reason i'm having a really hard time coming up with a good way to do this from a code structure stand-point. I was thinking some type of array might work?

From your title I had assumed you want to identify the stepper position at which the highest reading occurs. But when I see that you are thinking of arrays I suspect I may have been jumping to the wrong conclusion.

Do you have a stepper motor and are you able to control it between 0 and 359 degrees?

...R
Stepper Motor Basics
Simple Stepper Code

johnwasser:
Note: A typical servo won't go 360 degrees.

To keep track of where the signal was highest:

int highest = 0, highestPosition = 0;

for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                      // waits 15ms for the servo to reach the position
    int reading = analogRead(A0);
    if (reading >= highest) {
      highest = reading;
      highestPosition = pos;
    }
  }

This could totally work. Thanks. Only problem i see with this is i'm going to be stuck in a loop for most of the tracking and that might kill some of the other functionality of my code that will be executing at the time. Could i implement it somehow without the for loop and stick it in the bottom of void? I could still have trigger if statements to switch the motion back.

Robin2:
From your title I had assumed you want to identify the stepper position at which the highest reading occurs. But when I see that you are thinking of arrays I suspect I may have been jumping to the wrong conclusion.

Do you have a stepper motor and are you able to control it between 0 and 359 degrees?

...R
Stepper Motor Basics
Simple Stepper Code

You're assumption was correct. I'm wanting to record a value where the signal would be highest. I only through array out there because i simply didnt know what would work for this.

Only problem i see with this is i'm going to be stuck in a loop for most of the tracking and that might kill some of the other functionality of my code that will be executing at the time. Could i implement it somehow without the for loop and stick it in the bottom of void?

Your sketch does not have any voids in it. It has functions.

You could, on every pass through loop(), tell the servo to move, if it is time to. You could take a reading if the servo has had time to get into position. The blink without delay example bears looking at.

Of course, you'll need to make many of those variables global.

PaulS:
Your sketch does not have any voids in it. It has functions.

You could, on every pass through loop(), tell the servo to move, if it is time to. You could take a reading if the servo has had time to get into position. The blink without delay example bears looking at.

Of course, you'll need to make many of those variables global.

Hmm thanks, i think i have a good starting point!

Robin2:
From your title I had assumed you want to identify the stepper position at which the highest reading occurs. But when I see that you are thinking of arrays I suspect I may have been jumping to the wrong conclusion.

Do you have a stepper motor and are you able to control it between 0 and 359 degrees?

...R
Stepper Motor Basics
Simple Stepper Code

Robin is looks like i should have read your pinned post too. The only reason i dont want this in a ~for loop is that i need a few things to concurrently run, for instance i have an lcd screen hooked up to this same arduino that i need to update with that same sensor data.

hanslanda:
Only problem i see with this is i'm going to be stuck in a loop for most of the tracking and that might kill some of the other functionality of my code that will be executing at the time. Could i implement it somehow without the for loop and stick it in the bottom of void? I could still have trigger if statements to switch the motion back.

Sure. You can code it like the BlinkWithoutDelay example to take a step every 15 milliseconds. Start with:

const unsigned long INTERVAL = 15;
const int LowerLimit = 0;
const int UpperLimit = 180;
#include <Servo.h>
Servo servo;  // create servo object to control a servo
void setup() {
  servo.attach(9);  // attaches the servo on pin 9 to the servo object
}
// This function is called after every sweep with the position of the highest input sensed
void actOnDirection(int pos) {
  // You should put code here to do what you want to do.
}
void loop() {
  static int position = LowerLimit;
  static int direction = 1;
  unsigned long currentTime = millis();
  static unsigned long previousTime = 0;
  static int highest = 0;
  static int highestPosition;
  // You can put code here
  if (currentTime - previousTime >= INTERVAL) {
    previousTime += INTERVAL;
    // Done waiting for servo to settle
    int reading = analogRead(A0);
    // Record where we saw the highest reading.
    if (reading >= highest) {
      highest = reading;
      highestPosition = position;
    }
    // Check for high end of travel
    if (position >= UpperLimit) {
      actOnDirection(highestPosition);
      highest = 0;  // Reset to look for a new high on this sweep
      direction = -1;  // Head towatd the low end of travel
    }
    // Check for low end of travel
    if (position <= LowerLimit) {
      actOnDirection(highestPosition);
      highest = 0;  // Reset to look for a new high on this sweep
      direction = 1;  // Head for the high end of travel
    }
    position += direction;
    servo.write(position);
  }
  // You can put code here
}

One question i do have using this method. Is this really multiple things going on at once? Again i have a poor understanding of this type of program structure, but aren't we just calling functions one by one? Would the program not still execute these functions one at a time line by line?

The demo Several Things at a Time is an extended example of BWoD. It may help with understanding the technique.

You are quite correct to say that it calls the functions one by one. But note how each function runs very briefly and returns to loop() so the next one can be called. And there may be dozens of calls to a function before it is actually time for it to do anything. This gives the illusion of several things happening at once.

...R