How does mapping work?

I'm using a KeyeStudio 12-bit 16-channel PWM servo shield, and the map() function to move a servo. The KeyeStudio servo shield uses Adafruit's Adafruit_PWMServoDriver driver. At present, I'm assuming the map function converts a unit or data type to another. For example, from 0 degrees to 102 "something", and from 180 degrees to 512 "something". Am I wrong? The code used in my sketch is as follows:

int d, Duty, ThisServo;
for (d = 0; d <= 180; d++){
Duty = map(Pos, 0, 180, 102, 512); // What are 102 and 512 values?
HCSR04.setPWM(ThisServo, 0, Duty); // What is 0? Start at value?

In the map function statement above:
Pos = position set by 'for' statement using integer values between 0 and 180 degrees
0 = from lowest, in this case degrees
180 = from highest, also in degrees
102 = to lowest. This value in reference to? Pulse ON time in milli- or micro- seconds?
512 = to highest. This value in reference to? Pulse ON time in milli- or micro- seconds?

In the following line of code above:
HCSR04.setPWM = class constructor and class functiuon used in Adafruit_PWMServoDriver.h header file
(ThisServo, 0, Duty) = parameters passed to the function of that class

I'm new to electronics, Arduino and servo control. I found the above map statement in someone else's sketch and have been using it ever since but without fully understanding how it works or what it's doing. The servo I am using is a MG996R and its operating frequency is 50Hz with a 20ms period.

In the above example code, I suppose 102 somehow represents the servo's 0-degree position, and 512 it's 180-degree position, but based on what? Or, does it somehow represent the value of the control pulse in milliseconds? For example, 1ms for servo's 0-degree position, 1.5ms for 90-degree position, and 2ms for 180-degree position. I need help understanding this, and any help would be appreciated.

No guessing required: map() - Arduino Reference

For the mathematically inclined, here’s the whole function

long map(long x, long in_min, long in_max, long out_min, long out_max) {
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;

Where is the code for that function?

Reading a snippet of code is like coming into the middle of a conversation. We are missing information. Post the whole code and provide links to all of the libraries that do not come with the IDE if you want informed help.

Read the forum guidelines to see how to properly post code.
Use the IDE autoformat tool (ctrl-t or Tools, Auto format) before posting code in code tags.

I understand. Sorry about that.

#include <Adafruit_PWMServoDriver.h> // Used by KeyeStudio 12-bit 16-channel PWM servo shield 1
Adafruit_PWMServoDriver HCSR04 = Adafruit_PWMServoDriver(0x40); // HC-SR04 sensor positioning servo

from the Adafruit_PWMServoDriver.cpp file

  • @brief Sets the PWM output of one of the PCA9685 pins
  • @param num One of the PWM output pins, from 0 to 15
  • @param on At what point in the 4096-part cycle to turn the PWM output ON
  • @param off At what point in the 4096-part cycle to turn the PWM output OFF
    void Adafruit_PWMServoDriver::setPWM(uint8_t num, uint16_t on, uint16_t off) {

Thank you. That is what I couldn't understand. I thought it might have something to do with the ON and OFF time, but couldn't understand what the values 102 and 512 were based on. Now I get it! It's the 4096-part cycle. Thanks again groundFungus.

And I read up on code tags. Thanks. I will use these from now on now that I understand the problem it causes.

Thanks for the proportion function equation.

It's really just the linear function y=mx+b that we all learned in high school.

A typical servo pulse frequency is 50 Hz (20 milliseconds). Divide that into 4096 intervals and you get 4.88 microseconds per tick.

Typical pulse widths are 1000 to 2000 microseconds. Divide by 4.88 to get pulses of 205 to 410 ticks. It looks like you may be using a higher frequency PWM and, therefore, more ticks per pulse and a wider range of pulse widths.

If 512 ticks represent 2000 microseconds then each tick is about 3.9 microseconds. That is 16 milliseconds per cycle or 62.6 Hz.

This clarifies many things. I actually got the values 102 and 512 from someone’s sketch on the internet. I’d been using these values without knowing if these were right for my servos. With the info you’ve given me, I should be able to find the values I need. Thank you very much John.