极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 12414|回复: 2

介绍一款蓝牙遥控的小车机器人、制作与套材

[复制链接]
发表于 2016-3-20 22:01:24 | 显示全部楼层 |阅读模式

     这是一款廉价的,易制作的,可供中小学兴趣班、课后活动班以及青少年电子技师活动采用的;单片机控制,蓝牙遥控的机器人小车套材。 套材为散件形式,青少年可以从电子元器件的焊接学起。通过安装调试最后参赛整个过程锻炼动手能力,创新能力;而且充满知趣。 涉及单片机的事就离不开编程。但计算机程序对大多是人学起来较难。本套材将程序已调试好,并已下载,所以无需卖家任何操作。小车的运行参数修改都通过手机蓝牙完成, 是互动性很强的,非常现代的一款电子科普器材。 小车采用了本人持有的实用新型专利的直流电机驱动方案,主要特点是直接使用直流电机,而无须变速齿轮箱,不用传统的轮子。其结果是大大降低了整机的成本。 电机由PWM信号驱动,优点是小车运行平滑,特别是转弯的动作;避免了简单驱动方式的扭动。其弧度可以通过调节两个电机的PWM参数,使其具有不同的转速, 从而向某一方向偏转。这种驱动方式的动力来自电机轴与地面的摩擦力。实践证明,在一般的平整、坚实地面上(没有沟棱),小车可以跑的很快。 这款套材将从动手能力,单片机知识,机器人互动性以及竞赛等多方面给青少年以培养。    
特点:
硬件结构
    采用独特的电机直接驱动方式。
软件结构
    串口接收使用中断方式;
    采用软件PWM控制电机转速,软件PWM由定时器2定时中断产生;
    因为Arduino除了两个外部中断,其他中断功能都没有提供,以上中断都是标准avrgcc的写法。其实,所有的Arduino不具备的能力都可以通过这种方式获得。


详情请登录:www.machmouse.com

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2016-3-21 20:19:52 | 显示全部楼层
广告!!!!!!鉴定完毕!!!!!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-3-21 20:25:57 | 显示全部楼层
//蓝牙遥控小车
//Arduino 源程序
//定稿日期:2016-3-16
//程序功能简介:
//程序采用软件PWM方式,控制两支直流电机的运行行为,实现直行、后退、左转和右转动作。
//操作者使用Android手机的蓝牙功能发出指令,操控小车动作。
//操作者还通过蓝牙对小车的动作参数进行调试。
//使用自定义串口收发数据
//使用软件PWM,输出引脚可任意制定
//使用Atmega48芯片
//Arduio 版本1.0.5
#include <avr/io.h>  
#include <avr/interrupt.h>  
#include <EEPROM.h>
#include "usart.h"

unsigned int counter;   //PWM计数器
unsigned char wCnt = 0; //接收字计数
unsigned int pwm_LH;    //左电机高电平计数
unsigned int pwm_RH;    //右电机高电平计数
unsigned char lDirect;  //左电机运转方向
unsigned char rDirect;  //右电机运转方向
unsigned int LP = 0;
unsigned int RP = 0;
unsigned int LD = 0;
unsigned int RD = 0;

unsigned int PWM[6];        //存放当前PWM参数的整数型数组,全局变量

unsigned char inputString[8];         // 存输入数据字符串变量
boolean stringComplete = false;  // 数据串结束标志

//定时器2初始化函数
void timer2_init()  
{  
  cli();
  TCCR2B = 0x00; //
  TCNT2 = 0xF6; //
  TCCR2A = 0x00;
  TCCR2B = 0x02; //
  TIMSK2 = 0x01; //定时器2中断允许
  sei();
}  


//定时器2中断服务函数
//PWM波形产生器
ISR(TIMER2_OVF_vect)
{  
  TCNT2 = 0xF6; //
  counter++;
  if (counter == 0x3ff)
  {
    if (rDirect == 1)
      bitSet(PORTD,5);
    else
      bitSet(PORTD,4);

    if (lDirect == 1)
      bitSet(PORTD,7);
    else
      bitSet(PORTD,6);
    counter = 0;
  }
  if (counter == pwm_RH)
  {
    bitClear(PORTD,4);
    bitClear(PORTD,5);
  }
  if (counter == pwm_LH)
  {
    bitClear(PORTD,6);
    bitClear(PORTD,7);
  }

}
//电机运行函数
void Move(unsigned int LS,unsigned char LD,unsigned int RS,unsigned char RD)
{            
  asm("BCLR 7");  //关中断
  pwm_LH = LS;
  pwm_RH = RS;
  lDirect = LD;
  rDirect = RD;
  asm("BSET 7");  //开中断       
}

