12下一页

[讨论] DIY航模遥控器

[复制链接]

技术员

发表于 2017-3-8 15:23:20   2250 查看 24 回复 显示全部楼层 倒序浏览
分享
本帖最后由 zhangxh 于 2017-3-8 15:50 编辑

这是自己设计制作的PCB板 航模遥控器
供大家一起学习交流  
10.JPG

11.JPG

12.JPG

13.JPG

14.JPG

15.JPG

遥控器我采用的是STM32作为主控芯片,综合考虑这款芯片的性价比最高。无线发射与接收模块采用经济适用的24L01+模块,这款模块成本低,技术成熟、稳定性好空中传输速率选择在250K,以提高传输距离。采用跳频通讯方式能够很好地避开通讯中的信道冲突。理论上可以65535个遥控器仪器同时使用,相互不会产生干扰。
        采用硬件SPI通讯,使用W25X40 FLASH芯片作为存储单元。使用低成本的12864液晶作为显示单元。使用TL431基准芯片为ADC采样提供基准电压信号,是遥控器的ADC采集稳定可靠。左手油门和右手油门可以软件设定,但是需要硬件支持。
        ShockBurst模式下nRF24L01可以与成本较低的低速MCU相连高速信号处理是由芯片内部的射频协议处理的nRF24L01提供SPI接口数据率取决于单片机本身接口速度ShockBurst模式通过允许与单片机低速通信而无线部分高速通信减小了通信的平均消耗电流在ShockBurstTM接收模式下当接收到有效的地址和数据时IRQ通知MCU随后MCU可将接收到的数据从RX FIFO寄存器中读出 在ShockBurstTM发送模式下nRF24L01自动生成前导码及CRC校验。数据发送完毕后IRQ通知MCU减少了MCU的查询时间也就意味着减少了MCU 的工作量同时减少了软件的开发时间nRF24L01内部有三个不同的RX FIFO寄存器6个通道共享此寄存器和三个不同的TX FIFO寄存器在掉电模式下待机模式下和数据传输的过程中MCU可以随时访问FIFO寄存器这就允许SPI接口可以以低速进行数据传送并且可以应用于MCU硬件上没有SPI接口的情况下

遥控器支持模拟器,可以直接连接解密狗,输出标准的PPM信号。使用这个遥控器可以再电脑上模拟飞行。
下面接收遥控器和接收机之间的通许协议。通讯协议分为4种类型,分别是遥控器发出的PCM帧和广播帧。接收机发出的对码帧和数据帧。
遥控数据格式由32个字节数据组成。
遥控和接收机对码原理:
遥控器部分工作原理:遥控器上电后,首先检查上次对码的接收机信息,并发送上一次对码成功信息的地址,1秒后没有收到上次对码成功的接收机信息,遥控器会同时发送广播信息以接收其它接收机的配对信息。当遥控器接收到接收机的配对信息并确认后,停止发送广播信息。只发送接收机的信息。1秒以后仍然没有接收到信息,遥控器会扫频发送广播信息。
接收机部分工作原理:接收机上电后,首先检查上一次对码的遥控器信息,并等待接收遥控器信息。短接对码接口后,接收机会将广播地址打开,扫频接收广播信息。直到对码成功。

