目次

デバッグ・トラブルシューティング

CHIRIMEN Raspi を利用する上で基礎的なデバッグやトラブルシューティングを共有するページです。良くある質問については FAQ ページ に、利用上のテクニックや知っておくと良いことは TIPS ページ に書いているので、そちらも合わせてご覧ください。

CHIRIMEN Raspi でのプログラミングでも Web アプリケーションのプログラミングでも問題解決の手順は共通です。プログラムは意図したとおりではなく書いた通りに動くので、実際のコードや配線が意図通りか、一つずつ検証し、問題の原因となる範囲を絞っていくことが大事です。

まずは開発ツールの console を開きましょう。ショートカットキー (F12 または Ctrl+Shift+I) やメニュー (その他のツール -> デベロッパーツール) を開き Console タブを開きます。エラーメッセージなどがここに出力されます。また更新した内容が即座に反映するように Cache を Disable にしておきましょう(開発ツールの Settings/Preferences から指定できます)

プログラム中に console.log 関数 console.log(カンマ区切りで確認したい変数などを記載); を書けば、先の console 上に確認したい値が出力されます。これも基本的なデバッグのテクニックです。詳しくは下記開発ツール (DevTools) のリンクなどを参考にしてください。

エラーメッセージやデバイスの LED 表示、あるいは焦げた匂いなど問題のヒントがある時はまずそこから確認し、そのエラーメッセージが発生する原因を探ります。JavaScript では console.log で変数の状態を書き出しながら実行するだけでなく、開発ツール (DevTools) を使ってデバッグ することが解決の早道です。ブレークポイント でコードの実効を一時停止し、そのコードが意図通りのタイミング、回数、変数の状態で呼ばれているか確認するようにすると素早くデバッグできるようになります。

講師やチューターのいる場面ではデバッグの仕方も積極的に教えてもらってください。

デバッグチェックリスト

問題解決のためのチェックリスト (初心者向け) を書いてみたので参考にしてください:

トラブルシューティング

ディスプレイに何も表示されない

Raspi に AC アダプタと microUSB ケーブルを接続して (ケーブルにスイッチがあればオンにして) も HDMI ディスプレイに何も表示されない場合にはいくつかの原因が考えられます。

ssh や VNC で接続できない

pi ユーザのパスワードが分からない

本ページ執筆時点で CHIRIMEN の配付イメージは Raspbian をベースにしておりデフォルトユーザ pi のパスワードは Raspbian デフォルト同様に raspberry となっています (2018 年以前のイメージでは rasp に変更されていました)。

同時に複数のタブで開くと動作しない

コンソールに Uncaught (in promise) GPIOPort(XX).export() error などと表示される

複数のプログラムで同じ GPIO ポートや I2C ポートを同時に制御することは出来ない ため、複数のタブを同時に開くとポートの export に失敗します。API では特に規定されていませんが実装上は排他制御がされており、同一のページを複数タブで開いたり、I2C Detect ページと I2C を利用するページを同時に開くなど、同じポートを同時に扱うコードを書くと正しく動作しなくなることがあります。全てのタブを閉じてから目的のページだけを開き直してください。

JS Bin のコンソールに何もエラーが表示されないのに意図した動作をしない

残念ながら JS Bin のコンソールではすべての JavaScript エラーや警告メッセージが表示されるわけではありません。デバッグ時にはブラウザの開発ツールを (F12 または Ctrl+Shift+I で) 開き Console に表示されるメッセージを確認してください。

JS Bin で asyncawait に赤い下線の警告が表示される

JS Bin は軽量で便利なオンラインエディタですが、実装が古く JavaScript ペインでの自動構文チェック機能が async や await といった比較的新しい構文 (2017 年に仕様が固まり各ブラウザで正式サポートとなりました) を適切に認識できていません。これらの下に赤線が引かれている場合は無視して問題ありません。最新の言語機能・ブラウザの実装を考慮した構文チェック機能を使いたい場合は CodeSandbox を使うか、ローカルのエディタに構文チェックプラグインをインストールしてください。

コンソールに Uncaught ReferenceError: xxx is not defined などと表示される

変数 xxx にアクセスしようとしているがそれが定義されていないというエラーです。単純に変数名などを Typo (入力し間違え) していることが多いです。次に多いのは定義域の外でアクセスしようとしている場合です。JavaScript の変数スコープは var で宣言した場合は関数単位、let や const で宣言した場合にはブロック単位です。別の関数の中からなど、スコープ外からアクセスしようとしていないか確認してください。

コンソールに Uncaught TypeError: Cannot read property 'xxx' of nullUncaught TypeError: Cannot read property 'xxx' of undefined などと表示される

オブジェクトのプロパティ xxx にアクセスしようとしている (some.xxx のようなコード)、プロパティ xxx を持つと考えている変数 some がオブジェクトではなく null や undefined となっており、プロパティアクセスができないというエラーです。変数 some の取得・代入をしているコードに問題がないか確認してください。

コンソールに Uncaught (in promise) TypeError: navigator.requestGPIOAccess is not a function などと表示される

関数 (メソッド) 呼び出ししようとしているがその関数が定義されていないというエラーです。この場合 navigator.requestGPIOAccess が関数ではないと言うことですが、polyfill スクリプトを読み込んでいないか、読み込みより前にアクセスしようとしている場合に発生します。

コンソールに Uncaught SyntaxError: await is only valid in async function などと表示される

await 文は async (非同期) 関数の中でのみ利用可能です。関数の中で await を使って非同期処理を行いたい場合、その関数を async 関数として宣言する必要があります。特に addEventListener などで引数としてコールバック関数を渡している場合などには async を付け忘れてしまうことが多いので注意してください。

// 関数宣言:
async function wait100ms() { await sleep(100); }
// 匿名関数を使う場合:
element.addEventListener("click", async function() { await sleep(100); }, false);
// アロー(矢印)関数を使う場合
element.addEventListener("click", async () => { await sleep(100); }, false);

JS Bin のコンソールに error: ws error: [object Event] と表示される

コンソールに WebSocket connection to 'wss://localhost:33330/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED などと表示される

CHIRIMEN Raspi では JavaScript から GPIO などを操作できるように、JavaScript からの呼び出しに応じてハードを制御するローカル WebSocket サーバが Raspi 上の Node サーバとして起動しています。何らかの理由でそのサーバに問題が生じている場合はデスクトップにある reset.sh を実行して再起動させると正常動作するようになります。

コンソールに connection to 'wss://localhost:33330' failed: Error in connection establishment: net::ERR_INSECURE_RESPONSE などと表示される

CHIRIMEN Raspi のバックエンドサーバとの接続が許可されていません。ブラウザから一度 https://localhost:33330 にアクセスして 詳細設定 から localhostにアクセスする(安全ではありません) をクリックし、ローカル WebSocket サーバ (サーバ証明書無し) へのアクセスを許可してください。

詳しくは CHIRIMEN for Raspberry Pi 3 におけるセキュリティーエラーへの対処方法 を参考にしてください。

JavaScript から特定の URL にアクセスできない

コンソールに Failed to load https://...: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://...' is therefore not allowed access. などと表示される

コンソールに Access to fetch at 'https://...' from origin 'https://...' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. などと表示される

CHIRIMEN に限らず一般的な Web 開発でよく見かけるエラーです。Web には 同一オリジンポリシー (Same Origin Policy) というセキュリティ制約があり、JavaScript を読み込んでいるのと異なるドメインの URL には相手側のサーバが オリジン管理ソース共有 (CORS) で明示的に許可している場合以外は JavaScript のコード中で XMLHttpRequest や fetch からアクセスできません。

単純化して言えば、サーバからの HTTP レスポンスヘッダに access-control-allow-origin: * が付与されていれば JavaScript からのアクセスが許可されるため、任意の URL へのアクセスをプロキシ (中継) してレスポンスヘッダを勝手に追加してくれるようなサーバを用意すれば任意のドメインから任意の URL にアクセスが可能になります。

そのような機能を持った公開の CORS プロキシサービスには例えば https://cors-anywhere.herokuapp.com/https://cors.io/ などいろいろなものがあります。なお、これらのサービスの利用は本来のセキュリティ機能を無視するものであり、利用に際しては注意が必要です。あくまでもプライバシー情報などを含まないものについて、テストやプロトタイピング時だけに限って利用すべきです。

JS Bin や JS Fiddle で Web Bluetoooth, Web MIDI, WebRTC などが利用できない

Chrome 64 で Feature Policy というセキュリティ機構が導入され、iframe ページ内ではフレーム読み込み元のページの HTTP ヘッダで明示的な許可がされない限り、高度な機能が利用不可能になりました。JS Bin などのサービスでは読み込み結果を iframe 内に読み込んでいることが多いが、Feature Policy で許可をするヘッダの送信には未対応であるため、一部の Web API が利用できないことがあります。

これに該当する場合は開発ツールのコンソールに Feature Policy に関するエラーメッセージが表示されます。その場合にはコードをすべてローカルの HTML などで書いてそれをブラウザに読み込ませるようにしてください。

コードも配線も正しいのにとにかく動作しない!

いろいろな原因が考えらるため、ひとつずつ確認していく必要があります。例えばこのように考えます:

ハンズオン・ハッカソン・講義など、講師やチューターなどのいる時は、色々試して分からないときは一人で悩まず遠慮なく質問しましょう。 動かない時や解決できないときに教わるのは、デバッグ力のある人のテクニックや思考を教えてもらうチャンスです。質問するほどプログラミングとデバッグのスキルは向上するので、どんどん質問していってください。