ニックネーム: 居酒屋ガレージ店主
★ZAQのBlogari停止のため、あれこれ「データ吸い出し」対策しています。 新規記事はとりあえず停止。 コメント書き込みはまだ有効です。 (JH3DBO 下間憲行)
2015年04月23日(木)
オーバーフローするかも? そんな数値の処理
温調のためのヒータ制御に絡んで、C言語のテクニックを
紹介しておきます。

「PID」制御で目標温度に向かって温度を上昇させる
わけですが、この数値でちょいと気をつけなければ
ならないのがこの中の「I」に関する積算値です。

「I」つまり積分。
周期的に、目標値と現在温度との差を加算し続けて
積分結果を得ます。
最終的に偏差をゼロに収束させるための処理です。

今回は0.1℃単位で0〜100℃を制御します。
内部の温度データとして、0〜1000の値を扱います。
これが、制御周期で積算されるわけです。

入力として考えうる値の最大が1000。
16ビットの値(-32768〜+32767)では、最大値が継続したりすると、
しばらくするとオーバーフローするでしょう。

データを32ビットにすると、だいぶ安心ですが、それでも長時間
運転したとき、確実に数値範囲に入ってるかどうかはわかりません。

このようなとき、DSPの命令セットでは、オーバー
フローしたら正負の最大値に張り付かせるという
機能が利用できます。
正から負にオーバーフローしたら正のmax値に、負から正に
オーバーフローしたら負のmax値にという処理で、演算に
致命的な符号の反転を避けるのです。

アナログ回路を考えると、OP-AMPで作った積分回路は、その
出力が正負どちらかに張り付いて飽和します。
これと同じで動作をさせるのです。

このオーバーフローしたかしないかの確認と、飽和値の設定
方法を示します。

まず、どんなときにオーバーフローが発生するかを考えてみ
ましょう。



この図は、16ビット値の数直線(-32768〜+32767)の両端を
下に曲げたものです。
中央上が「0」。
右回りにプラス。 プラスの最大が32767。
左回りにマイナスで、最大が-32768です。

丸の下に記した左右の矢印がオーバーフローの方向
です。
この条件を2つの数値に対する「加算」で見てみます。
「+」と「-」は数値の符号です。
そして、「×」部がオーバーフローの発生する条件です。

 a + b = c
−−−−−−−−−−−−−
 a  b  c  OK
 +  +  +  ○
 +  +  -  × MAXに
 +  -  +  ○
 +  -  -  ○
 -  +  +  ○
 -  +  -  ○
 -  -  +  × MINに
 -  -  -  ○

「aとbが同符号のとき、加算結果cが
異符号になるとオーバーフロー発生」
です。

先ほどの円周で見ますと、符号付の16ビット値として
周回できる(加算あるいは減算値として)のは円周長の
半分までです。

aとbが異符号なら、aがどの位置にあってもbの値に
よらず、オーバーフローは発生しません。

aとbが同符号で、加算結果が同符号になるときは、
円周の右側(正側)あるいは左側(負側)だけでの
計算です。

結果が異符号になったということは、オーバーフロー
が発生して、円周下の矢印のような動きが発生した
わけです。

この処理を「C」で書くと、こんな具合です。
3つの数値の符号に対する「XOR」で、オーバーフローが
判断できるのです。

※ intは16ビットの符号付整数として

#define INT16_MAX 0x7FFF
#define INT16_MIN 0x8000

int add16v(int a, int b)
{
int c;        // 加算値
char sa, sb, sc;   // それぞれの+/-符号 -で1に
  c = a + b;    // まず加算 オーバーフローあるかも
  sa = (a >=0 ) ? 0 : 1;  // それぞれの符号
  sb = (b >=0 ) ? 0 : 1;  // +なら0,-で1に
  sc = (c >=0 ) ? 0 : 1;
// オーバーフロー条件の判断 符号のチェック
  if((sa ^ sc) && (sb ^ sc)){    //オーバーフロー発生
    if(sc)   c = INT16_MAX;  // 結果が-ならMAXに
    else    c = INT16_MIN;  // 結果が+ならMINに
  }
  return c;
}


DSPなら命令そのものに、こういった処理が組み込まれています。
汎用的なC言語なら、こんな具合にオーバーフローの判断を
行って、計算結果を最大最小に張り付かせます。


※追記

上の例は、オーバーフロー発生で数値の符号反転を防ぐの
が狙いでしたが、同じ考え方で、UP/DOWNカウンタの桁数
アップ処理が行えます。
例えば、8ビットのU/Dカウンタがあって、マイコンが
周期的にそのカウント値を読み出せる回路があるとし
ます。
ソフト的に設けた上位桁カウンタを、今回の考え方を使っ
てオーバーフロー検出のたびに+1/-1すれば、カウント桁数
が増やせます。
下位のハードウェアカウンタが、ソフトで間に合わない
部分を計数し、8ビットなら周波数が1/256になったとこ
ろで、上位桁をソフトがカウントするのです。

8ビットではちょいと力不足ですが、16ビットU/Dカウンタ
機能を備えたマイコンなら、たいていのメカ的2相パルス
スケールの読み出しに対応できます。



2015年4月23日 17時58分 | 記事へ | コメント(0) | トラックバック(0) |
| ・電子回路工作 |
トラックバックURL:http://blog.zaq.ne.jp/igarage/trackback/4089/
※ブログ管理者が承認するまで表示されません
コメントを記入  
お名前(必須)
 
パスワード:
 
メール:
 
URL:
 
非公開:  クッキーに保存: 
※非公開にチェックを入れると、管理者のみにコメントが届きます。
ブログの画面には表示されません。
captcha


※画像に表示されている文字を入力してください(半角・大文字/小文字の区別なし)。
文字が読みづらい場合はこちらをクリックしてください。
小文字 太字 斜体 下線 取り消し線 左寄せ 中央揃え 右寄せ テキストカラー リンク