手机APP遥控电动滑板车


拆解平衡车
主芯片 GD32F130
万用表探查电路,分析管脚功能;
使用KEIL编写单片机控制代码:

void gpio_config(void)
{rcu_periph_clock_enable(RCU_GPIOA);/* configure PA6(TIMER2 CH0) as alternate function */gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10);gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10);gpio_af_set(GPIOA, GPIO_AF_2, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10);rcu_periph_clock_enable(RCU_GPIOB);/* configure output GPIO port */gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15);gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15);gpio_bit_reset(GPIOB, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15);/* enable the Key GPIO clock */rcu_periph_clock_enable(RCU_GPIOA);/* configure button pin as input */gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN_1);/* enable the Key GPIO clock */rcu_periph_clock_enable(RCU_GPIOB);/* configure button pin as input */gpio_mode_set(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN_11);/* enable the Key GPIO clock */rcu_periph_clock_enable(RCU_GPIOC);/* configure button pin as input */gpio_mode_set(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN_14);}/*!\brief      configure the TIMER peripheral\param[in]  none\param[out] none\retval     none*/
void timer_config(void)
{/* -----------------------------------------------------------------------TIMER2CLK is 50KHzTIMER2 channel0 duty cycle = (25000/ 50000)* 100  = 50%----------------------------------------------------------------------- */timer_oc_parameter_struct timer_ocintpara;timer_parameter_struct timer_initpara;rcu_periph_clock_enable(RCU_TIMER0);timer_deinit(TIMER0);/*timer_initpara.prescaler      = 1339;timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;timer_initpara.counterdirection  = TIMER_COUNTER_UP;timer_initpara.period          = 49999;timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;timer_initpara.repetitioncounter = 0;timer_init(TIMER0,&timer_initpara);*//* TIMER0 configuration */timer_initpara.prescaler         = 719;timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;timer_initpara.counterdirection  = TIMER_COUNTER_UP;timer_initpara.period            = 499;timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;timer_initpara.repetitioncounter = 0;timer_init(TIMER0,&timer_initpara);/* CH0 configuration in PWM mode */timer_ocintpara.outputstate  = TIMER_CCX_ENABLE;timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;timer_ocintpara.ocpolarity   = TIMER_OC_POLARITY_HIGH;timer_ocintpara.ocnpolarity  = TIMER_OCN_POLARITY_HIGH;timer_ocintpara.ocidlestate  = TIMER_OC_IDLE_STATE_LOW;timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;timer_channel_output_config(TIMER0,TIMER_CH_0,&timer_ocintpara);timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_0,PWM_val);timer_channel_output_mode_config(TIMER0,TIMER_CH_0,TIMER_OC_MODE_PWM0);timer_channel_output_shadow_config(TIMER0,TIMER_CH_0,TIMER_OC_SHADOW_DISABLE);//timer_primary_output_config(TIMER0,ENABLE);/*timer_channel_output_config(TIMER0, TIMER_CH_0,&timer_ocintpara);timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_0,24999);timer_channel_output_mode_config(TIMER0,TIMER_CH_0,TIMER_OC_MODE_PWM0);timer_channel_output_shadow_config(TIMER0,TIMER_CH_0,TIMER_OC_SHADOW_DISABLE);*/timer_channel_output_config(TIMER0,TIMER_CH_1,&timer_ocintpara);timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_1,PWM_val);timer_channel_output_mode_config(TIMER0,TIMER_CH_1,TIMER_OC_MODE_PWM0);timer_channel_output_shadow_config(TIMER0,TIMER_CH_1,TIMER_OC_SHADOW_DISABLE);timer_channel_output_config(TIMER0,TIMER_CH_2,&timer_ocintpara);timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_2,PWM_val);timer_channel_output_mode_config(TIMER0,TIMER_CH_2,TIMER_OC_MODE_PWM0);timer_channel_output_shadow_config(TIMER0,TIMER_CH_2,TIMER_OC_SHADOW_DISABLE);/* auto-reload preload enable */timer_auto_reload_shadow_enable(TIMER0);/* auto-reload preload enable */timer_enable(TIMER0);timer_primary_output_config(TIMER0, ENABLE);
}/*******************************************************************************
* º¯ÊýÃû³Æ: PWM();
* ¹¦ÄÜÃèÊö: ¹Ø±Õ´ò¿ªPWM
* ÊäÈë²ÎÊý: ÎÞ
* ·µ»Ø²ÎÊý: ÎÞ
********************************************************************************/
void CH_ON(uint32_t pin)
{rcu_periph_clock_enable(RCU_GPIOA);/* configure PA6(TIMER2 CH0) as alternate function */gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE,pin);gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,pin);gpio_af_set(GPIOA, GPIO_AF_2, pin);
}
void CH_OFF(uint32_t pin)
{gpio_bit_reset(GPIOA, pin);/* enable the GPIO clock */rcu_periph_clock_enable(RCU_GPIOA);/* configure GPIO port */ gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, pin);gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, pin);/* reset GPIO pin */gpio_bit_reset(GPIOA, pin);
}/*******************************************************************************
* º¯ÊýÃû³Æ: Table_EX ͨµÀÅú´¦Àí
8--13
9--14
10--15
* ¹¦ÄÜÃèÊö:
* ÊäÈë²ÎÊý: ÎÞ
* ·µ»Ø²ÎÊý: ÎÞ
********************************************************************************/
void Table_EX(unsigned int table[6])
{if(table[0]==2){CH_ON(GPIO_PIN_8);timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_0,PWM_val);//PWMgpio_bit_set(GPIOB, GPIO_PIN_13);//¸ßPWMÊä³ö}if(table[0]==1){timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_0,0);CH_OFF(GPIO_PIN_8);gpio_bit_reset(GPIOB, GPIO_PIN_13);//µÍµ¼Í¨}if(table[0]==0){timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_0,0);CH_OFF(GPIO_PIN_8);//µÍgpio_bit_set(GPIOB, GPIO_PIN_13);//·´Ïà½ØÖÁ}if(table[1]==2){CH_ON(GPIO_PIN_9);timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_1,PWM_val);//PWMgpio_bit_set(GPIOB, GPIO_PIN_14);//¸ßPWMÊä³ö}if(table[1]==1){timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_1,0);CH_OFF(GPIO_PIN_9);gpio_bit_reset(GPIOB, GPIO_PIN_14);//µÍµ¼Í¨}if(table[1]==0){timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_1,0);CH_OFF(GPIO_PIN_9);//µÍgpio_bit_set(GPIOB, GPIO_PIN_14);//¸ß}if(table[2]==2){CH_ON(GPIO_PIN_10);timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_2,PWM_val);//PWMgpio_bit_set(GPIOB, GPIO_PIN_15);//¸ßPWMÊä³ö}if(table[2]==1){timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_2,0);CH_OFF(GPIO_PIN_10);gpio_bit_reset(GPIOB, GPIO_PIN_15);//µÍµ¼Í¨}if(table[2]==0){timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_2,0);CH_OFF(GPIO_PIN_10);//µÍgpio_bit_set(GPIOB, GPIO_PIN_15);//¸ß}}/*******************************************************************************
* º¯ÊýÃû³Æ: BLDC_Hall_Convet();
* ¹¦ÄÜÃèÊö: ¸ù¾Ý»ô¶û״̬½øÐл»Ïò--T1 T3 T5/T4 T6 T2ÅÅÁÐ
* ÊäÈë²ÎÊý: ÎÞ
* ·µ»Ø²ÎÊý: ÎÞ
********************************************************************************/
void BLDC_Hall_Convet(void)
{ PC14_Value = gpio_input_bit_get(GPIOC, GPIO_PIN_14)*1;PA1_Value = gpio_input_bit_get(GPIOA, GPIO_PIN_1)*2;PB11_Value = gpio_input_bit_get(GPIOB, GPIO_PIN_11)*4;HALL_Value = PC14_Value+PA1_Value+PB11_Value;if(n>10000){HALL_Value = HALL_Value+1;}if(x!=HALL_Value){/*table[0]=0;table[1]=0;table[2]=0;table[3]=0;table[4]=0;table[5]=0;Table_EX(table);delay_1ms(1);*/if(HALL_flag ==1) //Õýת{                                     switch(HALL_Value)   //¸ù¾Ýת×ÓλÖ㬾ö¶¨CCERÊä³öÏàλºÍת×Ó×ÖÆ«ÒÆÁ¿{case 5: table[0]=0;table[1]=1;table[2]=2;Table_EX(table);break;case 1: table[0]=2;table[1]=1;table[2]=0;Table_EX(table);break;case 3: table[0]=2;table[1]=0;table[2]=1;Table_EX(table);break;case 2: table[0]=0;table[1]=2;table[2]=1;Table_EX(table);break;case 6: table[0]=1;table[1]=2;table[2]=0;Table_EX(table);break;case 4: table[0]=1;table[1]=0;table[2]=2;Table_EX(table);break;default:break;} }if(HALL_flag ==2) //·´×ª{                                    switch(HALL_Value)   //¸ù¾Ýת×ÓλÖ㬾ö¶¨CCERÊä³öÏàλºÍת×Ó×ÖÆ«ÒÆÁ¿{case 5: table[0]=1;table[1]=0;table[2]=2;Table_EX(table);break;case 1: table[0]=0;table[1]=1;table[2]=2;Table_EX(table);break;case 3: table[0]=2;table[1]=1;table[2]=0;Table_EX(table);break;case 2: table[0]=2;table[1]=0;table[2]=1;Table_EX(table);break;case 6: table[0]=0;table[1]=2;table[2]=1;Table_EX(table);break;case 4: table[0]=1;table[1]=2;table[2]=0;Table_EX(table);break;default:break;}  }x=HALL_Value;IWDG_FEED();n=0;      }else{n++;}}//USART1³õʼ»¯
void uart1_init(uint32_t bound)
{/* ?? GPIOA ??? */rcu_periph_clock_enable(RCU_GPIOA);/* ?? USART1?? */rcu_periph_clock_enable(RCU_USART1);   /* ??PA2? USARTx_Tx */gpio_af_set(GPIOA, GPIO_AF_1,GPIO_PIN_2);/* ??PA2????????????? */gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_2);gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);/* ??PA3? USARTx_Rx */gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_3); /* ??PA3?????????????*/gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_3);gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3);/* USART configure */usart_deinit(USART1);usart_baudrate_set(USART1, bound);usart_word_length_set(USART1, USART_WL_8BIT);usart_stop_bit_set(USART1, USART_STB_1BIT);usart_parity_config(USART1, USART_PM_NONE);usart_hardware_flow_rts_config(USART1, USART_RTS_DISABLE);usart_hardware_flow_cts_config(USART1, USART_CTS_DISABLE);usart_receive_config(USART1, USART_RECEIVE_ENABLE);usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);usart_enable(USART1);// nvic_irq_enable(USART1_IRQn, 0, 0);usart_interrupt_enable(USART1 , USART_INT_RBNE);}//USART1½ÓÊÜÖжÏ
void USART1_IRQHandler(void)
{k=20;if(usart_interrupt_flag_get(USART1, USART_INT_FLAG_RBNE) != RESET) //½ÓÊÕÖжÏ{Usart_rec = usart_data_receive(USART1);//usart_data_transmit(USART1, Usart_rec);if(Usart_rec=='A'||flag==1){flag=1;if(i < k+1){aRxBuffer[i] = Usart_rec;i++;}if(Usart_rec=='E'){//printf("%s\r\n",aRxBuffer);if(aRxBuffer[0]=='A'&&aRxBuffer[10]=='E'){if (aRxBuffer[5]=='R'){HALL_Value=0;Run_flag =1;HALL_flag=2;PWM_val=(aRxBuffer[6]-'0')*100+(aRxBuffer[7]-'0')*10+(aRxBuffer[8]-'0')*1;}if (aRxBuffer[5]=='F'){HALL_Value=0;Run_flag =1;HALL_flag=1;PWM_val=(aRxBuffer[6]-'0')*100+(aRxBuffer[7]-'0')*10+(aRxBuffer[8]-'0')*1;}         if(PWM_val>0&&PWM_val<499){}else{PWM_val=0;}if (aRxBuffer[9]=='S'){Run_flag =0;}i=0;for(j=0;j<k+1;j++){aRxBuffer[j]=' ';}flag=0;}}}}// if(RESET != usart_interrupt_flag_get(USART1, USART_INT_FLAG_TBE)) //·¢ËÍÖжÏ//   {         //  }
}/*!\brief      main function\param[in]  none\param[out] none\retval     none
*/
int main(void)
{systick_config();uart1_init(115200);gpio_config();timer_config();//printf("\r\n start~\r\n");x=8;HALL_Value=0;IWDG_INIT();while(1){            if(Run_flag ==1){BLDC_Hall_Convet();//»»Ïò    }else{table[0]=0;table[1]=0;table[2]=0;Table_EX(table);IWDG_FEED();  }      USART1_IRQHandler();}
}

