查看原文
其他

干货|手把手教你自制轮式机器人

缪宇飏 果果小师弟 2022-07-15

击上方“果果小师弟”,选择“置顶/星标公众号

干货福利,第一时间送达!

摘要:制作这个项目的起因是大一下学期那会儿我通过学校图书馆里的《无线电》杂志开始接触Raspberry Pi卡片式计算机和Arduino微控制器,其中Raspberry Pi给当初什么都不懂的我留下了非常深刻的印象:一个信用卡大小的板子竟然可以跑带有图形界面的GNU/Linux操作系统

在强烈探索欲的驱使下,我从网上购买了两块Element14的Raspberry Pi一代Model B(现在早已经绝版了)板子以及其他相关配件,开始在Raspbian系统上自学Python和各种传感器的使用方法,后来为了检验一下自己的学习成果,于是我便花费几周的时间做了这个简单的轮式机器人。虽然它涉及的原理并不复杂,但是对于那会儿刚开始接触嵌入式的我来说,能成功搭建一个完整的机器人系统还是挺有挑战性的。

概述

简单轮式机器人其实是一个比较传统的入门级智能小车,它拥有蓝牙远程遥控、超声波避障、红外边缘检测和红外巡线(未完成)等功能,可以完成一些有趣的小实验。此外,简单轮式机器人的软件是开源的,具体代码可以从我的GitHub仓库上获得。

原理

硬件

以下是该简单轮式机器人的硬件系统连接图:

核心主控

系统的硬件核心主控分别为Arduino和Raspberry Pi。其中Arduino主要负责接收红外光电测距模块的数据,并控制装有超声波模块的单轴舵机云台的旋转;而Raspberry Pi则可通过电机驱动模块来完成对四个直流减速电机转向和转速的控制,此外它还能接收超声波模块和从Arduino串口发送上来的红外光电测距模块的数据来判断当前机器人的前方和两侧是否遇到障碍物,若机器人与障碍物之间的距离小于一个特定的阈值,则Arduino和Raspberry Pi会分别改变LED的颜色并启动蜂鸣器来发出警报。

当然,肯定会有人问:为什么我不能仅用Raspberry Pi来作为机器人的核心主控,非要再用一个Arduino呢?其实根据本项目的实际需求,确实只用一个Raspberry Pi就够了,不过对于我来说使用Arduino主要出于以下三个原因的考虑:

Raspberry Pi一代Model B板子的GPIO引脚数量只有26个,就算复用一些带有特殊功能的引脚,引脚资源依旧比较紧张。

Raspberry Pi官方提供的GPIO库虽然含有PWM函数,但是实际在控制舵机的时候可能是由于软件模拟的PWM方波还不够稳定,导致舵机抖动得比较厉害。

可以学习Python的串口编程。

因此,综合以上三个方面我选择了Arduino和Raspberry Pi双核心主控的系统架构。

外部电源

因为时间比较紧张,所以我没有在电源管理上花费太多的功夫。对于Arduino,我使用的是能装下6个1.5V干电池的的电池盒给其供电,而对于Raspberry Pi耗电量较大的需求,我是从大学舍友那借了一个充电宝来解决问题的,不过虽然供电可以了,但是由于充电宝的重量比较大,导致四个轮子受压偏大,使得遥控的精准度受到了一定的影响。

电机驱动

机器人的电机驱动部分采用传统的L293D芯片,它是一款单片集成的高电压、高电流、四通道电机驱动芯片,其内部包含有两个双极型H桥电路,可通过设置IN1和IN2输入引脚的逻辑电平来控制电机的旋转方向,而EN使能引脚可连接到一路PWM上,通过调整PWM方波的占空比便可调整电机的转速。

数据感知

为了能实现最基本的避障功能,我们需要为机器人配备有一些传感器。这里我使用的传感器为HC-SR04超声波测距模块和红外光电避障模块,其中红外光电避障模块具有一对红外线发射与接收管,运行时发射管会发射出一定频率的红外线,当检测方向遇到障碍物后,红外线会反射回来被接收管接收,经过比较电路处理之后,信号输出接口会输出一个低电平信号,这样只要在程序中对该接口的电平进行判断便能得知机器人是否距离障碍物比较近。

