VVVFのみスケッチ [ds-DCCデコーダ]
VVVFスケッチからメロディーを抜いて、説明してくださいとの依頼がありました。こちらのスケッチになります。(今回、延々と文字だけが並ぶ話です)
このスケッチの説明をしますと、
CV47に2を設定して吊りかけ音は50~440Hzです。
CV48は無視。
CV2が起動電圧(0~255)、
CV3が加速時のスムーズ値(0~255)(大きくするとスムーズになる)
CV4が減速時のスムーズ値(0~255)(大きくなるとスムーズになる)
CV5が最大電圧(0~255),
です。
ファンクションは
F0:Offでモーター音On、Onでモーター音Off
です。
・loop関数はステートマシンになっていますが、最初のループがl_pre_dccで、次のループからl_dccです。
・VVVF音が鳴る制御部分はMotor_Control関数で、中身を説明します。
・motor_control関数にはnotifyDccSpeed関数でときどき書き込まれるgSpeedCmdとgPwmDirが入力になります。
・まずLPF部分(スピードをスムーズにする)になります。DCCは128スピードしかありませんから、これをそのまま周波数にしてしまうと全部ドレミファインバーターのカッコ悪いのになってしまいますので、これをスムーズにしています。あとはついでに方向が変わったら急停止になるようにしています。
入力スピードはgSpeedCmd(0~255)で、出力スピード(スムーズになった後)はaPWMRef(0~1023)です。
-------------------
-------------------
・次が、はじめの一回(vvvf_first_flag==true)はVVVF行列(kasoku[][])をロードしています。なんでこんなところに持ってきているかというと、Setupに入れたら、頭でっかちになってしまい、Directモード書き込みなどのタイミングに間に合わなかったためです。(l_pre_dccに入れてもよさそうですが)
・次に、スムーズ後のスピードであるaPWMRefとVVVF行列(kasoku[][])からVVVF音の周波数を計算してその時の周期current_period1,currnet_period2を求めます。currnet_period2はモーター音を重厚にしようと思った名残で残っているだけで、今回は使っていません。(またそのうち使うかも)
そして、モーターの回転やトルクを出すためのduty比であるpwm_dutyを計算します。周波数によってかなりトルクが変わるため、これもVVVF行列[kasoku[][])にいっしょに入れてあります。
次に、方向情報を付けて最終的にcurrent_duty_a,current_duty_bでDuty比を出してやります。
なお、随所に「//interruptで渡す」と書いておりますが、やっていません。motor_control関数の最後にTimer1に書き込んでいます。
--------------------
--------------------
・その次が(今は残骸のF0によるヘッドライトテールライトルーチンが・・・)
--------------------
--------------------
・その次に実際にTimer1にPeriodとDutyを書き込んでやっています。この時、F0_Flagが1ならcurrent_periodを20,000Hz(中年には聞こえない高い音)にして、Current_Dutyを適当に1.9倍して、無音走行(ノッチオフ)にするというのもやっています。F0_Flagが0なら、上のほうで求めたPeriodとDutyでモーターを動かします。
Back EMFにするなら、目標スピードがaPWMRefで実際の指示スピードがpwm_dutyになると思います。
現在、pwm_dutyはkaosku[][]から求めていますが、BackEMFからうまくいくなら、個々の配列部分はすべて無視で「VVVF音あり」、「音無し」共に行けるかなあと思います。
---------------------
---------------------
ところでaccel_flagですが、加速中はVVVF音、定速になったり減速時は無音というのをやるために作った(作り途中の)flagです。
このスケッチの説明をしますと、
CV47に2を設定して吊りかけ音は50~440Hzです。
CV48は無視。
CV2が起動電圧(0~255)、
CV3が加速時のスムーズ値(0~255)(大きくするとスムーズになる)
CV4が減速時のスムーズ値(0~255)(大きくなるとスムーズになる)
CV5が最大電圧(0~255),
です。
ファンクションは
F0:Offでモーター音On、Onでモーター音Off
です。
・loop関数はステートマシンになっていますが、最初のループがl_pre_dccで、次のループからl_dccです。
・VVVF音が鳴る制御部分はMotor_Control関数で、中身を説明します。
・motor_control関数にはnotifyDccSpeed関数でときどき書き込まれるgSpeedCmdとgPwmDirが入力になります。
・まずLPF部分(スピードをスムーズにする)になります。DCCは128スピードしかありませんから、これをそのまま周波数にしてしまうと全部ドレミファインバーターのカッコ悪いのになってしまいますので、これをスムーズにしています。あとはついでに方向が変わったら急停止になるようにしています。
入力スピードはgSpeedCmd(0~255)で、出力スピード(スムーズになった後)はaPWMRef(0~1023)です。
-------------------
//LPF routin float instruct_speed = (float)(gSpeedCmd * 4);//change from 256 to 1023 float speed_step = 0; if( gPrevSpeed < instruct_speed ) { //Acceleration accel_flag = true; speed_step = 1024 / (1 + (float)gCV3_AccRatio * 16);// "* 16 " is because of smooth speed gPrevSpeed += speed_step ; if (gPrevSpeed > instruct_speed) { gPrevSpeed = instruct_speed; } } else if( gPrevSpeed > instruct_speed ) { //Deceleration speed_step = 1024 / (1 + (float)gCV4_DecRatio * 16);// "* 8 " is because of smooth speed gPrevSpeed -= speed_step ; if (gPrevSpeed < instruct_speed) { gPrevSpeed = instruct_speed; } } //when direction is different if(preDir != gPwmDir) { //stop gPrevSpeed = 0; } preDir = gPwmDir; aPWMRef = (uint16_t)gPrevSpeed;
-------------------
・次が、はじめの一回(vvvf_first_flag==true)はVVVF行列(kasoku[][])をロードしています。なんでこんなところに持ってきているかというと、Setupに入れたら、頭でっかちになってしまい、Directモード書き込みなどのタイミングに間に合わなかったためです。(l_pre_dccに入れてもよさそうですが)
・次に、スムーズ後のスピードであるaPWMRefとVVVF行列(kasoku[][])からVVVF音の周波数を計算してその時の周期current_period1,currnet_period2を求めます。currnet_period2はモーター音を重厚にしようと思った名残で残っているだけで、今回は使っていません。(またそのうち使うかも)
そして、モーターの回転やトルクを出すためのduty比であるpwm_dutyを計算します。周波数によってかなりトルクが変わるため、これもVVVF行列[kasoku[][])にいっしょに入れてあります。
次に、方向情報を付けて最終的にcurrent_duty_a,current_duty_bでDuty比を出してやります。
なお、随所に「//interruptで渡す」と書いておりますが、やっていません。motor_control関数の最後にTimer1に書き込んでいます。
--------------------
if(aPWMRef != 0) { //初期化 一回だけ行う if(vvvf_first_flag == true) { vvvf_first_flag = false; //安全策 if(gCV47_SoundSwitch > 8) { gCV47_SoundSwitch = 8; } int kasoku_offset = (int)pgm_read_word_near(&progmem_ref_kasoku[gCV47_SoundSwitch]); uplimit = (int)pgm_read_word_near(&progmem_ref_kasoku[gCV47_SoundSwitch+1]) - kasoku_offset; for(int i = 0;i < uplimit;i++) { for (int j = 0;j < 8;j++) { kasoku[i][j] = (int)pgm_read_word_near(&progmem_kasoku [i + kasoku_offset][j]); Serial.print(kasoku[i][j],DEC); Serial.print(","); } Serial.println(""); } } for(int i = 0;i < uplimit;i++) { if ( (kasoku[i][0] <= aPWMRef ) and ( aPWMRef <= kasoku [i][1])) { //音色側 //周波数1 pwm_freq = (double)kasoku[i][2] + (double)(kasoku[i][3] - kasoku[i][2]) / (double)(kasoku [i][1] - kasoku [i][0]) * (double)(aPWMRef - kasoku [i][0]); current_period1 = (double)1000000 / pwm_freq;//interruptで渡す //Serial.print(pwm_freq,DEC); //Serial.print(F(" Hz,")); //周波数2 pwm_freq = (double)kasoku[i][4] + (double)(kasoku[i][5] - kasoku[i][4]) / (double)(kasoku [i][1] - kasoku [i][0]) * (double)(aPWMRef - kasoku [i][0]); current_period2 = (double)1000000 / pwm_freq;//interruptで渡す //Serial.print(pwm_freq,DEC); //Serial.print(F(" Hz,")); //電力側 pwm_duty = (double)kasoku[i][6] + (double)(kasoku[i][7] - kasoku[i][6]) / (double)(kasoku [i][1] - kasoku [i][0]) * (double)(aPWMRef - kasoku [i][0]); //CV2,CV5で修正 pwm_duty = (double)gCV2_Vstart * 4 + (double)pwm_duty * (double)(gCV5_Vhigh - gCV2_Vstart) / (double)255; if (pwm_duty >1023) { pwm_duty = 1023; } //Serial.print(F("Duty:")); //Serial.println(pwm_duty,DEC); if(gPwmDir > 0) { //interruptで渡す current_duty_b = 0; current_duty_a = pwm_duty; } else { //interruptで渡す current_duty_a = 0; current_duty_b = pwm_duty; } } } } else { //interruptで渡す current_duty_b = 0; current_duty_a = 0; }
--------------------
・その次が(今は残骸のF0によるヘッドライトテールライトルーチンが・・・)
--------------------
//F0 if(gPwmDir > 0) { //F0 exec_function( 0, FunctionPin_CCW_Light, HIGH ); exec_function( 0, FunctionPin_CW_Light, !F0_flag ); } else { //CCW exec_function( 0, FunctionPin_CW_Light, HIGH ); exec_function( 0, FunctionPin_CCW_Light, !F0_flag ); }
--------------------
・その次に実際にTimer1にPeriodとDutyを書き込んでやっています。この時、F0_Flagが1ならcurrent_periodを20,000Hz(中年には聞こえない高い音)にして、Current_Dutyを適当に1.9倍して、無音走行(ノッチオフ)にするというのもやっています。F0_Flagが0なら、上のほうで求めたPeriodとDutyでモーターを動かします。
Back EMFにするなら、目標スピードがaPWMRefで実際の指示スピードがpwm_dutyになると思います。
現在、pwm_dutyはkaosku[][]から求めていますが、BackEMFからうまくいくなら、個々の配列部分はすべて無視で「VVVF音あり」、「音無し」共に行けるかなあと思います。
---------------------
//実際の命令 //if(accel_flag == false) if(F0_flag) { current_period1 = (double)1000000 / 20000; current_duty_a *= (double)1.9; current_duty_b *= (double)1.9; if( current_duty_a > 1023) { current_duty_a = 1023; } if( current_duty_b > 1023) { current_duty_b = 1023; } } Timer1.setPeriod(current_period1); Timer1.setPwmDuty(MOTOR_PWM_A,current_duty_a); Timer1.setPwmDuty(MOTOR_PWM_B,current_duty_b);
---------------------
ところでaccel_flagですが、加速中はVVVF音、定速になったり減速時は無音というのをやるために作った(作り途中の)flagです。
2016-09-13 22:10
コメント(0)
トラックバック(0)
コメント 0