zhixuanのアイコン画像
zhixuan 2025年01月11日作成 (2025年01月11日更新) © GPL-3.0+
製作品 製作品 閲覧数 67
zhixuan 2025年01月11日作成 (2025年01月11日更新) © GPL-3.0+ 製作品 製作品 閲覧数 67

Spresense HDR カメラをWifiやLTE使って遠隔操作

Spresense HDR カメラをWifiやLTE使って遠隔操作

Spresense HDR カメラをWifiやLTE使って遠隔操作

タイトルの通り今回活用コンテストで作成したのは遠隔操作できるカメラです。

システム構成図

現時点で操作できることは以下の通り、

  • 写真を撮る
  • 自動ホワイトバランスを設定
  • 自動ホワイトバランスモードを設定
  • 自動露光を設定
  • 絶対露光を設定
  • 自動ISO感度を設定
  • ISO感度を設定
  • カラーエフェクトを設定
  • HDRを設定

Other feature

  • Camera, Wifi, Lte Status LED

BOM

使用するものは以下の通りです。

Name Number of pieces Memo
Spresense メインボード 1
Spresense LTE拡張ボード 1
Spresense HDRカメラボード 1
SD Card 1
Sim Card 1 povo

動作環境&使用Library

MQTT

MQTT で Byte を送ると、LTEだとクラッシュし、Wifiだと受け取れなかったので。コマンド全部Stringで送るようにしました。

以下のようにコマンドを設計して。

1,2,1 command,subcommand, parameter

コマンドリストは以下の通りです。

#define commandTackPicture "0" #define commandSetCameraParameter "1" #define commandGetCemeraParameter "2" // Subcommand for commandSetCameraParameter #define subSetAutoWhiteBalance "0" #define subSetAutoWhiteBalanceMode "1" #define subSetAutoExposure "2" #define subSetAbsoluteExposure "3" #define subSetAutoISOSensitive "4" #define subSetISOSensitivity "5" #define subSetColorEffect "6" #define subSetHDR "7" // Subcommand for commandGetCemeraParameter // This is not implemented yet #define subGetAbsoluteExposure "0" #define subGetDeviceType "1" #define subGetFd "2" #define subGetFrameInterval "3" #define subGetHDR "4" #define subGetISOSensitivity "5" #define subGetJPEGQuality "6"

撮影

GIFのリンク

nyaacat

Code たち

これから全部コードです。
一応このCodeたちは自分のGithubに公開する予定なので、Cloneしたい人はそっちを探してください。もし、動かない場合自分にMessageをしてください。

一番下までのリンク

ファイル構造

% ls include lib platformio.ini src test % cd src/main && tree . ├── callback.cpp ├── callback.h ├── config.h ├── main.cpp ├── mqtt.cpp ├── mqtt.h ├── mycam.cpp ├── mycam.h ├── mylte.cpp └── mylte.h

platformio.ini

; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html [env] platform = sonyspresense board = spresense framework = arduino monitor_speed = 115200 upload_command = ${platformio.packages_dir}/tool-spresense/flash_writer/macosx/flash_writer -s -c $UPLOAD_PORT -b $UPLOAD_SPEED -d -n -s $SOURCE targets = upload build_flags = -D USE_HDR_CAMERA board_upload.maximum_size = 1572864 board_upload.maximum_ram_size = 1572864 upload_speed = 230400 lib_deps = https://github.com/jittermaster/GS2200-WiFi.git SPI arduino-libraries/ArduinoMqttClient@^0.1.8 [env:spresense_mainCore-lte] build_src_filter = +<main/> build_flags = -D USE_LTE [env:spresense_mainCore-wifi] build_src_filter = +<main/> build_flags = -D USE_WIFI [env:spresense_subCore1] build_flags = -DPIO_FRAMEWORK_ARDUINO_CORE_SUB_CORE_1 build_src_filter = +<sub1/>

callback.cpp