与红外光电避障模块的工作原理类似,超声波模块能够向空中发射超声波信号,当其检测到反射回来的信号后,只需将超声波从发射到接收所用的时间乘上声速再除以二便能得到机器人和障碍物之间的距离,从而为之后的机器人避障做好准备。

软件

Raspberry Pi库代码

simple_wheeled_robot_lib.py

该库代码实现了GPIO引脚初始化函数、LED灯设置函数、蜂鸣器设置函数、电机控制函数、超声波测距函数和LCD1602显示函数,其中LCD1602显示函数调用了Python的SMBUS库来完成IIC数据通信,从而能将字符串显示在屏幕上(注意:SMBUS和IIC协议之间是存在区别的,但在Raspberry Pi上两者概念基本等同)。

import time
import smbus
import RPi.GPIO as gpio

motor_run_left        = 17
motor_run_right       = 10
motor_direction_left  = 4
motor_direction_right = 25
led_left              = 7
led_right             = 8
ultrasonic_trig       = 23
ultrasonic_echo       = 24
servo                 = 11
buzzer                = 18
lcd_address           = 0x27
data_bus = smbus.SMBus(1)

class SimpleWheeledRobot:
   def __init__(self):
       gpio.setmode(gpio.BCM)
       gpio.setup(motor_run_left, gpio.OUT)
       gpio.setup(motor_run_right, gpio.OUT)
       gpio.setup(motor_direction_left, gpio.OUT)
       gpio.setup(motor_direction_right, gpio.OUT)
       gpio.setup(led_left, gpio.OUT)
       gpio.setup(led_right, gpio.OUT)

   def set_motors(self, run_left, direction_left, run_right, direction_right):
       gpio.output(motor_run_left, run_left)
       gpio.output(motor_run_right, run_right)
       gpio.output(motor_direction_left, direction_left)
       gpio.output(motor_direction_right, direction_right)

   def set_led_left(self, state):
       gpio.output(led_left, state)

   def set_led_right(self, state):
       gpio.output(led_right, state)

   def go_forward(self, seconds):
       if seconds == 0:
           self.set_motors(1111)
           self.set_led_left(1)
           self.set_led_right(1)
       else:
           self.set_motors(1111)
           time.sleep(seconds)
           gpio.cleanup()

   def go_reverse(self, seconds):
       if seconds == 0:
           self.set_motors(1010)
           self.set_led_left(0)
           self.set_led_right(0)
       else:
           self.set_motors(1010)
           time.sleep(seconds)
           gpio.cleanup()

   def go_left(self, seconds):
       if seconds == 0:
           self.set_motors(0011)
           self.set_led_left(1)
           self.set_led_right(0)
       else:
           self.set_motors(0011)
           time.sleep(seconds)
           gpio.cleanup()

   def go_right(self, seconds):
       if seconds == 0:
           self.set_motors(1100)
           self.set_led_left(0)
           self.set_led_right(1)
       else:
           self.set_motors(1100)
           time.sleep(seconds)
           gpio.cleanup()

   def go_pivot_left(self, seconds):
       if seconds == 0:
           self.set_motors(1011)
           self.set_led_left(1)
           self.set_led_right(0)
       else:
           self.set_motors(1011)
           time.sleep(seconds)
           gpio.cleanup()

   def go_pivot_right(self, seconds):
       if seconds == 0:
           self.set_motors(1110)
           self.set_led_left(0)
           self.set_led_right(1)
       else:
           self.set_motors(1110)
           time.sleep(seconds)
           gpio.cleanup()

   def stop(self):
       self.set_motors(0000)
       self.set_led_left(0)
       self.set_led_right(0)

   def buzzing(self):
       gpio.setup(buzzer, gpio.OUT)
       gpio.output(buzzer, True)
       for x in range(5):
           gpio.output(buzzer, False)
           time.sleep(0.1)
           gpio.output(buzzer, True)
           time.sleep(0.1)

   def get_distance(self):
       gpio.setmode(gpio.BCM)
       gpio.setup(ultrasonic_trig, gpio.OUT)
       gpio.setup(ultrasonic_echo, gpio.IN)
       gpio.output(ultrasonic_trig, False)
       while gpio.input(ultrasonic_echo) == 0:
           start_time = time.time()
       while gpio.input(ultrasonic_echo) == 1:
           stop_time = time.time()
       duration = stop_time - start_time
       distance = (duration * 34300) / 2
       gpio.cleanup()
       return distance

   def send_command(self, command):
       buf = command & 0xF0
       buf |= 0x04
       data_bus.write_byte(lcd_address, buf)
       time.sleep(0.002)
       buf &= 0xFB
       data_bus.write_byte(lcd_address, buf)
       buf = (command & 0x0F) << 4
       buf |= 0x04
       data_bus.write_byte(lcd_address, buf)
       time.sleep(0.002)
       buf &= 0xFB
       data_bus.write_byte(lcd_address, buf)

   def send_data(self, data):
       buf = data & 0xF0
       buf |= 0x05
       data_bus.write_byte(lcd_address, buf)
       time.sleep(0.002)
       buf &= 0xFB
       data_bus.write_byte(lcd_address, buf)
       buf = (data & 0x0F) << 4
       buf |= 0x05
       data_bus.write_byte(lcd_address, buf)
       time.sleep(0.002)
       buf &= 0xFB
       data_bus.write_byte(lcd_address, buf)

   def initialize_lcd(self):
       try:
           self.send_command(0x33)
           time.sleep(0.005)
           self.send_command(0x32)
           time.sleep(0.005)
           self.send_command(0x28)
           time.sleep(0.005)
           self.send_command(0x0C)
           time.sleep(0.005)
           self.send_command(0x01)
       except:
           return False
       else:
           return True

   def clear_lcd(self):
       self.send_command(0x01)

   def print_lcd(self, x, y, lcd_string):
       if x < 0:
           x = 0
       if x > 15:
           x = 15
       if y < 0:
           y = 0
       if y > 1:
           y = 1
       address = 0x80 + 0x40 * y + x
       self.send_command(address)
       for lcd_char in lcd_string:
           self.send_data(ord(lcd_char))

   def move_servo_left(self):
       servo_range = 13
       gpio.setmode(gpio.BCM)
       gpio.setup(servo, gpio.OUT)
       pwm = gpio.PWM(servo, 100)
       pwm.start(0)
       while servo_range <= 23:
           pwm.ChangeDutyCycle(servo_range)
           servo_range += 1
           time.sleep(0.5)
       pwm.stop()

   def move_servo_right(self):
       servo_range = 13
       gpio.setmode(gpio.BCM)
       gpio.setup(servo, gpio.OUT)
       pwm = gpio.PWM(servo, 100)
       pwm.start(0)
       while servo_range >= 0:
           pwm.ChangeDutyCycle(servo_range)
           servo_range -= 1
           time.sleep(0.5)
       pwm.stop()