遥控器软件选择FreeRTOS  ,现将部分代码分享出来
int main(void)
{        
         __set_PRIMASK(1);//关全局中断
        
   W25_dat.Sector=0xffff;//设置W25x40内存数据不可用
        
   BSP_Config();//硬件及软件配置
   
         AppResourcesInit();//任务资源初始化        
        
   #if TASK_DEBUG
         xTaskCreate(Simulation_Task,"Simulation_Task1",512,NULL,1,NULL);        //仿真调试监视任务
         xTaskCreate(UartDebug_Task,"UartDebug_Task",512,NULL,3,NULL);        //串口仿真调试监视任务
         UartRxQueue = xQueueCreate(10, sizeof(P_DAT) );//创建串口接收队列
   #endif
         xTaskCreate(Dog_Task,"Dog_200mS",256,NULL,5,NULL);        //看门狗监视任务         
         xTaskCreate(AppInit_Task,"AppInit",512,NULL,9,&AppInitHandleTaskStart);        //应用初始化任务
         
        
         
   
         vTaskStartScheduler();//开始调度任务
        while(1)
        {}
}
void AppInit_Task( void *pvParameters )          //应用初始化任务
{

        #if TASK_DEBUG        
  u8 buf[20];
        #endif
  portTickType xLastWakeTime;         
        const TickType_t xTicksToWait = 50 / portTICK_PERIOD_MS; /* 延迟50ms */
        xLastWakeTime=xTaskGetTickCount();//获取当前心跳值         
        #if TASK_DEBUG               
     DPrintfGetTheKey(); //获取打印资源                        
                 DPrintf("\r\n初始化任务已经启动\r\n");                        
     DPrintfGiveUpKey();//释放打印资源                        
        #endif
        
  for( ;; )
        {                  
                vTaskDelayUntil(&xLastWakeTime,xTicksToWait);
               
    Spi2GetTheKey();//获取Spi2的钥匙               
   
                /**********************FLASH芯片初始化************************/
                W25_dat.ChipID=W25_DeviceID();//读取芯片的8位型号ID  唤醒芯片               
                W25_dat.Jedec_Id=W25_JEDEC_ID();//读取芯片的制造商ID和16位型号ID
    if(W25_ReadSector(0)==0)W25_ReadSector(0);//读指定扇区的数据到内存 如果失败在读取一次
               
                if((W25_dat.page[0][0]!=0x18)||(W25_dat.page[0][1]!=0x18))//判断FLASH是否需要初始化
                 {//以下更新内存
                         W25_dat.page[0][0]=0x18;W25_dat.page[0][1]=0x18;
                         ee_wrfun();//初始化写EE数据
                         for(;W25_WeadeSector()==0;);//将内存的数据写入FLASH                                 
                 }
                else//读取已经初始化的数据
                {
                        ee_rdfun();//初始化读EE数据
                }               
                Spi2GiveUpKey();//归还Spi2的钥匙
               
                /***************打印输出初始化数据*****************/
                #if TASK_DEBUG               
     DPrintfGetTheKey(); //获取打印资源                        
                 DPrintf("\r\nFLASH初始化完成\r\n");                                 
                 U8_Uchar(&W25_dat.ChipID,buf,3);buf[3]='\r';buf[4]='\n';buf[5]=0;
                 DPrintf("\r\nFLASH ID编号:");DPrintf((const signed char *)buf);               
                 
                 DPrintf("\r\n初始化任务删除自身任务\r\n");                        
     DPrintfGiveUpKey();//释放打印资源                        
                #endif        
    LcmInit();//液晶初始化?
    lcd_rst_flag=1;//液晶完成初始化
                AppTaskCreate();//创建任务
                vTaskDelete(AppInitHandleTaskStart);//应用初始化任务执行一次后删除任务
        }
}
void Dog_Task( void *pvParameters )          //看门狗监视任务
{
  EventBits_t uxBits;
  portTickType xLastWakeTime;         
        const TickType_t xTicksToWait = 200 / portTICK_PERIOD_MS; /* 延迟200ms */
        xLastWakeTime=xTaskGetTickCount();//获取当前心跳值
        /*
          开始执行启动任务主函数前使能独立看门狗。
          设置LSI是128分频,下面函数参数范围0-0xFFF,分别代表最小值3.2ms和最大值13107.2ms
          下面设置的是1s,如果1s内没有喂狗,系统复位。
        */
        bsp_InitIwdg(0x138);

#if TASK_DEBUG        
    DPrintfGetTheKey(); //获取打印资源                        
                DPrintf("\r\n监视任务已经启动 \r\n");               
    DPrintfGiveUpKey();//释放打印资源        
#endif
  for( ;; )
        {   
                vTaskDelayUntil(&xLastWakeTime,xTicksToWait);
    /* 等待所有任务发来事件标志 */
                uxBits = xEventGroupWaitBits(DogEventGroup, /* 事件标志组句柄 */
                                                                 TASK_BIT_0_1,       /* 等碩ASK_BIT_0_1被设置 */
                                                                 pdTRUE,             /* 退出前TASK_BIT_0_1被清除,这里是TASK_BIT_0_1都被设置才表示“退出”*/
                                                                 pdTRUE,             /* 设置为pdTRUE表示等待TASK_BIT_0_1都被设置*/
                                                                 xTicksToWait);          /* 等待延迟时间 */
               
                if((uxBits & TASK_BIT_0_1) == TASK_BIT_0_1)
                {
                        IWDG_Feed();//喂狗                        
                        #if TASK_DEBUG               
      //DPrintfGetTheKey(); //获取打印资源        
                        //DPrintf("喂狗成功\r\n");        
      //DPrintfGiveUpKey();//释放打印资源                        
                        #endif                        
                }
          else
                {
                        #if TASK_DEBUG        
      //DPrintfGetTheKey(); //获取打印资源                        
                        //DPrintf("等待喂狗指令\r\n");        
     // DPrintfGiveUpKey();//释放打印资源                                       
                        #endif               
                }
        }
}
void UartDebug_Task( void *pvParameters )//串口仿真调试任务
{
        u8 buf[512];
  P_DAT p_dat;        
        u16 len;
        for(;;)
        {
                xQueueReceive(UartRxQueue,&p_dat,portMAX_DELAY);
               
                if(p_dat.id==1)                        
                {
                        len=UsartTaskRead(&p_dat,buf,USART1_MAX_LEN);//解析读取数据
                        Uart1GetTheKey();//获取串口1的钥匙
                        Usart1Tx(buf,len);         //发送数据      
                        Uart1GiveUpKey();//归还串口1的钥匙                        
                }               
        }
        
}
void Simulation_Task( void *pvParameters )//仿真调试监视任务
{
        portTickType xLastWakeTime;         
  uint8_t pcWriteBuffer[512];
        const TickType_t xTicksToWait = 5000 / portTICK_PERIOD_MS; /* 延迟5000ms */
        xLastWakeTime=xTaskGetTickCount();//获取当前心跳值

        DPrintfGetTheKey(); //获取打印资源        
        DPrintf("\r\n仿真任务已经启动 \r\n");                 
  DPrintfGiveUpKey();//释放打印资源

        for(;;)
        {
                vTaskDelayUntil(&xLastWakeTime,xTicksToWait);//延迟10s

                DPrintfGetTheKey(); //获取打印资源
                DPrintf("=================================================\r\n");
                DPrintf("   任务名称  任务状态 优先级  剩余栈  任务序号 \r\n\r\n");
                vTaskList( (char *)&pcWriteBuffer );                                                
                DPrintf((const signed char *)pcWriteBuffer);
               
                DPrintf("=================================================\r\n");
                DPrintf("  任务名称     运行计数      使用效率 \r\n\r\n");
                vTaskGetRunTimeStats( (char *)&pcWriteBuffer );                                                
                DPrintf((const signed char *)pcWriteBuffer);        
               
                DPrintfGiveUpKey();//释放打印资源
        }
        
}
void AppTaskCreate(void)//创建任务
{  
        RF2401xQueue = xQueueCreate(10, sizeof(RF_DAT) );//创建RF接收队列
        xTaskCreate(Task0,"Task0",512,NULL,3,NULL);
        xTaskCreate(ADC_Task,"ADC_Task",256,NULL,8,NULL);        
        xTaskCreate(URT_DEBUG_Task,"URT_DEBUG_Task",512,NULL,5,NULL);
        xTaskCreate(NRF2401_Task,"NRF2401_Task",512,NULL,9,NULL);
        xTaskCreate(NRF2401TX_Task,"NRF2401TX_Task",512,NULL,9,NULL);//最高优先级
        xTaskCreate(Task_lcd,"Task_lcd",512,NULL,3,NULL);
        xTaskCreate(Tim5mS_Task,"Tim10mS",512,NULL,8,NULL);        //5毫秒定时器任务
        
}

