李优秀 发表于 2024-10-15 23:56:12

Arduino平台软硬件原理及使用——开源库的使用

文章目录:
一、库文件的下载及导入
二、库文件源代码分析
三、库文件应用举例
一、库文件的下载及导入

https://i-blog.csdnimg.cn/blog_migrate/1cd479879679f31d8c9717240910ae57.png#pic_center
有关arduino开源库的导入有两种方案:
1.第一种方案需要借助arduino.cc网站来举行查询下载,然后在Arduino软件中举行导入。
2.第二种方案则只需要使用较新版本的Arduino软件(2.2版本之后),在软件中可以直接搜索并导入开源库。
1.在Arduino.cc举行导入库

首先在网页地点框直接输入arduino.cc便可进入网站:
https://i-blog.csdnimg.cn/blog_migrate/e2dd68b28a6315a09156336e26e0eefb.png#pic_center
然后点击上方【DOCUMENTATION】选项:
https://i-blog.csdnimg.cn/blog_migrate/e2429bccc6c11793314d313f94f36d1e.png#pic_center
在此页面点击左侧【Libraries】选项,便可进入官方收录的库文件页面:
https://i-blog.csdnimg.cn/blog_migrate/2d3733b7cb36a3ace97eb215f0dc95cd.png#pic_center
选择要用的库文件的类目,这里以【display】为例:
https://i-blog.csdnimg.cn/blog_migrate/fe76021ebc516d6e0f9dbcd32d669d30.png#pic_center
然后点击具体的库文件,以【LiquidCrystal】为例:
https://i-blog.csdnimg.cn/blog_migrate/7ce443b8a4dfdd270bd77c684fce98a7.png#pic_center
进入库文件下载目录后,直接点击要用的版本号即可直接下载。
下载完成后如果不是压缩包,最好压缩成zip文件:
https://i-blog.csdnimg.cn/blog_migrate/da340169a9f5e2c15ec48077dd2007ae.png#pic_center
末了打开Arduino软件,选择【项目】-【导入库】-【添加.ZIP库】然后选择对应的zip文件即可导入乐成。
2.使用Arduino软件导入库

上述方案较为复杂,所以建议使用较新版本的Arduino软件直接导入库:
https://i-blog.csdnimg.cn/blog_migrate/abcea6096abf7cec0c6a35f7dd460d21.png#pic_center
在此版本的软件中直接点选左侧的“册本”样式的图标(其表示为库文件),然后直接在搜索框查找要使用的库文件名,选择对应库文件及版本点击安装即可。
这种方案则最为简洁,当然有些时间要使用的库在软件中查询不到,此时就需要接纳第一种方案举行导入。
2、库文件源代码分析

https://i-blog.csdnimg.cn/blog_migrate/7ea0ccc9c767a48ca979b5f298402f4b.png#pic_center
如上图所示,一般库文件中会有如上几个文件(会存在些许不同)。
1.示例程序的使用

example文件即为【示例】,这里面会有开源文件贡献者编写的几个示例程序,用于资助学习者理解库的使用:
https://i-blog.csdnimg.cn/blog_migrate/1083ea0cba10aabe7c302d4ce6f3cce2.png#pic_center
当然只要将库文件导入过Arduino中,也可以在Arduino软件中打开相应的示例程序:
https://i-blog.csdnimg.cn/blog_migrate/e8a10984e0cac64690c078e0ee54ca53.png#pic_center
2.【.h文件】及【.cpp】文件分析

在【src】文件夹中存在以下两个文件:
【.h】后缀我们称之为头文件,【.cpp】后缀我们称之为源文件
https://i-blog.csdnimg.cn/blog_migrate/4d0b5a1a96e9f753ebf5ed408849ce55.png#pic_center
头文件通常包含类声明、函数原型、宏定义和全局变量声明等。它们的目的是提供一种方式来共享代码,并确保在多个源文件中使用一致的声明:
/*
HCSR04 - Library for arduino, for HC-SR04 ultrasonic distance sensor.
Created by Dirk Sarodnick, 2020.
*/

