緑の中に

緑の中に
国立天文台

3/24/2021

Rubyと温度センサー LM35DZ

  温度センサー LM35DZ 

 

温度センサー LM35DZ を使用したときのデータです。まだ、校正途中です。

2021.6.23  今振り返りますが、LM35DZ温度センサーの出力をマイコンのアナログ端子(A0)へ直接接続していました。

この事は、インピーダンスの関係では問題が何かしらあると考えます。

A0端子の入力インピーダンスとLM35DZの出力インピーダンスの関係です。

この問題があり不安定な受信(受信記録)データとなったと考えます。

回路を追加する実験をします。

後日の報告となります。


3/22/2021

Rubyでシリアル通信 大成功


Rubyでシリアル通信 大成功




 Rubyでシリアル通信 大成功
-------------------------------------------------------
log.bat の記述です

:START

@echo off

echo Hello Tom  10min. interval logger. eternally

cd C:\Users\ __\Documents\MyRuby

ruby RS232C_280.rb

timeout 600 /NOBREAK > NUL

REM 600-->10min

GOTO START

------------------------------------------------------

10分間隔の起動です。10分インターバルです。

プログラムを起動してからそのプログラムが終了する時間をT1とします。

インターバル時間をT2とします。すると、周期をTとするとT=T1+T2 となります。

ここで、T1=600(SEC),T2=(1SEC)

と仮定すると、1日(24時間)では24X6=144回実行します。T2の1(SEC)が144秒遅れで現れます。144/60=2.4分 

これが、インターバル時間による問題と言えば問題です。


これが嫌なら、

高度に時刻に厳密に実行させたいなら、割り込み処理を行わせます。

途中


3/11/2021

Ruby(ルビー)をはじめました

             Ruby(ルビー)をはじめました 

Rubyとは「まつもとひろゆき」さん開発による言語とのことです。
楽しいプログラミング(Enjoy Programming)というコンセプトから開発され、1995年12月に最初のバージョンが公開されました。

・オブジェクト指向型スクリプト言語
・インタプリタ形式で実行

宝石のパール(Pearl)は6月の誕生石で、ルビーは7月の誕生石です。
日本人が設計し、開発した言語です。世界中で使用されています。


Cではポインター(*)、アドレス演算子(&)で訳が分からなくまいりました。
構造体でも訳が分からず、降参です。unixがCで書き直されたとのことで、何としてもCを理解すべきだと考えましたが、意気込みだけでは手に負えませんでした。

「Rubyがいいよ」とのアドバイスを以前よりもらっていました。
コンピュータ言語の世界では、最初はその言語を扱う環境を作るところから始まります。その手順を書きます。

1. マイクロソフトのヴィジュアル・スタデオ・コード(Visual Studio Code)をパソコンに  インストールしました。無償です。
  要するに、エデイッターでもあり実行結果表示でもあり、ファイル管理でもあります。
 IDEという言葉がありますがまさにそれに相当しています。
 VSCを初期値のままでは画面が白系で目が疲れます。私は、ブルー系に変更しました。目には負担が少ないように思います。

2.  次にRubyそのものをパソコンにインストールする必要があります。
    https://www.ruby-lang.org/ja/downloads/
このサイトよりダウンロードします。

 さらに、インストーラーを入手します。
 https://rubyinstaller.org/
このサイトよりダウンロードします。

 インストールプログラムが必要であるなんて少し1ステップ余計ですが。
 Linuxなどでもインストーラを使用してインストールしていました。

ソースプログラムを格納するフォルダ(MyRuby)をMyDocumentsに配置しました。 
以上で環境構築はできると思います。

Ruby関係の書籍には、このことの記述があるはずです。またはNetによる検索でも情報は得られるはずです。

「たのしい Ruby 第6版 SB Creative(著者 高橋征義、後藤裕蔵、監修 まつもとひろゆき)を買いました。 [2600円+税]

   下記  ビジュアルスタデオコードを立ち上げて、ソースコードを書いた画面です。
 エデッータの補完機能は抜群です。色分けも自動で行ってくれます。


