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

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

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

Arduino IDEではじめるRaspberry Pi Pico

2024-04-21 12:03:52 | プログラミング

 Raspberry Pi Pico(以降Picoと呼ぶ)というマイコンボードがあることは知っていましたが、独自の開発環境を使ってプログラミングする必要がありそうなので、マイイカ?!と思ってスルーしてきました。先日、Kindleで面白そうな本はないかなぁと思って探していたところ、「Arduino IDEではじめるRaspberry Pi Pico」という本を見つけました。早速ダウンロードして読んだところ、使い慣れたArduino IDEでプログラミングできそうだったので、PicoをAmazonでポチッとしました。

 現物は1週間程前に配達されていたのですが、今日は雨降りなので野良仕事を休みにして、Kindleで本を読みながら、実際にArudio IDEにライブラリをインストールし、Blink(Lチカ)を試してみました。

 ESP32を含む従来のArduinoマイコンと違う点は、コンパイルされたバイナリファイルがuf2という拡張子であることと、そのバイナリファイルをPicoに内蔵されたフラッシュメモリ(PCから見るとUSBメモリ)にコピーすることで、当該アプリが動作するということです。これは初めての体験だったので、①ライプラリーのインストールに躓いたため、②uf2ファイルが生成されず、思った通りに動作しませんでしたが、本を読み直して一つ一つの作業を入念に確認しながら行ったところ、なんとか動作するようになりました。Kindleは電子書籍ですが、テキストをコピペできなかったので、環境設定でgithubのアドレスを1文字間違えて入力していたのが原因でした。

 Arudio IDEとPicoの組み合わせには、次のような特徴があります。①デュアルコアという特性を生かして2つのスレッドを同時並列的に動作させることができる。(ESP32もデュアルコアらしいのですが、Arduino IDEでのプログラミングが面倒くさい。その点、setup1/loop1という形で記述できるという点が素晴らしいです。)②キーボードやマウスなどのUSBデバイスを作成することができる。③動作クロックを指定することができる。いずれの機能も、Arduino IDEでサポートされています。

 Picoで何を作ろうかなぁ・・・


UDP通信アプリを簡単に作成するためのVB.Net用関数

2024-03-26 16:41:05 | プログラミング

 近頃はぐずついた天気の日が多いので、無線小屋に籠ってプログラミングをして過ごしています。以前製作したお月様自動追尾装置を改良しています。従来は、ESP32を使ってWiFiでTCP/IP通信をしていましたが、144.120MHz近傍にノイズが出るので、アンテナの近くに置くESP32ではWiFiの代わりにRS485を使い、アンテナから離れた場所に設置するESP32でRS485-WiFiブリッジを作成して通信するようにします。通信にはUDP/IPを使うこととし、RS485-WiFiブリッジは固定IPアドレスと固定UDPポートを持つこととします。PCから見れば、RS485-WiFiブリッジにコマンドをUDPパケットで送るとお月様自動追尾装置に中継されて、そのレスポンスがRS485-WiFiブリッジを経由してUDPパケットで返ってくるという仕組みです。

 前置きが長くなりましたが、上記のアプリを作成するためのUDP通信関数を作成しました。関数は一つだけなので、とてもシンプルです。その関数は、UdpCmdRspという名前で、次のように定義します。

   Public Function UdpCmdRsp(ByVal srcPort As Integer,     'local UDP port
                               ByVal destIP As String,      'remote IP address
                               ByVal destPort As Integer,   'remote UDP port
                               ByVal cmd As String,         'command message
                               ByVal cmdOnly As Boolean,    'set true when command only message
                               ByRef rsp As String          'response message
                               ) As Boolean                 'true when response is available

 UDPでコマンドを送って、それに対するレスポンスを得るという方式であれば、この関数を呼ぶだけで一連の動作を行うことができるようにしました。ソケットを作るとかエンドポイントがどうだとかという細々したことは全部覆い隠してしまいました。この関数だけをコピペして、作成したいアプリに貼り付けるだけで利用できます。

 この関数を使って、UDP tesl toolというアプリを作成しました。右のCOM12という画面はRS485-WiFiブリッジの内部情報を表示したものです。

 ソースコードを以下に示します。(これで全部です。)

'project name: TestUDPgateway
'File name Form1.vb
'Test tool for the dvice which resepond to UDP
'author H.NAMVA JH4ADK created on 2023.11.18
' revised on 2024.03.24: make it simple

Imports System.Text
Imports System.Net.Sockets