Raspberry Pi测试代码1

simple_wheeled_robot_run_1.py

该代码调用了上面自己编写的机器人代码库,主要实现了超声波距离检测函数和键盘遥控函数,其中键盘遥控函数里面又根据所按按键的不同调用并组合上面代码库中的不同函数来完成某些特定的功能(比如机器人遇到障碍物后首先会发出警报,然后再进行相应的规避运动等)。

import time
import serial
import random
import Tkinter as tk
import RPi.gpio as gpio
from simple_wheeled_robot_lib import SimpleWheeledRobot

simple_wheeled_robot = SimpleWheeledRobot()
simple_wheeled_robot.initialize_lcd()
port = "/dev/ttyUSB0"
serial_to_arduino = serial.Serial(port, 9600)
serial_from_arduino = serial.Serial(port, 9600)
serial_from_arduino.flushInput()
serial_to_arduino.write('n')

def detecte_distance():
    distance = simple_wheeled_robot.get_distance()

    if distance >= 20:
        # Light up the green led.
        serial_to_arduino.write('g')
    elif distance >= 10:
        # Light up the yellow led.
        serial_to_arduino.write('y')
    elif distance < 10:
        # Light up the red led.
        serial_to_arduino.write('r')
        simple_wheeled_robot.buzzing()
        simple_wheeled_robot.__init__()
        simple_wheeled_robot.go_reverse(2)
        simple_wheeled_robot.__init__()
        simple_wheeled_robot.go_pivot_right(2)

    # Check the distance between wall and car's both sides.
    serial_to_arduino.write('k')
    data_from_arduino = serial_from_arduino.readline()
    data_from_arduino_int = int(data_from_arduino)

    # Car is too close to the left wall.
    if data_from_arduino_int == 01:
        simple_wheeled_robot.buzzing()
        simple_wheeled_robot.__init__()
        simple_wheeled_robot.go_right(2)
    # Car is too close to the right wall.
    elif data_from_arduino_int == 10:
        simple_wheeled_robot.buzzing()
        simple_wheeled_robot.__init__()
        simple_wheeled_robot.go_left(2)

