arduino程序无法执行

2016-03-19 15:45:39 sdsunhui 阅读数 32572

点亮 LED

上一节介绍了 Ardunio UNO 的硬件结构,这一节将会写一个 UNO 的 “hello word” 程序,在软件领域通常会以输出 “hello word” 作为开始,而在硬件领域通常是以点亮 LED 灯作为开始。

搭建环境

首先,在编写程序之前,需要下载编译环境和安装驱动。这里以mac为例,具体的下载过程可以参考官方的Getting Started w/ Arduino on Mac OS X。从官方下载IDE时可能需要先捐献才能下载,为了表示对IDE的支持,我捐献了两美元。当然如果你没有信用卡或者其他的合适的支付手段,这里提供一个第三方的下载平台。按照上述方法安装完毕之后,需要再安装串口驱动,下载链接。驱动安装完毕之后,可以检查驱动是否安装成功。插上连接线,输入ls /dev/tty.*

这里写图片描述

这里是“/dev/tty.usbmodem1421”,驱动安装成功。

更改配置

在编写程序之前,还需要更改一些配置项:

第一步,选择对应的开发板,这里选用的是 UNO 开发板。

这里写图片描述

第二部,选择对应的下载端口,上面打印的端口是“/dev/tty.usbmodem1421”,这里选择它。

这里写图片描述

编写程序

Ardunio 采用自己的一套语言规范,程序可以被分解为三个主要部分:结构、值(变量和常量)以及函数。
一般结构中包含两个函数:“setup()”、“loop()”。“setup()” 是在“sketch”开始时被调用的,用于初始化变量、管脚、开始使用库文件等等。这个函数只会在开发板上电或复位时被调用一次。而“loop()”函数则是在“setup()”函数执行完毕后,一直循环执行。点亮 LED 的思路是只需要在程序开始时,将 LED 置于点亮状态。上一章可以看到,UNO 开发板的13管脚连接在 LED 的灯的一端,而 LED 的灯另一端连接到了低电平,也就是说,只需在初始化时,给13管脚上赋上高电平便可完成操作。

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin 13 as an output.
  pinMode(13, OUTPUT);
  // turn the LED on (HIGH is the voltage level)
   digitalWrite(13, HIGH);
}

// the loop function runs over and over again forever
void loop() {

}

编译下载到 UNO 板中,Done,效果如下:

这里写图片描述

Nodejs 点亮 LED

现如今,绝大多数嵌入式设备选用的是 C/C++ 语言,对于一些实时性较高的语言则选用汇编语言。但是随着硬件设备的性能提升,越来越有可能选用自己熟悉的语言进行编程,比如java、C#、javascript、python等。目前,在一些高端的微处理器(如树莓派)上已经可以使用这些语言进行编程,大多数 MCU (绝大多数8/16位芯片)的编译环境都是将 C 语言编译成16进制文件烧录到芯片中执行。所以,当选用一个自己熟悉的语言在低端芯片中编程时,可能无法借助现有的编译器完成。本文以 Ardunio UNO (8位芯片)为例,用 Javascript 编写一个硬件的“Hello World”(点亮LED)程序。

下载程序

MCU 下载程序需要软硬件共同支持,一般会使用现成的 IDE 工具,极少会关注到这些。那么将一段程序下载到 MCU 中需要哪些支持呢?这里以 Ardunio UNO 为例进行讲解。将一段程序下载到 Ardunio UNO ,Ardunio UNO 依靠 ATmega32U4/ATmega16U2(不同版本的 UNO 使用的芯片不同,高版本的有所升级)等 进行下载。而 ATmega32U4/ATmega16U2 等是 USB 接口芯片,是将 PC 发送的信号传递到 UNO 主芯片的中枢。从第一章的电路图可以看出,ATmega16U2 芯片可以将 USB 信号转换为 ISP、串口信号等,而这里是将其转化为串口信号下载到主芯片(不同厂商、不同芯片支持不同的下载方式)。另一方面,不同平台电脑也会装上对应的驱动(第一章安装环境中有提到),ATmega16U2 内置 Bootloader ,按照特定的协议与 PC 通信。这里特别提一下,ATmega16U2 系列芯片支持固件升级,需要借助官方提供的软件Flip对其升级,对应的固件megaUSB_DFU_Bootloaders都是16进制文件。下图是 ATmega16U2 等硬件及 Boot 处理流程:

