Arduino

图床 arduino-img/

太极创客arduino        w3c-arduino       官方示例
爱上Arduino(公众号)
arducam

General Tips

  • // 单行注释 /* 多行 注释 */ 每行代码之后用分号; 变颜色的词-关键词
  • Serial.begin(9600); //打开串口通讯,设置传输速率为9600字节每秒
  • 注意变量的作用于,如果在大括号里面定义,那么作用于就限于这个大括号。大括号外面的变量是全局变量
  • 一般红色的是正极黑色的是负极。就像交流电线是一样的。

 

串口通讯

arduino可以通过USB线进行串口通讯,引脚0(RX)中的RX表示receive,而引脚1(TX)的TX表示Transmit,这两个引脚是专门用于串口通讯的。Arduino IDE软件中的“串口监视器”按钮可以显示相关内容。

目前用到的函数:
(1) Serial.available()  //检测串口缓冲区是否有数据
具体来讲:Serial.available() 返回串口缓冲区中当前剩余的字符个数。一般用这个函数来判断串口的缓冲区有无数据,当Serial.available()>0时,说明串口接收到了数据,可以读取。

  • Serial.avaliable()的返回值是当前缓冲区中接收到的数据字节数。为了使它一次就捕获到所有缓冲区中的数据,我们通常需要加延时函数。下图例子,一次读取串口监视器的所有缓存数据,没有延时的话,连续输出1。
    void loop() {
       while (Serial.available()>0 )   //检测串口缓冲区是否有数据
      { delay(100);
        Serial.println(Serial.available());
        int a =Serial.read();
      }
    }
    
  • 特别注意,Serial.available并没有读取数据,所以没有读取之前,所有的数据都还是在当前缓冲区中。

(2) Serial.read()   //read() 函数可用于从设备接收到数据中读取一个字节(8 个bits)的数据, 本函数属于Stream类
具体来讲:Serial.read()指从串口的缓冲区取出并读取一个Byte的数据比如有设备通过串口向Arduino发送数据了,我们就可以用Serial.read()来读取发送的数据。实例如下

while (Serial.available()>0)
  {
    data= Serial.read();
    delay(2);
  }

注释:当串口接收到数据时(上面Serial.available()>0这句),反复读取串口的数据并赋值给data (上面data= Serial.read()这句),直到数据读完(即Serial.available()=0的时候)。

演示每读取一次少一个字节:

void setup(){
  Serial.begin(9600);
}
void loop(){
  if(Serial.available()>0){
    delay(2000);
    Serial.println("yes");
    char inchar= Serial.read();
    if(Serial.available()>0){
      Serial.println("yes2");
    }
    else{
       Serial.println("no2");
    }
  }
}
  • 选用换行符或者回车,会多增加一个字节。多read一次。

参考资料:
1. Arduino的串口结束符及串口缓冲区
2. 深入理解Arduino的串口结束符及串口缓冲区
3. 关于arduino清空串口缓存

Arduino的编程中,串口输入与输出都是针对ASCII码值的,比如字母's'的ASCII码值为115。

输入方面,对于Serial.read(), monitor中输入's'或者115,程序得到的值都为's'. 而且Serial.read()每次只能接受一个byte的数据,如果想要输入字符串,则需要专门写一段程序来实现。

(3) Serial.print()和Serial.println(),以人类可读的ASCII码形式向串口发送数据,但是后者有换行。

Serial.print(78) 发送 “78”
Serial.print(1.23456) 发送 “1.23”
Serial.print(‘N’) 发送 “N”
Serial.print(“Hello world.”) 发送 “Hello world.”
串口监视器输入2,那么Serial.print(Serial.read()) 的输入结果为50,因为2对应的ASCII码是50

 

数字I/O

(1) 引脚为输出(OUTPUT)模式
当引脚设置为输出(OUTPUT)模式时,引脚为低阻抗状态。这意味着Arduino可以向其它电路元器件提供电流。也就是说,Arduino引脚在输出(OUTPUT)模式下可以点亮LED或者驱动电机。(如果被驱动的电机需要超过40mA的电流,Arduino将需要三极管或其它辅助元件来驱动他们)

设为OUTPUT之后,就可以用digitalWrite()来设置高电平(5 V)或者低电平(0 V /GND),示例如下

