5iMX宗旨:分享遥控模型兴趣爱好

5iMX.com 我爱模型 玩家论坛 ——专业遥控模型和无人机玩家论坛(玩模型就上我爱模型,创始于2003年)
查看: 31533|回复: 55
打印 上一主题 下一主题

DIY发动机声音模拟器

[复制链接]
跳转到指定楼层
楼主
发表于 2011-3-31 18:21 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
试验版本,用电位器控制,以后要改成舵机信号控制。准备装到电车上,盖住电机的吱吱声,尽管我手头上连个玩具遥控车都没有。

用了ATmega8L、电阻、电容各一个,以后还要加功放。

原理:由ADC控制T/C0产生中断的速度,用T/C0给T/C1喂数据,用T/C1的PWM产生声音,反复播放一段声音(来自网游“飚车”的rpm.wav)。

还需要改进,希望能接近“极品飞车”的水平

[flash]http://www.tudou.com/v/Wj2ko_bLjFY/&rpid=45597529==.html[/media]

[ 本帖最后由 348826281 于 2011-3-31 18:24 编辑 ]

欢迎继续阅读楼主其他信息

点击查看详情
沙发
 楼主| 发表于 2011-3-31 18:22 | 只看该作者
原代码


//ICC-AVR application builder
// Target : M8
// Crystal: 8.0000Mhz
#include <iom8v.h>
#include <macros.h>
#include <STRING.H>
#include <stdlib.h>
int n;
unsigned int adc,tc0no;

//一段声音
__flash char sound[373]={0x89,0x96,0x95,0x94,0xA2,0xB3,0xBE,0xC6,0xC5,0xC2,0xC5,0xD8,
0xE5,0xE5,0xE7,0xE3,0xDE,0xE0,0xDF,0xDF,0xDA,0xDB,0xDC,0xDA,0xD5,0xD4,0xD3,0xD4,
0xD8,0xD4,0xD0,0xCE,0xCC,0xCF,0xD0,0xCC,0xB9,0xA8,0x9D,0x88,0x7B,0x70,0x5F,0x53,
0x50,0x4D,0x48,0x3F,0x47,0x60,0x69,0x60,0x56,0x44,0x41,0x4E,0x51,0x4D,0x4A,0x51,
0x56,0x49,0x46,0x44,0x44,0x4F,0x59,0x59,0x66,0x72,0x76,0x75,0x83,0x90,0x98,0xA2,
0xAD,0xB6,0xBB,0xB8,0xB8,0xBC,0xC0,0xC4,0xC2,0xBF,0xC1,0xD0,0xD2,0xCB,0xC6,0xCD,
0xCE,0xCB,0xC2,0xC2,0xC1,0xBB,0xAB,0xB0,0xB7,0xB9,0xA4,0xA4,0xB0,0xAC,0xAB,0xB2,
0xA7,0x9A,0x86,0x71,0x6A,0x6D,0x5A,0x41,0x34,0x31,0x25,0x11,0x08,0x06,0x08,0x0D,
0x11,0x14,0x16,0x12,0x13,0x13,0x1E,0x2F,0x32,0x33,0x40,0x47,0x3C,0x2B,0x26,0x21,
0x33,0x3F,0x3C,0x3F,0x3C,0x3F,0x57,0x66,0x5E,0x61,0x77,0x90,0x98,0x8B,0x88,0x90,
0x9A,0xA3,0xA5,0xA6,0xA7,0xAF,0xAE,0xB2,0xBC,0xC7,0xC6,0xCD,0xD3,0xDD,0xDA,0xDA,
0xDF,0xDE,0xDF,0xDC,0xD4,0xD4,0xD7,0xD3,0xD3,0xD3,0xD5,0xC8,0xB9,0xA4,0x97,0x8D,
0x75,0x65,0x61,0x66,0x61,0x50,0x44,0x3B,0x2E,0x2C,0x37,0x3A,0x41,0x49,0x44,0x38,
0x33,0x40,0x43,0x49,0x57,0x6C,0x6A,0x64,0x67,0x65,0x57,0x55,0x52,0x56,0x5E,0x64,
0x69,0x72,0x7B,0x8C,0x98,0x9A,0xAA,0xC1,0xC8,0xC7,0xC0,0xC6,0xD0,0xCE,0xCD,0xCA,
0xC9,0xC8,0xC8,0xC9,0xCD,0xCA,0xCD,0xC6,0xC9,0xCE,0xCE,0xCC,0xD0,0xD3,0xD7,0xCA,
0xBE,0xBB,0xB7,0xB1,0xA1,0x91,0x88,0x7E,0x7F,0x73,0x5E,0x50,0x35,0x31,0x3B,0x35,
0x29,0x24,0x11,0x0B,0x0B,0x0E,0x12,0x15,0x17,0x15,0x13,0x17,0x1C,0x20,0x20,0x2C,
0x3D,0x3A,0x31,0x29,0x1C,0x27,0x42,0x48,0x45,0x41,0x48,0x55,0x5E,0x6A,0x78,0x84,
0x8F,0x97,0x93,0x99,0xA5,0xA8,0xA6,0xB8,0xAD,0x9B,0xB2,0xC9,0xC8,0xC3,0xBB,0xBD,
0xC9,0xD5,0xD1,0xD1,0xD3,0xDB,0xDE,0xDA,0xD9,0xD8,0xD7,0xDA,0xD8,0xD4,0xCF,0xCA,
0xC7,0xC1,0xB4,0x9A,0x81,0x7A,0x70,0x67,0x5A,0x44,0x3A,0x35,0x28,0x18,0x0F,0x13,
0x28,0x31,0x24,0x1E,0x20,0x1E,0x30,0x3F,0x3D,0x3D,0x4D,0x52,0x4A,0x4A,0x4C,0x44,
0x49,0x53,0x52,0x52,0x5C,0x68,0x6E,0x75,0x80};

