Proximity Data Visualization Arduino-Processing. Running into issue with for loop visualization, layout of Processing sketch

Hi, running into an issue here that seems related to the for loop section of my processing sketch.

My aim is to re-draw the loaded image as a grid of ellipses, using .get. The Distance sensor reading from arduino, (myDis) will change the ellipses scale and the iteration within the for loop, depending on the viewers distance from the sensor.

A problem in the logic and order of the processing sketch? I have tried a few iterations of this sketch, it seems to be the for loop where I am running into an issue - Any tips or observations would be appreciated, thanks :slight_smile:

//ARDUINO CODE

#include <NewPing.h>
 
#define TRIGGER_PIN 11
#define ECHO_PIN 12
#define MAX_DISTANCE 400

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); 
int myDis;
 
void setup() {
   Serial.begin(9600);
}
 
void loop() {
  myDis = sonar.ping_in();
  Serial.println(myDis);
  Serial.write(myDis);
  delay(100);
}
//PROCESSING SKETCH

import processing.serial.*;

Serial mySerial;

String myString = null;
int nl = 10;
float myDis; // myDistance 

PImage img;

void setup() {

  size(918, 960, P2D); //same size as img

  String myPort = Serial.list() [1];
  mySerial = new Serial(this, myPort, 9600);

  pixelDensity(displayDensity());
  imageMode(CORNER);
  img = loadImage("artwork_2.jpg");

  //display myDis sensor reading
  textSize(128);
  fill(255);
  noStroke();
  text(myDis, 40, 120);
}

void draw() {

  while (mySerial.available() > 0) {

    myString = mySerial.readStringUntil(nl); //Strip

    if (myString != null) {

      background(0);
      myDis = int(myString);
      println(myDis);


      for (int x = 0; x < img.width; x += myDis) {
        for (int y = 0; y < img.height; y += myDis) {

          pushMatrix();

          color pix = img.get(x, y);
          fill(pix);
          noStroke();

          ellipse(x, y, myDis, myDis);

          popMatrix();
        }
      }
    }
  }
}

FIX: It’s fixed just about - Trim gets rid of unnecessary characters in the data such as white space/symbols, I believe this was part of the issue. I’ve also moved my for loop outside of the while loop, and there is an added function for error handling.

If anyone wants to expand on this code feel free.
*My next step is to try and make it run smoother/with less lag, any pointers let me know :slight_smile:

// FIXED PROCESSING SKETCH
import processing.serial.*;

Serial mySerial;

String myString = null;
int nl = 10;
float myDis; // myDistance

PImage img;

void setup() {
  size(918, 960, P2D); //same size as img

  String myPort = Serial.list()[1];
  mySerial = new Serial(this, myPort, 9600);

  pixelDensity(displayDensity());
  imageMode(CORNER);
  img = loadImage("artwork_2.jpg");
}

void draw() {
  while (mySerial.available() > 0) {
    myString = mySerial.readStringUntil(nl); //STRIP

    if (myString != null) {
      myString = myString.trim(); // error with white space and additional characters interfering, trim gets rid of these

      if (isValid(myString)) {
        myDis = float(myString);
        println(myDis);
      } else {
        println("Invalid value: " + myString);
        
      }
    }
  }

  background(0);

  //display myDis sensor reading
  textSize(128);
  fill(255);
  noStroke();
  text(myDis, 40, 120);

  for (int x = 0; x < img.width; x += myDis) {
    for (int y = 0; y < img.height; y += myDis) {
      pushMatrix();

      color pix = img.get(x, y);
      fill(pix);
      noStroke();

      ellipse(x, y, myDis, myDis);

      popMatrix();
    }
  }
}

boolean isValid(String value) {
  try {
    Float.parseFloat(value);
    return true;
  } catch (NumberFormatException e) {
    return false;
  }
}

Great!

pushMatrix and popMatrix is not needed in this context

Also i am not sure about the while loop.

Wouldn’t an if-clause be enough here?
And include the for loops into it

Because draw in itself loops permanently

Also, in Arduino code the delay 100 seems pretty high. Did you read this somewhere? Try delay (5); instead ?

Thanks for your response! I will have another look at the while loop.

delay(5) works a lot better, I was initially following this tutorial: https://www.youtube.com/watch?v=NhyB00J6PiM (where the delay is (100).

I am looking at the lerp function to see if I can make the distance values transition smoother also.

1 Like

apart from lerp() there is also easing

  • It means something like “don’t apply a change at once but only gradually”

cf. Easing / Examples / Processing.org

Just curious why you send both text and binary?

Also, because myDis is an int you will only send one byte of it when using Serial.write() in the way you use it. The better way would be

Serial.write((byte *)&myDis, sizeof(myDis));

This takes the address of myDis, casts it to a pointer to a byte and writes the two bytes (8-bit processors) or four bytes (32-bit processors). You’ll have to be careful with the endianness when sending binary data.

You are suggesting a delay(5) which means you are sending more than one string of data (ending in ‘/n’) per frame.

while (mySerial.available() > 0) will receive multiple strings of data per frame and keep up with the data that is being sent from Arduino.

if (mySerial.available() > 0) will only receive one string of data per frame; the data will be stuck in the buffer until it is received the next frame and the delay between data sent from Arduino and received by Processing will keep accumulate.

You can monitor the buffer and watch it grow with a simple statement:

println(mySerial.available());

Reference:

:)

delay(100) is good for initial development, when you are trying to watch leds, console windows etc. Probably too slow for normal performance.