Setting map ranges suitably

Hello everyone! can some one please explain to me why my map parameters of both Arduino and processing codes are not fluidly animating the array of pngs I have declared and then stopping with an ArrayIndexOutBoundsException error, thank you

Arduino

const int pingPin = 9;


void setup() {

  Serial.begin(9600);

}

void loop() {

  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
  
  duration = pulseIn(pingPin, HIGH);
 
  cm = microsecondsToCentimeters(duration);

  int val = map(cm, 0, 32, 0, 600);    
  Serial.println(cm);                                    
  delay(100);

}

long microsecondsToCentimeters(long microseconds) {

  return microseconds / 29 / 2;

}

Processing

import processing.serial.*;

Serial myPort;
String val;

PImage[] Artboard= new PImage[32];

int counter = 0;
PImage img;

int frame ;
float yPos;
int cm;
int intVal;

void setup () {

  size(767, 600);

  String portName = Serial.list()[2];
  myPort = new Serial(this, portName, 9600);
  myPort.bufferUntil ( '\n' );

  frameRate(60);

  Artboard[0]=loadImage("Artboard_1.png");
  Artboard[1]=loadImage("Artboard_2.png");
  Artboard[2]=loadImage("Artboard_3.png");
  Artboard[3]=loadImage("Artboard_4.png");
  Artboard[4]=loadImage("Artboard_5.png");
  Artboard[5]=loadImage("Artboard_6.png");
  Artboard[6]=loadImage("Artboard_7.png");
  Artboard[6]=loadImage("Artboard_8.png");
  Artboard[7]=loadImage("Artboard_9.png");
  Artboard[8]=loadImage("Artboard_10.png");
  Artboard[9]=loadImage("Artboard_11.png");
  Artboard[10]=loadImage("Artboard_12.png");
  Artboard[11]=loadImage("Artboard_13.png");
  Artboard[12]=loadImage("Artboard_14.png");
  Artboard[13]=loadImage("Artboard_15.png");
  Artboard[14]=loadImage("Artboard_16.png");
  Artboard[15]=loadImage("Artboard_17.png");
  Artboard[16]=loadImage("Artboard_18.png");
  Artboard[17]=loadImage("Artboard_19.png");
  Artboard[18]=loadImage("Artboard_20.png");
  Artboard[19]=loadImage("Artboard_21.png");
  Artboard[20]=loadImage("Artboard_22.png");
  Artboard[21]=loadImage("Artboard_23.png");
  Artboard[22]=loadImage("Artboard_24.png");
  Artboard[23]=loadImage("Artboard_25.png");
  Artboard[24]=loadImage("Artboard_26.png");
  Artboard[25]=loadImage("Artboard_28.png");
  Artboard[26]=loadImage("Artboard_29.png");
  Artboard[27]=loadImage("Artboard_30.png");
  Artboard[28]=loadImage("Artboard_31.png");
  Artboard[29]=loadImage("Artboard_32.png");
  Artboard[30]=loadImage("Artboard_33.png");
  Artboard[31]=loadImage("Artboard_34.png");

}

void serialEvent (Serial myPort) {

  yPos  =  float (myPort.readStringUntil ( '\n' ) ) ;  

} 

void draw() {

  background(255, 255, 255);

  frame = (int) map( yPos, 0, 32, 0, height );

  
  println(frame, yPos);
  image(Artboard[frame], 0, 0);
  
}
1 Like

you are using frame as an index for Artboard

Hence

frame = (int) map( yPos, 0, 32, 0, Artboard.length-1 );

When yPos is bigger than 32, frame could get bigger than Artboard.length-1, maybe. I think. That could be bad.

Then add

if (frame > Artboard.length-1)
    frame = Artboard.length-1 ;

after the line with map()

Chrisir

1 Like

When my previous post doesn’t solve the issue, I would look at this line.

You could add


    myString = myPort.readStringUntil(lf);
    if (myString != null) {
         yPos = float (  myString  ) ; // does this work?
    }

see https://www.processing.org/reference/libraries/serial/Serial_readStringUntil_.html

2 Likes

This works perfectly

  frame = (int) map( yPos, 0, 32, 0, ameba.length-1);

  if (frame > ameba.length-1) 
    frame = ameba.length-1;

but if I flip this order

  frame = (int) map( yPos, 32, 0, 0, ameba.length-1);

because I want the farthest reading of the ultrasonic mapping from first png to last, causes the out bound exception to appear. Adding

  myString = myPort.readStringUntil(lf);
    if (myString != null) {
         yPos = float (  myString  ) ; // does this work?
    }

does not work.

The order does matter

   frame = (int) map ( yPos, 32, 0,  ameba.length-1, 0);

   if (frame > ameba.length-1) 
      frame = ameba.length-1;

ah, that would give you the same old result… bad.

what about

  frame = (int) map ( yPos,  // value 
  32, 0,     // range 1
  0,  ameba.length-1);    // range 2

  println(frame);   // now this is to debug!   If you get a bound exception, check, what value frame had!

   // check upper and lower bound 
   if (frame > ameba.length-1) 
      frame = ameba.length-1;

   if (frame < 0) 
      frame = 0;