Public Class Form1
    Public Function UdpCmdRsp(ByVal srcPort As Integer,     'local UDP port
                               ByVal destIP As String,      'remote IP address
                               ByVal destPort As Integer,   'remote UDP port
                               ByVal cmd As String,         'command message
                               ByVal cmdOnly As Boolean,    'set true when command only message
                               ByRef rsp As String          'response message
                               ) As Boolean                 'true when response is available

        Dim sdat As Byte() = New Byte(100) {}

        Dim localPort As Integer = srcPort
        Dim localEndPoint As System.Net.IPEndPoint = New System.Net.IPEndPoint(System.Net.IPAddress.Any, localPort)
        Dim objSck As System.Net.Sockets.UdpClient = New System.Net.Sockets.UdpClient(localEndPoint)

        sdat = Encoding.UTF8.GetBytes(cmd)
        'Send Message as command
        objSck.Send(sdat, sdat.GetLength(0), destIP, destPort)
        Debug.Print("UDP packet sent From " + localEndPoint.Address.ToString + ": " + localEndPoint.Port.ToString +
                    " To " + destIP + ": " + destPort.ToString)

        If cmdOnly = False Then
            Try
                'Receive Message as response
                objSck.Client.ReceiveTimeout = 200 '200ms
                Dim RemoteEndPoint As System.Net.IPEndPoint = New System.Net.IPEndPoint(System.Net.IPAddress.Any, 0)
                Dim rdat As Byte() = objSck.Receive(RemoteEndPoint)
                Dim strDT As String = Encoding.UTF8.GetString(rdat)
                rsp = strDT
                Debug.Print("UDP packet received From IP Adress: " + RemoteEndPoint.Address.ToString + " UDP Port:" + RemoteEndPoint.Port.ToString)
                Debug.Print("Message: " + rsp)
                UdpCmdRsp = True

            Catch ex As Exception
                UdpCmdRsp = False
            End Try
        Else
            UdpCmdRsp = False
        End If
        objSck.Dispose()
    End Function

    Private Sub btnSend_Click(sender As Object, e As EventArgs) Handles btnSend.Click

        'Send message to specified IPaddress and port
        Dim strMsg As String = tbSend.Text
        If rbLF.Checked Then
            strMsg += vbLf
        ElseIf rbCR.Checked Then
            strMsg += vbCr
        ElseIf rbCRLF.Checked Then
            strMsg += vbCrLf
        End If
        Dim strRecv As String = ""
        Dim strFromIP As String = ""
        Dim fromPort As Integer = 0
        If UdpCmdRsp(Integer.Parse(tbLocalUDP.Text),
                  tbIPaddress.Text,
                  Integer.Parse(tbUDPport.Text),
                  strMsg, cbCmdOnly.Checked, strRecv) Then
            tbRecv.Text = strRecv
        Else
            tbRecv.Text = ""
        End If
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim hostName As String = System.Net.Dns.GetHostName()
        Dim ipAdList As System.Net.IPAddress() = System.Net.Dns.GetHostAddresses(hostName)
        Dim ipA As String = ""
        For Each address As System.Net.IPAddress In ipAdList
            ipA = address.ToString()
        Next address
        Debug.Print(vbCrLf + "Host name: " + hostName + "IP Address: " + ipA)
        tbLocalIP.Text = ipA
    End Sub

End Class


UDPのテストツール

2023-11-19 14:48:35 | プログラミング

 現在開発中のプロジェクトでは、UDPパケットを用いてWiFiでESP32と通信する予定です。ステップバイステップで製作を進めていますが、各ファンクションブロックがちゃんと機能することを確かめるために、UDPパケットを送って、そのレスポンスを確認するためのツールを作成しました。一回こっきりのノミプロとして作っても良かったのですが、汎用性を持たせて将来の製作にも役立つようなツールにしました。GUIは次のようなものです。

 送信先のIPアドレスとUDPポートおよび送信するメッセージを各テキストボックスに入力して、Sendボタンを押すとUDPパケットが当該PCから送信されます。1秒以内に自分宛にUDPパケットが返信されれば、ReceiveMessageテキストボックスに表示されます。上の表示例では、自作のNTPサーバーに時刻問合せのUDPパケットを送信した時の様子です。

 送信可能なデータはASCIIコードで、デリミタとしてLF/CR/CR+LFまたは無しをしてすることができます。VisualStudioCommunity2019を用いてVisualBasicで作成しました。ソースコードは次の通りです。たったこれだけです。