#include "callback.h" #include "mycam.h" int split(String data, char delimiter, String* dst) { int index = 0; int arraySize = (sizeof(data)) / sizeof((data[0])); int datalength = data.length(); for (int i = 0; i < datalength; i++) { char tmp = data.charAt(i); if (tmp == delimiter) { index++; if (index > (arraySize - 1)) return -1; } else dst[index] += tmp; } return (index + 1); } bool getBool(String data) { return data == "true"; } CAM_WHITE_BALANCE getAutoWhiteBalanceMode(String data) { if (data == "0") return CAM_WHITE_BALANCE_AUTO; else if (data == "1") return CAM_WHITE_BALANCE_INCANDESCENT; else if (data == "2") return CAM_WHITE_BALANCE_FLUORESCENT; else if (data == "3") return CAM_WHITE_BALANCE_DAYLIGHT; else if (data == "4") return CAM_WHITE_BALANCE_FLASH; else if (data == "5") return CAM_WHITE_BALANCE_CLOUDY; else if (data == "6") return CAM_WHITE_BALANCE_SHADE; else return CAM_WHITE_BALANCE_AUTO; } // Convert void setSetAutoWhiteBalance(String data) { callSetAutoWhiteBalance(getBool(data)); } void setSetAutoWhiteBalanceMode(String data) { callSetAutoWhiteBalanceMode(getAutoWhiteBalanceMode(data)); } void setSetAutoExposure(String data) { callSetAutoExposure(getBool(data)); } void setSetAbsoluteExposure(String data) { callSetAbsoluteExposure(data.toInt()); } void setSetAutoISOSensitive(String data) { callSetAutoISOSensitive(getBool(data)); } void setSetISOSensitivity(String data) { callSetISOSensitivity(data.toInt()); } void setSetColorEffect(String data) { callSetColorEffect((CAM_COLOR_FX)data.toInt()); } void setSetHDR(String data) { callSetHDR((CAM_HDR_MODE)data.toInt()); } // callSetAbsoluteExposure // Convert END void req_callback(String data) { if (data.length() == 0) { return; } String cmds[7] = { "" }; int index = split(data, ',', cmds); if (cmds[0] == commandTackPicture) { Serial.println("[MAIN][REQ] Take Picture"); takePic(); } else if (cmds[0] == commandSetCameraParameter) { Serial.println("[MAIN][REQ] Command get Camera Info"); if (cmds[1] == subSetAutoWhiteBalance) { Serial.println("[MAIN][REQ] Subcommand set Auto White Balance"); setSetAutoWhiteBalance(cmds[2]); } else if (cmds[1] == subSetAutoWhiteBalanceMode) { Serial.println("[MAIN][REQ] Subcommand set Auto White Balance Mode"); setSetAutoWhiteBalanceMode(cmds[2]); } else if (cmds[1] == subSetAutoExposure) { Serial.println("[MAIN][REQ] Subcommand set Auto Exposure"); setSetAutoExposure(cmds[2]); } else if (cmds[1] == subSetAbsoluteExposure) { Serial.println("[MAIN][REQ] Subcommand set Absolute Exposure"); setSetAbsoluteExposure(cmds[2]); } else if (cmds[1] == subSetAutoISOSensitive) { Serial.println("[MAIN][REQ] Subcommand set Auto ISO Sensitive"); setSetAutoISOSensitive(cmds[2]); } else if (cmds[1] == subSetISOSensitivity) { Serial.println("[MAIN][REQ] Subcommand set ISO Sensitive"); setSetISOSensitivity(cmds[2]); } else if (cmds[1] == subSetColorEffect) { Serial.println("[MAIN][REQ] Subcommand set Color Effect"); setSetColorEffect(cmds[2]); } else if (cmds[1] == subSetHDR) { Serial.println("[MAIN][REQ] Subcommand set HDR"); setSetHDR(cmds[2]); } else Serial.println("[MAIN][REQ] Unknown SubCommand"); } else if (cmds[0] == commandGetCemeraParameter) { Serial.println("[MAIN][REQ] Command get Camera Info"); Serial.println("[MAIN][REQ] This command is not implemented yet"); if (cmds[1] == subGetAbsoluteExposure) {} else if (cmds[1] == subGetDeviceType) {} else if (cmds[1] == subGetFd) {} else if (cmds[1] == subGetFrameInterval) {} else if (cmds[1] == subGetHDR) {} else if (cmds[1] == subGetISOSensitivity) {} else if (cmds[1] == subGetJPEGQuality) {} else Serial.println("[MAIN][REQ] Unknown SubCommand"); } else { Serial.println("[MAIN][REQ] Unknown Command"); } }

