Android手机控制树莓派制作的四驱小车

年初的时候看到@段念-段文韬 的这篇文章《使用树莓派制作的远程开门器》后,觉得硬件编程似乎没有想象的难。 之前认为硬件编程可能需要学习新的编程语言,需要特别的编程环境。然而树莓派使用Linux操作系统环境,只要Linux支持的编程语言 ,都可以成为你的选择。当语言环境不是问题的时候,对于我来说,我最感兴趣的部分是如何用树莓派来控制一些低速的外部设备,例如 :继电器、小马达。 一般的PC并不提供
摘要由CSDN通过智能技术生成

-------更新


完整的代码放在Github上了:

服务端:https://github.com/darlinglele/raspberry-server

手机客户端: https://github.com/darlinglele/raspberry-client


-------全文

年初的时候看到@段念-段文韬 的这篇文章《使用树莓派制作的远程开门器》后,觉得硬件编程似乎没有想象的难。 之前认为硬件编程可能需要学习新的编程语言,需要特别的编程环境。然而树莓派使用Linux操作系统环境,只要Linux支持的编程语言 ,都可以成为你的选择。当语言环境不是问题的时候,对于我来说,我最感兴趣的部分是如何用树莓派来控制一些低速的外部设备,例如 :继电器、小马达。 一般的PC并不提供这些通用接口,PC只提供一些高速设备的接口如USB。 而树莓派不止提供了USB接口,还提供了GPIO接口,有了这个接口使得控制通用的外部设备得以实现。

开始之前,请用最方便的方式连入树莓派。我自己没有额外的显示器,所以只好通过MBA的Terminal直接SSH上去。 树莓派预装了Python,但是你需要安装RPI GPIO python来驱动GPIO。安装包地址:http://log.liminastudio.com/writing/tutorials/tutorial-how-to-use-your-raspberry-pi-like-an-arduino 。安装之后,在程序中import就可以控制GPIO:

  • 10
    点赞
  • 107
    收藏
    觉得还不错? 一键收藏
  • 22
    评论
