• [技术干货] 基于嵌入式的车载导航定位系统设计
    一、前言1.1 项目介绍【1】项目背景随着汽车工业的飞速发展和智能化技术的不断突破,车载导航系统作为现代汽车不可或缺的一部分,在人们的日常生活中扮演着越来越重要的角色。它不仅能够提供精确的路线导航,还能提供丰富的地理信息和娱乐服务,为驾驶者带来了极大的便利和乐趣。传统的车载导航系统主要依赖于内置的地图数据和GPS定位技术,但随着移动互联网的普及和智能设备的快速发展,用户对车载导航系统的要求也在不断提高。希望车载导航系统能够具备更高的定位精度、更丰富的地图信息、更便捷的操作体验以及更强的可扩展性。开发一款基于嵌入式技术的车载导航定位系统,以满足现代用户对高效、智能、个性化导航服务的需求,成为了当前行业发展的一个重要方向。本项目就是通过集成高性能的主控开发板、精准的GPS定位模块以及强大的Qt开发框架,实现一个功能丰富、性能稳定、用户体验优越的车载导航系统。【2】设计实现的功能(1)实时定位与地图显示:通过外接的北斗GPS模块,系统能够实时接收并解析卫星信号,获取车辆的精确位置信息。这些信息将实时显示在基于Qt开发的主界面上,与百度地图API无缝对接,为用户呈现清晰、准确的地图画面。(2)路线规划与导航:用户可以通过主界面输入目的地信息,系统根据百度地图API提供的路径规划服务,计算出最优的行驶路线,并在地图上进行高亮显示。在导航过程中,系统能够实时追踪车辆位置,提供转向、距离等导航指令,确保用户能够准确、快速地到达目的地。(3)地图预览与缩放:系统支持地图的缩放和拖动功能,用户可以根据需要调整地图的显示范围,查看不同级别的地理细节。同时,系统还提供了多种地图视图模式(如白天模式、夜间模式等),以满足用户在不同场景下的使用需求。(4)语音提示与交互:为了提升用户体验,系统集成了语音提示功能,能够在关键导航节点(如转弯、路口等)给予用户语音指令,减少用户操作干扰。此外,系统还支持通过语音指令进行简单的交互操作,如查询附近的餐饮、加油站等设施。(5)个性化设置与偏好管理:用户可以根据自己的使用习惯,在系统设置中调整界面风格、导航偏好等参数。系统还会记录用户的行驶历史,为用户提供个性化的推荐和服务。(6)系统稳定性与扩展性:基于嵌入式Linux系统的开发框架,保证了系统的稳定性和可靠性。同时,开放式的架构设计使得系统易于扩展和升级,能够随时集成新的功能模块和服务,满足用户不断增长的需求。本项目设计的基于嵌入式的车载导航定位系统,通过集成高性能硬件和先进的软件开发技术,实现了实时定位、路线规划、地图预览、语音提示、个性化设置等多项功能,为用户提供了高效、智能、个性化的导航服务体验。【3】项目硬件模块组成(1)主控开发板:采用GEC6818开发板,该开发板搭载了三星Cortex-A53系列高性能八核处理器S5P6818,最高主频高达1.4GHz。主控开发板作为整个系统的核心,负责处理导航定位系统的所有运算和控制任务,确保系统的稳定运行。(2)GPS模块:采用北斗GPS模块,该模块负责接收并解析卫星信号,获取车辆的精确位置信息。通过与主控开发板的连接,将位置数据实时传输给系统进行处理和显示。(3)显示屏:用于呈现地图、导航指令以及其他相关信息。显示屏与主控开发板相连,通过Qt开发的界面,将系统的各项功能直观地展示给用户。(4)网卡: 用于上网,调用百度地图,这是开发板本身自带。(5)语音播报模块: 利用开发板本身的声卡播放导航提示。1.2 设计思路(1)需求分析:对车载导航定位系统的需求进行深入分析。确定系统需要具备的功能,如实时定位、路线规划、地图显示、语音提示等。同时,考虑到用户的操作习惯和驾驶过程中的安全性,对界面的设计、交互的流畅性等方面也进行了充分考虑。(2)硬件选型:根据需求分析的结果,选择适合的硬件组件。主控开发板选用GEC6818开发板,其高性能的处理器和嵌入式Linux系统为系统的稳定运行提供了有力支持。GPS模块选用北斗GPS模块,以确保定位的准确性和稳定性。同时,选择高质量的显示屏和其他辅助模块,以满足系统的各项需求。(3)软件架构设计:采用Qt作为软件开发框架,利用其强大的图形界面开发能力和跨平台特性,实现系统的主界面和各项功能。通过集成百度地图API,实现地图的加载、显示和路径规划等功能。同时,设计合理的软件架构,确保各个模块之间的协同工作和数据传输的高效性。(4)功能模块划分:将系统划分为多个功能模块,如定位模块、导航模块、地图显示模块、语音提示模块等。每个模块负责实现特定的功能,并通过接口与其他模块进行交互。这种模块化的设计方式便于后期的维护和扩展。1.3 系统功能总结功能模块功能描述技术实现与特点实时定位通过北斗GPS模块获取车辆精确位置信息。利用北斗卫星导航系统,提供高精度、稳定的定位服务。地图显示在显示屏上呈现百度地图,展示地理信息。集成百度地图API,实现地图的加载、缩放、拖动等功能。路线规划根据用户输入的目的地,计算最优行驶路线。利用百度地图API的路径规划服务,提供多种路线选择。导航指引提供转向、距离等导航指令,辅助用户驾驶。实时追踪车辆位置,根据规划路线提供准确的导航指引。语音提示通过语音输出导航指令和其他相关信息。集成语音合成技术,实现人性化的交互体验。地图预览与缩放支持地图的预览、缩放和拖动操作。提供多种地图视图模式,满足不同场景下的使用需求。个性化设置用户可根据喜好设置系统界面和导航偏好。提供丰富的设置选项,满足用户的个性化需求。系统稳定性确保系统在各种环境下的稳定运行。基于嵌入式Linux系统开发,具备高度的稳定性和可靠性。扩展性系统设计易于扩展和升级,适应未来需求变化。开放的架构设计,支持新功能模块和服务的集成。1.4 原理图二、Linux下Qt开发环境搭建养老院出行管理系统项目是在Linux下开发,接下来需要搭建Linux下的开发环境。(1)第一步,安装VM虚拟机(2)第二步,在VM虚拟机里安装Ubuntu18.04系统(3)第三步,在Ubuntu18.04系统里安装QT开发环境2.1 安装VMware虚拟机软件VMware软件下载地址: cid:link_0当前电脑使用的vmware版本为: 15.52.2 安装Ubuntu18.04系统18.04最新长期支持版本: cid:link_12.3 安装Qt5.12开发环境注意,安装Qt之前要先安装以下工具(如果之前安装了就不Qt安装包下载地址:cid:link_22.4 Qt编译常见问题解决如果在编译运行程序时, 提示缺少 cannot find -lGL 库报错, 可以按照下面方法解决:在命令行执行: locate libGL.so //这一步是查看本地系统里有没有这个库/usr/lib/x86_64-linux-gnu/mesa/libGL.so.1 //如果提示这两行, 说明系统有这个库/usr/lib/x86_64-linux-gnu/mesa/libGL.so.1.2.0下面只需要做一个链接即可:sudo ln -s /usr/lib/x86_64-linux-gnu/mesa/libGL.so.1 /usr/lib/libGL.so如果系统里没有查找到库, 就在命令行敲下面命令进行在线安装:sudo apt-get install libgl1-mesa-dev三、代码设计3.1 地图API调用下面使用Qt的网络模块来发送HTTP请求,并使用Qt的GUI模块来显示地图图片。 需要在百度地图开放平台上注册应用程序,并获取到百度地图API密钥(AK)。// mainwindow.h#ifndef MAINWINDOW_H#define MAINWINDOW_H​#include <QMainWindow>#include <QNetworkAccessManager>#include <QNetworkRequest>#include <QNetworkReply>#include <QImage>#include <QLabel>​class MainWindow : public QMainWindow{ Q_OBJECT​public: MainWindow(QWidget *parent = nullptr); ~MainWindow();​private slots: void onMapImageReceived(QNetworkReply *reply);​private: QLabel *mapLabel; QNetworkAccessManager *networkManager;};​#endif // MAINWINDOW_HcppCopy Code// mainwindow.cpp#include "mainwindow.h"#include <QUrl>​MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent){ mapLabel = new QLabel(this); mapLabel->setGeometry(10, 10, 600, 400); // 设置地图图片显示位置和大小​ networkManager = new QNetworkAccessManager(this); connect(networkManager, &QNetworkAccessManager::finished, this, &MainWindow::onMapImageReceived);​ QString mapUrl = "http://api.map.baidu.com/staticimage/v2"; QUrl url(mapUrl); url.addQueryItem("ak", "your_baidu_map_api_key"); // 替换为你的百度地图API密钥 url.addQueryItem("center", "北京"); // 地图中心位置 url.addQueryItem("width", "600"); // 图片宽度 url.addQueryItem("height", "400"); // 图片高度 url.addQueryItem("zoom", "11"); // 缩放级别​ QNetworkRequest request(url); networkManager->get(request);}​MainWindow::~MainWindow(){}​void MainWindow::onMapImageReceived(QNetworkReply *reply){ if (reply->error() == QNetworkReply::NoError) { QByteArray imageData = reply->readAll(); QImage mapImage; mapImage.loadFromData(imageData); mapLabel->setPixmap(QPixmap::fromImage(mapImage)); } else { qDebug() << "Error: " << reply->errorString(); }​ reply->deleteLater();}创建了一个MainWindow类,其中包含一个用于显示地图图片的QLabel和一个QNetworkAccessManager用于发送HTTP请求。在构造函数中,通过QUrl构建了百度地图API接口的URL,并添加了必要的参数,例如地图中心位置、图片大小和缩放级别。使用QNetworkRequest发送了一个GET请求,并在onMapImageReceived槽函数中处理收到的地图图片数据,并将其显示在QLabel上。3.2 导航提示音播放使用alsa-lib库在Linux下调用声卡驱动来播放声音。#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <alsa/asoundlib.h>​#define BUFFER_SIZE 1024​int main(int argc, char *argv[]){ int err; int fd; snd_pcm_t *pcm_handle; snd_pcm_hw_params_t *hw_params; unsigned int rate = 44100; unsigned int channels = 2; unsigned int buffer_time = 500000; // 500ms unsigned int period_time = 100000; // 100ms snd_pcm_uframes_t buffer_size; snd_pcm_uframes_t period_size; char *buffer;​ buffer = (char *)malloc(BUFFER_SIZE); if (!buffer) { printf("Error: Failed to allocate memory.\n"); return -1; }​ // 打开PCM设备 err = snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if (err < 0) { printf("Error: Failed to open PCM device. %s\n", snd_strerror(err)); return -1; }​ // 配置PCM设备参数 snd_pcm_hw_params_alloca(&hw_params); err = snd_pcm_hw_params_any(pcm_handle, hw_params); if (err < 0) { printf("Error: Failed to get PCM device parameters. %s\n", snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_access(pcm_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { printf("Error: Failed to set PCM device access mode. %s\n", snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_format(pcm_handle, hw_params, SND_PCM_FORMAT_S16_LE); if (err < 0) { printf("Error: Failed to set PCM device sample format. %s\n", snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_channels(pcm_handle, hw_params, channels); if (err < 0) { printf("Error: Failed to set PCM device channel count. %s\n", snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_rate_near(pcm_handle, hw_params, &rate, 0); if (err < 0) { printf("Error: Failed to set PCM device sample rate. %s\n", snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_buffer_time_near(pcm_handle, hw_params, &buffer_time, 0); if (err < 0) { printf("Error: Failed to set PCM device buffer time. %s\n", snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_period_time_near(pcm_handle, hw_params, &period_time, 0); if (err < 0) { printf("Error: Failed to set PCM device period time. %s\n", snd_strerror(err)); return -1; } err = snd_pcm_hw_params(pcm_handle, hw_params); if (err < 0) { printf("Error: Failed to set PCM device parameters. %s\n", snd_strerror(err)); return -1; }​ // 获取PCM设备缓冲区大小和周期大小 err = snd_pcm_get_params(pcm_handle, &buffer_size, &period_size); if (err < 0) { printf("Error: Failed to get PCM device buffer and period sizes. %s\n", snd_strerror(err)); return -1; }​ // 打开音频文件 fd = open(argv[1], O_RDONLY); if (fd < 0) { printf("Error: Failed to open audio file.\n"); return -1; }​ // 播放音频 while (1) { long frames = read(fd, buffer, BUFFER_SIZE); if (frames == 0) { // 播放完成 break; } else if (frames < 0) { // 读取错误 printf("Error: Failed to read audio data.\n"); break; } while (frames > 0) { long n = snd_pcm_writei(pcm_handle, buffer, frames); if (n < 0) { // 发生错误,重新配置PCM设备 printf("Error: Failed to write audio data to PCM device. %s\n", snd_strerror(n)); snd_pcm_prepare(pcm_handle); } else { frames -= n; buffer += n * channels * 2; // 每个采样点为16位(2字节),乘以通道数 } } }​ // 关闭PCM设备和音频文件 snd_pcm_close(pcm_handle); close(fd); free(buffer);​ return 0;}使用alsa-lib库来调用Linux声卡驱动来播放声音。(1)打开PCM设备并配置参数,然后通过snd_pcm_get_params函数获取缓冲区大小和周期大小。(2)打开音频文件并循环读取文件中的数据,每次将一定数量的数据写入PCM设备进行播放。在播放过程中,如果发生错误们需要重新配置PCM设备并重新开始播放。3.3 GPS导航模块#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <errno.h>#include <libserialport.h>​void parse_gps_data(char *data) { char *token; token = strtok(data, ","); int count = 0; double latitude, longitude;​ while (token != NULL) { if (count == 2) { // 纬度数据在第3个字段 latitude = atof(token); } else if (count == 4) { // 经度数据在第5个字段 longitude = atof(token); }​ token = strtok(NULL, ","); count++; }​ printf("Latitude: %f, Longitude: %f\n", latitude, longitude);}​int main() { struct sp_port *port; int err;​ // 打开串口 err = sp_get_port_by_name("/dev/ttyUSB0", &port); if (err != SP_OK) { fprintf(stderr, "Error: Failed to open serial port\n"); return -1; }​ err = sp_open(port, SP_MODE_READ); if (err != SP_OK) { fprintf(stderr, "Error: Failed to open serial port for reading\n"); sp_free_port(port); return -1; }​ // 设置串口参数 struct sp_port_config *config; sp_new_config(&config); sp_set_config_baudrate(config, 9600); sp_set_config_bits(config, 8); sp_set_config_parity(config, SP_PARITY_NONE); sp_set_config_stopbits(config, 1); sp_set_config(port, config);​ // 读取GPS数据 char data[256]; int bytes_read; while (1) { bytes_read = sp_input_waiting(port); if (bytes_read > 0) { sp_blocking_read(port, data, sizeof(data), 0); parse_gps_data(data); } usleep(100000); // 延时100ms }​ // 关闭串口 sp_close(port); sp_free_port(port);​ return 0;}​四、总结随着智能化和移动互联网技术的飞速发展,车载导航定位系统已经成为现代驾驶不可或缺的一部分。本项目通过集成高性能的GEC6818开发板、北斗GPS模块以及百度地图API,成功设计并实现了一个功能全面、性能稳定的车载导航定位系统。在项目实施过程中,注重用户体验和系统稳定性,通过Qt开发框架打造了直观易用的操作界面,并实现了实时定位、地图显示、路线规划、导航指引以及语音提示等核心功能。同时,系统的模块化设计和开放式架构保证了其易于维护和扩展,能够随时适应市场和用户需求的变化。通过本项目的实施,不仅提升了车载导航系统的技术水平,也为用户提供了更加便捷、智能的出行体验。
  • [技术干货] 基于视觉识别的自动采摘机器人设计与实现
    一、前言1.1 项目介绍【1】项目功能介绍随着科技的进步和农业现代化的发展,农业生产效率与质量的提升成为重要的研究对象。其中,果蔬采摘环节在很大程度上影响着整个产业链的效益。传统的手工采摘方式不仅劳动强度大、效率低下,而且在劳动力成本逐渐上升的背景下,越来越难以满足大规模种植基地的需求。人工采摘还可能因不规范的操作导致果实损伤,影响商品果率。基于视觉识别技术的自动采摘机器人的研发,正是针对这一问题提出的创新解决方案。本项目采用树莓派4B作为主控芯片,因其具有强大的计算能力和丰富的扩展接口,可以方便地集成各种传感器和执行机构,实现对复杂环境下的实时图像采集与处理。项目利用百度飞浆(PaddlePaddle)深度学习框架中的目标检测和分类算法,通过安装在机器人上的高清摄像头获取果树图像,并进行实时分析,精准识别出果实的位置、大小以及成熟度等信息。当成功识别到目标果实后,主控系统将根据识别结果快速计算出机械手臂的最佳运动路径,控制其移动至指定位置,以最适宜的方式完成果实的高效、无损采摘。基于视觉识别的自动采摘机器人设计与实现项目旨在解决传统农业中人工采摘的瓶颈问题,通过人工智能与自动化技术的深度融合,提高果园管理的智能化水平,降低劳动成本,提高生产效率,从而推动我国乃至全球农业产业向更加智能、高效的现代农业转型。【2】设计实现的功能(1)视觉识别:借助高性能的摄像头和图像处理算法(本项目采用百度飞浆的目标识别和分类算法),机器人能够捕捉到果园中的果实图像,并准确地从中识别出目标果实。(2)定位与导航:在识别到果实后,系统会通过计算果实的空间坐标和距离,确定机械手臂需要到达的精确位置。同时,机器人会根据果园内的环境信息和路径规划算法,自动导航至目标果实附近。(3)机械手臂控制:一旦机器人到达目标位置,机械手臂会在系统的精确控制下,自动调整姿态和动作,以轻柔而准确的方式采摘果实。这一过程涉及到复杂的机械动力学和协同控制算法,确保采摘动作的高效和安全。(4)果实收集与处理:采摘下来的果实会被机器人收集到专门的容器中,以便后续的分拣、包装和处理。系统还可以对采摘的果实进行数量统计和质量评估,为农业生产提供有价值的数据支持。本项目实现的功能是一个完整的自动采摘机器人系统,从视觉识别到机械手臂控制,再到果实收集与处理,形成了一个高效、智能的自动化采摘流程。这不仅大大提高了农业生产的效率和质量,也展示了人工智能技术在现代农业领域的广阔应用前景。【3】项目硬件模块组成(1)主控板:采用树莓派4B开发板作为整个系统的主控芯片。树莓派是一款功能强大且易于使用的计算机主板,具备高性能的处理器、充足的内存和存储空间,以及丰富的接口和扩展功能,可以满足本项目对计算和控制的需求。(2)视觉系统:视觉系统包括高性能的摄像头和图像处理单元。摄像头负责捕捉果园中的图像信息,而图像处理单元则基于百度飞浆的目标识别和分类算法,对图像进行处理和分析,以识别和定位目标果实。(3)机械手臂:机械手臂是实现自动采摘的关键部件,由多个关节和执行器组成,可以在三维空间内自由移动和旋转。通过精确的控制算法,机械手臂能够准确地到达目标果实的位置,并执行采摘动作。(4)传感器和导航系统:为了实现自动导航和精确定位,项目中还集成了多种传感器和导航系统。这些传感器可以感知环境信息,如距离、方位、障碍物等,而导航系统则根据这些信息规划出机器人的最佳路径。(4)电源和供电系统:为了保证机器人的持续工作,项目中还包括了电源和供电系统。电源负责为各个硬件模块提供稳定的电力供应,而供电系统则可以根据实际需要调整电力输出,以满足机器人在不同工作状态下的能耗需求。本项目的硬件模块组成包括主控板、视觉系统、机械手臂、传感器和导航系统、电源和供电系统以及其他辅助模块。这些硬件模块相互协作,共同实现了基于视觉识别的自动采摘机器人系统的功能。【3】功能总结系统集成了先进的视觉识别技术、机械手臂控制技术以及自动导航技术,能够自动识别和定位果园中的目标果实,并通过机械手臂完成采摘动作。整个过程无需人工干预,实现了果园采摘的自动化和智能化。功能包括果实的自动识别和定位、机械手臂的自动导航和控制以及果实的自动收集和处理。通过高性能的摄像头和图像处理算法,系统能够准确捕捉和识别目标果实的图像信息;借助精确的导航和控制算法,机械手臂能够自动导航至果实位置并完成采摘;最后,采摘下来的果实会被自动收集并进行后续处理。本项目的功能实现不仅提高了果园采摘的效率和准确性,降低了人力成本,同时也为农业生产的现代化和智能化发展提供了新的解决方案和思路。该系统的成功应用将为农业生产带来革命性的变革,推动农业向更高效、更环保、更可持续的方向发展。1.2 设计思路(1)需求分析:对果园采摘的实际需求进行分析,明确项目需要解决的问题和达到的目标。了解果园的环境特点、果实类型和生长状况,以及采摘作业的流程和要求,为后续设计提供基础依据。(2)技术选型:根据需求分析的结果,选择合适的技术方案。选用树莓派4B开发板作为主控芯片,利用其高性能的处理器和丰富的接口资源,实现机器人的控制和管理。同时,采用百度飞浆的目标识别和分类算法,通过视觉系统实现对目标果实的准确识别和定位。(3)硬件设计:根据技术选型,设计机器人的硬件结构。包括摄像头的选型和布局,确保能够捕捉到清晰、稳定的图像信息;机械手臂的设计和选型,使其能够适应果园环境和采摘需求;导航和传感器系统的设计和选型,实现机器人的自动导航和精确定位。(4)软件设计:编写机器人的控制程序和算法。通过图像处理算法实现对目标果实的识别和定位,将结果传递给导航和控制系统;根据导航和传感器系统提供的信息,规划机器人的运动路径和动作,控制机械手臂完成采摘动作;实现果实的计数、分类和收集等功能,以及数据的存储和传输。(5)系统集成与测试:将各个硬件模块和软件程序进行集成,并进行系统测试和调试。确保各个模块之间的通信和协作正常,机器人能够准确识别和采摘目标果实,并实现自动导航和收集等功能。1.3 系统功能总结功能模块功能描述视觉识别- 通过高性能摄像头捕捉果园图像- 利用百度飞浆的目标识别和分类算法,识别目标果实- 确定果实的空间坐标和距离导航与定位- 根据果园环境信息和路径规划算法,自动导航至目标果实附近- 集成多种传感器,感知环境信息,如距离、方位、障碍物等机械手臂控制- 在系统精确控制下,自动调整姿态和动作,采摘果实- 确保采摘动作的高效和安全果实收集与处理- 采摘下来的果实被自动收集到专门容器中- 对采摘的果实进行数量统计和质量评估- 提供数据支持,为农业生产决策提供参考通信与监控- 实现远程监控和控制功能二、树莓派4B环境搭建【1】硬件环境介绍树莓派是什么?Raspberry Pi(中文名为“树莓派”,简写为RPi,或者RasPi/RPi)是为学生计算机编程教育而设计,只有信用卡大小的卡片式电脑,其系统基于Linux。【2】资料下载第一步,先将树莓派4B需要使用的资料下载下来。【3】准备需要的配件(1)准备一张至少32G的TFT卡,用来烧写系统。(2)准备一个读卡器,方便插入TFT卡,好方便插入到电脑上拷贝系统(3)树莓派主板一个(4)一根网线(方便插路由器上与树莓派连接)(5)一根type-C的电源线。用自己Android手机的数据线就行,拿手机充电器供电。【4】准备烧写系统(1)安装镜像烧写工具(2)格式化SD卡将TFT卡通过读卡器插入到电脑上,将TFT卡格式化。(3)烧写系统接下来准备烧写的系统是这一个系统:将系统解压出来。然后打开刚才安装好的镜像烧写工具,在软件中选择需要安装的 img(镜像)文件,“Device”下选择SD的盘符,然后选择“Write”,然后就开始安装系统了,根据你的SD速度,安装过程有快有慢。注意:从网盘下载下来的镜像如果没有解压就先解压,释放出img文件。下面是烧写的流程:点击YES,开始烧写。烧写过程中:安装结束后会弹出完成对话框,说明安装就完成了,如果不成功,需要关闭防火墙一类的软件,重新插入SD进行安装。需要注意的是,安装完,windows系统下看到SD只有74MB了,这是正常现象,因为linux下的磁盘分区win下是看不到的。 烧录成功后windows系统可能会因为无法识别分区而提示格式化分区,此时千万不要格式化!不要格式化!不要格式化!点击取消,然后弹出内存卡,插入到树莓派上。至此,树莓派烧写成功。【5】启动系统(1)树莓派供电由于我买的树莓派开发板不带电源线,就采用Android手机的充电线供电。 使用Type-C供电时,要求电源头的参数要求,电压是5V,电流是3A。我的充电器是小米的120W有线快充,刚好满足要求。(2)启动树莓派(以Type-C供电示例)烧写完后把MicroSD卡直接插入树莓派的MicroSD卡插槽,如果有显示器就连接显示器,有DHMI线机也可以连接外接的显示器,有鼠标键盘都可以插上去,就可以进入树莓派系统了。但是,我这块板子就一个主板,什么都没有。就拿网线将树莓派的网口与路由器连接。上电之后,开发板的指示灯会闪烁,说明已经启动。(3)查看开发板的IP地址现在板子没屏幕,想要连接板子,只能通过SSH远程登录的方式,当前烧写的这个系统默认开机就启动了SSH,所以只要知道开发板的IP地址就可以远程登录进去。如何知道树莓派板子的IP地址?方法很多,最简单是直接登录路由器的后台界面查看连接进入的设备。我使用的小米路由器,登录后台,看到了树莓派的IP地址。(4)SSH方式登录开发板当前烧写系统的登录账号和密码如下:账号:pi 密码:yahboom打开SSH远程登录工具:PuTTY_0.67.0.0.exe。输入IP地址和端口号,点击open。然后输入账号和密码。输入用户名 pi按下回车,然后再输入密码 yahboom。 注意:Linux下为了保护隐私,输入密码是不可见的,你只需要正常输入,按下回车键确定 即可。正常情况下,就登录成功了。接下来看看联网情况。 ping一下百度测试互联网是否畅通,因为接下来要在线安装软件包。ping www.baidu.com可以看到网络没有问题。提示: 按下 Ctrl + C 可以终止命令行。 这算是Linux基础。【6】windows远程登录桌面为了方便图形化方式开发,可以使用windows系统通过远程桌面登录树莓派,就可以看到界面了,不过需要先安装工具。(1)安装xdrp在树莓派的命令行终端输入命令:sudo apt-get install xrdp按下回车之后,会弹出确认窗口。输入 y之后,按下回车,继续安装。(2)打开windows远程桌面在windows电脑上打开运行命令的窗口,输入mstsc来打开远程桌面。打开远程桌面的窗口:(3)连接树莓派远程桌面打开远程桌面后,输入树莓派开发板的IP地址,点击连接。如果弹出窗口,就选择是。接下来就进入到树莓派开发板的远程桌面的登录窗口了。接下来输入面账号和密码。账号:pi 密码:yahboom输入后点击OK按钮登录。正常情况下,就顺利的进入树莓派的桌面了。接下来就可以进行远程桌面开发了。【7】扩展树莓派SD卡可用空间树莓派系统默认启动时,树莓派默认没有把整个存储空间拓展到整张卡中,如果需要使用整个SD卡,这时候可以通过人为的把存储空间拓展到整张卡上。(1)查看内存使用情况打开命令行终端,输入df -h 命令。(2)扩展内存<1> 打开树莓派命令行终端输入:pi@raspberrypi:~ $ sudo raspi-config<2> 在弹出的命令行里选择Advanced Options<3> 选择第一个选项。<4> 点击确定<5> 点击右边的Finish按钮保存退出。确定之后,关闭界面,系统会自动重启,重启之后,使用df命令查看是否扩展成功(我这里插的是32G的SD卡)。可以看到,我的系统已经扩展成功了,目前可以内存空间是19G。【8】树莓派连接WIFI(1)配置需要连接的WIFI点击右上角的数据连接图标,打开WIFI列表,点击想要的WIFI进行连接。(2)通过WIFI的IP地址登录远程桌面在路由器的后台可以看到,目前树莓派连入了两个IP地址。接下来把网线拔掉,使用WIFI无线也可以直接连接无线桌面,这样就不用插网线了。账号和密码:账号:pi 密码:yahboom三、代码设计3.1 舵机控制代码(机械手臂控制)C语言代码: 使用wiringPi库控制树莓派上的GPIO引脚,实现对舵机的控制。通过servo_rotate()函数可以控制舵机旋转到指定的角度。在main()函数中,使用键盘输入获取目标角度,并调用servo_rotate()函数控制舵机旋转到目标角度。舵机的控制方式为PWM脉冲宽度调制,即将角度转换为脉宽值并输出对应的高低电平信号。将舵机信号线连接到GPIO18引脚,通过digitalWrite()函数输出高低电平来控制舵机旋转。#include <wiringPi.h>#include <stdio.h>​#define SERVO_PIN 18 // SG90舵机信号线连接的GPIO引脚​void servo_rotate(int angle) { int pulse_width = (angle * 11) + 500; // 将角度转换为脉宽值 digitalWrite(SERVO_PIN, HIGH); // 输出高电平 delayMicroseconds(pulse_width); // 延时脉宽值对应的时间 digitalWrite(SERVO_PIN, LOW); // 输出低电平 delay(20 - pulse_width / 1000); // 延时剩余时间}​int main(void) { wiringPiSetupGpio(); // 初始化wiringPi库 pinMode(SERVO_PIN, OUTPUT); // 将舵机信号线接口设为输出模式​ while(1) { // 从键盘输入目标角度 printf("Enter the angle to rotate (0-180): "); fflush(stdout); int angle; scanf("%d", &angle);​ // 旋转到目标角度 if(angle >= 0 && angle <= 180) { servo_rotate(angle); } else { printf("Invalid angle! Please enter an angle between 0 and 180.\n"); } }​ return 0;}Pyhon代码: 使用RPi.GPIO库来控制树莓派上的GPIO引脚,实现对舵机的控制。通过setup()函数进行初始化设置,并通过set_angle()函数控制舵机旋转到指定的角度。在main()函数中,使用键盘输入获取目标角度,并调用set_angle()函数控制舵机旋转到目标角度。import RPi.GPIO as GPIOimport time​SERVO_PIN = 18 # SG90舵机信号线连接的GPIO引脚​def setup(): GPIO.setmode(GPIO.BCM) GPIO.setup(SERVO_PIN, GPIO.OUT) global servo_pwm servo_pwm = GPIO.PWM(SERVO_PIN, 50) # 创建PWM对象,频率设置为50Hz servo_pwm.start(0) # 启动PWM输出,初始占空比设为0​def set_angle(angle): duty_cycle = (angle / 18) + 2.5 # 将角度转换为占空比值 servo_pwm.ChangeDutyCycle(duty_cycle) time.sleep(0.3) # 等待舵机转到指定角度​def main(): setup()​ while True: # 从键盘输入目标角度 angle = int(input("Enter the angle to rotate (0-180): "))​ # 旋转到目标角度 if 0 <= angle <= 180: set_angle(angle) else: print("Invalid angle! Please enter an angle between 0 and 180.")​if __name__ == '__main__': try: main() finally: servo_pwm.stop() # 停止PWM输出 GPIO.cleanup() # 清理GPIO资源3.2 调用算法识别目标(1)安装PaddlePaddle和PaddleDetection库:先安装Python和pip。然后,打开终端并执行以下命令安装PaddlePaddle和PaddleDetection库:pip install paddlepaddle paddlepaddle-gpupip install paddlehubpip install paddlehub -i https://pypi.tuna.tsinghua.edu.cn/simple(2)下载预训练模型:百度飞桨提供了预训练的目标检测模型,可以从PaddleDetection的GitHub页面下载这些模型。选择适合的任务的模型,并将其解压到合适的目录中。(3)编写调用代码:创建一个Python脚本文件,例如detect_fruits.py,并使用以下代码编写脚本:import paddlehub as hubimport cv2def detect_fruits(image_path, model_path): # 加载模型 module = hub.Module(name='yolov3_mobilenet_v1_coco2017') input_dict = {'image': [image_path]} # 目标检测 results = module.object_detection(data=input_dict) # 处理结果 for result in results: if len(result['data']) > 0: for obj in result['data']: label = obj['label'] confidence = obj['confidence'] left, top, right, bottom = obj['left'], obj['top'], obj['right'], obj['bottom'] print(f"Label: {label}, Confidence: {confidence:.2f}") print(f"Bounding Box: ({left}, {top}), ({right}, {bottom})") # 可视化结果 img = cv2.imread(image_path) for result in results: module.visualize(data=result, output_dir='output', score_thresh=0.5, use_visualize=True, visualization=True, plot_bbox=True, save_bbox_txt=True, image=img)if __name__ == '__main__': image_path = 'path/to/your/image.jpg' # 替换为你的图片路径 model_path = 'path/to/your/model' # 替换为你的模型路径 detect_fruits(image_path, model_path)在上面的代码中,使用PaddleHub库加载了预训练的yolov3_mobilenet_v1_coco2017模型,并将其应用于指定的图像。然后,处理检测结果并进行输出。最后,使用OpenCV库可视化结果并保存到指定目录中。(4)运行脚本:将目标果实图像放置在与脚本相同的目录下(或根据需要修改图像路径)。然后,在终端中执行以下命令运行脚本:python detect_fruits.py脚本将分析图像并输出检测到的目标果实的标签、置信度和边界框。会生成一个带有目标果实标注的图像。3.3 机器人小车控制代码小车的电机驱动采用L298N模块,连接在GPIO17、GPIO18、GPIO27和GPIO22上。 使用了wiringPi库来控制树莓派上的GPIO引脚,实现对小车电机驱动的控制。通过setup()函数进行初始化设置,并通过forward()、backward()、turn_left()和turn_right()函数控制小车前进、后退和转弯。其中,stop()函数用于停止小车运动。#include <wiringPi.h>#define MOTOR_ENA_PIN 0 // L298N模块ENA引脚连接的GPIO引脚#define MOTOR_ENB_PIN 2 // L298N模块ENB引脚连接的GPIO引脚#define MOTOR_IN1_PIN 3 // L298N模块IN1引脚连接的GPIO引脚#define MOTOR_IN2_PIN 4 // L298N模块IN2引脚连接的GPIO引脚#define MOTOR_IN3_PIN 5 // L298N模块IN3引脚连接的GPIO引脚#define MOTOR_IN4_PIN 6 // L298N模块IN4引脚连接的GPIO引脚void setup() { wiringPiSetup(); // 初始化wiringPi库 pinMode(MOTOR_ENA_PIN, OUTPUT); pinMode(MOTOR_ENB_PIN, OUTPUT); pinMode(MOTOR_IN1_PIN, OUTPUT); pinMode(MOTOR_IN2_PIN, OUTPUT); pinMode(MOTOR_IN3_PIN, OUTPUT); pinMode(MOTOR_IN4_PIN, OUTPUT);}void forward() { digitalWrite(MOTOR_IN1_PIN, HIGH); digitalWrite(MOTOR_IN2_PIN, LOW); digitalWrite(MOTOR_IN3_PIN, LOW); digitalWrite(MOTOR_IN4_PIN, HIGH); digitalWrite(MOTOR_ENA_PIN, HIGH); digitalWrite(MOTOR_ENB_PIN, HIGH);}void backward() { digitalWrite(MOTOR_IN1_PIN, LOW); digitalWrite(MOTOR_IN2_PIN, HIGH); digitalWrite(MOTOR_IN3_PIN, HIGH); digitalWrite(MOTOR_IN4_PIN, LOW); digitalWrite(MOTOR_ENA_PIN, HIGH); digitalWrite(MOTOR_ENB_PIN, HIGH);}void turn_left() { digitalWrite(MOTOR_IN1_PIN, LOW); digitalWrite(MOTOR_IN2_PIN, HIGH); digitalWrite(MOTOR_IN3_PIN, LOW); digitalWrite(MOTOR_IN4_PIN, HIGH); digitalWrite(MOTOR_ENA_PIN, HIGH); digitalWrite(MOTOR_ENB_PIN, HIGH);}void turn_right() { digitalWrite(MOTOR_IN1_PIN, HIGH); digitalWrite(MOTOR_IN2_PIN, LOW); digitalWrite(MOTOR_IN3_PIN, HIGH); digitalWrite(MOTOR_IN4_PIN, LOW); digitalWrite(MOTOR_ENA_PIN, HIGH); digitalWrite(MOTOR_ENB_PIN, HIGH);}void stop() { digitalWrite(MOTOR_ENA_PIN, LOW); digitalWrite(MOTOR_ENB_PIN, LOW);}int main() { setup(); while (1) { // 从键盘输入指令 char cmd = getchar(); getchar(); // 忽略回车符 // 根据指令执行动作 switch (cmd) { case 'w': // 前进 forward(); break; case 's': // 后退 backward(); break; case 'a': // 左转 turn_left(); break; case 'd': // 右转 turn_right(); break; case 'x': // 停止 stop(); break; default: break; } } return 0;}四、总结随着农业技术的不断进步,自动化、智能化已成为现代农业生产的重要趋势。本项目通过结合视觉识别技术、机器人技术和自动化控制技术,成功设计并实现了基于视觉识别的自动采摘机器人系统。这一创新性的成果不仅提高了果园采摘的效率和准确性,降低了人力成本,还为农业生产的现代化和智能化发展提供了新的解决方案和思路。
  • [技术干货] 基于STM32的儿童智能安全防护书包设计
    一、前言1.1 项目介绍【1】项目功能介绍随着社会的进步和科技的发展,儿童安全问题日益引起广泛关注。在日常生活中,尤其是在上学放学途中、户外活动时,儿童走失事件时有发生,给家庭和社会带来了极大的困扰和担忧。随着学业负担的增加,学生时常会因为忘记携带所需书籍而影响学习。如何利用现代技术手段提高儿童安全保障水平,并辅助他们培养良好的学习习惯,成为了一个待解决的社会需求。基于此背景,当前设计并实现一款基于STM32F103RCT6微控制器为核心的儿童智能安全防护书包,显得尤为必要与实际。这款书包集成了先进的定位技术和无线通信模块,能够实时追踪并发送儿童的位置信息给家长,确保在紧急情况下快速响应 (发送短信的时候,直接通过GPS经纬度拼接百度地图的HTTP请求链接,家长收到短信可以直接打开链接,在网页查看百度地图上显示的具体位置,可以直接通过百度地图导航过去)。同时,具备智能化功能,如课程表录入存储与提醒系统,利用EEPROM(例如AT24C02)进行数据持久化存储,并通过RFID-RC522射频识别模块自动检测所携带书籍是否齐全,避免孩子因疏忽遗漏课本而耽误学习。智能书包还配备了直观易读的1.44寸LCD显示屏,用于显示当前位置信息、当日课表以及未带书籍的提醒。当检测到缺少某本书籍时,蜂鸣器模块会发出声音警报,从而强化提醒效果,帮助学生养成有序整理个人物品的习惯。这款基于STM32的儿童智能安全防护书包是一个集成物联网技术、GPS定位、无线通信和智能感知于一体的创新产品,提升儿童的安全防护等级,加强家校互动,促进学生自我管理能力的培养,充分体现了科技服务于生活、服务于教育的理念。【2】设计实现的功能(1)实时定位与紧急求助功能:通过集成GPS模块,该智能书包能够实时获取并更新儿童的位置信息,并通过无线通信(GSM短信模块如Air724UG 4G)将位置数据发送给家长。当儿童在陌生环境中迷路或者遇到紧急情况时,只需按下求救按钮,系统立即向预设的家长手机发送包含当前位置信息的短信,方便家长迅速找到孩子。(2)课程表管理与提醒功能:设计有课程表录入存储模块,利用EEPROM芯片AT24C02进行非易失性数据存储,家长或学生可以预先将每日课程表输入到系统中。每天早上,书包会根据存储的课程表自动检查当天所需的书籍是否已放入书包内。通过射频识别RFID-RC522模块读取贴在书籍上的标签信息,若发现缺少某科书籍,则蜂鸣器会发出声音警报,同时LCD显示屏也会显示相应的提示信息,确保学生不会忘记携带必要的学习资料。(3)可视化信息展示:配备了1.44寸LCD显示屏,可实时显示当前地理位置信息、时间以及当日的课程表内容,使得学生和家长可以直观地查看重要信息。这款基于STM32的儿童智能安全防护书包实现了儿童安全监护和学业辅助两大核心功能,既有助于保障孩子的安全出行,又能培养他们的自我管理和规划能力,体现了科技产品在教育领域的深度应用价值。【3】项目硬件模块组成(1)主控芯片:STM32F103RCT6微控制器作为整个系统的“大脑”,负责控制和协调各个功能模块的运作,处理GPS定位数据、GSM短信通信、RFID识别信息等,并通过程序逻辑实现课程表管理、提醒以及数据显示等功能。(2)定位模块:GPS模块,用于实时获取并更新儿童所在位置信息,确保家长可以随时查看孩子的位置状态。(3)无线通信模块:Air724UG 4G GSM短信模块,提供远程通信能力,当发生紧急情况时,儿童可通过书包上的求救按钮触发发送带有位置信息的短信至预设的家长手机。(4)存储模块:AT24C02 EEPROM芯片,用作非易失性存储器,存储孩子的课程表信息,即使在断电情况下也能保存数据不丢失。(5)射频识别模块:RFID-RC522模块,配合贴在书籍上的RFID标签,检测书包内是否携带齐全当日所需的书籍资料,如果发现缺少书籍,会触发报警提示。(6)报警提示模块:高电平触发的蜂鸣器模块,在检测到未带书籍或其它异常情况时,通过发出声音警报来提醒学生。(7)显示模块:采用1.44寸LCD显示屏,实时展示当前位置、时间、当天课表及未带书籍等重要信息,方便用户直观了解当前状况。【3】功能总结基于STM32的儿童智能安全防护书包设计(1)定位模块:定位模块实时获取儿童位置信息,能够家长在放学时找到儿童位置,或者丢失时及时查找儿童的位置。 (2)GSM短信模块:儿童如果意识到自己走丢,就可以按下求救按钮发送位置短信给家长,进而使家长尽快找到儿童位置 (3)课程表录入存储模块:将每天的课程表录入系统,以便提醒学生第二天要带什么书籍。(eeprom) (4)射频识别模块:将每一科的书籍贴上标签再与系统中的课表进行对比,如果检测到当天某一科书本没有带,蜂鸣器会响,呼吸灯会亮。(RFID) (5)显示模块:LCD屏显示实时位置课表信息以及提示没有带的书籍。硬件选型:(1)主控芯片采用STM32F103RCT6(2)定位模块采用: GPS模块(3)短信发送模块采用 Air724UG 4G(4)存储模块采用AT24C02(5)射频识别模块采用RFID-RC522(6)报警提示采用高电平触发的蜂鸣器模块(7)显示屏采用1.44寸LCD显示屏1.2 设计思路(1)需求分析阶段:对目标用户群体(儿童与家长)的需求进行深入研究和理解,确定主要功能点:儿童安全定位、紧急求助、课程表管理与提醒、书籍携带检测等。(2)系统架构设计:根据需求,选择STM32F103RCT6作为主控芯片,因其具有强大的处理能力、丰富的外设接口及低功耗特性,能够满足项目所需的复杂计算任务和多模块协调工作。(3)功能模块划分:定位模块设计采用GPS接收器,实时获取并解析位置信息。无线通信模块选用4G GSM短信模块Air724UG,实现实时位置信息的远程发送和接收紧急求助信号。数据存储模块使用EEPROM AT24C02,确保课程表数据的安全可靠存储。为实现书籍携带检测,利用RFID-RC522射频识别模块,结合预置在书籍上的RFID标签,自动识别书包内书籍是否齐全。报警提示模块通过高电平触发的蜂鸣器来发出声音警告,提醒学生遗漏书籍。显示模块配备1.44寸LCD显示屏,直观展示位置信息、课程表以及未带书籍的提醒。(4)软硬件协同设计:硬件方面,合理布局各模块,优化电源管理,确保设备稳定运行;软件方面,编写高效的嵌入式程序,实现对各个硬件模块的控制和交互,包括GPS数据解析、GSM通信协议栈开发、RFID读取与比对算法、数据显示逻辑等。(5)人机交互设计:设计简洁易用的界面和操作流程,如一键求救按钮、清晰的课程表显示、直观的报警提示等,便于儿童和家长快速理解和操作。1.3 系统功能总结功能模块功能描述定位模块(GPS)实时获取并更新儿童地理位置信息,通过无线通信模块发送至家长设备,以便家长随时掌握孩子位置动态。短信通信模块(GSM)儿童在紧急情况下按下求救按钮,系统通过4G GSM模块向预设的家长手机号码发送包含定位信息的短信进行求助。课程表管理模块(EEPROM)学生或家长可以录入每日课程表至系统中,利用AT24C02 EEPROM芯片存储数据,确保断电后仍能保留课程信息。书籍检测模块(RFID)通过RFID-RC522射频识别模块读取书本上的标签信息,自动比对与当日课表要求的书籍是否齐全,如有遗漏则触发报警提示。报警提示模块(蜂鸣器)当检测到学生未携带某科书籍或发生其他异常情况时,高电平触发的蜂鸣器会发出声音警告提醒学生。显示模块(LCD显示屏)配备1.44寸LCD显示屏实时显示当前位置、时间、当天课程表以及未带书籍的提示信息,方便学生查看和确认。1.4 开发工具的选择STM32的编程语言选择C语言,C语言执行效率高,大学里主学的C语言,C语言编译出来的可执行文件最接近于机器码,汇编语言执行效率最高,但是汇编的移植性比较差,目前在一些操作系统内核里还有一些低配的单片机使用的较多,平常的单片机编程还是以C语言为主。C语言的执行效率仅次于汇编,语法理解简单、代码通用性强,也支持跨平台,在嵌入式底层、单片机编程里用的非常多,当前的设计就是采用C语言开发。开发工具选择Keil,keil是一家世界领先的嵌入式微控制器软件开发商,在2015年,keil被ARM公司收购。因为当前芯片选择的是STM32F103系列,STMF103是属于ARM公司的芯片构架、Cortex-M3内核系列的芯片,所以使用Kile来开发STM32是有先天优势的,而keil在各大高校使用的也非常多,很多教科书里都是以keil来教学,开发51单片机、STM32单片机等等。目前作为MCU芯片开发的软件也不只是keil一家独大,IAR在MCU微处理器开发领域里也使用的非常多,IAR扩展性更强,也支持STM32开发,也支持其他芯片,比如:CC2530,51单片机的开发。从软件的使用上来讲,IAR比keil更加简洁,功能相对少一些。如果之前使用过keil,而且使用频率较多,已经习惯再使用IAR是有点不适应界面的。二、代码设计2.1 GPS解析代码基于STM32 HAL库进行GPS NMEA协议数据解析的代码#include "stm32f1xx_hal.h"#include <string.h>#include <stdio.h>​// GPS 数据结构体定义typedef struct { char GPGGA[100]; // 用于存储GPGGA语句 double latitude; // 纬度 double longitude; // 经度 float UTC_time[7]; // UTC时间 int fix_quality; // 定位质量 float hdop; // 水平精度因子} GPS_Data_TypeDef;​// 全局变量声明GPS_Data_TypeDef GPS_Data;​// 串口接收缓冲区uint8_t RxBuffer[256];​// GPS NMEA数据处理函数void ProcessGPSData(void) { static uint8_t index = 0; // 从串口接收到的数据中查找特定的NMEA语句,例如GPGGA if (strstr((char*)RxBuffer, "$GPGGA")) { // 分割NMEA语句获取所需字段 char *token; token = strtok((char*)RxBuffer, ","); while(token != NULL) { // 解析各字段 if (/* 判断当前token是否为纬度 */) { GPS_Data.latitude = atof(token); // 考虑南北纬转换及格式化 } else if (/* 判断当前token是否为经度 */) { GPS_Data.longitude = atof(token); // 考虑东西经转换及格式化 } else if (/* 判断当前token是否为UTC时间 */) { // 处理时间信息 } token = strtok(NULL, ","); }​ // 清空接收缓冲区以便下次接收新的数据 memset(RxBuffer, 0, sizeof(RxBuffer)); index = 0; }}​// 串口中断服务函数void USART1_IRQHandler(void) { static uint8_t UART_Rx_STA = 0; uint8_t temp=0;​ if ((__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET) && (__HAL_UART_GET_IT_SOURCE(&huart1, UART_IT_RXNE) != RESET)) { temp = huart1.Instance->RDR & 0xff; // 读取接收到的数据​ // 将接收到的数据添加到缓冲区,并检查是否有完整的NMEA句子结束符'\r\n' if (temp == '\n') { // 根据实际使用情况可能需要同时检测'\r'和'\n' RxBuffer[index++] = temp; // 添加换行符 RxBuffer[index] = '\0'; // 字符串结束符 ProcessGPSData(); // 调用解析函数 } else if (index < (sizeof(RxBuffer)-1)) { RxBuffer[index++] = temp; } }}​int main(void) { // 初始化系统时钟和USART1 MX_GPIO_Init(); MX_USART1_UART_Init();​ // 开启串口中断 __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);​ while (1) { // 主循环 // ... }}2.2 AT24C02存储代码#include "stm32f1xx_hal.h"#include "stm32f1xx_hal_i2c.h"​#define EEPROM_ADDRESS 0xA0 // AT24C02的I2C地址​I2C_HandleTypeDef hi2c1;​void SystemClock_Config(void);​void I2C_Init() { hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 100000; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; HAL_I2C_Init(&hi2c1);}​void EEPROM_Write(uint16_t addr, uint8_t data) { HAL_I2C_Mem_Write(&hi2c1, EEPROM_ADDRESS, addr, I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY);}​uint8_t EEPROM_Read(uint16_t addr) { uint8_t data; HAL_I2C_Mem_Read(&hi2c1, EEPROM_ADDRESS, addr, I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY); return data;}​int main(void) { HAL_Init(); SystemClock_Config(); I2C_Init();​ uint16_t address = 0x00; uint8_t data_to_write = 0x55; uint8_t data_read;​ // 写入数据到EEPROM EEPROM_Write(address, data_to_write);​ // 从EEPROM读取数据 data_read = EEPROM_Read(address);​ // 检查读取的数据 if (data_read == data_to_write) { // 读取成功 } else { // 读取失败 }​ while (1) { }}2.3 RFID-RC522代码STM32与RFID-RC522的交互涉及到很多步骤,包括初始化RFID模块、检测卡片、读取卡片信息、以及将这些信息存储起来。#include "stm32f10x.h" #include "SPI.h" #include "RFID.h" #include "usart.h" // 如果你使用了串口打印,可以包含这个头文件 #define SS_PIN PA4 // 根据你的连接修改这个引脚 #define RST_PIN PA3 // RFID模块的复位引脚 RFID rfid(SS_PIN, RST_PIN); // 创建RFID对象 uint8_t uid[5]; // 用于存储卡片的UID int main(void) { SystemInit(); // 初始化系统 usart_init(115200); // 初始化串口,用于调试 SPI_Init(); // 初始化SPI接口 rfid.PCD_Init(); // 初始化RFID模块 while (1) { if (rfid.PICC_IsNewCardPresent()) // 检测是否有新卡片 { rfid.PICC_ReadCardSerial(); // 读取卡片UID for (uint8_t i = 0; i < rfid.uid.size; i++) // 将UID存储到uid数组中 { uid[i] = rfid.uid.uidByte[i]; } // 可以在这里添加代码将uid存储到EEPROM、Flash或其他存储介质中 // 也可以通过串口打印UID进行调试 printf("Card UID: "); for (uint8_t i = 0; i < rfid.uid.size; i++) { printf("%02X ", uid[i]); } printf("\r\n"); } HAL_Delay(100); // 延时一段时间,避免过度占用CPU } }2.4 Air724UG 4G代码使用STM32的HAL库和USART外设(串口)与Air724UG 4G模块进行通信。通过UART_SendString()函数可以发送字符串到串口,通过GSM_SendCommand()函数可以向4G模块发送AT指令。在main()函数中,设置短信格式为文本模式,设置短信接收方号码,发送短信内容。#include "stm32f1xx_hal.h"#include <string.h>​UART_HandleTypeDef huart1;​void SystemClock_Config(void);static void MX_GPIO_Init(void);static void MX_USART1_UART_Init(void);​void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { // UART发送完成回调函数}​void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { // UART接收完成回调函数}​void UART_SendString(const char *str) { HAL_UART_Transmit(&huart1, (uint8_t*)str, strlen(str), HAL_MAX_DELAY);}​void GSM_SendCommand(const char *cmd) { UART_SendString(cmd); UART_SendString("\r\n"); HAL_Delay(100); // 等待响应}​int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init();​ char phone_number[] = "13800138000"; char message[] = "Hello, this is a test message from STM32!";​ // 初始化Air724UG 4G模块 GSM_SendCommand("AT+CMGF=1"); // 设置短信格式为文本模式 GSM_SendCommand("AT+CMGS=\"+86"); // 设置短信接收方号码 GSM_SendCommand(phone_number); GSM_SendCommand("\"");​ // 发送短信内容 GSM_SendCommand(message); HAL_UART_Transmit(&huart1, (uint8_t)26, 1, HAL_MAX_DELAY); // 发送Ctrl+Z结束符​ while (1) { }}​void SystemClock_Config(void) { // 系统时钟配置}​static void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 9600; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; HAL_UART_Init(&huart1);}​三、总结基于STM32的儿童智能安全防护书包设计通过先进的技术手段,为儿童的安全提供全方位的保障。本项目融合了GPS定位、GSM短信通信、EEPROM存储、RFID射频识别以及LCD显示等多项功能,力求在儿童的日常生活和学习中提供便捷与安全。通过GPS模块,书包能够实时追踪儿童的位置,让家长随时了解孩子的行踪,确保在关键时刻能够迅速找到孩子。而GSM短信模块则为儿童提供了一个紧急求助的途径,一旦孩子意识到自己走丢或有其他紧急情况,只需按下求救按钮,即可将位置信息以短信的形式发送给家长,从而迅速获得帮助。在学习方面,本项目通过EEPROM存储模块实现了课程表的录入与存储功能。儿童或家长可以将每天的课程表录入系统,书包便会在需要时提醒孩子携带相应的书籍。而RFID射频识别模块则负责检测书包内是否已携带当天所需的各科书本。如果检测到某一科书本缺失,书包上的蜂鸣器会发出警报声,呼吸灯也会亮起,以提醒孩子及时补充。此外,本项目还采用了一块1.44寸的LCD显示屏,用于实时显示儿童的位置信息、课表内容以及未携带书籍的提示信息。这使得儿童在使用书包的过程中能够随时了解自己的位置和当天的学习任务,为他们的安全和学习提供了双重保障。
  • [问题求助] 物联网传感器在环境监测中的应用面临哪些挑战?如何解决这些问题?
    从智慧城市的角度来说,城市的环境监测系统,传感器被部署在多个监测点,收集空气质量、噪音、水质等数据.   这些设计过程会有什么实际的技术 挑战,和不确定因素?
  • [问题求助] 在工业物联网中,传感器数据如何帮助优化生产流程?
    在工业物联网中,传感器如何收集生产线上的数据,并通过数据分析为生产流程优化提供支持的?   如何优化提高生产效率、降低能耗和减少故障率。
  • [问题求助] 物联网传感器在农业领域的应用中,如何帮助实现精准农业?
    物联网传感器在农业领域的应用中,如何帮助实现精准农业?  有没有什么建议。 传感器的寿命很大问题。
  • [问题求助] POSTMAN无法获得设备影子数据
    请教各位大佬。新注册了华为云,现在好像只能是标准版了。能正确通过POSTMAN得到token。如下图。建好模型,定义好插件,建立虚拟设备,可以上报数据,在设备里也能看到上报的数据。但是用postman去访问设备影子数据却始终无法得到。但是同样的方法,我之前另一个账号使用基础版,是没有问题的。下图是我另一个账号,使用基础版,用postman得到的数据。是现在的标准版里还需要做什么其他的设置吗?求各位大佬指教。。。。
  • [问题求助] 新手,学习Iot物联网,需要会开发,需要买小熊派开发套件吗?
    本人是搞运维的,对开发语言不是怎么懂。shell脚本倒是会些。新手学习Iot物联网 HCIA,HCIP的内容, 需要会开发语言 JAVA,Python 吗,需要买小熊派开发套件吗?全套的小熊派,价格可不便宜呀。老手指导下学习过程与经验。
  • [问题求助] 传感器走modbus的可以接入吗
    传感器走modbus的可以接入吗
  • [问题求助] 关于mqtt协议传输数据的问题
    问题是这样:就是我需要用stm32+4g模块向华为云端传输传感器的数据(用的是lpuart,波特率最高是9600),我想让这个数据实时显示在华为云界面的ui上或者说传输延时在1s以内。但现在的问题是通过stm32向4g模块发送AT指令时,有两条指令得间隔1s左右才能发送,这样就导致传输的效率非常慢,所以想问一下各位大佬能不能用https协议传这些数呢,或者说有没有其他可以提高传输效率的方法呢?
  • [问题求助] 小熊派支持标准库开发吗
    小熊派支持标准库开发吗
  • [IoT类] Iot设备接入的C# SDK的操作有问题,无法上传设备模型
    按照GitHub - huaweicloud/huaweicloud-iot-device-sdk-csharp的说明进行操作,创建设备的时候遇到问题,无法下载文档中给出的设备模型。
  • [问题求助] 如何制作APP
    数据上传到iot平台,怎么根据这些数据制作APP啊
  • [问题求助] iot数据转存至OBS存储,数据上传成功了,但是csv文件里面没有数据怎么解决啊?
    结果就是生成文件了,但数据为空
  • [问题求助] 云端下发消息体结构能自定义吗
    通过华为云的云端下发消息,客户端收到的实际消息被包裹了一层,把发送的消息内容放在了content节点下了。请问有办法不包裹吗,直接就是消息内容是什么就给客户端发送什么。发送的消息收到的消息
总条数:701 到第
上滑加载中