#ifndef HCSR04_H
#define HCSR04_H

#include "Arduino.h"

#define HCSR04_INVALID_RESULT-1;
#define HCSR04_NO_TRIGGER      -2;
#define HCSR04_NO_ECHO         -3;

class HCSR04Sensor {
        public:
                HCSR04Sensor();
                ~HCSR04Sensor();

                typedef enum eUltraSonicUnlock {
                        unlockSkip = 0,
                        unlockMaybe = 1,
                        unlockForced = 2
                } eUltraSonicUnlock_t;
               
                void begin(uint8_t triggerPin, uint8_t echoPin) { begin(triggerPin, new uint8_t{ echoPin }, 1); }
                void begin(uint8_t triggerPin, uint8_t* echoPins, uint8_t echoCount) { begin(triggerPin, echoPins, echoCount, 100000, eUltraSonicUnlock_t::unlockSkip); }
                void begin(uint8_t triggerPin, uint8_t echoPin, uint32_t timeout, eUltraSonicUnlock_t unlock) { begin(triggerPin, new uint8_t{ echoPin }, 1, timeout, unlock); }
                void begin(uint8_t triggerPin, uint8_t* echoPins, uint8_t echoCount, uint32_t timeout, eUltraSonicUnlock_t unlock) { begin(triggerPin, echoPins, echoCount, timeout, 10, 10, unlock); }
                void begin(uint8_t triggerPin, uint8_t* echoPins, uint8_t echoCount, uint32_t timeout, uint16_t triggerTime, uint16_t triggerWait, eUltraSonicUnlock_t unlock);
                void end();
               
                long* measureMicroseconds() { measureMicroseconds(lastMicroseconds); return lastMicroseconds; }
                void measureMicroseconds(long* results);

                double* measureDistanceMm() { measureDistanceMm(defaultTemperature, lastDistances); return lastDistances; }
                void measureDistanceMm(double* results) { measureDistanceMm(defaultTemperature, results == NULL ? lastDistances : results); }
                double* measureDistanceMm(float temperature) { measureDistanceMm(temperature, lastDistances); return lastDistances; }
                void measureDistanceMm(float temperature, double* results);

                double* measureDistanceCm() { measureDistanceCm(defaultTemperature, lastDistances); return lastDistances; }
                void measureDistanceCm(double* results) { measureDistanceCm(defaultTemperature, results == NULL ? lastDistances : results); }
                double* measureDistanceCm(float temperature) { measureDistanceCm(temperature, lastDistances); return lastDistances; }
                void measureDistanceCm(float temperature, double* results);

                double* measureDistanceIn() { measureDistanceIn(defaultTemperature, lastDistances); return lastDistances; }
                void measureDistanceIn(double* results) { measureDistanceIn(defaultTemperature, results == NULL ? lastDistances : results); }
                double* measureDistanceIn(float temperature) { measureDistanceIn(temperature, lastDistances); return lastDistances; }
                void measureDistanceIn(float temperature, double* results);
               
                static void triggerInterrupt0(void);
                static void triggerInterrupt1(void);
                static void triggerInterrupt2(void);
                static void triggerInterrupt3(void);
                static void triggerInterrupt4(void);
                static void triggerInterrupt5(void);
                static void triggerInterrupt6(void);
                static void triggerInterrupt7(void);
                static void triggerInterrupt8(void);
                static void triggerInterrupt9(void);
               
                static void echoInterrupt0(void);
                static void echoInterrupt1(void);
                static void echoInterrupt2(void);
                static void echoInterrupt3(void);
                static void echoInterrupt4(void);
                static void echoInterrupt5(void);
                static void echoInterrupt6(void);
                static void echoInterrupt7(void);
                static void echoInterrupt8(void);
                static void echoInterrupt9(void);
       
        private:
                float defaultTemperature = 19.307;
                long* lastMicroseconds;
                double* lastDistances;

