天天看點

機器人控制器程式設計實踐指導書舊版-實踐一 LED燈(數字量)

适用于UNO/2560/DUE/ESP8266/ESP32,2021年之前使用版本。

機器人控制器程式設計實踐指導書舊版-實踐一 LED燈(數字量)

實踐一 LED燈(數字量)

1.1 實踐目的

  • 了解機器人控制器的基本概念和特點
  • 了解Arduino[ESP32]簡介及相應的硬體裝置
  • 掌握Arduino[ESP32] IDE的安裝和使用
  • 掌握Arduino[ESP32]硬體基本資源和程式設計方法

1.2 實踐裝置

  • PC機一台
  • Arduino[ESP32]開發闆及配件等
  • 萬用表和示波器等

1.3 實踐原理

  • 初級:

1.3.1 控制13引腳燈閃爍。

機器人控制器程式設計實踐指導書舊版-實踐一 LED燈(數字量)
機器人控制器程式設計實踐指導書舊版-實踐一 LED燈(數字量)

示意圖和原理圖

參考代碼:

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 跑馬燈。

示意圖

機器人控制器程式設計實踐指導書舊版-實踐一 LED燈(數字量)

原理圖

參考代碼:

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 按鍵控制。

機器人控制器程式設計實踐指導書舊版-實踐一 LED燈(數字量)

示意圖

機器人控制器程式設計實踐指導書舊版-實踐一 LED燈(數字量)

原理圖

參考代碼:

// 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。
機器人控制器程式設計實踐指導書舊版-實踐一 LED燈(數字量)

示意圖

機器人控制器程式設計實踐指導書舊版-實踐一 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 旋鈕控制燈亮度。

機器人控制器程式設計實踐指導書舊版-實踐一 LED燈(數字量)

示意圖

機器人控制器程式設計實踐指導書舊版-實踐一 LED燈(數字量)

原理圖

  • 進階:

開源機器人作業系統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交通燈:

該電路可以被編碼,使得汽車和行人交通燈都經過正常循環,直到行人按下按鈕。在這種情況下,燈會改變對行人的偏好。
機器人控制器程式設計實踐指導書舊版-實踐一 LED燈(數字量)

示意圖

機器人控制器程式設計實踐指導書舊版-實踐一 LED燈(數字量)

原理圖

請編寫代碼實作英文簡介中的功能。

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的控制信号為低使能時,并行輸出端的輸出值等于并行輸出緩存器所存儲的值。