本帖最后由 zoey不种土豆 于 2024-12-31 17:04 编辑  
 
在这个项目中,我们将探索Processing与Arduino的联合编程魅力,通过简单的界面交互实现创意的RGB灯光控制。想象一下,只需轻点Processing界面上的按钮,就能远程操控Arduino板上连接的RGB LED灯打开和关闭。这不仅是一次编程技能的实践,更是将数字创意融入日常生活的有趣尝试。让我们一起动手,用代码点亮生活的色彩吧! 
  元件清单 
 
 
  硬件连接 
 图 1 调光面板连线图  
  为了实现电脑上的Processing面板对Arduino控制的RGB炫彩灯进行颜色控制,首先需要确保安装了必要的软件。下面是Processing的详细安装步骤(由于版本更新等原因,以下步骤仅供参考)。  
    
 
根据您的操作系统(Windows, macOS, Linux)选择合适的安装包进行下载。 (以下安装步骤以windows为例)  
 
 
   下载完成后,按照安装向导完成安装过程  
 将下载的文件解压缩  
  双击解压缩文件中的processing.exe文件以运行processing。  
   
 只需点击“Get Started”即可进入processing编程界面。  
    
  编写你的第一个Processing程序  
 你现在正在运行Processing开发环境(PDE)。界面功能如下所示:  
  
 
 在文本编辑器中,输入以下内容: ellipse(50, 50, 80, 80);  
  
  这行代码的意思是“绘制一个椭圆,其中心距离左边50像素,距离顶部50像素,宽度和高度均为80像素。”点击工具栏上的运行按钮(三角形按钮)。  
  
  如果你输入的所有内容都是正确的,那么你会在屏幕上看到一个圆。  
  
  如果你没有正确输入,消息区域会变成红色,并显示错误信息。  
 
如果发生这种情况,请确保你已完全复制了示例代码:数字应包含在括号内,并且每个数字之间用逗号隔开,行尾应有一个分号。  
   简单了解Processing软件的使用规则后,你就可以参考下方的程序代码实现其与Arduino的互动效果啦!  
   示例代码Processing 样例代码: 
			
			
			- // 项目 - 调光面板  
 - 
 - import processing.serial.*; // 导入串口通信库  
 - 
 -   
 - 
 - Serial myPort; // 创建串口对象  
 - 
 -   
 - 
 - int circleX, circleY; // 按钮的位置  
 - 
 - int circleSize = 100; // 按钮的直径  
 - 
 -   
 - 
 - color currentColor, baseOffColor, baseOnColor; // 颜色变量  
 - 
 - color circleColor; // 颜色变量  
 - 
 - color circleHighlight; // 颜色变量  
 - 
 -   
 - 
 - boolean circleOver = false; // 判断鼠标是否在按钮上  
 - 
 -   
 - 
 - PFont f; // 字体类型  
 - 
 - void setup() {  
 - 
 -   size(600, 400); // 设置屏幕大小
 - 
 -   background(200); // 背景颜色
 - 
 -   
 - 
 -   circleColor = color(255, 30, 30); // 设置按钮原本颜色变量  
 - 
 -   circleHighlight = color(255, 100, 100); // 设置按钮高亮颜色变量  
 - 
 -  
 - 
 -   circleX = width / 4 * 2; // 设置按钮的X坐标  
 - 
 -   circleY = height / 2; // 设置按钮的Y坐标  
 - 
 -   
 - 
 -   printArray(PFont.list()); // 打印计算机上的字体列表  
 - 
 -   f = createFont("Ebrima Bold", 20); // 设置字体  
 - 
 -   textFont(f); // 应用字体  
 - 
 -   
 - 
 -   String portName = "COM3"; // 输入你的COM端口  
 - 
 -   myPort = new Serial(this, portName, 9600); // 选择第一个端口  
 - 
 -   print(portName); // 打印端口名  
 - 
 - }  
 - 
 -   
 - 
 - void draw() {  
 - 
 -   update(mouseX, mouseY); // 调用更新方法   
 - 
 -   
 - 
 -   if (circleOver) {  
 - 
 -     fill(circleHighlight); // 鼠标在按钮上时填充高亮颜色  
 - 
 -   } else {  
 - 
 -     fill(circleColor); // 鼠标不在按钮上时填充正常颜色  
 - 
 -   }  
 - 
 -  
 - 
 -   circle(circleX, circleY, circleSize); // 绘制圆形按钮  
 - 
 -   stroke(255); // 边框颜色  
 - 
 -   fill(140, 25, 25); // 文本颜色
 - 
 -   textAlign(CENTER); // 文本对齐方式
 - 
 -   text("RED", width / 4 * 2, height / 2 + 10); // 显示文本  
 - 
 -   
 - 
 - }  
 - 
 -   
 - 
 - void update(int x, int y) {  
 - 
 -   if (circleOver(circleX, circleY, circleSize)) {  
 - 
 -     circleOver = true; // 鼠标在按钮上  
 - 
 -   } else {  
 - 
 -     circleOver = false; // 鼠标不在按钮上  
 - 
 -   }  
 - 
 - }  
 - 
 -   
 - 
 - boolean circleOver(int x, int y, int diameter) {  
 - 
 -   float disX = x - mouseX;  
 - 
 -   float disY = y - mouseY;  
 - 
 -   if (sqrt(sq(disX) + sq(disY)) < diameter / 2) {  
 - 
 -     return true; // 鼠标在按钮上  
 - 
 -   } else {  
 - 
 -     return false; // 鼠标不在按钮上  
 - 
 -   }  
 - 
 - }
 - 
 -  
 - 
 - int clicknumber; // 点击次数  
 - 
 - void mousePressed() {  
 - 
 -   if (circleOver) {  
 - 
 -   
 - 
 -     clicknumber = clicknumber + 1;  
 - 
 -     if (clicknumber % 2 == 1) {  
 - 
 -       print("RedON"); // 打印信息"RedOn"
 - 
 -       myPort.write('1'); // 发送值1  
 - 
 -       background(200); // 背景颜色
 - 
 -     } else {  
 - 
 -       myPort.write('2'); // 发送值2  
 - 
 -       print("RedOff"); // 打印信息"RedOff"
 - 
 -       background(50); // 背景颜色
 - 
 -     }  
 - 
 -   }  
 - 
 - }  
 
  复制代码
  
