爆改平衡车-->电动滑板车

手机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 50KHz
    TIMER2 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);//PWM
		gpio_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);//PWM
		gpio_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);//PWM
		gpio_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() {
            @Override
            public 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控制源代码

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值