我可以使用 Arduino 超声波传感器在处理 move/play 中制作图像序列吗?

Can I make an image sequence in processing move/play with an Arduino ultrasonic sensor?

这是我的第一个 post 所以如果有任何不清楚的地方,我会提前道歉,我会尽快学习。在编程方面,我也是新手。使用Arduino Uno,超声波传感器HC-SR04,Processing3.5.3

在我提供的处理和 Arduino 草图中,我能够播放图像序列,当超声波传感器拾取物体的距离时,处理控制台中会打印一个“1”。

我想知道我是否可以使用这个“1”来做一个 if 语句。如果控制台打印出大于 0 的数字,则播放图像序列——否则,将只绘制一个图像(gif 将暂停)。我已经尝试了几个版本,但我不想假装我知道我在做什么。

如果有任何线索供我参考,那就太好了!或在线教程!

我觉得我只是缺少一些非常简单的东西...... 我想没有什么比这更简单了。 感谢您的宝贵时间:))

ARDUINO 代码:

#define trigPin 9
#define echoPin 10

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

void loop() {
  long distance;
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);           //CHANGE THIS??
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  distance = pulseIn(echoPin, HIGH);

  if (distance <= 2000) { //raise this number to raise the distance to wave hand
    Serial.print("1");
  } else {
    Serial.print("0");
  }
  delay(500);  
}

处理中

import processing.serial.*;

int numFrames = 22; //number of frames in animation
int currentFrame = 0;
PImage[] image = new PImage[22];
Serial myPort;
String instring = "";

void setup() {
  myPort = new Serial(this, Serial.list()[1], 9600);
  myPort.bufferUntil('\n');
  size(1600, 900);
  frameRate(30);
  background(0);
  
  //Load images below
  for(int i = 0; i<image.length; i++) {
    image[i] = loadImage("PatMovingFace" + i + ".png");
  }
}

void draw() {
  //ALL BELOW connects to arduino sensor
  while (myPort.available () > 0) {
    instring = myPort.readString();
    println(instring);
    int sensorAct = Integer.parseInt(instring, 10);
  }
  playGif();   
}

// ALL BELOW will make the pic array animate! Image moves! 

void playGif() {
  currentFrame = (currentFrame+1) % numFrames; //use % to cycle through frames!
  int offset = 0;

  for (int i = 0; i < image.length; i++) {
    //image(image[i] % numFrames), 0, 0);
    image(image[(currentFrame + offset) % numFrames], 0, 0);
    offset += 0;
    image(image[(currentFrame + offset) % numFrames], 0, 0);
    offset+= 0;
  }
}

您可以先简化/清理 playGif()

  • offset 目前似乎没有做任何事情(它从 0 到 0“递增”)
  • image() 被调用两次,使用相同的坐标在其自身之上透支相同的内容。一次 image() 调用应该做
  • 您可能不需要 for 循环,因为您一次绘制一帧
  • currentFrame是递增到下一帧,循环回到playGif()开始的开始,但是渲染图像时,数组索引递增offset (0) 再一次。目前尚不清楚意图是什么。你可以没有
  • currentFrame可以控制play/pause:如果递增则播放,否则暂停。最好将更新数据 (currentFrame) 和更新数据渲染 (image(image[currentFrame],0,0))
  • 分开
  • 您还可以将 image 数组重命名为 images,这样它更能代表它的本质,并且更难将它与 image() 函数

例如 playGif() 可以变成:

void playGif(){
      currentFrame = (currentFrame+1) % numFrames; //use % to cycle through frames!
      image(image[currentFrame], 0, 0);
}

关于使用 Arduino 的控制,如上所述,只需检查您是否获得“1”以更新 currentFrame(否则它将保持(暂停)相同的值):

void playGif(){
      if(instring.equals("1")){
         currentFrame = (currentFrame+1) % numFrames; //use % to cycle through frames!
      }
      image(image[currentFrame], 0, 0);
}

