電子回路工作

2017年5月12日 (金)

「else」抜け

仕事で使うマイコンたいてい「C言語」でプログラム
しています。
昔はアセンブラばっかしだったんで、良い世の中にな
りました。(遠い目)

しかしバグ取りの方法はあまり変わりません。
実機でプログラムを動かし、いろんな条件を変えて、
スカタンな動作をしないかどうか、あれこれ検証して
悪いところを見つけます。
これの積み重ねで、まともに動く装置が出来上がって
いくわけです。
  プログラムの変更、アセンブラの時代はROMの書き
  換えでした。
  今は、便利なツールがいっぱい。

おかしいところを見つけた時・・・
  組んだプログラムにはおかしいところが見つから
  ないぞ。
こんなとき、
  新しいハードだと、回路がおかしいかも?
  おかしなところを、装置を動かしながら
  「見える」ようにしてみよう。
などと、テストプログラムを書いたりします。
しっかり動きを確認しながら、プログラムをまとめて
いくわけです。
ややこしい装置だと、テストプログラムの方が大きく
なったりします。
  ※量産時の検査用ルーチンのほうが、実際の動作
   をするプログラムより場所をとっているなんて
   こともあります。

さて、そのおかしなところへの対策でした追加が、
また新たな虫を産むなんてことが生じます。
本人は対策したつもりになっているので「あれれ?」
でっす。

先日はこんな失敗を・・・
単純にして示します。

 if(x)      // 条件x
     a1();
 else       // それ以外
     b1();

条件「x」の時は、処理「a1」を実行。
それ以外は処理「b1」をというルーチンです。
a1あるいはb1、どちらかが実行されます。

プログラムを進めていて、このルーチンの前処理
としてちょいとプログラムを追加したのです。
こんな具合。
 if(y)       // 条件yなら
     c1();    // c1を実行を追加
 if(x)         // ↓元の処理
     a1();
 else
     b1();

条件「y」での処理を前処理として、追加したわけ
です。

しかし、落とし穴。
処理「c1」は「y」の条件で実行されるかされないか。
その後、「a1」か「b1」どちらかが実行されます。

しかし、処理「c1」で出た結果が、処理「a1」の中で
変えられることがあったのです。
これが失敗。
おかしな状態になるのは「xとy」の条件が重なった
時だけ。
だもんで、「あれれ?」だったのです。

追加した条件判断「y」では、c1だけを実行して後の
処理をスキップするのが正解でした。
こんな具合に修正して、思惑通りの処理になりました。
 if(y)
     c1();
 else if(x)    // ←このelseが重要
     a1();
 else
     b1();

これで、「c1」「a1」「b1」はどれか一つしか実行
されません。

最初から、「こうだ」と考えに至っていれば、こんな
ミスはしないんです。

  「バグを見つけてそのバグ殺しに追加した処理が
   新たなバグを産む」

この手の、ちょいミス、痛いんですよね~。
(新たな虫探しに余計な時間を食ってしまう)

| | コメント (0) | トラックバック (0)

2017年4月26日 (水)

ARMマイコンをごそごそ

お仕事です。
既存の基板の空きポートにちょいとハードを追加。

A1

0.26mmのポリウレタン線を空きピンにハンダして信号をやりとり。
0.5mmピッチの足なんでたいへん。

息を止めて… うまく付くように祈りながら…
そ~っとハンダ付け。
隣とくっつくとやり直し。

| | コメント (1) | トラックバック (0)

2017年4月 6日 (木)

「ハンダ付け補助ツール:文鎮」 今回は「男の黒」で

ハンダ付け補助ツール(文鎮) の新ロットが
やってきました。

2件のリクエストを頂戴しているので、
今回のでお分けできるのは「2つ」。

今ロットの材質は、SUSじゃなく「鉄」の塗装。
厚みが16mmになっています。 (前のは12mm)

11

左端の黄色クリップは、初回ロットの「鉄」。
手入れしてないと、うっすら錆が・・・・
その奥、青色クリップが「SUS」。
安定のステンレス。サビません。
厚みの違い、わかりますでしょうか?