                uint32_t timeout;
                uint16_t triggerTime = 10; // HC-SR04 needs at least 10�s trigger. Others may need longer trigger pulses.
                uint16_t triggerWait = 10; // HC-SR04 sends its signal about 200�s. We only wait a small amount to reduce interference, but to not miss anything on slower clock speeds.
                volatile uint8_t triggerPin;
                volatile unsigned long* volatile triggerTimes;
               
                uint8_t echoCount;
                volatile int16_t* volatile echoStages;
                volatile int16_t* volatile echoInts;
                volatile int16_t* volatile echoPorts;
                volatile unsigned long* volatile echoTimes;
               
                void triggerInterrupt(uint8_t);
                void echoInterrupt(uint8_t);
                void unlockSensors(eUltraSonicUnlock_t, uint8_t*);
};

extern HCSR04Sensor HCSR04;

#endif // HCSR04_H
源文件包含了实现代码,即函数和方法的定义。它们通常包含与头文件对应的实现:
/*
HCSR04 - Library for arduino, for HC-SR04 ultrasonic distance sensor.
Created by Dirk Sarodnick, 2020.
*/

#include "Arduino.h"
#include "HCSR04.h"

HCSR04Sensor::HCSR04Sensor() {}
HCSR04Sensor::~HCSR04Sensor() { this->end(); }

void HCSR04Sensor::begin(uint8_t triggerPin, uint8_t* echoPins, uint8_t echoCount, uint32_t timeout, uint16_t triggerTime, uint16_t triggerWait, eUltraSonicUnlock_t unlock) {
        if (this->echoCount != echoCount) this->end();
       
        this->triggerPin = triggerPin;
        pinMode(triggerPin, OUTPUT);

        this->timeout = timeout;
        this->triggerTime = triggerTime;
        this->triggerWait = triggerWait;
        this->echoCount = echoCount;
       
        if (this->lastMicroseconds == NULL) this->lastMicroseconds = new long;
        if (this->lastDistances == NULL) this->lastDistances = new double;
       
        if (this->triggerTimes == NULL) this->triggerTimes = new unsigned long;
        if (this->echoTimes == NULL) this->echoTimes = new unsigned long;

        if (this->echoStages == NULL) this->echoStages = new int16_t;
        if (this->echoInts == NULL) this->echoInts = new int16_t;
        if (this->echoPorts == NULL) this->echoPorts = new int16_t;

        for (uint8_t i = 0; i < this->echoCount; i++) {
                this->triggerTimes = 0;
                this->echoTimes = 0;

                int16_t interrupt = digitalPinToInterrupt(echoPins);
                if (interrupt == NOT_AN_INTERRUPT) {
                        this->echoStages = -1;
                        this->echoInts = -1;
                        this->echoPorts = echoPins;
                } else {
                        this->echoStages = 0;
                        this->echoInts = interrupt;
                        this->echoPorts = -1;
                }

                pinMode(echoPins, INPUT);
        }
       
        // Unlock sensors that are possibly in a locked state, if this feature is enabled.
        this->unlockSensors(unlock, echoPins);
}

void HCSR04Sensor::end() {
        if (this->lastMicroseconds != NULL) delete []this->lastMicroseconds;
        if (this->lastDistances != NULL) delete []this->lastDistances;
        if (this->triggerTimes != NULL) delete []this->triggerTimes;
        if (this->echoTimes != NULL) delete []this->echoTimes;
       
        if (this->echoPorts != NULL) delete []this->echoPorts;
        if (this->echoInts != NULL) delete []this->echoInts;
        if (this->echoStages != NULL) delete []this->echoStages;
       
        this->lastMicroseconds = NULL;
        this->lastDistances = NULL;
        this->triggerTimes = NULL;
        this->echoTimes = NULL;
        this->echoPorts = NULL;
        this->echoInts = NULL;
        this->echoStages = NULL;
}