我在上面使用 equals(),因为它是 String,即使您发送的是单个字符。 (或者比较第一个字符会起作用 if(instring.charAt(0) == '1')

我也有一些注意事项:

  • 在 Arduino 代码中您使用 print(),而不是 println(),这意味着不会发送 \n,因此不需要 myPort.bufferUntil('\n');instring = myPort.readString();
  • 您可以使用 myPort.read(); 读取单个字符(顺便说一下,您可以将其与 == 进行比较(而不是字符串的 equals())(例如 if(myPort.read() == '1'){...
  • while 正在阻塞,我建议不要使用它。它不会对你的情况产生很大的影响,因为你发送的是一个字节,但在发送更多字节的更复杂的程序中,这将阻止处理渲染单个帧,直到它收到所有数据

这是一个例子:

import processing.serial.*;

int numFrames = 22; //number of frames in animation
int currentFrame = 0;
PImage[] images = new PImage[numFrames];
Serial myPort; 

void setup() {
  myPort = new Serial(this, Serial.list()[1], 9600);  
  
  size(1600, 900);                                    
  frameRate(30);                                      
  background(0);

  //Load images below
  for (int i = 0; i < numFrames; i++)
  { 
    images[i] = loadImage("PatMovingFace" + i + ".png");
  }
}

void draw() {
  // if there's at least one byte to read and it's '1'
  if(myPort.available() > 0 && myPort.read() == '1'){
    // increment frame, looping to the start
    currentFrame = (currentFrame+1) % numFrames; //use % to cycle through frames!
  }
  // render current frame
  image(images[currentFrame], 0, 0);
}

更谨慎的版本,检查可能出错的地方(串行连接、数据加载)如下所示:

import processing.serial.*;
    
int numFrames = 22; //number of frames in animation
int currentFrame = 0;
PImage[] images = new PImage[numFrames];
Serial myPort; 

void setup() {
  String[] ports = Serial.list();
  int portIndex = 1;
  if(ports.length <= portIndex){
    println("serial ports index " + portIndex + " not found! check cable connection to Arduino");
    println("total ports: " + ports.length);
    printArray(ports);
    exit();
  }
  try{
    myPort = new Serial(this, ports[portIndex], 9600);  
  }catch(Exception e){
    println("error connecting to serial port: double check the cable is connected and no other program (e.g. Serial Monitor) uses this port");
    e.printStackTrace();
  }  
  size(1600, 900);                                    
  frameRate(30);                                      
  background(0);

  //Load images below
  try{
    for (int i = 0; i < numFrames; i++)
    { 
      images[i] = loadImage("PatMovingFace" + i + ".png");
    }
  }catch(Exception e){
    println("image loading error");
    e.printStackTrace();
  }
}

void draw() {
  // if Arduino connection was successfull
  if(myPort != null){
    // if there's at least one byte to read and it's '1'
    if(myPort.available() > 0 && myPort.read() == '1'){
      // increment frame, looping to the start
      currentFrame = (currentFrame+1) % numFrames; //use % to cycle through frames!
    }
  }else{
    text("serial port not initialised", 10, 15);
  }
  
  if(images[currentFrame] != null){
    // render current frame
    image(images[currentFrame], 0, 0);
  }else{
    text("serial port not loaded", 10, 15);
  }
}

或使用函数分组的相同事物:

import processing.serial.*;

int numFrames = 22; //number of frames in animation
int currentFrame = 0;
PImage[] images = new PImage[numFrames];

final int SERIAL_PORT_INDEX = 1;
final int SERIAL_BAUD_RATE  = 9600;
Serial myPort; 

void setup() {
  size(1600, 900);                                    
  frameRate(30);                                      
  background(0);
  
  setupArduino();
  //Load images below
  loadImages();
}

void setupArduino(){
  String[] ports = Serial.list();
  int numSerialPorts = ports.length;
  // optional debug prints: useful to double check serial connection 
  println("total ports: " + numSerialPorts);
  printArray(ports);
  // exit if requested port is not found  
  if(numSerialPorts <= SERIAL_PORT_INDEX){
    println("serial ports index " + SERIAL_PORT_INDEX + " not found! check cable connection to Arduino");
    //exit();
  }
  // try to open port, exit otherwise
  try{
    myPort = new Serial(this, ports[SERIAL_PORT_INDEX], SERIAL_BAUD_RATE);  
  }catch(Exception e){
    println("error connecting to serial port: double check the cable is connected and no other program (e.g. Serial Monitor) uses this port");
    e.printStackTrace();
    //exit();
  }
}

void loadImages(){
  try{
    for (int i = 0; i < numFrames; i++)
    { 
      images[i] = loadImage("PatMovingFace" + i + ".png");
    }
  }catch(Exception e){
    println("image loading error");
    e.printStackTrace();
    //exit();
  }
}

void serialUpdateImage(){
  // if Arduino connection was successfull
  if(myPort != null){
    // if there's at least one byte to read and it's '1'
    if(myPort.available() > 0 && myPort.read() == '1'){
      // increment frame, looping to the start
      currentFrame = (currentFrame+1) % numFrames; //use % to cycle through frames!
    }
  }else{
    text("serial port not initialised", 10, 15);
  }
}

void displayCurrentImage(){
  if(images[currentFrame] != null){
    // render current frame
    image(images[currentFrame], 0, 0);
  }else{
    text("image " + currentFrame + " not loaded", 10, 25);
  }
}

void draw() {
  
  serialUpdateImage();
  
  displayCurrentImage();
}