Arduino IDE 样例代码: - // 项目 - 调光面板  
 - 
 - int redPin;  
 - 
 - void setup() {  
 - 
 -   Serial.begin(9600); // 开启串口通信  
 - 
 -   redPin = 9;  
 - 
 -   pinMode(redPin, OUTPUT); // 设置Arduino引脚为输出  
 - 
 - }  
 - 
 - void loop() {  
 - 
 -   if (Serial.available() > 0) { // 检查串口是否有数据  
 - 
 -     char led = Serial.read(); // 读取串口数据  
 - 
 -     if (led == '1') { // 检查串口读取的数据  
 - 
 -         digitalWrite(redPin, HIGH); // 红灯亮  
 - 
 -     } else if (led == '2') { // 检查串口读取的数据  
 - 
 -         digitalWrite(redPin, LOW); // 红灯灭  
 - 
 -     }  
 - 
 -   }  
 - 
 - }
 
  复制代码
    
 
代码回顾Arduino IDE与Processing的交互主要通过串口通信(Serial Communication)实现,使得Arduino可以控制硬件设备(如RGB LED)并将数据发送到计算机,而Processing则能接收这些数据并进行可视化处理或发送控制指令给Arduino。  
 Arduino通过接收到的指令不同,执行对应的操作。  
 虽然在代码示例部分Processing代码和Arduino代码是两组独立的代码程序。但两组代码不是完全割裂的,而是相互配合来运行和使用的。所以在下方的代码讲解过程中,虽然为了代码讲解的连续和完整性,不会把两个程序穿插进行讲解。但请将两组代码对照着理解,这有助于你更好的理解代码的逻辑原理。  
   Processing程序代码回顾 
在setup()函数前,导入库和变量定义   - import processing.serial.*;  
 - 
 - Serial myPort;  
 - 
 - int circleX, circleY;  
 - 
 - int circleSize = 100;  
 - 
 - color currentColor, baseColor;  
 - 
 - color circlecolor;  
 - 
 - color circleHighligh;  
 - 
 - boolean circleOver = false;  
 - 
 - PFont f;
 
  复制代码
  
 这一部分导入了必要的库,定义了按钮的位置、大小、颜色,以及用于串行通信的Serial对象。同时,定义了字体和颜色变量。   在setup()函数中:   - size(600, 400);  
 - 
 -   circleColor = color(255, 100, 100);  
 - 
 -   circleHighlight = color(200, 50, 50);  
 - 
 -   baseColor = color(200);  
 - 
 -   currentColor = baseColor;  
 - 
 -   circleX = width / 4 * 2;  
 - 
 -   circleY = height / 2;
 - 
 -   printArray(PFont.list());  
 - 
 -   f = createFont("Ebrima Bold", 20);
 - 
 -   textFont(f);  
 - 
 -   String portName = "COM3";
 - 
 -   myPort = new Serial(this, portName, 9600);  
 - 
 -   print(portName);
 
  复制代码
  
在setup()函数中,设置了屏幕大小、按钮位置、颜色和字体。  
 很重要的是建立了与Arduino的串口通信连接,使用String portName = "COM3";输入Arduino连接的设备端口号,并初始化了串行通信。   draw()函数用于在屏幕上绘制所有元素:   复制代码
    
 用于更新鼠标位置,update()函数用于判断鼠标是否停留在按钮上。  
   -  if (circleOver) {  
 - 
 -     fill(circleHighlight);
 - 
 -   } else {  
 - 
 -     fill(circleColor);   
 - 
 -   }
 
  复制代码
    
 用if-else进行判断来更新按钮颜色,当鼠标停留在按钮区域显示高亮颜色;否则显示按钮原本颜色。  
   -   circle(circleX, circleY, circleSize);
 - 
 -   stroke(255);
 - 
 -   fill(140, 25, 25);
 - 
 -   textAlign(CENTER);
 - 
 -   text("RED", width / 4 * 2, height / 2 + 10);    
 
  复制代码
  
