IoT ALGYAN6周年基板の動作確認
1. はじめに
先日IoT ALGYAN主催の 【オンライン】ALGYAN6周年IoT祭2021『IoTは技術の総合格闘技!』講演&ノベルティ抽選会 に参加した時、 ALGYAN6周年記念基板という基板を200 枚ほど無償で提供していましたので、入手された方も多いかと思います。
2021年7月3日に開かれる、【オンライン】基板プレゼント有・ALGYAN6th IoT基板『はんだづけ勝手にもくもく会』イベントでは、参加者が各自もくもくはんだ付けを行いつつ部品の実装をするとイベントも開かれる予定だそうです。
待ちきれずにフライングして組み立ててしまっている人もいるようですが、私も同様に待ちきれずつい…
作ってみたら動かしたくなりますよね。
というわけで、ハードチェック用のソフトを勝手に作ってみましたのでその紹介です。
サムネイルの写真は、テスト中の基板です。(正規の部品使わないで、家にある部品を強引に実装して作ったので少し不格好ですが。)
イベント用に公式にはハードウェアチェックソフトウェアも準備中とのことですが、ここにあるのはそれとは別の非公式の物ですので、イベントで本ソフトについての質問等は控えて頂きます様お願いします。
2. ハードウェア
回路図や部品表等の資料はこちらの公式ページ で提供されている(組み立て方は後日掲載される予定のようです)ので、割愛します。
組み立て方含めてどうすればいいかよくわからないと思った人は、【オンライン】基板プレゼント有・ALGYAN6th IoT基板『はんだづけ勝手にもくもく会』イベントに参加してみるとフォローしてもらえるかもしれません。
既に基板の配布は終わっていますが、イベントサイトに掲載の回路図を元にして回路を構成すれば、同様のことはできます。またイベントで言っていましたが、基板発注用のガーバーデータも提供される予定とのことです。
2.1 重要事項
はんだ付け後に必ず、マルチメーター(テスター)で、ピー音が鳴るレンジに合わせて導通のチェックを行いましょう。
特に、5V 電源ライン , 3.3V 電源ライン, グランド(GND)ラインがお互いにショートしていないかを必ずチェックしておきましょう。
(電子工作に慣れている方はご存知、常識のこととは思いますが、はんだ付け後の必ずやらないといけない儀式です)
これをやらずに、ボードと PCを繋ぐと過電流で部品が燃えたり、基板上のパターンが焼き切れたり、最悪つないだ PCが破損したりする場合もありますので確実におこないます。
3. ソフトウェア
3.1. ハードウェアチェックソフトとは
ハードウェアチェックソフトというのは、部品がちゃんと実装できるかをチェックするためのソフトウェアです。
実際の生産現場でも、自動実装や熟練した人が実装したものといえども、品質確保するためには、正しく実装されたかを検査するためのソフトが必須です。
ましてや、はんだ付けに慣れていない方や初めての方、チップ部品を付けるのは初めてという方等もいる中、部品の向きを間違えていたり、はんだ付けが不完全だったりする可能性は十分ありえます。
ソフトを開発している段階で問題が出たとき、ハード問題なのかソフト問題なのかを切り分けには、非常に時間が掛かるものです。
部品がきちんと実装されたかをチェックすることは重要なのです。
また、開発中にハードを壊したかなと疑わしい時に、確実に動作していたソフトを入れてみて確認するという使い方もよくありますが、そういう目的でも使用可能です。
実は昨年の5周年基板のはんだ付けもくもく会では、ハードウェアチェックソフトを提供させていただいたのですが、複数の部品を組み合わせて動作するようなものであったので、動かない時にどこにが悪いかわかりにくいという意見もありました。
その反省をふまえ、出来るだけすべての部品を一つ一つ個別にチェックできるような構成を心がけました。
因みに、あくまでハードチェック用ソフトであり基本的な事しかやっていませんので、このソフトをベースに拡張とかあまりできない気はします。
3.2. 開発環境
大切なPCを壊さないためにも、ここから先は「2.1 重要事項」に書いた通り、しっかり導通チェックが済んでいる事を確認してから行うようにしましょう。
以下の物を準備します。
- Arduino IDE インストール(最新でいいと思います)
- ESP32の開発環境 (M5シリーズでも可)が適用済みであること
(ArduinoやESP32用のライブラリインストール方法等は長くなり、本記事の範疇ではありませんので割愛します。ネットで記事がたくさんあります。)
ボード接続後
- [ツール] - [ボード] "ESP32 Dev Module" を選択
- [ツール] - [シリアルポート] で接続したポートを選択する
3.3. ソース
Arduino の [ファイル] - [新規作成] で "ALGYAN6th_HWTest" という名前を付けて、以下のソースをコピペします。
Arduino用ソース
ALGYAN6th_HWTest.ino
// -----=====<<<<<[[[[[ Include ]]]]]>>>>>=====-----
#include <Wire.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <DNSServer.h>
// -----=====<<<<<[[[[[ Define ]]]]]>>>>>=====-----
// ボード選択(以下のうちのいずれかを有効(コメント解除)する)
#define CONFIG_HW_ALGYAN_6TH_BOARD
//#define CONFIG_HW_ALGYAN_5TH_BOARD
// デバッグ有効化(デバッグ情報を出したいときに有効化する)
//#define ENABLE_DEBUG
// ボード選択判定および条件定義
#if defined(CONFIG_HW_ALGYAN_6TH_BOARD) && defined(CONFIG_HW_ALGYAN_5TH_BOARD)
#error "Can't set both 6th and 5th board"
#elif defined(CONFIG_HW_ALGYAN_6TH_BOARD)
#define THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
#elif defined(CONFIG_HW_ALGYAN_5TH_BOARD)
#define THIS_BLOCK_IS_ONLY_FOR_ALGYAN_5TH_BOARD
#else
#error "NO board selected"
#endif
#ifdef ENABLE_DEBUG
#define DebugLog(format, ...) do \
{\
char tmp_str[81];\
snprintf(tmp_str, sizeof(tmp_str)-1, format, ##__VA_ARGS__);\
Serial.println(tmp_str);\
} while(0) // ログ出力マクロ
#define GraphPrint(format, ...) // グラフプロットマクロは無効
#else
#define DebugLog(format, ...) // ログ出力マクロは無効
#define GraphPrint Serial.print // グラフプロットマクロ
#endif
// 配列の要素数
#define ARRAY_SIZEOF(x) (sizeof(x)/sizeof(x[0]))
// アクセスポイント関連
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_5TH_BOARD)
#define BOARD_NAME "ALGYAN_5th" // SSIDの先頭
#elif defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
#define BOARD_NAME "ALGYAN_6th" // SSIDの先頭
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
#define BOARD_NUM "1" // 近くで同じSSIDを使うと重複してわからなくなるので区別の為番号を末尾に着けている。
#define MY_PASSWORD "12345678" // パスワード(WiFi電波の届く範囲の人に勝手にログインして操作されたくなければ変える。)
// 端子定義
#define PIN_I2C_SDA 21
#define PIN_I2C_SCL 22
#define PIN_LED1_R 12
#define PIN_LED2_G 15
#define PIN_LED3_B 23
#define PIN_MOTOR_AL_1 4
#define PIN_MOTOR_AL_2 26
#define PIN_MOTOR_BR_1 27
#define PIN_MOTOR_BR_2 25
#define PIN_USR_SW 35
#define PIN_CDS 34
#define PIN_SERVO 13
#define PIN_BUZZAR 14
// PWMコントローラ(ledc)関連設定
#define PWM_FREQ 50
#define PWM_BITS 10 // PWMビット数
#define PWM_MAX ((1<<PWM_BITS)-1) // PWMの最大値
// PWMコントローラ(ledc)のチャンネル定義
#define PWM_LED1_R 0
#define PWM_LED2_G 1
#define PWM_LED3_B 2
#define PWM_SERVO 3
#define PWM_MOTOR_AL_1 4
#define PWM_MOTOR_AL_2 5
#define PWM_MOTOR_BR_1 6
#define PWM_MOTOR_BR_2 7
// サーボモータパルス幅設定 (50Hz時 PWM_MAX:1023 の時の SG-90互換品マイクロサーボ
#define SERVO_PWM_MIN 26 // 0.5msec
#define SERVO_PWM_MAX 123 // 2.4msec
// DCモータのスピードマックス値
#define MOTOR_SPEED_MAX 100 // ±100
#define CDS_AVERAGE_BUF_SIZE 32
#define SW_ANTI_CHATTERING_CNT 5
// -----=====<<<<<[[[[[ Types ]]]]]>>>>>=====-----
// setLed() 巻子で使う LEDのチャンネル定義
enum {
LED_R1 = 0,
LED_G2,
LED_B3
};
// setDCMotor() で使うモーター指定チャンネル定義
enum {
DCMOTOR_AL = 0,
DCMOTOR_BR
};
// -----=====<<<<<[[[[[ Valiable ]]]]]>>>>>=====-----
// システムクロック(1msec でカウントアップ) (現状未使用)
uint32_t sys_timer_tick = 0;
// LED設定パラメータ
int led_r1_pos = 0;
int led_g2_pos = 0;
int led_b3_pos = 0;
int led_all_pos = 0;
// サーボモータ設定パラメータ
int servo_pos = 0;
// DCモータ設定パラメータ
int motor_AL_speed = 0;
int motor_BR_speed = 0;
int motor_BOTH_speed = 0;
// ブザー状態パラメータ
int buzzer_state = 0;
// 取得パラメータ
int cds_value = 0;
int sw_value;
int cds_average_pos = 0;
int cds_average_buf[CDS_AVERAGE_BUF_SIZE] = {0};
// システムクロックカウントアップ用の1msec割り込み用タイマー
hw_timer_t* hw_timer = NULL;
//無線LANのアクセスポイント設定
const char ap_ssid[] = BOARD_NAME "-AP_" BOARD_NUM; // APのSSID
const char ap_password[] = MY_PASSWORD; // APのパスワード 8文字以上
const IPAddress ap_ip_addr(192, 168, 12, 34);
const IPAddress ap_subnet(255, 255, 255, 0);
const byte ap_dns_port = 53;
// ネット(WiFi)関連オブジェクト
DNSServer dnd_server; // アクセスポイント用IPアドレス割り当て(CaptivePotal)要
WiFiServer wifi_server(80); // Webサーバ用
int scaned_wifi_count = 0; // スキャンで見つかったWiFiアクセスポイントの数
String wifi_ssid_list[50]; // 見つかった アクセスポイントの SSID と電界強度(電波強度) の情報を格納(最大50件)
uint16_t i2c_scan_result[7]; // I2Cスキャンの結果格納用
// -----=====<<<<<[[[[[ Prototype ]]]]]>>>>>=====-----
void setup();
void loop();
void pSensorThread(void *arg);
void timerTick();
static void setupPeripheralHardware();
static void sendMainPage(WiFiClient& client);
static void recvFromBrowser(String& str_buffer);
static void setLed(int led, int bright);
static void setServoMotor(int deg);
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
static void setDCMotor(int leftright, int speed);
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
static void setBuzzer(int onoff);
// -----=====<<<<<[[[[[ Tables ]]]]]>>>>>=====-----
// None
// -----=====<<<<<[[[[[ Functions ]]]]]>>>>>=====-----
// [[[[[ 起動時初期化関数(Arduino標準) ]]]]]
void setup()
{
int i;
// put your setup code here, to run once:
// Setup Serial
Serial.begin(115200);
delay(1000);
DebugLog("Starting...");
// Hardware Initilize
setupPeripheralHardware();
// 起動音
setBuzzer(1);
delay(100);
setBuzzer(0);
delay(100);
setBuzzer(1);
delay(100);
setBuzzer(0);
// 無線LAN接続APモード
WiFi.mode(WIFI_AP_STA);
DebugLog("Scanning WiFi AP");
scaned_wifi_count = WiFi.scanNetworks();
for (i = 0; i<ARRAY_SIZEOF(wifi_ssid_list); i++) {
if (i<scaned_wifi_count) {
wifi_ssid_list[i] = WiFi.SSID(i) + " : " + String(WiFi.RSSI(i)) + "[dBm]";
DebugLog("Found ssid :%s, %d[dBm]", wifi_ssid_list[i].c_str() );
}
else wifi_ssid_list[i] = "";
}
DebugLog("Done!!");
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
// i2cバススキャン
DebugLog("Scanning i2c Devices");
pinMode( PIN_I2C_SDA, INPUT_PULLUP); // ソフトでプルアップしておく
pinMode( PIN_I2C_SCL, INPUT_PULLUP); // ソフトでプルアップしておく
Wire.begin(PIN_I2C_SDA, PIN_I2C_SCL);
memset(i2c_scan_result, 0x00u, sizeof(i2c_scan_result));
for(i = 1; i<128; i++)
{
Wire.beginTransmission(i);
if (Wire.endTransmission() == 0) {
i2c_scan_result[i/16] |= (uint16_t) ( 1 << (i%16));
DebugLog("Found I2C SlaveAddress:%02xh", i);
}
}
DebugLog("Done!!!");
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
// APスキャン
DebugLog("Start DNS Server");
WiFi.softAPConfig(ap_ip_addr, ap_ip_addr, ap_subnet);
WiFi.softAP(ap_ssid, ap_password);
dnd_server.start(ap_dns_port, "*", ap_ip_addr);
DebugLog("Done!!!!");
DebugLog("begin WiFiServer");
wifi_server.begin();
DebugLog("Done!!!!!");
// タイマー開始
DebugLog("Starting Timer");
hw_timer = timerBegin(0, 80, true);
timerAttachInterrupt(hw_timer, &timerTick, true);
timerAlarmWrite(hw_timer, 1000, true); //1 msec
timerAlarmEnable(hw_timer);
DebugLog("Done!!!!!");
// 入力デバイス用タスクを起動
DebugLog("Starting Sensor Task");
xTaskCreate(pSensorThread, "SensorTask", 8192, NULL, 0, NULL);
DebugLog("Done!!!!!!");
// 出力デバイスの起動時設定
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
led_b3_pos = 127; // 準備完了インジケーター(青点灯)
setLed(LED_G2, led_g2_pos);
setLed(LED_B3, led_b3_pos);
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
setLed(LED_R1, led_r1_pos);
setServoMotor(servo_pos);
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
setDCMotor(DCMOTOR_AL, motor_AL_speed);
setDCMotor(DCMOTOR_BR, motor_BR_speed);
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
setBuzzer(buzzer_state);
//cds_value = 0;
DebugLog("Done!!!!!!");
}
// [[[[[ メインループ(Arduino標準) ]]]]]
void loop()
{
dnd_server.processNextRequest();
WiFiClient client = wifi_server.available(); // listen for incoming clients
if (client) {
String str_buffer = "";
while (client.connected()) {
if (client.available()) {
char c = client.read();
if (c == '\n') {
if (str_buffer.length() == 0) {
sendMainPage(client);
break;
} else {
recvFromBrowser(str_buffer);
str_buffer = "";
}
} else if (c != '\r') {
str_buffer += c;
}
}
}
client.stop();
}
}
// [[[[[ 入力デバイスのメイン処理 ]]]]]
void readInputDevices()
{
static int buz_onoff_before = false;
static int sw_raw_before = -1;
static int sw_same_count = SW_ANTI_CHATTERING_CNT;
int i;
int cds_raw_value;
long int cds_sum;
int sw_raw;
// CDSの取得処理
cds_raw_value = analogRead(PIN_CDS); // 生値を ADCから取得して
// CDSの平均化処理
cds_average_buf[cds_average_pos] = cds_raw_value;
if (cds_average_pos < CDS_AVERAGE_BUF_SIZE-1) cds_average_pos++; else cds_average_pos = 0;
for (i = 0, cds_sum = 0; i<CDS_AVERAGE_BUF_SIZE; i++) cds_sum += cds_average_buf[i];
cds_value = cds_sum / CDS_AVERAGE_BUF_SIZE;
// CDSの平均値をグラフに出力
GraphPrint(cds_value);
// スイッチの取得処理
sw_raw = digitalRead(PIN_USR_SW);
// チャタリング除去処理
if (sw_raw == sw_raw_before) {
if ( sw_same_count == 0) sw_value = sw_raw;
else sw_same_count--;
}
else sw_same_count = SW_ANTI_CHATTERING_CNT;
sw_raw_before = sw_raw;
// スイッチが押されていたらブザーを鳴らす処理
if (sw_value || buzzer_state )
{
if (buz_onoff_before == false) setBuzzer(true);
buz_onoff_before = true;
} else {
if (buz_onoff_before == true) setBuzzer(false);
buz_onoff_before = false;
}
// グラフデータを改行
GraphPrint("\r\n");
}
// [[[[[ センサー用のタスク関数 ]]]]]
void pSensorThread(void *arg)
{
while (1) {
readInputDevices();
delay(10);
}
}
// [[[[[ タイマ満了関数 ]]]]]
void timerTick()
{
sys_timer_tick++;
}
/*----------------------------------------------------------------------------*/
// [[[[[ 周辺ハードウェアの初期化関数 ]]]]]
static void setupPeripheralHardware()
{
DebugLog("Initializing PeripheralHardware");
// Setup Pins
pinMode(PIN_USR_SW, INPUT);
pinMode(PIN_CDS, INPUT);
pinMode(PIN_BUZZAR, OUTPUT);
digitalWrite(PIN_BUZZAR, LOW);
// Setup PWM
ledcSetup(PWM_SERVO, PWM_FREQ, PWM_BITS);
ledcSetup(PWM_LED1_R, PWM_FREQ, PWM_BITS);
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
ledcSetup(PWM_LED2_G, PWM_FREQ, PWM_BITS);
ledcSetup(PWM_LED3_B, PWM_FREQ, PWM_BITS);
ledcSetup(PWM_MOTOR_AL_1, PWM_FREQ, PWM_BITS);
ledcSetup(PWM_MOTOR_AL_2, PWM_FREQ, PWM_BITS);
ledcSetup(PWM_MOTOR_BR_1, PWM_FREQ, PWM_BITS);
ledcSetup(PWM_MOTOR_BR_2, PWM_FREQ, PWM_BITS);
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
ledcAttachPin(PIN_SERVO, PWM_SERVO);
ledcAttachPin(PIN_LED1_R, PWM_LED1_R);
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
ledcAttachPin(PIN_LED2_G, PWM_LED2_G);
ledcAttachPin(PIN_LED3_B, PWM_LED3_B);
ledcAttachPin(PIN_MOTOR_AL_1, PWM_MOTOR_AL_1);
ledcAttachPin(PIN_MOTOR_AL_2, PWM_MOTOR_AL_2);
ledcAttachPin(PIN_MOTOR_BR_1, PWM_MOTOR_BR_1);
ledcAttachPin(PIN_MOTOR_BR_2, PWM_MOTOR_BR_2);
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
ledcWrite(PWM_SERVO, 0);
ledcWrite(PWM_LED1_R, 0);
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
ledcWrite(PWM_LED2_G, 0);
ledcWrite(PWM_LED3_B, 0);
ledcWrite(PWM_MOTOR_AL_1, 0);
ledcWrite(PWM_MOTOR_AL_2, 0);
ledcWrite(PWM_MOTOR_BR_1, 0);
ledcWrite(PWM_MOTOR_BR_2, 0);
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
DebugLog("Done!");
}
// [[[[[ LEDの設定関数 ]]]]]
static void setLed(int led, int bright)
{
int pwm = map(bright, 0, 255, 0, PWM_MAX);
switch(led)
{
case LED_R1:
ledcWrite(LED_R1, bright);
DebugLog("LED R1:%d", bright);
break;
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
case LED_G2:
ledcWrite(LED_G2, bright);
DebugLog("LED G2:%d", bright);
break;
case LED_B3:
ledcWrite(LED_B3, bright);
DebugLog("LED B3:%d", bright);
break;
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
default:
break;
}
}
// [[[[[ サーボモータの設定関数 ]]]]]
static void setServoMotor(int deg)
{
// ledcライブラリ使用時
int out = map(deg, -90, 90, SERVO_PWM_MIN, SERVO_PWM_MAX);
ledcWrite(PWM_SERVO, out);
DebugLog("Servo Motor:%d", deg);
}
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
// [[[[[ DCモーターの設定関数 ]]]]]
static void setDCMotor(int leftright, int speed)
{
int pwm = map(abs(speed), 0, MOTOR_SPEED_MAX, 0, PWM_MAX);
switch(leftright)
{
case DCMOTOR_AL:
if ( speed == 0) {
ledcWrite(PWM_MOTOR_AL_1, PWM_MAX);
ledcWrite(PWM_MOTOR_AL_2, PWM_MAX);
} else if (speed > 0) {
ledcWrite(PWM_MOTOR_AL_1, pwm);
ledcWrite(PWM_MOTOR_AL_2, 0);
} else {
ledcWrite(PWM_MOTOR_AL_1, 0);
ledcWrite(PWM_MOTOR_AL_2, pwm);
}
DebugLog("Motor A_Left:%d", speed);
break;
case DCMOTOR_BR:
if ( speed == 0) {
ledcWrite(PWM_MOTOR_BR_1, PWM_MAX);
ledcWrite(PWM_MOTOR_BR_2, PWM_MAX);
} else if (speed > 0) {
ledcWrite(PWM_MOTOR_BR_1, pwm);
ledcWrite(PWM_MOTOR_BR_2, 0);
} else {
ledcWrite(PWM_MOTOR_BR_1, 0);
ledcWrite(PWM_MOTOR_BR_2, pwm);
}
DebugLog("Motor B_Right:%d", speed);
break;
default:
break;
}
}
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
// [[[[[ ブザーの設定関数 ]]]]]
static void setBuzzer(int onoff)
{
if (onoff != 0 ) {
digitalWrite(PIN_BUZZAR, HIGH);
}
else
{
digitalWrite(PIN_BUZZAR, LOW);
}
DebugLog("Buzzer:%d", onoff);
}
/*----------------------------------------------------------------------------*/
// [[[[[ メインWebページの出力関数 ]]]]]
static void sendMainPage(WiFiClient& client)
{
int i;
DebugLog("sendingMainPage()");
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
client.println("<!DOCTYPE html>\r\n");
client.println("<html lang=\"ja\" content='initial-scale=1.5'>\r\n");
client.println("<head>\r\n");
client.println(" <meta charset=\"UTF-8\">\r\n");
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
client.println(" <title>ALGYAN 6周年基板HW動作確認</title>\r\n");
#elif defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_5TH_BOARD)
client.println(" <title>ALGYAN 5周年基板HW動作確認</title>\r\n");
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
client.println(" <style>\r\n");
client.println(" #text_LED_R1{color: red;}\r\n");
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
client.println(" #text_LED_G2{color: green;}\r\n");
client.println(" #text_LED_B3{color: blue;}\r\n");
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
client.println(" </style>\r\n");
client.println("</head>\r\n");
client.println("<html>\r\n");
client.println(" <body style='background:#fbb); color:#000); font-size:200%);'>\r\n");
client.println(" <form method='get' <BR>\r\n");
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
client.println(" <h1>ALGYAN 6周年基板HW動作確認</h1>\r\n");
#elif defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_5TH_BOARD)
client.println(" <h1>ALGYAN 5周年基板HW動作確認</h1>\r\n");
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
client.println(" <hr>\r\n");
client.println(" <div>\r\n");
client.println(" <h3>出力デバイス</h3>\r\n");
client.println(" <div>\r\n");
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_5TH_BOARD)
client.println(" LED <input type='range' min='0' max='255' step = '5' class='slider' id='led_r1_slider' value=" + String(led_r1_pos) + " onchange='changeSliderPosition(this)'>\r\n");
#elif defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
client.println(" LED R1 <input type='range' min='0' max='255' step = '5' class='slider' id='led_r1_slider' value=" + String(led_r1_pos) + " onchange='changeSliderPosition(this)'>\r\n");
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
client.println(" <span id='text_LED_R1'>" + String(led_r1_pos) + "</span><BR>\r\n");
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
client.println(" LED G2 <input type='range' min='0' max='255' step = '5' class='slider' id='led_g2_slider' value=" + String(led_g2_pos) + " onchange='changeSliderPosition(this)'>\r\n");
client.println(" <span id='text_LED_G2'>" + String(led_g2_pos) + "</span><BR>\r\n");
client.println(" LED B3 <input type='range' min='0' max='255' step = '5' class='slider' id='led_b3_slider' value=" + String(led_b3_pos) + " onchange='changeSliderPosition(this)'>\r\n");
client.println(" <span id='text_LED_B3'>" + String(led_b3_pos) + "</span><BR>\r\n");
client.println(" LED ALL<input type='range' min='0' max='255' step = '5' class='slider' id='led_all_slider' value=" + String(led_all_pos) + " onchange='changeSliderPosition(this)'>\r\n");
client.println(" <span id='text_LED_ALL'>" + String(led_all_pos) + "</span><BR>\r\n");
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
client.println(" </div><BR>\r\n");
client.println(" <div>\r\n");
client.println(" Servo Motor <input type='range' min='-90' max='90' step = '5' class='slider' id='servo_slider' value=" + String(servo_pos) + " onchange='changeSliderPosition(this)'>\r\n"); client.println(" <span id='text_ServoPos'>" + String(servo_pos) + "</span>\r\n");
client.println(" <input type='button' id='servo_center_button' value=\"センター\" onmousedown=\"changeButtonState(this, '')\" ontouchstart=\"changeButtonState(this, '')\"></input><BR>\r\n");
client.println(" </div><BR>\r\n");
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
client.println(" <div>\r\n");
client.println(" DC Motor A_Left_ <input type='range' min='-100' max='100' step = '5' class='slider' id='motor_al_slider' value=" + String(motor_AL_speed) + " onchange='changeSliderPosition(this)'>\r\n");
client.println(" <span id='text_MOTOR_AL'>" + String(motor_AL_speed) + "</span>\r\n");
client.println(" <input type='button' id='stop_MOTOR_AL' value=\"停止\" onmousedown=\"changeButtonState(this, '')\" ontouchstart=\"changeButtonState(this, '')\"></input><BR>\r\n");
client.println(" DC Motor B_Right <input type='range' min='-100' max='100' step = '5' class='slider' id='motor_br_slider' value=" + String(motor_BR_speed) + " onchange='changeSliderPosition(this)'>\r\n");
client.println(" <span id='text_MOTOR_BR'>" + String(motor_BR_speed) + "</span>\r\n");
client.println(" <input type='button' id='stop_MOTOR_BR' value=\"停止\" onmousedown=\"changeButtonState(this, '')\" ontouchstart=\"changeButtonState(this, '')\"></input><BR>\r\n");
client.println(" DC Motor Both_AB <input type='range' min='-100' max='100' step = '5' class='slider' id='motor_both_slider' value=" + String(motor_BOTH_speed) + " onchange='changeSliderPosition(this)'>\r\n");
client.println(" <span id='text_MOTOR_BOTH'>" + String(motor_BOTH_speed) + "</span>\r\n");
client.println(" <input type='button' id='stop_MOTOR_BOTH' value=\"停止\" onmousedown=\"changeButtonState(this, '')\" ontouchstart=\"changeButtonState(this, '')\"></input><BR>\r\n");
client.println(" </div><BR>\r\n");
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
client.println(" <div>\r\n");
client.println(" Buzzer <input type='button' id='buzzer_button' value=\"鳴らす\" onmousedown=\"changeButtonState(this, 'on')\" onmouseup=\"changeButtonState(this, 'off')\" ontouchstart=\"changeButtonState(this, 'on')\" ontouchend=\"changeButtonState(this, 'off')\"></input><BR>\r\n");
client.println(" </div><BR>\r\n");
client.println(" </div>\r\n");
client.println(" <hr>\r\n");
client.println(" <div>\r\n");
client.println(" <h3>スキャン情報</h3>\r\n");
client.println(" <div>\r\n");
client.println(" <h4>WiFi scan result</h4>\r\n");
for (i = 0; i<scaned_wifi_count; i++)
{
if (wifi_ssid_list[i] == "") break;
client.println ( " " + wifi_ssid_list[i] +"<BR>\r\n");
}
client.println(" </div>\r\n");
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
client.println(" <div>\r\n");
client.println(" <h4>i2c device scan result</h4>\r\n");
for (i = 1; i<127; i++)
{
if ( (i2c_scan_result[i/16] & (uint16_t)(1 << (i%16))) != 0 ) {
char addr_str[3];
sprintf(addr_str, "%02X", i);
client.println ( " Slave Address " + String(addr_str) + "h found!<BR>\r\n");
}
}
client.println(" </div>\r\n");
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
client.println(" </div>\r\n");
client.println(" </form>\r\n");
client.println(" <script>\r\n");
client.println(" function changeSliderPosition(element) {\r\n");
client.println(" if(element.id=='led_r1_slider') {\r\n");
client.println(" document.getElementById(\"text_LED_R1\").innerHTML = element.value;\r\n");
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
client.println(" document.getElementById(\"text_LED_ALL\").innerHTML = "\
"((parseInt(document.getElementById(\"text_LED_R1\").innerHTML) + parseInt(document.getElementById(\"text_LED_G2\").innerHTML) + parseInt(document.getElementById(\"text_LED_B3\").innerHTML) ) / 3).toFixed(0);\r\n");
client.println(" document.getElementById(\"led_all_slider\").value = document.getElementById(\"text_LED_ALL\").innerHTML;\r\n");
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
client.println(" sendXMLHttpRequest(\"?led_R1=\" + element.value + \"&\");\r\n");
client.println(" }\r\n");
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
client.println(" if(element.id=='led_g2_slider') {\r\n");
client.println(" document.getElementById(\"text_LED_G2\").innerHTML = element.value;\r\n");
client.println(" document.getElementById(\"text_LED_ALL\").innerHTML = "\
"((parseInt(document.getElementById(\"text_LED_R1\").innerHTML) + parseInt(document.getElementById(\"text_LED_G2\").innerHTML) + parseInt(document.getElementById(\"text_LED_B3\").innerHTML) ) / 3).toFixed(0);\r\n");
client.println(" document.getElementById(\"led_all_slider\").value = document.getElementById(\"text_LED_ALL\").innerHTML;\r\n");
client.println(" sendXMLHttpRequest(\"?led_G2=\" + element.value + \"&\");\r\n");
client.println(" }\r\n");
client.println(" if(element.id=='led_b3_slider') {\r\n");
client.println(" document.getElementById(\"text_LED_B3\").innerHTML = element.value;\r\n");
client.println(" document.getElementById(\"text_LED_ALL\").innerHTML = "\
"((parseInt(document.getElementById(\"text_LED_R1\").innerHTML) + parseInt(document.getElementById(\"text_LED_G2\").innerHTML) + parseInt(document.getElementById(\"text_LED_B3\").innerHTML) ) / 3).toFixed(0);\r\n");
client.println(" document.getElementById(\"led_all_slider\").value = document.getElementById(\"text_LED_ALL\").innerHTML;\r\n");
client.println(" sendXMLHttpRequest(\"?led_B3=\" + element.value + \"&\");\r\n");
client.println(" }\r\n");
client.println(" if(element.id=='led_all_slider') {\r\n");
client.println(" document.getElementById(\"text_LED_R1\").innerHTML = element.value;\r\n");
client.println(" document.getElementById(\"led_r1_slider\").value = element.value;\r\n");
client.println(" document.getElementById(\"text_LED_G2\").innerHTML = element.value;\r\n");
client.println(" document.getElementById(\"led_g2_slider\").value = element.value;\r\n");
client.println(" document.getElementById(\"text_LED_B3\").innerHTML = element.value;\r\n");
client.println(" document.getElementById(\"led_b3_slider\").value = element.value;\r\n");
client.println(" document.getElementById(\"text_LED_ALL\").innerHTML = element.value;\r\n");
client.println(" sendXMLHttpRequest(\"?led_ALL=\" + element.value + \"&\");\r\n");
client.println(" }\r\n");
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
client.println(" if(element.id=='servo_slider') {\r\n");
client.println(" document.getElementById(\"text_ServoPos\").innerHTML = element.value;\r\n");
client.println(" sendXMLHttpRequest(\"?servo=\" + element.value + \"&\");\r\n");
client.println(" }\r\n");
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
client.println(" if(element.id=='motor_al_slider') {\r\n");
client.println(" document.getElementById(\"text_MOTOR_AL\").innerHTML = element.value;\r\n");
client.println(" document.getElementById(\"text_MOTOR_BOTH\").innerHTML = "\
"(( parseInt(document.getElementById(\"text_MOTOR_AL\").innerHTML) + parseInt(document.getElementById(\"text_MOTOR_BR\").innerHTML) ) / 2).toFixed(0);\r\n");
client.println(" document.getElementById(\"motor_both_slider\").value = document.getElementById(\"text_MOTOR_BOTH\").innerHTML;\r\n");
client.println(" sendXMLHttpRequest(\"?motor_al=\" + element.value + \"&\");\r\n");
client.println(" }\r\n");
client.println(" if(element.id=='motor_br_slider') {\r\n");
client.println(" document.getElementById(\"text_MOTOR_BR\").innerHTML = element.value;\r\n");
client.println(" document.getElementById(\"text_MOTOR_BOTH\").innerHTML = "\
"(( parseInt(document.getElementById(\"text_MOTOR_AL\").innerHTML) + parseInt(document.getElementById(\"text_MOTOR_BR\").innerHTML) ) / 2).toFixed(0);\r\n");
client.println(" document.getElementById(\"motor_both_slider\").value = document.getElementById(\"text_MOTOR_BOTH\").innerHTML;\r\n");
client.println(" sendXMLHttpRequest(\"?motor_br=\" + element.value + \"&\");\r\n");
client.println(" }\r\n");
client.println(" if(element.id=='motor_both_slider') {\r\n");
client.println(" document.getElementById(\"text_MOTOR_AL\").innerHTML = element.value;\r\n");
client.println(" document.getElementById(\"motor_al_slider\").value = element.value;\r\n");
client.println(" document.getElementById(\"text_MOTOR_BR\").innerHTML = element.value;\r\n");
client.println(" document.getElementById(\"motor_br_slider\").value = element.value;\r\n");
client.println(" document.getElementById(\"text_MOTOR_BOTH\").innerHTML = element.value;\r\n");
client.println(" sendXMLHttpRequest(\"?motor_both=\" + element.value + \"&\");\r\n");
client.println(" }\r\n");
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
client.println(" }\r\n");
client.println(" function changeButtonState(element, state) {\r\n");
client.println(" state_num = (state=='on')? 1: 0;\r\n");
client.println(" if(element.id=='servo_center_button') {\r\n");
client.println(" document.getElementById(\"servo_slider\").value = 0;\r\n");
client.println(" document.getElementById(\"text_ServoPos\").innerHTML = 0;\r\n");
client.println(" sendXMLHttpRequest(\"?servo=0\");\r\n");
client.println(" }\r\n");
client.println(" if(element.id=='buzzer_button') {\r\n");
client.println(" sendXMLHttpRequest(\"?buzzer=\" + state_num);\r\n");
client.println(" }\r\n");
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
client.println(" if(element.id=='stop_MOTOR_AL') {\r\n");
client.println(" document.getElementById(\"motor_al_slider\").value = 0;\r\n");
client.println(" document.getElementById(\"text_MOTOR_AL\").innerHTML = 0;\r\n");
client.println(" document.getElementById(\"text_MOTOR_BOTH\").innerHTML = (parseInt(document.getElementById(\"text_MOTOR_BR\").innerHTML) / 2).toFixed(0);\r\n");
client.println(" document.getElementById(\"motor_both_slider\").value = document.getElementById(\"text_MOTOR_BOTH\").innerHTML;\r\n");
client.println(" sendXMLHttpRequest(\"?stop_al\");\r\n");
client.println(" }\r\n");
client.println(" if(element.id=='stop_MOTOR_BR') {\r\n");
client.println(" document.getElementById(\"motor_br_slider\").value = 0;\r\n");
client.println(" document.getElementById(\"text_MOTOR_BR\").innerHTML = 0;\r\n");
client.println(" document.getElementById(\"text_MOTOR_BOTH\").innerHTML = (parseInt(document.getElementById(\"text_MOTOR_AL\").innerHTML) / 2).toFixed(0);\r\n");
client.println(" document.getElementById(\"motor_both_slider\").value = document.getElementById(\"text_MOTOR_BOTH\").innerHTML;\r\n");
client.println(" sendXMLHttpRequest(\"?stop_br\");\r\n");
client.println(" }\r\n");
client.println(" if(element.id=='stop_MOTOR_BOTH') {\r\n");
client.println(" document.getElementById(\"motor_al_slider\").value = 0;\r\n");
client.println(" document.getElementById(\"text_MOTOR_AL\").innerHTML = 0;\r\n");
client.println(" document.getElementById(\"motor_br_slider\").value = 0;\r\n");
client.println(" document.getElementById(\"text_MOTOR_BR\").innerHTML = 0;\r\n");
client.println(" document.getElementById(\"motor_both_slider\").value = 0;\r\n");
client.println(" document.getElementById(\"text_MOTOR_BOTH\").innerHTML = 0;\r\n");
client.println(" sendXMLHttpRequest(\"?stop_both\");\r\n");
client.println(" }\r\n");
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
client.println(" }\r\n");
client.println(" function sendXMLHttpRequest(str) {\r\n");
client.println(" xhr = new XMLHttpRequest();\r\n");
client.println(" xhr.open('GET', str, true); \r\n");
client.println(" xhr.send();\r\n");
client.println(" }\r\n");
client.println(" </script>\r\n");
client.println(" </body>\r\n");
client.println("</html>\r\n");
DebugLog("Done!!!!!!");
}
// [[[[[ ブラウザからのパラメータ受信時の処理関数 ]]]]]
static void recvFromBrowser(String& str_buffer)
{
int pos_start, pos_end;
DebugLog("\t|Rcv>\"%s\"", str_buffer.c_str());
if (str_buffer.indexOf("GET /") >= 0) {
DebugLog("Processing \"GET /\"");
if (str_buffer.indexOf("?servo=") >= 0) {
pos_start = str_buffer.indexOf('=') + 1;
pos_end = str_buffer.indexOf('&');
servo_pos = str_buffer.substring(pos_start, pos_end).toInt();
setServoMotor(servo_pos);
}
if (str_buffer.indexOf("?led_R1=") >= 0) {
pos_start = str_buffer.indexOf('=') + 1;
pos_end = str_buffer.indexOf('&');
led_r1_pos = str_buffer.substring(pos_start, pos_end).toInt();
setLed(LED_R1, led_r1_pos);
}
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
if (str_buffer.indexOf("?led_G2=") >= 0) {
pos_start = str_buffer.indexOf('=') + 1;
pos_end = str_buffer.indexOf('&');
led_g2_pos = str_buffer.substring(pos_start, pos_end).toInt();
setLed(LED_G2, led_g2_pos);
}
if (str_buffer.indexOf("?led_B3=") >= 0) {
pos_start = str_buffer.indexOf('=') + 1;
pos_end = str_buffer.indexOf('&');
led_b3_pos = str_buffer.substring(pos_start, pos_end).toInt();
setLed(LED_B3, led_b3_pos);
}
if (str_buffer.indexOf("?led_ALL=") >= 0) {
pos_start = str_buffer.indexOf('=') + 1;
pos_end = str_buffer.indexOf('&');
led_all_pos = str_buffer.substring(pos_start, pos_end).toInt();
led_r1_pos = led_all_pos;
led_g2_pos = led_all_pos;
led_b3_pos = led_all_pos;
setLed(LED_R1, led_r1_pos);
setLed(LED_G2, led_g2_pos);
setLed(LED_B3, led_b3_pos);
}
if (str_buffer.indexOf("?motor_al=") >= 0) {
pos_start = str_buffer.indexOf('=') + 1;
pos_end = str_buffer.indexOf('&');
motor_AL_speed = str_buffer.substring(pos_start, pos_end).toInt();
motor_BOTH_speed = (motor_AL_speed + motor_BR_speed) >> 1;
setDCMotor(DCMOTOR_AL, motor_AL_speed);
}
if (str_buffer.indexOf("?motor_br=") >= 0) {
pos_start = str_buffer.indexOf('=') + 1;
pos_end = str_buffer.indexOf('&');
motor_BR_speed = str_buffer.substring(pos_start, pos_end).toInt();
motor_BOTH_speed = (motor_AL_speed + motor_BR_speed) >> 1;
setDCMotor(DCMOTOR_BR, motor_BR_speed);
}
if (str_buffer.indexOf("?motor_both=") >= 0) {
pos_start = str_buffer.indexOf('=') + 1;
pos_end = str_buffer.indexOf('&');
motor_BOTH_speed = str_buffer.substring(pos_start, pos_end).toInt();
motor_AL_speed = motor_BOTH_speed;
motor_BR_speed = motor_BOTH_speed;
setDCMotor(DCMOTOR_AL, motor_AL_speed);
setDCMotor(DCMOTOR_BR, motor_BR_speed);
}
if (str_buffer.indexOf("?stop_al") >= 0) {
motor_AL_speed = 0;
motor_BOTH_speed = (motor_AL_speed + motor_BR_speed) >> 1;
setDCMotor(DCMOTOR_AL, motor_AL_speed);
}
if (str_buffer.indexOf("?stop_br") >= 0) {
motor_BR_speed = 0;
motor_BOTH_speed = (motor_AL_speed + motor_BR_speed) >> 1;
setDCMotor(DCMOTOR_BR, motor_BR_speed);
}
if (str_buffer.indexOf("?stop_both") >= 0) {
motor_BOTH_speed = 0;
motor_AL_speed = motor_BOTH_speed;
motor_BR_speed = motor_BOTH_speed;
setDCMotor(DCMOTOR_AL, motor_AL_speed);
setDCMotor(DCMOTOR_BR, motor_BR_speed);
}
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
if (str_buffer.indexOf("?buzzer=") >= 0) {
pos_start = str_buffer.indexOf('=') + 1;
pos_end = str_buffer.indexOf('&');
buzzer_state = str_buffer.substring(pos_start, pos_end).toInt();
}
DebugLog("Done!!!!!!!");
}
}
4. 使い方
本ソフトは、大まかにWebサーバーチェックとオンボードチェッカの、2部構成となっています。
Webサーバーは LED類、モーター類、ブザー等のアクチュエータや、WiFiとI2cのスキャンした結果の情報等の出力機能をチェックします。
オンボードチェックは センサーやスイッチ等の入力機能をチェックします。
まずは動画をご覧ください。
電源を入れるとピピっという音がします。
しばらく待つと青色LEDが点灯します。
ピピ音は、リセットが掛かった場合に気付ける目的で実装したもので、青色LEDは、 WiFi が使えるようになった時点で付くようにしました。
4.1. Webサーバー
基本的に、本ボードを WiFi のアクセスポイントとして使用し、Webブラウザでアクセスして動作させます。
起動するにはまず、スマホや PCの WiFi アクセスポイント選択画面を開きます。
下の画像は Windows10 の場合の設定画面です。
この中で、 "ALGYAN_6th-AP" で始まるものを選択し接続し、パスワードを入れます。(パスワードは3.3 にあるソフトをそのまま使った場合は "12345678" です)
無事にログイン出来たら、自動的に Webページが開いて、各種の機能の操作画面が表示されます。
以降で項目別に説明します。
4.1.1. LED チェッカ
LED1 に赤、LED2 に緑、LED3 に青を実装したか、RGB LED を実装した前提です。
スライダーを左右に動かすことで、各 LED の輝度を制御します。一番左が消灯、一番右が輝度最大となります。
上3つが個別に LED を制御するもので、一番下の4つ目のスライダーを操作すると、全 LED の輝度を同じにすることができます。RGB一体のLEDを使った場合、白色 LEDの輝度制御をしているように見えます。
4.1.2. サーボモータチェッカ
CN3に繋いだサーボモータを制御します。
スライダーを動かすことで -90°~ 90°の範囲で 180°動かすことができます。[センター] ボタンを押すと中央値 (0° ) に動かすことができます。
4.1.3. ブザーチェッカ
ボタンを押すとブザーが鳴りだし、離すと止まります。
ボタンを教えている最中にマウスを動かして、カーソルがボタンの範囲からずれてしまうと、鳴りっぱなしになります。その場合はもう一度軽く押してください。
4.1.4. DCモータチェッカ
CN2 に繋いだ DCモータを制御します。
スライダーを動かして -100 ~ 100 の範囲でスピードを設定します。 右に動かすと正転、左に動かすと反転、真ん中の位置で停止します。
[停止] ボタンを押すとスライダーが真ん中の位置になり停止します。
また、一番下のスライダーは両方のモータを同時に操作することができます。
接続は
CN2 pin1 - 2: Motor AL 左側A
CN2 pin3 - 4: Motor BR 右側B
と繋いだ場合の動作になります。
※モーター駆動用電源は別電源になっていて、ジャンバーで選択できるようになっている上に、デフォルトでは繋がっていないようです。以下の1. or 2. いずれかにして、供給してやる必要があります。
- USBからの電源を使う場合は、SJ3 の 1-2 側を半田盛りしてショートします。
- 別系統電源(こちらは5V以上も可)を入力する場合はCN9 から入れてやり、SJ3の 2-3 側を半田盛りしてショートします。
1.の場合は供給不足になりリセットを繰り返す場合があります。私の場合も USB2.0 ポートに挿すとリセットが繰り返しの現象が発生しましたが、 USB3.0 ポートに繋いでやるとうまくいきました。それでも改善しない場合は CN1 から5V の補助電源(5V only)を供給してやる必要があります。
4.1.5. WiFiアクセスポイント一覧
起動時に WiFi アクセスポイントをスキャンし、見つかったもの全て(ご近所の WiFi ルーターやテザリングスマホも含め)電波が届いて見つかったものを一覧表示します。
リアルタイム更新はしていないので、ブラウザ更新しても表示内容は更新されません。起動時に見つかったものだけが表示されます。
4.1.6. i2cバス一覧
CN10 や、グローブコネクタの CN5, CN6 に接続されている、i2c デバイスを起動時にスキャンし、見つかったもののデバイスアドレス(スレーブアドレス)を表示します。
あくまで、システムとしてデバイスを認識するかのチェックのみで、センサーの値やデバイスIDレジスタ等は読んでいません。
リアルタイム更新はしていないので、後から追加しても表示されません。起動時に接続されている必要があります。
複数電圧を繋ぐようにはできてなさそうなので、信号レベルが 3.3V のデバイスだけを繋ぎ、混在はやめておいた方がよさそうです。
デバイスを繋ぐのに、GROVEコネクタのCN6 を使う場合は裏面のジャンパー設定を下記の通りに修正(半田盛りジャンパ)が必要
- SJ1 の 2と3をショート
- SJ2 の 2と3をショート
4.2. オンボードチェッカ
こちらは、基本的に全て基板単体で確認するものです。但し、センサの値はボードとPCを繋いで、マイコンから出しているシリアルログで動作します。
項目別に説明します。
4.2.1. スイッチチェック
単純にスイッチを押すと、ブザーが鳴るだけです。
4.2.2. 明るさセンサ (CDS) チェック
Arduino 開発環境の、シリアルプロッタというグラフ表示機能を使って確認します。
PCに接続したまま、 Arduino のメニューから [ツール] - [シリアルプロッタ] を選択してやると下記の画面の様にグラフがリアルタイムで表示されます。グラフの画面左下に、通信速度の設定があり 9600bps となっている場合は、グラフが更新されませんのでその場合は 115200bps に変更します。
CDS センサの光をさえぎってやると小さく、光を当ててやると大きくなります。
5. トラブルシューティング
あくまで参考ですが、想定される障害現象とその対策を書いてみました。
基板の一部が動かなかった場合の参考にしてください。
症状 | 不具合箇所 | 対処法等 |
---|---|---|
電源が入らない(5V-GND間 が 0V) | CN4★ | はんだ付け接触不良又はブリッジ |
電源が入らない(3.3V-GND間 が 0V) | U2, C1, C2, C3, C4, C5, C6★ | はんだ付け接触不良又はブリッジ |
リセットがかかる(ピピ音が繰り返しなる) | 電力不足 | CN1から補助電源を供給してみる |
赤色LEDが付かない、付きっぱなし | R10, LED1orRGB_LED | はんだ付け接触不良又はブリッジ |
緑色LEDが付かない、付きっぱなし | R11, LED2 or LED4 | はんだ付け接触不良又はブリッジ |
青色LEDが付かない、付きっぱなし | R12, LED3 or LED4 | はんだ付け接触不良又はブリッジ |
ブザーが鳴らない | BZ1, D1 | はんだ付け接触不良又はブリッジ |
サーボが動かない | CN3 | はんだ付け接触不良又はブリッジ |
DCモータが動かない | CN1,CN9,SJ3 | モーター電源の供給方法がいくつかありますがデフォルトではつながっていません。供給されているか確認が必要 |
DCモーターを動かしていると、ピピっといって動かなくなる | 電力不足でリセットが掛かっている。 | モーターの電源共有方法を変えてみる。SJ3 を変更して CN9から供給してみる等 |
接続しているはずのi2cデバイスのアドレスが出てこない | CN5,CN6, CN10 | はんだブリッジ。またはCN6に繋いでいる場合は SJ,SJ2 が接続されていないという可能性もあります。 |
Web画面ではなるが、スイッチ押してもブザーが鳴らない | SW3, R8 | はんだ付け接触不良又はブリッジ |
CDSを手で覆ってもグラフに変化がない | CDS1, R9 | はんだ付け接触不良又はブリッジ |
★印の箇所は、「部品セットB(手作りFULL)」を選択した場合のみ。
6. おまけ
6.1. ALGYAN 5周年
使うためにはソフトウェア変更が必要ですが、実は去年【オンライン】基板プレゼント有・ALGYAN5th IoT基板はんだづけ勝手にもくもく会で配布された ALGYAN5周年基板も動作可能です。
(こちらも正規の部品使わないで、家にある部品を強引に実装して作ったので少し不格好ですが。)
搭載部品が少ない分、Webサーバー側の表示項目は少なくなりますが、以下のようになります。
使うためにはソフトの、10~12 行目の部分を
変更前
// ボード選択(以下のうちのいずれかを有効(コメント解除)する)
#define CONFIG_HW_ALGYAN_6TH_BOARD
//#define CONFIG_HW_ALGYAN_5TH_BOARD
以下のように変更します。
変更後
// ボード選択(以下のうちのいずれかを有効(コメント解除)する)
//#define CONFIG_HW_ALGYAN_6TH_BOARD
#define CONFIG_HW_ALGYAN_5TH_BOARD
6.1 ログインパスワード変更
基本的に外部(インターネット)には接続していませんので、外部からログインを試みられることはありませんが、電波の届く範囲からはログイン可能で、それが気になるかもしれません。
またはもっと短いパスワードにしたい方もいるかもしれません。
その場合はソフトの52行目の以下の
パスワード変更
// アクセスポイント関連
#if defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_5TH_BOARD)
#define BOARD_NAME "ALGYAN_5th" // SSIDの先頭
#elif defined(THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD)
#define BOARD_NAME "ALGYAN_6th" // SSIDの先頭
#endif // THIS_BLOCK_IS_ONLY_FOR_ALGYAN_6TH_BOARD
#define BOARD_NUM "1" // 近くで同じSSIDを使うと重複してわからなくなるので区別の為番号を末尾に着けている。
#define MY_PASSWORD "12345678" // パスワード(WiFi電波の届く範囲の人に勝手にログインして操作されたくなければ変える。)
#define MY_PASSWORD の後ろの文字列を変更してください。
7. さいごに
本基板の設計してくださった大栄 様
基板を制作をし無償提供してくださった Seeed 様
素敵な企画をしてくださった IoT ALGYAN(あるじゃん)運営委員会 小暮 様とその運営をしてくださっている 委員会の皆様
に深く感謝し、この基板で楽しいハンズオンが開かれることを期待しつつ、皆さんが無事に基板を完成できることを願っております。
投稿者の人気記事
-
TakSan0
さんが
2021/06/20
に
編集
をしました。
(メッセージ: 初版)
-
TakSan0
さんが
2021/06/23
に
編集
をしました。
(メッセージ: 友人から指摘を受けた部分を修正。)
-
TakSan0
さんが
2021/06/25
に
編集
をしました。
(メッセージ: 気になったところを少し修正。)
-
TakSan0
さんが
2022/01/05
に
編集
をしました。
(メッセージ: ライセンス設定等更新)
-
TakSan0
さんが
2022/01/05
に
編集
をしました。
ログインしてコメントを投稿する