//根据电位器的数值调整播放速度
__flash char tc0start[33]={0x82,0x87,0x8C,0x91,0x95,0x99,0x9D,0xA0,0xA4,0xA7,
0xA9,0xAC,0xAF,0xB1,0xB3,0xB5,0xB7,0xB9,0xBB,0xBC,0xBE,0xC0,0xC1,0xC2,0xC4,
0xC5,0xC6,0xC7,0xC8,0xCA,0xCB,0xCC,0xCD};

void port_init(void)
{
PORTB = 0x00;
DDRB  = 0x02; //PB1 --> OC1A  output
PORTC = 0x00; //m103 output only
DDRC  = 0x00; // PC.0 ADC
PORTD = 0x00;
DDRD  = 0x00;
}
//ADC initialize
void adc_init(void)
{
ADCSR = 0x00; //disable adc
ADMUX = 0x40; //AVcc ADC0 0100 0000
ACSR  = 0x80; //analogy comparer 1000 0000
ADCSR = 0xEF; //1110 1111  self trigger
}
#pragma interrupt_handler adc_isr:iv_ADC
void adc_isr(void)
{
adc=(unsigned int)ADCL;            //Read 8 low bits first (important)
adc|=((unsigned int)ADCH << 8); //read 2 high bits and shift into top byte
tc0no=(adc>>5);
}

//TIMER0 initialize - prescale:8
void timer0_init(void)
{
TCCR0 = 0x00; //stop
TCNT0 = 0x82; //set count
TCCR0 = 0x02; //start timer
}

#pragma interrupt_handler timer0_ovf_isr:iv_TIM0_OVF
void timer0_ovf_isr(void)
{
TCNT0 = tc0start[tc0no]; //播放速度
    OCR1AH =0x00;
    OCR1AL = sound[n];
    n++;    //声音循环播放
     if (n-372>0)
    {
     n=0;
    }
}
//TIMER1 initialize - prescale:1
// WGM: 5) PWM fast, TOP=0xFF
void timer1_init(void)
{
TCCR1B = 0x00; //stop
TCNT1H = 0xFF; //setup
TCNT1L = 0x01;
OCR1AH = 0x00;
OCR1AL = 0x80;
OCR1BH = 0x00;
OCR1BL = 0x80;
ICR1H  = 0x00;
ICR1L  = 0xFF;
TCCR1A = 0xA1; //1010 0010
TCCR1B = 0x09; //start Timer  0000 1001
}
//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
adc_init();
timer0_init();
timer1_init();
  