//获取EEPROM数据函数
//功能:从EEPROM里顺序读出六个PWM参数,存入PWM数组
void GetData()
{
  unsigned char bytes[2];        //暂时存放PWM参数的字节数组,全局变量
  unsigned char i;
  unsigned char j;
  unsigned char k;
  for (i = 0;i < 6;i++)                        //for 循环,读六个参数
  {
    for (j = 0;j < 2;j++)                //内循环,每次读两个字节
    {
      k = i * 2 + 1 - j;                //地址计算
      bytes[j] = EEPROM.read(k);        //EEPROM读操作
    }
    PWM[i] = word(bytes[0], bytes[1]);        //将读出的两个字节合成一个PWM整数数据
  }
}

//数据发送函数
//功能:将一个整数拆分成四个ASCII代码,通过蓝牙串口发出的函数。
//例如:整数784,将拆分成;' ','7','8','4'四个字符
void Number(int val)
{
  int tmp;                //中间变量
  unsigned char i;                //循环计数变量
  unsigned char buf[4];                //存字符数组

  tmp = val / 1000;
  buf[0] = tmp + 0x30;        //获得千位

  val = val % 1000;
  tmp = val / 100;
  buf[1] = tmp + 0x30;        //获得百位

  val = val % 100;
  tmp = val / 10;
  buf[2] = tmp + 0x30;        //获得十位

  val = val % 10;
  buf[3] = val + 0x30;        //获得个位

  for (i = 0;i < 4;i++)
  {
    if (buf[i] == 0x30)        //从高位整理,如果是0,则转换成空格。
      buf[i] = 0x20;
    else
      break;
  }
  Usart_Transmit(buf[0]);      //通过蓝牙串口连续发出四个字符。
  Usart_Transmit(buf[1]);
  Usart_Transmit(buf[2]);
  Usart_Transmit(buf[3]);
}


void setup() {
  timer2_init();
  Usart_Init(9600);
  sei();
  PORTD = 0x00;
  DDRD  = 0xF0;
  GetData();    //初始化PWM参数
}



void loop() {

  unsigned char buf[6];                //存连续字符的数组
  unsigned char index = 0;        //存索引值变量
  unsigned char i;
  unsigned char k;
  unsigned int para;                //存PWM数据变量
  delay(500);
  if (stringComplete == true)   //分解手机传过来的参数
  {                              //格式是:#n%dddd
    k = 0;                      //其中:n 为索引(地址);dddd 为数据
    index = 0;
    for (i = 0;i <= wCnt ;i++)
    {
      if (inputString[i] == '%')
      {
        index = inputString[i-1] - 0x30;  //获得索引
        k = 0;
      }
      else
      {
        buf[k] = inputString[i] - 0x30;  //获得数据
        k++;
      }
    }
    para = 0;
    for (i = 0;i < k-1;i++)
      para = para * 10 + buf[i];

    PWM[index] = para;        //将得到的整数参数立即存入对应的PWM数组单元,修改当前运行参数
    buf[1] = lowByte(para);   //将整数转换成两个字节。
    buf[0] = highByte(para);
    index = index * 2;                //计算EEPROM地址
    EEPROM.write(index, buf[1]);  //写入EEPROM低位在前
    index++;
    EEPROM.write(index, buf[0]);  //高位在后

    stringComplete = false;
    wCnt = 0;
  }
}


ISR(USART_RX_vect)
{
  unsigned char command=0;
  int i;
  command = UDR0;             //接收数据
  inputString[wCnt] = command;
  wCnt++;
  if (command == 13) {
    stringComplete = true;
    wCnt--;
  }
  else if (command == 10)
  {
    stringComplete = false;
    wCnt = 0;
  }
  switch (command) {
  case '@':
    GetData();        //从EEPROM中读出数据
    for (i = 0;i < 6;i++)
    {
      Number(PWM[i]);        //通过蓝牙回传,Android手机上会有显示
    }
    wCnt = 0;
    break;
  case '#':            //得到手机发回的修改参数数据
    break;
  case  'w' :     // 接收到 'w',前进
    LP = PWM[0];
    RP = PWM[1];
    LD = 1;
    RD = 1;
    wCnt = 0;
    break;
  case  'x' :     // 接收到 'x',后退
    LP = PWM[0];
    RP = PWM[1];
    LD = 0;
    RD = 0;
    wCnt = 0;
    break;
  case  'a' :     // 接收到 'a',左转
    LP = PWM[2];
    RP = PWM[3];
    LD = 0;
    RD = 1;
    wCnt = 0;
    break;
  case  'd' :     // 接收到 'd',右转
    LP = PWM[4];
    RP = PWM[5];
    LD = 1;
    RD = 0;
    wCnt = 0;
    break;
  case  's' :     // 接收到 's',停止电机
    LP = 0;
    RP = 0;
    LD = 1;
    RD = 1;
    wCnt = 0;
    break;
  default:
    LP = 0;
    RP = 0;
    LD = 1;
    RD = 1;
  }
  Move(LP,LD,RP,RD);
}


此为蓝牙小车的源程序,Android App 也是自己开发,跟帖提问随问随答。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-15 00:48 , Processed in 0.038413 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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