适用于UNO/2560/DUE/ESP8266/ESP32,2021年之前使用版本。
实践一 LED灯(数字量)
1.1 实践目的
- 了解机器人控制器的基本概念和特点
- 了解Arduino[ESP32]简介及相应的硬件设备
- 掌握Arduino[ESP32] IDE的安装和使用
- 掌握Arduino[ESP32]硬件基本资源和编程方法
1.2 实践设备
- PC机一台
- Arduino[ESP32]开发板及配件等
- 万用表和示波器等
1.3 实践原理
- 初级:
1.3.1 控制13引脚灯闪烁。
示意图和原理图
参考代码:
int led = 13; // integer variable led is declared
void setup() { // the setup() method is executed only once
pinMode(led, OUTPUT); // the led PIN is declared as digital output
}
void loop() { // the loop() method is repeated
digitalWrite(led, HIGH); // switching on the led
delay(1000); // stopping the program for 1000 milliseconds
digitalWrite(led, LOW); // switching off the led
delay(1000); // stopping the program for 1000 milliseconds
}
1.3.2 跑马灯。
示意图
原理图
参考代码:
int timer = 100; // The higher the number, the slower the timing.
void setup() { // use a for loop to initialize each pin as an output:
for (int thisPin = 2; thisPin < 8; thisPin ) {
pinMode(thisPin, OUTPUT);
}
}
void loop() {
// loop from the lowest pin to the highest:
for (int thisPin = 2; thisPin < 8; thisPin ) {
// turn the pin on:
digitalWrite(thisPin, HIGH);
delay(timer);
// turn the pin off:
digitalWrite(thisPin, LOW);
}
// loop from the highest pin to the lowest:
for (int thisPin = 7; thisPin >= 2; thisPin--) {
// turn the pin on:
digitalWrite(thisPin, HIGH);
delay(timer);
// turn the pin off:
digitalWrite(thisPin, LOW);
}
}
1.3.3 按键控制。
示意图
原理图
参考代码:
// constants won't change. They're used here to
// set pin numbers:
const int buttonPin = 2; // the number of the pushbutton pin
const int ledPin = 13; // the number of the LED pin
// variables will change:
int buttonState = 0; // variable for reading the pushbutton status
void setup() {
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
}
void loop(){
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);
// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
if (buttonState == HIGH) {
// turn LED on:
digitalWrite(ledPin, HIGH);
}
else {
// turn LED off:
digitalWrite(ledPin, LOW);
}
}
- 中级:
1.3.4 74HC595。
本项目使用两个74HC595移位寄存器,仅用3个Arduino管脚控制16个LED。 |
---|
示意图
原理图
使用74HC595与数字直接控制LED有何优势,写出核心代码。(选做)
595驱动电流大,35毫安每个端口,操作灵活,需要数据线,时钟线,锁存线,(三态控制线,清零线 可不用),数目多的话用595可以方便的组成动态显示,电路简单成本低。
void _74hc595_init(void)
{
gpio_config_t io_conf = {
.intr_type = GPIO_PIN_INTR_DISABLE,
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = (1ULL<<SCK_GPIO_PIN)|(1ULL<<RCK_GPIO_PIN)|(1ULL<<SDA_GPIO_PIN),
.pull_down_en = 1,
.pull_up_en = 0,
};
gpio_config(&io_conf);
HC595_SCK_Low();
HC595_RCK_Low();
HC595_Data_Low();
}
void HC595_Save(void)
{
HC595_RCK_Low(); // 将RCK拉低
delay(10);
HC595_RCK_High(); // 再将RCK拉高,RCK即可产生一个上升沿
}
void HC595_Send_Byte(uint8_t byte)
{
uint8_t i;
for (i = 0; i < 8; i ) //一个字节8位,传输8次,一次一位,循环8次,刚好移完8位
{
HC595_SCK_Low(); // SCK拉低
if (byte & 0x80){ //先传输高位,通过与运算判断第八是否为1
HC595_Data_High(); //如果第八位是1,则与 595 DS连接的引脚输出高电平
}else{ //否则输出低电平
HC595_Data_Low();
}
byte <<= 1; // 左移一位,将低位往高位移,通过 if (byte & 0x80)判断低位是否为1
HC595_SCK_High(); // SHCP拉高, SHCP产生上升沿
}
}
void HC595_Send_Multi_Byte(uint8_t *data, uint16_t len)
{
uint8_t i;
for (i = 0; i < len; i ) {
HC595_Send_Byte(data[i]);
debug_i("leve :%d data:%x",i,data[i]);
}
HC595_Save();
}
1.3.5 旋钮控制灯亮度。
示意图
原理图
- 高级:
开源机器人操作系统ROS和开源硬件Arduino[ESP32]联调(选修)
ROS 1.0 Melodic:
/*
* rosserial Subscriber Example
* Blinks an LED on callback
*/
#include <ros.h>
#include <std_msgs/Empty.h>
ros::NodeHandle nh;
void messageCb( const std_msgs::Empty& toggle_msg){
digitalWrite(13, HIGH-digitalRead(13)); // blink the led
}
ros::Subscriber<std_msgs::Empty> sub("toggle_led", &messageCb );
void setup()
{
pinMode(13, OUTPUT);
nh.initNode();
nh.subscribe(sub);
}
void loop()
{
nh.spinOnce();
delay(1);
}
依次分别在不同终端运行如下命令:
roscore
rosrun rosserial_python serial_node.py /dev/ttyUSB0
rostopic pub toggle_led std_msgs/Empty --once
观察LED灯状态。
ROS 2.0 Dashing:
#include <ros2Arduino[ESP32].h>
#define XRCEDDS_PORT Serial
void subscribeLed(std_msgs::Bool* msg, void* arg)
{
(void)(arg);
digitalWrite(LED_BUILTIN, msg->data);
}
class LedSub : public ros2::Node
{
public:
LedSub()
: Node("ros2Arduino[ESP32]_sub_node")
{
this->createSubscriber<std_msgs::Bool>("Arduino[ESP32]_led", (ros2::CallbackFunc)subscribeLed, nullptr);
}
};
void setup()
{
XRCEDDS_PORT.begin(115200);
while (!XRCEDDS_PORT);
ros2::init(&XRCEDDS_PORT);
pinMode(LED_BUILTIN, OUTPUT);
}
void loop()
{
static LedSub LedNode;
ros2::spin(&LedNode);
}
1.4 实践内容
阅读1.3中示意图、原理图和参考代码,在Arduino[ESP32]平台上完成实践。
1.5 实践问题
1.5.1交通灯:
该电路可以被编码,使得汽车和行人交通灯都经过正常循环,直到行人按下按钮。在这种情况下,灯会改变对行人的偏好。 |
---|
示意图
原理图
请编写代码实现英文简介中的功能。
void setup() {
pinMode(LED_G, OUTPUT);
pinMode(LED_Y, OUTPUT);
pinMode(LED_R, OUTPUT);
}
void loop() {
digitalWrite(LED_G, LOW);点亮 绿灯
delay(5000);//延时5秒
digitalWrite(LED_G, HIGH); //熄灭 绿灯
for(int i=0;i<3;i )//闪烁交替三次,黄灯闪烁效果
{
delay(500);//延时0.5 秒
digitalWrite(LED_Y, LOW);//点亮 黄灯
delay(500);//延时0.5 秒
digitalWrite(LED_Y, HIGH);//熄灭 黄灯
}
delay(500);//延时0.5 秒
digitalWrite(LED_R, LOW);//点亮 红灯
delay(5000);//延时5 秒
digitalWrite(LED_R, HIGH);//熄灭 红灯
}
1.5.2 能否调节非PWM口外接的LED灯的亮度,为什么?
能。
PWM是一种脉冲宽度调制,也就是看高电平持续的时长。PWM的占空比代表的是平均电压,占空比发生变化后LED和限流电阻两端的平均电压就会发生变化,那么流过LED的电流就会发生变化,这就是PWM调节亮度的原理。
int potpin=0;
int ledpin=11;
int val=0;
void setup()
{
pinMode ( ledpin, OUTPUT);
Serial.begin(9600);
}
void loop ()
{
val=analogRead(potpin);
Serial.println(val) ;
analogWrite(ledpin, val);
delay(10);
}
1.6 实践总结
回顾本次实践,遇到哪些问题,如何解决,经验和启发有哪些?
74HC595是一个8位串行输入、并行输出的位移缓存器:并行输出为三态输出。在SCK 的上升沿,串行数据由数据脚(A)输入到内部的8位位移缓存器,并由Q7’输出,而并行输出则是在LCK的上升沿将在8位位移缓存器的数据存入到8位并行输出缓存器。当串行数据输入端OE的控制信号为低使能时,并行输出端的输出值等于并行输出缓存器所存储的值。
评分: |
---|