【Processing+Arduino互动编程】

Processing串口编程

Processng的串口通信是由serial库提供的,可以通过调用成员函数来实现。
在这里插入图片描述
在processing中输入以下程序:

import processing.serial.*;
Serial myPort;

void setup()
{
  size(400,400);
}

void draw()
{
  println(Serial.list());
}

显示端口的串口号


Processing向串口发送数据

import processing.serial.*; //导入serial库
Serial port;                //实例化一个Serial对象   
String message;
void setup()
{
  message ="c";
  port =new Serial(this,"COM3",9600); //初始化port,第二个参数是端口号,第三个参数是比特率
}

void draw()
{
  port.write(message);  //发送数据
}

执行程序后Arduino板子上的RX灯一直亮起,数据不断发送,中断程序,RX灯熄灭。
在这里插入图片描述


Arduino串口编程
在这里插入图片描述
在这里插入图片描述


Arduino从串口输出字符

int c= 0;
void setup()
{ 
   Serial.begin(9600);//比特率9600
}

void loop() 
{
   if(Serial.available())
   {
     c= Serial.read();
     Serial.print("hello word:");
     Serial.println(c,DEC); 
   }
   delay(200);
}

在这里插入图片描述
从串口监视器里输入任意字符,单片机会接收到返回该字符的ASCII码。


在Processing界面上画一个矩形,当用鼠标单击矩形内的时候,Arduino板载的LED灯(13引脚)点亮,单击矩形外的时候,Arduino板载的LED灯熄灭。

processing代码

import processing.serial.*;
Serial port;
void setup()
{
  port =new Serial(this,"COM3",9600);
  size(400,400);
}
void draw()
{
  background(125);
  fill(255);
  rect(100,100,50,50);
}

void mouseClicked()
{
  if((mouseX>=100)&(mouseX<=150)&(mouseY>=100&mouseY<=150))
  {
    println("LED turn ON!");
    port.write("a");
  }
  else
  {
    println("LED trun OFF!");
    port.write("b");
  }
}

arduino代码

int c =0;
void setup()
{
    Serial.begin(9600); //比特率9600
    pinMode(13,OUTPUT); //设置数字引脚第13引脚为输出模式
    digitalWrite(13,LOW);//设置该引脚的初始值为低电平
}

void loop() 
{
   if(Serial.available())
   {
      c=Serial.read();
      if(c==97)                //收到字母a,相当于97
        digitalWrite(13,HIGH); //LED亮
      else
        if(c==98)              //收到字母b,相当于98
          digitalWrite(13,LOW);//LED灭
         
   }
}

在arduino上接一个开关,长按开关,processing的绘制的圆形会变成红色;松开开关,processing上的圆变成绿色。初始为绿色。

processing代码

import processing.serial.*;  //导入serial库
Serial myPort;               //实例化Serial对象
void setup()
{
  size(300,300);
  ellipse(100,100,100,100);
  myPort =new Serial(this,"COM3",9600); //初始化myport(根据Arduino分配的端口号填写)
}

void draw()
{
  while(myPort.available()>0)  //监听端口          
  {
    char inByte =myPort.readChar();//读取字节
    println(inByte);             //显示接收到的字节
    switch(inByte)
    {
      case 'a':                    //当接收的字母为a时填充红色
            fill(0,255,0);
            ellipse(100,100,100,100);//重新绘圆
            break;
      case 'b':
            fill(255,0,0);         //当接收到的字母为b时填充绿色
            ellipse(100,100,100,100);
      default:break;
    }
  }
}

arduino代码

boolean button; //定义布尔类型变量
void setup() 
{
   button =false;//初始值为false
   pinMode(8,INPUT);//定义8引脚为输入模式
   Serial.begin(9600);//设置比特率为9600bps

}

void loop()
{
  button =digitalRead(8);//读取第8引脚
  if(button)
  {
    Serial.write("a");//读到高电平发送‘a’
  }
  else
  {
    Serial.write("b");//读到低电平发送‘b’
  }

}

在这里插入图片描述
按下开关后:
在这里插入图片描述


实现arduino与processing双向收发

processing代码

import processing.serial.*; //导入serial库
Serial myPort;              //实例化一个Serial对象
int lf=10;                  //换行符号的ASCII码值
String myString =null;      //定义一个字符串变量
void setup()
{
  size(300,300);
  background(125);
  myPort =new Serial(this,"COM3",9600);
  myPort.clear();
}