void HCSR04Sensor::measureMicroseconds(long* results) {
        if (results == NULL) results = this->lastMicroseconds;

        bool finished = true;
        bool waiting = true;
        unsigned long startMicros = micros();
        unsigned long currentMicros = 0;
        unsigned long elapsedMicros = 0;

        // Make sure that trigger pin is LOW.
        digitalWrite(triggerPin, LOW);
        delayMicroseconds(4);
       
        // Hold trigger HIGH for 10 microseconds (default), which signals the sensor to measure distance.
        digitalWrite(triggerPin, HIGH);
        delayMicroseconds(this->triggerTime);

        // Set trigger LOW again and wait to give the sensor time for sending the signal without interference
        digitalWrite(triggerPin, LOW);
        delayMicroseconds(this->triggerWait);
       
        // Attach interrupts to echo pins for the starting point
        for (uint8_t i = 0; i < this->echoCount; i++) {
                if (this->echoInts >= 0 && this->echoStages == 0) {
                        this->echoStages = 1;
                        switch (i) {
                                case 0: attachInterrupt(this->echoInts, &triggerInterrupt0, RISING); break;
                                case 1: attachInterrupt(this->echoInts, &triggerInterrupt1, RISING); break;
                                case 2: attachInterrupt(this->echoInts, &triggerInterrupt2, RISING); break;
                                case 3: attachInterrupt(this->echoInts, &triggerInterrupt3, RISING); break;
                                case 4: attachInterrupt(this->echoInts, &triggerInterrupt4, RISING); break;
                                case 5: attachInterrupt(this->echoInts, &triggerInterrupt5, RISING); break;
                                case 6: attachInterrupt(this->echoInts, &triggerInterrupt6, RISING); break;
                                case 7: attachInterrupt(this->echoInts, &triggerInterrupt7, RISING); break;
                                case 8: attachInterrupt(this->echoInts, &triggerInterrupt8, RISING); break;
                                case 9: attachInterrupt(this->echoInts, &triggerInterrupt9, RISING); break;
                        }
                }
        }
       
        // Wait until all echos are returned or timed out.
        while(true) {
                delayMicroseconds(1);
               
                finished = true;
                waiting = true;
                currentMicros = micros();
                elapsedMicros = currentMicros - startMicros;

                for (uint8_t i = 0; i < this->echoCount; i++) {
                        waiting &= elapsedMicros < this->timeout || (this->triggerTimes > 0 && this->echoTimes == 0 && (currentMicros - this->triggerTimes) < this->timeout);

                        if (this->echoPorts >= 0 && this->triggerTimes == 0) {
                                if (digitalRead(this->echoPorts) == HIGH) this->triggerTimes = micros();
                        }

                        if (this->triggerTimes > 0 || !waiting) {
                                if (this->echoInts >= 0 && (this->echoStages == 1 || !waiting)) {
                                        if (this->echoStages == 1) this->echoStages = 2;
                                        detachInterrupt(this->echoInts);
                                }
                        } else finished &= false;

                        if (this->echoInts >= 0 && this->triggerTimes > 0 && this->echoStages == 2 && waiting) {
                                this->echoStages = 3;
                                switch (i) {
                                        case 0: attachInterrupt(this->echoInts, &echoInterrupt0, FALLING); break;
                                        case 1: attachInterrupt(this->echoInts, &echoInterrupt1, FALLING); break;
                                        case 2: attachInterrupt(this->echoInts, &echoInterrupt2, FALLING); break;
                                        case 3: attachInterrupt(this->echoInts, &echoInterrupt3, FALLING); break;
                                        case 4: attachInterrupt(this->echoInts, &echoInterrupt4, FALLING); break;
                                        case 5: attachInterrupt(this->echoInts, &echoInterrupt5, FALLING); break;
                                        case 6: attachInterrupt(this->echoInts, &echoInterrupt6, FALLING); break;
                                        case 7: attachInterrupt(this->echoInts, &echoInterrupt7, FALLING); break;
                                        case 8: attachInterrupt(this->echoInts, &echoInterrupt8, FALLING); break;
                                        case 9: attachInterrupt(this->echoInts, &echoInterrupt9, FALLING); break;
                                }
                        }

                        if (this->echoPorts >= 0 && this->triggerTimes > 0 && this->echoTimes == 0) {
                                if (digitalRead(this->echoPorts) == LOW) this->echoTimes = micros();
                        }
                       
                        if ((this->triggerTimes > 0 && this->echoTimes > 0) || !waiting) {
                                if (this->echoInts >= 0 && (this->echoStages == 3 || !waiting)) {
                                        if (this->echoStages == 3) this->echoStages = 4;
                                        detachInterrupt(this->echoInts);
                                }
                        } else finished &= false;
                }
               
                if (!waiting || finished) break;
        }
       
        // Determine the durations of each sensor.
        for (uint8_t i = 0; i < this->echoCount; i++) {
                if (this->echoInts >= 0) this->echoStages = 0;
                if (this->triggerTimes > 0 && this->echoTimes > 0) {
                        long resultTime = this->echoTimes - this->triggerTimes;
                        results = resultTime > 0 ? resultTime : HCSR04_INVALID_RESULT;
                } else if (this->triggerTimes > 0) {
                        results = HCSR04_NO_ECHO;
                } else {
                        results = HCSR04_NO_TRIGGER;
                }

                this->triggerTimes = 0;
                this->echoTimes = 0;
        }
}

