2020年5月10日日曜日

小型工作機CNC2418 その79(スピンドルモータのSoft Start/Stop制御回路)

始まりは、この時、このハイスビットを使って
DREMEL 4000で5mm厚のアルミ板を削った時にとても楽に削れたのです。
回転数:5000~32000rpm可変ですが、Maxで使ったことはなく
7000~8000rpmでやったと思います。
DREMEL 4000の定格を調べるとAC100V仕様で135Wなのです。
いよいよスピンドルを強化したくなってきました。
今使ってる775タイプのスピンドルモーターは、
12Vで1.7Aらしいので、20Wしかありません。
24Vだと単純に倍しても、たかだか40Wなのです。
CNC2418にも、せめて100Wはつけたいな~
でも、モーターマウント径が45mmなのです。
775は、42mm径ですが、鉄板が巻いてあり45mmになっています。

なのでモーターの選択肢は、42mmということになりますが、
この辺りがほとんどで、ブラシレスなので高いんです。
コントローラーも別にいるし...
US$ 70.63(25% OFF、送料 $16.64)

しかも、モーターを冷却するファンがないので
こんなヒートシンクをつけるしかなさそうですが、
モーター自体をどうやって取り付けるかという問題がでてきます。
これはこれでかっこいいのですが...
US$ 5.62(送料 $3.26)

直径52mmだとブラシモーターがあり、安く手に入ります。
300WでもUS$ 35.84(20% OFF、送料無料)なのです。
ちなみに、200Wは、US$ 27.2(20% OFF、送料無料)
500WでもUS$ 45(20% OFF、送料無料)です。

もやもや悩んでいると
YYさんから愛用されてたものを譲っていただくことに\(^o^)/
・・・ほどなくして届きました!
上の写真によく似てて、定格ラベルは剥がれてますが、
300Wか400Wとのこと(・o・)
上のAliExpressで寸法図を見ると
本体長 90mmのこれと同じなので300W品のようです。
400Wだと本体長 100mmです。
ついでに定格を見ると
12V 3000rpm、24V 6000rpm、36V 9000rpm、48V 12000rpm
のようです。
300Wだと48Vで6.25Aということになります。

電圧かけていって、回転数と電流を見ていくことにします。
可変電源は、0~48V 10Aのこれ使います。
本体にVRと電圧計が付いてて、なかなか重宝します。
US$ 32.29(50% OFF)

回転数の測定は、約2年前に「小型工作機CNC2418 その8」でやった
この6枚羽根を使います。
この時は、厚紙をブルー・レーザーでカットしましたが
当時は、Fusion360のCAM設定にとても苦労しました。
Φ20mmです。
羽根に3mmのボルトつけて、コレットで取り付け
52mm径のモーターを装着できるCNCは工房にないので
木材の端切れの超簡易Vブロックに乗せて
モーターを固定します。
テーブルごと固定しています。
これで少々反動があっても転げることはないでしょう^^;
回転数計用のセンサーも同じく「小型工作機CNC2418 その8」で使った
古いマウスの基板をそのまま使います。
ジャーマンスタンドで回転羽根とセンサー位置を調整します。
6枚羽根なので、回転センサーからのパルスは、丁度rpmの1/10がでます。
つまり周波数カウンタの値を10倍すれば、rpmを直読できるというわけです。
測定器類をセットして配線終わりました^^;
左上から、センサー用5V電源、モーター用0~48V電源、クランプ型DC電流計
左下は、周波数カウンタ(x10でrpm値)
では、開始!
お~っ!0.98Vで回転し始めました!
左下が周波数カウンタで15.62Hzの表示なので156.2rpmです。
右上は、モーター電流、クランプ型DC電流計なので精度は悪いです。
右下が、モーターのコレット部と回転数センサー基板。
48.1Vです!
0.55A・・・無負荷時は電流がこんなに小さいんですね~
回転数 10970rpm
定格の12000rpmには、ちと届かず(T_T)
無負荷時のグラフです。
12V 2650rpm、24V 5400rpm、36V 8200rpm、48V 11000rpm
電圧 vs 回転数の直線性はいいですね~
各3回測定してますが、電流は測定精度が悪いので数十mA程振らついてます。
負荷時のデータを捕りたいですが、負荷の掛け方が浮かびません(-_-;)
手に持って、いきなり48Vを印加してみると、かなり強い反動です。
CNC2418のフレーム強度は別として
これでは、フレームへの衝撃が心配ですね~