控制四轮驱动麦克纳姆轮小车需要用到PWM信号控制电机的转速和方向,同时还需要使用编码器实时反馈电机的转速和位置,以便精确控制小车的运动。 以下是一个简单的控制程序示例,可以供参考: 1. 首先定义各个电机的控制引脚和编码器引脚: ```C #define PWM_TIM TIM3 #define PWM_CH1 GPIO_Pin_6 #define PWM_CH2 GPIO_Pin_7 #define PWM_CH3 GPIO_Pin_8 #define PWM_CH4 GPIO_Pin_9 #define ENCODER_TIM TIM4 #define ENCODER_CH1 GPIO_Pin_6 #define ENCODER_CH2 GPIO_Pin_7 #define ENCODER_CH3 GPIO_Pin_8 #define ENCODER_CH4 GPIO_Pin_9 ``` 2. 初始化PWM信号和编码器: ```C void PWM_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_OCInitTypeDef TIM_OCInitStruct; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Pin = PWM_CH1 | PWM_CH2 | PWM_CH3 | PWM_CH4; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM3); GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_TIM3); GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_TIM3); GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_TIM3); TIM_TimeBaseInitStruct.TIM_Prescaler = 0; TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStruct.TIM_Period = 3999; TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(PWM_TIM, &TIM_TimeBaseInitStruct); TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStruct.TIM_Pulse = 0; TIM_OC1Init(PWM_TIM, &TIM_OCInitStruct); TIM_OC2Init(PWM_TIM, &TIM_OCInitStruct); TIM_OC3Init(PWM_TIM, &TIM_OCInitStruct); TIM_OC4Init(PWM_TIM, &TIM_OCInitStruct); TIM_Cmd(PWM_TIM, ENABLE); } void Encoder_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_ICInitTypeDef TIM_ICInitStruct; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Pin = ENCODER_CH1 | ENCODER_CH2 | ENCODER_CH3 | ENCODER_CH4; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_TIM4); GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_TIM4); GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_TIM4); GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_TIM4); TIM_TimeBaseInitStruct.TIM_Prescaler = 0; TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStruct.TIM_Period = 65535; TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(ENCODER_TIM, &TIM_TimeBaseInitStruct); TIM_ICInitStruct.TIM_Channel = TIM_Channel_1; TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStruct.TIM_ICFilter = 0; TIM_ICInit(ENCODER_TIM, &TIM_ICInitStruct); TIM_ICInitStruct.TIM_Channel = TIM_Channel_2; TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStruct.TIM_ICFilter = 0; TIM_ICInit(ENCODER_TIM, &TIM_ICInitStruct); TIM_ICInitStruct.TIM_Channel = TIM_Channel_3; TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStruct.TIM_ICFilter = 0; TIM_ICInit(ENCODER_TIM, &TIM_ICInitStruct); TIM_ICInitStruct.TIM_Channel = TIM_Channel_4; TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStruct.TIM_ICFilter = 0; TIM_ICInit(ENCODER_TIM, &TIM_ICInitStruct); TIM_EncoderInterfaceConfig(ENCODER_TIM, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); TIM_SetCounter(ENCODER_TIM, 0); TIM_Cmd(ENCODER_TIM, ENABLE); } ``` 3. 编写PWM控制函数: ```C void SetPWM(uint16_t ch1, uint16_t ch2, uint16_t ch3, uint16_t ch4) { TIM_SetCompare1(PWM_TIM, ch1); TIM_SetCompare2(PWM_TIM, ch2); TIM_SetCompare3(PWM_TIM, ch3); TIM_SetCompare4(PWM_TIM, ch4); } ``` 4. 编写电机控制函数: ```C void SetMotorSpeed(int16_t speed1, int16_t speed2, int16_t speed3, int16_t speed4) { uint16_t pwm1, pwm2, pwm3, pwm4; pwm1 = abs(speed1); pwm2 = abs(speed2); pwm3 = abs(speed3); pwm4 = abs(speed4); if (speed1 >= 0) { GPIO_SetBits(GPIOC, GPIO_Pin_0); GPIO_ResetBits(GPIOC, GPIO_Pin_1); } else { GPIO_ResetBits(GPIOC, GPIO_Pin_0); GPIO_SetBits(GPIOC, GPIO_Pin_1); } if (speed2 >= 0) { GPIO_SetBits(GPIOC, GPIO_Pin_2); GPIO_ResetBits(GPIOC, GPIO_Pin_3); } else { GPIO_ResetBits(GPIOC, GPIO_Pin_2); GPIO_SetBits(GPIOC, GPIO_Pin_3); } if (speed3 >= 0) { GPIO_SetBits(GPIOC, GPIO_Pin_4); GPIO_ResetBits(GPIOC, GPIO_Pin_5); } else { GPIO_ResetBits(GPIOC, GPIO_Pin_4); GPIO_SetBits(GPIOC, GPIO_Pin_5); } if (speed4 >= 0) { GPIO_SetBits(GPIOC, GPIO_Pin_6); GPIO_ResetBits(GPIOC, GPIO_Pin_7); } else { GPIO_ResetBits(GPIOC, GPIO_Pin_6); GPIO_SetBits(GPIOC, GPIO_Pin_7); } SetPWM(pwm1, pwm2, pwm3, pwm4); } ``` 5. 编写控制程序,通过串口接收控制指令并控制小车运动: ```C int main(void) { // 初始化各个引脚和模块 PWM_Init(); Encoder_Init(); USART_Init(); int16_t vx, vy, vw; int16_t speed1, speed2, speed3, speed4; while (1) { // 从串口接收控制指令 USART_Receive(&vx, &vy, &vw); // 计算电机转速 speed1 = vx - vy - vw; speed2 = vx + vy + vw; speed3 = vx + vy - vw; speed4 = vx - vy + vw; // 控制电机 SetMotorSpeed(speed1, speed2, speed3, speed4); } } ``` 以上是一个简单的控制程序示例,实际应用中还需要根据实际情况进行调整和完善。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值