囧囧-科技大神粉 发表于 2015-2-26 19:10:37

8个LED的音量表 的思考

本帖最后由 囧囧-科技大神粉 于 2015-2-26 23:43 编辑

原帖:http://www.dianziaihaozhe.com/mulu/guowai/2627.html


下面的音量表电路采用两个四电压比较器(LM339),照亮了一系列的8个LED指示灯,指示音量。每个8比较器的偏置电压的增加由分压器设定为使右下LED点亮时,首先输入的是约400毫伏,或约22毫瓦的峰值在8欧姆系统。分压器的电压被设定为使得每个LED代表大约两倍的功率电平之前,当所有的LED被点亮时,这样的比例范围是从22毫瓦到大约2.5瓦特。灵敏度可与输入控制降低到读更高的水平。




我还没有建立或测试该电路,功率电平应该如下:1个LED = 22MW
2个LED = 42MW
3个LED = 90mW的
4个LED =为175mW
5个LED =达320mW
6个LED =为650mW
7个LED = 1.2瓦
8个LED =2.5瓦特
————————————————————————————————————————————————衍生,楼主想直接测3.5耳机音频孔出来的电压,就用这个电路,但根据其他论坛大神的描述,峰值电压最高不过1Vpp,均值不过700mVpp,显然不太适合则个阻值,目测原文作者的阻值是接在功放出口的,所以能达到这么大
现在,楼主想改成同相输入端为10mV、20mV、30mV、40mV、50mV、60mV、70mV、80mV,这种小电压的
那么问题来了,Vcc端5V,要分出80mV的,根据串联分压来说,如果R1为1200欧(8个150欧),那么R2需要73800欧
坑爹啊~~~楼主压根就没这么多的电阻(73800约要16个4.7k电阻)怎么办?
苦思冥想后,祭出一个神气,5.1V的稳压二极管,然后串联一个4.7K+1.57K(3个4.7K并联)+8个150欧
进而实现了,实测5.1V稳压管实际降压大概4.48V,剩下0.5V左右就比较好分了


http://www.tudou.com/listplay/NCZI5vbIFQE/IUKGSm4mutQ.html
——————————————————————————————————————————
另外,再附上1种单片机读音频的电路


囧囧-科技大神粉 发表于 2015-2-26 23:45:18

本帖最后由 囧囧-科技大神粉 于 2015-2-28 09:29 编辑



/*
纯串口控制
加入脱机控制
*/


//电机的高电平持续时间 us
int maichongjiangeMax=357;
int maichongjiangeMin=120;

//电机的高电平持续时间的初始值 120us
int maichongjiange=357;

// EN+,脱机,高电平有效
// CW+,方向
// CLK+,频率(转速)
int EN=10;
int CW=11;
int CLK=12;


//脉冲的占空比为1/maichongzhankongbi
int maichongzhankongbi=4;

////////////////////////////////////////////

int tempint;
int maichongjsq=0;//脉冲计数器


unsigned long time2=micros();


void setup(){

Serial.begin(9600);

pinMode(EN, OUTPUT);// EN+,脱机,高电平有效
pinMode(CW, OUTPUT);// CW+,方向
pinMode(CLK, OUTPUT);// CLK+,频率(转速)

digitalWrite(EN, HIGH);//电机默认脱机
digitalWrite(CW, LOW);//
digitalWrite(CLK, LOW);

for(int col=2;col<10;col++)pinMode(col, INPUT_PULLUP);

}


void loop(){




   while (Serial.available() > 0) {

    //丧心病狂的单字节控制,0延迟,纯ASCII分拆
      //定义1 0-9表示转速,每一个表示10%
      //定义2 A正转、B反转
      //定义3 C联机、D脱机

   tempint=Serial.read();

   //调速度
   if(tempint>47 && tempint< 58) maichongjiange = 625/(1.75+3.25*(tempint-48)/10);//0-1023
   //调方向
   else if(tempint==65)digitalWrite(CW, 0);
   else if(tempint==66)digitalWrite(CW, 1);
    //脱机
   else if(tempint==67)digitalWrite(EN, 0);
   else if(tempint==68)digitalWrite(EN, 1);

//E jiansu   F jiasu
   else if(tempint==69){
    maichongjiange=maichongjiange+3;
    if(maichongjiange>maichongjiangeMax)maichongjiange=maichongjiangeMax;
   }
   else if(tempint==70){
    maichongjiange=maichongjiange-3;
    if(maichongjiange<maichongjiangeMin)maichongjiange=maichongjiangeMin;
   }


   Serial.println(maichongjiange);
   tempint=0;

}



for(int col=10;col>1;col--){

   tempint= digitalRead(col);
         if(tempint==LOW){
               Serial.print("Max:");
               Serial.println(col);
               col=0;

         }

}

//在脉冲频率无变化的时候驱动电机正常运行
maichongqudong();


}



