JP7FKFの備忘録

ヒトは,忘れる生き物だから.

Microsoft Comfort Mouse 6000の修理

メインPC(Windows)の入力インターフェースとして,マウス,Microsoft Comfort Mouse 6000を使っています.
ちなみにキーボードはHHKB Pro.

ある日CADを使おうとしたら,マウスの中ボタンクリック(ホイールクリック)が効きづらくなっていることに気づいた.
CADで中ボタンって結構重要な役割なんですよね.視点変更とか色々.
かなり長く使っているしそろそろスイッチの寿命だったのかもしれない.

ということで,分解清掃して,スイッチを交換することにした.
まずは裏のソール上下二箇所を外します.両面テープ止めになっている.
そうするとネジが見えるので,すべて外します.
これでカバーが外れます.
f:id:jp7fkf:20160906105721j:plain

結構簡単な作りですね.
基板.
f:id:jp7fkf:20160906105906j:plain

スクロールホイールの右側に,中ボタンクリック検知用のタクトスイッチがあります.
中ボタンってタクトスイッチだったのね.
これは修理してしまった後の画像になりますが….
f:id:jp7fkf:20160906110038j:plain

赤いタクトスイッチに交換しています.
これは普段見る,普通のタクトスイッチですが,はじめに基板についていたものは,スイッチの押す部分がもっと長いものでした.
なので,私は瞬間接着剤で適当なプラスチック片を貼り付けて高さを稼いでいます(笑).

この交換用のスイッチですが,秋月によさげなスイッチがありました.
長さ的には,おそらくこれくらいだったと思うので,修理にはこれが最適かもしれません.
タクトスイッチ(黒色): パーツ一般 秋月電子通商 電子部品 ネット通販
もちろん私のように,普通の背の低いタクトスイッチにいい感じにバイアスしても良いと思いますが,やっぱり美しい方がいいと思います.

この長い棒の部分のところに,小さなスプリングが入っており,あの独特のホイールクリックの感覚になっているのでした.

修理方法はいたって簡単で,単純にスクロールホイールを外し,下の基板を固定しているネジを外し,基板からタクトスイッチを取っ払って新しいものと交換するだけです.

これでCADを快適に使えるようになりました.

サインスマート製のAD9851モジュールの試食

秋月電子で売られているサインスマートのDDSモジュール(http://akizukidenshi.com/catalog/g/gM-09945/)をPICとARMで試食した.

使ってみた感想としては,シリアル経由で簡単に扱えることがまず一番嬉しい点.
あとはモジュールにフィルタやらなんやらがすでに入っているので余計な労力を使わなくてもそれなりの高周波が得られる点.

ちょっと気になった点としては,このモジュール結構発熱する気がします.
高い周波数にすればするほど発熱します.最高周波数にすると結構な熱をもちます.
ICのAbsolute Maximumは結構高いけどちょっと心配.

Arduinoでのサンプルプログラムは秋月のHPからDLできるが,PICでやっている人を見つけられなかったので,誰かがARMかなんかでやっていたやつをPIC用に改造してみた.
最後にコードを載せておきます.

まだ信号の位相ノイズとかジッタとか高調波をスペアナで見たりはしていないのだけど,簡単な高周波測定器の自作には向いていると思った.
f:id:jp7fkf:20160905194817j:plain

// PIC16F88 Configuration Bit Settings

// 'C' source line config statements

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG1
#pragma config FOSC = INTOSCIO  //  (INTRC oscillator; port I/O function on both RA6/OSC2/CLKO pin and RA7/OSC1/CLKI pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital I/O, MCLR internally tied to VDD)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF         // Low-Voltage Programming Enable bit (RB3/PGM pin has PGM function, Low-Voltage Programming enabled)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off)
#pragma config CCPMX = RB0      // CCP1 Pin Selection bit (CCP1 function on RB0)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

// CONFIG2
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor enabled)
#pragma config IESO = ON        // Internal External Switchover bit (Internal External Switchover mode enabled)

#define PIN_DATA RA0
#define PIN_FQ_UD RA1
#define PIN_W_CLK RA2
#define PIN_RESET RA3
#define _XTAL_FREQ 8000000

#include <xc.h>
#include <pic16f88.h>

void init();
void wr_serial(unsigned char w0,double frequence);
void reset();
void set_freq(unsigned long  freq);

void main(void)
{
  init();
  reset();
  wr_serial(0x01, 30000000);

  while(1)
  {
    
  }
}