void draw()
{
  rect(100,100,50,50);
  while(myPort.available()>0) //监听端口
  {
    myString  = myPort.readStringUntil(lf);//读字符串,直到出现换行符后,将字符串赋值给myString变量
    if(myString!=null)
    {
      background(125); //清空屏幕
      text(myString,10,30); //灯光开启,关闭提示显示屏幕左上角
    }
  }
}

void mouseClicked()
{
  if((mouseX>=100)&(mouseX<=150)&(mouseY>=100)&(mouseY<=150)) //鼠标在矩形区域内单机时
  {
    myPort.write("a"); //往串口发送a
  }
  else
  {
    myPort.write("b");//发送b
  }
}

arduino代码

int c= 0;
void setup()
{
  Serial.begin(9600); //比特率9600
  pinMode(13,OUTPUT); //设置数字引脚第13脚为输出模式
  digitalWrite(13,LOW);//设置该引脚的初始值为低电平
}

void loop()
{
  if(Serial.available())
  {
    c=Serial.read();
    if(c==97)               //如果收到字母a(ASCII码值为97)
    {
      digitalWrite(13,HIGH);//第13引脚置为高电平,LED灯亮
      Serial.println("Light turn ON");//向着Processing发送灯已开启的字符串,结尾处有换行符
    }
    else
    {
      if(c==98) //接收到字母b
      {
        digitalWrite(13,LOW);//第13引脚置为高电平,LED灯亮
        Serial.println("Light turn OFF");//向Processing发送灯灭的字符串
      }
    }
  }
}

在这里插入图片描述
在这里插入图片描述
readStringUntil()函数能一直读取字符串,直到出现事先约定好的中指符号,使用该函数能完整的读取整个字符串。若使用readString()函数则可能会出现读不到完整的字符串,或者只读一半的情况。


Arduino读取声音传感器

声音传感器的模拟输出A0可实时输出麦克风的电压信号,数字输出口D0相当于一个开关,在没有声音或者声音较弱的时候,输出低电平,当声音强度到达一个阀值(可通过调节电位器来改变)时,才输出高电平。
Arduino代码:

int sensorPin =A5;   //模拟5输入端口
int DigitalInput =2;//数字2输入端口
int LEDPin =13;      //LED显示端口
int sensorValue =0;   //声音值变量
boolean threshold;

void setup()
{
  pinMode(sensorPin,INPUT);
  pinMode(DigitalInput, INPUT);
  pinMode(LEDPin,OUTPUT);
  Serial.begin(9600);
}
void loop()
{
  sensorValue =analogRead(sensorPin); //读声音传感器的值
  threshold =digitalRead(DigitalInput);
  if(threshold)
  {
    digitalWrite(LEDPin,HIGH);        //大于阈值灯亮
  }
  else
  {
    digitalWrite(LEDPin,LOW);         //小于阈值灯灭
    delay(50);
    Serial.println(sensorValue,DEC);  //以十进制的形式输出声音值
  }
}

在这里插入图片描述


Processing绘制振动条

通过改变正弦曲线的振幅和相位,就能显示出振动条的效果。
正弦曲线表达式:
y = A*sin(x+f)+b
A:曲线的振幅
x:横坐标上的变量
f:相位
b:纵坐标上的初始位置

processing代码

float offset =100;     //正弦曲线零点向y轴移动的值
float scaleVal =35;    //曲线振幅
float angleInc =PI/60; //角速度,控制曲线的正弦周期
float angle =0;
float dx =0;           //x轴的偏移量

void setup()
{
  size(600,200);
  noStroke();
}

void draw()
{
  background(204);
  fill(0);
  for(int posx =0;posx<=width;posx++)//从左向右,每次加一个单位直到画面的右边
  {
    float posy =offset+(sin(angle-dx)*scaleVal); //求出曲线的下,y坐标
    rect(posx,posy,1,1);       //画出该点
    angle+=angleInc;           //角速度增加,控制曲线的正弦周期
  }
  dx+=0.05;                    //改变曲线的相位,值越小曲线运动越慢
  angle=0;                     //重置角度
}

在这里插入图片描述


声音振幅的显示

Arduino 读取声音传感器的数值,通过串口传给Processing。Processing将读取到的数据转化为曲线的振幅。

Processing代码:

import processing.serial.*;              //导入Serial库

Serial myPort;                           //实例化一个Serial对象

public static final char HEADER ='h';    //从串口读取信息的第一个字符的效验符

public static final short LF =10;        //每次从串口读取信息的长度