callback.h

#ifndef __CALLBACK_H__ #define __CALLBACK_H__ #include <Arduino.h> #include "config.h" void req_callback(String data); #define commandTackPicture "0" #define commandSetCameraParameter "1" #define commandGetCemeraParameter "2" // Subcommand for commandSetCameraParameter #define subSetAutoWhiteBalance "0" #define subSetAutoWhiteBalanceMode "1" #define subSetAutoExposure "2" #define subSetAbsoluteExposure "3" #define subSetAutoISOSensitive "4" #define subSetISOSensitivity "5" #define subSetColorEffect "6" #define subSetHDR "7" // Subcommand for commandGetCemeraParameter // This is not implemented yet #define subGetAbsoluteExposure "0" #define subGetDeviceType "1" #define subGetFd "2" #define subGetFrameInterval "3" #define subGetHDR "4" #define subGetISOSensitivity "5" #define subGetJPEGQuality "6" #endif // __CALLBACK_H__

config.h

/* * config.h - WiFi Configration Header * * This work is free software; you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Foundation; * either version 2.1 of the License, or (at your option) any later version. * * This work is distributed in the hope that it will be useful, but without any warranty; * without even the implied warranty of merchantability or fitness for a particular * purpose. See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with * this work; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _CONFIG_H_ #define _CONFIG_H_ /*-------------------------------------------------------------------------* * Configration *-------------------------------------------------------------------------*/ #define AP_SSID "<Change ME>" #define PASSPHRASE "<Change ME>" #define MQTT_SRVR "test.mosquitto.org" #define MQTT_PORT 1883 #define MQTT_CLI_ID "Telit_Device_pub" #define MQTT_REQ "<Change ME>" #endif /*_CONFIG_H_*/

main.cpp

#include <Arduino.h> #include "callback.h" #include "config.h" #include "mycam.h" #ifdef USE_LTE #include "mylte.h" #endif #ifdef USE_WIFI #include "mqtt.h" #endif #define CONSOLE_BAUDRATE 115200 void setup() { /* initialize digital pin LED_BUILTIN as an output. */ pinMode(LED0, OUTPUT); // Camera LED pinMode(LED1, OUTPUT); // WiFi LED pinMode(LED2, OUTPUT); // LTE LED pinMode(LED3, OUTPUT); Serial.begin(CONSOLE_BAUDRATE); // talk to PC camera_setup(); #ifdef USE_LTE lte_setup(); mqtt_setup(); #endif #ifdef USE_WIFI wifi_setup(); #endif } void loop() { #ifdef USE_LTE String data = mqtt_loop(); req_callback(data); #endif #ifdef USE_WIFI String data; mqtt_sub(MQTT_REQ, data); req_callback(data); #endif }

mqtt.cpp