お申し込みは、メールアドレスを記入の上、まずは
この記事に書き込みしてください。
  (お届け先などはメールでやりとりします)

今ロットの文鎮、代金は「1000円」。
   ※クリップは付いていません。
     65mm幅のを買ってください。
お届けはレターパックで。
   ※ライトかプラスをご指定ください。
     郵便受けに入らないときは対面受け渡しのプラスを。
口座をお知らせしますので、代金+送料を振り込んでください。


※2017-04-07
今回のロット、完売しました。
リクエストいただければ、次回の製作に向けて動きますので。
また、使用感やご意見など歓迎します。

| | コメント (8) | トラックバック (0)

2017年3月22日 (水)

「6809」で制御していました

「ザイコー X2212」 が乗った回路、日立の「6809」 で制御
されていました。 

11

頂戴した回路図の日付が「1984」年。
30年以上前の設計です。

| | コメント (0) | トラックバック (0)

2017年3月17日 (金)

動いたの?

ひさしぶりに引っ張り出してきた実験用電源。
+5V、±15V出力の3出力スイッチング電源を
ベースに、0~±12Vの可変電圧トラッキング
電源(シリーズレギュレータ)を仕込んだもの。
アナログ回路の実験用です。

机の上に置いたら、なぜかガタガタ。
ひっくり返してみたら、「貼り付けゴム足」が
移動!

11

本来、四隅に貼り付けてあったのが・・・
なぜ?

移動の痕跡↓
12

| | コメント (1) | トラックバック (0)

2017年3月 8日 (水)

「8749」を書くなんてひさしぶり・・・

29年前に作ったツール:スケーリング機能付アップダウン・カウンタ
制御プログラムをちょいと変えたいということで、ひさしぶりにPC-9821を
起動。
MS-DOSですな~。
使うのは自作の8748、49ライター。

11

しかし、・・・・ すんなりとはいきませんでした。
PC98のバックアップ電池がアウトに。
カレンダーが狂っています。
   ※リチウム・バナジウム充電池
    VL2330 が使われていました。
    とりあえず、3セルのNiCdを仮つなぎ。

ひさしぶりの「VZエディター 」、WIn環境でばかし仕事してると、
感覚が戻りません。

アセンブラはCP/Mの「MAC」を改造した8048用MAC。
これをMS-DOS環境で動くようにしたもの。

   ※ソースを逆アセンブル。
    8080コードから8086コードにニーモニック変換して
    MS-DOS上でアセンブルしたもの。
    ファイルハンドルじゃなく、CP/MのFCBでアクセス
    しているから、実行中の「ctrl-C中断」は厳禁。

12

懐かしの黒バックに白文字に癒されます。

NECとインテルのチップが残っていました。
13

※チップの拡大 見えるかな?
・NEC製
・インテル製

| | コメント (0) | トラックバック (0)

2017年3月 6日 (月)

29年前に製作したツール

29年前に作ったツール:スケーリング機能付アップダウン・カウンタ
をひさしぶりに動かしました。
1988年2月に製作。

基本は、2相パルスをU/Dカウントして、カウント値を表示するだけの
ものなんですが「スケーリング機能」を入れてあります。

11_3

2相パルス10000で12.3mのスパンを移動などという時、
デジタルスイッチでパルス数と実距離との比率を設定
できるようにしてあるのです。

使ったマイコンは8748(回路には8749が乗っていた)。
カウンタは「HP」の「HCTL-2000」。
12ビットのカウンタです。

12_2

13

長いこと使ってなかったんで、
  『電源のコンデンサ液漏れでもしてないか?』
っと不安で、ケースを開けてみました。
大丈夫でした。

回転角度絡みで、ロータリー・エンコーダをつないで
ちょいと検証に使います。

※参考:
Vector:8749を使ったアップダウンカウンタ
プロセッサ目次  …1989年12月号に掲載してもらっています

※回路図(BIDツールで)
Udcnt
(クリックで拡大↑)

| | コメント (0) | トラックバック (0)

2017年2月26日 (日)

