Processing and Arduino ultrasonic sensor

Hello! I’m working on a project with processing, Arduino and an ultrasonic sensor. Now I’ve come across a problem that I can’t solve, if anyone can help me I’d be grateful!
This Processing code controls the playback of videos based on readings from a proximity sensor connected to an Arduino. Here’s a brief explanation:

  1. It loads three videos: “curtains,” “open,” and “close.”
  2. The Arduino reads the distance from a proximity sensor and sends a message (1 or 0) to Processing via serial communication based on whether a person is nearby.
  3. The code checks the message received from the Arduino, and if proximity changes, it switches the currently playing video. It also pauses the current video before starting the new one.
  4. When the “close” video reaches its end, it automatically switches to the “curtains” video.
  5. The video is displayed in the Processing window, and this process repeats continuously, allowing the videos to be controlled based on the proximity of a person to the proximity sensor.

The problem is that when any video is played for the second time, the frame from the last playback appears for 1 second and only then does the new playback begin.

Processing code:

import processing.serial.*;
import processing.video.*;

Serial arduinoPort; 
String instring = "";

Movie abrir;
Movie fechar;
Movie curtinas;
Movie atual;

boolean pessoaProxima = false;
boolean pessoaDistante = false;
boolean pessoaProximaAnterior = false;

void setup() {
  size(1280, 720);
  frameRate(30);

  // VIDEOS
  curtinas = new Movie(this, "teste.mp4");      
  abrir = new Movie(this, "abrir.mp4");
  fechar = new Movie(this, "fechar.mp4");

// Pré-carrega os vídeos na memória
  curtinas.loop();
  curtinas.read();
  
  abrir.play();
  abrir.read();
  abrir.stop();

  fechar.play();
  fechar.read();
  fechar.stop();
  
  atual = curtinas;

  // PARTA DE PARTILHA DE INFROMAÇÃO DO ARDUINO
  arduinoPort = new Serial(this, "COM3", 9600);
  arduinoPort.bufferUntil('\n');
}

