

SDカードにあるファイルには1行ずつ値が入っており、その値を割り込み関数内にある `val` に代入してモータを回転させたいです。  
ファイルには `1500, 2500, 500...` と1行ずつ入っていて、`val` に代入されるとそれぞれ`1.5s, 2.5s, 0.5s...`
おきにモーターを回転させます。

しかし、今の動きはファイルにある最後の数 1500 が `val` に入って 1.5s おきに回転してしまいます。

setup内に書かれているファイルの読み取りコードこれを1行ずつ `val` に値入れたらその都度回せるようにしたいです。  
スケッチの改善点あれば教えていただきたいです。  
よろしくお願いします。

[code]

    #include<SD.h>
    #include<SPI.h>
    
    int APHASE=2;
    int AENBL=3;
    int BPHASE=6;
    int BENBL=7;
    volatile int count=0;           // LED用のカウンター
    volatile int RotCounter=0;      // 現在の回転角(0,1,2,3)
    volatile int TimeDivCounter=0;  // 割り込みのカウンター用
    volatile int datacount=0;       // データ用のカウンター
    volatile int val;
    
    ISR(TIMER1_COMPA_vect){         // 1ms(0.001s)で読みだす
        // 18度回転の処理
        if(TimeDivCounter==val){    // ==のあとの数字はSDの値
            switch(RotCounter){
                case 0:
                    digitalWrite(APHASE, LOW);
                    digitalWrite(AENBL, HIGH);
                    digitalWrite(BPHASE, LOW);
                    digitalWrite(BENBL, HIGH);
                    break;
                case 1:
                    digitalWrite(APHASE, HIGH);
                    digitalWrite(AENBL, HIGH);
                    digitalWrite(BPHASE, LOW);
                    digitalWrite(BENBL, HIGH);
                    break;
                case 2:
                    digitalWrite(APHASE, HIGH);
                    digitalWrite(AENBL, HIGH);
                    digitalWrite(BPHASE, HIGH);
                    digitalWrite(BENBL, HIGH);
                    break;
                case 3:
                    digitalWrite(APHASE, LOW);
                    digitalWrite(AENBL, HIGH);
                    digitalWrite(BPHASE, HIGH);
                    digitalWrite(BENBL, HIGH);
                    break;
            }
            RotCounter++;
    
            if(RotCounter>=4){
                RotCounter=0;
            }
            TimeDivCounter=0;
        }else{
            TimeDivCounter++;
        }
    }
    
    void setup() {
        pinMode(APHASE,OUTPUT);
        pinMode(AENBL,OUTPUT);
        pinMode(BPHASE,OUTPUT);
        pinMode(BENBL,OUTPUT);
        digitalWrite(AENBL,HIGH);
        digitalWrite(BENBL,HIGH);
    
        Serial.begin(9600);
        while (!Serial) {
            ;
        }
        Serial.println("SDカードの初期化");
    
        if (!SD.begin(4)) {
            Serial.println("初期化に失敗");
            while(1);
        }
        Serial.println("初期化完了");
    
        File dataFile = SD.open("data.txt");
        if(dataFile){
            char buffer[65];
    
            while(dataFile.available()){
                int length=dataFile.available();
    
                if(length>64){
                    length=64;
                }
    
                dataFile.read(buffer,length);
                buffer[length]='\0';
                Serial.write(buffer,length);
                val=atoi(buffer);
            }
            dataFile.close();
        }else{
            Serial.println(F("error opening data.txt"));
        }
    
        DDRB=0b00000100;
        TCCR1A = 0b00000010;
        TCCR1B = 0b00000011;
        TIMSK1 = 0b00000010;
        OCR1A = 249;
    }
    
    void loop(){
    }
    
[/code]


CC BY-SA 4.0
2020-09-14T17:22:16.027
70391
2020-09-15T03:40:26.870
2020-09-15T01:43:30.783
3060
question
c++ c arduino
ファイルから読み取った値を元にモーターの回転を制御したい


setup関数は最初に１度だけ実行されるのですから、「1行ずつvalに値入れたらその都度」という動作をsetup関数に書くのは不適切です(１度きりの動作に、その都度はありえない）。

繰り返し実行されるloop関数の中に、「valに値をいれて、その時間だけモーターを回す」というコードを移したら良いです。


CC BY-SA 4.0
2020-09-15T01:35:56.480
70400
2020-09-15T01:35:56.480
217
70391
answer


組み込み系の基礎知識として

  * 初期化処理を１回だけして （提示 `setup()` が相当）
  * メインループをぐるぐるまわって終わることは無い `loop()`
  * 割り込み処理は最短で終わらせないと破綻する `ISR()`

提示プログラムはこの鉄則を守っていないので期待通りに動かなくて当然・ではどう直すかの方針だけ提示

  * 割り込み処理の中でファイル内容を使いたい
  * が、割り込み内でファイルを読むのは処理時間的に論外
  * ファイル内容を事前に読み込んでおき割り込み内ではメモリ上のデータを使う
  * 事前の処理のための関数が `setup()`
  * ついでに言うとメモリは有限

ということで、やるべきは

  * 秒数を保持するテーブルを作る (要素は有限個数になるだろう）
  * `setup()` で値を読んでテーブルに記憶しておく（読んだ要素数も必要：ファイル内容が多かったらどうするかを仕様策定する必要がある）
  * `ISR()` でそのテーブルの値を１つ１つ使う
  * どこまで使ったかのインジケータが別途必要だろう（読んだ要素数と別に）
  * 読み込んだ個数を使い切ったらどうするかを仕様策定する必要がある

のではないかなー、ということで改善点の提案とします。


CC BY-SA 4.0
2020-09-15T03:40:26.870
70402
2020-09-15T03:40:26.870
8589
70391
answer