MCUCR = 0x00;
GICR  = 0x00;
TIMSK = 0x01; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
void main(void)
{
    n=0;tc0no=0;
init_devices();

while (1)
{
} //while(1)
} //main



有不对的地方请指出,我也是初学者,见笑了
3
发表于 2011-3-31 18:59 | 只看该作者
原帖由 llzzxxmmwwcc 于 2011-3-31 06:47 PM 发表
比电机声还难听
我觉得换一个音效+控制顺滑 就会很好听了
4
发表于 2011-3-31 20:05 | 只看该作者
有点像赛车
5
发表于 2011-3-31 20:22 | 只看该作者
真是高人,不过高速部分声音频率不够高
6
 楼主| 发表于 2011-3-31 20:30 | 只看该作者
就目前的效果来说,确实是这样。
原帖由 llzzxxmmwwcc 于 2011-3-31 18:47 发表
比电机声还难听


模拟的是一台4缸发动机在3000~8000转的声音,高转速段需要新的声音
7
发表于 2011-4-1 10:36 | 只看该作者
不错不错!特来顶之!:em26:
8
 楼主| 发表于 2011-5-15 12:05 | 只看该作者
对声音的控制不再用电位器,换成舵机信号了。
如果变速播放发动机声音,油门快速变化时会出现像电子琴的声音,否定这个方法。
[flash]http://www.tudou.com/v/s6VJ0yjooc4/&rpid=45597529==.html[/media]

在外国人的文章里,他们用波形叠加的方法,把每个气缸的声音按一定间隔叠加。


有文章介绍用GT-Suite软件的GT-power模块可以得到单缸声音的波形,可惜找不到那软件,只能现学FLUENT,建了个二维的直排管的模型,尾气排入一个半圆空间,计算压力

再用tecplot 360获得距离排气管口0.5m,偏移45度位置的压力波形。


试着发出声音,一点都不像发动机,但油门快速变化时能正常发声,说明波形叠加的方法可行

在上图中,压力的衰减相当快,如果安装消音器衰减更快,因此只要发动机转速不是很高,完全可以从实际的发动机连续工作的声音里截取波形。从ken block的漂移视频里截取了6个声音波形,

重写程序
[flash]http://www.tudou.com/v/7vrEEay5Jm8/&rpid=45597529==.html[/media]
听起来还是不爽。谁来指点下?????
也许找辆改装车,实地录制排气声音,会好点。宿舍外面的电子四路经常能听到改装车的声音,电子四路从电子西街至太白南路一段一直封闭,没车没人,六车道宽的柏油路是个很好的场地(西安)。
视频里用来产生舵机信号的板子,数码管中间一位不亮,电位器阻值跳动,弄的声音也跟着哆嗦,真是便宜没好货,工资一发就去买个控。


电路画的不标准,凑活看吧。声音信号可以直接输出到笔记本音箱,或者用LM386、TDA2422放大后输出到喇叭。还有个问题,小尺寸喇叭的频率下限,能否发出发动机的低频声音

熔丝配置,内部8M时钟,关闭看门狗计数器

代码 iccavr 写的不好,见笑了,对应2000~8000rpm的四缸机
原理:使用TC0和INT0测量舵机信号,用TC1按照声音采样率产生中断,叠加波形后由TC2的快速PWM发声。声音样本都是152长度,153~160的数值为中性点,当一段声音播放完就会指向这部分,不发出声音,直到再次开始播放
源代码 cfd.c (8.29 KB, 下载次数: 140)
hex文件 CFD.hex (7.71 KB, 下载次数: 71)

[ 本帖最后由 348826281 于 2011-5-15 12:07 编辑 ]
9
发表于 2011-5-15 23:16 | 只看该作者
怎么越搞越不靠普了呢?。。。。。:em15:
10
 楼主| 发表于 2011-5-19 19:58 | 只看该作者