void init()
{
  CMCON = 0b00000111; //cut off analog comparator just add this one
  INTCON = 0; // purpose of disabling the interrupts.
  OSCCON = 0b01111010;
  TRISA = 0b00000000;
  TRISB = 0b00000000;
  PORTA = 0b00000000;
  PORTB = 0b00000000;
  ANSEL = 0b00000000;
}

void set_freq(unsigned long  freq)
{
  // freq (delta phase)
  for (int i = 0; i < 32; i++) {
      PIN_DATA = (freq>>i & 1);
      PIN_W_CLK = 1;
      __delay_ms(1);
      PIN_W_CLK = 0;
      __delay_ms(1);
  }

  // control bits
  PIN_DATA = 1;
  PIN_W_CLK = 1;
  __delay_ms(1);
  PIN_W_CLK = 0;
  __delay_ms(1);
  PIN_DATA = 0;
  PIN_W_CLK = 1;
  __delay_ms(1);
  PIN_W_CLK = 0;
  __delay_ms(1);

  // powerdown
  PIN_DATA = 0;
  PIN_W_CLK = 1;
  __delay_ms(1);
  PIN_W_CLK = 0;
  __delay_ms(1);

  // phase
  for (int i = 0; i < 5; i++) {
      PIN_DATA = 0;
      PIN_W_CLK = 1;
      __delay_ms(1);
      PIN_W_CLK = 0;
      __delay_ms(1);
  }

  PIN_FQ_UD = 1;
  __delay_ms(1);
  PIN_FQ_UD = 0;
  __delay_ms(1);
}

void reset() {
  // ensure low
  PIN_DATA = 0;
  PIN_FQ_UD = 0;
  PIN_W_CLK = 0;

  // reset
  PIN_RESET = 1; 
  __delay_ms(1000);
  PIN_RESET = 0;
  __delay_ms(1000);

  // reset to serial mode
  // Pins of D0, D1 = 1, D2 = 0 for serial mode
  PIN_W_CLK = 1; 
  __delay_ms(1);
  PIN_W_CLK = 0;
  __delay_ms(1);

  PIN_FQ_UD = 1;
  __delay_ms(1);
  PIN_FQ_UD = 0;
  __delay_ms(1);
}
    
void wr_serial(unsigned char w0,double frequence)
{
  unsigned char i,w;
  long int y;
  double x;

  //Calculate the frequency of the HEX value
  x=4294967295/180;//Suitable for 180M Crystal  125-180 
  frequence=frequence/1000000;
  frequence=frequence*x;
  y=(long int)frequence;

  //write w4
  w=(y>>=0);
  for(i=0; i<8; i++)
  {
    PIN_DATA = ((w>>i)&0x01);
    __delay_ms(1);
    PIN_W_CLK = 1;
    __delay_ms(1);
    PIN_W_CLK = 0;
    __delay_ms(1);
  }
  //write w3
  w=(y>>8);
  for(i=0; i<8; i++)
  {
    PIN_DATA = ((w>>i)&0x01);
    __delay_ms(1);
    PIN_W_CLK = 1;
    __delay_ms(1);
    PIN_W_CLK = 0;
    __delay_ms(1);
  }
  //write w2
  w=(y>>16);
  for(i=0; i<8; i++)
  {
    PIN_DATA = ((w>>i)&0x01);
    __delay_ms(1);
    PIN_W_CLK = 1;
    __delay_ms(1);
    PIN_W_CLK = 0;
    __delay_ms(1);
  }
  //write w1
  w=(y>>24);
  for(i=0; i<8; i++)
  {
    PIN_DATA = ((w>>i)&0x01);
    __delay_ms(1);
    PIN_W_CLK = 1;
    __delay_ms(1);
    PIN_W_CLK = 0;
    __delay_ms(1);
  }
  //write w0
  w=w0;
  for(i=0; i<8; i++)
  {
    PIN_DATA = ((w>>i)&0x01);
    __delay_ms(1);
    PIN_W_CLK = 1;
    __delay_ms(1);
    PIN_W_CLK = 0;
    __delay_ms(1);
  }
  __delay_ms(1);
    PIN_FQ_UD = 1;
  __delay_ms(1);
  PIN_FQ_UD = 0;
  __delay_ms(1);
}

PIC16F88を用いた周波数カウンタの作製

とりあえず一通りの測定器が欲しいわけなので,周波数カウンタを持っていなかったから作ってみた.

