极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 18976|回复: 4

用Processing控制Arduino(多舵机和步进电机)

[复制链接]
发表于 2019-3-31 19:58:07 | 显示全部楼层 |阅读模式
用Processing控制Arduino(多舵机和步进电机)


作用:

1.上位机选择舵机角度和步进电机步数,通过串口发送给Arduin驱动多个舵机和步进电机.

2.上位机控制软件采用Processing (串口可选).

3.舵机及步进电机电源采用外接.


  


材料:

1.Arduino UNO

2.三个9g 舵机

3.一个步进电机

4.I2C LCD1602

5.PC(Processing)


连线图:


Arduino代码:

//arduino
#include <Wire.h>
#include <LiquidCrystal_I2C.h> //引用I2C库
//I2C 引脚接A4, A5
//设置LCD1602设备地址,这里的地址是0x3F,一般是0x20,或者0x27,具体看模块手册
LiquidCrystal_I2C lcd(0x27,16,2);  
#include <Stepper.h>
#include<Servo.h>
Servo myservo0;
Servo myservo1;
Servo myservo2;
Servo myservo3;
char data;
int servo0=2;
int servo1=3;
int servo2=4;
int servo3=5;
int pos0;
int pos1;
int pos2;
int pos3;
int step0;
int bj;
int temp=0;
int mark = 0;
//底盘步进电机
const int stepsPerRevolution=200;
Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);    //步进电机 Pin
int step=0;

void setup() {
Serial.begin(9600);
  lcd.init();                  // 初始化LCD
  lcd.backlight();             //设置LCD背景等亮
  myservo0.attach(servo0);
  myservo1.attach(servo1);
  myservo2.attach(servo2);
  myservo3.attach(servo3);
  pos0=0;
  pos1=0;
  pos2=0;
  pos3=0;
  step0=0;
  bj=0;
  myStepper.setSpeed(60);
  updateServo();
}
void loop(){
  recv_data();
  show_data();
  updateServo();
}
void recv_data(){   //
  while(Serial.available()){
    data=Serial.read();
    if(data=='%'){
    pos0=Serial.read();
    delay(100);
    pos1=Serial.read();
    delay(100);
    pos2=Serial.read();
    delay(100);
    pos3=Serial.read();
    delay(100);
    step0=Serial.read();
    delay(100);
    bj=Serial.read();   
    delay(100);
    }
     mark = 1;
  }
}
void updateServo(){
if(mark == 1){
myservo0.write(pos0);
delay(1000);
myservo1.write(pos1);
delay(1000);
myservo2.write(pos2);
delay(1000);
myservo3.write(pos3);
delay(1000);
if(bj==1 && !temp==step0){
Stepper(step0);        //步进电机+转
delay(500);
temp=step0;
}
if(bj==0  && !temp==step0 ){
Stepper(-step0);       //步进电机-转
delay(500);
temp=step0;
}
mark = 0;
}
}
void show_data(){
lcd.setCursor(0,0);              
lcd.print("0=");     
lcd.setCursor(2,0);         
lcd.print(pos0);     
lcd.setCursor(5,0);            
lcd.print("1=");     
lcd.setCursor(7,0);              
lcd.print(pos1);     
lcd.setCursor(10,0);            
lcd.print("2=");     
lcd.setCursor(13,0);              
lcd.print(pos2);   
lcd.setCursor(0,1);        
lcd.print("3=");   
lcd.setCursor(2,1);         
lcd.print(pos3);     
lcd.setCursor(5,1);           
lcd.print("4=");     
lcd.setCursor(7,1);         
lcd.print(step0);     
}
//步进电机
void Stepper(int stepsPerRevolution) {
myStepper.step(stepsPerRevolution);
delay(500);
}
Processing 代码:
import processing.serial.*;
PFont font;
String ComX[] = null;
String SerialName = "COM1";
boolean serial;
int pos0=0;
int pos1=0;
int pos2=0;
int pos3=0;
int step0=0;
int value=10;
int value1=10;
String mesg1="";
String mesg2="";
String mesg3="";
String mesg4="";
String mesg5="";
String mesg="";
int bj=0;
void setup(){
size(800, 600);
ComX = myPort.list();
font = createFont("宋体.vlw",48);
textFont(font);
frameRate(30);
smooth();
printArray(ComX);
}
void draw(){
background(255);
drawWindows(20,50);
Serial_Handle(20,50);
CheckBoxHandle();
CheckBoxHandle_S();
}
void drawWindows(float x, float y){

drawForm(x,y);

if(button(x + 350, y + 450,"选串口")!= 0){
Serial_SetClick();
}
if(button(x + 500, y + 450,"发送指令") != 0){
  if(SerialName==null){
  }else{
send_data();
  }
}
if(button(x + 650, y + 450,"退  出") != 0){
exit();
}
}

//绘制主窗口
void drawForm(float x, float y){
strokeWeight(2);
textSize(18);
text("Processing-Arduino 四自由度机械臂操控", 200,23);
fill(0);
strokeWeight(1);
textSize(12);
text("( 探索软件制 @ CopyRight 2019 )", 560,25);
textSize(18);
strokeWeight(1);
fill(0);
textSize(18);
line(0,25,1000,36);
line(0,450,1000,450);
text("舵机-0",5,65);
text("舵机-1",5,110);
text("舵机-2",5,155);
text("舵机-3",5,200);
line(0,280,1000,280);
text("步电-0",5,320);
text("POS0=",350,65);
text(int(pos0),420,65);
text("POS1=",350,110);
text(int(pos1),420,110);
text("POS2=",350,155);
text(int(pos2),420,155);
text("POS3=",350,200);
text(int(pos3),420,200);
text("Step0=",350,320);
text(int(step0),420,320);
mesg="POS0="+pos0+","+"POS1="+pos1+","+"POS2="+pos2+","+"POS3="+pos3+","+"step0="+step0+","+"bj="+bj;
fill(237,28,36);
text(mesg1,280,65);
text(mesg2,280,110);
text(mesg3,280,155);
text(mesg4,280,200);
text(mesg5,280,320);
textSize(16);
strokeWeight(2);
fill(0);
text("向Arduino发送数据:",50,580);
text(mesg,200,580);
text("角度增量选择=", 20, 260);
text(value, 125, 260);
text("度", 145, 260);
text("步数增量选择=", 20, 370);
text(value1, 125, 370);
text("步", 150, 370);
text("当前串口=", 20, 420);
text(SerialName + "    9600bps", 100,420);

if(button(60, 45,"向前") != 0){
mesg1="向前进";
pos0=pos0+value;
pos0=constrain(pos0,0,180);
}
if(button(165, 45,"向后") != 0){
mesg1="向后进";
pos0=pos0-value;
pos0=constrain(pos0,0,180);
}
if(button(545, 45,"归零") != 0){
mesg1="归零";
pos0=0;
pos0=constrain(pos0,0,180);
}
if(button(60, 90,"向前") != 0){
mesg2="向前进";
pos1=pos1+value;
pos1=constrain(pos1,0,180);
}
if(button(165, 90,"向后") != 0){
mesg2="向后进";
pos1=pos1-value;
pos1=constrain(pos1,0,180);
}
if(button(545, 90,"归零") != 0){
mesg2="归零";
pos1=0;
pos1=constrain(pos1,0,180);
}
if(button(60, 135,"向前") != 0){
mesg3="向前进";
pos2=pos2+value;
pos2=constrain(pos2,0,180);
}
if(button(165, 135,"向后") != 0){
mesg3="向后进";
pos2=pos2-value;
pos2=constrain(pos2,0,180);
}
if(button(545, 135,"归零") != 0){
mesg3="归零";
pos2=0;
pos2=constrain(pos2,0,180);
}
if(button(60, 180,"向前") != 0){
mesg4="向前进";
pos3=pos3+value;
pos3=constrain(pos3,0,180);
//send_data();
}
if(button(165, 180,"向后") != 0){
mesg4="向后进";
pos3=pos3-value;
pos3=constrain(pos3,0,180);
}
if(button(545, 180,"归零") != 0){
mesg4="归零";
pos3=0;
pos3=constrain(pos3,0,180);
}

if(button(60, 300,"向前") != 0){
mesg5="向前进";
step0=step0+value1;
step0=constrain(step0,0,360);
bj=1;
}
if(button(165, 300,"向后") != 0){
mesg5="向后进";
step0=step0-value1;
step0=constrain(step0,0,360);
bj=0;
}
if(button(545, 300,"归零") != 0){
mesg5="归零";
step0=0;
step0=constrain(step0,0,360);
bj=0;
}
}
byte button(float x , float y , String str){
byte ret = 0;
//fill(0,255,0);
fill(0,0,0);
strokeWeight(2);
//stroke(255,255,0);
if((mouseX > x) && (mouseY > y) && (mouseX < (x + 100) ) &&(mouseY < (y + 30))){
fill(128,255,255);
if (mousePressedFlag && (mouseButton == LEFT)) {
mousePressedFlag = false;
fill(0,128,128);
ret = 1;
}
}
rect(x,y, 100, 30);
fill(255,255,255);
textSize(16);
text(str, x + 24, y + 22);
return ret;
}

//舵机角度选择
boolean X_checkBox = true;
boolean Y_checkBox = false;
boolean Z_checkBox = false;
boolean A_checkBox = false;
boolean B_checkBox = false;
boolean C_checkBox = false;
boolean D_checkBox = false;
boolean E_checkBox = false;

void CheckBoxHandle(){
if(CheckBox(240,245,X_checkBox, "10")== 1){
X_checkBox = (X_checkBox == false) ? true: false;
value=10;
}
if(CheckBox(300,245,Y_checkBox, "20") == 1){
Y_checkBox = (Y_checkBox == false) ? true: false;
value=20;
}
if(CheckBox(360,245, Z_checkBox, "30") == 1){
Z_checkBox = (Z_checkBox == false) ? true: false;
value=30;
}
if(CheckBox(420,245, A_checkBox, "40") == 1){
A_checkBox = (A_checkBox == false) ? true: false;
value=40;
}
if(CheckBox(480,245, B_checkBox, "50") == 1){
B_checkBox = (B_checkBox == false) ? true: false;
value=50;
}
if(CheckBox(540,245, C_checkBox, "60") == 1){
C_checkBox = (C_checkBox == false) ? true: false;
value=60;
}
if(CheckBox(600,245, D_checkBox, "70") == 1){
D_checkBox = (D_checkBox == false) ? true: false;
value=70;
}
if(CheckBox(660,245, E_checkBox, "80") == 1){
E_checkBox = (E_checkBox == false) ? true: false;
value=80;
}
}
boolean checkBox_GetXFlag(){
return X_checkBox;
}
boolean checkBox_GetYFlag(){
return Y_checkBox;
}
boolean checkBox_GetZFlag(){
return Z_checkBox;
}
boolean checkBox_GetAFlag(){
return A_checkBox;
}
boolean checkBox_GetBFlag(){
return B_checkBox;
}
boolean checkBox_GetCFlag(){
return C_checkBox;
}
boolean checkBox_GetDFlag(){
return D_checkBox;
}
boolean checkBox_GetEFlag(){
return E_checkBox;
}


byte CheckBox(float x, float y, boolean sL, String str){
noFill();
//stroke(255,255,0);
if(sL){
fill(0,255,0);
}
rect(x, y, 20, 20);
textSize(16);
fill(0);
strokeWeight(2);
text(str, x + 30, y + 20);
if((mouseX > x) && (mouseY > y) && (mouseX < (x + 20) ) &&(mouseY < (y + 20))){
if (mousePressedFlag && (mouseButton == LEFT)) {
mousePressedFlag = false;
return 1;
}
}
return 0;
}
//步进电机步数选择
boolean S1_checkBox = true;
boolean S2_checkBox = false;
boolean S3_checkBox = false;
boolean S4_checkBox = false;
boolean S5_checkBox = false;
boolean S6_checkBox = false;
boolean S7_checkBox = false;
boolean S8_checkBox = false;
void CheckBoxHandle_S(){
if(CheckBox_S(240,350,S1_checkBox, "10")== 1){
S1_checkBox = (S1_checkBox == false) ? true: false;
value1=10;
}
if(CheckBox_S(300,350,S2_checkBox, "20") == 1){
S2_checkBox = (S2_checkBox == false) ? true: false;
value1=20;
}
if(CheckBox_S(360,350, S3_checkBox, "30") == 1){
S3_checkBox = (S3_checkBox == false) ? true: false;
value1=30;
}
if(CheckBox_S(420,350, S4_checkBox, "40") == 1){
S4_checkBox = (S4_checkBox == false) ? true: false;
value1=40;
}
if(CheckBox_S(480,350, S5_checkBox, "50") == 1){
S5_checkBox = (S5_checkBox == false) ? true: false;
value1=50;
}
if(CheckBox_S(540,350, S6_checkBox, "60") == 1){
S6_checkBox = (S6_checkBox == false) ? true: false;
value1=60;
}
if(CheckBox_S(600,350, S7_checkBox, "70") == 1){
S7_checkBox = (S7_checkBox == false) ? true: false;
value1=70;
}
if(CheckBox_S(660,350, S8_checkBox, "80") == 1){
S8_checkBox = (S8_checkBox == false) ? true: false;
value1=80;
}
}
boolean checkBox_GetS1Flag(){
return S1_checkBox;
}
boolean checkBox_GetS2Flag(){
return S2_checkBox;
}
boolean checkBox_GetS3Flag(){
return S3_checkBox;
}
boolean checkBox_GetS4Flag(){
return S4_checkBox;
}
boolean checkBox_GetS5Flag(){
return S5_checkBox;
}
boolean checkBox_GetS6Flag(){
return S6_checkBox;
}
boolean checkBox_GetS7Flag(){
return S7_checkBox;
}
boolean checkBox_GetS8Flag(){
return S8_checkBox;
}
byte CheckBox_S(float x, float y, boolean sL, String str){
noFill();
//stroke(255,255,0);
if(sL){
fill(0,255,0);
}
rect(x, y, 20, 20);
textSize(16);
fill(0);
strokeWeight(2);
text(str, x + 30, y + 20);
if((mouseX > x) && (mouseY > y) && (mouseX < (x + 20) ) &&(mouseY < (y + 20))){
if (mousePressedFlag && (mouseButton == LEFT)) {
mousePressedFlag = false;
return 1;
}
}
return 0;
}
int name = 0;
String strName = String.valueOf(name);
byte click = 0;
byte comNum = 0;
byte Serial_StopFlag = 0;
boolean Serial_OpenFlag = false;
boolean Serial_DatareadFlag = false;
byte[] Serial_buffer = new byte[6];
Serial myPort;
String strSerial = "com1";
boolean Serial_GetdataFlag = false;
String[] strComBuff = new String[4];


void Serial_Handle(float x, float y){
if(click != 0){
comNum = 0;
Serial_DrawComX(20, 50);
}
else{
textSize(12);
//fill(255);
fill(0);
}
Serial_GetdataFromCom();
}

void Serial_DrawComX(float x, float y){
int i = 0;
int len = ComX.length;
textSize(12);
while(i < len){
if(comNum != 0){//选择了端口
break;
}
Serial_DrawCom(x + 350, y + 480 + i * 30, ComX);
i++;
}
}
void Serial_DrawCom(float x, float y, String str){
fill(255);
//noStroke();
rect(x, y, 101, 30);
if(mouseX > x && mouseY > y && mouseX < x + 100 && mouseY < y + 30){
fill(175,183,203);
rect(x,y, 101, 30);
if (mousePressed && (mouseButton == LEFT)) { //按键按下
if(str.equals("COM1") == true){
comNum = 1;
}
else if(str.equals("COM2") == true){
comNum = 1;
}
else if(str.equals("COM3") == true){
comNum = 1;
}
else if(str.equals("COM4") == true){
comNum = 1;
}
else if(str.equals("COM5") == true){
comNum = 1;
}
else if(str.equals("COM6") == true){
comNum = 1;
}
else if(str.equals("COM7") == true){
comNum = 1;
}
else if(str.equals("COM8") == true){
comNum = 1;
}
else if(str.equals("COM9") == true){
comNum = 1;
}
if(str.equals(SerialName) != true){
SerialName = str;
if(comNum != 0){
click = 0;
if(Serial_StopFlag != 0){
myPort.stop();//停止上一个串口
}
myPort =new Serial(this,SerialName,9600 );
myPort.bufferUntil(10);
Serial_StopFlag = 1;
Serial_OpenFlag = true;
}
}
click = 0;
}
}
fill(0,0,255);
text(str,x + 10, y + 25);
}

void Serial_SetClick(){
click = 1;
}
void Serial_GetdataFromCom(){
if(Serial_OpenFlag != true){
strComBuff[0] = " ";
strComBuff[1] = " ";
strComBuff[2] = " ";
return;
}
if(myPort.available() > 0){
Serial_GetdataFlag = true;
strSerial = myPort.readString();
strComBuff = strSerial.split(",");
}
}

float Serial_String2float(String str){
float a = 0;
a = float(str)*150;
return a;
}

boolean Serial_GetdataFlag(){
return Serial_GetdataFlag;
}

boolean Serial_GetComOpenFlag(){
return Serial_OpenFlag;
}

void serialEvent(Serial p) {
Serial_GetdataFlag = true;
strSerial = p.readString();
strComBuff = strSerial.split(",");
}

//send data to Arduino
void send_data(){
print("pos0=");
print(pos0);
print(',');
print("pos1=");
print(pos1);
print(',');
print("pos2=");
print(pos2);
print(',');
print("pos3=");
print(pos3);
print(',');
print("step0=");
print(step0);
print(',');
print("bj=");
println(bj);
myPort.write('%');
myPort.write(int(pos0));
myPort.write(int(pos1));
myPort.write(int(pos2));
myPort.write(int(pos3));
myPort.write(int(step0));
myPort.write(int(bj));
serial=false;
}

boolean mousePressedFlag = false;
void mousePressed() {
mousePressedFlag = true;
}
boolean SaveFlag = false;

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

 楼主| 发表于 2019-4-2 17:16:50 | 显示全部楼层
操作控制界面图

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

发表于 2019-4-21 19:37:29 | 显示全部楼层
新手学习刚好需要,感谢分享!!
回复 支持 反对

使用道具 举报

发表于 2019-4-22 17:40:26 | 显示全部楼层
本帖最后由 haiyang4060 于 2019-4-22 17:44 编辑

软件呢 发来看看呗  o 我看错了 抱歉 是Processing
回复 支持 反对

使用道具 举报

发表于 2019-4-22 19:02:21 | 显示全部楼层
Processing  有点难度 没弄白
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-20 06:19 , Processed in 0.050278 second(s), 20 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表