略有进展

之前的变速率播放方案因为所谓的“电子琴声”而放弃,但那讨厌的声音同样出现在波形叠加方案中,分析后得出结论:“电子琴声”实际是声音的阶梯式跳变,不连续,所以出现那种声音。查出问题在那个自制的舵机测试机,更新的速度慢,导致声音模拟器出现怪声。修复后,变速率播放就能发出比较好的声音,在快速变化时也有较好表现。(舵机信号的50Hz频率足够了,不会导致电子琴声)

WRC版本,前进时发声,并根据油门大小变化,倒车时声音减弱且恒定(目前不能分辨是倒车还是刹车,所以倒车无声)
[flash]http://www.tudou.com/v/KwgEcNvHAsY/&rpid=45597529==.html[/media]

坦克声音版本,双向发声,攀爬用估计合适
[flash]http://www.tudou.com/v/9UzTRJI-CmM/&rpid=45597529==.html[/media]


源代码和烧录单片机用的Hex文件
新建文件夹.rar (13.9 KB, 下载次数: 139)
11
发表于 2011-5-20 17:20 | 只看该作者
高手
12
发表于 2011-5-20 17:45 | 只看该作者
感觉不错。
13
 楼主| 发表于 2011-6-27 19:43 | 只看该作者
多样本的方案不容易实现,中间又因为“逮捕令”和“胧村正_妖刀传”停工两周(都是小鬼子的东西),总算摆平。
之前犯了个小错,定时/计数器TC0的溢出中断等级低,导致油门大小的测量出错,换成TC1就好了,一个月才想明白,笨死了。


效果请看视频,模仿的是极品飞车9里的evo,差的比较远,目前的ATmega8只能做到这效果,凑活用吧。
还需要些小调整,收油门时声音应该逐渐减慢。
还有什么要求尽管提

[flash]http://www.tudou.com/v/WcnU5WZABkI/&rpid=45597529==.html[/media]


代码和烧录用HEX文件
evo_tc0.c (18.69 KB, 下载次数: 133)
EVO_TC0.hex (14.96 KB, 下载次数: 85)
14
发表于 2011-6-29 10:51 | 只看该作者
:em26:
15
发表于 2011-6-29 11:47 | 只看该作者
高手:em26: 对代码很头疼
16
 楼主| 发表于 2011-6-30 19:36 | 只看该作者
做了些小改动,加速和减速时的声音不会过快变化,用来模仿现实情况

重新做了兰博基尼Murcielago的声音模拟器,效果一般。原始声音文件、硬件、软件都限制了效果,录像里是用耳机发声,不知道换成笔记本音箱会怎样,也许该换成更好的单片机,配上专门的声音DAC。最大的问题是小音箱不给力,也许原始的声音是衰减过的,不能轰鸣。


[flash]http://www.tudou.com/v/Mo9OeRw3sp0/&rpid=45597529==.html[/media]



原始的声音
[flash]http://www.tudou.com/v/e_-D8RSVgAc/&rpid=45597529==.html[/media]
17
发表于 2011-7-7 03:00 | 只看该作者
牛人 厉害
18
 楼主| 发表于 2011-7-7 20:59 | 只看该作者
兰博基尼Murcielago的声音模拟器 的代码,由外部中断INT0和TC1测量油门大小(代码中的width,取值范围0~125,对应脉冲宽度1.5~2ms),并在int0的中断处理中控制播放的样本,TC0控制播放速度,最后由TC2的PWM方式输出声音
bat2.c (22.44 KB, 下载次数: 217)

现在的问题是原始声音只是11025Hz的采样率,丢失了很多细节,不像真车声音。要想用高采样率的声音必须换芯片,准备换成stm32,需要不少时间
19
发表于 2011-7-7 21:29 | 只看该作者
厉害啊厉害
20
发表于 2011-7-7 21:38 | 只看该作者
:em26:
您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

关闭

【站内推荐】上一条 /1 下一条

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