void maichongqudong()//脉冲驱动
{

//步进电机控制脉冲
if (micros()-time2 > maichongjiange){

      maichongjsq++;//每过一个“脉冲间隔”时间段,则“脉冲计数器”自增1
      maichongjsq=maichongjsq%maichongzhankongbi;//对“脉冲计数器”取模,这个取摸结果实质就是对占空比的调节(占空比为1/模),以4为例,则“脉冲计数器”的变化为:0——1——2——3——0

      if(maichongjsq==0)digitalWrite(CLK, HIGH);//输出控制步进电机的电平
      else digitalWrite(CLK, LOW);

   time2= micros();
}

}


囧囧-科技大神粉 发表于 2015-2-28 20:18:25

本帖最后由 囧囧-科技大神粉 于 2015-2-28 20:26 编辑

音压、电机联动,最粗暴的一版
http://www.tudou.com/programs/view/PYSe20YSoy8/

/*
纯串口控制
加入脱机控制
*/


//电机的高电平持续时间 us
int maichongjiangeMax=357;
int maichongjiangeMin=120;

//电机的高电平持续时间的初始值 120us
int maichongjiange=357;

// EN+,脱机,高电平有效
// CW+,方向
// CLK+,频率(转速)
int EN=10;
int CW=11;
int CLK=12;


//脉冲的占空比为1/maichongzhankongbi
int maichongzhankongbi=4;

////////////////////////////////////////////

int tempint;//打杂的中间数


int shuaijianzhi;//衰减值

int maichongjsq=0;//脉冲计数器

boolean zusaiqu=0;//阻塞区


unsigned long time1=micros();//电机CLK

unsigned long time2=millis();//防止因音频变化而过快的改变电机的运行状态


void setup(){

Serial.begin(9600);

pinMode(EN, OUTPUT);// EN+,脱机,高电平有效
pinMode(CW, OUTPUT);// CW+,方向
pinMode(CLK, OUTPUT);// CLK+,频率(转速)

digitalWrite(EN, HIGH);//电机默认脱机
digitalWrite(CW, LOW);//
digitalWrite(CLK, LOW);

for(int col=2;col<10;col++)pinMode(col, INPUT_PULLUP);

}


void loop(){



//串口调速
   while (Serial.available() > 0) {

    //丧心病狂的单字节控制,0延迟,纯ASCII分拆
      //定义1 0-9表示转速,每一个表示10%
      //定义2 A正转、B反转
      //定义3 C联机、D脱机

   tempint=Serial.read();

   //调速度
   if(tempint>47 && tempint< 58) maichongjiange = 625/(1.75+3.25*(tempint-48)/10);//0-1023
   //调方向
   else if(tempint==65)digitalWrite(CW, 0);
   else if(tempint==66)digitalWrite(CW, 1);
    //脱机
   else if(tempint==67)digitalWrite(EN, 0);
   else if(tempint==68)digitalWrite(EN, 1);

//E jiansu   F jiasu
   else if(tempint==69){
    maichongjiange=maichongjiange+3;
    if(maichongjiange>maichongjiangeMax)maichongjiange=maichongjiangeMax;
   }
   else if(tempint==70){
    maichongjiange=maichongjiange-3;
    if(maichongjiange<maichongjiangeMin)maichongjiange=maichongjiangeMin;
   }


   Serial.println(maichongjiange);
   tempint=0;

}



//音频调速

if(!zusaiqu){ //阻塞区内不做判断,最粗暴,完善的方法是,阻塞区内低值无效,高值有效

      for(int col=9;col>1;col--){

                tempint= digitalRead(col);
               
         if(!tempint){ //低电平有效
                              zusaiqu=1;//进入阻塞期间
                // Serial.print("Max:"); //实际情况是其发送非常耗时,直接影响了步进电机的运行
                // Serial.println(col);
                              //对于速度增加的定义,鉴于其返回值有9、8····2端口值,先粗暴一把吧,直接按声压,而非实际分贝分类
                              maichongjiange = 625/(1.75+3.25*(col-1)/8);//
                              
                              //确定衰减值
                              shuaijianzhi=(maichongjiangeMax-maichongjiange)/3;
      
   
                col=0;//跳出循环
         }
      }


}else{
         
         
//核心部分,转速的衰减,暂定为3秒,即声压带来的速度提升效果,会在3秒后消失
//那么就意味,只有最慢的357才是常态,其他都是浮云
//衰减暂定为3部曲,每秒衰减1/3,梯形衰减,不做平滑处理(平滑的效果反而很差,因为不是闭环)
      if (millis() - time2 > 1000 && shuaijianzhi>0){
      time2=millis();
      
                        maichongjiange=maichongjiange+shuaijianzhi; //脉冲周期增加,频率下降,转速衰减
                        
                        if(maichongjiange>maichongjiangeMax){
                              maichongjiange=maichongjiangeMax;//防止过度衰减
                              zusaiqu=0;//退出阻塞期间
                              shuaijianzhi=0;//衰减值归零
                              
                        }

      }



}



//在脉冲频率无变化的时候驱动电机正常运行
maichongqudong();






}