void setup() {
  // put your setup code here, to run once:
  pinMode(8,OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(8,HIGH);
  delay(1000);
  digitalWrite(8,LOW);
}

(2) 引脚为输入(INPUT)模式
此时,引脚为高阻抗状态(100兆欧)。此时该引脚可用于读取传感器信号或开关信号。注意:当Arduino引脚设置为输入(INPUT)模式或者输入上拉(INPUT_PULLUP)模式,请勿将该引脚与负压或者高于5V的电压相连,否则可能会损坏Arduino控制器。

(3) 设置引脚为输入上拉(INPUT_PULLUP)模式
Arduino 微控制器自带内部上拉电阻。如果你需要使用该内部上拉电阻,可以通过pinMode()将引脚设置为输入上拉(INPUT_PULLUP)模式。

 

电机

电机根据电源种类分为直流电机(DC)交流电机(AC)和交直流两用电机(Universal),arduino通常配合直流电机进行开发。

这里用步进电机28BYJ-48,5V DC

#include<Stepper.h>
// 这里设置步进电机旋转一圈是多少步(可以根据步进电机实际进行修改,28BYJ-48 八拍为64步,单四拍为32步)。
//根据您的步进电机参数修改。
#define STEPS 64
//设置步进电机的步数和引脚(就是注意点2里面说的驱动板上IN1~IN4连接的四个数字口)。
Stepper stepper(STEPS, 8, 10, 9, 11);
void setup()
{
// 以每分钟转速设置电机速度,此功能不会使电机转动,只是设置调用step()时的速度。
stepper.setSpeed(500);
// 初始化串口,用于调试输出信息
Serial.begin(9600);
}
void loop()
{
stepper.step(300); //4步模式下旋转一周用2048 步。8拍模式下旋转一周用4096步。
delay(500);
stepper.step(-300); 
delay(500);
}

注意接上板子的5V 的电源。
参考:How to use Arduino as a 28BYJ-48 Stepper Motor Controller with a ULN2004 Driver Board

 

舵机

棕色 — 接GND
橙色 — 接Digital 10 (PWM 信号)
红色 — 接 5V

#include <Servo.h>
 
#define PIN_SERVO 10
Servo myservo;
 
void setup()
{
  myservo.attach(PIN_SERVO);
}
 
void loop()
{
  myservo.write(0);
  delay(1000);
  myservo.write(80);
  delay(1000);
  myservo.write(160);
  delay(1000);
  myservo.write(80);
  delay(1000);
  myservo.write(0);
  delay(1000);
}

注:如果上述舵机是在0度和180度之间来回旋转,但是实际运行过程中旋转到160度就停了下来,这时要修改attach方法的默认值,改为servo.attach(pin, 500, 2500),原因参考Servo - attach()或者孙老师视频。

舵机(servo) = 电机 + 控制 +反馈

舵机的旋转不像普通电机那样只是转圈圈,它可以根据你的指令旋转到0至180度之间的任意角度然后精准的停下来,常用于机器人、遥控飞机、飞机航模等。高速旋转的电机,通过齿轮降低了输出的转速,但是增加了输出轴上的输出扭矩,其结构如下图。

电位器(Potentiometer)实际上就是可变电阻。电位器和电机均被连接到电路板上。控制电路通过电位计可监控舵机的当前角度。如果轴的位置与控制信号相符,那么电机就会关闭。如果控制电路发现这个角度不正确,它就会控制马达转动,直到它达到指定的角度。舵机角度根据制造商的不同而有所不同。比如,一个180度的舵机,它可以在0度至180度之间运动。由于限位装置被安装在主输出装置上,超出这个范围机械结构就不能再转动了。舵机的输出功率与它所需要转动的距离成正比。如果输出轴需要转动很长的距离,马达就会全速运转,如果它只需要短距离转动,马达就会以较慢的速度运行,这叫做速度比例控制。

舵机的控制一般需要一个20ms左右的时基脉冲,该脉冲的高电平部分一般为0.5ms-2.5ms范围,总间隔为2ms。脉冲的宽度(PWM信号的空占比,使用Arduino数字前带~的pin)将决定马达转动的距离:0.5ms————-0度; 1.0ms————45度; 1.5ms————90度; 2.0ms———–135度; 2.5ms———–180度。

Arduino 的驱动能力有限,所以当需要控制1 个以上的舵机时需要外接电源。一个机器人经常需要很多个舵机同时工作,此时需要加一个舵机控制板(比如PCA9685),舵机控制板本身是一个单片机,它不但能接多个舵机,同时也简化了舵机操作命令。SG90小舵机可用arduino板上的5V供电,大的舵机有的需要外部供电才能驱动,外接电源时需要将降到舵机指定的电压,否则会烧坏舵机。

常见的舵机如下:

  • SG90,便宜,能够应付绝大部分场景(基本能用)。缺点是市面上有大量的山寨品,品质无法得到保证,另外塑料减速齿轮也比较容易磨损,扭矩也比较小。
  • MG90,是SG90的升级版,使用了金属齿轮,扭矩和寿命都得到改善,当然价格更贵。
  • MG996,金属齿轮,最大特点是扭矩大,几乎是SG90的10倍左右,体积也更大。

360度舵机 = 普通舵机 - 电位器

360度舵机不具备角度定位功能,只能控制转动的方向。360度舵机一个PWM信号,舵机会以一个特定的速度转动,类似与电机。但与电机不同的是,360舵机是闭环控制,速度控制稳定。 PWM 信号与360舵机转速的关系: 0.5ms----------------正向最大转速; 1.5ms----------------速度为0; 2.5ms----------------反向最大转速。

参考资料:
(1) 【Arduino百问】舵机?你懂舵机吗?三分钟深入了解舵机 更精准的控制——孙老师
(2) 舵机控制简易入门教程
(3) 180度舵机与360度舵机

 

 

Arduino UV Index Meter – Measuring UV Light

 

Arduino 制作光谱仪

 

Arduino 制作闪烁体探测器

参考资料:
(1) Wolszczak W, Krämer K W, Dorenbos P. CsBa2I5: Eu2+, Sm2+—The First High‐Energy Resolution Black Scintillator for γ‐Ray Spectroscopy[J]. physica status solidi (RRL)–Rapid Research Letters, 2019, 13(9): 1900158.
(2) Scintillino - an Arduino-based Quick&dirty Scintillation Counter
(3) ArduSiPM a small, light and low power, All-In-One particle detector

经典实例

blink

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output. 
  pinMode(LED_BUILTIN, OUTPUT);  
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}

注:对于UNO板子,板子上的LED is attached to digital pin 13

Leave a Reply