'project name: TestUDPgateway
'File name Form1.vb
'Test tool for the device which resepond to UDP
'author H.NAMVA JH4ADK created on 2023.11.19

Imports System.Text
Public Class Form1
    Private Sub btnSend_Click(sender As Object, e As EventArgs) Handles btnSend.Click
        'Make UDP client
        Dim objSck As System.Net.Sockets.UdpClient
        Dim ipAny As System.Net.IPEndPoint =
            New System.Net.IPEndPoint(System.Net.IPAddress.Any, 0)
        objSck = New System.Net.Sockets.UdpClient(ipAny)

        'Send message to specified IPaddress and port
        Dim sdat As Byte() = New Byte(100) {}
        Dim strMsg As String = tbSend.Text
        If rbLF.Checked Then
            strMsg += vbLf
        ElseIf rbCR.Checked Then
            strMsg += vbCr
        ElseIf rbCRLF.Checked Then
            strMsg += vbCrLf
        End If
        sdat = Encoding.UTF8.GetBytes(strMsg)
        tbRecv.Text = ""
        objSck.Send(sdat, sdat.GetLength(0), tbIPaddress.Text, tbUDPport.Text)
        Try
            'Receive message as reply
            objSck.Client.ReceiveTimeout = 1000 '1sec
            Dim rdat As Byte() = objSck.Receive(ipAny)
            Dim strDT As String = Encoding.UTF8.GetString(rdat)
            tbRecv.Text = strDT
        Catch ex As Exception
            'MsgBox("exection occured during receive, timeout")
        End Try
    End Sub
End Class

 


ESP32でRS485通信

2023-11-18 16:26:39 | プログラミング

 今日は雪がチラつくような寒い日だったので、DXペディション局PR0Tをワッチしながら、無線小屋でプログラミングをして遊びました。

 今日のテーマはRS485通信です。秋月電子でLTC485CN8というRS485ドライバ・レシーバICを購入していたので、先日購入したESP32 Devkitとコンビで使えるようにブレッドボードに配線しました。通信なので、2個作成してPCも2台用意しました。一方のPCがクライアント、他方のPCがサーバーという想定です。クライアントからコマンドを送ると、サーバーからレスポンスが返るというものです。クライアント側のPCでターミナルソフトを使い、コマンドラインから"hello"と入力すると、サーバーからは"goodbye"と返ってきてターミナルに表示されます。同様に、"abc"と入力すれば"xyz"と表示されます。それ以外の単語が入力されてもサーバーから何も返信しません。

 ESP32を用いたのは、シリアルポートが3chあるからです。Serial1はUSBシリアル経由でコンソールとして、Serial2をRS485として使います。RS485は1ペアの信号線で半二重通信方式なので、送受の切替が必要なので、そのためにESP32のGPIO0を使います。

 以下にクライアント側のソースコードを示します。

// This example demonstraits how to use the serial port2 for RS485.
// We need the terminal software using USB COM port connected to the serial port 1.
// redirect the chars from serial-1 to serial-2
// print the chars from serial-2
// Author: H.NAMVA, created on 2023.11.18

// Serial port1 Pin number
int RX_PIN = 16;
int TX_PIN = 17;
int TxEN = 0; // for RS-485 Driver/Reciver

void setup() {
  pinMode(TxEN, OUTPUT);
  Serial.begin(115200);
  Serial2.begin(38400, SERIAL_8N1, RX_PIN, TX_PIN);
}

void loop() {
  // read from port 2, send to port 1 (console out):
  if (Serial2.available()) {
    String fromLine = Serial2.readStringUntil(0x0a);
    Serial.println(fromLine);
  }
  delay(1);
  // read from port 0, send to port 2:
  if (Serial.available()) {
    String fromConsole = Serial.readStringUntil(0x0a);
    digitalWrite(TxEN, HIGH);
    Serial2.println(fromConsole);
    Serial2.flush();
    digitalWrite(TxEN, LOW);
  }
  delay(2);
}

 以下にサーバー側のソースコードを示します。

// This example demonstraits how to use the serial port2 for RS485.
// The server is waiting for the messages from RS485 assigned as serial port-2.
// The message will be send over the serial-2 when a particular token was received.
// Author: H.NAMVA, created on 2023.11.18

// RS485 serial port pin nuber
int RX_PIN = 16;
int TX_PIN = 17;
int TxEN = 0; // Enalbe(High)/Disable(Low) control signal for RS485 Driver