void maichongqudong()//脉冲驱动
{

//步进电机控制脉冲
if (micros()-time1 > maichongjiange){

      maichongjsq++;//每过一个“脉冲间隔”时间段,则“脉冲计数器”自增1
      maichongjsq=maichongjsq%maichongzhankongbi;//对“脉冲计数器”取模,这个取摸结果实质就是对占空比的调节(占空比为1/模),以4为例,则“脉冲计数器”的变化为:0——1——2——3——0

      if(maichongjsq==0)digitalWrite(CLK, HIGH);//输出控制步进电机的电平
      else digitalWrite(CLK, LOW);

   time1= micros();
}

}


囧囧-科技大神粉 发表于 2015-3-1 11:47:49

本帖最后由 囧囧-科技大神粉 于 2015-3-1 13:15 编辑

http://www.tudou.com/programs/view/2P5KP6n270o/


音频电压控制电机精细版_修正音频电压与转速的关系
http://www.tudou.com/programs/view/KtN3iQ68DkY/
在16欧耳机内阻的情况下涵盖41-59db,共18db的音频变化,范围太窄,这个需要改进

囧囧-科技大神粉 发表于 2015-3-3 17:46:29

/*
纯串口控制
加入脱机控制
加入细分变量 xifen 用1250/xifen 取代625
单周期高电平US——圈/S := (1000000/(X*200))/xifen*0.25=xifen2/X=xifen2/X

*/


//电机的高电平持续时间 us
int maichongjiangeMax=357;
int maichongjiangeMin=120;

//电机的高电平持续时间的初始值 120us
int maichongjiange=357;

// EN+,脱机,高电平有效
// CW+,方向
// CLK+,频率(转速)
int EN=10;
int CW=11;
int CLK=12;

//步进电机控制器的细分数1、2、8、16(整、半、1/8、1/16)、
int xifen=8;
int xifen2;

//10步距角
int bujujiao=18;
//100度所需的色脉冲数,把度数放大,可以极大的提高控制精度,
int dumaichong100;

//脉冲的占空比为1/maichongzhankongbi
int maichongzhankongbi=4;

////////////////////////////////////////////

int tempint;//打杂的中间数

int yunxingmoshi;//运行模式
int moshijsq=0;//模式计数器
boolean fangxiang=0;//电机转动方向标识
int fanzhuanfazhi=0;

float quanshuzy;//圈数增益(量)每秒,作为感官等额衰减的依据
int tempint2;//打杂的中间数2,专注记录,maichongjiange的变化

int maichongjsq=0;//脉冲计数器




unsigned long time1=micros();//电机CLK

unsigned long time2=millis();//防止因音频变化而过快的改变电机的运行状态


void setup(){

Serial.begin(9600);

pinMode(EN, OUTPUT);// EN+,脱机,高电平有效
pinMode(CW, OUTPUT);// CW+,方向
pinMode(CLK, OUTPUT);// CLK+,频率(转速)

digitalWrite(EN, HIGH);//电机默认脱机
digitalWrite(CW, LOW);//
digitalWrite(CLK, LOW);

for(int col=2;col<10;col++)pinMode(col, INPUT_PULLUP);

xifen2=1250/xifen;
dumaichong100=xifen*10/bujujiao; //55(1)        \        111(2)        \        444(8)        \        888(16)
maichongjiangeMax=maichongjiangeMax*2/xifen;
maichongjiangeMin=maichongjiangeMin*2/xifen;

}