float vol;                               //音量变量
float offset =100;                       //正弦曲线零点向y轴移动的值
float scaleVal =35;                      //曲线振幅
float angleInc =PI/60;                   //角速度,控制曲线的正弦周期
float angle =0;
float dx =0;                             //x轴的偏移量
float under;                             //振幅的最小量
float high =200;                         //音量的最大值
String [] com;

void setup()
{
  println(Serial.list());                //获取当前可用串口列表,并保存到com中
  com =Serial.list();
  myPort =new Serial(this,com[1],9600);  //初始化myPort,读取第一个可用串口,串口比特率为9600
  myPort.bufferUntil('\n');              //从串口读取数据时遇到换行符则结束读取
  size(600,200);
  noStroke();
  frameRate(60);
}

void draw()
{
  scaleVal =map(vol,under,high,0,90);    //将音量从范围为under~high插值到0~90
  background(204);
  fill(255,0,0);
  rect(20,20,20,20);                     //绘制一个矩形,当鼠标单击它时获取当前背景噪音,并以当前噪音为基准线
  fill(0);
  for(int posx =0;posx<=width;posx++)
  {
    float posy =offset+(sin(angle-dx)*scaleVal); //从左往右,每次加一个单位直到画面的右边
    rect(posx,posy,1,1);                          //画出该点
                                            
    angle+=angleInc;                              //角度增加
  }
  dx+=0.05;                                       //改变曲线的相位,值越小曲线运动越慢 
  angle =0;                                       //角度重置
}
void serialEvent(Serial myPort)
{
  String message =myPort.readStringUntil(LF);     //返回一个字符串缓冲区,并包括一个特殊字符
  if(message!=null)                               //当读取到的信息不为空时
  {
    String [] data =message.split(",");           //将字符串信息以逗号(“,”)分隔
    
    if(data[0].charAt(0)==HEADER)                 //当data中第一个字符为h时
    {
      if(data.length>1)                           //当data长度大于1的时候
      {
        vol =Integer.parseInt(data[1]);           //获取音量数据大于当前设定的最大值时
        if(high<vol)                               //当最大值设置为读取到的音量的值
        {
          vol = high;
        }
        if(under>vol)                             //当音量数据大于当前设定的最小值时
        {                  
          vol=under;                              //将最小值设置为读取到的音量的值       
        }
      }
    }
  }
}
void mouseClicked()
{
  if(mouseX<40&&mouseX>20)
  {
    if(mouseY<40&&mouseY>20)
    {
      under =vol;
    }
  }
}

arduino代码

int sensorPin =A5;

int sensorValue =0;

void setup()
{
  pinMode(sensorPin,INPUT);
  Serial.begin(9600);
}
void loop()
{
  sensorValue =analogRead(sensorPin);
   Serial.println(sensorValue,DEC);
}

旋转编码器控制播放音乐

在这里插入图片描述
Arduino读取编码器值

const int interruptA =0;                   //中断InterruptA在0引脚上
int CLK =2;                                //连接D2的脉冲信号
int DT=3;                                  //连接D3的脉冲信号,用于判断
int SW =4;                                 //正转(前进)或者反转(后退)
int COUNT =0;                              //连接D4的开关信号

void setup()
{
  attachInterrupt(interruptA,RoteStateChanged,FALLING);//外部中断,高电平变为低电平触发,调用中断处理字函数RotestateChanged()
  pinMode(CLK,INPUT);
  digitalWrite(2,HIGH);
  pinMode(DT,INPUT);
  digitalWrite(3,HIGH);
  pinMode(SW,INPUT);
  digitalWrite(4,HIGH);
  Serial.begin(9600);
}
void loop()
{
  if(!(digitalRead(SW)))   //按下按钮
  {
    COUNT =0;              //计数清零
    Serial.println("STOP COUNT =0");//串口输出清零
    delay(2000);           //延迟2秒
  }
  Serial.println(COUNT);   //如果没有按钮,输出计数值
}
void RoteStateChanged()    //当CLK下降沿触发的时候,进入中断
{
  if(digitalRead(DT))      //当DT为高电平时,前进方向
  {
    COUNT++;               //计数器累加
    delay(20);
  }
  else
  {
    COUNT--;
    delay(20);
  }
}

Processing读取音乐文件用arduino调节音量大小

processing代码

import processing.serial.*;                         //导入Serial和minim函数库
import ddf.minim.*;
Minim minim;                                        //实例化一个Minim对象
AudioPlayer song;                                   //实例化一个音乐播放器对象
Serial port =new Serial(this,"COM3",9600);
float volume =-40;                                  //初始音量大小