グルグル回る軸の角度変動の平均値を出す方法#4

回転角度の平均値計算
風向の平均計算

グルグル回る軸の角度変動の平均値を出したい
グルグル回る軸の角度変動の平均値を出す方法
グルグル回る軸の角度変動の平均値を出す方法#2
グルグル回る軸の角度変動の平均値を出す方法#3 

これのまとめです。

ひとつのルーチンで、いくつもデータを扱えるようにしてみました。
これまでのは、平均処理したい角度がいくつもある場合、
それぞれの値に対して関数を作らなくちゃなりませんでした。

これも面倒なんで、移動平均処理するそれぞれのデータを
置いておく場所を「構造体」で記述し、一つの関数でこれを
処理できるようにしました。
構造体はそれぞれの角度ごとに必要ですが、それを処理
する関数は一つだけ。
入力データ値と構造体名、それに平均する回数を指定して
関数を呼び出します。

こんな具合・・・・

//    BYTEとWORD
typedef unsigned char    BYTE;
typedef unsigned short   WORD;
#define PAI   3.141592654  // πの値

/***** 四捨五入    *****/
//   正負で±0.5して整数に変換
short rounds(float d)
{
  if(d >= 0){
    return (short)(d + 0.5);
  }else{
    return (short)(d - 0.5);
  }
}

/***** 360度1回転規制   *****/
//   0~359度を得る
WORD lim359(short d)
{
  if(d < 0){       // マイナスかもしれない
    d = -d;       // 正の数に
    d = d % 360;    // 0~359に
    d = 360 - d;    // 360から減算
  }
  d = d % 360;      // 0~359に
  return d;
}

/***** 角度スムージング処理  *****/
// 計算のための構造体
typedef struct{
  short  *bfx;      // Xスムージングバッファ
  short  *bfy;      // Y
  long  adx;      // X合計加算値
  long  ady;      // Y
  short  p;       // データポインタ
  short  f1;       // 初回チェックフラグ
}SMZ_359;

/***** 角度スムージング処理  *****/
// 浮動小数点計算での誤差を累積ささないため
// X,Yを10000倍したwordデータで計算する
// sin,cos ±1.0が最大なので2バイトで足りる
// deg : 0~359 入力角度
// smz : スムージングバッファ 構造体
// size: スムージング処理加算回数=バッファの大きさ 
WORD smz359c(short deg, SMZ_359 *smz, const WORD size)
{
short *px, *py;
short i, x, y;
float d, e;
  PH3_H;         // (!!!)PH3 17pin H/L
  d = (PAI / 180.0) * (float)(lim359(deg));  // 0~2πに
  x = rounds(cos(d) * 10000.0);    // X,Yの値
  y = rounds(sin(d) * 10000.0);    // 10000倍して整数で
  if(smz->f1 == 0){          // 初めて
    smz->bfx = malloc(sizeof(short) * size); // バッファ確保
    smz->bfy = malloc(sizeof(short) * size);
    if((smz->bfx == NULL) ||         // メモリ確保失敗なら
      (smz->bfy == NULL))   return deg; // 元数値を持ってリターン
    smz->adx = (long)x * size;   // X,Y合計加算値
    smz->ady = (long)y * size;
    px = smz->bfx;         // バッファの先頭
    py = smz->bfy;
    for(i = 0; i < size; i++){   // バッファを初期値で埋める
      *px++ = x;
      *py++ = y;
    }
    smz->p = 0;          // データポインタ先頭に
    smz->f1 = 1;          // 初回処理終了
  }
  else{                // 2回目以降
    px = smz->bfx + smz->p;
    py = smz->bfy + smz->p;
    smz->adx = smz->adx - *px + x; // 古い値を引いて
    smz->ady = smz->ady - *py + y; // 新値を加算
    *px = x;            // 新値をセット
    *py = y;
    smz->p++;            // ポインタを後ろに
    if(smz->p >= size) smz->p = 0; // 最後まで来たらゼロに
  }
  e = 10000.0 * (float)size;     // スケーリング
  d = (180.0 / PAI) *         // 角度に
     atan2((float)smz->ady / e,  // X,Y平均値
        (float)smz->adx / e);
  PH3_L;               // (!!!)PH3 17pin H/L
  return lim359(rounds(d));      // 0~359
}