void HCSR04Sensor::measureDistanceMm(float temperature, double* results) {
        if (results == NULL) results = this->lastDistances;

        double speedOfSoundInMmPerMs = (331.3 + 0.606 * temperature) / 1000; // Cair ≈ (331.3 + 0.606 ⋅ ϑ) m/s
        long* times = measureMicroseconds();
       
        // Calculate the distance in mm for each result.
        for (uint8_t i = 0; i < this->echoCount; i++) {
                double distanceMm = times / 2.0 * speedOfSoundInMmPerMs;
                if (distanceMm < 10 || distanceMm > 4000) {
                        results = HCSR04_INVALID_RESULT;
                } else {
                        results = distanceMm;
                }
        }
}

void HCSR04Sensor::measureDistanceCm(float temperature, double* results) {
        if (results == NULL) results = this->lastDistances;

        double speedOfSoundInCmPerMs = (331.3 + 0.606 * temperature) / 1000 / 10; // Cair ≈ (331.3 + 0.606 ⋅ ϑ) m/s
        long* times = measureMicroseconds();
       
        // Calculate the distance in cm for each result.
        for (uint8_t i = 0; i < this->echoCount; i++) {
                double distanceCm = times / 2.0 * speedOfSoundInCmPerMs;
                if (distanceCm < 1 || distanceCm > 400) {
                        results = HCSR04_INVALID_RESULT;
                } else {
                        results = distanceCm;
                }
        }
}

void HCSR04Sensor::measureDistanceIn(float temperature, double* results) {
        if (results == NULL) results = this->lastDistances;

        double speedOfSoundInCmPerMs = (331.3 + 0.606 * temperature) * 39.37007874 / 1000 / 1000; // Cair ≈ (331.3 + 0.606 ⋅ ϑ) m/s
        long* times = measureMicroseconds();

        // Calculate the distance in cm for each result.
        for (uint8_t i = 0; i < this->echoCount; i++) {
                double distanceIn = times / 2.0 * speedOfSoundInCmPerMs;
                if (distanceIn < 1 || distanceIn > 157.4804) {
                        results = HCSR04_INVALID_RESULT;
                }
                else {
                        results = distanceIn;
                }
        }
}

void HCSR04Sensor::unlockSensors(eUltraSonicUnlock_t unlock, uint8_t* echoPins) {
        if (unlock == eUltraSonicUnlock_t::unlockSkip) return;
        bool hasLocked = false;

        // Check if any sensor is in a locked state and unlock it if necessary.
        for (uint8_t i = 0; echoPins != 0; i++) {
                if (unlock == eUltraSonicUnlock_t::unlockMaybe && digitalRead(echoPins) == LOW) continue;
                pinMode(echoPins, OUTPUT);
                digitalWrite(echoPins, LOW);
                hasLocked = true;
        }
       
        if (hasLocked) delay(100);

        // Revert the pinMode after potential unlocking.
        for (uint8_t i = 0; echoPins != 0; i++) {
                pinMode(echoPins, INPUT);
        }
       
        if (hasLocked) delay(100);
}