ということで、
SOFT START、SOFT STOPにしたくなり、本題に入るわけであります^^;
正攻法で行くには、GRBLのFirmwareをイジればいいのでしょうが
C++だし、マーティーには、敷居が高すぎます(-_-;)

実は、この前、PIC 16F1827で作成した
「FrequencyとDuty比の簡易計測器」は、
GRBLコントローラからのPWM駆動パルスを検出して、
この様にDUTY比の変化をSoft Start、Soft Stopさせるつもりだったのです。

所が、エッジをカウントする方式では、
DUTY比 0%はいいとして、DUTY比 100%の時に検出できないので
PICに回路を追加しようとも考えましたが
周波数とDUTY比の検出も、今一安定しないので、PICは諦めました(-_-;)
まあ、PICの使い方を少し思い出せたのでよしとして^^;

やっぱ、ATtiny85の出番のようです。
まずは、周波数固定で、VRでDUTY比を可変できるスケッチです。
DUTY比の分解能を8bit最大にしたいので、OCR1C=255で7.8KHzに固定です。
マーティーのCNC2418は、「小型工作機CNC2418 その32」で
GRBL v1.1f デフォルトの0.98KHzでなく、v0.9jと同じ7.8KHzにしてます。

****DUTYをVRで可変、7.8KHz固定*****
//**************************************
// ATtiny85
// Freq. 7.8KHz固定
// ADC3(PB3)(pin2):VR2でDUTY比可変
// PB1(6pin):PWM OUTPUT
// Timer1 Clock:CPU、Clock:8MHz(internal)
//**************************************

#define PWM_OUT 1 // PB1(pin6)
#define Duty_VR A3 // ADC ch3(pin2)(PB3)

short Duty_Level ;

void setup() {
  // initialize
  pinMode(PWM_OUT, OUTPUT);  //PB1(pin6)
  pinMode(Duty_VR, INPUT); // ADC ch3(PB3)(pin2)
  
  // timer1 の設定 PWM出力for PB1
  TCCR1 = (1 << CTC1) | (1 << PWM1A) | (1 << COM1A1);
  //timer1 Prescaler 1/4
  TCCR1 |= (1 << CS11) | (1 << CS10);
  //周波数固定 CPU Clock 8000KHz / (255+1) / 4(Prescaler)= 7.8KHz
  OCR1C = 255 ; 
}

void loop() {
    Duty_Level = analogRead(Duty_VR);
    OCR1A = (float)Duty_Level / 1024.0 * OCR1C; // Duty比 OCR1A/OCR1C
}
*********

Arduino IDE Ver.1.8.3の設定はこれです。
新品のATtiny85は、最初に[ブートローダを書き込む]を忘れないように^^;
さて、上のスケッチでは、VRで0~Vccで可変してDUTY比を変えますが
VRのDC電圧の代わりに、PWMを平滑してADCに入れたいのです。
ATtiny85に限らず、AVRマイコンのADC入力Impedanceは、
100KΩ程度と低いです。