使用ST-link下载程序到单片机,滑板车的程序部分就搞定了。
需要自己制作一个电机安装支架,喜欢DIY的可以自己做,也可以某宝买个;
电路板用3D打印了一个壳子,方便安装。

接下来制作手机的APP,效果图如下,使用蓝牙透传连接到滑板车。

APP主要控制代码如下:

 @SuppressLint("ClickableViewAccessibility")private void touch_pad(){LinearLayout linearLayout = (LinearLayout) findViewById(R.id.touch_pad);final  DrawView drawView = new DrawView(this);drawView.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:break;case MotionEvent.ACTION_MOVE:moveX = event.getX();moveY = event.getY();Log.d("move","moveX= "+moveX);Log.d("move","moveY= "+moveY);//Log.d("time","sys= "+System.currentTimeMillis()+"temp= "+temp);if(moveX<0){moveX=0;}if(moveX>padlength){moveX=padlength;}if(moveY<0){moveY=0;}if(moveY>padlength){moveY=padlength;}drawView.currentX = moveX;drawView.currentY = moveY;drawView.invalidate();//通过draw组件重绘if(System.currentTimeMillis()-temp>200) {moveY = padlength / 2 - moveY;moveX = moveX - padlength / 2;WL = (int) moveY + (int) moveX;WR = (int) moveY - (int) moveX;if (WL > 499) {//限幅WL = 498;}else if(WL<-499){WL=-498;}if (WR > 499) {WR = 498;}else if(WR<-499){WR=-498;}if(WL>0){sendstr = "AR" +numtostr(WL);}else{sendstr = "AF" +numtostr(-WL);}if(WR>0){sendstr = sendstr+"R" +numtostr(WR);}else{sendstr = sendstr+"F" +numtostr(-WR);}sendstr = sendstr+"RE";mBLESPPUtils.send(sendstr.getBytes());temp=System.currentTimeMillis();}break;case MotionEvent.ACTION_UP:drawView.currentX = padlength/2;drawView.currentY = padlength/2;drawView.invalidate();//通过draw组件重绘sendstr="AS000S000SE";mBLESPPUtils.send(sendstr.getBytes());break;case MotionEvent.ACTION_CANCEL:break;}return true;}});linearLayout.addView(drawView);}

APP及单片机源代码链接
单片机控制代码
安卓APP控制源代码

爆改平衡车-->电动滑板车相关推荐

  1. 基于STC单片机的两轮平衡车设计

    给大家传福利了..后续继续共享基于Arduino/安卓Android/树莓派raspberry等平台的两轮车设计 这是我前年暑假做的一个小项目,今年拿出来整理了下当毕设了(当然毕设里添加了许多其他元素 ...

  2. 双轮载人平衡车设计完整教程之调校测试篇

    双轮载人平衡车设计完整教程之调校测试篇 实验及路测结果 6.1 硬件测试 6.1.1车体与元件安装 车体采用的是精钢打造的船型包厢,车体机械部分的安装及重量分布,直接影响到小车的平衡性能.拿起螺丝准备 ...

  3. [单片机学习笔记](35):串级PID算法应用剖析、通过串口控制电机、MPU6050获取平衡车姿态、自制平衡车PID算法程序设计

    串级PID算法应用剖析 这是经过给队友讲解串级PID的程序的之后的进一步的理解总结. 内环的实际值,取决于你能测出什么值给内环.而内环的输入就是内环误差 内环的输出值,是内环误差(内环目标值-内环实际 ...

  4. 直立智能车(平衡车)毕业论文

    直立智能车设计 摘  要 随着微电子控制技术的发展和人们对出行工具的日益增长的需求,一款简单易操作.容易携带.清洁无污染的两轮自平衡车开始走进大众的视野,但这种小型代步工具仍可能存在一定的不稳定性和安 ...

  5. 造物者之吻:中国手机“爆改安卓”的这些年

    如果我们把时间倒回去智能手机刚兴起的那几年,回到iPhone早先几代的时候.不知道大家是不是还记得这样一个画面?用苹果的朋友会对安卓用户说,安卓那么卡,我实在不知道怎么用. 那时候,苹果还频繁地与肾这 ...

  6. 平衡车轮子控制器使用

    平衡车轮子控制器使用 说明 在使用中遇到了很多问题,所以特将问题记录下来. 主要参考bilibili上大佬的视频解决的. 视频链接:[摇杆控制电动车制作 开源无刷电机驱动板使用第3节 ADC摇杆模块使 ...

  7. 基于 NI myRIO 的平衡车设计

    摘要 本文设计了以 NI myRIO 作为核心控制器,用 LabVIEW 编程语言开发的两轮自平衡小车.根据加速度传感器的测量数据以及编码器的数据,通过PID算法,利用NI myRIO调节PWM从而获 ...

  8. 浅谈两轮平衡车的控制原理

    前言:在IT行业摸爬滚打了好几年,好不容易从学生熬成了社会人士,通过自己的不断努力又从社会人士熬成了学生.这几年的修行,同道博友给了我很多的帮助,很早之前就有写博客的想法,想借自己绵薄之力来回馈一下默 ...

  9. 【立创开源】ESP32 平衡车

    本项目参考了B站上 手工大 的视频以及程序,然后根据自己的需要稍微进行了改动. 原视频网址:[平衡小车--使用ESP32在Arduino环境下自制加测试(开源)] https://www.bilibi ...

最新文章

  1. excel小写转大写公式_【Excel函数贴】五个技巧性函数小套路
  2. 无需羡慕,今后.NET开发想拿30k也可以毫不费劲!
  3. FatMouse's Speed hdu 1160(动态规划,最长上升子序列+记录路径)
  4. java.util.Scanner简单应用
  5. windows设置mysql使用率_Windows下配置Mysql
  6. 作者:温孚江,现任山东农业大学校长、教授,农业大数据创新战略联盟理事长,全国人民代表大会常务委员会委员。...
  7. 【需求工程】需求管理
  8. KITTI数据集解读
  9. 图片压缩软件有哪些?分享三个好用的图片压缩软件
  10. cocos2d-x游戏开发 《坠入蔚蓝》
  11. linux播放器安装包下载地址,linux安装MPLAYER播放器
  12. macOS Ventura 13.1 (22C65) 正式版发布,ISO、IPSW、PKG 下载
  13. 将手机流氓软件彻底赶出去
  14. 小白学习编程遇到问题应该如何正确的提问
  15. 图片base64转存本地url
  16. 分布式技术原理与实战45讲--05 第05讲:共识问题:区块链如何确认记账权?
  17. Ueditor去掉图片之间的间隙
  18. 盘点5大高频移动端场景,你不会用就落后了(内附模板下载)
  19. 巴菲特给出了六条人生的建议
  20. 递归_青蛙跳台阶(进阶版)

热门文章

  1. 【工业物联网基础】现代企业环境中的DCS(分布式控制系统)和SCADA(站点控制和数据采集)...
  2. NTC温度传感器 (含arduino程序)(公式解算版)(终极)
  3. i8本地兼容html5文件,浏览器兼容性
  4. 智能工厂以MES系统为基础,实现"信息化减人,自动化换人"
  5. python图片自动校正流量_案例:基于自动节点树的数据异常原因下探分析(python_029)...
  6. djay Pro 2 Mac(DJ混音软件)破解激活教程
  7. 三十天学会绘画pdf_《30天学会绘画》我从零基础开始
  8. Rimini Street公布2020年第二季度财务业绩
  9. Hive QL场景题第六部分详解
  10. 一位初级进阶中级 JavaScript 工作者的自我修养(一)