闲来无事,用手头STM32做个项目。
开始制作。
还有系统原理图等在资料中。
1、首先测试GPS,找到地址(经纬度)数据。再测试GSM,通过AT指令使其可以发短信(也可测试打电话,本项目用不到),然后在板子中测试,再测试GPS,找到地址(经纬度)数据。
2、测试小车自动循迹。
3、测试小车
GPS(ATK-NEO-6M GPS)模块
设置好后,模块接收NMEA码并解析出我们需要的数据。
例如:
每个都代表着不同的数据。可以参考:GPS的NMEA码的详细解释定义
具体的模块已经配置好了,我们使用就可以了。
1、给模块供5V电、GND接地。
2、模块接到板子串口1上(模块TX接板子PA10、模块RX接板子PA9)。
1、代码要做的就是将这个过程自动化。收集到数据之后自动处理。
2、部分代码如下
void parseGpsBuffer()
{
char *subString;
char *subStringNext;
char i = 0;
if (Save_Data.isGetData)
{
Save_Data.isGetData = false;
u2_printf("**************\r\n");
u2_printf(Save_Data.GPS_Buffer);
for (i = 0 ; i <= 6 ; i++)
{
if (i == 0)
{
if ((subString = strstr(Save_Data.GPS_Buffer, ",")) == NULL)
errorLog(1);
}
else
{
subString++;
if ((subStringNext = strstr(subString, ",")) != NULL)
{
char usefullBuffer[2];
switch(i)
{
case 1:memcpy(Save_Data.UTCTime, subString, subStringNext - subString);break; //??è?UTCê±??
case 2:memcpy(usefullBuffer, subString, subStringNext - subString);break; //??è?UTCê±??
case 3:memcpy(Save_Data.latitude, subString, subStringNext - subString);break; //??è??3?èD??¢
case 4:memcpy(Save_Data.N_S, subString, subStringNext - subString);break; //??è?N/S
case 5:memcpy(Save_Data.longitude, subString, subStringNext - subString);break; //??è??-?èD??¢
case 6:memcpy(Save_Data.E_W, subString, subStringNext - subString);break; //??è?E/W
default:break;
}
subString = subStringNext;
Save_Data.isParseData = true;
if(usefullBuffer[0] == 'A')
Save_Data.isUsefull = true;
else if(usefullBuffer[0] == 'V')
Save_Data.isUsefull = false;
}
else
{
errorLog(2);
}
}
}
}
}
1、模块供5V电,GND接地。
2、模块接到板子串口2上(模块TX接板子PA2、模块RX接板子PA3)。
首先用AT指令测试模块,达到可以发短信,打电话。
下边是部分AT指令:
AT | 返回 | 作用 |
---|---|---|
AT | OK | 模块通讯正常 |
AT+CPIN? | +CPIN:READY | 查询 SIM 卡的状态,主要是 PIN 码 |
AT+CSQ | +CSQ: 24,0 | 查询信号质量 |
AT+COPS? | +COPS:0,0,”CHINA MOBILE” | 查询当前运营商 |
AT+CGMI | SIMCOM_Ltd | 查询模块制造商 |
AT+CGMM | SIMCOM_SIM800C | 查询模块型号 |
AT+CGSN | 866104023267696 | 查询产品序列号(集 IMEI 号) |
AT+CNUM | +CNUM:””,”136******”,”129”,7,4 | 查询本机号码 |
ATE1 | OK | 设置回显模式(默认开启) |
ATD10086; | OK | 用于拨打任意电话号码 |
ATA | OK | 应答电话 |
ATH | OK | 挂断电话 |
AT+CMGF=1 | OK | 置短消息模式,设置为文本模式 |
AT+CSCS=“GSM” | OK | 用于设置 TE 字符集,纯英文为GSM,中英文为UCS2 |
AT+CMGS | > | 用于发短信 |
AT+CSCS="GSM"
;AT+CMGF=1
;AT+CMGS="18********"
;>
,此时我们输入我们需要发送的内容:ATK-SIM800C MSG SEND TEST
;1A
(即 0X1A),即可启动一次短信发送。AT+CMGF=1
, 设置为文本模式;AT+CSMP=17,167,2,25
;AT+CSCS="UCS2"
;由于使用了 UCS2字符集,所有字符/数字/汉字,都必须使用 UNICODE 编码
AT+CMGS=”00310038003200390030003100390035003600330032”
,这个指>
00410054004B002D00530049004D003800300030004300204E2D82F1658777ED4FE153D 190016D4B8BD5
注意,此可以不用发送回车了;1A
(即 0X1A),启动一次短信发送。void sim800c_test(void)
{
OLED_Clear();
sim800c_send_cmd((u8*)0X1A,"+CMGS:",10);
IWDG_ReloadCounter();
while(sim800c_send_cmd("AT","OK",100))//检测是否应答AT指令
{
OLED_ShowString(0,0,"SBLJZ ",16); //连接成功
sim800c_send_cmd((u8*)0X1A,"+CMGS:",10);
}
printf("ATE0");
OLED_ShowString(0,0,"LJCG ",16); //连接成功
delay_ms(10);
while(sim800c_send_cmd("AT+CMGF=1","OK",200)){} //设置文本模式
OLED_ShowString(0,2,"WBMS ",16);//文本模式
while(sim800c_send_cmd("AT+CSCS=\"GSM\"","OK",200)){} //设置TE字符集为UCS2
OLED_ShowString(0,4,"ZFMS ",16);//字符模式
//发送短信测试
OLED_ShowString(0,4,"ZZSZ ",16); //正在发送
if(sim800c_send_cmd("AT+CMGS=\"10086\"",">",800) == 0);
printf("Test!/r/nTest1\r\n");
IWDG_ReloadCounter();
if(sim800c_send_cmd((u8*)0X1A,"+CMGS:",800)==0){OLED_ShowString(0,6," FSCG ",16);return;}
OLED_ShowString(0,6," FSSB ",16);
IWDG_ReloadCounter();
USART_RX_STA=0;
if(USART_RX_STA&0X8000)sim_at_response(1);//检查从GSM模块接收到的数据
}
I am full,I am 110'46E,40°51′
模块原理:
红外检测模块:通过一个红外发射管和一个红外接受管来检测路径上是否有不可反射红外线的东西。这里主要用来黑线循迹。
人体红外热释电模块:用来检测前方是否有人。实现停车装卸垃圾。
人体红外检测模块及红外检测模块都是开关量检测。我们只需要检测到高电平做出相应的动作即可。
模块作用:主要作为载体,进行黑线循迹。检测到有人后停下,垃圾满后停下。
这里由于单片机驱动力不够,无法直接驱动小车。我们用UNL2003驱动小车。带上一个独立的9V电源给小车供电。这里我们只驱动电机正转,意思就是只能向前走。ULN2003是负极驱动。驱动板的接线方式为:给驱动板的正负极接电源(干电池串联组成的9V直流电源)正极负极,电机的所有正极都接到一起,接到电源的正极,负极接到四个ULN2003的输出极上,单片机出来四根控制极接到对应的四个控制引脚上,这样单片机高电平输出的时候,ULN2003输出极输出,电机转动。(也可以通过输出一个pwm波来控制电机转速,这里我们电源电压没采用12V的,驱动四个电机,速度本也不快,就没有做速度控制,如果用作pwm输出,请注意单片机引脚要有定时器复用功能。)这里就是个单片机IO口输出,就不放代码了。
说说明:这里车很垃圾,我也很垃圾。就只做了个绕行一圈,没有做其他路况,可根据自身情况增加其他路况。
解释一下:
红外检测没有遇到黑色的线的时候,反馈检测不到反馈的值,当遇到黑色的线,发射的红外线就会反射,接受极就会检测到高电平。
直行的时候四个电平都是低电平。
当3号红外探头检测到高电平的时候,说有前边有向右的转弯,让右边前一个电机停转,左边两个电机继续走,直到再次四个检测到空。
当四号探头检测高高电平的时候,说明已经走过很多了,这个时候让右边两个电机停止,当3号检测到的时候,开右边一个电机这时候恢复到上边那种情况。
可根据自己的情况微调电机。这是向右转弯。向左转弯是一样的。这里不再赘述了。
//五种状态 0:都没踩到 1:左二踩到 2:左12踩到 3:右1 4:右12踩到
//没有检测到 Off 检测到 On
int Infrared_Find()
{
if((Infrared_1 == Off)&&(Infrared_2 == Off)&&(Infrared_3== Off)&&(Infrared_4 == Off)) //四个都没检测到
{
return 5;
}
else if((Infrared_1 == On)&&(Infrared_2 == Off)&&(Infrared_3== Off)&&(Infrared_4 == Off))
{
return 1;
}
else if((Infrared_1 == Off)&&(Infrared_2 == On)&&(Infrared_3== Off)&&(Infrared_4 == Off))
{
return 2;
}
else if((Infrared_1 == Off)&&(Infrared_2 == Off)&&(Infrared_3== On)&&(Infrared_4 == Off))
{
return 3;
}
else if((Infrared_1 == Off)&&(Infrared_2 == Off)&&(Infrared_3== Off)&&(Infrared_4 == On))
{
return 4;
}
else if((Infrared_1 == On)&&(Infrared_2 == On)&&(Infrared_3== Off)&&(Infrared_4 == On))
{
return 6;
}
else if((Infrared_1 == Off)&&(Infrared_2 == Off)&&(Infrared_3== On)&&(Infrared_4 == On))
{
return 7;
}
return 0;
}
//小车前进
void Motor_Go()
{
Motor_1_Go;
Motor_2_Go;
Motor_3_Go;
Motor_4_Go;
}
//小车右转
void Motor_Right()
{
Motor_1_Go;
Motor_3_Go;
Motor_2_Stop;
Motor_4_Stop;
}
//小车左转
void Motor_Lift()
{
Motor_2_Go;
Motor_4_Go;
Motor_1_Stop;
Motor_3_Stop;
}
//小车停止
void Motor_Stop()
{
Motor_1_Stop;
Motor_2_Stop;
Motor_3_Stop;
Motor_4_Stop;
}
这里采用的是180度舵机,舵机是一个固定pwm输出就对应一个角度的装置。我们将舵机固定到自己的模拟垃圾桶的盖子上,实现自动控制。每次打开垃圾桶打开盖子10s后自动关闭垃圾桶盖子。
这里可以根据自己装舵机的方向,去调整舵机开关时候角度对应的pwm值。
底层配置这里就不放出来了。
if(LED_Peo) //人体红外检测到有人
{
TIM_SetCompare2(TIM3,194); //开一次垃圾桶
}
else
{
TIM_SetCompare2(TIM3,183);
}
当检测到前方有人的时候就停下,打开垃圾桶,然后关闭垃圾桶,当垃圾丢满的时候,给手机发送当前位置进行提醒。当检测到没人的时候就走。
最后附上完整的项目文件。自行下载。
这个项目到这里就算完了。
还有很多不足的地方,希望大佬可以指正。也希望和爱好者交流学习。
禁止转载!!!