Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
星火1号_spark_星火一号_开发板
RT-Thread 第29组 大学生夏令营
发布于 2023-07-26 04:19:10 浏览:616
订阅该版
[tocm] # 简介 本项目的主要功能是通过定义星火1号开发板上相应IO的电平状态,调试智能手机与星火一号开发板之间的WIFI通讯,从而通过手机输入相关的命令,实现对麦克纳姆轮四驱小车的移动控制(如下图所示) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/1eaf8de85ced5be117c6021a8032ba6b.png.webp) # 硬件介绍 ### 开发板 ![使用 RT-Thread 星火 1 号 开发板开发本项目,各模块在开发板中位置如图所示](https://oss-club.rt-thread.org/uploads/20230726/ce90e6e56a53ff703712a93655ec061c.png.webp)、 使用 RT-Thread 星火 1 号 开发板开发本项目,各模块在开发板中位置如图所示 ### RSAPBEERY CONN ![如上图所示,开发板RSAPBEERY CONN中各引脚与对应L298N中输入输出口的对应关系](https://oss-club.rt-thread.org/uploads/20230726/18299315b0b1d8ff8f8a1a9bebce0800.png.webp) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/c8e30e88e29153e5c25e6c520cc104f8.png.webp) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/60c523aa006f60d42e60431b5adf807d.png.webp) 如上图所示,开发板RSAPBEERY CONN中各引脚与对应L298N中输入输出口的对应关系 ### RW007 WIFI ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/99c52d58f8e61602c0783e77819ff6de.png.webp) ### 供电方案 1. 八节5号电池串联提供12V电压(两个L298N,两个电池盒共计16个电池):优点是供电较为稳定其,缺点是其重量过大,可能导致小车速度下降。 2. 充电宝3.6V+升压模块升至12V:利用可调输出电压的升压模块可以输出12V电压供L298N使用。但是因为充电宝、升压模块不稳定,其无法稳定输出12V电压,故而舍弃此方案。 ### 接线 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/64ad5556cce94ea346a2b2e761b132de.png.webp) 接线如上图所示,各个端口所对应具体情况如下: 1. 电源线:+12V接升压模块OUT+ 2. GND接升压模块OUT- 3. GND接开发板GND 4. +5V接开发板+5V ### 逻辑控制 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/0a68489fcf27a140565f239b05aef62a.png.webp) 对于Motor_A(小车前轮的两个电机)和Motor_B(小车前轮的两个电机)的控制逻辑如下,其中本项目使用的是PIN,因此无需考虑PWM ### 杜邦线 1. 红色:通常用于连接电源正极或高电平信号。 2. 黑色:通常用于连接电源负极或地线。 3. 蓝色、绿色、黄色等其他颜色:通常用于连接数据线或其他信号线,具体用途取决于具体的电路设计。 ### 小车装配 1. 第一层:电池盒及电池 2. 第二层:星火1号开发板 3. 第三层:L298N电机驱动模块、轮子、电机 # 软件介绍 ### WIFI 完成初始化 ```c static int i = 0; int result = RT_EOK; struct rt_wlan_info info; rt_thread_mdelay(500); ``` ### 热点扫描 ```c /* 执行扫描 */ rt_sem_init(&scan_done,"scan_done",0,RT_IPC_FLAG_FIFO); rt_wlan_register_event_handler(RT_WLAN_EVT_SCAN_REPORT, wlan_scan_report_hander,&i); rt_wlan_register_event_handler(RT_WLAN_EVT_SCAN_DONE, wlan_scan_done_hander,RT_NULL); if(rt_wlan_scan() == RT_EOK) { LOG_D("the scan is started... "); }else { LOG_E("scan failed"); } /*等待扫描完毕 */ rt_sem_take(&scan_done,RT_WAITING_FOREVER); ``` ### Join 网络 ```c /* 热点连接 */ LOG_D("start to connect ap ..."); rt_sem_init(&net_ready, "net_ready", 0, RT_IPC_FLAG_FIFO); /* 注册 wlan ready 回调函数 */ rt_wlan_register_event_handler(RT_WLAN_EVT_READY, wlan_ready_handler, RT_NULL); /* 注册 wlan 断开回调函数 */ rt_wlan_register_event_handler(RT_WLAN_EVT_STA_DISCONNECTED, wlan_station_disconnect_handler, RT_NULL); /* 同步连接热点 */ result = rt_wlan_connect(WLAN_SSID, WLAN_PASSWORD); if (result == RT_EOK) { rt_memset(&info, 0, sizeof(struct rt_wlan_info)); /* 获取当前连接热点信息 */ rt_wlan_get_info(&info); LOG_D("station information:"); print_wlan_information(&info,0); /* 等待成功获取 IP */ result = rt_sem_take(&net_ready, NET_READY_TIME_OUT); if (result == RT_EOK) { LOG_D("networking ready!"); msh_exec("ifconfig", rt_strlen("ifconfig")); } else { LOG_D("wait ip got timeout!"); } /* 回收资源 */ rt_wlan_unregister_event_handler(RT_WLAN_EVT_READY); rt_sem_detach(&net_ready); } else { LOG_E("The AP(%s) is connect failed!", WLAN_SSID); } rt_thread_mdelay(5000); LOG_D("ready to disconect from ap ..."); rt_wlan_disconnect(); ``` ### 自动连接 ```c LOG_D("start to autoconnect ..."); wifi_autoconnect(); ``` ### 串口连接模块 使用sscom5发送数据,rt-studio平台接收数据,数据作为参数传入到电机控制模块 ```c static const char send_data[] = "This is TCP Client from RT-Thread."; /* 发送用到的数据 */ char *recv_data; #define THREAD_PRIORITY 25 #define THREAD_STACK_SIZE 512 #define THREAD_TIMESLICE 5 static rt_thread_t tid1 = RT_NULL; static rt_thread_t tid2 = RT_NULL; /* 线程2的入口函数 */ static void thread2_entry(void *parameter) { int ret; struct hostent *host; int sock, bytes_received; struct sockaddr_in server_addr; const char *url; int port; url = "192.168.43.96"; port = 8800; /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */ host = gethostbyname(url); /* 分配用于存放接收数据的缓冲 */ recv_data = rt_malloc(BUFSZ); if (recv_data == RT_NULL) { rt_kprintf("No memory\n"); return; } /* 创建一个socket,类型是SOCKET_STREAM,TCP类型 */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { /* 创建socket失败 */ rt_kprintf("Socket error\n"); /* 释放接收缓冲 */ rt_free(recv_data); return; } /* 初始化预连接的服务端地址 */ server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); server_addr.sin_addr = *((struct in_addr *)host->h_addr); rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); /* 连接到服务端 */ if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) { /* 连接失败 */ rt_kprintf("Connect fail!\n"); closesocket(sock); /*释放接收缓冲 */ rt_free(recv_data); return; } while (1) { /* 从sock连接中接收最大BUFSZ - 1字节数据 */ bytes_received = recv(sock, recv_data, BUFSZ - 1, 0); if (bytes_received < 0) { /* 接收失败,关闭这个连接 */ closesocket(sock); rt_kprintf("\nreceived error,close the socket.\r\n"); /* 释放接收缓冲 */ rt_free(recv_data); break; } else if (bytes_received == 0) { /* 默认 recv 为阻塞模式,此时收到0认为连接出错,关闭这个连接 */ closesocket(sock); rt_kprintf("\nreceived error,close the socket.\r\n"); /* 释放接收缓冲 */ rt_free(recv_data); break; } /* 有接收到数据,把末端清零 */ recv_data[bytes_received] = '\0'; if (strncmp(recv_data, "q", 1) == 0 || strncmp(recv_data, "Q", 1) == 0) { /* 如果是首字母是q或Q,关闭这个连接 */ closesocket(sock); rt_kprintf("\n got a 'q' or 'Q',close the socket.\r\n"); /* 释放接收缓冲 */ rt_free(recv_data); break; } else { /* 在控制终端显示收到的数据 */ rt_kprintf("\nReceived data = %s ", recv_data); } /* 发送数据到sock连接 */ ret = send(sock, send_data, strlen(send_data), 0); if (ret < 0) { /* 接收失败,关闭这个连接 */ closesocket(sock); rt_kprintf("\nsend error,close the socket.\r\n"); rt_free(recv_data); break; } else if (ret == 0) { /* 打印send函数返回值为0的警告信息 */ rt_kprintf("\n Send warning,send function return 0.\r\n"); } } return; rt_thread_mdelay(500); } /* 线程2 */ int thread2_sample(void) { /* 创建线程2,名称是thread2,入口是thread2_entry*/ tid2 = rt_thread_create("thread2", thread2_entry, RT_NULL, 2048, THREAD_PRIORITY, THREAD_TIMESLICE); /* 如果获得线程控制块,启动这个线程 */ if (tid2 != RT_NULL) rt_thread_startup(tid2); return 0; } MSH_CMD_EXPORT(thread2_sample, thread sample); ``` ### 开发板IO引脚定义 ```c /* 配置 控制电机引脚(L2980N1) */ #define PIN_Motor_PA0 GET_PIN(A, 0) // PA0 : define --> Motor1 #define PIN_Motor_PA8 GET_PIN(A, 8) // PA8 : define --> Motor1 #define PIN_Motor_PB15 GET_PIN(B, 15) // PB15: define --> Motor2 #define PIN_Motor_PB14 GET_PIN(B, 14) // PB14: define --> Motor2 /* 配置 控制电机引脚(L2980N2) */ #define PIN_Motor_PB2 GET_PIN(B, 2) // PB2 : define --> Motor3 #define PIN_Motor_PG6 GET_PIN(G, 6) // PG6 : define --> Motor3 #define PIN_Motor_PG7 GET_PIN(G, 7) // PG7 : define --> Motor4 #define PIN_Motor_PD7 GET_PIN(D, 7) // PD7 : define --> Motor4 /* 定义电机引脚宏 */ #define PIN_Motor1_A PIN_Motor_PA0 #define PIN_Motor1_B PIN_Motor_PA8 #define PIN_Motor2_A PIN_Motor_PB15 #define PIN_Motor2_B PIN_Motor_PB14 #define PIN_Motor3_A PIN_Motor_PB2 #define PIN_Motor3_B PIN_Motor_PG6 #define PIN_Motor4_A PIN_Motor_PG7 #define PIN_Motor4_B PIN_Motor_PD7 ``` ### 小车行驶控制 通过设置对应IO引脚的高低电平,可以控制电机的转动和停止,从而控制小车的前进,后退,左移和右移 ```c /* 控制小车前进 */ void motor_forward(void) { // 向前加速1s rt_pin_write(PIN_Motor1_A, PIN_HIGH); rt_pin_write(PIN_Motor1_B, PIN_LOW); rt_pin_write(PIN_Motor2_A, PIN_HIGH); rt_pin_write(PIN_Motor2_B, PIN_LOW); rt_pin_write(PIN_Motor3_A, PIN_HIGH); rt_pin_write(PIN_Motor3_B, PIN_LOW); rt_pin_write(PIN_Motor4_A, PIN_HIGH); rt_pin_write(PIN_Motor4_B, PIN_LOW); rt_thread_mdelay(1000); //停下 rt_pin_write(PIN_Motor1_A, PIN_LOW); rt_pin_write(PIN_Motor1_B, PIN_LOW); rt_pin_write(PIN_Motor2_A, PIN_LOW); rt_pin_write(PIN_Motor2_B, PIN_LOW); rt_pin_write(PIN_Motor3_A, PIN_LOW); rt_pin_write(PIN_Motor3_B, PIN_LOW); rt_pin_write(PIN_Motor4_A, PIN_LOW); rt_pin_write(PIN_Motor4_B, PIN_LOW); } /* 控制小车后退 */ void motor_backward(void) { // 向后加速1s rt_pin_write(PIN_Motor1_A, PIN_LOW); rt_pin_write(PIN_Motor1_B, PIN_HIGH); rt_pin_write(PIN_Motor2_A, PIN_LOW); rt_pin_write(PIN_Motor2_B, PIN_HIGH); rt_pin_write(PIN_Motor3_A, PIN_LOW); rt_pin_write(PIN_Motor3_B, PIN_HIGH); rt_pin_write(PIN_Motor4_A, PIN_LOW); rt_pin_write(PIN_Motor4_B, PIN_HIGH); rt_thread_mdelay(1000); //停下 rt_pin_write(PIN_Motor1_A, PIN_LOW); rt_pin_write(PIN_Motor1_B, PIN_LOW); rt_pin_write(PIN_Motor2_A, PIN_LOW); rt_pin_write(PIN_Motor2_B, PIN_LOW); rt_pin_write(PIN_Motor3_A, PIN_LOW); rt_pin_write(PIN_Motor3_B, PIN_LOW); rt_pin_write(PIN_Motor4_A, PIN_LOW); rt_pin_write(PIN_Motor4_B, PIN_LOW); } /* 控制小车左走*/ void motor_left(void) { // 向左加速0.5s rt_pin_write(PIN_Motor1_A, PIN_LOW); rt_pin_write(PIN_Motor1_B, PIN_HIGH); rt_pin_write(PIN_Motor2_A, PIN_HIGH); rt_pin_write(PIN_Motor2_B, PIN_LOW); rt_pin_write(PIN_Motor3_A, PIN_HIGH); rt_pin_write(PIN_Motor3_B, PIN_LOW); rt_pin_write(PIN_Motor4_A, PIN_LOW); rt_pin_write(PIN_Motor4_B, PIN_HIGH); rt_thread_mdelay(1000); //停下 rt_pin_write(PIN_Motor1_A, PIN_LOW); rt_pin_write(PIN_Motor1_B, PIN_LOW); rt_pin_write(PIN_Motor2_A, PIN_LOW); rt_pin_write(PIN_Motor2_B, PIN_LOW); rt_pin_write(PIN_Motor3_A, PIN_LOW); rt_pin_write(PIN_Motor3_B, PIN_LOW); rt_pin_write(PIN_Motor4_A, PIN_LOW); rt_pin_write(PIN_Motor4_B, PIN_LOW); } /* 控制小车右走 */ void motor_right(void) { // 向右加速0.5s rt_pin_write(PIN_Motor1_A, PIN_HIGH); rt_pin_write(PIN_Motor1_B, PIN_LOW); rt_pin_write(PIN_Motor2_A, PIN_LOW); rt_pin_write(PIN_Motor2_B, PIN_HIGH); rt_pin_write(PIN_Motor3_A, PIN_LOW); rt_pin_write(PIN_Motor3_B, PIN_HIGH); rt_pin_write(PIN_Motor4_A, PIN_HIGH); rt_pin_write(PIN_Motor4_B, PIN_LOW); rt_thread_mdelay(1000); //停下 rt_pin_write(PIN_Motor1_A, PIN_LOW); rt_pin_write(PIN_Motor1_B, PIN_LOW); rt_pin_write(PIN_Motor2_A, PIN_LOW); rt_pin_write(PIN_Motor2_B, PIN_LOW); rt_pin_write(PIN_Motor3_A, PIN_LOW); rt_pin_write(PIN_Motor3_B, PIN_LOW); rt_pin_write(PIN_Motor4_A, PIN_LOW); rt_pin_write(PIN_Motor4_B, PIN_LOW); } /* 线程1的入口函数 */ static void thread1_entry(void *parameter) { rt_pin_mode(PIN_Motor_PA0, PIN_MODE_OUTPUT); rt_pin_mode(PIN_Motor_PA8, PIN_MODE_OUTPUT); rt_pin_mode(PIN_Motor_PB15, PIN_MODE_OUTPUT); rt_pin_mode(PIN_Motor_PB14, PIN_MODE_OUTPUT); rt_pin_mode(PIN_Motor_PB2, PIN_MODE_OUTPUT); rt_pin_mode(PIN_Motor_PG6, PIN_MODE_OUTPUT); rt_pin_mode(PIN_Motor_PG7, PIN_MODE_OUTPUT); rt_pin_mode(PIN_Motor_PD7, PIN_MODE_OUTPUT); while (1) { /* 线程1采用低优先级运行,一直打印计数值 */ if (strcmp(recv_data, "a") == 0) { motor_forward(); // rt_kprintf(" data:%s \r\n",recv_data); rt_memset(recv_data, 0, strlen(recv_data)); } else if (strcmp(recv_data, "b") == 0) { motor_backward(); rt_memset(recv_data, 0, strlen(recv_data)); } else if (strcmp(recv_data, "c") == 0) { motor_left(); rt_memset(recv_data, 0, strlen(recv_data)); } else if (strcmp(recv_data, "d") == 0) { motor_right(); rt_memset(recv_data, 0, strlen(recv_data)); } rt_thread_mdelay(500); } } /* 线程1 */ int thread1_sample(void) { /* 创建线程1,名称是thread1,入口是thread1_entry*/ tid1 = rt_thread_create("thread1", thread1_entry, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); /* 如果获得线程控制块,启动这个线程 */ if (tid1 != RT_NULL) rt_thread_startup(tid1); return 0; } /* 导出到 msh 命令列表中 */ MSH_CMD_EXPORT(thread1_sample, thread sample); ``` # 运行结果 最后,在完成上面步骤后,我们通过命令行执行一下代码(如下图)即可完成小车与控制设备的WIFI连接(下面代码以小车与智能手机的WIFI连接为例) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/a7454c38c5a9bf3273af624d57128dc6.png.webp) # 应用参考 1. 星火1号例程:https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/hw-board/spark-1/spark-1 2. 星火1号官方论坛: club.rt-thread.org
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
SCUTWei
这家伙很懒,什么也没写!
文章
1
回答
0
被采纳
0
关注TA
发私信
相关文章
1
[星火一号] 代码模板, 手动写启动代码, 开机后 snprintf 不能处理 %llu 了, 是有什么配置上的冲突吗?
2
使用MDK5.37开发星火一号,双击mklinks.bat 文件后,目录下没有 rt-thread 和 libraries 的文件夹图标。
3
studio文件构建丢失
4
rtt中星火一号stm-32怎么把两个示例工程合并成一个
5
星火一号串口发送问题
6
基于开发板建工程的疑问
7
使用星火一号开发板建工程的奇怪问题
8
星火一号板pwm功能,不报错,但也不输出,为什么?
9
星火一号怎么强制改变已占用的引脚的功能呢
10
火星一号的标准库在哪里?外设的数据手册在哪里看?
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
I2C_IIC
ESP8266
UART
WIZnet_W5500
ota在线升级
PWM
cubemx
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
xusiwei1236
8
个答案
2
次被采纳
踩姑娘的小蘑菇
1
个答案
2
次被采纳
用户名由3_15位
7
个答案
1
次被采纳
bernard
4
个答案
1
次被采纳
RTT_逍遥
3
个答案
1
次被采纳
本月文章贡献
聚散无由
2
篇文章
15
次点赞
catcatbing
2
篇文章
5
次点赞
Wade
2
篇文章
2
次点赞
Ghost_Girls
1
篇文章
6
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部