#include "mqtt.h" TelitWiFi gs2200; TWIFI_Params gsparams; MqttGs2200 theMqttGs2200(&gs2200); bool served = false; MQTTGS2200_Mqtt mqttc; void wifi_setup() { /* Initialize SPI access of GS2200 */ Init_GS2200_SPI_type(iS110B_TypeC); /* Initialize AT Command Library Buffer */ gsparams.mode = ATCMD_MODE_STATION; gsparams.psave = ATCMD_PSAVE_DEFAULT; if (gs2200.begin(gsparams)) { Serial.println("GS2200 Initilization Fails"); while (1) ; } /* GS2200 Association to AP */ if (gs2200.activate_station(AP_SSID, PASSPHRASE)) { Serial.println("Association Fails"); while (1) ; } MQTTGS2200_HostParams hostParams; hostParams.host = (char *) MQTT_SRVR; hostParams.port = (char *) MQTT_PORT; hostParams.clientID = (char *) MQTT_CLI_ID; hostParams.userName = NULL; hostParams.password = NULL; theMqttGs2200.begin(&hostParams); digitalWrite(LED1, HIGH); // turn on LED } void mqtt_sub(const char *topic, String & opt) { if (!served) { // Start a MQTT client ConsoleLog("Start MQTT Client"); if (false == theMqttGs2200.connect()) { return; } ConsoleLog("Start to receive MQTT Message"); // Prepare for the next chunck of incoming data WiFi_InitESCBuffer(); // Start the loop to receive the data strncpy(mqttc.params.topic, topic, sizeof(mqttc.params.topic)); mqttc.params.QoS = 0; mqttc.params.retain = 0; if (true == theMqttGs2200.subscribe(&mqttc)) { ConsolePrintf("Subscribed! \n"); } served = true; } else { String data; /* just in case something from GS2200 */ while (gs2200.available()) { if (false == theMqttGs2200.receive(data)) { break; } Serial.println("Recieve data: " + data); opt = data; } } } void stop() { theMqttGs2200.stop(); exit(0); }

mqtt.h

#ifndef __MQTT_H__ #define __MQTT_H__ #include <Arduino.h> #include <MqttGs2200.h> #include <TelitWiFi.h> #include "config.h" #define SUBSCRIBE_TIMEOUT 100 // ms void wifi_setup(); void mqtt_sub(const char *topic, String & opt) ; #endif // __MQTT_H__

mycam.cpp