void loop(){



//串口调速
   while (Serial.available() > 0) {

    //丧心病狂的单字节控制,0延迟,纯ASCII分拆
      //定义1 0-9表示转速,每一个表示10%
      //定义2 A正转、B反转
      //定义3 C联机、D脱机

   tempint=Serial.read();

   //调速度
   if(tempint>47 && tempint< 58) maichongjiange = xifen2/(1.75+3.25*(tempint-48)/10);//0-1023
   //调方向 A、B
   else if(tempint==65){
    digitalWrite(CW, 0);
    fangxiang=0;
   }
   else if(tempint==66){
    digitalWrite(CW, 1);
    fangxiang=1;
   }
    //联机、脱机 C、D
   else if(tempint==67)digitalWrite(EN, 0);
   else if(tempint==68)digitalWrite(EN, 1);

//E 减速   F 加速
   else if(tempint==69){
    maichongjiange=maichongjiange+3;
    if(maichongjiange>maichongjiangeMax)maichongjiange=maichongjiangeMax;
   }
   else if(tempint==70){
    maichongjiange=maichongjiange-3;
    if(maichongjiange<maichongjiangeMin)maichongjiange=maichongjiangeMin;
   }
   
   //模式G 转动
   else if(tempint==71)yunxingmoshi=0;
   //模式H 摇摆
   else if(tempint==72)yunxingmoshi=1;
   //模式J
   //else if(tempint==73)yunxingmoshi=2;
   
   


   Serial.println(maichongjiange);
   tempint=0;

}



//音频调速

//阻塞区内不做判断,最粗暴,完善的方法是,阻塞区内低值无效,高值有效

      for(int col=9;col>1;col--){

                tempint= digitalRead(col);
               
         if(!tempint){ //低电平有效
               
                // Serial.print("Max:"); //实际情况是其发送非常耗时,直接影响了步进电机的运行
                // Serial.println(col);
                              //对于速度增加的定义,鉴于其返回值有9、8····2端口值,先粗暴一把吧,直接按声压,而非实际分贝分类
                               // tempint2 = xifen2/(1.75+3.25*(col-1)/8);//在变化有效的情况下,maichongjiange的值得
          //实际人耳的分类,与电压、耳机灵敏度有关
          //现在以100db/mw灵敏度的耳机进行分类
          //目前实测,2个LM339的,8个基准脚的电压与接口、分贝对于关系为
          /*
      IO        2        \        3        \        4        \        5        \        6        \        7        \        8        \        9
      基准mV        6.5        \        12.9\        19.5\        26.1\        33        \        39.8\        46.2\        53.1
      32欧对应db        41.2\        47.1\        50.7\        53.2\        55.3\        56.9\        58.2\        59.4
      16欧对应db        44.2\        50.1\        53.7\        56.2\        58.3\        59.9\        61.2\        62.4
      定义每个等级增加 0.40625圈,8个增量 =3.25圈
   
      可见
      1、耳机内阻减小虽然会导致功率翻倍,但分贝数不过变化3
      2、坑爹啊,基准值取得太高,导致范围曲在了41-59db,所需音量太大(电脑音量输出50%以上),且范围窄(小于提速无效,大于衰减无效)
      3、如果在32欧内阻下测量,需要细分到2mV(31db)、3mV(34db)、4mv(36.9db),328p分辨率不足,LM339的10mv分辨率更不足,需要放大
         
          */
      
      tempint2 = xifen2/(1.75+0.40625*(col-1));//在变化有效的情况下,maichongjiange的值得
      
                              //仅当新值低于现值(周期短,频率高),此变化才是有效的
      if(maichongjiange>tempint2){
   maichongjiange=tempint2;
   
   if(yunxingmoshi==1)fanzhuanfazhi=5*col;//反转阀值度数的确定,取端口值的5倍数
}



      
                col=0;//跳出循环
         }
      }



         
         
//核心部分,转速的衰减,暂定为3秒,即声压带来的速度提升效果,会在3秒后消失
//那么就意味,只有最慢的357才是常态,其他都是浮云
//衰减暂定为3部曲,每秒衰减1/3,梯形衰减,不做平滑处理(平滑的效果反而很差,因为不是闭环)
      if (millis() - time2 > 1000){
      time2=millis();

                  //确定衰减值,这次是动态计算,理想中省资源的方式是直接分类
      //先确定增益圈数
      quanshuzy=xifen2/maichongjiange - 1.75;//等价 xifen2/maichongjiange - xifen2/maichongjiangeMax
         
                        //每次衰减增益数的20%
      //等价xifen2/(1.75+quanshuzy*0.8)
      //理论上,只要quanshuzy不为负,就速度下限就是1.75圈/秒,但328p的浮点不靠谱性得防
      if(quanshuzy>0){
      
       maichongjiange=xifen2/(1.75+quanshuzy*0.8); //脉冲周期增加,频率下降,转速衰减
   
    if(yunxingmoshi==1 && fanzhuanfazhi>10)fanzhuanfazhi=fanzhuanfazhi*0.8;//H模式下,同转速,每次衰减20%
   
      }else{
      
    fanzhuanfazhi=5;
       quanshuzy=0;
      }
      

      }






//在脉冲频率无变化的时候驱动电机正常运行
maichongqudong();






}



