×

平衡segway机器人开源项目

消耗积分:0 | 格式:zip | 大小:0.12 MB | 2022-11-18

分享资料个

描述

“Segbot”是 UIUC ME 461 级制造的平衡 segway 机器人。segbot 由 Dan Block (d-block@illinois.edu) 教授设计的电路板和 F28379D 微控制器组成,该微控制器是德州仪器 C2000 系列的一部分。该项目的目标是让 segbot 播放歌曲和舞蹈以响应检测到不同的音符。

音符检测

音符检测是使用模数转换完成的,将从麦克风接收到的模拟信号转换为数字值。没有占空比输出的脉宽调制被用作定时器,以 10 kHz 的采样率触发 ADC 中断。为了识别不同的频率,使用Goertzel 算法一次对 1000 个 ADC 值进行离散傅里叶变换。如果算法的输出超过某个阈值,则检测到音符。阈值是一个稍微随意的值,调整为在适当的时间做出响应,这意味着如果由于意外事件(例如落笔)而出现频率,则不会检测到音符。

// DFT with Goertzel Algorithm
float goertzel_mag(int numSamples,int TARGET_FREQUENCY,int SAMPLING_RATE, float* data)
{
    int     k,i;
    float   floatnumSamples;
    float   omega,sine,cosine,coeff,q0,q1,q2,magnitude,real,imag;

    float   scalingFactor = numSamples / 2.0;

    floatnumSamples = (float) numSamples;
    k = (int) (0.5 + ((floatnumSamples * TARGET_FREQUENCY) / SAMPLING_RATE));
    omega = (2.0 * PI * k) / floatnumSamples;
    sine = sin(omega);
    cosine = cos(omega);
    coeff = 2.0 * cosine;
    q0=0;
    q1=0;
    q2=0;

    for(i=0; i
    {
        q0 = coeff * q1 - q2 + data[i];
        q2 = q1;
        q1 = q0;
    }

    // calculate the real and imaginary results
    // scaling appropriately
    real = (q1 - q2 * cosine) / scalingFactor;
    imag = (q2 * sine) / scalingFactor;

    magnitude = sqrtf(real*real + imag*imag);
    return magnitude;
}

乒乓缓冲器

实现了一个乒乓缓冲器版本,以将 ADC 读数存储在单独的阵列中,这样一个可以收集数据,而另一个可以在 Goertzel 函数中执行计算。使用了三个这样的数组,以便 Goertzel 算法在检查对应于三种不同歌曲和舞蹈的三个单独音符之间交替。当检测到其中一个目标频率时,它会发出歌舞开始的信号。

//Use three-part "Ping-Pong" Buffer in ADC interrupt
//Ping
    if(PingPong == 0){
        adcb_arrayPing[adcbcount] = adcb0result; // add ADC reading to array
        if(adcbcount == (n_samples-1)){
            adcbcount = -1; //incremented to 0 at end of interrupt
            RunPing = 1; //check in while loop
            PingPong = 1; //switch to Pong buffer
        }
    }
    //Pong
    if(PingPong == 1){
        adcb_arrayPong[adcbcount] = adcb0result;
        if(adcbcount == (n_samples-1)){
            adcbcount = -1; //incremented to 0 at end of interrupt
            RunPong = 1;
            PingPong = 2; //switch to Dong buffer
        }
    }
    //Dong
    if(PingPong == 2){
        adcb_arrayDong[adcbcount] = adcb0result;
        if(adcbcount == (n_samples-1)){
            adcbcount = -1; //incremented to 0 at end of interrupt
            RunDong = 1;
            PingPong = 0; //switch to Ping buffer
        }
    }

// IDLE loop. Use to pass arrays through Goertzel fxn and check for note detection
    while(1)
    {
        //after n samples, pass data through Goertzel fxn
        // use Ping Pong buffer

        if(RunPing == 1){
            goer_result = goertzel_mag(n_samples,NOTE,sampling_rate, adcb_arrayPing);
            RunPing = 0;
            if(goer_result > thresh){
                note_detected = 1;
            }
        }
        if(RunPong == 1){
            goer_result2 = goertzel_mag(n_samples,NOTE2,sampling_rate, adcb_arrayPong);
            RunPong = 0;
            if(goer_result2 > thresh){
                note2_detected = 1;
            }
        }
        if(RunDong == 1){
            goer_result3 = goertzel_mag(n_samples,NOTE3,sampling_rate, adcb_arrayDong);
            RunDong = 0;
            if(goer_result3 > thresh){
                note3_detected = 1;
            }
        }

歌舞

为了让 segbot 播放歌曲,蜂鸣器由脉冲宽度调制控制。三个 CPU 定时器中断中的每一个都被设置为不同的周期以对应歌曲的节奏。歌曲的音符组合成一个数组,用来改变PWM的周期,在检测到第一个音符的情况下,每次发生定时器中断时,蜂鸣器都会播放相应的音符。播放的歌曲是对披头士的“Hey Jude”、夏奇拉的“Hips Don't Lie”和海滩男孩的“Little Saint Nick”的演绎。为了增强“小圣尼克”的表现,增加了一个铃铛,并结合 RC 伺服电机使用 PWM,在歌曲的不同部分敲击表面。

让 segbot 平衡是在此项目中完成的,再次使用 PWM 触发 ADC,其中值通过 SPI 写入,以便从 MPU-9250 读取加速度和陀螺仪值。实施卡尔曼滤波器以在将值发送到平衡 segbot 的控制律之前对其进行过滤。与播放歌曲类似,为了让 segbot 跳舞,为转弯速率和向前/向后偏移创建了一个数组。当检测到相应的音符时,在 CPU 定时器中断中执行舞蹈。

//Sing and dance when the Goertzel value exceeds threshold
if(note_detected == 1){

        GPIO_SetupPinMux(16, GPIO_MUX_CPU1, 5);// set up buzzer

        if (numtimer1calls < songsize){
            //play the song
            if(song[numtimer1calls]==0){
                GpioDataRegs.GPACLEAR.bit.GPIO16 = 1; // ground the buzzer
            }else{
                EPwm9Regs.TBPRD = (int)(3125000/song[numtimer1calls]/2);
            }
            //dance
            FwdBkOffset = fwddance[numtimer1calls];
            turnrate = turndance[numtimer1calls];
        }   else{
            GPIO_SetupPinMux(16, GPIO_MUX_CPU1, 0); // set GPIO16 back to GPIO
            GpioDataRegs.GPACLEAR.bit.GPIO16 = 1; // ground the buzzer
            note_detected = 0;
            numtimer1calls = 0;
            FwdBkOffset = 0;
            turnrate = 0;
        }

        numtimer1calls++; // only increment after note is detected
    }
 

 


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.lene-v.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'平衡segway机器人开源项目',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.lene-v.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);