// // Created by Zhixuan Jin on 2024/12/14. // /* * camera.ino - Simple camera example sketch * Copyright 2018, 2022 Sony Semiconductor Solutions Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * This is a test app for the camera library. * This library can only be used on the Spresense with the FCBGA chip package. */ #include "mycam.h" SDClass theSD; int take_picture_count = 0; void CameraConsolePrintln(const char *str) { Serial.println("[MAIN][CAM]: " + String(str)); } /** * Print error message */ void printError(enum CamErr err) { Serial.print("[MAIN][CAM]: Error: "); switch (err) { case CAM_ERR_NO_DEVICE: Serial.println("No Device"); break; case CAM_ERR_ILLEGAL_DEVERR: Serial.println("Illegal device error"); break; case CAM_ERR_ALREADY_INITIALIZED: Serial.println("Already initialized"); break; case CAM_ERR_NOT_INITIALIZED: Serial.println("Not initialized"); break; case CAM_ERR_NOT_STILL_INITIALIZED: Serial.println("Still picture not initialized"); break; case CAM_ERR_CANT_CREATE_THREAD: Serial.println("Failed to create thread"); break; case CAM_ERR_INVALID_PARAM: Serial.println("Invalid parameter"); break; case CAM_ERR_NO_MEMORY: Serial.println("No memory"); break; case CAM_ERR_USR_INUSED: Serial.println("Buffer already in use"); break; case CAM_ERR_NOT_PERMITTED: Serial.println("Operation not permitted"); break; default: break; } } // /** // * Callback from Camera library when video frame is captured. // */ // void CamCB(CamImage img) { // /* Check the img instance is available or not. */ // if (img.isAvailable()) { // /* If you want RGB565 data, convert image data format to RGB565 */ // img.convertPixFormat(CAM_IMAGE_PIX_FMT_RGB565); // /* You can use image data directly by using getImgSize() and getImgBuff(). // * for displaying image to a display, etc. */ // Serial.print("Image data size = "); // Serial.print(img.getImgSize(), DEC); // Serial.print(" , "); // Serial.print("buff addr = "); // Serial.print((unsigned long) img.getImgBuff(), HEX); // Serial.println(""); // } else { // Serial.println("Failed to get video stream image"); // } // } void CAM_CHECK(CamErr err, const char *str) { // CameraConsolePrintln("setting " + str); char opt[64] = {0}; sprintf(opt, "setting %s", str); CameraConsolePrintln(opt); if (err != CAM_ERR_SUCCESS) { printError(err); } } // /* Camera Setting */ // CAM_CHECK(theCamera.setAutoWhiteBalance(false), "Auto White Balance"); // CAM_CHECK(theCamera.setAutoWhiteBalanceMode(CAM_WHITE_BALANCE_DAYLIGHT), "Auto White Balance Mode"); // CAM_CHECK(theCamera.setAutoExposure(true), "Auto Exposure"); // CAM_CHECK(theCamera.setAbsoluteExposure(1000), "Absolute Exposure"); // CAM_CHECK(theCamera.setAutoISOSensitive(true), "Auto ISO Sensitive"); // CAM_CHECK(theCamera.setISOSensitivity(CAM_ISO_SENSITIVITY_100), "ISO Sensitive"); // CAM_CHECK(theCamera.setColorEffect(CAM_COLOR_FX_VIVID), "Color Effect"); // CAM_CHECK(theCamera.setHDR(CAM_HDR_MODE_AUTO), "HDR"); // CAM_CHECK(theCamera.setJPEGQuality(100), "JPEG Quality"); void callSetAutoWhiteBalance(bool val) { CAM_CHECK(theCamera.setAutoWhiteBalance(val), "Auto White Balance"); }; void callSetAutoWhiteBalanceMode(CAM_WHITE_BALANCE val) { CAM_CHECK(theCamera.setAutoWhiteBalanceMode(val), "Auto White Balance Mode"); }; void callSetAutoExposure(bool val) { CAM_CHECK(theCamera.setAutoExposure(val), "Auto Exposure"); }; void callSetAbsoluteExposure(int val) { CAM_CHECK(theCamera.setAbsoluteExposure(val), "Absolute Exposure"); }; void callSetAutoISOSensitive(bool val) { CAM_CHECK(theCamera.setAutoISOSensitive(val), "Auto ISO Sensitive"); }; void callSetISOSensitivity(int val) { CAM_CHECK(theCamera.setISOSensitivity(val), "ISO Sensitive"); }; void callSetColorEffect(CAM_COLOR_FX val) { CAM_CHECK(theCamera.setColorEffect(val), "Color Effect"); }; void callSetHDR(CAM_HDR_MODE val) { CAM_CHECK(theCamera.setHDR(val), "HDR"); }; int32_t callGetAbsoluteExposure() { return theCamera.getAbsoluteExposure(); }; CAM_DEVICE_TYPE callGetDeviceType() { return theCamera.getDeviceType(); }; inline int callGetFd() { return theCamera.getFd(); }; int callGetFrameInterval() { return theCamera.getFrameInterval(); }; CAM_HDR_MODE callGetHDR() { return theCamera.getHDR(); }; int callGetISOSensitivity() { return theCamera.getISOSensitivity(); }; int callGetJPEGQuality() { return theCamera.getJPEGQuality(); }; /** * @brief Initialize camera */ void camera_setup() { CamErr err; /* Initialize SD */ while (!theSD.begin()) { /* wait until SD card is mounted. */ CameraConsolePrintln("Insert SD card."); } /* begin() without parameters means that * number of buffers = 1, 30FPS, QVGA, YUV 4:2:2 format */ CameraConsolePrintln("Prepare camera"); // err = theCamera.begin(1, CAM_VIDEO_FPS_5, CAM_IMGSIZE_QVGA_H, CAM_IMGSIZE_QVGA_V, CAM_IMAGE_PIX_FMT_JPG); err = theCamera.begin(); if (err != CAM_ERR_SUCCESS) { printError(err); exit(1); } /* Start video stream. * If received video stream data from camera device, * camera library call CamCB. */ // Serial.println("Start streaming"); // err = theCamera.startStreaming(false, NULL); // if (err != CAM_ERR_SUCCESS) // { // printError(err); // } CAM_CHECK(theCamera.setISOSensitivity(CAM_ISO_SENSITIVITY_100), "ISO Sensitive"); /* Set still picture format */ CameraConsolePrintln("Set still picture format"); err = theCamera.setStillPictureImageFormat(CAM_IMGSIZE_QUADVGA_H, CAM_IMGSIZE_QUADVGA_V, CAM_IMAGE_PIX_FMT_JPG, 3); if (err != CAM_ERR_SUCCESS) { printError(err); exit(1); } digitalWrite(LED0, HIGH); // turn the LED on } void takePic() { /* Take still picture. * Unlike video stream(startStreaming) , this API wait to receive image data * from camera device. */ CameraConsolePrintln("call takePicture()"); CamImage img = theCamera.takePicture(); /* Check availability of the img instance. */ /* If any errors occur, the img is not available. */ if (img.isAvailable()) { /* Create file name */ char filename[16] = {0}; sprintf(filename, "PICT%03d.JPG", take_picture_count); // Serial.print("Save taken picture as "); // Serial.print(filename); // Serial.println(""); char str[64]; sprintf(str, "Save taken picture as %s", filename); CameraConsolePrintln(str); /* Remove the old file with the same file name as new created file, * and create new file. */ theSD.remove(filename); File myFile = theSD.open(filename, FILE_WRITE); myFile.write(img.getImgBuff(), img.getImgSize()); myFile.close(); } else { /* The size of a picture may exceed the allocated memory size. * Then, allocate the larger memory size and/or decrease the size of a picture. * [How to allocate the larger memory] * - Decrease jpgbufsize_divisor specified by setStillPictureImageFormat() * - Increase the Memory size from Arduino IDE tools Menu * [How to decrease the size of a picture] * - Decrease the JPEG quality by setJPEGQuality() */ Serial.println("Failed to take picture"); } take_picture_count++; }