下図 マイコンからの受信データはおおよそ下記の形式で受信予定です。
この状態を想定して、データの一部を抜き出しできるか簡単なプログラムを作り、実行させた結果です。



    • コンパイラ型の言語と違い、プログラムのデバッグが楽です。コンパイラ型では都度、exeーファイルを生成して実行する必要があり手間を要しましたが、これは楽です。
    • p メソッドがいい!  プログラムの実行状況の確認に便利です。 






3/01/2021

RS232C この先がわかんない!

 //+++++++ 各文の分かりやすい注釈文(コメント)が欲しいです +++++++

// +++++ コンパイルができたので、とにかく何とかなりそうな予感がします +++

// +++  minGW でコンパイルができました。ワーニングは出ました。ですが、+++

//++++ コンパイルエラーではなかったです +++++++++++++

//Good.

//東京工業大学ロッボト技術研究会さんありがとうございました。私、何とか自力でCompileできました。

//■C:\MinGW\RS232C> mingw32-g++  RS232C~1.CPP   私の現在のマシンはデヴァイスマネージャーでCOM1・COM6を表示していたのでCOM1を記述しました。

//私のマシンのCOM6は現在DataLoggerBで稼働使用中です。

// Compileエラー無し。ワーニングはあり。

/* RS232Cプログラムを書く方法ですが、

・C#やVBで.NETFrameworkを利用する

・C++でWin32APIを利用する

の二つの方法があるようですが、私がCしか触れたことがないのでWin32APIをつかって作ります。

またWindowsアプリケーションはよくわからないのでコンソールアプリケーションを想定しています。


全体の流れは

1.ファイルとしてCOMポートを開く

2.送信バッファの設定

3.送受信バッファの初期化

4.COMポート構成情報の初期化

5.タイムアウトの設定

でRS232C通信が使えるようになります。

今回の通信の仕様は

RTS,CTSフロー制御なし

9600bps

データサイズ8bit

パリティビットなし

ストップビット1bit

main()関数内での受信処理

です。


まずはいくつかのヘッダファイルを読み込んでおきましょう。*/

#include <string>//良く知らん

#include <stdio.h>//printfなどの標準入出力関数を使うためのヘッダファイル

#include <windows.h>//Wi32APIを使うためのヘッダファイル

#include <tchar.h>//_T()使うのに要る