void setup()
{
  size(300,300);
  minim =new Minim(this);                           //初始化minim
  song =minim.loadFile("Michal.mp3");               //初始化song对象,读取音乐文件
  song.play();                                       //播放音乐
  song.loop();                                       //循环播放
}

void draw()
{
   background(125); 
   if(port.read()=='a')                             //如果Processing从串口读到字符a,增大音量
   {
     volume++;
   }
   if(port.read()=='b')                              //如果Processing从串口读到字符b,减小音量
   {
     volume--;
   }
   song.setGain(volume);
}

void stop()                                          //停止播放音乐
{
  song.close();                                      //关闭音乐
  minim.stop();
  super.stop();
}

arduino代码

const int interruptA =0;                   //中断InterruptA在0引脚上
int CLK =2;                                //连接D2的脉冲信号
int DT=3;                                  //连接D3的脉冲信号,用于判断
int SW =4;                                 //正转(前进)或者反转(后退)
int COUNT =0;                              //连接D4的开关信号

void setup()
{
  attachInterrupt(interruptA,RoteStateChanged,FALLING);//外部中断,高电平变为低电平触发,调用中断处理字函数RotestateChanged()
  pinMode(CLK,INPUT);
  digitalWrite(2,HIGH);
  pinMode(DT,INPUT);
  digitalWrite(3,HIGH);
  pinMode(SW,INPUT);
  digitalWrite(4,HIGH);
  Serial.begin(9600);
}
void loop()
{
  if(!(digitalRead(SW)))   //按下按钮
  {
    COUNT =0;              //计数清零
  }
}
void RoteStateChanged()    //当CLK下降沿触发的时候,进入中断
{
  if(digitalRead(DT))      //当DT为高电平时,前进方向
  {
    COUNT++;               //计数器累加
    Serial.println('a');
    delay(50);
  }
  else
  {
    COUNT--;
    delay(50);
    Serial.println('b');
  }
}

运行程序后 转传感器的旋钮改变音量大小。


跟随环境光变化的太阳

processing代码

PImage img;
import processing.serial.*;
Serial myPort;

void setup()
{
  myPort =new Serial(this,"COM3",9600);
  size(500,500);
  img =loadImage("sun.jpg");
  background(255);
  myPort.clear();
}
int data;

void draw()
{
  if(myPort.available()>0)
  {
    data=myPort.read();
    if(data>255)
    {
      data =255;
    }
    data =255-data;
    println(data);
  }
  sun(data);
 // println("");
}

void sun(int light)
{
  tint(light);
  image(img,0,0);
}

arduino代码


const int photocellPin = A0; //photoresistor module attach to A0
const int ledPin = 13;      //pin 13 built-in led
const int relayPin=8;      //relay module attach to digital 8
int outputValue = 0;

void setup()
{
  pinMode(relayPin,OUTPUT); 
  pinMode(ledPin,OUTPUT);
  Serial.begin(9600); 
}

void loop()
{
  outputValue = analogRead(photocellPin);
  Serial.write(outputValue); //print it in serial monitor
  if(outputValue <= 200) //if the value of photoreisitor is greater than 400
  {
    digitalWrite(ledPin,HIGH); //turn on the led 
    digitalWrite(relayPin,LOW); //relay connected
  }
  else //else
  {
    digitalWrite(ledPin,LOW);
    digitalWrite(relayPin,HIGH);
  }
  delay(20); //delay 1s
}


在这里插入图片描述
在这里插入图片描述


超声波测距传感器的读取与显示
在这里插入图片描述
在这里插入图片描述

Arduino读取超声波传感器

int outputPin =2;              //接超声波Trig到数字D2脚
int inputPin =3;               //接超声波Echo到数字D3脚

void setup()
{
  Serial.begin(9600);
  pinMode(inputPin,INPUT);
  pinMode(outputPin,OUTPUT);
}

void loop()
{
  digitalWrite(outputPin,LOW);
  delayMicroseconds(2);
  digitalWrite(outputPin,HIGH);//发出持续时间为10微秒到Trig脚驱动超声波检测
  delayMicroseconds(10);
  digitalWrite(outputPin,LOW);
  int distance =pulseIn(inputPin,HIGH);   //接收脉冲的时间
  distance =distance/58;                  //将脉冲时间转换为距离值
  Serial.print("The distance is :");      
  Serial.println(distance);
  delay(50);
}

在这里插入图片描述
串口监测
在这里插入图片描述


Processing绘制距离与提示

读取一张电动车的图片,在右边画上一堵墙,墙上的读数是电动车与墙的距离。用键盘“左”和“右”键控制电动车原理或靠近墙。与墙的距离会实时显示在屏幕右上角。最远为450cm,最近为0cm。

