

周期的にADC値を読む方法について教えてください。  
Arduino IDEで開発を行っています。

### やりたいこと

10msec毎にSpresence標準搭載のアナログ入力専用ピンの電圧値を読み出したい。  
(Spresenceホームページ記載の"1.1.12. attachTimerInterrupt()"の項目から  
割り込み関数内から呼び出し可能な API には制限があり、analogRead()ができないことは確認済みです。）

タイマー割込みに登録した関数から直接analogRead()を行うとエラーが出るが、他の関数を介してanalogRead()を呼べば、正常にアナログ値を読み取れるのではないかと考えた。タイマー割込みから外部割り込み（IOピンをショート）を経由して、analogRead()を呼んでみようと考え、下記のプログラムを作成しました。（一部抜粋）

開発ソフトウェアでは、T2_TIMEを10msecに相当する値に変更して実装する予定です。  
ADCの速度について.configファイルから256Hzに変更済みです。  
外付けのADCをつける等も考えられるのですが、Spresence単体で行いたいです。

[code]

    #include <Arduino.h>
    
    #define T2_TIME       5000000                   // Timer割り込み 5[s]
    #define BAUDRATE_Debug  115200              // Debug Baud rate of UART in bps
    HardwareSerial UARTDebug = Serial;    //DebugSerialのUART割当て
    void setup() {
      // put your setup code here, to run once:
      UARTDebug.begin(BAUDRATE_Debug,SERIAL_8N1);
      pinMode(02, OUTPUT);
      digitalWrite(02, LOW);
      pinMode(40, INPUT);
      //40番ピン,関数,立ち上がり
      attachInterrupt(40,Ext_ISR,RISING);
      attachTimerInterrupt(timer_ISR, T2_TIME); //タイマー割り込み
      UARTDebug.println("SetUpEnd");
    }
    void loop() {
      // put your main code here, to run repeatedly:
    }
    uint timer_ISR(void) {
      UARTDebug.println("Timer_ISR");
      digitalWrite(02,HIGH);
      return T2_TIME;
    }
    void Ext_ISR(void)
    {
      UARTDebug.println("Ext_ISR");
      digitalWrite(02, LOW);
      int sensor_v = analogRead(A3) & 0x3ff;
      UARTDebug.prinGAItf("%d\n",sensor_v);
    }
    
[/code]

### 結果

Arduino IDEのシリアルモニタの出力

[code]

    11:37:29.648 -> SetUpEnd
    11:37:34.665 -> Timer_ISR
    11:37:34.665 -> Ext_ISR
    11:37:34.665 -> read failed:9
    11:37:39.652 -> Timer_ISR
    11:37:39.652 -> Ext_ISR
    
[/code]

### 備考

外部割り込みからanalogRead()を呼べるか疑問に思ったため、追加で確認しました。結果は似たようなものになりました。

### ソースコード

[code]

    #include <Arduino.h>
    
    #define T2_TIME       5000000                   // Timer割り込み 5[s]
    #define BAUDRATE_Debug  115200              // Debug Baud rate of UART in bps
    
    HardwareSerial UARTDebug = Serial;    //DebugSerialのUART割当て
    
    void setup() {
      // put your setup code here, to run once:
      UARTDebug.begin(BAUDRATE_Debug,SERIAL_8N1);
      pinMode(02, OUTPUT);
      digitalWrite(02, LOW);
      pinMode(40, INPUT);
      //40番ピン,関数,立ち上がり
      attachInterrupt(40,Ext_ISR,RISING);
      UARTDebug.println("SetUpEnd");
    }
    
    
    void loop() {
      // put your main code here, to run repeatedly:
      delay(5000);
      digitalWrite(02, HIGH);
    }
    
    
    
    void Ext_ISR(void)
    {
      UARTDebug.println("Ext_ISR");
      digitalWrite(02, LOW);
      int sensor_v = analogRead(A3) & 0x3ff;
      UARTDebug.printf("%d\n",sensor_v);
    }
    
[/code]

### シリアルモニタ

[code]

    11:48:41.653 -> SetUpEnd
    11:48:46.642 -> Ext_ISR
    11:48:46.676 -> read failed:9
    11:48:51.658 -> Ext_ISR
    11:48:56.701 -> Ext_ISR
    
[/code]


CC BY-SA 4.0
2023-08-02T03:00:13.437
95825
2023-08-03T00:52:32.567
2023-08-02T06:28:31.980
59351
59351
question
spresense
Spresenceで周期的にADCを読み込む方法は？


[こちらに回答](https://ja.stackoverflow.com/questions/85512/spresense%E3%81%AB%E3%81%A6-attachtimerinrerrupt%E3%81%A8ads1115%E3%81%AE%E4%BD%B5%E7%94%A8%E6%99%82%E3%81%AB%E7%99%BA%E7%94%9F%E3%81%99%E3%82%8Bhard-
fault%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/85517#85517)がありますが、どうも割り込みルーチンの中で
analogRead
は使えないみたいなんですよねェ。簡単な例ではありますが、私は次のようにして回避しました。高度な回避方法の例もリンク先にあります。ご参考まで。

[code]

    #define TIMER_INTERVAL 1000000
    bool isTimerFired = false;
    
    uint32_t fire() {
      isTimerFired = true;
      return TIMER_INTERVAL;
    }
    
    void setup() {
      Serial.begin(115200);
      attachTimerInterrupt(fire, TIMER_INTERVAL); // 1sec
    }
    
    void loop() {
      if (isTimerFired) {
        int val = analogRead(A2);
        Serial.println("A2:" + String(val));
        isTimerFired = false;
      }
      delayMicroseconds(100);
    }
    
[/code]


CC BY-SA 4.0
2023-08-03T00:52:32.567
95832
2023-08-03T00:52:32.567
27334
95825
answer