goo blog サービス終了のお知らせ 

南無ちゃんのブログ https://namva.net/blog2

上記のアドレスに引っ越しました。

WordPressを試す

2025-05-19 19:53:48 | プログラミング
 これまでブログは、yahooブログやgooブログなどのフリーのものを利用してきましたが、何年か前にyahooブログが停止し、乗り換えたgooブログが今年11月に停止すると通知されています。
 他のフリーのブログに乗り換えるという方法もありますが、またいつか停止するかもしれません。この際、自前でブログのページを作ることにしました。その方が、変な広告などが入らないのでスッキリします。アフィリエイトで稼ごうなどと恐れ多いことは考えていません。
 もう10年以上も前のことですが、会社勤めを辞めて、自前のホームページを作りました。レンタルサーバーを借りて、独自ドメインも取得しました。それ以来、ずっと運用していますが、最近はあまり更新していません。その代わりと言っては何ですが、ブログだけは、ほぼ毎日更新しています。そのブログが閉鎖されるのは悲しい話です。
 折角独自ドメインを取得してレンタルサーバー上にWebサイトを開設しているのですから、かの有名なWordPressを使ってブログを開設したいと思ったのです。色々調べてみると、私が借りているレンタルサーバーでは、WordPressを簡単にインストールできる専用ツールが用意されていたので、ホントに簡単に10分程でインストールすることができました。
 URLは、 https://namva.net/blog2 です。
 これからブログのコンテンツをどうやって入力すれば良いのか学習するところです。
 あまり勉強もしない内に、初めての投稿をしてみました。写真と記事だけです。何とか投稿できたようです。XとかFaceBookとかのアイコンがずらっと並んでいるのは意図していません。どうやれば削除できるのかは今後の検討課題です。
 スマホでも見てみました。流石にWordPressです。レスポンシブルなレイアウトになっていて、どんなデバイスでも、それなりに見られるようです。いっそのこと、スマホとかタブレットなどのデバイスで投稿するようなスタイルにするのも良いかもしれません。





加速度センサーの値から傾斜(仰角)を計算

2025-05-01 17:42:06 | プログラミング
 秋月電子で購入したKXR94-2050というアナログ電圧出力の3軸加速度センサーを使って、傾斜計を作っています。重力加速度を利用して傾斜角(仰角)を計算しています。
 センサーを水平面に置いた時、Zは1G、Xは0Gになり、Y軸を回転軸としてセンサーを垂直に立てた時、 Zは0G、Xは1Gになります。センサーから出力される電圧には、オフセットがありますし、XとZの間には僅かですがゲインの違いがあります。これらをキャンセルするには、較正(キャリブレーション)が必要です。較正と言っても、4つの値を保持しておくだけです。
 ①センサーを水平面に置いた時の読みをVz1、Vx0とし保持する
 ②センサーを垂直に立てた時の読みをVz0、Vx1とし保持する
 これらの値を利用して、次のような計算によりX軸とZ軸の加速度を計算します。
 1)Z軸のオフセットはVz0 なので、Z軸のゲインGzは
  Gz = 1/(Vz1 - Vz0)
 2)X軸のオフセットはVx0 なので、X軸のゲインGxは
  Gx = 1/(Vx1 - Vx0)
 3)X軸の読みをVxとすると、X軸の加速度gxは
  gx = (Vx - Vx0)*Gx
 4)Z軸の読みをVzとすると、Z軸の加速度gzは、
  gz = (Vz - Vz0)*Gz
 5)X軸とZ軸の加速度から傾斜角Θは、atan2関数で求めることができます。
  Θ = atan2(gx, gz)*180/3.15192 (単位は°)

 プログラムでは、較正によって求めた4つの値と、それらの値から計算した2つのゲインを次のように記述しています。
uint16_t Vx0 = 1314;
uint16_t Vz1 = 1893;
uint16_t Vx1 = 1870;
uint16_t Vz0 = 1357;
float Gx = 1.0/(Vx1-Vx0);
float Gz = 1.0/(Vz1-Vz0);

 1秒周期でA/D変換して、Θを計算し、表示するようにしました。
Vx = analogRead(ADC0);
Vz = analogRead(ADC1);
theta = atan2((Vx-Vx0)*Gx, (Vz-Vz0)*Gz)*180.0/3.14159;
 しかし、このままだとバラつきが気になったので、5回分のデータで平均してみました。

 バラつきもさることながら若干ドリフトしているようにも見えますが、0.5°位の範囲には収まっているようなので、2mEMEの仰角検出器としては使えるんじゃないかと思います。

リニアアンプ操作パネルのレイアウトを変更

2025-03-30 19:53:27 | プログラミング
 今日は、小雪が舞うような寒い日だったので、農作業はちょこっとだけにして、プログラミングをして過ごしました。リニアアンプ操作パネルのレイアウトを変更しました。
 元々のプログラムでは、パネルに表示する文字(ラベル)や数値、ボタンやランプなどのオブジェクトの座標は、数値を表示関数の引数として記述していて、プログラムの広い範囲に分布していました。レイアウト修正をし易くするために、オブジェクトの座標をヘッダーファイルにまとめました。
 一つのプログラムだったものから色んな派生品種が出来て、今では3つのプログラムになっています。それらに同じような修正を加えるのは単純でつまらない仕事ですが、辛抱してやっつけました。早いもので、このプロジェクトを開始してから6か月以上経ちます。いい加減に切りを付けないと、飽きて忘れてしまいます。


IC-PW2のリモート機能を確認するプログラム

2025-03-24 12:52:09 | プログラミング
 IC-PW2を遠隔制御したいと思って、色々調べています。IC-PW2にはLANコネクタ(RJ-45)がありますが、遠隔制御には使えないようで、NTPサーバーと接続して時計の時刻合わせのためだけのようです。
 REMOTE-AUXコネクタ(3.5φモノラルジャック)を通してCI-Vプロトコルで遠隔操作ができるようなので、ラズパイpico多目的ボードを使って実験しています。最終的には、ラズパイpicoWを使ってWiFiでパソコンから遠隔制御するようにしたいのですが、そのためにも、IC-PW2のCI-Vでのコマンド・レスポンスについて知見が必要です。ICOMのホームページからIC-PW2の補足説明書をダウンロードしましたが、これを読んだだけでは今一つ理解できませんでしたので、試して合点するっきゃないなと思ったのです。
 色んなコマンドが容易されているので、汎用のコマンドインタープリタを製作しました。cmd xx yy zzと入力すれば、IC-PW2に対してコマンドxx、サブコマンドyy、データzzを送信するものです。受信したデータは、16進数で表示されます。
 トランシーバ側の周波数ダイヤルを回すと、コマンドを送らなくても周波数データがIC-PW2側から送られてきます。IC-PW2のIDはaaで、ライズパイpicoのIDはeeとしました。
 cmd 18 01で、IC-PW2の電源をONにします。
 cmd 1a 00で、どちらのINPUTが選択されているのか知ることができます。
 cmd 1a 06 00で、INPUT1とアンテナの関係がわかります。
 以下にシリアルモニタの画面を示します。


以下にソースプログラム(全部)を示します。
// filename: ICPW2.ino
// description: ICPW2 remote controller by RP2040W
// 2025.03.17 ver 0.1 1st issue by H.NAMVA
#define MAXBUFLEN 30


char cmdBuf[MAXBUFLEN];
char rspBuf[MAXBUFLEN];


void setup() {
Serial1.setTX(0);
Serial1.setRX(1);


Serial.begin(115200);
Serial1.begin(9600);


// while (!Serial); // for debug
Serial.println("program has started");


}


void cmdSend(char param[], int nParam){
char cmd[20];
cmd[0] = 0xfe;
cmd[1] = 0xfe;
cmd[2] = 0xaa;
cmd[3] = 0xee;
int i;
for(i=0; i
cmd[4+i] = param[i];
}
cmd[4+nParam] = 0xfd;
for(i=0; i<=(4+nParam); i++){
Serial1.write(cmd[i]);
}
}


char char2hex(char highN, char lowN){
// convert 2 byte hexadicimal ASCII chars into 1 byte bin
// Serial.printf("char2hex high:%02x low:%02x\n", highN, lowN);
char bin;
if((highN >= 'a') && (highN <= 'f')){
bin = (highN-'a' + 10) <
}else if((highN > 'A') && (highN <= 'F')){
bin = (highN-'A' + 10) <
}else if((highN >= '0') && (highN <= '9')){
bin = (highN-'0') <
}else{
bin = 0;
}
if((lowN >= 'a') && (lowN <= 'f')){
bin |= (lowN-'a' + 10);
}else if((lowN >= 'A') && (lowN <= 'F')){
bin |= (lowN-'A' + 10);
}else if((lowN >= '0') && (lowN <= '9')){
bin |= (lowN-'0');
}
return bin;
}


void analyzeCmd(int bufLen){
int i;
char param[10];
cmdBuf[bufLen] = 0x00;
String strCmd = String(cmdBuf);
Serial.println(strCmd);
if(strCmd.startsWith("cmd ")){
if((bufLen %3) == 0){
int nParam = (bufLen /3) -1;
for(i=1; i<=nParam; i++){
param[i-1] = char2hex(cmdBuf[i*3 +1], cmdBuf[i*3 +2]);
}
cmdSend(param, nParam);
}
}
}


void analyzeRsp(int bufLen){
int i;
for(i=0; i
Serial.printf("%02x ", rspBuf[i]);
}
switch(rspBuf[4]){
case 0x00: // frequency data
case 0x03:
if(bufLen == 11){
Serial.printf("| Freq: %02x%02x%02x%02xHz", rspBuf[8], rspBuf[7], rspBuf[6], rspBuf[5]);
}
break;
case 0xfa: // NG
Serial.printf("| NG");
break;
case 0xfb: // OK
Serial.printf("| OK");
break;
default:
break;
}
Serial.println("");
}


void loop() {
char c;
static int idxCmd;
static int idxRsp;




if(Serial.available()){
c = Serial.read();
if(c == '\n'){
analyzeCmd(idxCmd);
idxCmd = 0;
}else if(c >= 0x20){
cmdBuf[idxCmd++] = c;
if(idxCmd >= MAXBUFLEN){
idxCmd = 0;
}
}// ignore control char
}




if(Serial1.available()){
c = Serial1.read();
rspBuf[idxRsp++] = c;
if(idxRsp >= MAXBUFLEN){
idxRsp = 0;
}
if(c == 0xfd){
analyzeRsp(idxRsp);
idxRsp = 0;
}
}
}