// ★使用例
BYTE f_tm10ms;    // A/D値が10mSごとに確定 (0/1)
WORD ad_deg;     // A/D値から算出した角度データ (0~359度)
SMZ_359 smz_deg;   // 角度データ平均用配列:構造体
    :
    :
// 1秒ごとに平均角度を出力
  if(f_tm10ms){  // 10mSごとにA/D値が確定
    printf("%3d deg\n",           // 3桁で出力
        smz359c(ad_deg, &smz_deg, 100)); // スムージング処理
    f_10ms = 0;
    :
  }

※全角スペースを使ってます。

移動平均データを置いておく配列は「malloc」でメモリーを確保。
メモリー不足だった場合は平均処理は行わず、元データを持って
リターンするようにしています。

メモリー不足のエラーは出していません。
smz.bfx、smz.bfyがNULLじゃないことを、この関数実行後に
別場所で調べればと。
あるいは、smz.f1が1ならメモリー確保成功していると判断で
きます。

| | コメント (0) | トラックバック (0)

2017年2月24日 (金)

グルグル回る軸の角度変動の平均値を出す方法#2

グルグル回る軸の角度変動の平均値を出す方法 の続き。

浮動小数点でX、Y値と合計値を保持するのが不安
(誤差の累積)なので、整数で保持するように変えて
みました。

sin、cosで出たXとYの値は0~±1.0。
一万倍して±10000なので、ワードデータに納まります。

// 浮動小数点計算での誤差を累積ささないため
// X,Yを10000倍したwordデータで計算する
// sin,cos ±1.0が最大なので2バイトで足りる
WORD smz359b(short deg)
{
static short smz_x[SMZ_SIZ];      // Xスムージングバッファ
static short smz_y[SMZ_SIZ];      // Y ★
static long ttl_x, ttl_y;       // 合計値 ★
static BYTE f1 = 0;           // 初めての処理
static short p = 0;           // データポインタ
short i;
short x, y;
float d;
  PH3_H;               // (!!!)PH3 17pin H/L
  d = (PAI / 180.0) * (float)(lim359(deg));  // 0~2πに
  x = round(cos(d) * 10000.0);    // X,Yの値 ★
  y = round(sin(d) * 10000.0);    // 10000倍して整数で
  if(f1 == 0){            // 初めて
    ttl_x = x * SMZ_SIZ;      // X,Y合計値 ★
    ttl_y = y * SMZ_SIZ;
    for(i = 0; i <SMZ_SIZ; i++){  // バッファを初期値で埋める
      smz_x[i] = x;
      smz_y[i] = y;
    }
    p = 0;             // データポインタ
    f1 = 1;             // 初回処理終了
  }
  else{                // 2回目以降
    ttl_x = ttl_x - smz_x[p] + x;  // 古い値を引いて ★
    ttl_y = ttl_y - smz_y[p] + y;  // 新値を加算
    smz_x[p] = x;          // 新値をセット
    smz_y[p] = y;
    p++;              // ポインタを後ろに
    if(p >= SMZ_SIZ)  p = 0;   // 最後まで来たら先頭に
  }
  d = (180.0 / PAI) * atan2(         // 角度
      (float)ttl_y / (10000.0 * SMZ_SIZ), // X,Y平均値 ★
      (float)ttl_x / (10000.0 * SMZ_SIZ));
  PH3_L;               // (!!!)PH3 17pin H/L
  return lim359(round(d));      // 0~359
}

※全角スペースを使ってます。

★の所が変更点。
shortの整数に。
intと書くと、チップが32ビットなのでlongのデータになって
しまいます。

それと、atan2()のX、Yを求めている所、
    (float)ttl_y / 10000.0 / SMZ_SIZ
と書くと、コンパイラは除算を2回繰り返していました。
    (float)ttl_y / (10000.0 * SMZ_SIZ)