void HCSR04Sensor::triggerInterrupt(uint8_t index) {
        if (this->triggerTimes == 0) this->triggerTimes = micros();
}

void HCSR04Sensor::echoInterrupt(uint8_t index) {
        if (this->triggerTimes > 0 && this->echoTimes == 0) this->echoTimes = micros();
}

void HCSR04Sensor::triggerInterrupt0() { HCSR04.triggerInterrupt(0); }
void HCSR04Sensor::triggerInterrupt1() { HCSR04.triggerInterrupt(1); }
void HCSR04Sensor::triggerInterrupt2() { HCSR04.triggerInterrupt(2); }
void HCSR04Sensor::triggerInterrupt3() { HCSR04.triggerInterrupt(3); }
void HCSR04Sensor::triggerInterrupt4() { HCSR04.triggerInterrupt(4); }
void HCSR04Sensor::triggerInterrupt5() { HCSR04.triggerInterrupt(5); }
void HCSR04Sensor::triggerInterrupt6() { HCSR04.triggerInterrupt(6); }
void HCSR04Sensor::triggerInterrupt7() { HCSR04.triggerInterrupt(7); }
void HCSR04Sensor::triggerInterrupt8() { HCSR04.triggerInterrupt(8); }
void HCSR04Sensor::triggerInterrupt9() { HCSR04.triggerInterrupt(9); }

void HCSR04Sensor::echoInterrupt0() { HCSR04.echoInterrupt(0); }
void HCSR04Sensor::echoInterrupt1() { HCSR04.echoInterrupt(1); }
void HCSR04Sensor::echoInterrupt2() { HCSR04.echoInterrupt(2); }
void HCSR04Sensor::echoInterrupt3() { HCSR04.echoInterrupt(3); }
void HCSR04Sensor::echoInterrupt4() { HCSR04.echoInterrupt(4); }
void HCSR04Sensor::echoInterrupt5() { HCSR04.echoInterrupt(5); }
void HCSR04Sensor::echoInterrupt6() { HCSR04.echoInterrupt(6); }
void HCSR04Sensor::echoInterrupt7() { HCSR04.echoInterrupt(7); }
void HCSR04Sensor::echoInterrupt8() { HCSR04.echoInterrupt(8); }
void HCSR04Sensor::echoInterrupt9() { HCSR04.echoInterrupt(9); }

HCSR04Sensor HCSR04;
三、库文件应用举例

下文以超声波传感器的库HCSR04来举行举例(仅分析代码用法,不作实物接线)
在导入HCSR04库之后,可打开库文件中的实例:
#include <HCSR04.h>

HCSR04 hc(5, 6); //initialisation class HCSR04 (trig pin , echo pin)
               //初始化超声波传感器,即表明接口号。

void setup()
{
    Serial.begin(9600);//串口初始化
}

void loop()
{
    Serial.println(hc.dist()); // return curent distance in serial
                               // hc.dist()会返回超声波传感器检测的距离数据
    delay(60);               // 延时60毫秒
}
具体实例可参考文章——Arduino项目式编程讲授第四章——超声波测距
如果想要了解此库文件下的方法,则可以在Arduino软件中,按住【Alt / cmd】键,然后使用鼠标点击对应的库文件名,即可打开其头文件:
https://i-blog.csdnimg.cn/blog_migrate/37c12065181fa956abf47453e4b1ce6f.png#pic_center
https://i-blog.csdnimg.cn/blog_migrate/c130044ca7feb5c37b4bac41b58dfe4a.png#pic_center
在头文件中,可以阅读文件贡献者做出的注释来了解此库文件中可供使用的方法。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Arduino平台软硬件原理及使用——开源库的使用