这里写图片描述

Firmata 协议

Arduino IDE 是不支持 Javascript 语法的,这里无法使用 Arduino IDE 进行 Js 编程。首先,需要用 js 编写程序,然后将 js 程序写入到 arduino 中。这里需要一个协议来支持 PC 与 MCU 的通信。而 Arduino IDE 本身集成 Firmata 协议(准确的说是 Firmata 从 Aduino 抽离出来的)。这里首先需要做的事讲 Firmata 协议的 Arduino 实现烧写到芯片中。然后,用 js 实现 Firmata 协议,PC 通过 Firmata 协议控制 Arduino.

烧写 Firmata 协议

Arduino IDE 本身是集成了 Firmata,只需要找到这个程序,烧写到 arduino 中即可,具体位置如下图:

这里写图片描述

PC 端程序

首先,要实现 PC 与 MCU 的 Firmata 协议,这里直接借助 firmata.js,firmata.js 实现了用 PC 端用 js 与 MCU 的 Firmata 通信。在这个基础上,编写“Hello World”。连接 USB 线,找到对应的设备端口ls /dev/tty.usb*

这里写图片描述

编写程序,当 PC 和 MCU 与连接成功之后,将 Arduino 的13(连接LED)管脚置为高电平。将刚才显示的设备端口写到以下程序中:

var Board = require("firmata");
var board = new Board("/dev/tty.usbmodem1421");

board.on("ready", function() {
  // Arduino is ready to communicate
 console.log('connet');
 board.digitalWrite(13, 1)
});                                                                                       

如图,连接成功,开发板 LED 点亮:

这里写图片描述

上面就实现了用 js 控制硬件,当想用 js 编写复杂的程序是,也可以依赖一些现成的 js 库,这里推荐一个 johnny-five。同样,用其他的语言也可以实现,只需要使用 Firmata 对应的实现。Firmata client libraries,这个文档中列出各种语言对 Firmata 实现的库。

2015-06-06 00:05:02 zhiboyongjian 阅读数 1959

Arduino程序设计

        我们知道程序结构分为顺序结构、分支结构、循环结构三种。这三种基本结构可以组成Arduino控制所需的各种复杂程序,我们学习Arduino编程常用到的几个基本语句,为后文各章节的学习和动手实战打下一定基础。

2.3.1  if 语句

用if 语句可以构成分支结构。它根据给定的条件进行判断,然后决定要执行那个分支程序段。Arduino编程中,if 语句有三种基本形式。

1.第一种:if(表达式) 语句

语义是:如果表达式的值为真,则执行其后的语句,否则不执行该语句。

例:

   int a, b, max;
   max = a;
   if(max < b) max = b;

上例中首先定义整形变量a、b、max,把a的值先赋予给变量max,再用if 语句判别max和b的大小,如果max小于b,则把b 赋予给max。因此max中总是大数。

2.第二种:if-else 语句

if(表达式)

语句1;

else

语句2;

语义是:如果表达式的值为真,则执行语句1,否则执行语句2。

例:

   int a, b, max;
   if(a < b)
     max = b;
   else
     max = a;


上面的比较语句中,a、b、max同样均为整形,这次不同的是a与b先作比较,如果a的值小于b的,则把b的值赋给max,否则把a的值赋给max。这里的else即相当于if(a >= b)了。

3.第三种:if-else if-else 形式