PImage electrocar;
int x =0,y =220;
int distance =0;

void setup()
{
  size(640,480);
  electrocar =loadImage("diandongche.jpg");      //读取图片
  background(255);                           
  image(electrocar,x,y);
}

void draw()
{
  background(255);
  fill(30,40,40);
  rect(600,80,30,395);
  image(electrocar,x,y);
  distance=450-x*450/(600-electrocar.width);  //换算与墙之间的距离,设其最大值为450m
  text("Distance is "+distance+"CM",250,50);
}

void keyPressed()                             //特殊键的key值为CODED,此时需要keyCode再次判断
{
 if(key==CODED)
 {
   switch(keyCode)
   {
     case LEFT:                               //按下“左”键
          if(x>0)
          {
            x=x-1;
          }
          else
          {
            x=0;
          }
          break;
     case RIGHT:                               //按下“右”键
     if(x<(600-electrocar.width))
     {
       x=x+1;
     }
     else
     {
       x= 600-electrocar.width;
     }
     break;
     default:
     break;
 }
 }
}

在这里插入图片描述


根据该距离值与墙的距离绘制电动车。超声波测距传感器读取的数值大,则电动车离墙的距离远,读取的数值小,则电动车离墙的距离近。

processing代码:

import processing.serial.*;
Serial myPort;
PImage electrocar;
int x =0,y =220;
int distance =0;

void setup()
{
  size(640,480);
  electrocar =loadImage("diandongche.jpg");
  myPort =new Serial(this,"COM3",9600);
}

void draw()
{
  if(myPort.available()>0)
  {
    distance =myPort.read();
    println(distance);
  }

  background(255);
  fill(30,40,40);
  rect(600,80,30,395);
  x =(450-distance)*(600-electrocar.width)/450; //将读取的距离值换算成实际的坐标
  image(electrocar,x,y);
  text("Distance is "+distance+"CM",250,50);
}

Arduino代码

int outputPin =2;              //接超声波Trig到数字D2脚
int inputPin =3;               //接超声波Echo到数字D3脚

void setup()
{
  Serial.begin(9600);
  pinMode(inputPin,INPUT);
  pinMode(outputPin,OUTPUT);
}

void loop()
{
  digitalWrite(outputPin,LOW);
  delayMicroseconds(2);
  digitalWrite(outputPin,HIGH);//发出持续时间为10微秒到Trig脚驱动超声波检测
  delayMicroseconds(10);
  digitalWrite(outputPin,LOW);
  int distance =pulseIn(inputPin,HIGH);   //接收脉冲的时间
  distance =distance/58;                  //将脉冲时间转换为距离值      
  Serial.write(distance);
  delay(50);
}

在这里插入图片描述
在这里插入图片描述


控制彩色LED灯

int Red =3;
int Green =5;
int Blue =6;

void setup()
{
  pinMode(Red,OUTPUT);
  pinMode(Green,OUTPUT);
  pinMode(Blue,OUTPUT);
}

void loop()
{
  analogWrite(Red,random(0,255));
  analogWrite(Green,random(0,255));
  analogWrite(Blue,random(0,255));
  delay(200);
}

在这里插入图片描述


Processing进度条控制

int redDisplay,greenDisplay,blueDisplay;  //定义R,G,B 3个颜色分量显示的长度变量
int red,green,blue;                       //定义R,G,B三种颜色分量的值的变量

void setup()
{
  size(700,500);
}

void draw()
{
  background(204);
  rectMode(CORNER);
  noFill();                              //不填充颜色
  strokeWeight(2);                       //三个进度条的边框厚度为2个像素
  stroke(255,0,0);                       //描边颜色为红色
  rect(50,100,500,50);                   //绘制红色分量进度条的边框
  stroke(0,255,0);                       //描边颜色为绿色
  rect(50,200,500,50);                   //绘制绿色分量进度条的边框
  stroke(0,0,255);                       //描边颜色为蓝色
  rect(50,300,500,50);                   //绘制蓝色分量进度条的边框
  fill(red,0,0);                         //填充颜色为当前红色分量的值
  rect(50,100,redDisplay,50);            //以当前红色分量的长度画出进度条
  fill(0,green,0);                       //填充颜色为当前绿色分量的值
  rect(50,200,greenDisplay,50);          //以当前绿色分量的长度画出进度条
  fill(0,0,blue);                        //填充颜色为当前蓝色分量的值
  rect(50,300,blueDisplay,50);           //以当前蓝色分量的长度画出进度条
  fill(red,green,blue);                  //以当前R,G,B分量合成的颜色值为填充,画出一个矩形
  rect(300,400,50,50);
}
void mouseClicked()                         //定义一个鼠标事件
{
  if(mouseX<=550&&mouseX>=50)             
  {
    if(mouseY<=150&&mouseY>=100)             //当鼠标指针在该范围时,读取mouseX的值,映射到0~255,为红色颜色分量的值
    {
      red =(int)map(mouseX,50,550,0,255);
      redDisplay =mouseX-50;
    }
    else if(mouseY<=250&&mouseY>=200)       
    {
      green =(int)map(mouseX,50,550,0,255);
      greenDisplay =mouseX-50;
    }
    else if(mouseY<=350&&mouseY>=300)
    {
      blue=(int)map(mouseX,50,550,0,255);
      blueDisplay =mouseX-50;
    }
  }
}