mycam.h

#ifndef __MYCAM_H__ #define __MYCAM_H__ #include <Arduino.h> #include <SDHCI.h> #include <stdio.h> /* for sprintf */ #include <Camera.h> void printError(enum CamErr err); void camera_setup(); void takePic(); void CAM_CHECK(CamErr err, const char *str); // Callback void callSetAutoWhiteBalance(bool val); // subCommand ID is "0" void callSetAutoWhiteBalanceMode(CAM_WHITE_BALANCE val); // subCommand ID is "1" void callSetAutoExposure(bool val); // subCommand ID is "2" void callSetAbsoluteExposure(int val); // subCommand ID is "3" void callSetAutoISOSensitive(bool val); // subCommand ID is "4" void callSetISOSensitivity(int val); // subCommand ID is "5" void callSetColorEffect(CAM_COLOR_FX val); // subCommand ID is "6" void callSetHDR(CAM_HDR_MODE val); // subCommand ID is "7" int32_t callGetAbsoluteExposure(); // subCommand ID is "0" CAM_DEVICE_TYPE callGetDeviceType() ; // subCommand ID is "1" inline int callGetFd() ; // subCommand ID is "2" int callGetFrameInterval() ; // subCommand ID is "3" CAM_HDR_MODE callGetHDR() ; // subCommand ID is "4" int callGetISOSensitivity() ; // subCommand ID is "5" int callGetJPEGQuality() ; // subCommand ID is "6" #endif // __MYCAM_H__

mylte.cpp