前二种形式的if 语句一般都用于两个分支的情况。 当有多个分支选择时,可采用if-else if-else语句,其一般形式为:

if(表达式1)

语句1;

else if(表达式2)

语句2;

else if(表达式3)

语句3;

else if(表达式m)

语句m;

else

语句n;

其语义是:依次判断表达式的值,当出现某个值为真时,则执行其对应的语句。然后跳到整个if语句之外的部分继续执行。如果所有的表达式均为假,则执行语句n。然后继续执行后续程序。

例:

char Re_data = Serial.read();
if(Re_data == 'M')
{
     th_test();
     TH_Print();
 }
else if(Re_data == 'R')    
 {
     LED(0,1);
     Serial.println("Red LED ON!");
 }
else if(Re_data == 'G')      
{
     LED(1,0);
     Serial.println("Green LED ON!");
}
else if(Re_data == 'B')    
 {
     LED(0,0);
     Serial.println("Redand Green LED ON!");
  }
else      
{
     LED(1,1);
     Serial.println("Both lights off!");
}


上面例程中,我们先不考虑程序具体要执行什么任务,在这里分析一下if-else if-else语句结构。语句中首先将Serial.read()的值赋给Re_data,然后通过第一个if(Re_data == 'M')来判断是否为真,如果为真,则执行th_test()和TH_Print();如果为假,则继续下面的判断,直到else如果还没有一个判断为真,则执行else后的语句。

以上三种if语句结构在编写时需要注意的是:

       在if 语句中,条件判断表达式必须用括号括起来,在语句之后必须加分号;

       在if 语句的三种形式中,如果要想在满足条件时执行一组(多个)语句,则必须把这一组语句用{} 括起来组成一个复合语句。但要注意的是在花括号之后不能再加分号。

另外,除了上面三种结构,编程时可能会遇到if语句的嵌套,即当if 语句中的执行语句又是if 语句时,则构成了if 语句嵌套的情形。其一般形式可表示如下:

if(表达式)

if 语句;

或者为

if(表达式)

if 语句;

else

if 语句;

在嵌套内的if 语句可能又是if-else 型的,这将会出现多个if 和多个else 重叠的情况,这时要特别注意if和else的配对问题。例:

if(表达式1)

if(表达式2)

语句1;

else

语句2;

其中的else究竟是与哪一个if 配对呢?为了避免这种二义性,C语言规定,else 总是与它前面最近的if配对。对于以上问题读者在具体应用时切实体会,这里不再给出示例。

2.3.2  switch语句

在Arduino编程中,可选择的另一种分支结构是switch语句,其一般形式为:

switch(表达式)

{

case 常量表达式1: 语句1;

case 常量表达式2: 语句2;

case 常量表达式n: 语句n;

default : 语句n+1;

}

其语义是:计算表达式的值,并逐个与其后的常量表达式值相比较,当表达式的值与某个常量表达式的值相等时,执行其后的语句,然后不再进行判断,继续执行后面所有case 后的语句。如表达式的值与所有case后的常量表达式均不相同时,则执行default后的语句。

例:

int a;
a = smog_level;
switch (a)
 {
   case 1: Serial.println("Attention! There is smog here ");
   case 2: Serial.println(" Danger! Smog's value is increasing ");
   case 3: Serial.println(" Danger! Smog’s value is high here ");
   default: Serial.println(" Safe now! ");
 }

本程序中将smog_level的值赋给a,这样a就相当于常量了,然后在case语句中比较哪个值与a的值相等。当相等了,则相应地执行后面的语句,比如smog_level的值为2,那么就要执行Serial.println(" Danger! Smog'svalue is increasing ")语句。

在switch 语句中,“case 常量表达式”只相当于一个语句标号,表达式的值和某标号相等则转向该标号执行,但不能在执行完该标号的语句后自动跳出整个switch 语句,所以出现了继续执行所有后面case语句的情况。这是与前面介绍的if 语句完全不同的。