在这里插入图片描述


Processing调节彩色LED灯

processing通过R,G,B分量经串口发送到Arduino上面。Arduino经过处理数据,将R,G,B各分量传送到RGB彩色LED模块,就能实现颜色的改变。
processing代码

import processing.serial.*;
Serial port =new Serial(this,"COM3",9600);
int redDisplay,greenDisplay,blueDisplay;
int red,green,blue;
String strRed,strGreen,strBlue;
String message;

void setup()
{
  size(700,500);
}

void draw()
{
  background(204);
  frame();                                  //绘制进度条边框
  RGBDisplay();                             //绘制进度条
  sendMessage();                            //发送数据
  
}
void frame()                                 //绘制进度条边框函数
{
  rectMode(CORNER);
  noFill();
  stroke(255,0,0);
  strokeWeight(2);
  rect(50,100,500,50);
  stroke(0,255,0);
  rect(50,200,500,50);
  stroke(0,0,255);
  rect(50,300,500,50);
}
void RGBDisplay()                            //绘制进度条函数
{
  rectMode(CORNER);
  noStroke();
  fill(red,0,0);
  rect(50,100,redDisplay,50);
  fill(0,green,0);
  rect(50,200,greenDisplay,50);
  fill(0,0,blue);
  rect(50,300,blueDisplay,50);
  fill(red,green,blue);
  rect(300,400,50,50);
  fill(0);
  rect(400,400,50,50);
}

void mouseClicked()                           //单击鼠标事件,改变现实的进度条,同时更新R,G,B各分量的值
{
  if(mouseX<=550&&mouseX>=50)
  {
    if(mouseY<=150&&mouseY>=100)
    {
      red =(int)map(mouseX,50,550,0,255);
      redDisplay =mouseX-50;
    }
    if(mouseY<=250&&mouseY>=200)
    {
      green =(int)map(mouseX,50,550,0,255);
      greenDisplay =mouseX-50;
    }
    if(mouseY<=350&&mouseY>=300)
    {
      blue =(int)map(mouseX,50,550,0,255);
      blueDisplay =mouseX-50;
    }
    if(mouseX<=450&&mouseX>=400)
      if(mouseY>=400&&mouseY<=450)
      {
        shut();                             //当鼠标在该区域单击时,关闭LED灯
      }
  }
}

void sendMessage()                         //定义发送数据函数
{
  strRed =red+"";                          //将red分量转换为字符串类型
  if(red<100)                              //当red分量小于100时,将red转换为字符串,并且在前面加上字符0
    strRed ="0"+red;
  if(red<10)                               //当red分量小于10时,将red转换为字符串,并且在前面加上字符00
    strRed="00"+red;
  strGreen =green+"";
  if(green<100)
    strGreen="0"+green;
  if(green<10)
    strGreen="00"+green;
  strBlue =blue+"";
  if(blue<100)
    strBlue ="0"+blue;
  if(blue<10)
    strBlue="00"+blue;
  message ="a"+strRed+strGreen+strBlue+"s";   //将R,G,B各分量连接为字符串,通过串口发送到Arduino
  port.write(message);
}

void shut()                                  //定义关闭LED灯函数
{
  redDisplay =0;                             
  greenDisplay =0;
  blueDisplay =0;
  red =0;
  green =0;
  blue =0;
}

在这里插入图片描述
在这里插入图片描述


遥感控制坦克

Arduino读取摇杆数值

