Map function not giving expected results

I’m using the map function to transform the potentiometer value from analog pin 0 to between 0 and 30000 (milliseconds). The problem is that when the potentiometer is turned all the way down, the lowest output value I get is just above 1023 (it’s currently at 1037). Which seems suspiciously close to the 1023 highest analog pin value. When I serial print pin 0 (Serial.println(analogRead(CAMERA_DELAY_PIN));), the lowest value I get is around 300, not 0. I thought maybe my pot was just not working as expected, and so I tried just mapping from 300 to 1023 (e.g., map(analogRead(CAMERA_DELAY_PIN), 300, 1023, 0, 30000);), but that does the opposite of what I would expect. Instead of getting an output value close to 0, it’s coming closer to 2328.

I’d love to know if I’m doing something wrong. But maybe I just need to change the potentiometer.

Here is the mapping code: cameraPause = map(analogRead(CAMERA_DELAY_PIN), 0, 1023, 0, 30000);

/*
  Author: GulJanjua
  Date  : December 30, 2018

  Software Requirements:
  ----------------------
  -Arduino IDE
  -AccelStepper

  Hardware Requirements:
  ----------------------
  -Arduino
  -Stepper motor driver
  -

  Project Requirents:
  -------------------
  1. Stop
  2. Forward once for a given distance, then trigger the camera.
  3. Reverse once for a given distance, then trigger the camera.
  4. Forward infinitely: move a given distance, then pause for x milliseconds while the camera is triggered, then repeat.
  5. Reverse infinitely: move a given distance, then pause for x milliseconds while the camera is triggered, then repeat.

*/

#include <AccelStepper.h>

AccelStepper stepper1(AccelStepper::DRIVER, 9, 8);


int period = 500; // delay time for serial printing pot value to monitor. Increasing this will slow down when button changes are responded to and thus they won't act as expected. 
unsigned long time_now = 0; // start millis time at 0

#define ledPin       10
#define STOP_PIN      2

#define LEFT_ONE_PIN  5
#define RIGHT_ONE_PIN 6
#define LEFT_PIN      3
#define RIGHT_PIN     4

// #define SPEED_PIN 0
// #define MAX_SPEED 1000
// #define MIN_SPEED 0.01

#define CAMERA_DELAY_PIN 0
#define MAX_DEALY 30000
#define MIN_DELAY 250

#define STEPS1 10                          //STEPS in one time rotation only
#define STEPS2 10                          //STEPS in infinite rotation

#define preShutterPause 10                  // Not really needed, but may give objects time to stop shaking. 
#define shutterPause 250                    // Allows shutter trigger to turn on only for this instance and not remain on               
// #define cameraPause 3000                    // pause while camera takes photo

int dir = 0;

void setup() {

  Serial.begin(9600);

  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);

  pinMode(LEFT_PIN,     INPUT_PULLUP);
  pinMode(STOP_PIN,     INPUT_PULLUP);
  pinMode(RIGHT_PIN,    INPUT_PULLUP);
  pinMode(RIGHT_ONE_PIN, INPUT_PULLUP);
  pinMode(LEFT_ONE_PIN, INPUT_PULLUP);

  stepper1.setMaxSpeed(200.0);
  stepper1.setAcceleration(500.0);
  stepper1.setSpeed(200);
}

void loop() {

  time_now = millis(); // used for timing of things that aren't using delay()

  // SETTING CAMERA DELAY TIME VIA POT
  static float cameraPause = 0.0;         // Defines the camera pause time as numbers
  cameraPause = map(analogRead(CAMERA_DELAY_PIN), 0, 1023, 0, 30000); //  Scale the pot's value 0-1023 to what I want min to max delay time

  while (millis() < time_now + period) { // Simply writing the current potentiomiter camera pause time on the serial monitor
    Serial.println(analogRead(CAMERA_DELAY_PIN));
    Serial.println(cameraPause);
  }

  // ONE MOVE ONLY

  if (digitalRead(LEFT_ONE_PIN) == LOW) {
    stepper1.runToNewPosition(STEPS1);
    stepper1.setCurrentPosition(0);
    delay(preShutterPause);
    digitalWrite(ledPin , HIGH);
    delay(shutterPause);
    digitalWrite(ledPin , LOW);
    delay(cameraPause);
    dir = 0;
  }
  if (digitalRead(RIGHT_ONE_PIN) == LOW) {
    stepper1.runToNewPosition(-STEPS1);
    stepper1.setCurrentPosition(0);
    delay(preShutterPause);
    digitalWrite(ledPin , HIGH);
    delay(shutterPause);
    digitalWrite(ledPin , LOW);
    delay(cameraPause);
    dir = 0;
  }

  // INFINITE MOVES

  if (digitalRead(LEFT_PIN) == LOW) {
    dir = 1;
  }

  if (digitalRead(RIGHT_PIN) == LOW) {
    dir = 2;
  }

  if (digitalRead(STOP_PIN) == LOW) {
    dir = 0;
  }

  if (dir == 1) {
    stepper1.runToNewPosition(STEPS2);
    stepper1.setCurrentPosition(0);
    delay(preShutterPause);
    digitalWrite(ledPin , HIGH);
    delay(shutterPause);
    digitalWrite(ledPin , LOW);
    delay(cameraPause);
  }

  if (dir == 2) {
    stepper1.runToNewPosition(-STEPS2);
    stepper1.setCurrentPosition(0);
    delay(preShutterPause);
    digitalWrite(ledPin , HIGH);
    delay(shutterPause);
    digitalWrite(ledPin , LOW);
    delay(cameraPause);
  }
}