void maichongqudong()//脉冲驱动
{

//步进电机控制脉冲
if (micros()-time1 > maichongjiange){

      maichongjsq++;//每过一个“脉冲间隔”时间段,则“脉冲计数器”自增1
      maichongjsq=maichongjsq%maichongzhankongbi;//对“脉冲计数器”取模,这个取摸结果实质就是对占空比的调节(占空比为1/模),以4为例,则“脉冲计数器”的变化为:0——1——2——3——0

      if(maichongjsq==0){
   
   digitalWrite(CLK, HIGH);//输出控制步进电机的电平
   
///////////////////////////////////////////////////////////////////////////////////
   //H模式
    if(yunxingmoshi==1){
   //对于脉冲数的计数
    if(fangxiang)moshijsq++;
    else moshijsq--;

    //反转阀值折算为脉冲数进行反转
    tempint=fanzhuanfazhi*dumaichong100/100; // 需要度数*100度所需周期数
   
    if(moshijsq<-tempint || moshijsq>tempint){ //达到既定周期后反向
   fangxiang=!fangxiang;
   digitalWrite(CW, fangxiang);
    }
   }


/////////////////////////////////////////////////////////////////////////////////////

}else digitalWrite(CLK, LOW);


   time1= micros();
}



}


囧囧-科技大神粉 发表于 2015-3-3 21:07:21

/*
纯串口控制
加入脱机控制
加入细分变量 xifen 用1250/xifen 取代625
单周期高电平US——圈/S := (1000000/(X*200))/xifen*0.25=xifen2/X=xifen2/X

*/


//电机的高电平持续时间 us
int maichongjiangeMax=1563;
int maichongjiangeMin=174;

//电机的高电平持续时间的初始值 120us
int maichongjiange=357;

// EN+,脱机,高电平有效
// CW+,方向
// CLK+,频率(转速)
int EN=10;
int CW=11;
int CLK=12;

//步进电机控制器的细分数1、2、8、16(整、半、1/8、1/16)、
int xifen=8;
int xifen2;

//10步距角
int bujujiao=18;
//100度所需的色脉冲数,把度数放大,可以极大的提高控制精度,
int dumaichong100;

//脉冲的占空比为1/maichongzhankongbi
int maichongzhankongbi=4;

////////////////////////////////////////////

int tempint;//打杂的中间数

int yunxingmoshi;//运行模式
int moshijsq=0;//模式计数器
boolean fangxiang=0;//电机转动方向标识
int fanzhuanfazhi=0;

float quanshuzy;//圈数增益(量)每秒,作为感官等额衰减的依据
int tempint2;//打杂的中间数2,专注记录,maichongjiange的变化

int maichongjsq=0;//脉冲计数器




unsigned long time1=micros();//电机CLK

unsigned long time2=millis();//防止因音频变化而过快的改变电机的运行状态


void setup(){

Serial.begin(9600);

pinMode(EN, OUTPUT);// EN+,脱机,高电平有效
pinMode(CW, OUTPUT);// CW+,方向
pinMode(CLK, OUTPUT);// CLK+,频率(转速)

digitalWrite(EN, HIGH);//电机默认脱机
digitalWrite(CW, LOW);//
digitalWrite(CLK, LOW);

for(int col=2;col<10;col++)pinMode(col, INPUT_PULLUP);

xifen2=1250/xifen;
dumaichong100=xifen*1000/bujujiao; //55(1)      \      111(2)      \      444(8)      \      888(16)

}