int Xaxis =A0;
int Yaxis =A1;
int SW =A2;
int value =0;             //该变量读取模拟口的值

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  value =analogRead(Xaxis);       //读取X轴模拟端口0
  Serial.print("X:");
  Serial.print(value,DEC);
  value =analogRead(Yaxis);       //读取Y轴模拟端口1
  Serial.print("| Y:");
  Serial.print(value,DEC);        //读取SW按钮模拟端口2
  value =analogRead(SW);
  Serial.print("| SW:");
  Serial.println(value,DEC);      //该值设置需大小适中,太大了延时较长
  delay(40);
}

在这里插入图片描述


Processing绘制坦克和键盘控制移动

int x=300,y=200;                                   //坦克的起始坐标
int speed =3;                                      //坦克的移动速度
class Tank
{
  Tank()
  {
    
  }
  
  void DisplayTank(int px,int py,char direction)  //显示坦克的函数
  {
    background(204);
    switch(direction)                             //判断坦克的方向
    {
      case 'F':                                   //前进
      fill(255,255,0);
      rect(px-10,py,20,40);
      rect(px+30,py,20,40);
      ellipse(px+20,py+20,20,25);
      rect(px+17,py-10,6,19);
      break;
      case 'B':                                   //后退
      fill(255,255,0);
      rect(px-10,py,20,40);
      rect(px+30,py,20,40);
      ellipse(px+20,py+20,20,25);
      rect(px+17,py+30,6,19);
      break;
      case 'L':                                   //左行
      fill(255,255,0);
      rect(px,py-10,40,20);
      rect(px,py+30,40,20);
      ellipse(px+20,py+20,25,20);
      rect(px-10,py+17,19,6);
      break;
      case 'R':                                   //右行
      fill(255,255,0);
      rect(px,py-10,40,20);
      rect(px,py+30,40,20);
      ellipse(px+20,py+20,25,20);
      rect(px+30,py+17,19,6);
      break;
      default:
      break;
    }
  }
  
  void boundary(int px,int py)                  //坦克超出边界判断
  {
    if(px<10) x=10;
    if(py<10) y =10;
    if(px>(width-50)) x=width-50;
    if(py>(height-50)) y =height-50;
  }
}
Tank tank;
void setup()
{
  size(640,480);
  tank =new Tank();
  tank.DisplayTank(x,y,'F');                     //出现在初始位置
}
void draw()
{
  
}

void keyPressed()
{
  if(key==CODED)      //特殊键的key值为CODED,此时需要keyCode再次判断
  {
    switch(keyCode)
    {
      case UP:        
      y=y-speed;
      tank.boundary(x,y);
      tank.DisplayTank(x,y,'F');
      break;
      
      case DOWN:
      y=y+speed;
      tank.boundary(x,y);
      tank.DisplayTank(x,y,'B');
      break;
      case LEFT:
      x=x-speed;
      tank.boundary(x,y);
      tank.DisplayTank(x,y,'L');
      break;
      case RIGHT:
      x=x+speed;
      tank.boundary(x,y);
      tank.DisplayTank(x,y,'R');
      break;
      default:
      break;
    }
  }
  
}

在这里插入图片描述

摇杆控制坦克移动

processing代码

import processing.serial.*;
Serial myPort;
public static final char HEADER ='M';
public static final short LF =10;
public static final short portIndex =2;
public static final short centerX=515;
public static final short centerY=517;
int x=300,y=200;
int speed =3;
char Direction;

class Tank
{
  Tank()
  {
    
  }
  
  void DisplayTank(int px,int py,char direction)
  {
    background(204);
    switch(direction)
    {
      case 'F':
        fill(255,255,0);
        rect(px-10,py,20,40);
        rect(px+30,py,20,40);
        ellipse(px+20,py+20,20,25);
        rect(px+17,py-10,6,19);
        break;
      case 'B':
        fill(255,255,0);
        rect(px-10,py,20,40);
        rect(px+30,py,20,40);
        ellipse(px+20,py+20,20,25);
        rect(px+17,py+30,6,19);
        break;
      case 'L':
        fill(255,255,0);
        rect(px,py-10,40,20);
        rect(px,py+30,40,20);
        ellipse(px+20,py+20,25,20);
        rect(px-10,py+17,19,6);
        break;
      case 'R':
        fill(255,255,0);
        rect(px,py-10,40,20);
        rect(px,py+30,40,20);
        ellipse(px+20,py+20,25,20);
        rect(px+30,py+17,19,6);
        break;
      default:
        break;
    }
  }
  
  void boundary(int px,int py)
  {
    if(px<10) x=10;
    if(py<10) y=10;
    if(px>(width-50)) x=width-50;
    if(py>(height-50)) y=height-50;
  }
  
