インテリジェント駐車システム:都市部駐車問題の効率的解決策
必要な部品と材料
| 部品 | 数量 |
|---|---|
| Raspberry Pi 3 Model B | 1 |
| Arduino Mega 2560 | 1 |
| 超音波距離センサー HC-SR04 | 3 |
使用アプリ・オンラインサービス
- Samsung ARTIK Cloud for IoT
- Google Maps API
- Arduino IDE
プロジェクト概要
バンガロールのような混雑した都市で空き駐車スペースを見つけるのは非常に困難です。車で外出する際、まず頭をよぎるのが「どこに駐車するか」という問題。駐車場に行ってみたら満車で、別の駐車場を探さなければならないことがよくあります。これは大きな手間であり、多くの人が車での外出を躊躇する原因になっています。
この問題を解決するため、クラウドベースのスマート駐車システムを開発しました。このシステムを導入すれば、都市の駐車問題を解消できると確信しています。ARTIK Cloudは、このような用途に最適なIoTクラウドプラットフォームです。
ユーザーはモバイルやWebアプリから、どこからでも簡単に空き駐車スペースを見つけられます。システムは30秒ごとに駐車データを更新します。
プロジェクトの手順
- ARTIK Cloudでデバイス作成
- ARTIK Cloudでアプリケーション作成
- ARTIK Cloudでルール作成
- Arduinoの準備
- センサーの接続
- Raspberry Piの準備
- Webアプリケーション開発
ステップ1:ARTIK Cloudでデバイス作成
Samsungアカウントでログインし、右上の「DEVELOPER」をクリック。ダッシュボードから「DEVICE TYPES」→「NEW」でデバイス作成。表示名とユニーク名を入力し、「CREATE DEVICE TYPE」。
「+ NEW MANIFEST」でフィールド名(センサーデータ用)とデータ型(integer)を設定。「NEXT: DEVICE ACTIONS」→ アクション設定(今回は不要)→「NEXT: ACTIVE MANIFEST」。デバイスフィールド確認後、再度「NEXT: ACTIVE MANIFEST」でデバイス作成完了。
「MY ARTIK CLOUD」→「DEVICES」→「+Add another device」で作成したデバイスを選択し、「CONNECT DEVICE」でクラウド接続。デバイスIDとデバイストークンをメモ(後で必要)。
ステップ2:ARTIK Cloudでルール作成
条件に合致したときにアクションを生成するルールを作成。「RULES」→「NEW RULE」で、IF条件(デバイスのデータフィールドと値)とTHENアクション(特定デバイスへのアクション)を設定。別デバイスのデータを参照することも可能。
ステップ3:Arduinoの準備
Arduinoの役割は、駐車場に接続されたセンサーからデータを収集し、シリアルポート経由でRaspberry Piに送信すること。Arduino Megaを1駐車場分使用し、複数の駐車場には複数のArduinoを接続可能。超音波センサーを使用。Arduinoスケッチはコードセクション参照。
ステップ4:センサー接続
センサーとArduinoの接続は回路図セクションを参照。