def input_key(event):
    simple_wheeled_robot.__init__()
    print 'Key', event.char
    key_press = event.char
    seconds = 0.05

    if key_press.lower() == 'w':
        simple_wheeled_robot.go_forward(seconds)
    elif key_press.lower() == 's':
        simple_wheeled_robot.go_reverse(seconds)
    elif key_press.lower() == 'a':
        simple_wheeled_robot.go_left(seconds)
    elif key_press.lower() == 'd':
        simple_wheeled_robot.go_right(seconds)
    elif key_press.lower() == 'q':
        simple_wheeled_robot.go_pivot_left(seconds)
    elif key_press.lower() == 'e':
        simple_wheeled_robot.go_pivot_right(seconds)
    elif key_press.lower() == 'o':
        gpio.cleanup()
        # Move the servo in forward directory.
        serial_to_arduino.write('o')
        time.sleep(0.05)
    elif key_press.lower() == 'h':
        gpio.cleanup()
        # Light up the logo.
        serial_to_arduino.write('h')
    elif key_press.lower() == 'j':
        gpio.cleanup()
        # Turn off the logo.
        serial_to_arduino.write('j')
    elif key_press.lower() == 'p':
        gpio.cleanup()
        # Move the servo in reverse directory.
        serial_to_arduino.write('p')
        time.sleep(0.05)
    elif key_press.lower() == 'i':
        gpio.cleanup()
        serial_to_arduino.write('m')
        # Enter the random run mode.
        serial_to_arduino.write('i')
        for z in range(20):
            x = random.randrange(05)
            if x == 0:
                for y in range(30):
                    detecte_distance()
                    simple_wheeled_robot.__init__()
                    simple_wheeled_robot.go_forward(0.05)
            elif x == 1:
                for y in range(30):
                    detecte_distance()
                    simple_wheeled_robot.__init__()
                    simple_wheeled_robot.go_left(0.05)
            elif x == 2:
                for y in range(30):
                    detecte_distance()
                    simple_wheeled_robot.__init__()
                    simple_wheeled_robot.go_right(0.05)
            elif x == 3:
                for y in range(30):
                    detecte_distance()
                    simple_wheeled_robot.__init__()
                    simple_wheeled_robot.go_pivot_left(0.05)
            elif x == 4:
                for y in range(30):
                    detecte_distance()
                    simple_wheeled_robot.__init__()
                    simple_wheeled_robot.go_pivot_right(0.05)

            data_from_arduino = serial_from_arduino.readline()
            data_from_arduino_int = int(data_from_arduino)

            if data_from_arduino_int == 1111:
                simple_wheeled_robot.__init__()
                simple_wheeled_robot.go_forward(0.05)
                if data_from_arduino_int == 1111:
                    simple_wheeled_robot.__init__()
                    simple_wheeled_robot.stop()
                elif data_from_arduino_int == 0000:
                    simple_wheeled_robot.__init__()
                    simple_wheeled_robot.go_forward(0.05)
                elif data_from_arduino_int == 0100:
                    simple_wheeled_robot.__init__()
                    simple_wheeled_robot.go_left(0.05)
                elif data_from_arduino_int == 1000 or \
                     data_from_arduino_int == 1100:
                    simple_wheeled_robot.__init__()
                    simple_wheeled_robot.go_left(0.08)
                elif data_from_arduino_int == 0010:
                    simple_wheeled_robot.__init__()
                    simple_wheeled_robot.go_right(0.05)
                elif data_from_arduino_int == 0001 or \
                     data_from_arduino_int == 0011:
                    simple_wheeled_robot.__init__()
                    simple_wheeled_robot.go_right(0.08)

        serial_to_arduino.write('l')

    elif key_press.lower() == 'u':
        gpio.cleanup()
        simple_wheeled_robot.print_lcd(10'UltrasonicWare')
        simple_wheeled_robot.print_lcd(11'Distance:%.lf CM' %
                                              simple_wheeled_robot.get_distance())
    else:
        pass

    distance = simple_wheeled_robot.get_distance()

    if distance >= 20:
        serial_to_arduino.write('g')
    elif distance >= 10:
        serial_to_arduino.write('y')
    elif distance < 10:
        serial_to_arduino.write('r')
        simple_wheeled_robot.buzzing()
        simple_wheeled_robot.__init__()
        simple_wheeled_robot.go_reverse(2)

    serial_to_arduino.write('k')
    data_from_arduino = serial_from_arduino.readline()
    data_from_arduino_int = int(data_from_arduino)

    if data_from_arduino_int == 1:
        simple_wheeled_robot.buzzing()
        simple_wheeled_robot.__init__()
        simple_wheeled_robot.go_right(2)
    elif data_from_arduino_int == 10:
        simple_wheeled_robot.buzzing()
        simple_wheeled_robot.__init__()
        simple_wheeled_robot.go_left(2)