int main(void){

//1.COMポートを開く

// HANDLE hComPort;//COMポートのハンドルいろいろ使うのでグローバル変数にしておくとよい

//  hComPort = CreateFile(    //ファイルとしてポートを開く

//      _T("COM4"),// ポート名を指すバッファへのポインタ:COM4を開く(デバイスマネージャでどのポートが使えるか確認)

//      GENERIC_READ | GENERIC_WRITE, // アクセスモード:読み書き両方する

//      0,        //ポートの共有方法を指定:オブジェクトは共有しない

//      NULL,       //セキュリティ属性:ハンドルを子プロセスへ継承しない

//     OPEN_EXISTING,     //ポートを開き方を指定:既存のポートを開く

//      0,   //ポートの属性を指定:同期 非同期にしたいときはFILE_FLAG_OVERLAPPED

//      NULL       // テンプレートファイルへのハンドル:NULLって書け

//  );

HANDLE hComPort;


hComPort = CreateFile(

_T("COM1"), //@@@@@@@@@@@@@@@@@@@@@@@@@ ここ

GENERIC_READ | GENERIC_WRITE,

0,

NULL,

OPEN_EXISTING,

0,

NULL

);

 if (hComPort == INVALID_HANDLE_VALUE){//ポートの取得に失敗

  printf("指定COMポートが開けません.\n\r");

  CloseHandle(hComPort);//ポートを閉じる

return 0;

 }

 else{

  printf("COMポートは正常に開けました.\n\r");

 }

/*ポートをファイルとみなしCreateFile()関数を用いて開きます。失敗するとINVALID_HANDLE_VALUEを返します。

ポートの属性は非同期(FILE_FLAG_OVERLAPPED)にした方がいいらしいですが上手くいかなかったので同期通信にしてあります。


2.送受信バッファの設定 */

 int check;//エラーチェック用の変数

 check = SetupComm(

       hComPort,//COMポートのハンドラ

       1024,//受信バッファサイズ:1024byte

       1024//送信バッファ:1024byte

  );

 if (check == FALSE){

     printf("送受信バッファの設定ができません.\r\n");

CloseHandle(hComPort);

     return 0;

 }

 else{

      printf("送受信バッファの設定が完了しました.\r\n");

 }

/*SetupComm()関数を用いて送受信バッファの設定をします。


3.送受信バッファの初期化 */

 check = PurgeComm(

       hComPort,//COMポートのハンドラ

       PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR//出入力バッファをすべてクリア

 );

 if (check == FALSE){

     printf("送受信バッファの初期化ができません.\r\n");

     CloseHandle(hComPort);

     return 0;

 }

 else{

      printf("送受信バッファの初期化が完了しました.\r\n");

 }

/* PurgeComm()関数を用いて出入力すべてのバッファをクリアします。


4.COMポート構成情報の初期化 */

 DCB dcb;//構成情報を記録する構造体の生成

 GetCommState(hComPort, &dcb);//現在の設定値を読み込み

 dcb.DCBlength = sizeof(DCB);//DCBのサイズ

 dcb.BaudRate = 9600;//ボーレート:9600bps

 dcb.ByteSize = 8;//データサイズ:8bit

 dcb.fBinary = TRUE;//バイナリモード:通常TRUE

 dcb.fParity = NOPARITY;//パリティビット:パリティビットなし

 dcb.StopBits = ONESTOPBIT;//ストップビット:1bit

 dcb.fOutxCtsFlow = FALSE;//CTSフロー制御:フロー制御なし

 dcb.fOutxDsrFlow = FALSE;//DSRハードウェアフロー制御:使用しない

 dcb.fDtrControl = DTR_CONTROL_DISABLE;//DTR有効/無効:DTR無効

 dcb.fRtsControl = RTS_CONTROL_DISABLE;//RTSフロー制御:RTS制御なし


 dcb.fOutX = FALSE;//送信時XON/XOFF制御の有無:なし

 dcb.fInX = FALSE;//受信時XON/XOFF制御の有無:なし

 dcb.fTXContinueOnXoff = TRUE;// 受信バッファー満杯&XOFF受信後の継続送信可否:送信可

 dcb.XonLim = 512;//XONが送られるまでに格納できる最小バイト数:512

 dcb.XoffLim = 512;//XOFFが送られるまでに格納できる最小バイト数:512

 dcb.XonChar = 0x11;//送信時XON文字 ( 送信可:ビジィ解除 ) の指定:XON文字として11H ( デバイス制御1:DC1 )

 dcb.XoffChar = 0x13;//XOFF文字(送信不可:ビジー通告)の指定:XOFF文字として13H ( デバイス制御3:DC3 )


 dcb.fNull = TRUE;// NULLバイトの破棄:破棄する

 dcb.fAbortOnError = TRUE;//エラー時の読み書き操作終了:終了する

 dcb.fErrorChar = FALSE;// パリティエラー発生時のキャラクタ(ErrorChar)置換:なし

 dcb.ErrorChar = 0x00;// パリティエラー発生時の置換キャラクタ

 dcb.EofChar = 0x03;// データ終了通知キャラクタ:一般に0x03(ETX)がよく使われます。

 dcb.EvtChar = 0x02;// イベント通知キャラクタ:一般に0x02(STX)がよく使われます


 check = SetCommState(hComPort, &dcb);  //設定値の書き込み

 if (check == FALSE){//エラーチェック

     printf("COMポート構成情報の変更に失敗しました.\r\n");

     CloseHandle(hComPort);

     return 0;

 }

 else{

      printf("COMポート構成情報を変更しました.\r\n");

 }

/* DCB構造体で構成情報を設定します。今回すべての変数について書き込んでいますが、GetCommState()関数で基本情報を読み込んでいるため変更する部分だけ書き換えればいいです。

ボーレートやデータサイズ、パリティビット、ストップビットなどはマイコン側とあわせてください。

書き換えた後にSetCommState()関数で再設定を行います。*/


//5.タイムアウト時間の設定

 COMMTIMEOUTS TimeOut; // COMMTIMEOUTS構造体の変数を宣言

 GetCommTimeouts(hComPort, &TimeOut); // タイムアウトの設定状態を取得


 TimeOut.ReadTotalTimeoutMultiplier = 0;//読込の1文字あたりの時間:タイムアウトなし

 TimeOut.ReadTotalTimeoutConstant = 1000;//読込エラー検出用のタイムアウト時間

 //(受信トータルタイムアウト) = ReadTotalTimeoutMultiplier × (受信予定バイト数) + ReadTotalTimeoutConstant

 TimeOut.WriteTotalTimeoutMultiplier = 0;//書き込み1文字あたりの待ち時間:タイムアウトなし

 TimeOut.WriteTotalTimeoutConstant = 1000;//書き込みエラー検出用のタイムアウト時間

 //(送信トータルタイムアウト) = WriteTotalTimeoutMultiplier ×(送信予定バイト数) + WriteTotalTimeoutConstant


 check = SetCommTimeouts(hComPort, &TimeOut);//タイムアウト設定の書き換え

 if (check == FALSE){//エラーチェック

     printf("タイムアウトの設定に失敗しました.\r\n");

     CloseHandle(hComPort);

     return 0;

 }

 else{

      printf("タイムアウトの設定に成功しました.\r\n");

 }

/*構成情報の設定と似た手順です。COMMTIMEOUTS構造体を使い、GetCommTimeouts()関数で基本情報を取得し、変更したのちSetCommTimeouts()関数で書き換えています。各値はよく知りませんがこんな感じが多いです。

ここまででCOMポートの初期設定ができました次に送信してみましょう。


6.送信 */

 char SendData[] = "17";//送信データの用意

 int SendSize = strlen(SendData)+1;//送信データサイズを取得

 DWORD writeSize;//実際に送信したデータサイズ

 WriteFile(hComPort,SendData,SendSize,&writeSize,NULL);

/* WriteFile()関数を用いて送信。送信するデータサイズはNULL文字の分+1するのを忘れないように。


7.受信 */

 int i = 0;

 char RecieveChar[1];//1文字受信のための変数

 char RecieveData[100];//受信文字列

 unsigned long nn;

 while (1) {

       ReadFile(hComPort, RecieveChar, 1, &nn, 0); // シリアルポートに対する読み込み

       if (nn == 1) {

           if (RecieveChar[0] == 10 || RecieveChar[0] == 13) { // '\r'や'\n'を受信すると文字列を閉じる

               if (i != 0) {

                   RecieveData[i] = '\0';//最後にNULL文字を付加して

                   i = 0;//文字列を先頭に戻す

                   printf("%s\n", RecieveData);//受信した文字列を表示

               }

}

           else {

                RecieveData[i] = RecieveChar[0];//受信した文字を文字列にする

                i++;

           }

       }

}

}

/*ReadFil()関数で1文字ずつ受信して'\r'や'\n'で文字列の切り分けを行っています。

受信のタイミングは分からないのでスレッド受信にすべきなのですが、スレッドに関して未だ理化していないことが多いので今回はwhileで回し続けています。


VisualStudio2013で作り、PIC32MX440FとRS23C通信を行いました。

数字を文字データとして送信しPICが素数かどうか判定して素数だと「~ is a prime! 」と返すプログラムを書いて実行したところ。*/



//--------------------------------------------------------------

//COM1を指定して、Compileし、実行しました

//Compilerは ■C:\MinGW\RS232C> mingw32-g++  RS232C~1.CPP

//C:\MinGW\RS232C>a.exe

//---------------------------------------------------------------

//COMポートは正常に開けました.

//送受信バッファの設定が完了しました.

//送受信バッファの初期化が完了しました.

//COMポート告ャ|情報を変更しました.

//タイムアウトの設定に成功しました.

//------------------------------------------------------------------------------------------------------------------------------

//なるメッセージを表示しました

//c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../../mingw32/bin/ld.exe: cannot open output file a.exe: Permission denied

//はa.exegaがすでに実行中においてCompile実行をしたからです。

//--------------------------------------------------------------------------------------------------------------------------------