  char tankDirection(int px,int py)
{
  if((px<(centerX-30))&&(abs(px-centerX)>abs(py-centerY)))
    Direction ='L';
  if((px>(centerX+30))&&(abs(px-centerX)>abs(py-centerY)))
    Direction ='R';
  if((py<(centerY-30))&&(abs(px-centerX)<abs(py-centerY)))
    Direction ='F';
  if((py>(centerY+30))&&(abs(px-centerX)<abs(py-centerY)))
    Direction ='B';
  if((px>=(centerX-30))&&(px<=(centerX+30))&&(py>=(centerY-30))&&(py<=(centerY+30)))
    Direction='S';  
  return Direction;
  } 
}
Tank tank;
void setup()
{
  size(640,480);
  tank =new Tank();
  tank.DisplayTank(x,y,'F'); 
  myPort =new Serial(this,"COM3",9600);
  myPort.clear();
}
void draw()
{
  
}

void serialEvent(Serial myPort)
{
  String message =myPort.readStringUntil(LF);
  char direction;
  if(message!=null)
  {
    print(message);
    String [] data =message.split(",");
    println(data[1]);
    println(data[2]);
    if(data[0].charAt(0)==HEADER)
    {
      if(data.length>2)
      {
        int tempX =Integer.parseInt(data[1]);
        int tempY =Integer.parseInt(data[2]);
        print("x="+tempX);
        print(",y="+tempY);
        direction =tank.tankDirection(tempX,tempY);
        switch(direction)
        {
          case 'F':
            y =y-speed;
            tank.boundary(x,y);
            tank.DisplayTank(x,y,'F');
            break;
          case 'B':
            y =y+speed;
            tank.boundary(x,y);
            tank.DisplayTank(x,y,'B');
            break;
          case 'L':
            x =x-speed;
            tank.boundary(x,y);
            tank.DisplayTank(x,y,'L');
            break;
          case 'R':
            x =x+speed;
            tank.boundary(x,y);
            tank.DisplayTank(x,y,'R');
            break;
          case 'S':
            break;
          default:
            break;
          
        }
      }
    }
  }
}

arduino代码

int potXPin =A0;
int potYPin =A1;
char HEADER ='M';        

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  int x =analogRead(potXPin);       //读取摇杆X轴数据
  int y =analogRead(potYPin);       //读取摇杆Y轴数据
  Serial.print(HEADER);             //输出数据帧头
  Serial.print(",");                //逗号分隔符
  Serial.print(x,DEC);              //X轴数据
  Serial.print(",");                //逗号分隔符
  Serial.print(y,DEC);              //Y轴数据
  Serial.print(",");                //逗号分隔符
  Serial.println();                 //输出换行符作为帧尾
  delay(40);
}

在这里插入图片描述

  • 23
    点赞
  • 178
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个基本的智能小车processing串口通讯代码示例: ```processing import processing.serial.*; Serial myPort; //创建一个串口对象 void setup() { size(400, 300); //创建一个窗口 //打开串口连接(根据实际情况修改端口号和波特率) myPort = new Serial(this, "/dev/tty.usbmodem14101", 9600); } void draw() { //等待接收数据 if (myPort.available() > 0) { //读取串口数据 String inString = myPort.readStringUntil('\n'); if (inString != null) { //将接收到的数据打印到控制台 println("Received: " + inString); //解析接收到的数据 int sensorValue = int(inString.trim()); //根据传感器值控制小车 if (sensorValue > 500) { //向左转 myPort.write('L'); } else if (sensorValue < 100) { //向右转 myPort.write('R'); } else { //直行 myPort.write('F'); } } } } ``` 在这个示例中,我们首先使用 `import processing.serial.*;` 导入processing串口库。然后在 `setup()` 函数中创建一个串口对象 `myPort`,并打开与小车的串口连接(根据实际情况修改端口号和波特率)。 在 `draw()` 函数中,我们等待接收从小车传回的数据。如果有数据可用,我们将其读取并打印到控制台。然后解析接收到的数据,并根据传感器值控制小车的运动。在这个示例中,我们假设小车通过传感器返回一个数值,大于500时向左转,小于100时向右转,否则直行。 最后,我们使用 `myPort.write()` 函数将控制指令发送回小车,控制其运动。在这个示例中,我们将指令 'L' 发送到串口以让小车向左转,将指令 'R' 发送到串口以让小车向右转,将指令 'F' 发送到串口以让小车直行。 请注意,这只是一个基本示例,实际情况可能更加复杂,需要根据具体需求进行修改。同时,还需要确保小车和processing之间的串口通讯协议一致,以确保正确的数据传输和控制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值