とはいえ自分で一から作ったわけではなく,こちら(PIC<40>)を参考にさせていただいた.
PIC16F88を用いて,直接計数方式でカウントしている.
1:1, 1:8のプリスケーラが選べて,1secと0.1secのゲートタイムが選べる.

作製したものがこちら.
外観はこんな感じ.
f:id:jp7fkf:20160905192621j:plainf:id:jp7fkf:20160905192642j:plain

頑張って小さいサイズに収めれるように,PICはICソケットで下駄を履かせずに直接ユニバーサル基板にハンダしてます.
あとは小型化のために,小型のLCD(http://akizukidenshi.com/catalog/g/gP-01797/)を用いています.
これ,超小型LCDとかいてあるけど,どっちかというと超薄型と記載したほうがいい気がする.
TFT液晶と比べるとバックライトあたりが厚くて全然超薄型でもないんだけど.
f:id:jp7fkf:20160905192702j:plainf:id:jp7fkf:20160905192731j:plain
f:id:jp7fkf:20160905192558j:plainf:id:jp7fkf:20160905192522j:plain

スプラッシュ表示と,測定画面.
f:id:jp7fkf:20160905192810j:plainf:id:jp7fkf:20160905192749j:plain

作るのは簡単でした.
しかしながら,上記の紹介されていたHPの作り方では2SC1815のベースにカップリングコンデンサ経由で信号を入れていたので,もうちょっとハイインピーダンスなもので信号を終端したい気もする.J-FETかMMICかオペアンプかなんかで.
あと50Ω終端もあると便利なのかな.

あと,基準クロックに20MHZのクリスタルオシレータを用いているのですが,これがTCXOではないため,温度の影響を受けます.
電源投入後直後からだんだんと表示周波数が上がっていき,"ハー"と息を吹きかけると一時的に周波数が上昇します.
まあ変動幅が数十Hzくらいなので,あまり気にしていません.普段使う分には〜10Hzくらいの偏差で済んでいます.

あと,1secと0.1secのゲートタイムで測定に差があります.
タイマのレジスタにセットする値と,NOP命令で調整はしてみたのですが,
1secと0.1secのどちらのモードもぴったりに合わせるということはできませんでした.
まぁif文で1secと0.1secを判別して,NOPの数を変えてしまえば済むことかもしれないのですが,時間的にクリティカルな場所にif文を置きたくないと思いました.
たぶんきちんとがんばって値を探っていくと,どっちもいいかんじになる最適値がわかる気がします.
NOP命令1つあたりの測定周波数の差と,タイマのレジスタ1ビット変えた時の測定周波数の差から計算してみようと思ったところで終わっています.たぶんこれで計算すればいけるはず.

とりあえずアマチュア用途くらいには使えそうな周波数カウンタができました.
今後改造するならば,TCXO化と,入力回路の改造(終端抵抗値の変更(1MΩと50Ωくらい?)),とレジスタの設定値,NOPの数の最適値を探ることです.
改造するかすらわかりませんが.

つくりたいもの

今後作りたいものがいろいろある.


・デジタルSWRメータ
氾濫原さん(https://lowreal.net/2016/03/08/1)の記事を見て作りたくなって作ってる.
デジタルSWRメータの作製1 =方向性結合器の作製= - JP7FKFの備忘録
デジタルSWRメータの作製2 =方向性結合器の作製2= - JP7FKFの備忘録
このエントリでも紹介してあったが,方結がうまく動いてなくて止まってた.
原因はなんとコアを通る同軸の外皮の両端がシャーシ(GND)に落としてあるということだった.
当たり前だ.GNDを伝わる電流がコア内部を流れてしまう.
これに気づくのにしばらくかかってしまった.わけがわからない.
ということでうまくいきそうです.
(というか今の所PICマイコン(PIC16F88)を使って仮組みしてあるのですが,かねいい感じです)
ただ,PICのメモリが今の時代にしては極端に小さく,POWER関数を計算するだけでプログラムメモリがあっぷあっぷで,他の実装がろくにできません.進行波,反射はの電力とSWRを計算して出すくらいはできるんだけど.
なので,ARMに移植してみようかなと考えています.
PIC16F88は10bitADCしかもっていないため,特に大電力域での電力分解能が著しく落ちます.
なので,少なくとも12bitADCを使いたい.なので,12bitADCが内蔵されていて,かつプログラムメモリも十分であるSTM32F042(http://akizukidenshi.com/catalog/g/gI-10789/)なんかを使ってみようかと考えている.
正直オーバースペックなのだが,なんにせよこの価格は安い.なのでまぁいいかという感じ.

・アンテナアナライザ
これも氾濫原さんのところで見たやつです.
簡単かつ安く高精度なアンテナアナライザーを自作したい | tech - 氾濫原
アンテナアナライザーをケースに収めた | tech - 氾濫原
市販のアナライザと同じような波形が出ていて,十分使い物になりそう.
先日AD9851のモジュール(http://akizukidenshi.com/catalog/g/gM-09945/)をPICやらnucleoでいじってみたのだけど,簡単なシリアル通信で周波数設定ができるし,非常に使い易い.
なので私にもできそう.今はRFスイッチの入手をどうしようか苦労してる.

・VNA
これはHFアップコンバータなどの頒布でもお世話になったTT@北海道さんのところの記事で見た.
DDS AD9859とGNURadioでVNAを作ってみる(5.周波数レンジ拡大2GHz編) - Computer Radio RF Tech
VNA製作(6):matplotlibとSciKit-RFによる校正とスミスチャートのプロット - Computer Radio RF Tech
HFコンバータキットのポート特性を自作VNAで眺めてみる - Computer Radio RF Tech
NanoVNA(仮称)を製作予定です - Computer Radio RF Tech

非常によくできており,DG8SAQさんのところのVNWA(http://sdr-kits.net/VNWA3_Description.html)とも良く似た特性が出ていて(仕組みは同じだから当たり前といえば当たり前なのだが)使い物になりそう.
AD9859が若干高価なのが痛い.
けど,RSオンラインでAD9859は手に入るし,ミキサであるSA612もRSで手に入る.
なので実現はできそう.
私の場合これにBluetoothやら何やらで他の液晶に転送して表示するということをやりたいかもしれない.
たぶんnanoVNAでTT@北海道さんがSDカードソケットをつけているのはFlashAirをつけて同じようなことをしようとしているのか?とも思った.

オシロスコープ
オシロを持ってない.高価なので買う気になれないので作りたい感じ.
別に高機能を求めているわけでなく,時々信号が見たいときがあるのでそういう時に使えればいいかなという感じ.
ATT,アンプと高速ADC,CPLDSRAMMPUで構成しようかなという感じ.
おそらく観れるのは10MHzくらいが限度か?
なので最近はCPLDに手を出そうとしています.
で,CPLDは所持しているのですが書き込み機を持っていません.
なので書き込み機を作るところからです.
JTAGの書き込み機を自作しているページがちらほらあるので,まずはLチカ(もしくはAND回路?)からかな?

で,ここまで書いて思った事.
自分は誰かのやっていることをコピーしているだけで,オリジナリティがないなぁと思う.
TT@北海道さんなんかはアイディアも知識も技能も素晴らしく,いろいろなモノの組み合わせで新しい事をしている.
氾濫原のcho45さんなんかは,webまわりのプログラミング知識だけでなくRFにも精通する人で,この方も新しい事をしている.

私はそんな人をただ真似ているだけで,新しい事をしていない.
第一,私はもともと新しいことをしたいわけじゃなく,測定器やら機材にあまりお金をかけられないので,自分で作ってしまいたいという思いがあるからなのかもしれない.まぁパーツやなんやらを買うと測定器が買えてしまうくらいのお金をかけている場合もよくあるのだが,作るとともに知識も同時に得る事ができればと思っている.
なので,作っている時はあんまり楽しくない(要は作業だから)ときもある.
だが自分でその測定器やら機材を手に入れたいから作る.

しかし最近はちょっと新しいこともしたいなという思いもある.
楽しみながらやる工作っていいよなと思う.
そもそも,そういうものがものづくりの根底な気もする.
という最近の心情.

作れる測定器をさっさと作って,そろそろ新しいことをやってみようかなという感じ.

オーディオレベルメータを作ってみた

本題のとおり,以前作成したD級アンプ(TPA3122D2を用いたD級アンプの製作 - JP7FKFの備忘録)にレベルメータを追加してみた.

www.youtube.com

回路は簡単に,オペアンプで入力信号を増幅して,マイコンのADCで受ける.

そのADCの値に応じてLEDを光らせるという単純なものだ.
入力まわりの回路は以下のようにした.
f:id:jp7fkf:20160811223319p:plain
入力側から,DCカットのコンデンサ,非反転増幅をするオペアンプ,半波整流,そして最後にLPFを入れている.

入力は,RかLの片一方を取っている.今回はバーLEDを一つしか使わないので,それでいいと思った.
本気でやるなら,RとLの平均を取ったりなんだりするんだろうけど,別にRとLは多くの場合同じような音圧だと思うし,私はそこまで真面目にレベルメータを使おうと思ってないし.

真面目に作るなら音圧レベルに応じてキャリブレーションしたりなんだりきちんとするべきだし.

オペアンプの増幅度は適当に実験しながら決めればいいと思う.
整流はめんどくさいので小信号用ダイオードでカジュアルに半波整流.

LPFの定数も,作りながら適当に決めた.
ゆっくり下がっていくのが好きな人もいれば,LEDが音声に応じて高速にチカチカ応答してくれるのが好きな人もいるだろうから,
これは個人の好きな時定数を選べばいいと思う.

実のところ,間違って開けた穴をなんとかして塞ぎたかっただけなのだが,
案外いいかんじのアンプになったと思う.
音楽に合わせてレベルメータが上下してくれるとやはりなんだか楽しい.
また,このアンプもレベルメータも自分でつくったもんだから,愛着はやっぱり計り知れない.

また,音質にこだわる人はこのレベルメータによる音質低下を懸念されるかもしれないが,
今の所特に気になる点はない.というか,私はもともとそこまでこだわって聞いていない.

普通に使う分にはD級アンプサイコーです.省電力だし小型だし.

しかしこれだとまぶしくてウザいということになりかねない.
今,電源ONから遅延させてスピーカー出力のリレーを駆動させている部分にPICマイコンを用いているのだが,そのマイコンの足が空いてるので,その足とメインボリュームのON,OFFのタイミングをうまく組み合わせて,レベルメータの有効,無効を切り替えれるようにしたいと思っている.

具体的には,メインボリュームをONにしてLEDのblinkingが始まって,それが終わるまで(出力ONになるまで)の間にボリュームがOFFになったときに,有効から無効,または無効から有効に切り替え用と思っている.
これはマイコン内部のEEPROMに保存しておいて,電源を切っても前の設定を保存するようにする.

これでもっと使いやすくなるだろうから,早く改造したい.

rbenvなrubyをcronで回す

ドはまりしたので載せておく.
$ crontab -e とかの設定ファイルにこいつを書く.

* * * * * {username(なくてもいい)} /bin/bash -c 'export PATH="$HOME/.rbenv/bin:$PATH" && eval "$(rbenv init -)" && cd {実行したいrbファイルのディレクトリまでのパス} && ruby {実行したい.rb}'

blog.livedoor.jp

ここを参照したのだけど,結局1,2,3のうち2がうまくいった.
gemで怒られたりいろいろしたけど上記のやつならうまくいった.


=2017/04/06追記=
usernameはなくてもいいって書いたけど,逆にあるとうまくいかない
/bin/sh: 1: {username}: not found
と言われる.なので今のところ下記が良さそう.

* * * * * /bin/bash -c 'export PATH="$HOME/.rbenv/bin:$PATH" && eval "$(rbenv init -)" && cd {実行したいrbファイルのディレクトリまでのパス} && ruby {実行したい.rb}'

screenコマンドでシリアル通信しながらxmodem転送

mac El capitanでxmodemした

http://netmark.jp/2011/12/gnu-screen-xmodem.html

上記がとても参考になったので備忘録として書いておく.

lrzszをインストールしておく

$ brew install lrzsz

screenを使ってシリアル接続する.

多分大体こんな感じだと思う.USB接続されたデバイスはdevの下にあるはずなので.tty.まで打つと補完が効くと思う.

$ screen /dev/tty.usbserial

Xmodem転送の実行

Ctrl+aを一回押し,コロンを入力するとコンソールの下らへんにコロンが入力されていて,コマンドが打てるようになる.
そこに下記のようにコマンドを入れて実行する.

:exec !! /usr/local/Cellar/lrzsz/0.12.20/bin/lsx -kb [ファイルまでのパス]

/usr/local/Cellar/lrzsz/0.12.20/bin/lsx はバージョンによって変わってくると思うので適切に.
ファイルまでのパスはフルパスいれればいいと思う.相対パスはどこ基準なのだろう?
たぶん/usr/local/Cellar/lrzsz/0.12.20/bin/lsxか?
オプションの-kbは1kパケットのバイナリ転送.

$ /usr/local/Cellar/lrzsz/0.12.20/bin/lsx --help

すればオプションが確認できるのでお好みで.