为了避免上述情况,可以用break语句,跳出switch语句,break 语句只有关键字break,没有参数。在每一个case 语句之后加break语句,使每一次执行之后均可跳出switch语句,从而避免输出不应有的结果。

在使用switch 语句时还应注意以下几点:

1.在case后的各常量表达式的值不能相同,否则会出现错误;

2.在case后允许有多个语句,可以不用{}括起来;

3.各case和default子句的先后顺序可以变动,而不会影响程序执行结果;

4.default 子句可以省略不用。

2.3.3  while与do-while语句

while 语句的一般形式为: while(表达式)语句; 其中表达式是循环条件,语句为循环体。while 语句的语义是:计算表达式的值,当值为真(非0)时执行循环体语句。

例:

While( power_flog > 0)
{
  digitalWrite(P_led,HIGH);
}

这里只要“power_flog > 0”为真,则将一直执行digitalWrite(P_led,HIGH)语句。

使用while 语句应注意以下几点:

1.while 语句中的表达式一般是关系表达或逻辑表达式,只要表达式的值为真(非0)即可继续循环。

2.循环体如包括有一个以上的语句,则必须用{}括起来,组成复合语句。

3.应注意循环条件的选择以避免死循环。

do-while 语句的一般形式为:

do

语句;

while(表达式);

其中语句是循环体,表达式是循环条件。do-while语句的语义是:先执行循环体语句一次,再判别表达式的值,若为真(非0)则继续循环,否则终止循环。

do-while语句和while 语句的区别在于do-while是先执行后判断,因此do-while至少要执行一次循环体。而while是先判断后执行,如果条件不满足,则一次循环体语句也不执行。while 语句和do-while 语句一般都可以相互改写。

例:

do
{
  digitalWrite(P_led,HIGH);
}
While( power_flog > 0);

本例实际上是上例while结构的改写,这里先执行do语句,然后判断while语句是否为真,为真则继续执行do结构,否则执行其他语句。

对于do-while 语句需要注意以下几点:

1.在 while 语句中,表达式后面不能加分号,而在 do-while语句的表达式后面则必须加分号。

2.do-while 语句也可以组成多重循环,而且也可以和while 语句相互嵌套。

3.在do 和while 之间的循环体由多个语句组成时,也必须用{}括起来组成一个复合语句。

4.do-while 和while 语句相互替换时,要注意修改循环控制条件。

2.3.4  for语句

for 语句在Arduino编程中很常见,也是一种循环语句。其一般形式为:

for(表达式1;表达式2;表达3)

语句;

表达1通常用来给循环变量赋初值,一般是赋值表达式。也允许在for语句外给循环变量赋初值,此时可以省略该表达式。

表达式2 通常是循环条件,一般为关系表达式或逻辑表达式。

表达式3 通常可用来修改循环变量的值,一般是赋值语句。

for 语句的语义是:首先计算表达式1 的值。再计算表达式2 的值,若值为真(非0)则执行循环体一次,否则跳出循环。然后再计算表达式3 的值,转回第2 步重复执行。在整个for循环过程中,表达式1 只计算一次,表达式2 和表达式3则可能计算多次。循环体可能多次执行,也可能一次都不执行。

例:

int s = 0, s0 =0; 
for(i = 0; i < = 9; i++)
{
  Distance_test();
  s = s0 + distance ;
}

循环的初值i为0,并且小于9,则执行Distance_test()与s = s0 + distance,然后i的值自加为1,此时i的值依然小于9,继续执行循环体。直到i的值为9且执行完循环体后,i的值自增为10,此时10大于9了,条件不成立,循环结束。在整个过程中,一共进行了10次循环。

在使用for 语句中要注意以下几点

1.for 语句中的各表达式都可省略,但分号间隔符不能少。如:for(;表达式;表达式)省去了表达式1;for(表达式;;表达式)省去了表达式2;for(表达式;表达式;)省去了表达式3;for(;;)省去了全部表达式。

2.在循环变量已赋初值时,可省去表达式1。如果省去表达式2 或表达式3 则将造成无限循环,这时应在循环体内设法结束循环。如以下示例。

例:

int i=0,n=10;
for(;n > 0;)
{
  i++;
  value_send();
  n--;
 }

3.循环体可以是空语句。

4.for 语句也可与if,while,do-while语句相互嵌套,构成多重循环。

2017-07-02 23:19:30 u014364615 阅读数 1681
ESP8266自带是AT模式,现在arduino开发IDE直接可以编译程序。今天焊接一个新板子遇到奇特现在,连最基本的setup都不执行,肯定是编译有问题还是下载器。想起之前也遇到一次,换了新的IDE就好了。现在结合今天的所遇,应该还是下载器的问题。

一般使用的这个软件,没有什么设置参数,之前用的这个基本都是没问题(也没怀疑有问题,这个是刷电视盒子用过的了)
这里写图片描述

然后换了这个版本的下载工具,发现还是执行不了,于是一个网友帮我分析了一下,如图打勾的地方,下载了,竟然可以执行了。牛,感谢这个耐心的网友,其实网络世界这类不算问题的问题,往往是不愿意回答的。

这里写图片描述

fuhome.net未来之家物联网实验室,开发的这个模块,主要实现远程微信控制wifi继电器,测温湿度。

还可以网页和APP控制,也提供第三方接口供个人和中小企业使用。案例设备的地址:

http://www.fuhome.net/home/?id=1784,可以控制,权限是开放的
这里写图片描述

2017-12-24 13:54:32 grey_csdn 阅读数 8543

       买树莓派的时候知道了这个小板子,一同买了。买来太久,一直没有玩过。近段时间倒是花了点时间把手头的几个开发板学习、探索了一下。现在轮到Arduino了。

       其实,比较简单的入门就是安装一下开发环境烧写个程序了。这个完成后,接下来的折腾就顺理成章了。相应的环境搭建主要是就两部分:1,串口驱动的安装;2,Arduino IDE的安装。串口驱动的安装是比较通用的一个,Arduino的安装则需要去其官网上下载。

       IDE有安装版本,也有绿色版本。我觉得安装版麻烦,就直接下载了免安装版本。比较好的一点是软件打开后已经默认是中文版本,看起来是增加了区域语言的识别。


       通过上面的菜单操作可以导入一个示例程序工程。


       以上是导入例程之后的样子,画出来的图标中,对号是编译启动功能而箭头是编译并下载。在此之前,需要先选择串口配置。


       通过如上界面,选择相应的串口。比较人性化的是,串口中连接到Arduino的串口端口会有相应的文字提示。选项的上面是开发板的选择,我自己用的ArduinoUno。

       好了,接下来就是编译烧写了。简化的方法就是直接点击向右的箭头了。


       编译以及下载(IDE中叫做上传),在下面的框条中会有显示。从上面看,我的程序已经烧写成功。

       按下板子上的复位键,LED等三次闪烁后代表复位成功。接下来即可看到LED的规律闪烁。

2015-09-29 19:16:09 sillycheat 阅读数 2203

Arduino程序基本结构如下:

void setup() {

  // put your setup code here, to run once:


}


void loop() {
  // put your main code here, to run repeatedly:


}

(1)setup()

Arduino控制器通电或者复位后,即开始执行setup()函数中的程序,该程序只会执行一次。

通常在setup()函数中完成对Arduino的初始化设置,如配置I/O状态和初始化串口操作等。

(2)loop()

setup()函数执行完后,Arduino会接着执行loop()中程序。loop()函数是一个死循环,其中的程序会不断的重复运行。

通常在loop()函数中完成程序的主要功能,如驱动各种模块和采集数据等。

第一个Arduino程序

阅读数 2653