微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 第四篇?Rico Board测量前方任意角度的距离

第四篇?Rico Board测量前方任意角度的距离

时间:10-02 整理:3721RD 点击:
在上篇舵机的基础上,添加了超声波雷达测距模块,并融合到了舵机的驱动中。主要实现功能,通过舵机调整前方180度的任意方向,然后,读取该方向到障碍物的距离。先普及下雷达测距原理:


上图,为我的驱动编写提供了基础
先罗列下我的前期调试过程,主要是在雷达反射波的中断处,关键代码如下:


正常调试过程的debug输出:


接下来就是完整的测距代码了。
代码如下:

  1. /**
  2. * [url=home.php?mod=space&uid=1455510]@file[/url]   motor.c
  3. * [url=home.php?mod=space&uid=40524]@author[/url] yang yongsheng
  4. * @date   2016.11.2
  5. */

  6. #include
  7. #include
  8. #include
  9. #include                  // Required for the GPIO functions
  10. #include
  11. #include
  12. #include
  13. #include
  14. #include
  15. #include
  16. #include
  17. #include
  18. #include
  19. #include

  20. #define NAME_LEN 16

  21. /*gpio5_8*/
  22. //#define MOTOR_GPIO_NUM 168

  23. #define RADAR_TIME_SCALE 1000

  24. /*gpio5_9*/
  25. #define LED_GPIO_NUM 169


  26. #define MOTOR_NUM 1
  27. #define MOTOR_NAME "rico_lan motor"

  28. #define MOTOR_MAJOR 0
  29. static int motor_major = MOTOR_MAJOR;
  30. static dev_t motor_dev_num;
  31. int motor_gpio[MOTOR_NUM] = {113};
  32. int trig_gpio[MOTOR_NUM] = {110};
  33. int echo_gpio[MOTOR_NUM] = {111};



  34. MODULE_LICENSE("GPL");
  35. MODULE_AUTHOR("yang yongsheng ");
  36. MODULE_VERSION("0.1");

  37. struct motor_dev{
  38.         struct cdev cdev;
  39.         int num;//舵机引脚
  40.         int trig_num;//雷达触发引脚
  41.         int echo_num;//雷达接受引脚
  42.         unsigned int radar_time;//雷达时间
  43.         unsigned int pwm_value_us;//舵机高脉冲时间
  44.         unsigned int echo_irq_num;
  45.         struct hrtimer radar_hrt;
  46.         struct hrtimer hrt;
  47.         struct semaphore radar_sem;
  48.         char name[NAME_LEN];
  49.         bool pwm_state;
  50.         bool hrt_state;
  51.         bool radar_hrt_state;
  52. } *motor_devp;

  53. struct class *motor_class;



  54. static enum hrtimer_restart motor_hrtimer_callback(struct hrtimer *hrt)
  55. {
  56.         struct motor_dev *devp_tmp;
  57.         devp_tmp = container_of(hrt, struct motor_dev, hrt);
  58.         devp_tmp->pwm_state = !devp_tmp->pwm_state;
  59.         gpio_set_value(devp_tmp->num, devp_tmp->pwm_state);
  60.         if(devp_tmp->pwm_state == false)
  61.         hrtimer_forward_now(hrt, ns_to_ktime((20000-devp_tmp->pwm_value_us)*1000));//T=20,000ns
  62.         else if(devp_tmp->pwm_state == true)
  63.         hrtimer_forward_now(hrt, ns_to_ktime((devp_tmp->pwm_value_us) * 1000));//T=20,000ns
  64.         return HRTIMER_RESTART;
  65. }

  66. static enum hrtimer_restart radar_hrtimer_callback(struct hrtimer *hrt)
  67. {
  68.         struct motor_dev *devp_tmp;
  69.         devp_tmp = container_of(hrt, struct motor_dev, radar_hrt);
  70.         (devp_tmp->radar_time)++;
  71.         hrtimer_forward_now(hrt, ns_to_ktime(RADAR_TIME_SCALE));
  72.         return HRTIMER_RESTART;
  73. }

  74. irqreturn_t radar_echo_interrupt(int irq, void *dev_id)
  75. {
  76.         struct motor_dev *devp_tmp = (struct motor_dev *)dev_id;
  77.         if (gpio_get_value(devp_tmp->echo_num))//上升沿触发               
  78.         {
  79.                 if(!down_trylock(&devp_tmp->radar_sem))
  80.                 {
  81.                 hrtimer_init(&devp_tmp->radar_hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
  82.                 devp_tmp->radar_hrt.function = radar_hrtimer_callback;
  83.                 devp_tmp->radar_time = 0;
  84.                 hrtimer_start(&devp_tmp->radar_hrt, ns_to_ktime(RADAR_TIME_SCALE), HRTIMER_MODE_REL);
  85.                 devp_tmp->radar_hrt_state = false;
  86.                 }
  87.         }
  88.         else  if (!gpio_get_value(devp_tmp->echo_num))//下降沿触发
  89.         {       
  90.                 devp_tmp->radar_hrt_state = true;
  91.                 up(&devp_tmp->radar_sem);
  92.                 hrtimer_cancel(&devp_tmp->radar_hrt);
  93.         }
  94.         return IRQ_HANDLED;
  95. }

  96. int motor_open (struct inode *inode, struct file *filp)
  97. {
  98.         struct motor_dev *devp_tmp;
  99.         devp_tmp = container_of(inode->i_cdev, struct motor_dev, cdev);
  100.         filp->private_data = devp_tmp;
  101.         if(devp_tmp->hrt_state == false)
  102.         {
  103.                 hrtimer_init(&devp_tmp->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
  104.                 devp_tmp->hrt.function = motor_hrtimer_callback;
  105.                 gpio_set_value(devp_tmp->num, devp_tmp->pwm_state);
  106.                 hrtimer_start(&devp_tmp->hrt, ns_to_ktime(devp_tmp->pwm_value_us), HRTIMER_MODE_REL);       
  107.                 devp_tmp->hrt_state = true;
  108.                 devp_tmp->radar_hrt_state = false;
  109.         }
  110.         sema_init(&devp_tmp->radar_sem, 1);
  111.         printk(KERN_INFO "motor_open.\n");
  112.         return 0;
  113. }

  114. int motor_release (struct inode *inode, struct file *filp)
  115. {
  116.         struct motor_dev *devp_tmp;
  117.         devp_tmp = filp->private_data;
  118.         printk(KERN_INFO "motor_release and pwm_value_us is %d.\n", devp_tmp->pwm_value_us);
  119.         return 0;       
  120. }

  121. ssize_t motor_write (struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
  122. {
  123.         char pwm_value_tmp[8];
  124.         struct motor_dev *motor_devp_tmp = filp->private_data;
  125.         copy_from_user(pwm_value_tmp, buf, sizeof(buf));       
  126.         gpio_set_value(LED_GPIO_NUM        , motor_devp_tmp->pwm_state);       
  127.         motor_devp_tmp->pwm_value_us = simple_strtoul(pwm_value_tmp, NULL, 10);
  128.         if(motor_devp_tmp->pwm_value_us > 2500)
  129.                 motor_devp_tmp->pwm_value_us = 2500;
  130.         else if(motor_devp_tmp->pwm_value_us pwm_value_us = 500;
  131.         printk(KERN_INFO "pwm_value is %d.\n", motor_devp_tmp->pwm_value_us);
  132.         printk(KERN_INFO "motor_write.\n");
  133.         return count;
  134. }

  135. ssize_t radar_read (struct file *filp, char __user *buf, size_t count, loff_t *ppos)
  136. {
  137.         struct motor_dev *motor_devp_tmp = filp->private_data;
  138.         gpio_set_value(motor_devp_tmp->trig_num, false);
  139.         udelay(10);
  140.         gpio_set_value(motor_devp_tmp->trig_num, true);
  141.         udelay(100);
  142.         gpio_set_value(motor_devp_tmp->trig_num, false);
  143.         mdelay(10);
  144.         down(&motor_devp_tmp->radar_sem);
  145.         if(motor_devp_tmp->radar_hrt_state == true)
  146.                 printk(KERN_INFO "radar_read ente radar_timer is %dus and radar_len is %dmm.\n", motor_devp_tmp->radar_time, 34*(motor_devp_tmp->radar_time)/100);
  147.         up(&motor_devp_tmp->radar_sem);
  148.         return 0;
  149. }


  150. static struct file_operations motor_fops =
  151. {
  152.         .owner = THIS_MODULE,
  153.         .open = motor_open,
  154.         .release = motor_release,
  155.         .write = motor_write,
  156.         .read = radar_read,
  157. };

  158. int motor_setup(struct motor_dev *devp, int min, int num, int trig, int echo)
  159. {
  160.         int ret = 0;
  161.         sprintf(devp->name, "motor%d", min);       
  162.         if(!gpio_is_valid(num))
  163.         {
  164.                 printk(KERN_INFO "invalid motor%d_gpio_num:%d.\n",min, num);
  165.                 goto fail_num;
  166.         }
  167.         else
  168.         {
  169.         gpio_request(num, "sysfs");
  170.         gpio_direction_output(num, false);
  171.         gpio_export(num, false);        /*cause GPIO_NUM to appear in /sys/class/gpio*/
  172.         }
  173.         if(!gpio_is_valid(trig))
  174.         {
  175.                 printk(KERN_INFO "invalid motor%d_gpio_trig:%d.\n",min, trig);
  176.                 goto fail_trig;
  177.         }
  178.         else
  179.         {
  180.         gpio_request(trig,"sysfs");
  181.         gpio_direction_output(trig, false);
  182.         gpio_export(trig, false);
  183.         }
  184.         if(!gpio_is_valid(echo))
  185.         {
  186.                 printk(KERN_INFO "invalid motor%d_gpio_trig:%d.\n",min, trig);
  187.                 goto fail_echo;
  188.         }
  189.         else
  190.         {
  191.         gpio_request(echo,"sysfs");
  192.         gpio_direction_input(echo);
  193.         gpio_export(echo, false);
  194.         }
  195.         devp->num = num;
  196.         devp->trig_num = trig;
  197.         devp->echo_num = echo;
  198.         devp->pwm_value_us = 1500;//500~2500 us
  199.         devp->pwm_state = true;
  200.         devp->hrt_state = false;
  201.         devp->radar_hrt_state = false;
  202.         devp->echo_irq_num = gpio_to_irq(echo);
  203.         request_irq(devp->echo_irq_num, radar_echo_interrupt, IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, "radar_echo_handler", devp);
  204.         devp->cdev.owner = THIS_MODULE;
  205.         cdev_init(&devp->cdev, &motor_fops);
  206.         ret = cdev_add(&devp->cdev, MKDEV(motor_major, min), 1);
  207.         if(ret)
  208.         {
  209.                 printk(KERN_INFO "error %d adding motor%d.\n", ret, min);
  210.         }
  211.         else
  212.         {
  213.                 device_create(motor_class, NULL, MKDEV(motor_major, min), NULL,devp->name);
  214.         }
  215.         return 0;
  216. fail_echo:
  217.         gpio_unexport(trig);
  218. fail_trig:
  219.         gpio_unexport(num);
  220. fail_num:
  221.         return -ENODEV;
  222. }

  223. int __init motor_init(void)
  224. {
  225.         int ret,i;
  226.         printk(KERN_INFO "motor_init begin.\n");
  227.         if(!gpio_is_valid(LED_GPIO_NUM))
  228.         {
  229.                 printk(KERN_INFO "invalid LED_GPIO_NUM:%d.\n",LED_GPIO_NUM);
  230.                 return -ENODEV;
  231.         }

  232.         motor_devp = kzalloc(sizeof(struct motor_dev) * MOTOR_NUM, GFP_KERNEL);
  233.         if(IS_ERR(motor_devp))
  234.         {
  235.                 printk(KERN_INFO "no space for motor_dev.\n");
  236.                 return -ENOMEM;
  237.         }

  238.         motor_class = class_create(THIS_MODULE, MOTOR_NAME);

  239.         if(motor_major == 0)
  240.         {
  241.                 ret = alloc_chrdev_region(&motor_dev_num, 0, MOTOR_NUM, MOTOR_NAME);
  242.                 motor_major = MAJOR(motor_dev_num);
  243.         }
  244.         else
  245.         {
  246.                 motor_dev_num = MKDEV(motor_major, 0);
  247.                 ret = register_chrdev_region(motor_dev_num, MOTOR_NUM, MOTOR_NAME);
  248.         }
  249.         if(ret hrt);
  250.                 gpio_unexport((motor_devp+i)->num);
  251.                 gpio_free((motor_devp+i)->num);
  252.                 gpio_unexport((motor_devp+i)->trig_num);
  253.                 gpio_free((motor_devp+i)->trig_num);
  254.                 gpio_unexport((motor_devp+i)->echo_num);
  255.                 gpio_free((motor_devp+i)->echo_num);
  256.                 free_irq((motor_devp+i)->echo_irq_num, (motor_devp+i));
  257.                 device_destroy(motor_class,MKDEV(motor_major,i));
  258.                 cdev_del(&(motor_devp+i)->cdev);
  259.                 unregister_chrdev_region(MKDEV(motor_major, i), 1);
  260.                 kfree(motor_devp+i);
  261.         }

  262.        
  263.         gpio_unexport(LED_GPIO_NUM);
  264.         gpio_free(LED_GPIO_NUM);
  265.         class_destroy(motor_class);       
  266.        
  267.         printk(KERN_INFO "motor_exit finished.\n");
  268. }

  269. module_init(motor_init);
  270. module_exit(motor_exit);

复制代码

我选取了三个方向,现场图示如下:




它们依次对应的脉宽长度为1500us、1000us、2000us。
debug口的调试信息如下:


舵机加雷达的驱动调试告一段落,代码中关键的部分是我引入信号量来告知距离信息可用


Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top