今更ながらSPRESENSEの消費電力調べてみた②

前回はこちら
- <a href="https://qiita.com/saya-reg/items/d124487c7a474bb3f8ad">今更ながらSPRESENSEの消費電力調べてみた①</a>

この記事はソニー製SPRESENSEの消費電力について実機測定した結果をまとめたものです(N数=1)

# メインボード + Cameraでの消費電力
## 条件(前回と同じ)
- USBではなくバッテリー供給口の方から5Vを入力
- メインボードのLEDは除去したものしかなかったので、それを使用(大体200μAくらい節電だった気がする)
- n数は1。端末依存って言われたらそれまでだけど、仕事柄数十台のSPRESENSEを扱っているので大体同じ感じな印象

### 結果だけ知りたい人向け
- カメラを付けただけなら、カメラ非搭載時と消費電力は変わらず
    - idle : 8mA
    - coldSleep : 1.3mA
    - deepSleep : 50μA
- 1枚撮影後
    - idle : 85mA
    - coldSleep : 7mA
    - deepSleep : 50μA
- CallBackによるストリーミング取得
    - idle：65mA

## ただ単純に接続しただけの場合
### 1. idle状態
- 電源投入直後
![メイン_カメラidle_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737064/2eca1394-8f47-539c-a9c6-c6e4dce4f540.png)

- 1分間平均
![メイン_カメラidle_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737064/eda251a1-4f0a-6e4b-c594-b7fe4c0f41a3.png)

### 2. coldsleep
- 電源投入直後
![メイン_カメラcoldS_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737064/eb775e30-e951-79d2-1399-66c80eddf299.png)


- 1分間平均
![メイン_カメラcoldS_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737064/ff564313-fa0d-cab3-6a93-a1b6a208e7ce.png)


- 検証ソースは前回と同じ

### 3. deepsleep
- 電源投入直後
![メイン_カメラdeepS_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737064/fd86e33f-2208-963b-5f75-39e991a570ce.png)


- 1分間平均
![メイン_カメラdeepS_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737064/c286ee84-5d1f-e545-faf1-917674608c2d.png)


- 検証ソースは前回と同じ

前回の非カメラ接続時と比較しても、誤差の範囲内ですね。
他のマイコンだとカメラを起動せずに接続しただけで1~2mA程度増えることもあるので、非常に優秀。

## カメラを起動して1枚撮影を実施した場合

### 1. 撮影後、idle状態
- 電源投入直後
![メイン_カメラ_撮影_idle_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737064/00ac7430-2028-4350-5d1c-9cbc1237ab05.png)

- 1分間平均
![メイン_カメラ_撮影_idle_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737064/25ee48ea-af47-099f-6228-4ee89d5a71b0.png)

- カメラ起動時
![メイン_カメラ_撮影_idle_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737064/cb09bbb7-891a-ff34-391b-f21e51827a50.png)

<details><summary>検証ソース</summary>

```cpp
#include <Camera.h>
#define BAUDRATE                (115200)

void printError(enum CamErr err)
{
    Serial.print("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;
        }
}


void setup()
{
    CamErr err;
    Serial.begin(BAUDRATE);
    while (!Serial){
        ; /* wait for serial port to connect. Needed for native USB port only */
        }
    
    Serial.println("Prepare camera");
    err = theCamera.begin();
    if (err != CAM_ERR_SUCCESS){
        printError(err);
        }
    
    Serial.println("Start streaming");
    
    Serial.println("Set Auto white balance parameter");
    err = theCamera.setAutoWhiteBalanceMode(CAM_WHITE_BALANCE_DAYLIGHT);
    if (err != CAM_ERR_SUCCESS){
        printError(err);
        }
    
    Serial.println("Set still picture format");
    err = theCamera.setStillPictureImageFormat(
        CAM_IMGSIZE_QUADVGA_H,
        CAM_IMGSIZE_QUADVGA_V,
        CAM_IMAGE_PIX_FMT_JPG);
    if (err != CAM_ERR_SUCCESS){
        printError(err);
        }
}

void loop()
{
    sleep(1); 
    Serial.println("call takePicture()");
    CamImage img = theCamera.takePicture();
    if (img.isAvailable()){
        Serial.print("Image data size = ");
        Serial.print(img.getImgSize(), DEC);
        while(true){
            ;
            }
        }
    else{
        Serial.println("Failed to take picture");
        }
}

```
    
</details>

カメラを起動すると当然ながら消費電力はいっきに100mA程度まで跳ね上がります。
分平均を見ると`85mA`となっているので、やはり撮影後そのまま何かしらの処理を行うとロスが大きそうです。

