pinewell's farmer blog 農業と電子工作、ソフトウェア、バイク、車

2023年12月26日

USB接続自動操舵ON/OFFスイッチ

Filed under: GNSS,ポチトン,農業機械 — pinewell @ 12:28 PM

USBキーボードやマウスなどのHIDデバイスに準拠した変換ICであるCH9329とRP2040を用いて、

自動操舵のON/OFFを外部スイッチでできるようにしてみた。

接続はUSBでOK。スイッチを2つ付けることで自動操舵のON/OFF、転回も手元スイッチで可能。

USBマウスのエミュレータなのでタッチパネルの位置情報が把握できれば幅広い機種に対応が可能と思われる。

AgLeader、CHCNAV、Trimble GFX-750では動作確認済み。

近々販売のためのクラウドファンディングを画策中。時間がかかりそうなので中止。

申し込みページを作成しました。
CHCNAVでの動作確認
AgLeaderでの動作確認

2023年1月29日

OrangePi zero2を用いた基準局設備

Filed under: GNSS — pinewell @ 9:31 PM

本来ならRaspberryPiを使いたいのだが入手困難な上、高額となってしまったため試行錯誤。

機能的には充分なOrangePi zero2にしてみた。お値段も手頃。

OSにはarmbianを選択。これとPX1122R-EVBをTX/RXで接続して基準局データを送信することができることを確認。

で、ケースをRaspberryPiと同じサイズにで作成すると上部に余ったスペースが出来た。

まぁケースを小くすることも考えたが、折角なのでOLEDの液晶とタクトスイッチをユニバーサル基板に半田付けして、と。

OLEDの液晶はSSD1306を用いたi2c接続で128×64の解像度。アマゾンでも買える。

まぁ、難儀しましたよ。Raspiと違って圧倒的に情報量が少ない。しかもOrangepi は種類が多くてサンプルがあってもzero2では動かないとか。

pythonのOPi.GPIOも結局まともに動作させられず、pythonからsubprocessを呼び出すなんて美しくない方法でタクトスイッチのON/OFFを取得せざるを得ず。

LCDにはIPアドレスと現在時刻。タクトスイッチの状態を表示。スイッチを5秒以上長押しでシャットダウンできるようにしてみた。

キモはWiringOPでのGPIOコマンドとタクトスイッチの状態を確定させるための10kΩプルダウン抵抗。

#!/usr/bin/env python                                             

import subprocess                                                 
import datetime                                                   
import time                                                       
from oled.device import ssd1306                                   
from oled.render import canvas                                    
from PIL import ImageFont                                         
                                                                  
import ipget                                                      
                                                                  
while True:                                                       
  try:                                                            
    target_ip = ipget.ipget()                                     
    ip = target_ip.ipaddr("eth0")                                 
    break;                                                        
  except:                                                         
    time.sleep(5)                                                 
                                                                                                                                   
device = ssd1306(port=3, address=0x3C)  # rev.1 users set port=0  
                                                                  
font = ImageFont.load_default()                                   

flgPush = False #押されているか                                      
pushStart =0 #押された時間                                           
pushInt = 0                                                          
onStr="OFF"                                                          
                                                                     
flgShutdown = False                                                  
                                                                     
result = subprocess.run(                                             
        "/usr/local/bin/gpio mode 2 in",shell=True,                  
        stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True)     

while True:                                                                              
    result = subprocess.run(                                                             
            "/usr/local/bin/gpio read 2",shell=True,                                     
            stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True)                     
    val=result.stdout[0:1]                                                               
    if val == "1" :                                                                      
        if flgPush : #既におされているか?                                               
          pushInt = time.time()-pushStart                                                
        else :                                                                           
          flgPush=True                                                                   
          pushStart = time.time()                                                        
          pushInt = 0                                                                    
        onStr="ON"                                                                       
    else:                                                                                
        if flgPush :#既におされていて離した                                              
          flgPush=False                                                                  
          pushInt = time.time()-pushStart                                                
          onStr="OFF"                                                                    
          if pushInt > 5 :                                                               
              flgShutdown = True                                                         
              onStr="Shutdown..."                                                        
        else :                                                                           
          flgPush=False
          pushInt = 0
          onStr="OFF"

    with canvas(device) as draw:
       font = ImageFont.load_default()
       draw.text((0, 0), ip   ,  font=font, fill=255)
       t_delta = datetime.timedelta(hours=9)
       JST = datetime.timezone(t_delta,'JST')
       now = datetime.datetime.now(JST)
       d=now.date().strftime('%Y/%m/%d')
       draw.text((0, 12),d  ,  font=font, fill=255)
       t=now.time().strftime('%X')
       draw.text((0, 24),t  ,  font=font, fill=255)

       draw.text((0, 40),onStr  ,  font=font, fill=255)
       if not flgShutdown :
         if pushInt>0:
           draw.text((40,40),'{:.2f}'.format(pushInt),font=font,fill=255)
    if flgShutdown :
        break
    time.sleep(0.3)

time.sleep(3)
with canvas(device) as draw:
  draw.rectangle((0, 0, device.width-1, device.height-1), outline=0, fill=0)

print("shutdown")
result = subprocess.run(
         "/usr/sbin/shutdown -h now",shell=True,
         stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True)

2022年7月16日

NTRIP Caster SNIPの購入

Filed under: GNSS — pinewell @ 10:32 PM

基準局が3つになったのでLite版ではいろいろと使い辛く、BASICを購入。

実は2021/4/1に研究用として購入していたライセンスがある。この時は$851で購入。

2つのサーバーに使用するため今回追加で1ライセンスと思ったら$950に値上げされていた。円安も伴い、実際の請求はいくらになることやら。

PX1122Rでの5波対応基準局は上手く動いている。みちびき対応トリンブルで確認してもらったところ、QZSSを使用して補正されているとのこと。

GPS7500を使用した基準局をPX1122Rに置き換えるために「NS-HP-GN2 : PX1122R MULTI-BAND QUAD-GNSS RTK BREAKOUT BOARD」を発注。

こちらは$99。必要十分。

2022年6月29日

PX1122R を使用してのRTK基準局

Filed under: GNSS — pinewell @ 4:47 PM

NavSpark Store で購入したPX1122R-EVB が届いた。

早速自局の位置をRTKでFIX。そしてBaseモードにして基準局が設定できた。

ZED-F9PではできなかったGPS,GLONASS,QZSS,Galileo,Beidouの5波対応基準局となる。

AgLeaderにてFIXできることを確認。悲しい事にAgLeaderではGPSとGLONASSのみなので恩恵はまったくなし。

後日TrimbleなりのQZSSに対応したROVERで確認してみないと。

2021年1月18日

NtripCasterのロードバランサー

Filed under: GNSS — pinewell @ 11:01 PM

NtipCasterにSNIPを使用している。これはさくらのVPSでWindowsServerを借りての運用。耐障害性を考えて2台での運用していた。

2020年はそれぞれrtk1 とか rtk2 として接続先を変えていたのだが、本年より接続ユーザー数が30、クライアントとしては50台くらいにはなるのだろうか?

負荷分散を考えるに手動で設定するのは面倒。なのでロードバランサーの検討/導入となった。

単純にDNSラウンドロビンでも良いのだが、サーバーダウン時には対応が出来ないとなると二の足を踏んだ。

CentOSにてLVSとKeepalivedでの構築も考えたのだが(全て石狩データセンターなのでそれぞれがローカルでも繋っている)、ntripcasterはただのhttpサーバーとは違い、NtripServerからの基準局データを受け付けなければならず、これも断念。(実サーバーのdefaultgatewayがロードバランサーにしなければならず、globalIPでのntripserverの受付ができない。)

そこでさくらのクラウドにあるGSLB(広域負荷分散)を用いることとした。

NtripServerからの基準局データ送信は caster1.example.com と caster2.example.comとしてDNSにて登録されたglobalIPへ送信する。

NtripClientからは rtk.example.com としてDNSにてCNAMEされた GSLBのFQDNへ変換。さくらのGSLBに登録されている実サーバーのうち、適切なサーバーのglobalIPをクライアントに返すように設定ができた。

料金は月額550円。これは安い!

2021年1月16日

NTRIP 接続

Filed under: GNSS — pinewell @ 2:24 PM

ntripcaster 0.1.5 を使用してlinux鯖によるrtk配信サービスを構築するつもり。

”Lefebure NTRIP Client”での接続でローカル環境でのテストではOKなのにインターネット上のサーバーに接続すると認証エラーでつながらない。

ソースから main.c のinfo.logfiledebuglevel = 0 を 9にして全デバッグ情報を確認すると どういうわけか接続時の文字列の分解に失敗しているよう。

[Authorization] == [Basic XXXXXXXXXXXXXXXX] が取得できていない。

[Connectiotion] == [Basic XXXXXXXXXXXXXXXX]になってしまっているので client.c をいじって [Authorization]の取得に失敗していたら [Connectiotion]の値を使って認証させるように(場当たり的ではあるが)修正した。

AgLeaderではどうかと思い確認すると[Authorization] == [Basic XXXXXXXXXXXXXXXX]が無事取得できているのでまぁよし。

GET /AGS HTTP/1.0
User-Agent: NTRIP AgLeader/1.0 (InCommand)
Host: 192.168.1.254
Authorization: Basic XXXXXXXXXXXX

[16/Jan/2021:13:57:58] [4:Connection Handler] DEBUG: Building request out of [GET /AGS HTTP/1.0]
[16/Jan/2021:13:57:58] [4:Connection Handler] DEBUG: Building clean request from [/AGS]
[16/Jan/2021:13:57:58] [4:Connection Handler] DEBUG: Adding varpair [User-Agent] == [NTRIP AgLeader/1.0 (InCommand)]
[16/Jan/2021:13:57:58] [4:Connection Handler] DEBUG: Building request out of [Host: 192.168.1.254]
[16/Jan/2021:13:57:58] [4:Connection Handler] DEBUG: Adding varpair [Authorization] == [Basic XXXXXXXXXXXX]
[16/Jan/2021:13:57:58] [4:Connection Handler] DEBUG: Checking need for authentication on mount /AGS

 

GET /AGS HTTP/1.0
User-Agent: NTRIP LefebureAndroidIntNTRIPClient/20200406
Accept: */*
Connection: close
Authorization: Basic XXXXXXXXXXXX

[15/Jan/2021:14:48:04] [3:Connection Handler] DEBUG: Building request out of [GET /AGS HTTP/1.0]
[15/Jan/2021:14:48:04] [3:Connection Handler] DEBUG: Building clean request from [/AGS]
[15/Jan/2021:14:48:04] [3:Connection Handler] DEBUG: Adding varpair [User-Agent] == [NTRIP LefebureAndroidIntNTRIPClient/20200406]
[15/Jan/2021:14:48:04] [3:Connection Handler] DEBUG: Adding varpair [Accept] == [*/*]
[15/Jan/2021:14:48:04] [3:Connection Handler] DEBUG: Adding varpair [Connectiotion] == [Basic XXXXXXXXXXXX]
[15/Jan/2021:14:48:04] [3:Connection Handler] WARNING: Invalid header line [XXXXXXXXXXXX] without colon
[15/Jan/2021:14:48:04] [3:Connection Handler] DEBUG: Checking need for authentication on mount /AGS

 

簡単に修正できたように書いているが辿り着くまでは困難だった。

なにせローカルでは問題ないので苦もなく動くものと思いこんでいました。

それにしても[Connectiotion]って?再現性はあるのでもう少しスマートな修正もできるのでしょうが、C言語は不得手で。

2020年3月7日

ngrok

Filed under: GNSS — pinewell @ 11:29 AM

ngrokとは. 簡単にいうと、ローカルPC上で稼働しているネットワーク(TCP)サービスを外部公開できるサービス」だそうだ。
これを使うとグローバルIPが貰えないMVNOでも外部からアクセス出来そうだ。

2020年3月5日

自前基準局の作製

Filed under: GNSS — pinewell @ 11:18 PM

ZED-F9Pを用いた安価なRTK基準局の作製 その9

前回まででインターネット環境が整った自宅などを基準局とすることができるようになりました。(自宅ルーターのポート解放とかDDNSとかは端折ってますが。)
ここからはインターネット環境の無い場所での基準局の構築です。
実際のところ牛舎の屋根の上とか、倉庫の屋根の上など自宅にインターネット環境があっても敷地内にはLANケーブルの敷設が難しい場所もあるでしょう。
Wifiを使っても良いのですがここではMVNOを使った通信を行います。

アンテナ設置状況
D型の屋根に設置
まだ専用ケースが無くてダイソーのプラケース

・LTEルーターについて
NECから PA-HT100LNという製品が2017年の8月に発売されています。
半年前に購入した時は12,000円ぐらいだったし即入荷だったのですが、現在は最安値で13,140円しかも在庫は無しで2月22日に注文したら入荷予定が5月2日〜5月29日。即納できそうな処は15,000円を越えてきます。
RasPi3以降のWifiは高性能/電源キビシメで夏場の発熱が怖くて、どうしても有線で繋ぎたいので、代替機を模索中です。
いっそのことL-02Cでraspiから直接LTE通信してしまおうかとも。

・MVNO SIMについて
自宅からsshで繋いで管理をする都合上、グローバルIPが貰えるSIMが必要でした。調べると某ショッピングセンター系のドコモType2プランが最適です。
月1Gプランで480円。通信速度が低速時でも200kbpsなのでRTCMデータのみなら問題はありません。シリアルの通信が115.2kbpsなのですから。
1日24時間で約250MBのデータ送信を行っています。250*30=7500ひと月で8Gくらいのデータをアップロードしてますが今のところ上手くいってます。
問題があるとするならば一人5回線の制限です。とうとう妻の名前を借りることになりました。
他に低速(常時250kbps)でもつなぎ放題なMVNOがあります。某カメラ店で販売しています。
これでもテストを行っていますが通信速度的には問題ないのですがグローバルIPがもらえないので却下です。
その他2社ほど試してみた結果の結論です。

・ルーターに求める機能について
有線接続ができること。
ポート解放ができること。
DHCPサーバー機能でMACアドレスで指定ができること。
必須ではないが無線LANのアクセスポイントとなること。これができると現場でPCからWifi接続、raspiの設定変更が出来る。

この据置きルーターは使えなかった。

上記のLTEルーターはルーターとしての機能(DHCPサーバーのMACアドレス指定、ポート解放)が出来無いものだったのでゴミとなった。Amazonでも売ってますね。コメントが微妙。技適ってなに?商品です。

自前基準局の作製

Filed under: GNSS — pinewell @ 9:35 PM

ZED-F9Pを用いた安価なRTK基準局の作製 その8

RaspberryPiの設定
Raspbianをセットアップ。
sshを使えるように。/boot/ に touch ssh
基本的な設定(raspi-configによるupdate、パスワード変更など。)
GPIOのUART(シリアルポート)を使えるように。
raspi-configにて
[5 Interfacing Options]-[P6 Serial]を選択。
Would you like a login shell to be accessible over serial?に<No>。
Would you like the serial port hardware to be enabled?に<Yes>。


RTKLIBのダウンロード、unzip。
RTKLIBのstr2strだけコンパイル。
$ cd {解凍dir}/app/str2str/gcc
$ make
終わるまで待つ。
/usr/bin/にstr2strをコピー。
$sudo cp str2str /usr/bin/
接続確認
$sudo str2str -in serial://ttyAMA0:115200 -out ntrips://:{PASS}@xxx.xxx.xxx.xxx:2101/KAYANO
これで繋がるならRaspi起動後に実行されるようにrc.localの設定。
exit 0 の前の行に
/usr/bin/str2str -in serial://ttyAMA0:115200 -out ntrips://:{PASS}@xxx.xxx.xxx.xxx:2101/KAYANO

str2strでシリアルから受信、NtripCasterに接続できている様子。
Reserved MountPtsから接続されるとグリーンに変る。
解析が済むとRTCM3viewerで送信されている状況がわかる。

自前基準局の作製

Filed under: GNSS — pinewell @ 1:26 PM

ZED-F9Pを用いた安価なRTK基準局の作製 その7

NtripCater SNIPのインストール・設定
私はさくらのVPSを借りていますが自宅サーバーでも運用しています。
DDNSなどで名前解決、ポート開放などができれば自宅サーバーでも可能でしょう。
VPSを借りているのは複数台のRoverからのアクセスに耐えられる帯域を確保したいためです。
自宅サーバーのアップロードの帯域では不安で。
サーバーの能力的にはW1Gプランで十分かと。HDD容量も必要ありません。

SNIPをダウンロードしてインストールします。
・ユーザー登録が必要だったはず。
・サービスとしては動かず、ログインした状態で実行しつづけなければならない。
・LITEとしてレジストしなければ評価モードとして動作し1時間で切れる。
・LITEでレジストしてしまうとStream設定の編集・追加ができなくなる?
特に最後の部分が問題です。お金があるならばBASICを購入した方が良いです。

SNIP起動
最初の起動でいきなり配信がスタートしてしまいます。(「Auto Start」にチェックが入っている)
[Caster and Clients]タブを選択して [Disconnect]します。
[Caster IP:] 127.0.0.1 これはVPSならグローバルIPです。
[Cster Port:] 2101 特に問題なければ変えません。NtripのWellKnownPortはまだ無いようです。実質多くのアプリが2101がデフォルト値となっているようです。
Windowsのファイアウォールの設定で開放しておきます。
[User Accounts]ボタンで接続ユーザーの管理ができます。
ユーザーあたりの接続数も制限できます。
[Allow Annoymous Access for Users]のチェックを外すと匿名では接続できなくなります。
[Allow Use-SNIP.com access for quality monitoring]も外しておきます。

[Relay Streams]タブ
ここは5つの転送するストリームが登録されています。
全て不要なのでストリームを選択して右クリック [Remove] します。

[Pushed-In Streams]タブ
ここにRaspiから受信するストリームを設定します。
[Add]ボタンを押します。
[MountPt]-[Configure]ボタンでマウントポイントの詳細設定ができます。

右側から
[Mount Pt] 一意になる名称を設定します。
[City/Satte] 都道府県で良いかな。
[Contry] JP
[Data Format] RTCM 3.x(Auto)
[GNSS types] GPSとGLONASSにチェック
[Carrier] 周波の数です。ZED-F9Pは2周波なので2
[Msg Types] 空白でも作成してくれます。
[Location] おおよその値を入力しています。
[Access] 初期値のままで。
[Misc]空白です。
左側
[Password]このストリームにアップするためのパスワードです。
[Parse] チェックを入れます。送られてくるストリームを解析してくれる。
保存して [Caster and Clients]タブに戻り、[Connect]ボタンでNtripCasterとして受付待ちとなります。
その前に。
[Misc]ツールバーからの[Data File Settings]を開き、ログデータの設定をします。
容量の少ないVPSではログを貯めきれないので[Delete data files after ] 3 [Days].としてチェックをいれます。

[Help]-[Registration]
[Select the type of license below]のコンボボックスでLite(Free)を選択。
[Next]ボタンで名前とメールアドレスを入力して[Next]。
SNIP Legal Agreement を読んで [I agree to the terms of the license]に同意ができたらチェック。[Next]。
[Register]ボタンでLiteバージョンとして登録されます。
以降、ストリームの編集・削除?ができなくなります。
追加も個数を超えるとできなくなる?

« Newer PostsOlder Posts »

Powered by WordPress