void loop(){



//串口调速
   while (Serial.available() > 0) {

    //丧心病狂的单字节控制,0延迟,纯ASCII分拆
      //定义1 0-9表示转速,每一个表示10%
      //定义2 A正转、B反转
      //定义3 C联机、D脱机

   tempint=Serial.read();

   //调速度
   if(tempint>47 && tempint< 57) maichongjiange = xifen2/(0.1+0.1*(tempint-48));//0-1023
   //调方向 A、B
   else if(tempint==65){
    digitalWrite(CW, 0);
    fangxiang=0;
   }
   else if(tempint==66){
    digitalWrite(CW, 1);
    fangxiang=1;
   }
    //联机、脱机 C、D
   else if(tempint==67)digitalWrite(EN, 0);
   else if(tempint==68)digitalWrite(EN, 1);

//E 减速   F 加速
   else if(tempint==69){
    maichongjiange=maichongjiange+3;
    if(maichongjiange>maichongjiangeMax)maichongjiange=maichongjiangeMax;
   }
   else if(tempint==70){
    maichongjiange=maichongjiange-3;
    if(maichongjiange<maichongjiangeMin)maichongjiange=maichongjiangeMin;
   }

   //模式G 转动
   else if(tempint==71)yunxingmoshi=0;
   //模式H 摇摆
   else if(tempint==72)yunxingmoshi=1;

   else tempint=0;




   Serial.println(maichongjiange);
   tempint=0;

}



//音频调速

//阻塞区内不做判断,最粗暴,完善的方法是,阻塞区内低值无效,高值有效

      for(int col=9;col>1;col--){

                tempint= digitalRead(col);

         if(!tempint){ //低电平有效

                // Serial.print("Max:"); //实际情况是其发送非常耗时,直接影响了步进电机的运行
                // Serial.println(col);
                              //对于速度增加的定义,鉴于其返回值有9、8····2端口值,先粗暴一把吧,直接按声压,而非实际分贝分类
                               // tempint2 = xifen2/(1.75+3.25*(col-1)/8);//在变化有效的情况下,maichongjiange的值得
          //实际人耳的分类,与电压、耳机灵敏度有关
          //现在以100db/mw灵敏度的耳机进行分类
          //目前实测,2个LM339的,8个基准脚的电压与接口、分贝对于关系为
          /*
      IO      2      \      3      \      4      \      5      \      6      \      7      \      8      \      9
      基准mV      6.5      \      12.9\      19.5\      26.1\      33      \      39.8\      46.2\      53.1
      32欧对应db      41.2\      47.1\      50.7\      53.2\      55.3\      56.9\      58.2\      59.4
      16欧对应db      44.2\      50.1\      53.7\      56.2\      58.3\      59.9\      61.2\      62.4
      定义每个等级增加 0.1圈,8个增量 =0.8圈

      可见
      1、耳机内阻减小虽然会导致功率翻倍,但分贝数不过变化3
      2、坑爹啊,基准值取得太高,导致范围曲在了41-59db,所需音量太大(电脑音量输出50%以上),且范围窄(小于提速无效,大于衰减无效)
      3、如果在32欧内阻下测量,需要细分到2mV(31db)、3mV(34db)、4mv(36.9db),328p分辨率不足,LM339的10mv分辨率更不足,需要放大

          */

      tempint2 = xifen2/(0.1*col);//在变化有效的情况下,maichongjiange的值得

                              //仅当新值低于现值(周期短,频率高),此变化才是有效的
      if(maichongjiange>tempint2){
   maichongjiange=tempint2;

   if(yunxingmoshi==1)fanzhuanfazhi=5*col;//反转阀值度数的确定,取端口值的5倍数
}




                col=0;//跳出循环
         }
      }





//核心部分,转速的衰减,暂定为3秒,即声压带来的速度提升效果,会在3秒后消失
//那么就意味,只有最慢的357才是常态,其他都是浮云
//衰减暂定为3部曲,每秒衰减1/3,梯形衰减,不做平滑处理(平滑的效果反而很差,因为不是闭环)
      if (millis() - time2 > 1000){


                  //确定衰减值,这次是动态计算,理想中省资源的方式是直接分类
      //先确定增益圈数
                quanshuzy=xifen2/maichongjiange - 0.1;//等价 xifen2/maichongjiange - xifen2/maichongjiangeMax

                        //每次衰减增益数的20%

      //理论上,只要quanshuzy不为负,就速度下限就是0.1圈/秒,但328p的浮点不靠谱性得防
      if(maichongjiangeMax>maichongjiange){

       maichongjiange=xifen2/(0.1+quanshuzy*0.8); //脉冲周期增加,频率下降,转速衰减

    if(yunxingmoshi==1 && fanzhuanfazhi>10)fanzhuanfazhi=fanzhuanfazhi*0.8;//H模式下,同转速,每次衰减20%

      }else{

    fanzhuanfazhi=5;
       maichongjiange=maichongjiangeMax;
      }

            time2=millis();

      }






//在脉冲频率无变化的时候驱动电机正常运行
maichongqudong();



}



void maichongqudong()//脉冲驱动
{



      maichongjsq++;//每过一个“脉冲间隔”时间段,则“脉冲计数器”自增1
      maichongjsq=maichongjsq%maichongzhankongbi;//对“脉冲计数器”取模,这个取摸结果实质就是对占空比的调节(占空比为1/模),以4为例,则“脉冲计数器”的变化为:0——1——2——3——0

      if(maichongjsq==0){

                        digitalWrite(CLK, HIGH);//输出控制步进电机的电平

///////////////////////////////////////////////////////////////////////////////////
                              //H模式
                                    if(yunxingmoshi==1){
                                     //对于脉冲数的计数
                                    if(fangxiang)moshijsq++;
                                    else moshijsq--;

                                    //反转阀值折算为脉冲数进行反转
                                    tempint=fanzhuanfazhi*dumaichong100/100; // 需要度数*100度所需周期数

                                    if(moshijsq<-tempint || moshijsq>tempint){ //达到既定周期后反向
                                     fangxiang=!fangxiang;
                                     digitalWrite(CW, fangxiang);
                                        }
                                 }


/////////////////////////////////////////////////////////////////////////////////////

}else digitalWrite(CLK, LOW);



}



囧囧-科技大神粉 发表于 2015-3-4 12:06:21

