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
- platformio + arduino
- Wifi Libary: https://github.com/jittermaster/GS2200-WiFi.git
- SPI library
- arduino-libraries/ArduinoMqttClient@^0.1.8
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"
撮影
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はとてもわかりやすくて開発者に感謝です。
-
zhixuan
さんが
2025/01/11
に
編集
をしました。
(メッセージ: 初版)
-
zhixuan
さんが
2025/01/11
に
編集
をしました。
ログインしてコメントを投稿する