使用circle(x, y, d)函数绘制圆形(配合对应函数做按钮使用),其中x和y是圆形中心的位置,d对应的是圆形的直径。并绘制该圆形的边框,文本内容颜色和位置。  
   update()函数根据鼠标的当前位置(x, y)更新每个按钮的悬停状态。   - void update(int x, int y) {  
 - 
 -   if (circleOver(circleX, circleY, circleSize)) {  
 - 
 -     circleOver = true; // 鼠标在按钮上  
 - 
 -   } else {  
 - 
 -     circleOver = false; // 鼠标不在按钮上  
 - 
 -   }  
 - 
 - } 
 
  复制代码
  
这里虽然名为update,但它实际上是draw()函数中调用的一个函数,用于更新悬停状态,并不直接绘制任何内容。该函数中circleOver(circleX, circleY, circleSize)为update()函数的一个辅助方法,用于判断鼠标是否停在按钮圆形区域内。  
   - boolean circleOver(int x, int y, int diameter) {  
 - 
 -   float disX = x - mouseX;  
 - 
 -   float disY = y - mouseY;  
 - 
 -   if (sqrt(sq(disX) + sq(disY)) < diameter / 2) {  
 - 
 -     return true; // 鼠标在按钮上  
 - 
 -   } else {  
 - 
 -     return false; // 鼠标不在按钮上  
 - 
 -   }  
 - 
 - }
 - 
 -  
 
  复制代码
  
这些辅助方法用于判断鼠标是否悬停在特定的圆形按钮上。  
 disX和disY是鼠标现在位置与按钮圆心横坐标和纵坐标的差值(这个差值有可能为正有可能为负,后续只使用该差值的平方值,所以正负无影响)。利用勾股定理a²+b²=c²,使用sqrt(sq(disX) + sq(disY))计算得出鼠标位置与按钮中心的距离,如果距离小于按钮半径,则返回true,表示鼠标悬停在该按钮上。否则返回false,表示鼠标悬停在按钮之外的位置。  
   最后,mousePressed()函数属于processing内置的事件处理函数,在用户点击鼠标时调用。  
   - void mousePressed() {  
 - 
 -   if (circleOver) {  
 - 
 -     clicknumber = clicknumber + 1;  
 - 
 -     if (clicknumber % 2 == 1) {  
 - 
 -       print("RedON");
 - 
 -       myPort.write('1');   
 - 
 -       background(200);
 - 
 -     } else {  
 - 
 -       myPort.write('2');   
 - 
 -       print("RedOff");
 - 
 -       background(50);
 - 
 -     }  
 - 
 -   }  
 - 
 - }  
 
  复制代码
  
当用户点击鼠标时鼠标 在mousePressed()函数内进行判断,当点击发生在圆形按钮内,则按下按钮次数clicknumber加1。接着对按下总次数进行判断,如果按下次数为奇数,向Arduino发送数字“1”,否则按下次数为偶数,向Arduino发送数字“2”。并在控制台输出对应的开关信息。  
   Processing程序不直接控制RGB LED的高低电平,而是通过发送数字信号给Arduino。Arduino根据接收到的数字信号,向RGB LED输出相应的高低电平,以控制其颜色和亮度。这样,Processing与Arduino协同工作,实现了对RGB LED的间接控制。  
   Arduino程序代码回顾在loop()函数中,if (Serial.available() > 0)检查串口是否有新的数据可读。如果有,就执行大括号内的代码。  
   - if (Serial.available() > 0) { 
 - 
 -   }  
 
  复制代码
  
在if执行块内,先将Processing发送的数字赋值给字符串型变量led,接下来的两个if语句检查读取的数据led。如果为'1',则通过digitalWrite(redPin, HIGH);打开LED;如果为‘2',则通过digitalWrite(redPin, LOW);关闭LED。  
   - char led = Serial.read();
 - 
 - if (led == '1') { // 检查串口读取的数据  
 - 
 -         digitalWrite(redPin, HIGH); // 红灯亮  
 - 
 -     } else if (led == '2') { // 检查串口读取的数据  
 - 
 -         digitalWrite(redPin, LOW); // 红灯灭  
 - 
 -     }  
 - 
 -  
 
  复制代码
  
课后练习使用多个按钮实现RGB LED的光线明暗度的调节,或者颜色的变化。 发挥你的想象力,制作一个功能强大的调光面板,实现更绚丽多彩的灯光效果吧!(本项目附件程序中有多个按钮版本的程序供您参考)  
附件下载: 
 示例代码.rar 
 
 |