dhorton668
Published © CC BY-SA

A better mapping with map()

It should be easy, right? map(x, 0, 1023, 0, 10) and any analog input reading becomes a digit from 0..10. Yes, but not like you'd think.

BeginnerFull instructions provided22,190
A better mapping with map()

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
10 LEDs Bar Array, Green
10 LEDs Bar Array, Green
×1
Rotary potentiometer (generic)
Rotary potentiometer (generic)
×1
Breadboard (generic)
Breadboard (generic)
×1
Through Hole Resistor, 330 ohm
Through Hole Resistor, 330 ohm
×10
Hook Up Wire Kit, 22 AWG
Hook Up Wire Kit, 22 AWG
×1

Story

Read more

Schematics

Bargraph Voltmeter (KiCAD schematic)

Indicate potentiometer voltage on LED bargraph display.

Bargraph Voltmeter (schematic)

Screenshot image of KiCAD schematic.

Code

Demo code for map() function

Arduino
This is the code used to debug the flickering 9th LED.
/*
  MapDemo -- A simple program to demonstrate converting the 0..1023 values from the analog to digital converter (ADC) inputs to a more useful range for human consuption of 0..10.
  The reason for this demo is not to read any actual values, but to show a technique for getting the most even distribution of values from the map function. The technique used is
  not entirely intuitive after reading the Arduino reference page at: https://www.arduino.cc/reference/en/language/functions/math/map/

  This program is public domain and comes with no warranty of any kind. 
*/

void setup() {
  
  // Turn the built-in LED on to indicate program is starting.
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);

  // Initialize serial communication and delay to give time to start the serial console.
  Serial.begin(9600);
  delay(10000);

  // Turn off the built-in LED to indicate startup is done.
  digitalWrite(LED_BUILTIN, LOW);
}

void loop() {

  // All these loop map 0 through 1023 onto 0 through 10, but in different ways.

  // This seems logigal. The ADC from value ranges 0..1023 and the to value ranges 0..10, with 0 meaning no LEDs lit. But, there's a problem. The distribution is not even. Only one analog value maps to 10. 
  for (int x=0; x<1024; x++) {
    int y = map(x, 0, 1023, 0, 10);
    Serial.print("y = map(x, 0, 1023, 0, 10): x = ");
    Serial.print(x);
    Serial.print(", y = ");
    Serial.println(y);
  }

  // This way is not as intuitive, as it seems to be mapping the impossible to obtain ADC value 1024 to the impossible to display value of 11. But, it works and it gives a more even distribution of values.
  for (int x=0; x<1024; x++) {
    int y = map(x, 0, 1024, 0, 11);
    Serial.print("y = map(x, 0, 1024, 0, 11): x = ");
    Serial.print(x);
    Serial.print(", y = ");
    Serial.println(y);
  }

  // There's also the mathematical way of doing it using slope-intercept form: y = mx + b where the slope (m) is found by the ratio of the two ranges and the y intersection is 0.
  // See: https://en.wikipedia.org/wiki/Linear_equation#Slope-intercept_form
  // Since the intersection with the y-axis is at 0, we can ignore it and the equation simplifies to y = mx.
  // The value of m (slope) can be found using the concept of rise over run. The rise is the change in y value, so 0..11 in our case. The run is the change in x, or 0..1024. So m = 11 /1024.
  for (int x=0; x<1024; x++) {
    int y = (int) 11 * x / 1024;
    Serial.print("y = (int) 11 * x / 1024: x = ");
    Serial.print(x);
    Serial.print(", y = ");
    Serial.println(y);
  }

  // Pause and wait for any kind of input before running again.
  Serial.println("Send any serial input to run again.");
  while (!Serial.available());
  Serial.read();
}

Bargraph Voltmeter

Arduino
Read analog input voltage and light one of ten LEDs on a bargraph, or none if the voltage is below the lowest threshold.
/* 
  Bargraph Meter -- Light a single LED in a 10-segment bargraph to indicate input voltage at analog pin.
  No LEDs are lit below the lowest threshold.

  Code by Alex Horton
  Public domain with no warranty or guaranty as to fitness of purpose.
*/

int analogValue = 0;
int level = 0;