#include "mylte.h" // initialize the library instance LTE lteAccess; LTEClient client; MqttClient mqttClient(client); String readFromSerial() { /* Read String from serial monitor */ String str; int read_byte = 0; while (true) { if (Serial.available() > 0) { read_byte = Serial.read(); if (read_byte == '\n' || read_byte == '\r') { Serial.println(""); break; } Serial.print((char)read_byte); str += (char)read_byte; } } return str; } void readApnInformation(char apn[], LTENetworkAuthType *authtype, char user_name[], char password[]) { /* Set APN parameter to arguments from readFromSerial() */ String read_buf; while (strlen(apn) == 0) { Serial.print("Enter Access Point Name:"); readFromSerial().toCharArray(apn, LTE_NET_APN_MAXLEN); } while (true) { Serial.print("Enter APN authentication type(CHAP, PAP, NONE):"); read_buf = readFromSerial(); if (read_buf.equals("NONE") == true) { *authtype = LTE_NET_AUTHTYPE_NONE; } else if (read_buf.equals("PAP") == true) { *authtype = LTE_NET_AUTHTYPE_PAP; } else if (read_buf.equals("CHAP") == true) { *authtype = LTE_NET_AUTHTYPE_CHAP; } else { /* No match authtype */ Serial.println("No match authtype. type at CHAP, PAP, NONE."); continue; } break; } if (*authtype != LTE_NET_AUTHTYPE_NONE) { while (strlen(user_name)== 0) { Serial.print("Enter username:"); readFromSerial().toCharArray(user_name, LTE_NET_USER_MAXLEN); } while (strlen(password) == 0) { Serial.print("Enter password:"); readFromSerial().toCharArray(password, LTE_NET_PASSWORD_MAXLEN); } } return; } void lte_setup() { char apn[LTE_NET_APN_MAXLEN] = APP_LTE_APN; LTENetworkAuthType authtype = APP_LTE_AUTH_TYPE; char user_name[LTE_NET_USER_MAXLEN] = APP_LTE_USER_NAME; char password[LTE_NET_PASSWORD_MAXLEN] = APP_LTE_PASSWORD; Serial.println("Starting web client."); /* Set if Access Point Name is empty */ if (strlen(APP_LTE_APN) == 0) { Serial.println("This sketch doesn't have a APN information."); readApnInformation(apn, &authtype, user_name, password); } Serial.println("=========== APN information ==========="); Serial.print("Access Point Name : "); Serial.println(apn); Serial.print("Authentication Type: "); Serial.println(authtype == LTE_NET_AUTHTYPE_CHAP ? "CHAP" : authtype == LTE_NET_AUTHTYPE_NONE ? "NONE" : "PAP"); if (authtype != LTE_NET_AUTHTYPE_NONE) { Serial.print("User Name : "); Serial.println(user_name); Serial.print("Password : "); Serial.println(password); } while (true) { /* Power on the modem and Enable the radio function. */ if (lteAccess.begin() != LTE_SEARCHING) { Serial.println("Could not transition to LTE_SEARCHING."); Serial.println("Please check the status of the LTE board."); for (;;) { sleep(1); } } /* The connection process to the APN will start. * If the synchronous parameter is false, * the return value will be returned when the connection process is started. */ if (lteAccess.attach(APP_LTE_RAT, apn, user_name, password, authtype, APP_LTE_IP_TYPE) == LTE_READY) { Serial.println("attach succeeded."); break; } /* If the following logs occur frequently, one of the following might be a cause: * - APN settings are incorrect * - SIM is not inserted correctly * - If you have specified LTE_NET_RAT_NBIOT for APP_LTE_RAT, * your LTE board may not support it. * - Rejected from LTE network */ Serial.println("An error has occurred. Shutdown and retry the network attach process after 1 second."); lteAccess.shutdown(); sleep(1); } ledOn(LED2); } void mqtt_setup() { Serial.print("Attempting to connect to the MQTT broker: "); Serial.println(MQTT_SRVR); if (!mqttClient.connect(MQTT_SRVR, MQTT_PORT)) { Serial.print("MQTT connection failed! Error code = "); Serial.println(mqttClient.connectError()); while (1); } Serial.println("You're connected to the MQTT broker!"); Serial.println(); Serial.print("Subscribing to topic: "); Serial.println(MQTT_REQ); Serial.println(); // subscribe to a topic mqttClient.subscribe(MQTT_REQ); // topics can be unsubscribed using: // mqttClient.unsubscribe(topic); Serial.print("Waiting for messages on topic: "); Serial.println(MQTT_REQ); Serial.println(); } String mqtt_loop() { int messageSize = mqttClient.parseMessage(); if (messageSize) { // we received a message, print out the topic and contents Serial.print("Received a message with topic '"); Serial.print(mqttClient.messageTopic()); Serial.print("', length "); Serial.print(messageSize); Serial.print(" bytes: "); // use the Stream interface to print the contents String mystring; while (mqttClient.available()) { mystring += (char)mqttClient.read(); } Serial.print(mystring); Serial.println(); return mystring; } return ""; }