Hi,
Can suggest you change this;

cameraPause = map(analogRead(CAMERA_DELAY_PIN), 0, 1023, 0, 30000);

To this for a start.

int cameraDelayValue =analogRead(CAMERA_DELAY_PIN);
int cameraPause = map(cameraDelayValue, 0, 1023, 0, 30000);

then use cameraDelayValue all through your code rather than keep reading the analog pin.

Run a test program just for the analog input, with serial prints to see what your results are for the pot value from 0 to 1023, you will not see 1024 as that is an 11 bit number and the AtoD is 10bit.

Tom… :slight_smile:

Hi, Then try;

int cameraPause = map(cameraDelayValue, 300, 1023, 0, 30000);

Be aware that when the value goes below 300, cameraPause will go negative, there are no constranst on the map function output.

You will need you use this function in your code. https://www.arduino.cc/reference/en/language/functions/math/constrain/

Tom.. :)

@ThomGeorge I tried your ideas, but seem to be getting the same results. But I think the issue may be the POT and not the code.

When I implement your code using int(shown below), the functionality of my project works the same as before. The serial print numbers for pin 0 (the POT) and the map function output in the serial monitor appear to have the same results. Serial.println(analogRead(CAMERA_DELAY_PIN)); still hovers around 300 and Serial.println(camera pause); still remains between around 10,000 and 30,000.

int cameraDelayValue =analogRead(CAMERA_DELAY_PIN);
int cameraPause = map(cameraDelayValue, 0, 1023, 0, 30000);

I guess this means the map numbers are correct (a pin/pot reading of 300 should map to around 10,000 since 300 is about 1/3 of 1023) and maybe my POT just isn't working as expected.

Increasing the input-low value to 300 does help (map(cameraDelayValue, 300, 1023, 0, 30000);). But it does occasionally give me negative numbers as you said. Is there a way to constrain the number so that anything below 0 gives a result of 0?

It is interesting how using your code below only allows the serial print to update on the serial monitor when the stepper move is happening. Why is that? I'm pretty sure it printed continuously before.

int cameraPause = map(cameraDelayValue, 300, 1023, 0, 30000);[code]

I don’t know what Arduino you’re using, but I see 2 problems:

#define CAMERA_DELAY_PIN 0
#define MAX_DEALY 30000

‘DEALY’ instead of ‘DELAY’, but if you did this all along the code it’s not a real problem.

You defined the pot pin as 0. This is digital pin 0 and you want an analog pin here, so it should be ‘A0’. Furthermore, you didn’t declare this pin as INPUT (using pinMode).

You defined the pot pin as 0. This is digital pin 0 and you want an analog pin here, so it should be 'A0'. Furthermore, you didn't declare this pin as INPUT (using pinMode).

The function analogRead() uses A0 in either case, and does not require the pin to be declared as INPUT.

Well, I changed out the POT and now everything is working as expected. I get a pin reading of 0 when the POT is turned all the way down. Nevertheless, I did learn some new things here. Thanks, everyone for your help!

I do wonder how my POT began to fail. I hope it's not somehow receiving too much current, or something, and might fail again.

Is there a way to constrain the number so that anything below 0 gives a result of 0?

constrain()

if (x < 0) x=0;

Hi,

Is there a way to constrain the number so that anything below 0 gives a result of 0?

See link in post #2.

Tom... :)