void Tim5mS_Task( void *pvParameters )          //5毫秒定时器任务
{ u8 i,rf_da;
        RF_DAT  rf_dat;
  portTickType xLastWakeTime;         
        const TickType_t xTicksToWait = 5/ portTICK_PERIOD_MS; /* 延迟5ms */
        xLastWakeTime=xTaskGetTickCount();//获取当前心跳值
  for( ;; )
        {                  
                vTaskDelayUntil(&xLastWakeTime,xTicksToWait);//延迟5ms
                rf_da++;
    if(rf_da>=2){rf_da=0;rf_dat.id=1; rf_dat.p=NULL;xQueueSend(RF2401xQueue,&rf_dat,pdPASS);}
               
    if(bz_con){bz_con--;GPIO_SetBits(GPIOA,GPIO_Pin_12);}//蜂鸣器控制
    else{GPIO_ResetBits(GPIOA,GPIO_Pin_12);}
                                
    key_bmbuf[key_bmcnt]=GPIO_ReadInputData(GPIOB);
                key_bmcnt++;if(key_bmcnt>=20){key_bmcnt=0;if(key_bmflag==0){key_bmflag=1;for(i=0;i<50;i++){key_bmbuff=key_bmbuf;}}}
                UsartRxQuery();//串口接收查询函数        
                /* 发送事件标志,表示任务正常运行 */
                xEventGroupSetBits(DogEventGroup, TASK_BIT_1);
        }
}