void setup() {
  Serial.begin(9600);
  pinMode(13,OUTPUT);
  pinMode(12,OUTPUT);
  pinMode(11,OUTPUT);
  pinMode(10,OUTPUT);
  pinMode(9,OUTPUT);
  pinMode(8,OUTPUT);
  pinMode(7,OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(A5,INPUT);
}

void loop() {
  analogValue = analogRead(A5);
  level = map(analogValue, 0, 1024, 0, 11);
  Serial.println(level);
  Serial.println(analogValue);

  switch (level) {
    case 0:
      digitalWrite(13,LOW);
      digitalWrite(12,LOW);
      digitalWrite(11,LOW);
      digitalWrite(10,LOW);
      digitalWrite(9,LOW);
      digitalWrite(8,LOW);
      digitalWrite(7,LOW);
      digitalWrite(6,LOW);
      digitalWrite(5,LOW);
      digitalWrite(4,LOW);
    break;
    case 1:
      digitalWrite(13,LOW);
      digitalWrite(12,LOW);
      digitalWrite(11,LOW);
      digitalWrite(10,LOW);
      digitalWrite(9,LOW);
      digitalWrite(8,LOW);
      digitalWrite(7,LOW);
      digitalWrite(6,LOW);
      digitalWrite(5,LOW);
      digitalWrite(4,HIGH);
    break;
    case 2:
      digitalWrite(13,LOW);
      digitalWrite(12,LOW);
      digitalWrite(11,LOW);
      digitalWrite(10,LOW);
      digitalWrite(9,LOW);
      digitalWrite(8,LOW);
      digitalWrite(7,LOW);
      digitalWrite(6,LOW);
      digitalWrite(5,HIGH);
      digitalWrite(4,LOW);
    break;
    case 3:
      digitalWrite(13,LOW);
      digitalWrite(12,LOW);
      digitalWrite(11,LOW);
      digitalWrite(10,LOW);
      digitalWrite(9,LOW);
      digitalWrite(8,LOW);
      digitalWrite(7,LOW);
      digitalWrite(6,HIGH);
      digitalWrite(5,LOW);
      digitalWrite(4,LOW);
    break;
    case 4:
      digitalWrite(13,LOW);
      digitalWrite(12,LOW);
      digitalWrite(11,LOW);
      digitalWrite(10,LOW);
      digitalWrite(9,LOW);
      digitalWrite(8,LOW);
      digitalWrite(7,HIGH);
      digitalWrite(6,LOW);
      digitalWrite(5,LOW);
      digitalWrite(4,LOW);
    break;
    case 5:
      digitalWrite(13,LOW);
      digitalWrite(12,LOW);
      digitalWrite(11,LOW);
      digitalWrite(10,LOW);
      digitalWrite(9,LOW);
      digitalWrite(8,HIGH);
      digitalWrite(7,LOW);
      digitalWrite(6,LOW);
      digitalWrite(5,LOW);
      digitalWrite(4,LOW);
    break;
    case 6:
      digitalWrite(13,LOW);
      digitalWrite(12,LOW);
      digitalWrite(11,LOW);
      digitalWrite(10,LOW);
      digitalWrite(9,HIGH);
      digitalWrite(8,LOW);
      digitalWrite(7,LOW);
      digitalWrite(6,LOW);
      digitalWrite(5,LOW);
      digitalWrite(4,LOW);
    break;
    case 7:
      digitalWrite(13,LOW);
      digitalWrite(12,LOW);
      digitalWrite(11,LOW);
      digitalWrite(10,HIGH);
      digitalWrite(9,LOW);
      digitalWrite(8,LOW);
      digitalWrite(7,LOW);
      digitalWrite(6,LOW);
      digitalWrite(5,LOW);
      digitalWrite(4,LOW);
    break;
    case 8:
      digitalWrite(13,LOW);
      digitalWrite(12,LOW);
      digitalWrite(11,HIGH);
      digitalWrite(10,LOW);
      digitalWrite(9,LOW);
      digitalWrite(8,LOW);
      digitalWrite(7,LOW);
      digitalWrite(6,LOW);
      digitalWrite(5,LOW);
      digitalWrite(4,LOW);
    break;
    case 9:
      digitalWrite(13,LOW);
      digitalWrite(12,HIGH);
      digitalWrite(11,LOW);
      digitalWrite(10,LOW);
      digitalWrite(9,LOW);
      digitalWrite(8,LOW);
      digitalWrite(7,LOW);
      digitalWrite(6,LOW);
      digitalWrite(5,LOW);
      digitalWrite(4,LOW);
    break;
    case 10:
      digitalWrite(13,HIGH);
      digitalWrite(12,LOW);
      digitalWrite(11,LOW);
      digitalWrite(10,LOW);
      digitalWrite(9,LOW);
      digitalWrite(8,LOW);
      digitalWrite(7,LOW);
      digitalWrite(6,LOW);
      digitalWrite(5,LOW);
      digitalWrite(4,LOW);
    break;
  }
}

Credits

dhorton668

dhorton668

4 projects • 5 followers

Comments