void setup() {
  pinMode(TxEN, OUTPUT);
  Serial.begin(115200);
  Serial2.begin(38400, SERIAL_8N1, RX_PIN, TX_PIN);
  Serial2.setTimeout(10);
}

void loop() {
  // read from port 2, send to port 0:
  if(Serial2.available()){
    String fromLine = Serial2.readStringUntil(0x0a);
    if (fromLine.indexOf("hello")>=0){
      Serial.println("find hello");
      Serial2TX("goodbye");
    }else if(fromLine.indexOf("abc")>=0){
      Serial.println("find abc");
      Serial2TX("xyz");
    }else{
      Serial.print("Unknown token: ");
      Serial.println(fromLine);
    }
  }
  delay(2);
}

void Serial2TX(String TXmsg) {
  digitalWrite(TxEN, HIGH);
  Serial2.println(TXmsg);
  Serial2.flush();
  digitalWrite(TxEN, LOW);
}

 写真を以下に示します。右側がクライアント側で、左側がサーバー側です。サーバー側には、次のテーマのためにMPU9250という加速度・ジャイロ・地磁気センサーのモジュールを取付けています。


CSVファイルからHTMLファイルに変換

2023-02-13 12:59:02 | プログラミング

 ひょんなことから、とある団体の中国支部のWeb担当をお引き受けすることになりました。勿論、無報酬のボランティアとしてです。ホームページ作成にあたっては、ホームページビルダーなどの有償アプリは使わないで、テキストエディターのみでゴリゴリ書いていく手法です。こんな方法でも、Bootstrap5の恩恵によりシンプルでレスポンシブルなWebデザインが作成できて、追加や修正などの編集が簡単にできます。しかし、年間行事予定表や役員名簿などの表を作成する時、テキストエディターだけで入力するのは大変手間がかかる作業です。いちいちtrタグやtdタグなどを付けなければならないからです。こんな面倒なことを辛抱強くやっていると間違いの元なので、CSVファイルからHTMLファイルに変換するソフトがあれば便利なのになぁ・・・と思いました。

 ネットでググってみると、そういうサービスを提供しているサイトが幾つか見つかりました。しかし、外国のサイトのためか、日本語(Shit-JISによるカナ漢字)のデータは化けてしまいました。仕方がないので、自分で作ることにしました。作成にあたり、仕様を次のように設計しました。

プロジェクト名:
 csv2html

機能:
 表計算ソフトで作成したcsv形式のデータをhtmlファイルに変換する。

使用目的:
 ホームページを作成する際に、表を手入力で作成するのは手間がかかるので、一括で変換して、コピペしてホームページを作成する。

仕様:
 csvファイルを入力とし、htmlファイルを出力する。
 入力ファイル名の拡張子はcsvとし、出力ファイル名は入力ファイル名の拡張子をhtmlに付け替えたものとする。
 htmlファイルには、ブラウザで表示し確認できるようにBootstrap5に対応したヘッダを付ける。
 csvファイルには、Shift-JISのカナ漢字が含まれることとする。(Winddows標準)
 htmlファイルは、utf-8形式のデータに変換されることとする。
 csvファイルのカラムはコンマで区切られることとし、それ以外(;やスペース)はデリミタとして認識しないこととする。
 csvファイルのカラムはダブルクオーテーションで囲まないこととする。
 csvファイルの1行目には、カラム名がカラム数だけ記述されていることとする。

開発環境:
 Visual Studio Community 2022 VB.netを使用する。

 デバッグし易いように次のようなフォームにしました。スクロール可能なテキストボックスに変換後のhtmlファイルが表示されます。デバッグ時には、ここで内容を確認しました。

 上の図は実際に動作させた時のスナップショットですが、入力ファイルである「表のサンプル.csv」はOpenOfficeで作成したものです。OpenOfficeでは次のように表示されています。

 変換後の「表のサンプル.html」をEdgeで表示すると次のようになりました。

 実際にホームページを作成する時には、htmlファイルの一部(表の部分)をコピーしてターゲットのhtmlファイルにペーストします。

 VB.netのソースコードを、このブログに掲載しようと試みたところ、ダブルクオーテーションで囲んだ部分が消失するなどのトラブルがあったので、代わりに私のHPのプログラミングチャンネルに記事を作成して掲載しました。製作メモの中にソースコードを掲載しています。宜しければご覧ください。なお、exeファイルを含むプロジェクトファイルもダウンロードできるように掲載していますが、お使いのブラウザがダウンロードをブロックするかもしれませんので、悪しからず。