try:
    command = tk.Tk()
    command.bind('<KeyPress>', input_key)
    command.mainloop()
except KeyboardInterrupt:
    gpio.cleanup()

Raspberry Pi测试代码2

simple_wheeled_robot_run_2.py

该代码实现的功能比较简单,仅测试了机器人的电机遥控和超声波避障两个功能。

import Tkinter as tk
import RPi.GPIO as gpio
from simple_wheeled_robot_lib import SimpleWheeledRobot

simple_wheeled_robot = SimpleWheeledRobot()
simple_wheeled_robot.initialize_lcd()

def input_key(event):
    print 'Key', event.char
    key_press = event.char
    seconds = 0.05

    if key_press.lower() == 'w':
        simple_wheeled_robot.go_forward(seconds)
    elif key_press.lower() == 's':
        simple_wheeled_robot.go_reverse(seconds)
    elif key_press.lower() == 'a':
        simple_wheeled_robot.go_left(seconds)
    elif key_press.lower() == 'd':
        simple_wheeled_robot.go_right(seconds)
    elif key_press.lower() == 'q':
        simple_wheeled_robot.go_pivot_left(seconds)
    elif key_press.lower() == 'e':
        simple_wheeled_robot.go_pivot_right(seconds)
    elif key_press.lower() == 'o':
        simple_wheeled_robot.move_servo_left()
    elif key_press.lower() == 'p':
        simple_wheeled_robot.move_servo_right()
    else:
        pass

    distance = simple_wheeled_robot.get_distance()
    simple_wheeled_robot.print_lcd(10'UltrasonicWare')
    simple_wheeled_robot.print_lcd(11'Distance:%.lf CM' % distance)
    print "Distance: %.1f CM" % distance

    if distance < 10:
        simple_wheeled_robot.__init__()
        simple_wheeled_robot.go_reverse(2)

try:
    command = tk.Tk()
    command.bind('<KeyPress>', input_key)
    command.mainloop()
except KeyboardInterrupt:
    gpio.cleanup()

Raspberry Pi测试代码3

simple_wheeled_robot_run_3.py