### 2. 撮影後、coldSleep
- 電源投入直後
![メイン_カメラ_撮影_coldS_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737064/ec826096-d8cf-75f8-1fa7-f965c0c055d4.png)


- 1分間平均
![メイン_カメラ_撮影_coldS_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737064/c4b8b1c8-1384-42ad-ea85-dc973de61541.png)


- カメラ起動時
![メイン_カメラ_撮影_coldS_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737064/18ffc983-0833-30ae-f5b9-f6c5113d54cf.png)


<details><summary>検証ソース</summary>

```cpp
#include <Camera.h>
#include <LowPower.h>
#define BAUDRATE                (115200)

void printError(enum CamErr err)
{
    Serial.print("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;
        }
}

void setup()
{
    CamErr err;
    Serial.begin(BAUDRATE);
    while (!Serial){
        ; /* wait for serial port to connect. Needed for native USB port only */
        }
    LowPower.begin();
    
    Serial.println("Prepare camera");
    err = theCamera.begin();
    if (err != CAM_ERR_SUCCESS){
        printError(err);
        }
    
    Serial.println("Start streaming");
    
    Serial.println("Set Auto white balance parameter");
    err = theCamera.setAutoWhiteBalanceMode(CAM_WHITE_BALANCE_DAYLIGHT);
    if (err != CAM_ERR_SUCCESS){
        printError(err);
        }
    
    Serial.println("Set still picture format");
    err = theCamera.setStillPictureImageFormat(
        CAM_IMGSIZE_QUADVGA_H,
        CAM_IMGSIZE_QUADVGA_V,
        CAM_IMAGE_PIX_FMT_JPG);
    if (err != CAM_ERR_SUCCESS){
        printError(err);
        }
}

void loop()
{
    sleep(1); 
    Serial.println("call takePicture()");
    CamImage img = theCamera.takePicture();
    if (img.isAvailable()){
        Serial.print("Image data size = ");
        Serial.print(img.getImgSize(), DEC);
        while(true){
            LowPower.deepSleep(70);
            }
        }
    else{
        Serial.println("Failed to take picture");
        }
}

```
    
</details>

分平均を見ると`6.54mA`と、無負荷時の`1.4mA`からはだいぶ増えています。
この状態ですと乾電池などで動くIoT端末としては無視できない電力消費かと思います。


### 2. 撮影後、deepSleep
- 電源投入直後
![メイン_カメラ_撮影_deepS_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737064/3e8eb5fe-9274-fb04-7b2c-0e7894ce4957.png)


- 1分間平均
![メイン_カメラ_撮影_deepS_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737064/693226bc-7b4c-a750-9f15-0f5fbe546c5c.png)


- カメラ起動時
![メイン_カメラ_撮影_deepS_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737064/10511b9d-31bf-a8a8-729b-6bd948a9a904.png)

- 検証ソース
    - coldSleepをdeepSleepにしただけ

本命のdeepSleepですが、分平均は無負荷時と同じ`47μA`と、かなりいい線いっています！
これならIoT端末にも使えそうですね！
※とはいっても、私が扱うLPWA系だと処理の関係上deepSleep不可とかいう制約もあったりするので、実はあんまり喜べなかったり・・・・・・

## カメラを起動してストリーミング撮影を実施した場合
### ストリーミング中
- 電源投入直後
![メイン_カメラ_撮影_streaming_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737064/2b9922f1-81fe-2947-e3fd-c76f25ad27e6.png)


- 1分間平均
![メイン_カメラ_撮影_streaming_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737064/3a1bb5bf-4000-dba4-5c86-62efa8266f43.png)

最後にcallBack関数を使用して裏で取得し続けた場合です。サンプルプログラムもこのタイプですね。
結果としては1枚撮影後idleの状態よりも消費電力は少なくなりました。誤差の範囲、というには20mAもあるので無視できない結果です。
このあたりcallBackと`takePicture()`の処理がもしかしたら何か関係しているかもしれないですね。

いかがだったでしょうか。
ぶっちゃけ私はcoldSleepでカメラを使っているので、思ったより省エネになっていないじゃん、と愕然としてます（焦）

次回は拡張ボードかESP32S3の電力調査をお届けする予定です。
ESP32S3は最近手に入れた<a href="https://wiki.seeedstudio.com/xiao_esp32s3_getting_started/">XIAO ESP32S3 (sense)</a>で計測したものとなります。

まぁ今扱っているからわかるんですが、とにかくカメラ回りが酷いのなんの（笑）
フォーラムでも結構ひどい言われ様だったりするのですが、しかしAIが搭載できたりSDカードよりも小さいといったメリットはどうにかデメリットを上回りそうです（笑）

でわでわ、良いマイコンライフを！