ステップ5:Raspberry Piの準備
Raspberry PiはWebSocketクライアントとしてARTIK Cloudと通信。Node.jsでプログラミング(Pythonと異なりNodeはプリインストールされていない)。
インストール手順
sudo apt-get update
sudo apt-get install nodejs npm
npm install --save ws
npm install serialport
完了後、GitHubからソースコードをダウンロードし、FileZilla等でRaspberry Piにアップロード。DEVICE IDとDEVICE TOKENを自分のものに変更するのを忘れずに。
実行コマンド:
sudo node staff-parking.js
ステップ6:Webアプリケーション開発
HTMLとJavaScriptで開発。ARTIK Cloudとの通信にWebSocket、地図表示にGoogle Maps APIを使用。GitHubからweb-appフォルダをダウンロードし、DEVICE IDとTOKENを自分のものに変更。websocket.htmlをブラウザで開いて動作確認。
コード
Raspberry Pi (staff-parking.js)
// staff parking data transfer
var webSocketUrl = "wss://api.artik.cloud/v1.1/websocket?ack=true";
var device_id = "Your Device ID";
var device_token = "Your Device Token";
var WebSocket = require('ws');
var isWebSocketReady = false;
var ws = null;
var serialport = require("serialport");
var SerialPort = serialport.SerialPort;
var sp = new SerialPort("/dev/ttyACM0", {
baudrate: 9600,
parser: serialport.parsers.readline("\n")
});
var parking_state = 0;
function getTimeMillis() {
return parseInt(Date.now().toString());
}
function start() {
isWebSocketReady = false;
ws = new WebSocket(webSocketUrl);
ws.on('open', function() {
console.log("WebSocket connection is open ....");
register();
});
ws.on('message', function(data) {
handleRcvMsg(data);
});
ws.on('close', function() {
console.log("WebSocket connection is closed ....");
});
}
function register() {
console.log("Registering device on the WebSocket connection");
try {
var registerMessage = '{"type":"register", "sdid":"' + device_id + '", "Authorization":"bearer ' + device_token + '", "cid":"' + getTimeMillis() + '"}';
console.log('Sending register message ' + registerMessage + '\n');
ws.send(registerMessage, {mask: true});
isWebSocketReady = true;
} catch (e) {
console.error('Failed to register messages. Error: ' + e.toString());
}
}
function handleRcvMsg(msg) {
var msgObj = JSON.parse(msg);
if (msgObj.type != "action") return;
var actions = msgObj.data.actions;
var actionName = actions[0].name;
console.log("The received action is " + actionName);
// アクション処理
}
function sendStateToArtikCloud(parking_slot) {
try {
ts = ', "ts": ' + getTimeMillis();
var data = { "parking_slot": parking_slot };
var payload = '{"sdid":"' + device_id + '"' + ts + ', "data": ' + JSON.stringify(data) + ', "cid":"' + getTimeMillis() + '"}';
console.log('Sending payload ' + payload + '\n');
ws.send(payload, {mask: true});
} catch (e) {
console.error('Error in sending a message: ' + e.toString() + '\n');
}
}
function exitClosePins() {
console.log('Exit and destroy all pins!');
process.exit();
}
start();
sp.on("open", function() {
sp.on('data', function(data) {
console.log("Serial port received data: " + data);
var parking_slot = parseInt(data);
sendStateToArtikCloud(parking_slot);
});
});
process.on('SIGINT', exitClosePins);
Arduino (sonar.ino)
#define echoPin1 2
#define trigPin1 3
#define echoPin2 4
#define trigPin2 5
#define echoPin3 6
#define trigPin3 7
long duration1, distance1;
long duration2, distance2;
long duration3, distance3;
int count = 0;
int freeSlot = 0;
void setup() {
Serial.begin(9600);
pinMode(trigPin1, OUTPUT); pinMode(echoPin1, INPUT);
pinMode(trigPin2, OUTPUT); pinMode(echoPin2, INPUT);
pinMode(trigPin3, OUTPUT); pinMode(echoPin3, INPUT);
}
void loop() {
// センサー1
digitalWrite(trigPin1, LOW);
delayMicroseconds(2);
digitalWrite(trigPin1, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin1, LOW);
duration1 = pulseIn(echoPin1, HIGH);
// センサー2
digitalWrite(trigPin2, LOW);
delayMicroseconds(2);
digitalWrite(trigPin2, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin2, LOW);
duration2 = pulseIn(echoPin2, HIGH);
// センサー3
digitalWrite(trigPin3, LOW);
delayMicroseconds(2);
digitalWrite(trigPin3, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin3, LOW);
duration3 = pulseIn(echoPin3, HIGH);
// 距離計算 (cm)
distance1 = duration1 / 58.2;
distance1 = (distance1 < 10) ? 1 : 0;
distance2 = duration2 / 58.2;
distance2 = (distance2 < 10) ? 1 : 0;
distance3 = duration3 / 58.2;
distance3 = (distance3 < 10) ? 1 : 0;
count = distance1 + distance2 + distance3; // 駐車車両数
freeSlot = 3 - count; // 空きスロット数
Serial.println(freeSlot); // Raspberry Piへ送信
delay(5000); // 5秒ごとに更新(元コードは30秒)
}
Webアプリ (HTML)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ARTIK Cloud based Smart Parking System</title>
<script src="websocket_client.js"></script>
<style> /* CSSスタイル */ </style>
</head>
<body onload="javascript:init()">
<h2>ARTIK Cloud based Smart Parking System</h2>
<div class="container">
<div class="left">
<h1>Staff Parking</h1>
<h4>Near Main Campus</h4>
<rainbowParking id="rainbow">Receiving Data...</rainbowParking>
<h1>Student/Guest Parking</h1>
<h4>Front Gate, Near Union bank</h4>
<indigoParking id="indigo">Receiving Data...</indigoParking>
</div>
<div class="right">
<div id="map" style="width:100%;height:100%"></div>
</div>
</div>
<script>
// Google Maps初期化とマーカー表示
function myMap() { /* マップ設定 */ }
</script>
<script src="https://maps.googleapis.com/maps/api/js?callback=myMap"></script>
</body>
</html>
Webアプリ クライアント側 (JavaScript)
var wsUri = "wss://api.artik.cloud/v1.1/websocket?ack=true";
var device_id = "Your Device ID";
var device_token = "Your Device Token";
var websocket;
function init() {
// WebSocket接続、登録、メッセージ受信処理
// 受信データで駐車場の空き数を表示更新
}
全ソースコードはGitHubリポジトリにあります:https://github.com/husinul/Smart-Car-Parking
回路図



製造プロセス
- スマートバーテンダー:Raspberry Pi駆動の自作カクテルステーション
- コンベアシステム完全ガイド:仕組み、種類、導入メリット
- 車用ジャッキ完全ガイド:種類、用途、安全な使い方
- 車両サスペンションシステム徹底解剖:愛車を守り乗り心地を高めるメカニズム
- 車のヒーターが走行中しか効かない原因と対処法
- スマートコンプレッサーシステムが施設効率を高める理由
- スマート照明制御で温室電気代を最大33%削減
- SensiCut:材料を正確に識別する高度レーザーカッタープラットフォーム
- ビル管理システム(BMS):IoTでスマートシティを支える
- C# コンストラクター:種類、例、高度なパターン
- C# usingステートメント完全ガイド:名前空間インポート、エイリアス、静的ディレクティブ