该代码实现的功能与上面的测试代码2类似,只不过图形界面本代码里使用的是Pygame而不是之前的Tkinter。

import sys
import pygame
from pygame.locals import *
import RPi.GPIO as gpio
from simple_wheeled_robot_lib import SimpleWheeledRobot

simple_wheeled_robot = SimpleWheeledRobot()

pygame.init()
screen = pygame.display.set_mode((800800))
font = pygame.font.SysFont("arial"64)
pygame.display.set_caption('SimpleWheeledRobot')
pygame.mouse.set_visible(0)

while True:
   gpio.cleanup()
   for event in pygame.event.get():
       if event.type == QUIT:
           sys.exit()
       if event.type == KEYDOWN:
           time = 0.03
       if event.key == K_UP or event.key == ord('w'):
           simple_wheeled_robot.go_forward(time)
       elif event.key == K_DOWN or event.key == ord('s'):
           simple_wheeled_robot.go_reverse(time)
       elif event.key == K_LEFT or event.key == ord('a'):
           simple_wheeled_robot.go_left(time)
       elif event.key == K_RIGHT or event.key == ord('d'):
           simple_wheeled_robot.go_right(time)
       elif event.key == ord('q'):
           simple_wheeled_robot.go_pivot_left(time)
       elif event.key == ord('e'):
           simple_wheeled_robot.go_pivot_right(time)

Arduino测试代码

simple_wheeled_robot.ino

该代码从逻辑上比较好理解,在setup()函数初始化引脚的模式和串口波特率后,主函数loop()会不断地从串口中读取字符数据,并根据字符的不同进行不同的处理工作。

int      distance;
int      distance_left;
int      distance_right;
int      motor_value;
int      motor_value_a;
int      motor_value_b;
int      motor_value_c;
int      motor_value_d;
int      motor_a               = 6;
int      motor_b               = 7;
int      motor_c               = 8;
int      motor_d               = 9;
int      servo                 = 5;
int      led                   = 2;
int      led_red               = 13;
int      led_yellow            = 12;
int      led_green             = 11;
int      distance_sensor_left  = 3;
int      distance_sensor_right = 4;
char     data;
uint16_t angle                 = 1500;