产品设计过程及成本分析
        首先设计的是遥控器和接收机,当时考虑遥控器是不是要采购一个外壳,但是在淘宝搜索了好久也没有找到什么合适的 后来找到广东航模配件店购买了2套外壳 一套黑色12元 一套白色13元。
        接下来选择高频模块,最后选择了24L01模块 接收机部分才有低成本的 200米 模块4.5元   遥控器采用 32元的100豪瓦的模块收发距离2500米的哪一种 ,两种模块结合使用经过测试 空旷传输800米没有问题 指示500米以上方向性比较强。
      在接下来就是选择液晶显示 最后考虑成本选择了一款10元左右的12864液晶模块,以上图形大家看到的液晶就是此液晶和背光。当然以上都是不包含运费的价格。
     以后就是设计原理图和PCB  遥控器的PCB做了有两款 一款是有外壳的 一款是没有外壳的  接收机开始设计了一款但是体积比较大 后来又设计了一款 小体积的 以减轻重量  2*3CM的尺寸

产品设计过程及成本分析
        首先设计的是遥控器和接收机,当时考虑遥控器是不是要采购一个外壳,但是在淘宝搜索了好久也没有找到什么合适的 后来找到广东航模配件店购买了2套外壳 一套黑色12元 一套白色13元。
        接下来选择高频模块,最后选择了24L01模块 接收机部分才有低成本的 200米 模块4.5元   遥控器采用 32元的100豪瓦的模块收发距离2500米的哪一种 ,两种模块结合使用经过测试 空旷传输800米没有问题 指示500米以上方向性比较强。
      在接下来就是选择液晶显示 最后考虑成本选择了一款10元左右的12864液晶模块,以上图形大家看到的液晶就是此液晶和背光。当然以上都是不包含运费的价格。
     以后就是设计原理图和PCB  遥控器的PCB做了有两款 一款是有外壳的 一款是没有外壳的  接收机开始设计了一款但是体积比较大 后来又设计了一款 小体积的 以减轻重量  2*3CM的尺寸

这款遥控器采用STM32 芯片   12864液晶  串口下载程序已经做到板子上  只需要一根串口线就可以下载   采用18650电池用电  电池壳固定尺寸已经画到线路板上   可以连接使用手机充电器充电,充电电路也已经集成到线路板上 ,可以使用充电宝供电 。充电口采用和手机一样的接口 方便实用。
        震撼的外观、集成多种功能 、方便程序调试 。是DIY遥控器的不二选择

447026.rar
447028.rar
447027.rar


PCB图.rar

320.67 KB, 下载次数: 28

原理图1.rar

22.18 KB, 下载次数: 21

原理图2.rar

16 KB, 下载次数: 26

标签:遥控器 单片机

版主

发表于 2017-3-8 15:57:55  
帮你分享了  
回复

点赞 举报

实习生

发表于 2017-3-8 18:07:57   来自发烧友APP

PCB在线计价下单

板子大小:

cm
X
cm

层数:

2

板子数量:

10

厚度:

1.6
666
回复

点赞 举报

等待验证会员

发表于 2017-3-12 18:10:20  
漂亮!!!!!!!!
回复

举报

等待验证会员

发表于 2017-3-13 09:04:28   来自发烧友APP
6666
回复

点赞 举报

实习生

发表于 2017-3-14 12:14:06   来自发烧友APP
厉害了我的哥
回复

点赞 举报

技术员

发表于 2017-3-15 18:11:32  
板子很骚气啊,楼主
回复

点赞 举报

实习生

发表于 2017-3-17 09:06:49  
不错,朋友!加油!
回复

点赞 举报

技术员

发表于 2017-3-19 19:20:53  
程序不开源??
回复

点赞 举报

实习生

发表于 2017-3-25 00:08:59   来自手机
厉害
回复

举报

实习生

发表于 2017-4-4 18:40:05  

板子很骚气啊,楼主
回复

点赞 举报

实习生

发表于 2017-4-4 18:40:58  
有源代码发分享吗
回复

点赞 举报

技术员

发表于 2017-4-6 08:59:41   来自手机
顶一下
回复

举报

实习生

发表于 2017-4-12 00:04:38  

漂亮!!不错
回复

举报

发表于 2017-4-24 23:35:34  
非常不错,谢谢分享
回复

点赞 举报

总工程师

发表于 2017-5-5 10:02:25  
造型很酷,像鸟一样
回复

点赞 举报

总工程师

发表于 2017-5-5 10:02:35  
不知道功能怎样啊?
回复

点赞 举报

技术员

发表于 2017-5-5 16:02:48    楼主|
lee_st 发表于 2017-5-5 10:02
不知道功能怎样啊?

还没有做板子  呵呵 设计阶段  就急忙分享出来了
回复

点赞 举报

技术员

发表于 2017-5-5 16:03:33    楼主|
blylbx 发表于 2017-4-4 18:40
有源代码发分享吗

设计阶段还没有 成套的代码

回复

点赞 举报

总工程师

发表于 2017-5-6 12:49:53  
哦哦,加油啊,兄弟
回复

点赞 举报

12下一页

只有小组成员才能发言,加入小组>>

110个成员聚集在这个小组

加入小组

创建小组步骤

关闭

站长推荐 上一条 /7 下一条

快速回复 返回顶部 返回列表
-

推荐专区

技术干货集中营

专家问答

用户帮助┃咨询与建议┃版主议事

工程师杂谈

工程师创意

工程师职场

论坛电子赛事

社区活动专版

发烧友活动

-

嵌入式论坛

ARM技术论坛

Android论坛

Linux论坛

单片机/MCU论坛

FPGA|CPLD|ASIC论坛

DSP论坛

嵌入式系统论坛

-

电源技术论坛

电源技术论坛

无线充电技术

-

硬件设计论坛

PCB设计论坛

电路设计论坛

电子元器件论坛

控制|传感

总线技术|接口技术

-

测试测量论坛

LabVIEW论坛

Matlab论坛

测试测量技术专区

仪器仪表技术专区

-

EDA设计论坛

multisim论坛

PADS技术论坛

Protel|AD|DXP论坛

Allegro论坛

proteus论坛|仿真论坛

EasyEDA-中国人自已的EDA工具

Orcad论坛

-

综合技术与应用

电机控制

智能电网

光电及显示

参考设计中心

汽车电子技术论坛

医疗电子论坛

-

开源硬件

-

无线通信论坛

无线通信技术专区

天线|RF射频|微波|雷达技术

-

IC设计论坛

芯片测试与失效分析

Mixed Signal/SOC[数模混合芯片设计]

Analog/RF IC设计

设计与制造封装测试

-

厂商专区

TI论坛

TI Deyisupport社区

-

检测技术与质量

电磁兼容(EMC)设计与整改

安规知识论坛

检测与认证

-

消费电子论坛

手机技术论坛

平板电脑/mid论坛

音视/视频/机顶盒论坛

-

电子论坛综合区

聚丰众筹官方社区

新人报道区

聚丰供应链

-

论坛服务区

-

供求信息发布

供需广告

招聘┃求职发布区

电子展览展会专区