正在上传图片(0/1)

CodeMaster第2次任务--用语音报数实现

 5
手机看帖 9 3325
       第二次任务相对比较易于实现,各位机甲大师们已经很快很好的实现了斐波那契数列的生成、识别和打印,自己也就不在重复了。
       本着大疆机甲大师“玩出名堂”的初衷,我考虑到能不能把生成的每个数字读出来呢?经过一番折腾,基本上实现了语音报数。以下分步骤进行详细解释,还真心希望小伙伴们不吝指出存在的不足、错误以及可以进一步完善提高的地方,在此先表示感谢了!

一、任务二介绍
    1.随机生成“1、2、3、4、5”中的任意两个数字,作为斐波那契数列的前两项(斐波那契数列:从第三项开始,当前项为前两项数字之和,即F(n)=F(n-1)+F(n-2))。要求:生成的两个初始随机数需要有明显的指示信号(灯光闪烁或者云台摆动等)提示数值是多少。
    2.根据上面产生的前两项生成斐波那契数列,要求最后一项小于100。
    3.按照下图,以产生的两个数字中较小的一个,作为S1机器人的第一个击打目标,较大的作为第二个击打目标,两个数的和作为第三个击打目标,此后的击打目标按照类似斐波那契数列的规律进行计算。举个栗子,如果初始的两个数分别是2和3,则以2作为第一个击打目标,第二个击打目标为3,2+3 =5作为第三个击打目标,3+5 = 8作为第四个击打目标,以此类推。大于10的击打目标数字,以分别击打(十位和个位)两个数字进行组合完成。例如,数字34,则先击打3后紧接着击打4完成(*请注意,此处有先后顺序);数字55,则连续击打5两次。每完成击打一个数字,需要有明显的提示信号(可自定义)。
    4.参照斐波那契数列的规律,依次击打完成100以内的数字,即被认为完成编程任务,完成任务者加5分。
     附:数字视觉标签下载地址,https://dl.djicdn.com/downloads/ ... _44pcs_15_15cm_upda
ted.pdf
用打印出来的图片由于反光少,S1识别效果更好
二、让机甲大师播放自定义的声音
     S1并没有开发自定义声音的播放功能,只能自己想办法了!能不能把 S1的扬声器接到树莓派、arduino等外围智能设备播放呢?.
      先拿手机试验一下……
     S1的扬声器接口是2.5mm的,需要一个2.5到3.5mm的转换接头,网上几块钱一个,买来接上手机播放音乐基本听不到声音!!!应该是输出功率小了,再找一个PAM8403超微型数字功放板(3W)进行放大,网上几块钱一个,焊接、连接后如下图。注意,S1的2.5mm接头不能全部插到底,否则声音效果不好,可能是左右声道的原因,具体也没搞清楚,还请不吝赐教啊。
      加上放大器后,把3.5mm接头插入树莓派,则可以用树莓派随意大声播放了!
      如何让S1控制树莓派播放特定声音呢?
      1.通信,没有开放!!pwm开放了,那么可以让树莓派GPIO口检测机甲大师的pwm口的高低电平实现简单的S1到树莓派的单向通信。利用5个pwm的高低电平实现2的5次共32种信号,树莓派根据不同的信号播放不同的声音,从而实现语音播报斐波那契数列。
      2.具体是通过树莓派3b+的BCM模式的第20/21/23/24/25号GPIO口连接pwm1-5,每秒检测一次各端口的电平状态。程序如下:
(1)树莓派段程序如下(配套的声音文件可以自己录制,只要是MP3格式就行,也可以微信找我要):
import RPi.GPIO as GPIO
import time
import os

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(20,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(21,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(23,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(24,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(25,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
time.sleep(0.5)

while True:   
    a=GPIO.input(20)
    b=GPIO.input(21)
    c=GPIO.input(23)
    d=GPIO.input(24)
    e=GPIO.input(25)   
   
    if a==1 and b==0 and c==0 and d==0 and e==0:
        os.system('mpg321 ./peiyin/1.mp3 &')
    elif a==0 and b==1 and c==0 and d==0 and e==0:
        os.system('mpg321 ./peiyin/2.mp3 &')
    elif a==1 and b==1 and c==0 and d==0 and e==0:
        os.system('mpg321 ./peiyin/3.mp3 &')
    elif a==0 and b==0 and c==1 and d==0 and e==0:
        os.system('mpg321 ./peiyin/4.mp3 &')
    elif a==1 and b==0 and c==1 and d==0 and e==0:
        os.system('mpg321 ./peiyin/5.mp3 &')   
    elif a==0 and b==1 and c==1 and d==0 and e==0:
        os.system('mpg321 ./peiyin/6.mp3 &')   
    elif a==1 and b==1 and c==1 and d==0 and e==0:
        os.system('mpg321 ./peiyin/7.mp3 &')   
    elif a==0 and b==0 and c==0 and d==1 and e==0:
        os.system('mpg321 ./peiyin/8.mp3 &')   
    elif a==1 and b==0 and c==0 and d==1 and e==0:
        os.system('mpg321 ./peiyin/9.mp3 &')   
    elif a==0 and b==1 and c==0 and d==1 and e==0:
        os.system('mpg321 ./peiyin/start.mp3 &')
    elif a==1 and b==1 and c==0 and d==1 and e==0:
        os.system('mpg321 ./peiyin/feibo.mp3 &')
    elif a==0 and b==0 and c==1 and d==1 and e==0:
        os.system('mpg321 ./peiyin/end.mp3 &')
    elif a==1 and b==0 and c==0 and d==0 and e==1:
        os.system('mpg321 ./peiyin/10.mp3 &')
    elif a==0 and b==1 and c==0 and d==0 and e==1:
        os.system('mpg321 ./peiyin/20.mp3 &')
    elif a==1 and b==1 and c==0 and d==0 and e==1:
        os.system('mpg321 ./peiyin/30.mp3 &')
    elif a==0 and b==0 and c==1 and d==0 and e==1:
        os.system('mpg321 ./peiyin/40.mp3 &')
    elif a==1 and b==0 and c==1 and d==0 and e==1:
        os.system('mpg321 ./peiyin/50.mp3 &')   
    elif a==0 and b==1 and c==1 and d==0 and e==1:
        os.system('mpg321 ./peiyin/60.mp3 &')   
    elif a==1 and b==1 and c==1 and d==0 and e==1:
        os.system('mpg321 ./peiyin/70.mp3 &')   
    elif a==0 and b==0 and c==0 and d==1 and e==1:
        os.system('mpg321 ./peiyin/80.mp3 &')   
    elif a==1 and b==0 and c==0 and d==1 and e==1:
        os.system('mpg321 ./peiyin/90.mp3 &')
    else:
        pass
   
    time.sleep(1)
(2)机甲大师端程序见后续介绍
机甲大师扬声器-2.5之3.5mm转接头-3w功放连接图
三、 任务实现
1.控制1-5号pwm输出不同的高低电平,实现与树莓派的单向通信
2.生成斐波那契数列,最大不超过100。
3.识别0-9十个标签,记录各标签的位置(使用了两种方法:一是使用识别并瞄准函数,这种方法对标签的质量要求较低,同等条件下可识别的标签在第二种方法中却不能被识别,缺点是速度慢;二是获取整体识别到的视觉标签信息,优点是速度快,缺点是需要将识别距离调为3m,根据光照条件适当调整曝光值为大或小,我在室内灯光条件下,设置为大曝光值,调整机甲大师的角度防止标签正好在反光的位置实现了10个标签的一次识别)。然后将标签的x、y值转换为云台的航向、俯仰角,从0-9存储到angleList列表中。需要注意的是对标签信息列表,通过index函数分别找到id为10-19的索引位置,将会与第一个10重复,需要先把第一个10值pop掉。
4.射击函数,从斐波那契数列中依次拿出一项,小于10时直接取出angleList中存储的航向、俯仰角,将云台调整到这个位置即可;大于10时通过整取、取余分别取出十位、个位按前方法调整云台位置即可。这里取余时有个BUG:千万不要用%取余符号,有%符号将导致存储的程序再次打开时就空白了,无论是存到云上还是本地、或是生成了dsp文件,统统不行!!可用以下变通方法进行取余:index01=b//10;index02=b-index01*10
1-5#pwm、地线接出图
pwm与树莓派gpio、地线连接图
运行时的接线图
FPV机甲大师自带录像的运行成功
运行中机甲大师状态录像
app调试截屏录像,关键看调试输出(注:与上面不是同一次运行,斐波那契数列不相同)
import random
angleList=RmList()
feiboList=RmList()
infoList=RmList()

#pwm输出同树莓派通信函数
def output_Pwm(num=0,flag=0):
    if num==0:
        chassis_ctrl.set_pwm_value(rm_define.pwm1,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm2,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm3,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm4,0)
        if flag==0:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
        else:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
    elif num==1:
        chassis_ctrl.set_pwm_value(rm_define.pwm1,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm2,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm3,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm4,0)
        if flag==0:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
        else:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
    elif num==2:
        chassis_ctrl.set_pwm_value(rm_define.pwm1,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm2,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm3,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm4,0)
        if flag==0:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
        else:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
    elif num==3:
        chassis_ctrl.set_pwm_value(rm_define.pwm1,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm2,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm3,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm4,0)
        if flag==0:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
        else:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
    elif num==4:
        chassis_ctrl.set_pwm_value(rm_define.pwm1,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm2,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm3,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm4,0)
        if flag==0:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
        else:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
    elif num==5:
        chassis_ctrl.set_pwm_value(rm_define.pwm1,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm2,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm3,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm4,0)
        if flag==0:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
        else:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
    elif num==6:
        chassis_ctrl.set_pwm_value(rm_define.pwm1,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm2,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm3,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm4,0)
        if flag==0:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
        else:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
    elif num==7:
        chassis_ctrl.set_pwm_value(rm_define.pwm1,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm2,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm3,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm4,0)
        if flag==0:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
        else:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
    elif num==8:
        chassis_ctrl.set_pwm_value(rm_define.pwm1,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm2,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm3,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm4,100)
        if flag==0:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
        else:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
    elif num==9:
        chassis_ctrl.set_pwm_value(rm_define.pwm1,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm2,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm3,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm4,100)
        if flag==0:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
        else:
            chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
    elif num==10:
        chassis_ctrl.set_pwm_value(rm_define.pwm1,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm2,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm3,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm4,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
    elif num==11:
        chassis_ctrl.set_pwm_value(rm_define.pwm1,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm2,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm3,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm4,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
    elif num==12:
        chassis_ctrl.set_pwm_value(rm_define.pwm1,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm2,0)
        chassis_ctrl.set_pwm_value(rm_define.pwm3,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm4,100)
        chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
    else:
        pass

#生成斐波那契数列
def make_Feibo():
    global feiboList
    feiboList.append(random.randint(1,5))
    feiboList.append(random.randint(1,5))
    output_Pwm(10,0)
    time.sleep(1)
    output_Pwm(0,0)
    time.sleep(2)
    output_Pwm(feiboList[1],0)
    time.sleep(1)
    output_Pwm(feiboList[2],0)
    time.sleep(1)
    output_Pwm(0,0)
    for i in range(3,12):
        a=feiboList[i-1]+feiboList[i-2]
        if a>100:break
        feiboList.append(a)
        
#存储云台航向、俯仰角函数
def storage_Angle():
    global angleList
    angleList.append(gimbal_ctrl.get_axis_angle(rm_define.gimbal_axis_yaw))
    angleList.append(gimbal_ctrl.get_axis_angle(rm_define.gimbal_axis_pitch))
   
#方法一:通过识别并瞄准函数获取0-9标签位置信息的函数
def detect_Marker_0to9_by_aim():
    vision_ctrl.enable_detection(rm_define.vision_detection_marker)
    vision_ctrl.set_marker_detection_distance(2)
    gimbal_ctrl.set_rotate_speed(180)
    #try to use the number of enum
    '''for i in range(10,20):
        vision_ctrl.detect_marker_and_aim(i)
        time.sleep(0.2)
        storage_Angle()
        gimbal_ctrl.angle_ctrl(0,0)'''
    vision_ctrl.detect_marker_and_aim(rm_define.marker_number_zero)
    time.sleep(0.2)
    storage_Angle()
    gimbal_ctrl.angle_ctrl(0,0)
    vision_ctrl.detect_marker_and_aim(rm_define.marker_number_one)
    time.sleep(0.2)
    storage_Angle()
    gimbal_ctrl.angle_ctrl(0,0)
    vision_ctrl.detect_marker_and_aim(rm_define.marker_number_two)
    time.sleep(0.2)
    storage_Angle()
    gimbal_ctrl.angle_ctrl(0,0)
    vision_ctrl.detect_marker_and_aim(rm_define.marker_number_three)
    time.sleep(0.2)
    storage_Angle()
    gimbal_ctrl.angle_ctrl(0,0)
    vision_ctrl.detect_marker_and_aim(rm_define.marker_number_four)
    time.sleep(0.2)
    storage_Angle()
    gimbal_ctrl.angle_ctrl(0,0)
    vision_ctrl.detect_marker_and_aim(rm_define.marker_number_five)
    time.sleep(0.2)
    storage_Angle()
    gimbal_ctrl.angle_ctrl(0,0)
    vision_ctrl.detect_marker_and_aim(rm_define.marker_number_six)
    time.sleep(0.2)
    storage_Angle()
    gimbal_ctrl.angle_ctrl(0,0)
    vision_ctrl.detect_marker_and_aim(rm_define.marker_number_seven)
    time.sleep(0.2)
    storage_Angle()
    gimbal_ctrl.angle_ctrl(0,0)
    vision_ctrl.detect_marker_and_aim(rm_define.marker_number_eight)
    time.sleep(0.2)
    storage_Angle()
    gimbal_ctrl.angle_ctrl(0,0)
    vision_ctrl.detect_marker_and_aim(rm_define.marker_number_nine)
    time.sleep(0.2)
    storage_Angle()
    gimbal_ctrl.angle_ctrl(0,0)

#方法二:通过一次整体识别函数获取0-9标签位置信息的函数   
def detect_Marker_0to9_by_info():
    global infoList
    global angleList
    vision_ctrl.enable_detection(rm_define.vision_detection_marker)
    vision_ctrl.set_marker_detection_distance(3)
    media_ctrl.exposure_value_update(rm_define.exposure_value_large)
    time.sleep(2)
    while len(infoList)!=51:
        infoList=RmList(vision_ctrl.get_marker_detection_info())
        time.sleep(1)
        media_ctrl.play_sound(rm_define.media_sound_scanning)        
    if len(infoList)==51:
        infoList.pop(1)
        for i in range(10,20):
            indexofi=infoList.index(i)
            angleList.append((infoList[indexofi+1]-0.5)*96)
            angleList.append((0.5-infoList[indexofi+2])*54)            

#射击函数  
def shoot():
    global feiboList
    global angleList
    global infoList
   
    output_Pwm(11,0)
    time.sleep(1)
    output_Pwm(0,0)
    time.sleep(2)
    for i in range(1,len(feiboList)+1):
        b=feiboList[ i ]        
        print(b)
        time.sleep(2)
        if b<10:
            gimbal_ctrl.angle_ctrl(angleList[b*2+1],angleList[b*2+2])
            led_ctrl.gun_led_on()
            output_Pwm(b,0)
            time.sleep(1)
            output_Pwm(0,0)
            led_ctrl.gun_led_off()
        else:
            index01=int(b//10)
            index02=b-index01*10
            gimbal_ctrl.angle_ctrl(angleList[index01*2+1],angleList[index01*2+2])
            output_Pwm(index01,1)
            led_ctrl.gun_led_on()
            time.sleep(1)
            output_Pwm(0,0)
            led_ctrl.gun_led_off()
            gimbal_ctrl.angle_ctrl(angleList[index02*2+1],angleList[index02*2+2])
            output_Pwm(index02,0)
            led_ctrl.gun_led_on()
            time.sleep(1)
            output_Pwm(0,0)
            led_ctrl.gun_led_off()
            
def start():
    global feiboList
    global angleList
    global infoList   
   
    media_ctrl.record(1)
    robot_ctrl.set_mode(rm_define.robot_mode_free)
    make_Feibo()
    print(feiboList)
    time.sleep(1)
    #detect_Marker_0to9_by_aim()
    detect_Marker_0to9_by_info()
    print(angleList)
    time.sleep(1)
    shoot()
    output_Pwm(12,0)
    time.sleep(1)
    output_Pwm(0,0)
    time.sleep(2)
    media_ctrl.record(0)
总结:基本实现了预期效果,但有两方面的缺点:一是为等待树莓派读数,主程序必须加sleep函数等待,造成整体看来比较迟钝;二是pwm输出和树莓派的输入不十分稳定,虽然设置了下拉电阻,但时不时的会有个别意外的信号被捕捉到,尚需改进。
不足之处欢迎批评指正,交流学习!!!微信号:cumtzd
评论
上传
你需要登录之后才能回帖    登录 | 注册
benq  Mavic 2 Pro认证用户 2019-9-28 3#
学习了
boolrobot  机甲大师 RoboMaster S1认证用户 2019-9-28 4#
大神
CPYCPY  Mavic Mini认证用户 2019-9-28 5#
bakedkids  机甲大师 RoboMaster S1认证用户 2019-9-28 6#
多面大神!
Alfred888  Mavic Air 2认证用户 2019-9-29 7#
这个很有意思
g1107  Osmo Mobile 3认证用户 2019-9-29 8#
厉害
scratch   2019-9-29 9#
是矿大的同学吗?
楼主  机甲大师 RoboMaster S1认证用户 2019-9-29 10#
scratch9-29 09:33
是矿大的同学吗?
是啊02级的
哆来咪  机甲大师 RoboMaster S1认证用户 2019-10-5 11#
高阶玩家
取消 点赞 评论
分享至:
回复:
上传
取消 评论
快速回复 返回顶部 返回列表