void setup()
{
  // Set serial's baud rate.
  Serial.begin(9600);
  pinMode(motor_a, INPUT);
  pinMode(motor_b, INPUT);
  pinMode(motor_c, INPUT);
  pinMode(motor_d, INPUT);
  pinMode(servo, OUTPUT);
  pinMode(led , OUTPUT);
  pinMode(led_red, OUTPUT);
  pinMode(led_yellow, OUTPUT);
  pinMode(led_green, OUTPUT);
  pinMode(distance_sensor_left, INPUT);
  pinMode(distance_sensor_right, INPUT);
  pinMode(A0, OUTPUT);
  pinMode(A1, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  pinMode(A4, OUTPUT);
  pinMode(A5, OUTPUT);
}

void loop()
{
  if (Serial.available()) {
      switch(Serial.read()) {
          // Light up the logo.
          case 'h': {
              digitalWrite(A0, HIGH);
              digitalWrite(A1, HIGH);
              digitalWrite(A2, HIGH);
              digitalWrite(A3, HIGH);
              digitalWrite(A4, HIGH);
              digitalWrite(A5, HIGH);
              break;
          }
          // Turn off the logo.
          case 'j': {
              digitalWrite(A0, LOW);
              digitalWrite(A1, LOW);
              digitalWrite(A2, LOW);
              digitalWrite(A3, LOW);
              digitalWrite(A4, LOW);
              digitalWrite(A5, LOW);
              break;
          }
          // Move the servo in forward directory.
          case 'o' : {
              angle += 50;
              if (angle > 2500) {
                  angle = 2500;
              }
              break;
          }
          // Move the servo in reverse directory.
          case 'p' : {
              angle -= 50;
              if (angle < 500) {
                  angle = 500;
              }
              break;
          }
          case 'n': {
              digitalWrite(led, HIGH);
              break;
          }
          case 'm': {
              digitalWrite(led, LOW);
              break;
          }
          case 'g': {
              // When the distance between objects and car is far enough,
              // light the green led.
              digitalWrite(led_green, HIGH);
              digitalWrite(led_yellow, LOW);
              digitalWrite(led_red, LOW);
              break;
          }
          case 'y': {
              // When the distance between objects and car is near enough,
              // light the yellow led.
              digitalWrite(led_yellow, HIGH);
              digitalWrite(led_green, LOW);
              digitalWrite(led_red, LOW);
              break;
          }
          case 'r': {
              // When the distance between objects and car is very near,
              // light the red led.
              digitalWrite(led_red, HIGH);
              digitalWrite(led_yellow, LOW);
              digitalWrite(led_green, LOW);
              break;
          }
          case 'k': {
              // Return distance sensor's state between objects and car.
              distance_left = digitalRead(distance_sensor_left);
              distance_right = digitalRead(distance_sensor_right);
              distance = distance_left * 10 + distance_right ;
              Serial.println(distance, DEC);
              break;
          }
          case 'i': {
              while (1) {
                  // Return motor's state to raspberry pi.
                  motor_value_a = digitalRead(motor_a);
                  motor_value_b = digitalRead(motor_b);
                  motor_value_c = digitalRead(motor_c);
                  motor_value_d = digitalRead(motor_d);
                  motor_value = motor_value_a * 1000 + motor_value_b * 100 +
                      motor_value_c * 10 + motor_value_d;
                  Serial.println(motor_value, DEC);
                  delay(1000);
                  data = Serial.read();
                  if (data == 'l') {
                      break;
                  }
              }
          }
          default:
              break;
      }
  }
  // Delay enough time for servo to move position.
  digitalWrite(servo, HIGH);
  delayMicroseconds(angle);
  digitalWrite(servo, LOW);
  delay(15);
}

成果

以下是制作完成后的成果图和测试视频:

总结

这个简单轮式机器人是大一那会儿我对自己课外所学知识的一个应用。虽然现在回过头再来看自己当初做的项目,感觉技术原理非常简单,远没有我之后研究的ROS和MoveIt!那么复杂,但是通过整个制作过程,我学会了如何根据项目需求去网上购买相关的材料,如何将主控等硬件设备安装在机器人机械结构最合理的位置上,如何使用IDE编写Arduino程序,如何在Raspberry Pi上使用Python语言来读取硬件数据并控制硬件,如何实现简单的串口通信等等。我一直认为兴趣是最好的老师,当你开始接触一个全新的领域时,兴趣可以成为你克服各种困难并鼓舞你前进的强大动力。当然,除了兴趣,更重要的是亲自动手实践,书上的东西讲得再好也是别人的,不是你的,就算重复造轮子也有着其无法替代的重要意义,因为并不是每个人都能造得出轮子,通过学习并实践前人所学习过的知识,你会收获别人不会有的宝贵经验!

最后,个人认为智能小车对于广大刚开始接触机器人的初学者来说确实是一个非常好的练手项目,你可以根据自己的喜好和技术水平的高低来定制属于你自己的智能小车,实现你想要的各种功能。总之,对于我来说,通过本次项目我开始真正喜欢上了嵌入式开发并逐渐走上了专业化的道路,每个人都应该有自己的梦想,那这个简单轮式机器人就是我梦想的起点,激励着我不断向前!当然,也希望大家能在制作机器人的道路上玩得开心并有所收获!


文章作者:缪宇飏,myyerrol  转载于:https://myyerrol.io/zh-cn/2018/05/15/diy_robots_1_simple_wheeled_robot/

End

推荐好文  点击蓝色字体即可跳转

【收藏】烂大街的ESP82666该咋玩
☞【鸡汤】一个普通人的大学四年
☞【干货】基于STM32的PS2遥控小车
☞【干货】手把手教你写一个安卓APP
☞【干货】手把手教你写单片机的指针

☞【干货】手把手教你写单片机的结构体

欢迎转发、留言、点赞、分享,感谢您的支持!

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存