void draw() {
  background(0);

  if (atual.available()) {
    atual.read();
  }

  image(atual, 0, 0);

  while (arduinoPort.available() > 0) {
    instring = arduinoPort.readString();
    println(instring);
    
    int sensorAct = -1; // Valor padrão ou um valor que indique que não há leitura válida

    if (instring != null && !instring.isEmpty()) {
      try {
        sensorAct = Integer.parseInt(instring.trim());
      } catch (NumberFormatException e) {
        println("Erro ao converter valor da porta serial para inteiro: " + e.getMessage());
      }
    }

    pessoaProximaAnterior = pessoaProxima;
    // BOOLEAN DO RESULTADO DA MENSAGEM ENVIADA PELO ARDUINO
    pessoaProxima = (sensorAct == 1);
    pessoaDistante = (sensorAct == 0);
  }

  // VERIFICA A MUDANÇA DA PROXIMIDADE DA PESSOA 
  if (pessoaProxima != pessoaProximaAnterior) {
    if (pessoaProxima) {
      abrir.jump(0); // Reinicia o vídeo "abrir" do início
      atual = abrir;
    } if (pessoaDistante) {
      fechar.jump(0); // Reinicia o vídeo "abrir" do início
      atual = fechar;
    }
    atual.play();
  }
    
  // VERIFICAR SE O VIDEO FECHAR CHEGOU AO FIM E TROCAR PARA O CURTINAS
  if (atual.time() >= atual.duration()) {
    if (atual == fechar) {
      atual = curtinas;    
    }
  }

Arduino code:

#define trigPin 4
#define echoPin 5
#define NUM_READINGS 10  // Número de leituras para a média

void setup() {
  Serial.begin(9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop() {
  long distance;
  long sum = 0;

  // Para garantir melhor leitura do sensor, e para anualar leituras erradas, elimina leituras não coerentes com as restantes para não serem lidas e não atrapalhar as mensagens para o processing
  for (int i = 0; i < NUM_READINGS; i++) {
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    distance = pulseIn(echoPin, HIGH);
    sum += distance;
    delay(30);  // curto período de tempo entre as leituras
  }

  long averageDistance = sum / NUM_READINGS;

  if (averageDistance <= 200) {
    Serial.print("1");
  } else {
    Serial.print("0");
  }
  delay(500);
}```

Hi @andreiaferrsilva, Welcome to the forum. I think you should look at your system in separate testable pieces, and prove that some parts are working perfectly. This may not tell you immediately what the problem is, but should reduce the area where it might be. I suggest:

Don’t run the processing sketch, run the Arduino and watch the output on the Serial Monitor. Move something in front of the proximity sensor. Does the output do exactly what it is supposed to?

Make a copy of your Processing sketch, in draw() have only the Serial code, and the conversion to Sensor act. Put in a print of sensorAct. Run it with the Arduino. Does it do exactly what it is supposed to do?

If I understand the Serial reference correctly the “.bufferUntil(‘\n’);” is for setting up SerialEvent which you are not using. Your Ard code is sending 0 or 1 char and that’s all I think. You might simplify the read code using Serial.read. Print out what you get.

Hope that helps things along. Please post the results.

Hi, @RichardDL, thank you for your help!

Right at the beginning of the project I tested the just the Arduino and saw the results on the serial monitor and everything was fine.

Now I tested as you suggested, leaving in the draw() only the Serial code, and the conversion to Sensor act. The arduino sends the right mensege.

I change the code just like you said.
I’m not sure if it was supposed to be this… if so, then it didn’t do anything different.

Another problem that I have come across now is that the video “curtinas” when played for the second time it only appears as a still frame, it does not play. Even with the old code, which used to work, it no longer works.

If I did something wrong I apologize if I didn’t understand

import processing.serial.*;
import processing.video.*;

Serial arduinoPort; 
String instring = "";

Movie abrir;
Movie fechar;
Movie curtinas;
Movie atual;

boolean pessoaProxima = false;
boolean pessoaDistante = false;
boolean pessoaProximaAnterior = false;

int frameCounter = 0;
boolean fecharTerminou = false;

void setup() {
  size(1280, 720);
  frameRate(30);

  // VIDEOS
  curtinas = new Movie(this, "curtinas.mp4");
  abrir = new Movie(this, "abrir.mp4");
  fechar = new Movie(this, "fechar.mp4");

  // Pré-carrega os vídeos na memória
  curtinas.loop();
  abrir.play();
  abrir.stop();
  fechar.play();
  fechar.stop();

  atual = curtinas;

  // PARTA DE PARTILHA DE INFORMAÇÃO DO ARDUINO
  arduinoPort = new Serial(this, "COM3", 9600);
}

void draw() {
  background(0);

  if (atual.available()) {
    atual.read();
  }

  image(atual, 0, 0);

  while (arduinoPort.available() > 0) {
    char receivedChar = arduinoPort.readChar(); // Lê um caractere da porta serial
    
    // Converte o caractere recebido de volta para um valor inteiro
    int sensorAct = Character.getNumericValue(receivedChar);

    println("Mensagem Arduino: " + sensorAct);

    pessoaProximaAnterior = pessoaProxima;

    // BOOLEAN DO RESULTADO DA MENSAGEM ENVIADA PELO ARDUINO
    pessoaProxima = (sensorAct == 1);
    pessoaDistante = (sensorAct == 0);
  }

  // VERIFICA A MUDANÇA DA PROXIMIDADE DA PESSOA 
  if (pessoaProxima != pessoaProximaAnterior) {
    if (pessoaProxima) {
      if (atual != abrir) {
        abrir.jump(0); // Reinicia o vídeo "abrir" do início
        atual = abrir;
        atual.play();
      }
      if (atual == fechar) {
        fechar.pause(); // Pausa o vídeo "fechar" se estiver em execução
      }
    } else if (pessoaDistante) {
      if (atual != fechar) {
        fechar.jump(0); // Reinicia o vídeo "fechar" do início
        atual = fechar;
        atual.play();
      }
      if (atual == abrir) {
        abrir.pause(); // Pausa o vídeo "abrir" se estiver em execução
      }
    }
  }
    
  // VERIFICAR SE O VIDEO FECHAR CHEGOU AO FIM E TROCAR PARA O CURTINAS
  if (atual == fechar && atual.time() >= atual.duration()) {
    atual = curtinas;
    atual.loop();
  }
}```

@andreiaferrsilva I’ve had a ultrasonic sensor for some time. Thanks for encouraging me to try it. It’s probably the same model and worked with your code. In the Processing I think I’ve found one issue.

The usual code for detecting difference compares new with previous, and inside the conditional code sets previous to new. You have ‘previous =’ in the serial action code, and that doesn’t always run. As yours is now when the value changes the difference reads true multiple times until the next serial char arrives. (This could be what you want, I haven’t understood the video part yet.)

The usual structure is:

if (pessoaProxima != pessoaProximaAnterior) {
   // code you want done on detecting different value
   pessoaProximaAnterior = pessoaProxima;
   // you have this line after serial detected
   // think move it here
}