mylte.h

#ifndef __MYLTE_H__ #define __MYLTE_H__ #include <Arduino.h> #include <LTE.h> #include <ArduinoMqttClient.h> #include "config.h" // APN name #define APP_LTE_APN "povo.jp" // replace your APN /* APN authentication settings * Ignore these parameters when setting LTE_NET_AUTHTYPE_NONE. */ #define APP_LTE_USER_NAME "" // replace with your username #define APP_LTE_PASSWORD "" // replace with your password // APN IP type #define APP_LTE_IP_TYPE (LTE_NET_IPTYPE_V4V6) // IP : IPv4v6 // #define APP_LTE_IP_TYPE (LTE_NET_IPTYPE_V4) // IP : IPv4 // #define APP_LTE_IP_TYPE (LTE_NET_IPTYPE_V6) // IP : IPv6 // APN authentication type #define APP_LTE_AUTH_TYPE (LTE_NET_AUTHTYPE_CHAP) // Authentication : CHAP // #define APP_LTE_AUTH_TYPE (LTE_NET_AUTHTYPE_PAP) // Authentication : PAP // #define APP_LTE_AUTH_TYPE (LTE_NET_AUTHTYPE_NONE) // Authentication : NONE /* RAT to use * Refer to the cellular carriers information * to find out which RAT your SIM supports. * The RAT set on the modem can be checked with LTEModemVerification::getRAT(). */ #define APP_LTE_RAT (LTE_NET_RAT_CATM) // RAT : LTE-M (LTE Cat-M1) // #define APP_LTE_RAT (LTE_NET_RAT_NBIOT) // RAT : NB-IoT String readFromSerial(); void readApnInformation(char apn[], LTENetworkAuthType *authtype, char user_name[], char password[]); void lte_setup(); void mqtt_setup(); String mqtt_loop(); #endif // __MYLTE_H__

<Change Me> を正しく変更した上、platformioでENVを

  • spresense_mainCore-lte
  • spresense_mainCore-wifi

どちらかに変更すると動作します。

試すMQTT Client

main.py

# python 3.6 import random import time from paho.mqtt import client as mqtt_client broker = '<Change Me>' port = 1883 topic = "<Change Me>" client_id = f'publish-{random.randint(0, 1000)}' def connect_mqtt(): def on_connect(client, userdata, flags, rc): if rc == 0: print("Connected to MQTT Broker!") else: print("Failed to connect, return code %d\n", rc) client = mqtt_client.Client(mqtt_client.CallbackAPIVersion.VERSION1, client_id) client.on_connect = on_connect client.connect(broker, port) return client def publish(client): msg_count = 1 while True: time.sleep(1) msg = f"0" result = client.publish(topic, msg) status = result[0] if status == 0: print(f"Send `{msg}` to topic `{topic}`") else: print(f"Failed to send message to topic {topic}") msg_count += 1 print("This is loop: ", msg_count) def run(): client = connect_mqtt() client.loop_start() publish(client) client.loop_stop() if __name__ == '__main__': run()

最後に

Spresense は複数コアがあり、最初はびっくりしました。色々知らない機能を試して面白いです。
LTEも今回初めて触りましたけど、便利だなと思いました、これからSpresenseを使って面白いものを作りたいです。

また、SonyのLibraryはとてもわかりやすくて開発者に感謝です。

ログインしてコメントを投稿する