待修改的半成品

// EN+,脱机,高电平有效
// CW+,方向
// CLK+,频率(转速)
int EN=10;
int CW=11;
int CLK=12;

//步进电机控制器的细分数1、2、8、16(整、半、1/8、1/16)、整步用loop的方式是不行的,脉冲周期太短
int xifen=2;

//10步距角
int bujujiao=18;
//100度所需的色脉冲数,把度数放大,可以极大的提高控制精度,
int dumaichong100;

//脉冲的占空比为1/maichongzhankongbi
int maichongzhankongbi=4;

////////////////////////////////////////////

int tempint;//打杂的中间数

int yunxingmoshi;//运行模式
int moshijsq=0;//模式计数器
boolean fangxiang=0;//电机转动方向标识
int fanzhuanfazhi=0;//反转阀值

float quanshuzy;//圈数增益(量)每秒,作为感官等额衰减的依据
int tempint2;//打杂的中间数2,专注记录,maichongjiange的变化

int maichongjsq=0;//脉冲计数器

int loopjsq=0;
unsigned long loopjsq2=0;


float zhuansunow=0;
float zhuansuWill=0;

boolean suduok=0;
boolean suduok2=0;

int tuoshijian;//拖时间,每增加1,则周期增加 基数×占空比

unsigned long time0=millis();

unsigned long time1=micros();//电机CLK

unsigned long time3=millis();//防止因音频变化而过快的改变电机的运行状态


void setup(){

Serial.begin(9600);

pinMode(EN, OUTPUT);// EN+,脱机,高电平有效
pinMode(CW, OUTPUT);// CW+,方向
pinMode(CLK, OUTPUT);// CLK+,频率(转速)

digitalWrite(EN, HIGH);//电机默认脱机
digitalWrite(CW, LOW);//
digitalWrite(CLK, LOW);

for(int col=2;col<10;col++)pinMode(col, INPUT_PULLUP);

dumaichong100=xifen*1000/bujujiao; //走100度所需脉冲数5555(1)        \        111(2)        \        444(8)        \        888(16)

}




void loop(){


//获得可达到的最高理论转速,半步的情况下大概6转/秒,10ms测速一次

loopjsq++;

if (millis() - time0 > 10){
   //此刻的loopjsq本质就是loop的运行次数,因为电机控制脉冲是以一次loop为基础的
   //转速 转/s = 有效脉冲数/细分/200
   
   /*
       表达方式无效 zhuansunow=loopjsq/(maichongzhankongbi*xifen*200);
               
                328p扯淡的故事~~~
                其中, zhuansunow为float,其他为int

                tempint=maichongzhankongbi*xifen*200;
                zhuansunow=loopjsq/tempint;
                计算错误!!

                zhuansunow=maichongzhankongbi*xifen*200;
                zhuansunow=loopjsq/ zhuansunow;
                计算正确
   */

zhuansunow=maichongzhankongbi*xifen*2;
zhuansunow=loopjsq/zhuansunow; //计算出每秒圈速

   


//引入布尔量,证明这个速度是可用的
   suduok=1;
   suduok2=1;
   
   
   loopjsq=0;

   
   time0=millis();
}



//串口调速
chuankoutiaosu();



//音频调速
yinpintiaosu();
         
         
//速度衰减
sudushuaijian();



//速度的调节
   


if(suduok){
       suduok=0;

        if(zhuansuWill<zhuansunow)tuoshijian++;
        else if(tuoshijian>1)tuoshijian--;

}





for(int col=1;col<tuoshijian;col++)delayMicroseconds(10);



//在脉冲频率无变化的时候驱动电机正常运行
maichongqudong();






}



void maichongqudong()//脉冲驱动
{

   maichongjsq++;//每过一个“脉冲间隔”时间段,则“脉冲计数器”自增1
      maichongjsq=maichongjsq%maichongzhankongbi;//对“脉冲计数器”取模,这个取摸结果实质就是对占空比的调节(占空比为1/模),以4为例,则“脉冲计数器”的变化为:0——1——2——3——0

      if(maichongjsq==0){
   
   digitalWrite(CLK, HIGH);//输出控制步进电机的电平
   
///////////////////////////////////////////////////////////////////////////////////
    //H模式
      if(yunxingmoshi==1){
         //对于脉冲数的计数
      if(fangxiang)moshijsq++;
      else moshijsq--;

      //反转阀值折算为脉冲数进行反转
      tempint=fanzhuanfazhi*dumaichong100/100; // 需要度数*100度所需周期数
   
      if(moshijsq<-tempint || moshijsq>tempint){ //达到既定周期后反向
         fangxiang=!fangxiang;
         digitalWrite(CW, fangxiang);
   }
       }


/////////////////////////////////////////////////////////////////////////////////////

}else digitalWrite(CLK, LOW);



}