だと、( )内が定数になって、除算は1回だけ。

※検索:角度の平均値計算

※続き:グルグル回る軸の角度変動の平均値を出す方法#3

| | コメント (0) | トラックバック (0)

2017年2月23日 (木)

グルグル回る軸の角度変動の平均値を出す方法

2016年09月07日:グルグル回る軸の角度変動の平均値を出したい  で
話題にしました「0~359度」ぐるぐる回る軸の回転角度の平均値算出。
これをまとめておきます。

関連するのは初めての「部品」は失敗するかも  の
「ストッパー無しのボリューム」。
この抵抗値から「0~359度」を得たい時の平均値の算出方法です。
単純な加算平均だと「359←0→1」を行き来すると、「180」なんて
値が出てしまいます。

そこで、角度をsinとcosでXとY値に分解して、2つ値を移動平均。
平均値として出てきたXとYから「atan2」で角度を得るという手法です。

sin、cos、atan2関数をそれぞれ1回ずつ実行します。
値により実行時間は変動しますが、32MHzのRX220マイコン
(非力なんでハード的な浮動小数点機能は無い)で処理時間
は100~130μSくらいでした。
  (空きの出力ポートにパルスを出してオシロで時間確認)

// 非力なマイコンなので浮動小数点はfloatで。 doubleではない
// BYTEとWORDの定義
typedef unsigned char    BYTE;
typedef unsigned short   WORD;
// πの値
#define PAI   3.141592654

/***** 四捨五入    *****/
//   正負で±0.5して整数に変換
short round(float d)
{
  if(d >= 0){
    return (short)(d + 0.5);
  }else{
    return (short)(d - 0.5);
  }
}

/***** 360度1回転規制   *****/
//   0~359度を得る
WORD lim359(short d)
{
  if(d < 0){       // マイナスかもしれない
    d = -d;       // 正の数に
    d = d % 360;    // 0~359に
    d = 360 - d;    // 360から減算
  }
  d = d % 360;      // 0~359に
  return d;
}

/***** 角度をスムージング   *****/
// in/out deg:0~359度を得る
#define SMZ_SIZ   20     // スムージング回数

WORD smz359(short deg)
{
static float smz_x[SMZ_SIZ];      // Xスムージングバッファ
static float smz_y[SMZ_SIZ];      // Y
static float ttl_x, ttl_y;       // 合計値
static BYTE f1 = 0;           // 初めての処理
static short p = 0;           // データポインタ
short i;
float x, y, d;
  PH3_H;               // (!!!)PH3 17pin H/L
  d = (PAI / 180.0) * (float)(lim359(deg)); // 角度を0~2πに
  x = cos(d);             // X,Yの値
  y = sin(d);
  if(f1 == 0){            // 初めて
    ttl_x = ttl_y = 0.0;      // バッファを初期値で埋める
    for(i = 0; i <SMZ_SIZ; i++){
      smz_x[i] = x;
      smz_y[i] = y;
      ttl_x += x;         // 合計値
      ttl_y += y;
    }
    p = 0;             // データポインタ
    f1 = 1;             // 初回処理終了
  }
  else{                // 2回目以降
    ttl_x = ttl_x - smz_x[p] + x;  // 古い値を引いて新値を加算
    ttl_y = ttl_y - smz_y[p] + y;
    smz_x[p] = x;          // 新値をセット
    smz_y[p] = y;
    p++;              // ポインタを後ろに
    if(p >= SMZ_SIZ)  p = 0;   // バッファの最後まで来たら先頭に
  }
  x = ttl_x / SMZ_SIZ;        // X,Y平均値
  y = ttl_y / SMZ_SIZ;
  d = (180.0 / PAI) * atan2(y, x);  // atan2でX,Yから角度に
  PH3_L;               // (!!!)PH3 17pin H/L
  return lim359(round(d));      // 0~359
}

※半角スペースだと見にくくなるんで全角スペースを使っています。

★:整数で計算すると・・・グルグル回る軸の角度変動の平均値を出す方法#2

※検索:角度の平均値計算

| | コメント (1) | トラックバック (0)