如何让Arduino运行脚本 [英] How to make Arduino run a script

查看:56
本文介绍了如何让Arduino运行脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一名软件开发人员,但我是 Arduino 和电子世界的新手.
我想构建一个将两者结合起来的简单项目,并且非常感谢任何从哪里开始的帮助.

最终项目应该是带有按钮和 LED 的 Arduino,当点击按钮时我想在我的 mac 上运行一个脚本,然后如果脚本成功完成我想打开 LED

我已经看过一些关于如何使用按钮和 LED 的教程
我在这里感兴趣的主要事情是如何从 Arduino 通信到 mac,反之亦然.尤其是如何让它在我的 mac 上运行脚本.

解决方案

您应该查看 Serial class 和示例(通过 File > Examples > Commmunication)

您需要在 Arduino 端编写一些代码,以便在按下按钮时通过串行发送数据(以便您可以触发脚本)并接收数据(脚本完成后)以控制 LED.

这是 Arduino 方面的一个粗略示例:

const int btnPin = 12;//按钮引脚const int ledPin = 13;int lastButtonState;无效设置(){//设置引脚pinMode(btnPin,INPUT_PULLUP);pinMode(ledPin,OUTPUT);//设置通讯Serial.begin(9600);}无效循环(){int currentButtonState = digitalRead(btnPin);//读取按钮状态if(lastButtonState != currentButtonState && currentButtonState == LOW){//如果引脚状态改变Serial.write(currentButtonState);//发送数据lastButtonState = currentButtonState;//更新最后一个按钮状态//打开LED数字写入(ledPin,高);}}void serialEvent(){//如果有数据发送if(Serial.available() > 0){//并且至少有 1 个字节要查看int data = Serial.read();//读取数据//如果你愿意,可以用它做一些事情//关闭LED数字写入(ledPin,低);}}

请注意,您的设置中可能有不同的引脚编号,并且根据按钮的接线方式,您将在条件检查 currentButtonState.

就沟通而言,有几个关键要素:

Serial.begin(9600);

以 9600 波特率开始串行通信.您需要在另一端匹配此波特率以确保正确通信.

Serial.write();

将数据发送到端口.

serialEvent()

在 Arduino 中预定义并在新串行数据到达时被调用.注意,这会在 Arduino Uno(和其他更简单的电路板)上自动调用,但不会在其他电路板上调用:

<块引用>

serialEvent() 不适用于 Leonardo、Micro 或 Yún.

serialEvent() 和 serialEvent1() 在 Arduino SAMD 板上不起作用

serialEvent()、serialEvent1()``serialEvent2() 和 serialEvent3() 不适用于 Arduino Due.

在脚本方面,你没有提到语言,但原理是一样的:你需要知道端口名称和波特率才能与你的mac建立通信.

(您可以在 loop() 中手动调用 serialEvent() 作为解决方法.有关更多详细信息,请参阅 Arduino 参考)

端口是您用来上传 Arduino 代码的端口(类似于 /dev/tty.usbmodem####),在这种特殊情况下,波特率为 9600.您应该能够在 Arduino IDE 中使用串行监视器进行测试.

你的脚本将是类似的东西(伪代码)

打开串口连接(端口名,波特率= 9600)轮询串行连接如果有数据运行你需要的脚本脚本执行完毕,因此通过串行连接发回数据

请务必查看与软件交互以查找有关您的脚本语言的指南选择

更新

这是一个使用 Processing 与使用 串行库.所以在 Arduino 方面,这是一个最小的草图:

const int btnPin = 12;//按钮引脚const int ledPin = 13;布尔值被按下;char cmd[] = "/Applications/TextEdit.app\n";无效设置(){//设置引脚pinMode(btnPin,INPUT_PULLUP);pinMode(ledPin,OUTPUT);//设置通讯Serial.begin(9600);}无效循环(){int currentButtonState = digitalRead(btnPin);//读取按钮状态if(!wasPressed && currentButtonState == LOW){//如果引脚状态改变了Serial.write(cmd);//发送数据wasPressed = true;//更新最后一个按钮状态//打开LED数字写入(ledPin,高);}if(currentButtonState == HIGH) wasPressed = false;}void serialEvent(){//如果有数据发送if(Serial.available() > 0){//并且至少有 1 个字节要查看int data = Serial.read();//读取数据//如果你愿意,可以用它做一些事情//关闭LED数字写入(ledPin,低);}}

在处理方面:

import processing.serial.*;无效设置(){尝试{Serial arduino = new Serial(this,"/dev/tty.usbmodemfa141",9600);arduino.bufferUntil('\n');//缓冲直到遇到新行}catch(异常e){System.err.println(打开串行连接时出错!(检查电缆和端口/波特率设置!");e.printStackTrace();}}void draw(){}无效的串行事件(串行s){String[] command = s.readString().trim().split(",");//修剪空格,分割为String[] for argsprintln(command);//看看我们得到了什么open(command);//运行命令s.write("A");//发送消息回标志命令完成(关闭LED)}

希望这是一个有用的概念证明.随意使用带有可用串行库的任何其他语言而不是 Processing.语法可能略有不同(可能更多在于进程/命令的运行),但概念是相同的.

更新 上面的例子可以通过在 Arduino 端没有命令来简化:

  • 从 Arduino 串行发送到处理的数据较少,从而减少了通信时间和通信干扰的几率
  • 该应用程序在计算机上运行,​​因此在软件方面更改命令更简单,而不是每次都必须更改 Arduino 代码并重新上传.

阿杜诺:

const int btnPin = 12;//按钮引脚const int ledPin = 13;布尔值被按下;无效设置(){//设置引脚pinMode(btnPin,INPUT_PULLUP);pinMode(ledPin,OUTPUT);//设置通讯Serial.begin(9600);}无效循环(){int currentButtonState = digitalRead(btnPin);//读取按钮状态if(!wasPressed && currentButtonState == LOW){//如果引脚状态改变了Serial.write('R');//发送数据wasPressed = true;//更新最后一个按钮状态//打开LED数字写入(ledPin,高);}if(currentButtonState == HIGH) wasPressed = false;}void serialEvent(){//如果有数据发送if(Serial.available() > 0){//并且至少有 1 个字节要查看int data = Serial.read();//读取数据//如果你愿意,可以用它做一些事情//关闭LED数字写入(ledPin,低);}}

处理:

import processing.serial.*;String[] command = {/Applications/TextEdit.app", myText.txt"};无效设置(){尝试 {Serial arduino = new Serial(this, "/dev/tty.usbmodemfa141", 9600);}捕获(异常 e){System.err.println(打开串行连接时出错!(检查电缆和端口/波特率设置!");e.printStackTrace();}}无效画(){}无效的串行事件(串行s){如果(s.read()=='R'){启动(命令);//运行命令s.write("A");//发送消息回标志命令完成(关闭LED)}}

(顺便说一句,'R' 是一个任意的单个字符,可以是其他字符,只要它在串行发送端和接收端的字符相同)

另外,记住 launch() 返回 进程 可用于从启动的软件中获取更多信息.>

i'm a software developer but i'm new to Arduino, and to the electronics world.
I would like to build a simple project that combined both, and really appreciate any help where to start.

final project should be Arduino with a button and a LED, when tapping the button I want run a script on my mac, then if the script finished successfully i want to turn on the LED

I already saw some tutorial about how to use buttons and LEDs so
the main thing i'm interested here is how communicate from the Arduino to the mac and vice versa. and especially how to make it run a script on my mac.

解决方案

You should look into the Serial class and the examples (via File > Examples > Commmunication)

You will need to write a bit of code on the Arduino side to send data via Serial when the button is pressed (so you can trigger your script) and receive data (when the script is done) to control the LED.

Here is a rough example on the Arduino side:

const int btnPin = 12;//button pin
const int ledPin = 13;

int lastButtonState;

void setup(){ 
  //setup pins
  pinMode(btnPin,INPUT_PULLUP);
  pinMode(ledPin,OUTPUT);
  //setup communication
  Serial.begin(9600);
}

void loop() {
  int currentButtonState = digitalRead(btnPin);//read button state
  if(lastButtonState != currentButtonState && currentButtonState == LOW){//if the state of the pin changed
    Serial.write(currentButtonState);//send the data
    lastButtonState = currentButtonState;//update the last button state
    //turn on LED
    digitalWrite(ledPin,HIGH);
  }
}
void serialEvent(){//if any data was sent
  if(Serial.available() > 0){//and there's at least 1 byte to look at
    int data = Serial.read();//read the data
    //do something with it if you want
    //turn off the LED
    digitalWrite(ledPin,LOW);
  }
}

Be aware you may have different pin numbers in your setup and depending on how the button wired, you will either look for a LOW or HIGH value in the in the condition checking the currentButtonState.

In terms of the communication there are a few key elements:

Serial.begin(9600);

Starts Serial communication with baud rate 9600. You will need to match this baud rate on the other end to ensure correct communication.

Serial.write();

Will send data to the port.

serialEvent()

is predefined in Arduino and gets called when new Serial data arrives. Note that this gets called automatically on a Arduino Uno (and other simpler boards), however this doesn't get called on other boards:

serialEvent() doesn’t work on the Leonardo, Micro, or Yún.

serialEvent() and serialEvent1() don’t work on the Arduino SAMD Boards

serialEvent(), serialEvent1()``serialEvent2(), and serialEvent3() don’t work on the Arduino Due.

On the script side, you haven't mentioned the language, but the principle is the same: you need to know the port name and baud rate to establish communication from your mac.

(You can manually call serialEvent() in loop() as a workaround. For more details see the Arduino Reference)

The port is what you used to upload the Arduino code (something like /dev/tty.usbmodem####) and in this particular case the baud rate is 9600. You should be able to test using Serial Monitor in the Arduino IDE.

Your script will be something along there lines (pseudo code)

open serial connection ( port name, baudrate = 9600 )
poll serial connection
   if there is data
      run the script you need
      script finished executing, therefore send data back via serial connection

Be sure to checkout the Interfacing with Software to find guide on the scripting language of your choice

Update

Here's a quick example using Processing to interface with the arduino using it's Serial library. So on the Arduino side, here's a minimal sketch:

const int btnPin = 12;//button pin
const int ledPin = 13;

boolean wasPressed;

char cmd[] = "/Applications/TextEdit.app\n";

void setup(){ 
  //setup pins
  pinMode(btnPin,INPUT_PULLUP);
  pinMode(ledPin,OUTPUT);
  //setup communication
  Serial.begin(9600);
}

void loop() {
  int currentButtonState = digitalRead(btnPin);//read button state
  if(!wasPressed && currentButtonState == LOW){//if the state of the pin changed
    Serial.write(cmd);//send the data
    wasPressed = true;//update the last button state
    //turn on LED
    digitalWrite(ledPin,HIGH);
  }
  if(currentButtonState == HIGH) wasPressed = false;
}
void serialEvent(){//if any data was sent
  if(Serial.available() > 0){//and there's at least 1 byte to look at
    int data = Serial.read();//read the data
    //do something with it if you want
    //turn off the LED
    digitalWrite(ledPin,LOW);
  }
}

and on the Processing side:

import processing.serial.*;

void setup(){
  try{
    Serial arduino = new Serial(this,"/dev/tty.usbmodemfa141",9600);
    arduino.bufferUntil('\n');//buffer until a new line is encountered
  }catch(Exception e){
    System.err.println("Error opening serial connection! (check cables and port/baud settings!");
    e.printStackTrace();
  }
}
void draw(){}
void serialEvent(Serial s){
  String[] command = s.readString().trim().split(",");//trim spaces, split to String[] for args
  println(command);//see what we got
  open(command);//run the command
  s.write("A");//send a message back to flag that the command is finished (turn LED off)
} 

Hope this is a helpful proof of concept. Feel free to use any other language with a serial library available instead of Processing. The syntax may differ just a tad (probably more on the running of the process/command), but the concept is the same.

Update The example above can be simplified a touch by not having the command on the Arduino side:

  • there's less data sent on Serial from Arduino to Processing reducing communication time and the odds of communication interference
  • the app runs on a computer hence changing the command is simpler to do on software side as opposed to having to change the Arduino code and re-upload each time.

Arduino:

const int btnPin = 12;//button pin
const int ledPin = 13;

boolean wasPressed;

void setup(){ 
  //setup pins
  pinMode(btnPin,INPUT_PULLUP);
  pinMode(ledPin,OUTPUT);
  //setup communication
  Serial.begin(9600);
}

void loop() {
  int currentButtonState = digitalRead(btnPin);//read button state
  if(!wasPressed && currentButtonState == LOW){//if the state of the pin changed
    Serial.write('R');//send the data
    wasPressed = true;//update the last button state
    //turn on LED
    digitalWrite(ledPin,HIGH);
  }
  if(currentButtonState == HIGH) wasPressed = false;
}
void serialEvent(){//if any data was sent
  if(Serial.available() > 0){//and there's at least 1 byte to look at
    int data = Serial.read();//read the data
    //do something with it if you want
    //turn off the LED
    digitalWrite(ledPin,LOW);
  }
}

Processing:

import processing.serial.*;

String[] command = {"/Applications/TextEdit.app", "myText.txt"};

void setup() {
  try {
    Serial arduino = new Serial(this, "/dev/tty.usbmodemfa141", 9600);
  }
  catch(Exception e) {
    System.err.println("Error opening serial connection! (check cables and port/baud settings!");
    e.printStackTrace();
  }
}

void draw() {
}

void serialEvent(Serial s) {
  if (s.read() == 'R') {
    launch(command);//run the command
    s.write("A");//send a message back to flag that the command is finished (turn LED off)
  }
} 

(btw, 'R' is an arbitrary single character, can be something else as long it's the same char on both Serial send and receive sides)

Also, bare in mind launch() returns Proccess which can be useful to get more information from the software launched.

这篇关于如何让Arduino运行脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