void sudushuaijian(){
       
       
        //核心部分,转速的衰减
//此处用计数器代替时间
//设每转2圈减速一次
//理论上maichongzhankongbi*200*xifen =1圈 ,25%占空比、16细分,一圈为12800脉冲
//换言之 loopjsq2 为int时,占空比应该大于10%,改为unsigned long后就比较随意了
loopjsq2++;
      if (loopjsq2 > maichongzhankongbi*400*xifen){

                        loopjsq2=0;
                        Serial.print(zhuansuWill);
                        Serial.print("zhuansuWill/zhuansunow=");
                        Serial.println(zhuansunow);
         
               
                        if(zhuansunow>0.5)zhuansuWill = zhuansuWill*0.95;
                        else zhuansuWill=0.5;


                        if(yunxingmoshi==1 && fanzhuanfazhi>10)fanzhuanfazhi=fanzhuanfazhi*0.8;//H模式下,同转速,每次衰减20%
   
      }
          
          
          
       
       
}


void yinpintiaosu(){
       
//阻塞区内不做判断,最粗暴,完善的方法是,阻塞区内低值无效,高值有效

      for(int col=9;col>1;col--){

                tempint= digitalRead(col);
               
         if(!tempint){ //低电平有效
               
                // Serial.print("Max:"); //实际情况是其发送非常耗时,直接影响了步进电机的运行
                // Serial.println(col);
                              //对于速度增加的定义,鉴于其返回值有9、8····2端口值,先粗暴一把吧,直接按声压,而非实际分贝分类
                               // tempint2 = xifen2/(1.75+3.25*(col-1)/8);//在变化有效的情况下,maichongjiange的值得
          //实际人耳的分类,与电压、耳机灵敏度有关
          //现在以100db/mw灵敏度的耳机进行分类
          //目前实测,2个LM339的,8个基准脚的电压与接口、分贝对于关系为
          /*
      IO        2        \        3        \        4        \        5        \        6        \        7        \        8        \        9
      基准mV        6.5        \        12.9\        19.5\        26.1\        33        \        39.8\        46.2\        53.1
      32欧对应db        41.2\        47.1\        50.7\        53.2\        55.3\        56.9\        58.2\        59.4
      16欧对应db        44.2\        50.1\        53.7\        56.2\        58.3\        59.9\        61.2\        62.4

   
      可见
      1、耳机内阻减小虽然会导致功率翻倍,但分贝数不过变化3
      2、坑爹啊,基准值取得太高,导致范围曲在了41-59db,所需音量太大(电脑音量输出50%以上),且范围窄(小于提速无效,大于衰减无效)
      3、如果在32欧内阻下测量,需要细分到2mV(31db)、3mV(34db)、4mv(36.9db),328p分辨率不足,LM339的10mv分辨率更不足,需要放大
         
          */
      
   
      
                              //仅当新值低于现值(周期短,频率高),此变化才是有效的
                                                               
                float zhuansuWill2 = 0.5*col+0.5;
               
      if(zhuansuWill2>zhuansuWill){
   
                        zhuansuWill = zhuansuWill2;
   
                        if(yunxingmoshi==1)fanzhuanfazhi=5*col;//反转阀值度数的确定,取端口值的5倍数
                }



      
                col=0;//跳出循环
         }
      }
       
       
}


void chuankoutiaosu(){
       
       //串口调速
   while (Serial.available() > 0) {

    //丧心病狂的单字节控制,0延迟,纯ASCII分拆
      //定义1 0-9表示转速,每一个表示10%
      //定义2 A正转、B反转
      //定义3 C联机、D脱机

   tempint=Serial.read();

   //调速度
   if(tempint>47 && tempint< 58) zhuansuWill = 0.5*(tempint-47);//48——58(0.5——5)
   //调方向 A、B
   else if(tempint==65){
    digitalWrite(CW, 0);
    fangxiang=0;
   }
   else if(tempint==66){
    digitalWrite(CW, 1);
    fangxiang=1;
   }
    //联机、脱机 C、D
   else if(tempint==67)digitalWrite(EN, 0);
   else if(tempint==68)digitalWrite(EN, 1);

//E 减速   F 加速
   else if(tempint==69){
    zhuansuWill = zhuansuWill*0.95;

   }
   else if(tempint==70){
    zhuansuWill = zhuansuWill*1.05;

   }
   
   //模式G 转动
   else if(tempint==71)yunxingmoshi=0;
   //模式H 摇摆
   else if(tempint==72)yunxingmoshi=1;

   else tempint=0;
   
   


Serial.println(zhuansunow);


}
       
}







页: [1]
查看完整版本: 8个LED的音量表 的思考