PWMの後にCRフィルタで平滑してADCに入力してみます。
その辺のパーツを適当に見繕って~
カットオフ周波数:1255Hzとかなり低いですが、
まだ、こんなにリップルがあります。
 黄色:ADC IN(CRフィルタ後
 水色:PWM(CRフィルタ前)

リップルが大きいので、10msec間隔でADC 10回やって平均化処理してみます。

****入力PWMと同じDUTY比で出力、7.8KHz固定*****
//**************************************
// ATtiny85
// Freq. 7.8KHz固定
// ADC3(PB3)(pin2):PWM入力をCRで平滑化してDUTY比計測
// PB1(6pin):PWM OUTPUT
// Timer1 Clock:CPU、Clock:8MHz(internal)
// ADC入力に10回平均化を追加
//**************************************

#define PWM_OUT 1 // PB1(pin6)
#define Duty_VR A3 // ADC ch3(pin2)(PB3)

short Duty_Cont = 128;
int Duty_Stack = 0;

void setup() {
  // initialize
  pinMode(PWM_OUT, OUTPUT);  //PB1(pin6)
  pinMode(Duty_VR, INPUT); // ADC ch3(PB3)(pin2)
  
  // timer1 の設定 PWM出力for PB1
  TCCR1 = (1 << CTC1) | (1 << PWM1A) | (1 << COM1A1);
  //timer1 Prescaler 1/4
  TCCR1 |= (1 << CS11) | (1 << CS10);
  // 周波数固定 CPU Clock 8000KHz / (255+1) / 4(Prescaler)= 7.8KHz
  OCR1C = 255 ;
}

void loop() {
  // 入力のリップルを平滑化するため10回の平均をとる
  Duty_Stack = 0 ;
  int i ;
  for ( i = 1; i <= 10; i++ ) {
    Duty_Cont = analogRead(Duty_VR);
    Duty_Stack = Duty_Stack + Duty_Cont ;
    delay(10) ; // 10msec delay x 10回 で平均するため
  }
    Duty_Cont = Duty_Stack / 10 ;
    OCR1A = (float)Duty_Cont / 1024.0 * OCR1C; // Duty比 OCR1A/OCR1C
}
*********

回路図はこれです。

思ったより上手くいきました^^;
入力周波数が微妙に違って、7.5KHz程なので、出力とズレてます(-_-;)
 黄色:ADC入力(pin2、ADC ch3)
 水色:出力(pin6、PB1)

DUTY比 99%辺り
 黄色:ADC入力(pin2、ADC ch3)
 水色:出力(pin6、PB1)

Vcc:5.1V  ADC入力の平滑電圧:5.07V なので
単純計算では、DUTY比 99.4% ですが、
周波数 7.8KHzで、パルスが間引かれた様になって
周波数が半分になった様な波形になってます。
まあ、モーター回す分には、ほぼ100%と変わりないでしょう。
 黄色:ADC入力(pin2、ADC ch3)
 水色:出力(pin6、PB1)

DUTY比 0%というか、ADC 入力:0V(GND)では、
出力もパルスが出なくなり、思惑通りの動作です^^;
 黄色:ADC入力(pin2、ADC ch3)
 水色:出力(pin6、PB1)

概ね、問題ない動作しているのですが、
今一つ入力のリップルが気に入りません^^;
ちょっと凝りたくなりました^^;
ADC前段を2次のバターワース・フィルタにしようかな~
もっと急峻にするなら、チェビシェフかな~
ん~ん、連立チェビシェフ(エリプティック)ってのもあったな~
凝りだしたらきりがりません(-_-;)
出所:エヌエフ回路設計ブロック

そうだ、逆転の発想で前段フィルタを取り去ってしまい
デジタルオシロのサンプリングの様にすればいいかも?
・等価時間サンプリング(Equivalent Time Sampling)
・シーケンシャル等価時間サンプリング(Sequential Equivalent Time Sampling)
というやつです。
Teltronixサイトのここの「ダウンロード・ファイル」のPDF
「オシロスコープのすべて」のP21の解説が判り易いです。
エイリアシングの発生を逆利用して入力と相似波形を再生する感じです。

マーティーも頭の整理でちょっと描いてみました^^;
連続波形ならば、INPUTに同期してない周期で長いCycleでADCすれば、
PWMとADCを直結して、INPUTと相似の波形を再構築できます。
そのADCの値を算術平均すれば、デジタルで平滑できるはずです。
まあ、先のリップルのADC 10回平均も同じことなんですが...^^;

ATtiny85 Datasheetによると、
ADCのNormal Conversions Time:13-cycle なので
ADC Clock 1MHzの時、Acquisition Time 13μsec となり、
50KHzの時、260μsecということになります。
また、
By default, the successive approximation circuitry requires an input clock frequency
between 50 kHz and 200 kHz to get maximum resolution.
とあるので、
最高解像度にするには、ADC Clock 50K~200KHzがいいということです。

System Clock 8MHzなので、ADC Clock Prescale 1/64にすれば
ADC Clock 125KHzで良さそうです。
ADC Normal Conversions Time 13-cycle・・・104μsec になります。

WoodpeckerのPWMの正確な値は、
8MHz ÷(255+1)÷ 4 = 7.8125KHz:128μsec
のはずです。
入力PWMよりADC間隔が短くなるので、サンプリングの絵を描いてみます。
ぴったり128μsecと104μsecで同期してる場合は、16分割になってしまいますが、
実際には、ADCの前後に幾らかの処理が入るし、
ATtiny85のClockは、内部RC発振+Calibrationで、水晶の精度はないので
細かい分解能で、ランダム等価時間サンプリングになるはずです。
仮に、104μsecが104.5μsecになると
上の図で8μsecの分解能だったのが、0.5μsecになり、
128 ÷ 0.5 = 256の分解能になります。
ADC 13-cycle、Prescale 1/64で、104.5μsecになるSystem Clockを逆算すると、
7.961722MHz・・・8MHzの-0.48%
これは、ATtiny85の内部Clockのバラツキでズレる範囲と考えていいでしょう。

また、Datasheetによると、内部Clockの温度変動は、
[Figure 22-41. Calibrated 8 MHz RC Oscillator Frequency vs. Temperature]
で、5V駆動時、20℃ UPで+0.05MHz程度になってるので
8MHz+0.05MHz・・・+0.625%
ということになるので、いい感じに104μsecからズレてくれそうです。
奥の手は、Datasheet[6.5.1 OSCCAL – Oscillator Calibration Register]
にあるレジスタを使えば、Runtimeで微調できますね~
工場出荷値はFuse bitにあるので消えません。
波形を観てズラせば、いいでしょう!

では、スケッチです。
PINB |= 0b1;
は、ADC完了毎にPB0をトグルしてます。
つまり、ADCの周期の1/2でPB0からパルスを出したいのです。
この前、ここ「AVRWiki」の「I/O入出力ポート」で見つけた技です^^;

***PWM直接入力、同一DUTY比でPWM出力、7.8KHz固定******
//**************************************
// ATtiny85
// Freq. 7.8KHz固定
// ADC3(PB3)(pin2):PWMを直接入力
// PB1(6pin):PWM OUTPUT
// PB0(5pin):1回のADC終了毎に反転(ADC変換時間の確認用)
// Timer1 Clock:CPU、Clock:8MHz(internal)
// ADCは512回のランダム等価時間サンプリング
//**************************************

#define PWM_OUT 1 // PB1(pin6)
#define PWM_IN A3 // ADC ch3(pin2)(PB3)

short PWM_ADC = 128;  // INPUT PWMのランダムサンプリングADC
short DUTY_Avr = 0;    // ADC_Stackの平均
long ADC_Stack ;   // INPUT PWMのランダムサンプリングADC値の蓄積用

void setup() {
  // initialize
  pinMode(0, OUTPUT);  // PB0(pin5) for ADC時間確認用
  pinMode(PWM_OUT, OUTPUT);  //PB1(pin6) for PWM OUTPUT
  pinMode(PWM_IN, INPUT); // ADC ch3(PB3)(pin2)
  
  // timer1 の設定 PWM出力for PB1(Digital 1 Pin)
  TCCR1 = (1 << CTC1) | (1 << PWM1A) | (1 << COM1A1);
  //timer1 Prescale 1/4 
  TCCR1 |= (1 << CS11) | (1 << CS10);
  OCR1C = 255 ; 
  //周波数固定 CPU Clock 8000KHz / (255+1) / 4(Prescaler)= 7.8KHz

// ADC Clock Prescale 1/64・・・ADC Clock 125KHz @System Clock 8MHz
  ADCSRA |= ( 1 << ADPS2 ) | ( 1 << ADPS1 ) ; // ADC Clock Prescale 1/64

// System Clock Fine Tuning(8MHzを微調する必要がある時のみ)
// OSCCAL = OSCCAL + 0 ;
}

void loop() {
  // ランダム等価時間サンプリング(Random Equivalent Time Sampling)して平均する
  ADC_Stack = 0 ;
  int i ;
  for ( i = 1; i <= 512; i++ ) {  //
    PWM_ADC = analogRead(PWM_IN);  // 125KHz 13cycle=104μsec
    ADC_Stack = ADC_Stack + PWM_ADC ;  //
    PINB |= 0b1; // PB0をトグル、ADC周期の時間確認用
  }
    DUTY_Avr = ADC_Stack / 512 ;  // PWMの平滑化してDUTY比を算出
    OCR1A = (float)DUTY_Avr / 1023.0 * OCR1C; // Duty比 OCR1A/OCR1C
}
*********

回路は、CRフィルタなしで、PWM波をADCに直結です。
シンプルでいいですね~^^;

オシロは[ch A&B]でトリガしてます。
PB0の1周期は、11.1DIV なので、222μsec
PB0はトグル動作なので、ADCルーチンの時間は1/2して111μsec
ADC 125KHz Sampling x 13cycle = 104μsec
実測:111μsecということは、
111-104=7μsec・・・8MHz Clockの56cycle
これが、ADC以外の処理のClock Cycleということになります。
±0.1DIVほどチラチラ変動してるので、±16 cycleの誤差かな?
ATtiny85の上を指でしばらく温めましたが、目でわかる変化はないです。
 黄色:ADCサイクル、1回のADC終了毎にトグル動作(PB0)
 水色:出力PWM(PB1)
これは、
シャッター速度:1/5sec
トリガは、水色のchA(入力PWM)で、
黄色のADCサイクルの両エッジでADCサンプリングしてますが、
非同期で写っています。
上手いことランダム等価時間サンプリングできてるということです。
 黄色:ADCサイクル、1回のADC終了毎にトグル動作(PB0)
 水色:ADC ch3:入力PWM(PWMを直接入力)
残念ながら、マーティーのオシロ DS203には、積み重ねモードがないので
シャッター速度:1/2secで!
ADCのサンプリング・ポイントのエッジが薄く沢山散らばってて
水色の入力PWMを細かくサンプリングできてそうです\(^o^)/
 黄色:ADCサイクル、1回のADC終了毎にトグル動作(PB0)
 水色:ADC ch3:入力PWM(PWMを直接入力)
入力のDUTY比を可変すると、よく追従してくれます。
111μsec間隔で512回のADCを平均してDUTY比を反映させるので
追従は、57msec!
ADC 512回の期間に、入力PWM(128μsec)が
111 x 512 ÷ 128 = 444 波形 入ることになります。
考えるのが面倒になってきましたが(-_-;)
DUTY比の平均化の計算は、最大で1波形の誤差と考えていいかな?
とすると、1/444=0.2%!
ん~ん、間違ってそうだけど、波形は期待通りだからいいか(-_-;)
 黄色:ADC ch3:入力PWM(PWMを直接入力)
 水色:PB1:出力PWM 
入力PWMは、この前作った、ATtiny85で周波数とDUTY比可変のPWM発振器
なので、周期は微妙にずれてます。
PWM発振器のVR MinでこのDUTY比。
 黄色:ADC ch3:入力PWM(PWMを直接入力)
 水色:PB1:出力PWM 

PWM発振器のVR Max。
バッチシです(^o^)
 黄色:ADC ch3:入力PWM(PWMを直接入力)
 水色:PB1:出力PWM 
入力をGNDへ
 黄色:ADC ch3:入力PWM(PWMを直接入力)
 水色:PB1:出力PWM 
入力をVcc 5Vへ
OCR1A = OCR1Cで、DUTY比 100% = DC 5Vベタになるハズだが?
まあ、いいかな^^;
 黄色:ADC ch3:入力PWM(PWMを直接入力)
 水色:PB1:出力PWM 
と思ったら、間違ってますね~(-_-;)
*********
OCR1A = (float)DUTY_Avr / 1024.0 * OCR1C;
の1024.0 ⇒ 1023.0に修正して
OCR1A = (float)DUTY_Avr / 1023.0 * OCR1C;
*********
無事、入力 Vcc 5Vで出力もDUTY比100%になりました!
今頃になって気づくとは(T_T)
 黄色:ADC ch3:入力PWM(PWMを直接入力)
 水色:PB1:出力PWM 
***訂正 2020.7.12***
居酒屋ガレージさんのここで「1023」は、間違いで
1024」が正しいと気付きましたので訂正します。

Microchip社のATmega328PのDatasheetのこのPDFを見ると
23.7の項に式と説明があります。

10bitの最大値:0x3FF(1023) は、VREF-1LSB
つまり、0x3FF+1 = 1024 が VREF
ということになりますね~


ということで
:OCR1A = (float)DUTY_Avr / 1024.0 * OCR1C;
:OCR1A = (float)DUTY_Avr / 1023.0 * OCR1C;
です。
ブログ内のほうぼうで間違ってますのでご容赦をm(_ _)m

それにしても、1024の時には
入力:5V(Vcc)でDUTY比 100%にならないのは何故だろう?
どこか別の所の式が間違ってるんでしょうね~(-_-;)

***訂正ここまで***

では、やっと、Soft Start/Soft Stop 処理を入れ込みます。

直前のDUTY比から±5%の変動があったら、
一定の傾斜で変動するモードに入る仕様にします。

0~100%を5secの傾斜とすると、50msec/%になりますが、
DUTY比計測の1回(ADC 512回の平均化処理)が57msecなので
その1回(57msec)にADC 10カウント増減の傾斜にすると、
DUTY比 0~100%、つまりADC 0~1023カウントの時間は、
1024 ÷ 10 x 57msec ≒ 5.8sec
ちょっと長いな~
では、15カウント増減の傾斜だと
1024 ÷ 15 x 57msec ≒ 3.8sec
2.6%/msec
これでいこう!
動作波形の絵をちゃんと描くのは大変なのでイメージ図です^^;
途中のDUTY比の急変動も同様に追従する仕様にします。

ひとまずスケッチ完成です!
***PWM直接入力、Soft Start/Stop処理してPWM出力***
//***********************************************
// ATtiny85
// Freq. 7.8KHz固定
// ADC3(PB3)(pin2):PWMを直接入力
// PB1(6pin):PWM OUTPUT
// PB0(5pin):1回のADC終了毎に反転(ADC変換時間の確認用)
// Timer1 Clock:CPU、Clock:8MHz(internal)
// ADCは512回のランダム等価時間サンプリング
// Soft Start/Soft Stop処理追加 
//***********************************************

#define PWM_OUT 1 // PB1(pin6)
#define PWM_IN A3 // ADC ch3(pin2)(PB3)

short PWM_ADC ;          // INPUT PWMのランダムサンプリングADC
short DUTY_Avr ;          // PWM_ADCの平均
short Last_DUTY_Avr ;  // 前回のDUTY_Avr
short New_DUTY_Avr ;  // 更新用 DUTY_Avr
int Chg_DUTY_Avr ;      // New_DUTY_AvrとLast_DUTY_Avrの差(符号あり)
// 変数 xxx_DUTY_Avr は、全て 0~1023でDUTY比 0~100%
long ADC_Stack ;           // INPUT PWMのランダムサンプリングADC値の蓄積用
signed char SignPN ;      // DUTY_Avrの前回との増減符号の±1(8bit -128~127)

void setup() {
  // initialize
  pinMode(0, OUTPUT);  // PB0(pin5) for ADC時間確認用
  pinMode(PWM_OUT, OUTPUT);  //PB1(pin6) for PWM OUTPUT
  pinMode(PWM_IN, INPUT); // ADC ch3(PB3)(pin2)
  
  // timer1 の設定 PWM出力for PB1(Digital 1 Pin)
  TCCR1 = (1 << CTC1) | (1 << PWM1A) | (1 << COM1A1);
  //timer1 Prescale 1/4 
  TCCR1 |= (1 << CS11) | (1 << CS10);
  OCR1C = 255 ; //周波数固定 CPU Clock 8000KHz / (255+1) / 4(Prescaler)= 7.8KHz

  // ADC Clock Prescale 1/64・・・ADC Clock 125KHz @System Clock 8MHz
  ADCSRA |= ( 1 << ADPS2 ) | ( 1 << ADPS1 ) ; // ADC Clock Prescale 1/64
}

void loop() {
  // ランダム等価時間サンプリング(Random Equivalent Time Sampling)して平均する
  ADC_Stack = 0 ;
  int i ;
  for ( i = 1; i <= 512; i++ ) {  //
    PWM_ADC = analogRead(PWM_IN);  // 125KHz 13cycle=104μsec
    ADC_Stack = ADC_Stack + PWM_ADC ;
    PINB |= 0b1; // PB0をトグル、ADC周期の時間確認用
  }
  DUTY_Avr = ADC_Stack / 512 ;  // PWMを平滑化してDUTY比を算出(100%:1023)
  // 前回のDUTY_Avr(Last_DUTY_Avr)との差分計算
  Chg_DUTY_Avr = DUTY_Avr - Last_DUTY_Avr ;  
  SignPN = Chg_DUTY_Avr / abs( Chg_DUTY_Avr ) ;  //※1 増減の符号 ±1 
  // SignPN = ( Chg_DUTY_Avr >> 31 ) & 1 ;  //※1代替可 int型の最上位bit 正:1、負:0
  // SignPN = ( SignPN + (SignPN - 1) ) * -1 ; //※1代替可 正:1、負:-1 に変換
  // 前回DUTY_Avrとの差が±5%以上(1024の5%=50)だったら、Soft動作する
  if ( (Chg_DUTY_Avr > 50) | (Chg_DUTY_Avr < -50) ) {
    // 更新用DUTY値(New_DUTY_Avr)に±15で変化させる
    // 57msec毎に変化するので、0~1023の変化は、1024÷15 x 0.057 ≒ 4sec
    // 差が51の時は、1回目で36になり、次が一気に3.6%変化するがいいだろう
    New_DUTY_Avr = Last_DUTY_Avr + ( 15 * SignPN ) ;
  }
  else {
    // 差が±5%未満になったら、最新のDUTY_Avr値を即反映させる(Softなし動作)
    New_DUTY_Avr = DUTY_Avr ;
  }
    Last_DUTY_Avr = New_DUTY_Avr ;
    OCR1A = (float)New_DUTY_Avr / 1023.0 * OCR1C; // Duty比 OCR1A/OCR1C
}
*********

とても珍しいことに、一発で動きました^^;
なかなか思い通りの動作をしてくれてます(^O^)
動画で!
最初は、DUTY比 99%近く設定して、電源を入れてます。
約4秒で最高DUTY比に到達します。
その後、入力PWMを急激に変化させても出力はゆっくり変化してます。
黄色:ADC ch3:入力PWM(PWMを直接入力)
水色:PB1:出力PWM 

約1Vで回転を始めるので、48Vに対して、2%のDUTY比ですが
入力PWMとADC入力を直結してて、低インピーダンスなので
ノイズは乗り難いでしょう。
また、入力PWMを57msecで平均してるので
かなりノイズが乗らないと2%に達しないと考えます。
なので、スレッショルドは設けなくていいでしょう!

さて、CNC2418のGRBLコントロールボードWoodpeckerの
スピンドルモーター駆動のPower MOS-FET:IRF540は、
RDS(on)max:0.077Ω @ID:17A なので
ON抵抗での損失が大きすぎて使えません。

取り敢えず、テストでは、昔買ってたこれを使います。
48V 20AまでモーターをPWM制御できるもので、最大定格:60Vです。
US$ 3.23(34% OFF)

そのままでは、使えないので、ちょっと分析~^^;
メインのPower MOS-FET、ちと判読し難いですが「80NF70」と読めます。
STMicroelectronicsのSTP80NF70でした。(Datasheetはここから
VDSS:68V、ID:68A(Tc 100℃)
RDS(on):8.2mΩ(VGS=10V、ID=40A)
これが2個、Gateだけ独立で駆動して、SourceとDrainは、単純パラ接です。
まあ、特性が揃ってれば、136A/4.1mΩ品1個相当です。
これは、
回生用のツインのショットキーダイオード MBRB30H60G
VR:60V(DC)
IF:15A(Average、Tc 159℃)
IFRM:30A(@20KHz方形波)
同一ペレットに2個入ってるのをパラ接で使われてます。
こちらは、特性が揃ってるからいいでしょう。
駆動パルスは、このNE555Pで生成されてます。
Vcc(推奨):16V、Vcc(絶対最大定格):18V です。
出力は、トーテムポールで、出力最大定格:±225mA です。
モーター電源(最大60V)から
ボルテージ・レギュレータ LM317で駆動用のVccが作られてます。
LM317の入力最大定格:37Vなので、入力に抵抗が入ってます。
低損失型ではないのでVIN~VOUTは、Max3.4Vもあります。
測ってみると、VIN:16V以上でVOUT:9.3Vに安定しますが、
それ以下では、単なる電圧ドロップ的に動作して
VIN:12Vでは、VOUT:7.0Vに下がります。
ボードのパターンを追ってみると
この様になってます。
STP80NF70のVGS(th)は、これです。
無負荷状態のモーターでは、IDが少ないので、5V駆動でも大丈夫でしょう。
でも、Gate抵抗を300Ωでは、心もとないのですが、
ATtiny85のI/OのPeak Current定格がDatasheetには載ってません(T_T)
単なる感ですが(-_-;) ±200mA peak辺りだろうか?
68ΩでATtiny85と接続して動作テストしてみます。
で、Gate抵抗は、ボードのこれになります。
裏面のこの部分です。
Gateの抵抗の足を浮かせます。
マーティーは、サンハヤトの「はんだシュッ太郎 30W」を使ってます。
実は、たまたまAliExpressを散歩してたら、何と極似のが!
US $8.67(30% OFF、送料 $1.27)

更に、これを発見(・o・) したので記録しておきます^^;
上のは、ポンプを毎回手動で押し込まないといけないのですが、
これは、350Wのソレノイドで電動化されてるようで、便利そうです。
が、USプラグなのに220Vと書いてあるんですよね~
US$ 23.21(21% OFF、送料 $4.84)・・・ちょっと試すには...

話はそれましたが、
サンハヤト「はんだシュッ太郎 30W」は、手動ですが、
この様にキレイに吸い取れるので重宝します。
ボードのMOS-FETと接続する前の波形と比較するために
ATtiny85の出力無負荷時のIN、OUT波形
 黄色:入力PWM 
 水色:ATtiny85出力(無負荷) 
ATtiny85出力から68ΩでMOS-FETのGateに接続すると、
立上りがだいぶ鈍りましたね~
 黄色:入力PWM 
 水色:ATtiny85出力(MOS-FET Gateに68Ωで接続) 
220Ωにしてみると、
あまり代わり映えしませんが、じっくり見ると微妙に良くなったかな?
時間軸を拡大して確認するの忘れました(-_-;)
たぶん、Drain OPEN状態だからでしょう。
68Ωで良かったかもですが、取り敢えず置いといて先に進めます(-_-;)
 黄色:入力PWM 
 水色:ATtiny85出力(MOS-FET Gateに220Ωで接続) 
やっと、スピンドルモーターの接続が試せるようになりました。

全景です^^;
スピンドルモーターは、転がらないようにクランプで固定してます。
一番左の水色の半固定VRがついたのが
ATtiny85で作った、周波数・DUTY可変できるPWM発振器です。
まずは、モーター電源 12Vで

IN、OUT波形
まあ正常そうです。
やはり、Drainに電圧がかかると波形の様相(水色)が変わりました。
 黄色:入力PWM 
 水色:ATtiny85出力(Gate抵抗 220Ω)
 同じく、12V駆動の時のDrain波形
 黄色:入力PWM 
 水色:MOS-FET Drain(入力と反転です)

では、48Vでの動作テスト全景を動画で!
最初、一気にDUTY Maxに、その後、段階的に下げて、再びMaxにして
最後にMinにしています。
 黄色:入力PWM
 水色:MOS-FET Drain(入力と反転です)

さ~て、メインのPower MOS-FETを1個にしたいのですが、
そうだ!「3Dプリンタ その34」で使った
この3Dプリンター用のヒーターの制御用のMOS-FETモジュールの
Power MOS-FETが良かったはずです。

この HA210N06 です。
ここのDatasheetでは、VDSS:60V、ID:210A、RDS(on):3.2mΩ type
ちょっとやりすぎかもですが、
ちょっとAliExpressを散策して~
US$ 0.65/個を5個にしてポチッ!  US$ 3.57(送料 $0.32)

回生用のショットキーバリア・ダイオードもでかいのを探します。
60CPQ150 60A(2 x 30A) 150V!これくらいが安心でしょう!
US$ 3.11/5個(送料 $0.72)
この手のやつを国内で買うと1個 1000円くらいします。
Datasheetは、このPDF

最終的には、こんな回路図でいこうかな~
まだ、回路図だけなので、
解説は、実際に動かしてからやりま~す^^;
ATtiny85のpinが3つも余ってるので、何かに使いたいな~
それよりもフレームの強化が先なので
のんびりいこうと思いま~す^^;

0 件のコメント: