工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

thingser.ioマップ統合を備えた車のGPSトラッカー

コンポーネントと消耗品

>
Arduino Leonardo
Leonardoを使用して専用のハードウェアシリアルを取得します。
× 1
SIM900開発ボード
× 1
u-blox NEO-6MGPSモジュール
× 1
アンテナ、GPS
× 1
抵抗220オーム
× 2
LED(汎用)
× 2
はんだボード7x 5cm
ステータスLEDの「回路」に3Dプリントされたエンクロージャーに適合するはんだボードを使用しました。ただし、一般的なブレッドボードを使用することも、ステータスLEDが必要ない場合は完全にスキップすることもできます
× 1
12Vから5Vへの降圧モジュール
電源を車のバッテリー(またはタバコのソケット)に接続するため
× 1
AdafruitSDカードリーダー
× 1
フラッシュメモリカード、MicroSDカード
× 1

必要なツールとマシン

>
はんだごて(汎用)

アプリとオンラインサービス

>
Thinger.ioプラットフォーム
ダッシュボードを備えた無料のIoTサービス!

このプロジェクトについて

このプロジェクトは、単純な「GPSトラッカーのアイデア」として始まり、「多目的GPSトラッカー」であることが判明しました。私の最初のプロジェクトとして、学習曲線は急勾配でした。そのため、私は常にデザインの入力、フィードバック、および改善を受け入れています。 :)

トラッカーは私の車に配置するためのもので、次の機能があります。

  • GPS座標を追跡し、2分ごとにthinger.io IoTクラウドダッシュボードに最後の既知の場所を投稿します(地図に表示されます)。 HTTPPOSTリクエストを使用してthinger.ioに投稿します。
  • SMSコマンドに応答し、現在または最後の既知の場所(現在の場所が利用できない場合は最後の既知の場所)へのGoogleマップリンクを返します。
  • XXキロメートルごとにSMS通知を送信します(4000 kmごとにオイルキャッチタンクを空にするようにトラッカーに通知させるというアイデアです)。これは、カスタマイズ可能なソフトウェア「走行距離計」として機能します。

このプロジェクトの間に、使用可能なメモリに関してArduinoがいかに「制限されている」かをすぐに理解し、オーバーヘッドを削減して効率的なコードを作成するための手法を学ぶ必要がありました(少なくとも私は試みました)。また、軽量ライブラリを使用して、チップ上のすべてのものと使用可能なRAMを適合させました。

使用されるコンポーネントは次のとおりです(コンポーネントリストのように):

  • NEO-6MGPSデバイス。これは、Ebayなどで安価に入手できる非常に人気のあるGPSデバイスのようです。 GPSとの通信はハードウェアシリアルになります。
  • GPSアンテナ。互換性のあるものならどれでもかまいませんが、Ebayの最も安いものはそれほどうまく機能しませんでした。つまり、受信状態が悪い/衛星の数が少ないということです。最初のアンテナが不運だったのかもしれませんが、安定した受信のために別のより高品質のアンテナを入手する必要がありました。
  • GSMおよびGPRS接続用のSIM900開発ボード。このプロジェクトは、SIM800および互換性のあるモジュールでも機能するはずですが、保証はありません。 SIM900との通信はソフトウェアシリアルになります。
  • Arduino レオナルド ボード。私はレオナルドボードを使用して、専用のハードウェアシリアルラインを使用しました。 2本のシリアル回線が必要なので。通常のUNOボードを使用することも可能ですが、ソフトウェアをダウンロードするにはGPSを切断する必要があり、デバッグ用のシリアルモニターもありません。 2つのシリアル回線が必要です(1つはGPS用、もう1つはSIM900ボード用)。 1つのソフトウェアシリアルと1つのハードウェアシリアル。
  • SDカードリーダー(5V互換のAdafruitカードリーダーを使用しました(5V SPIヘッダーへの接続が簡単になりました)。他の安価なモジュールでも同様に機能する可能性があります。マイクロSDカードを使用して移動距離を保存します。<強い>警告: 私の回路図に従う場合は、SDカードリーダーが5V電源をサポートしていることを確認してください。多くのSDカードリーダーは3.3Vしか使用していません。誤った電圧レベルを使用すると、電子機器が損傷する可能性があります。 SDカードリーダーとの通信はSPIインターフェースになります。
  • ステータスインジケータ回路を作成するためのLEDと抵抗器(電源およびGPSロックLED)。
  • データ付きのSIMカード。
  • また、3Dプリンターで直接印刷できるSTLファイルが添付された3D印刷可能なエンクロージャーを設計しました。

まず、必要なライブラリをインストールする必要があります。このプロジェクトでは次のライブラリを使用しました:

  • NeoGPS GPSの追跡とデコード用。 ArduinoIDEのライブラリマネージャーから直接インストールできます。詳細:https://github.com/SlashDevin/NeoGPS
  • 時間 ライブラリ(UTCタイムゾーン変換に使用):https://github.com/PaulStoffregen/Time
  • PetitFS SDカードへの読み取り/書き込みの場合:https://github.com/greiman/PetitFS Lightweight SDFATライブラリ。

Arduinoで利用可能なライブラリを使用してみませんか thingser.io?

thingser.ioが提供するライブラリは非常に使いやすく、IDEにすでに統合されていることは言うまでもなく、大幅に簡素化されますが、Arduino Leoのストレージのほぼ80%を消費し、残りのコード用のスペースをほとんどまたはまったく残しません。ですから、このプロジェクトには大きすぎるので、私たちはそれを難し​​い方法でやらなければなりません。 thingser.ioクラウドとの通信には、 HTTPPOSTリクエストを使用します。

SMS コマンド

SMSで使用できるコマンドは次のとおりです(すべて大文字)。これらは、提供されたコードでサポートされているコマンドです。独自のプロジェクト/要件のコマンドを追加/削除できます:

  • 「POS」 座標が利用可能な場合は、Googleマップリンクで座標を返します。それ以外の場合は、最後の既知の場所が返されます。
  • 「GETKM」 最後の「リセット」からの現在の距離を返します。
  • 「RESETKM」 距離カウンターを0に設定します(走行距離計をリセットします)。
<図> >

NeoGPSの設定

TinyGPS ++のような代替手段よりも、パフォーマンスとリソースの使用にNeoGPSライブラリを使用します。 RAMの消費量は非常に少なく、これが必要です。そうしないと、メモリ不足と安定性に関する警告が表示されます。

ライブラリをインストールしたら、ファイル GPSPort.h を変更します ライブラリのインストールパス(OS Xの場合の例-Windowsの場合、ライブラリは別の場所にあります)

GPSPort.hのすべてのコンテンツを次のように置き換えます。

  #ifndef GPSport_h#define GPSport_h#define gpsPort Serial1#define GPS_PORT_NAME "Serial1" #define DEBUG_PORT Serial#endif  
<図> <図>

このファイルには、NeoGPSライブラリで使用される定義が含まれています。別のArduinoボードを使用している場合は、ここでGPS受信機へのシリアルラインを定義します。 Arduino MEGAの「Serial2」、「Serial3」。

精度に関する注意事項

GPSは、静止しているときでも位置がわずかにドリフトするため、距離を測定および累積するための最も正確な方法ではないことに注意してください。同じ場所にじっと立ってこれをテストし、GPS座標が読み取りごとに異なることを確認できます。このアプリケーションでは、精度はそれほど重要ではないため、偏差を小さくしても問題ありません。

ただし、座標の小さなドリフトを考慮しようとしましたが、ソフトウェアは15秒を超える10mを超える移動(10m未満のすべての移動は静止していると見なされます)の距離のみを追加します。

また、距離は直線で計算されますが、実際の車の走行距離は道路や曲がり角などによって異なります。サンプリングレートを15秒に設定しましたが、もっと長くしたい場合はこれを短くすることもできます。精度。

PetitFSの設定

このライブラリは、FAT形式のSDカードの読み取り/書き込み用の超軽量ライブラリです。ドキュメントがほとんど存在せず、場所によっては間違っている/古くなっているため、これがどのように機能するかを理解するのに少し時間がかかりました。提供されているライブラリのサンプルコードはコンパイルすらしません。 ロットが付属しています 制限事項(ArduinoのSDライブラリやSDFatのような「通常の」ライブラリとは対照的):

  • ファイルを作成できません。書き込むことができるのは既存のファイルのみです。
  • ファイルサイズを拡張できません。
  • ファイルのタイムスタンプを更新できません。
  • ファイルにデータを追加できません(毎回ファイルを書き換えます)。
  • 一度に開くファイルは1つだけです。

多くの癖のある小さくて限られたライブラリを使用するのはなぜですか?

サイズ、基本的に。 Arduino SDライブラリ、SDFat、fat16libなどのライブラリをいくつか試しました。それらはすべて大きすぎてすべてのコードをチップに収めることができないため、機能を削除しないためにこのライブラリを使用しました(標準のArduino SDライブラリは約12%多くのスペースを必要とします)。すべての癖や制限があっても、このアプリケーションに必要なもの、つまりストレージ用の単一の値の単純な読み取りと書き込みを提供します。

すべてのコードを使用せず、余分なものを詰め込むのに十分なスペースがある場合は、標準のSDライブラリなどのライブラリを使用する方がはるかに簡単です。

<図> <図>

ファイル pffArduino.h を開きます PetitFSライブラリフォルダから。 SD_CS_PIN を変更します 〜 10。 これは、SPIを使用してSDカードと通信するために使用されるSSピンです。

<図> <図>

ファイル pffconf.h を開きます ライブラリフォルダから。 無効 設定値を1から0に切り替えることにより、以下のオプションがあります。

  • _USE_DIR
  • _USE_LSEEK
  • _FS_FAT12
  • _FS_FAT16

これらのオプションを無効にすることで、コンパイルされたプログラムが占めるスペースが少なくなります。これは必要です。最終的なスケッチは約かかります。ストレージの96%。

<図> <図>

ライブラリの最初のインポート時に、無視できる*コンパイルエラーが発生します(2番目のコンパイルではエラーは表示されません-それでも理由はわかりません)。ただし、これを修正したい場合(Arduino IDEを起動するたびに再表示されます->コンパイル)、上のスクリーンショットに示すように、欠落している関数の戻りパラメーター「FRESULT」を追加します。これはファイル pff.cpp にあります ライブラリフォルダにあります。

私はこのライブラリがどのように機能するかを理解するために最善を尽くしました。すべてが機能するようになりましたが、状況も改善できると確信しています。私が書いたルーチンに間違いや改善を見つけたら、遠慮なく共有してください!もっと学び、経験を積んでいきたいです。

SDカードを準備します

このプロジェクトではマイクロSDカードを使用しました。ライブラリはファイル自体を作成できないため、使用する前にカードにファイル「dist.txt」と「settings.txt」を作成することが重要です。 添付の「dist.txt」と「settings.txt」をコピーすることをお勧めします このプロジェクトページのファイル。これらのファイルはすでに正しい形式で機能しているためです(ライブラリは非常に テキストの形式と内容にこだわりがあります。

ファイルをMicroSDカードに挿入する前に、カードを適切にフォーマットしてください( FAT32 として) )。 SDアソシエーションの公式「SDカードフォーマッター」を使用することをお勧めします:https://www.sdcard.org/downloads/formatter/。

SDカードが機能することを確認する(ファイルの読み取り/書き込みが正しく行われる)

PetitFSライブラリは非常に 入力ファイルにうるさい。デバイスを起動し、シリアルモニターに出力が表示されない場合(空白のみ)、カードからファイルを読み取ろうとするが何らかの理由でできない「ループ」でスタックしている可能性があります(initializeSD()関数)。なんらかの理由で読み取れなかったテキストファイルが無数にあるため、使用した参照テキストファイルを含めました。 これらの参照を配置 SDカード上のファイルであり、SDカードに対して正しく読み取りと書き込みの両方ができる必要があります。

もう1つのオプションは、テキストファイルに大きい番号を入力することです。 その執筆のものより。私はこれをテストしていませんが、ライブラリはファイルサイズ自体を拡張できないため、これが問題になる可能性があると考えています。

<図> <図>

PetitFSは文字配列の全長をファイルに書き込むため、実際の数値の前に空のスペースが表示されます(数値が配列を満たすのに十分な大きさでない限り、「配列」の長さはコードで定義されています)。ファイルを変更するときは、これらのスペースを保持する必要があります。PetitFSはファイルサイズを変更できないため、文字数を変更すると問題が発生する可能性があります。

走行距離計を「0」から開始する場合は「dist.txt」ファイルを「0」に設定し、動作を簡単に確認できるように他の数値を設定します。 SMS応答を確認するために「GETKM」コマンドを送信します。

「settings.txt」で、通知トリガー距離、走行距離計が通知SMSをトリガーする距離(メートル単位)を設定します。

SIM900ボードを準備する

SIM900ボードを使用するには、いくつかの設定が必要です。詳細については、https://lastminuteengineers.com/sim900-gsm-shield-arduino-tutorial/にこのボードのセットアップに関する優れたリソースがあります。

<図> <図> <図> <図>

電源

Arduinoボードは十分な電力を供給できないため、外部電源を使用する必要があります。スパイクは最大2Aを消費する可能性があるため、5V〜9VDCで少なくとも2Aを供給できる電源を使用してください。バレル5.5mmコネクタを使用しています。

電源セレクター

DCジャックの隣には電源セレクターがあります 。外部電源を使用するには、上の図のようにスライダーを動かします。

シリアルセレクター

ソフトウェアシリアルを使用するようにボードを設定します 上記のようにジャンパーを揃えます。

ソフトウェアトリガー

毎回手動で電源キーを押す代わりに、ソフトウェアでSIM900のオン/オフを切り替えることができます。そのためには、R13という名前のジャンパーをはんだ付けする必要があります。次に、SIM900ピン#9をArduinoピン#7に接続してボードの電源を入れます(回路図を参照)。

「手動電源オン」機能を維持する場合は、コード内の「SIM900power()」関数を削除できます。

SIMカードのPINロックを解除する

必ず PINロックを解除してください 使用する前にSIMカードに。これは、通常の電話に挿入し、該当する設定メニューからピンロックを解除することで実行できます。

また、回路図のSIM900モジュールは実際のボードとは異なって見える場合がありますが、ピンのレイアウトが正しいことにも注意してください。これが最も重要な部分です。

SIM900ファームウェアバージョン (重要!)

正しいバージョンのファームウェアをチップにロードすることが非常に重要です。これは、HTTP POSTヘッダーを正しく設定するコマンドの1つが、ファームウェアのバージョンB10までサポートされていないためです。これは、http通信が機能するためには少なくともバージョンB10以降が必要であることを意味します。具体的には、ファームウェアバージョンが低い場合、httpヘッダーに「Content-type」を設定できません。 postリクエストでcontent-typeが「application / json」に設定されていない場合、サーバーによって拒否されます。

ファームウェアのバージョンを確認するには、次のATコマンドを使用します。

  AT + CGMR  

SIM900チップは、出力コンソールに現在のファームウェアバージョンを提供します。 setup()セクションの最後に次のように入力して、起動時にファームウェアバージョンを出力します。

  SIM900.println(F( "AT + CGMR"));  

私の場合、これが表示されます(更新する前):

  Revision:1137B01SIM900M64_ST_AM  

これは、このチップ( "B01")の可能な最も古いファームウェアバージョンであったため、バージョンB10に更新しました: 1137B10SIM900M64_ST 。新しいファームウェアも機能するはずです。

このガイドではファームウェアの更新方法については説明しませんが、これを行うための優れたガイドがすでにあります。SIM900ファームウェアの更新-ACOPTEX(多少面倒なプロセスですが)。

SIM800のような他のチップにこれが当てはまるかどうかはわかりませんが、これは新しいチップであるため、すでにそこに配置されている可能性が高いと思います。

コードの調整

コードを独自のプロジェクトに適合させるには、いくつかの調整が必要です。

  • APN(ネットワークプロバイダー)情報を変更します。
  • thinger.ioのURLを自分のものと一致するように変更します(URLは、更新要求をアクセストークンを使用して自分の「バケット」にリンクします)。これについては、「thinger.io統合」の章で説明しています。
  • 正しいタイムゾーンを設定します。
  • SMS通知のトリガー距離を設定する
  • SMS通知テキストを設定(または無効化)します。
  • 通知用のデフォルトの電話番号を設定します。

APNプロバイダー

  void connectGPRS(){... SIM900.println(F( "AT + SAPBR =3,1、\" APN \ "、\" TeleXXX \ "")); delay(1000); updateSIM900(); ...  

connectGPRS()の下 関数には、ネットワークプロバイダーによって指定されたAPN名があり、上記の "TeleXXX"として示されています。 これを独自のAPN名に置き換えてください。

  ATOKAT + CMGF =1OKAT + CNMI =1,2,0,0,0OKAT + SAPBR =3,1、 "CONTYPE"、 "GPRS" OKAT + SAPBR =3,1、 "APN"、 " TeleXXX "OKAT + SAPBR =1,1OKAT + SAPBR =2,1 + SAPBR:1,1、" 36.57.240.233 "OK  

上:接続が機能しているときのconnectGPRS()関数の出力。すべてのコマンドは「OK」ステータスを返す必要があります。

タイムゾーン

  #define UTC_OFFSET 1 //タイムゾーンオフセットを設定します。つまり、1 =UTC + 1  

「定義」セクションで、要件に応じてタイムゾーンを設定します。コードはUTC + 1 に設定されています 。

SMS通知

オイルキャッチタンクを空にするために4000kmごとに通知を設定しました。ほとんどの人がオイルキャッチタンクを持っていないことを私は理解しているので、この通知はあなたが望むものに変更する必要があります(または完全に無効にします)。

  void loop(){... //合計距離が4000kmを超えると、SMSで通知を送信しますif(totalDistance> triggerDistance){char sms_msg [160]; char distanceTotalMsg [10]; itoa((totalDistance / 1000)、distanceTotalMsg、10); sprintf(sms_msg、 "空のキャッチタンク!現在の距離:%skm"、distanceTotalMsg); textMessage =""; totalDistance =0; //通知番号をトリガーするデフォルトの電話番号を設定します=DEFAULT_NUMBER; sendSMS(sms_msg); } ...}  

上:通知をトリガーするコードセクション(メインloop()内)。

トリガーされた通知が必要ない場合は、このセクションをコメントアウト/削除してください。または、テキストを有用なものに変更します。

「走行距離計」(累積距離)が「settings.txt」ファイルで設定された設定距離に達すると、通知がトリガーされます。

デフォルトの電話番号

これは、トリガーされた通知が送信される電話番号です(通知には返信する「送信者」番号がないため)

  //トリガーされた通知の電話番号#defineDEFAULT_NUMBER "+4712345678"  

シリアル接続を待ちます

コード内の次の行のコメントを外すこともお勧めします。これにより、Arduinoボードは、シリアル接続がアクティブになるのを待機します。つまり、デバッグ用のシリアルモニターです。このようにして、シリアルラインがアクティブになる前にコードの先頭にあるデバッグメッセージを見逃すことはありません。

Arduinoに外部電源から電力を供給する前に、その行を削除/コメントすることを忘れないでください。そうしないと、PCに接続するまで無限ループで停止します。

  // while(!Serial); //シリアルポートが接続するのを待ちます-ATmega32u4(Leonardo)の場合 

Thinger.io統合

非常に簡単なthinger.ioの設定方法については詳しく説明しません。あなたは彼らのウェブサイトを通してデータを受け取るためのアカウントと「バケツ」、そして私たちが接続する「デバイス」を作成しなければなりません。 「バケット」は、データを受信するためのデータベースです。 「デバイス」は、データをどのように処理するかを決定するコードの接続ポイントです(この場合、「バケット」データベースにデータを入力します)。

<図>

上記のように、自分の名前と説明を使用して「バケット」を作成します。

次に、公式ドキュメントhttps://docs.thinger.io/quick-sart/devices/http-devicesで説明されているように、「HTTPデバイス」を作成します。

<図> <図> <図>

短いを使用する デバイス 名前 。デバイス名は認証キーを生成するアルゴリズムの一部であるため、デバイス名が長いほど認証キーも長くなることがわかりました。問題?認証キーは、Arduinoから文字列を送信するために使用される256文字のバッファよりもすぐに長くなりました。これを修正するためのより良い方法はおそらくいくつかありますが、デバイス名を短くして問題を回避するための最も簡単な方法を見つけました。

デバイスのコールバック > 設定 セクションでは、「書き込みバケット」設定が以前に作成されたバケットを指していることを確認します。これにより、「デバイス」に受信データをデータベースに書き込むように指示されます。

デバイスのコールバック > 概要 セクションでは、メソッドをメモします URL および認証ヘッダー (キーワード「Bearer」のない長い文字列)。

データをthinger.ioに送信するには、HTTPPOSTリクエストで「認証URL」を使用します。次に、コード内のURLと認証キーを独自のものに置き換える必要があります。

postDataThinger() 呼び出しを見つける機能(実際の認証キーがスクランブルされています):

  SIM900.println(F( "AT + HTTPSARA =\" URL \ "、\" http://backend.thinger.io/v3/users/tom/devices/CT/callback/data?authorization =eyJhbGciOiJIUzI1NiIsInR5cdfkjowiuerdf.sdfsdf.wekrjciI6InRvcm1vZCJ9.AR1gWvIZB9KmtI-5Z12YXKuchPTGn58AkwBJSZQIoxQ \ ""));  

次に、 URLを置き換える必要があります および承認 キー 上記のリンクの指示に従って生成された、独自のコードで。

  http://backend.thinger.io / ...  

デフォルトでは、生成される認証URLは https になります 。 SIM900はしません サポート SSL (少なくとも動作していません)ので、必ず「http s 」を変更してください :// "から" http:// "。thingerAPIは非SSL接続もサポートします。これは非常に重要です。" https "を保持すると機能しません。すべてが機能する場合、シリアルモニターは" 200を表示する必要があります。 --OK」http投稿リクエストを送信するときに返信します。

ATコマンドの後 "AT + HTTPACTION =1" (HTTP POSTリクエストを送信)シリアルモニターで次のような応答を受信する必要があります:

  + HTTPACTION:1,200,0  

「400-不正なリクエスト」の返信などを受け取った場合。

  + HTTPACTION:0,400,51  

..URLに何か問題がある可能性があります。 「http」の代わりに「https」、「認証キー」の構文が間違っているなど。「200-OK」メッセージを受信すると、データは次のようにthingerバケットに表示されます。前述のように正しいファームウェアがない場合は、400-「不正な要求」を受け取ることもあります。

<図>

上記は、データが到着した後のバケットのビューです(プライバシー上の理由からスクランブルされています)。コンテンツ(データ列)は、コード内のHTTP POSTリクエスト構文によって設定されます。thinger.ioでの設定は必要ありません。

以下は、すべてが機能したときに表示されるHTTPPOSTリクエストのシリアル出力です。 + HTTPACTION:1、200、0は、更新が成功したことを示します。

  AT + HTTPINITOKAT + HTTPSARA ="CID"、1OKAT + HTTPSARA ="URL"、 "OKAT + HTTPSARA =" CONTENT "、" application / json "OKAT + HTTPSDATA =84,10000DOWNLOADOKAT + HTTPACTION =1OK + HTTPACTION:1,200,0AT + HTTPTERMOK  

ダッシュボード その後、バケットをデータソースとして使用して、マップウィジェットを使用してThingerで簡単に設定できます。

<図>

より多くのデータを物事に?

経度、緯度、日付/時刻よりも多くのデータをプッシュしますか?以下に示すように、httpリクエストにデータフィールドを追加するだけです。

形式は{"field1name":field1、 "field2 name":field2、 "field3 name":field3}

  sprintf(httpContent、 "{\" longitude \ ":%s、\" latitude \ ":%s、\" date \ ":\"%s%s \ "}"、tempstrLong、tempstrLat 、date1、time1);  

上記のsprintfコマンドは、thingerに送信されたデータ文字列をコンパイルします。構文は*非常に*厳密であり、まったく同じ方法で新しいデータフィールドを追加する必要があります。例はコード(コメントセクション)に示されています。文字列を表示するコマンドのシリアルモニター印刷をメモしておくことをお勧めします。次に、「field4」などを追加します。

エンクロージャー

完全な3D印刷可能なエンクロージャーを取り付けました。これは、このプロジェクトで使用される正確なPCBに適合するように設計されています。取り付けにはM3ネジを使用します。

<図> <図> <図> <図> > <図> > <図> >

ブレッドボードではなく、LED「回路」用の7x5cmはんだボード用に設計されています。ブレッドボードを使用する場合は、代わりに接着剤を使用してください。 GPSとはんだボード(「ブレッドボード」)は上部ケーシングに取り付けられています。上部ケーシングにPCBを最適に取り付けるには、小さなスペーサーを使用してください。

また、サポートなしで簡単に印刷できるように、上部ケーシングの取り付けポイントをしっかりと(穴なしで)維持しました。これらを3mmのドリルビットで開きます。

サポートなしで0.2mmでうまく印刷されます。

車のバッテリー/電源への接続

これを行うにはおそらく何百もの方法があるので、私には唯一の答え、またはその問題に対する最良の答えはありません。車のバッテリーに配線する方法。それはすべてアプリケーションによって異なりますが、私のソリューションについて簡単に説明します。

私はデバイスを車から始めたいと思っていたので、バッテリーに直接接続されていませんでした(そして車がオフになっている間は電力を消費していました)。それで、私はそれをすでに車でオン/オフになっている「タバコソケット」回路に接続しました。車がオフのときでもオンラインにしたい場合は、バッテリーに配線する方法を見つける必要があります。ほとんどの車では、タバコのソケットは車と一緒にオフになりますが、自分でこれを確認する必要があります。これも車ごとに異なるので、私の正確な配線は示しません。また、バッテリーパックを間に置いて、車の電源を切った(または盗まれた)後もデバイスを何時間も動かし続けることができます。

もちろん、これらのUSB電話充電器のようなアダプターを使用することもできますが、それは(車が盗まれた場合に備えて)それを隠すという私の目的に反します。また、ArduinoボードとSIM900モジュールの2つの電源があります。私は12V-5Vから変換する「Chinacheap-omatic」降圧モジュールを使用しました(実際の入力範囲は9V-20Vと言われていました)。おそらく品質は良くありませんが、これまでは問題なく機能しています:)

降圧モジュールは、12V入力を5V出力に変換して2つのUSBメスコネクタに変換します。次に、ArduinoおよびSIM900モジュールをこれらの各USB出力に接続して、それらに電力を供給しました。おそらく他のもっと「専門的な」解決策がありますが、これは安価で十分に機能しました。

私はGSM活動中の消費電力を約110maHと測定したので、消費電力はごくわずかです。おそらく、GSMのカバレッジが悪い地域でより多くの電力を引き出すでしょう。

<図> > <図> > <図> > <図> >

既知の問題

thingser.io httpリクエストの処理と同時に(データがthingerにプッシュされている間に)SMSコマンドを受信した場合、そのコマンドはソフトウェアによって取得されません。この場合、SMS応答は受信されません。数秒後に新しいコマンドを送信すると、再び機能します。これは大きな問題ではないため、回避策は作成していません。誰かがこれを修正する必要がある場合は、遠慮なく共有してください。

また、Arduinoがネットワークカバレッジのないエリアで起動された場合、起動時にのみ接続されるため、ネットワークが再び利用可能になったときに再接続されません。これを修正するために、ある時点でコードを変更する可能性がありますが、現時点では

コード

  • GPS_tracker_Leonardo_v2.ino
GPS_tracker_Leonardo_v2.ino Arduino
 #include  #include  #include  #include  #include "PF.h" #include "PetitSerial.h" #define UTC_OFFSET 1 / /タイムゾーンオフセットを設定します。つまり、1 =UTC + 1#define TXPin 8 // SIM900 Tx pin#define RXPin 9 // SIM900 Rx pin#define PWRPin 7 // SIM900ソフトウェア電源ピン//トリガーされた通知の電話番号#defineDEFAULT_NUMBER "+4712345678" FATFS fs; //ファイルシステムオブジェクト-SDカードの読み取り用// GSM変数StringtextMessage; //最後に受信したテキストを保持しますmessageStringnumber =DEFAULT_NUMBER; //最後のテキストからの電話番号messagecharsms_msg [160]; // SMS応答テキストを保持します//場所変数floatLat =0、Long =0; boolean valid_location =false; //初期の有効な場所flaguint8_tnum_sat; NeoGPS ::Location_t prevFix; //距離計算のために以前の場所を保持しますNMEAGPSgps; // GPS文字を解析しますgps_fixfix; //最新の値を保持しますconstchar * googlePrefix ="http://maps.google.com/maps?q=";const char * filename =" DIST.TXT "; const char * settings =" SETTINGS.TXT "; //時間変数NeoGPS ::time_t timeFix; //現在のGPSの時間オブジェクトfixchardatePrint [13]; char timePrint [10]; //距離追跡変数floattotalDistance =0; //メートル単位// triggerdistance(走行距離計通知)はinitfloatのSDカードから読み取られますtriggerDistance =4000000; SoftwareSerial SIM900(TXPin、RXPin); // SIM900 Tx&RxはArduino#8&#9に接続されていますvoid setup(){pinMode(3、OUTPUT); pinMode(4、OUTPUT); digitalWrite(3、HIGH); //電源LEDをオンにしますSerial.begin(9600); //シリアルモニター/ *以下の「while(!serial)」構文は、PCに接続されている場合にのみデバッグ目的で有効にする必要があります。これがコードに保持されている場合、シリアル接続が確立されないため、外部電源に接続するとプログラムはループで停止します* / // while(!Serial); //シリアルポートが接続するのを待ちます-ATmega32u4(Leonardo)の場合SIM900.begin(9600); //ピン#8および#9のSIM900モジュールgpsPort.begin(9600); // Serial1ピン#0および#1のGPS受信機-GPSport.hで定義// SDカードを初期化し、標準設定と累積距離を読み取りますinitializeSD(); //ソフトウェアトリガーSIM900power();でSIM900の電源を入れますSIM900.println(F( "AT")); // SIM900でのハンドシェイクdelay(500); SIM900.println(F( "AT + CMGF =1")); // TEXTモードの設定delay(500); SIM900.println(F( "AT + CNMI =1,2,0,0,0")); //新しく到着したSMSメッセージの処理方法を決定しますdelay(500); connectGPRS();} void loop(){while(gps.available(gpsPort)){fix =gps.read(); num_sat =fix.satellites; if(fix.valid.location){digitalWrite(4、HIGH); // GPSロックLEDを設定しますLat =fix.latitude(); Long =fix.longitude(); //最初の「GPSロック」フラグを保存します-有用なデータがありますif(Lat!=0 &&Long!=0 &&!valid_location){valid_location =true; prevFix =fix.location; }} if(fix.valid.date &&fix.valid.time){timeFix =fix.dateTime; updateTime(); } //thinger.ioを更新し、有効なgps修正のためにのみSDカードに値を書き込む//通常、gpsが最初に座標にロックされる前の起動時if(valid_location){// 15秒ごとに移動距離を更新staticconst unsigned long REFRESH_INTERVAL_UPD =15000; // 15秒staticunsigned long lastRefreshTime =millis(); if(millis()-lastRefreshTime> =REFRESH_INTERVAL_UPD){lastRefreshTime + =REFRESH_INTERVAL_UPD; //現在の修正と以前の修正の間の距離をメートル単位で計算しますfloatdistanceDelta =prevFix.DistanceKm(fix.location)* 1000; //距離が10メートルより大きく10km未満の場合にのみ更新します// 10kmチェックが実装され、GPSからの誤ったデータ読み取りを回避しますif(distanceDelta> 10 &&distanceDelta <10000){totalDistance + =distanceDelta; } //次のループの計算ポイントをリセットします(「前の」場所を設定します)prevFix =fix.location; } // 2分ごとにSDカードまでの移動距離を書き込みます// 2分ごとにthinger.ioに座標をアップロードしますstaticconst unsigned long REFRESH_INTERVAL_WRITE_SD =120000UL; // 2分staticunsigned long lastRefreshTimeWriteSD =millis(); if(millis()-lastRefreshTimeWriteSD> =REFRESH_INTERVAL_WRITE_SD){lastRefreshTimeWriteSD + =REFRESH_INTERVAL_WRITE_SD; // SDカードへのファイル書き込みbeginchar buf [9]; dtostrf(totalDistance、8、0、buf); if(PF.open(filename))Serial.println(F( "error open file")); while(1){UINT nr; if(PF.writeFile(buf、sizeof(buf)、&nr))Serial.println(F( "エラー書き込みファイル")); if(nr ==sizeof(buf)){PF.writeFile(0、0、&nr); // nullポインタブレークを書き込んで、書き込み操作を終了します。 }} // Petit FSは、ファイルに対して「閉じる」操作を行いません。//次のセクションでは、HTTPPOSTリクエストを使用してデータをthinger.ioIoTクラウドに転送します。 //最初にGPSロックが成功した後にのみthinger.ioを更新しますcharhttpContent [60]; char tempstrLong [10]; char tempstrLat [10]; dtostrf(Lat、2、6、tempstrLat); dtostrf(Long、2、6、tempstrLong); //thinger.ioバケットへのデータフィールド。バケットへのアクセスは、post関数のURL認証を介して与えられます。 //形式は{"field1name":field1、 "field2 name":field2、 "field3 name":field3}で、正確なバイト数が含まれます。 sprintf(httpContent、 "{\" longitude \ ":%s、\" latitude \ ":%s、\" date \ ":\"%s%s \ "}"、tempstrLong、tempstrLat、datePrint、timePrint); char httpdataLen [20]; //コンテンツの正確なバイト数をHTTPDATAに追加する必要があります//そうでない場合、HTTP POSTリクエストは無効です。つまり、ステータス400が返されます。 sprintf(httpdataLen、 "AT + HTTPDATA =%i、10000"、strlen(httpContent)); postDataThinger(httpdataLen、httpContent); }}} //合計距離が設定された制限を超えた場合にSMS通知を送信するif(totalDistance> triggerDistance){char distanceTotalMsg [10]; itoa((totalDistance / 1000)、distanceTotalMsg、10); sprintf(sms_msg、 "空のキャッチタンク!現在の距離:%skm"、distanceTotalMsg); textMessage ="";番号=DEFAULT_NUMBER; totalDistance =0; sendSMS(sms_msg); } updateSerial();} void updateSerial(){//着信バッファを読み取ります。 (SIM900.available()> 0){textMessage =SIM900.readString();の場合、任意のテキストメッセージのコンテンツを読み取ります。 } if(textMessage.indexOf( "POS")> =0){extractSenderNumber(); textMessage =""; char latPrint [10]; dtostrf(Lat、5、6、latPrint); char LonPrint [10]; dtostrf(Long、5、6、LonPrint); if(num_sat> =3 &&valid_location){sprintf(sms_msg、 "現在の場所:緯度:%s、長い:%s。%s%s、+%s \ n"、latPrint、LonPrint、googlePrefix、latPrint、LonPrint); } else if(num_sat <3 &&valid_location){sprintf(sms_msg、 "gps修正なし。最後に表示された%s%sat:Lat:%s、Long:%s。%s%s、+%s \ n"、datePrint 、timePrint、latPrint、LonPrint、googlePrefix、latPrint、LonPrint); } else if(!valid_location){sprintf(sms_msg、 "トムが見つかりません。たぶん彼は北朝鮮にいますか?"); } sendSMS(sms_msg); } //現在の合計累積距離を返しますif(textMessage.indexOf( "GETKM")> =0){char sms_msg [32]; char distanceTotalMsg [10]; itoa((totalDistance / 1000)、distanceTotalMsg、10); sprintf(sms_msg、 "現在の距離:%skm"、distanceTotalMsg); textMessage =""; sendSMS(sms_msg); } //距離カウンターを0にリセットしますif(textMessage.indexOf( "RESETKM")> =0){totalDistance =0; char sms_msg [] ="確認:距離のリセット"; textMessage =""; sendSMS(sms_msg); }} void SIM900power(){//ピン#7からSIM900ボードの電源を入れます(デフォルト)-> 2秒。信号pinMode(PWRPin、OUTPUT); digitalWrite(PWRPin、LOW); delay(1000); digitalWrite(PWRPin、HIGH); delay(2000); digitalWrite(PWRPin、LOW); delay(15000); //モジュールに起動時間を与えます} void updateSIM900(){// read()delay(500);を使用してSIM900からの着信バッファを空にします。 while(SIM900.available()){//接続されている場合はシリアルモニターにバッファーを出力しますSerial.write(SIM900.read()); }} void extractSenderNumber(){uint8_t startPos =textMessage.indexOf( "+"、6); uint8_t endPos =textMessage.indexOf( "、"); number =textMessage.substring(startPos、endPos --1);} void sendSMS(char * content){//最初から適切な文字処理を行うのが面倒だったので//本当にくだらない文字列変換。 // SMSは送信者番号に返されます。 char numberChar [number.length()+ 1]; number.toCharArray(numberChar、number.length()+ 1); char cmd_sms [50]; sprintf(cmd_sms、 "AT + CMGS =%c%s%c"、0x22、numberChar、0x22); SIM900.println(cmd_sms); updateSIM900(); SIM900.print(content); updateSIM900(); SIM900.write(0x1A);} void connectGPRS(){SIM900.println(F( "AT + SAPBR =3,1、\" CONTYPE \ "、\" GPRS \ "")); delay(1000); updateSIM900(); SIM900.println(F( "AT + SAPBR =3,1、\" APN \ "、\" TeleXXX \ "")); delay(1000); updateSIM900(); SIM900.println(F( "AT + SAPBR =1,1")); delay(1000); updateSIM900(); SIM900.println(F( "AT + SAPBR =2,1")); delay(1000); updateSIM900();} void postDataThinger(char * httpDataLen、char * content){SIM900.println(F( "AT + HTTPINIT")); delay(1000); updateSIM900(); SIM900.println(F( "AT + HTTPSARA =\" CID \ "、1")); delay(1000); updateSIM900(); SIM900.println(F( "AT + HTTPPARA =\" URL \ "、\" http://backend.thinger.io/v3/users/tom/devices/CT/callback/data?authorization =eyJhbGciOiJIUzI1NiIsInR5cCI6lskjdflksjdfweruiowe19DVCIsInVzciI6In \ "")); delay(1000); updateSIM900(); SIM900.println(F( "AT + HTTPSARA =\" CONTENT \ "、\" application / json \ "")); delay(1000); updateSIM900(); SIM900.println(httpDataLen); delay(1000); updateSIM900(); SIM900.println(content); delay(1000); updateSIM900(); SIM900.println(F( "AT + HTTPACTION =1")); delay(10000); updateSIM900(); SIM900.println(F( "AT + HTTPTERM")); delay(1000); updateSIM900();} // SDカードを初期化し、保存されている距離値を取得しますvoid initializeSD(){//最初のセクションはSDカードから現在の距離を読み取りますchar buf [10]; //取得した距離値を保持するためのバッファ// SDカードとファイルシステムを初期化します。 if(PF.begin(&fs))Serial.println(F( "エラー開始ファイル")); //読み取り用にファイルを開きます-保存された累積合計距離if(PF.open(filename))Serial.println(F( "error open file")); while(1){UINT nr; if(PF.readFile(buf、sizeof(buf)、&nr))Serial.println(F( "エラー読み取りファイル")); if(nr ==sizeof(buf))break; } // PetitFSのクローズ関数はありません。 //保存された距離値をプログラムに取得しますtotalDistance =atof(buf); // 2番目のセクションは走行距離計の通知トリガー値を読み取りますcharbufTrigger [10]; //トリガー値を保持するためのバッファーif(PF.open(settings))Serial.println(F( "error open file")); while(1){UINT nr; if(PF.readFile(bufTrigger、sizeof(bufTrigger)、&nr))Serial.println(F( "エラー読み取りファイル")); if(nr ==sizeof(bufTrigger))break; } //走行距離計の通知値を取得triggerDistance =atof(bufTrigger);} //タイムゾーンで時間オブジェクトを修正offsetvoidupdateTime(){// GPSデータ文字列から時間を設定setTime(timeFix.hours、timeFix.minutes、timeFix.seconds、 timeFix.date、timeFix.month、timeFix.year); //現在のタイムゾーン時間をオフセット値で計算しますadjustTime(UTC_OFFSET * SECS_PER_HOUR); sprintf(datePrint、 "%02d /%02d /%04d"、day()、month()、year()); sprintf(timePrint、 "%02d:%02d:%02d"、hour()、minute()、second());} 

カスタムパーツとエンクロージャー

より多くのスペースのためのケーシングの上部(背が高い)。取り付け穴は閉じており、印刷後にドリルで穴を開ける必要があります(印刷を容易にするため)コンパクトバージョンの上部ケーシング(エンクロージャー内のスペースが少ない)ケーシングの下部-コネクタ用の切り欠きがあるSIM900およびArduinoボード用ロックSIM900ボードを所定の位置にロックSIM900ボードを所定の位置に配置します(SIM900ボードに取り付け穴はありません)。名前を「dist.txt」に変更し、SDカードに配置します dist_1qOG9VMO2D.txtの名前を「settings.txt」に変更し、SDカードに配置します settings_iMpR6v81OB.txt

回路図


製造プロセス

  1. アイロン台
  2. サーフボード
  3. 屋外(GPS)資産追跡テクノロジーはどうなっていますか?
  4. RaspberryPiは4ドルのボードと一緒に独自のMCUを設計します
  5. センサーデータとRaspberryPiマイクロプロセッサーの統合
  6. PSoC 6PioneerボードとPioneerIoTアドオンシールドの使用
  7. BIOVIAリビングマップで安全な医薬品を再利用する
  8. Java の HashMap 例で学ぶ
  9. 例を使用した Python map() 関数
  10. 社内統合システムの操作
  11. クーラントが少ない状態で車を運転するとどうなりますか?