質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

2回答

5336閲覧

Arduinoのファイル読み取りについて

退会済みユーザー

退会済みユーザー

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

0クリップ

投稿2020/09/13 20:29

編集2020/09/15 12:59
#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(){ }

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

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

ご意見を頂き、ファイル内容を配列に格納してみるやり方でやってみました。まだ動作を見た感じ、最後の値のみでしか回転させていなかったです。

#include<SD.h> #include<SPI.h> int APHASE=2; //AIN1へ接続 int AENBL=3; //AIN2へ接続 int BPHASE=6; //BIN1へ接続 int BENBL=7; //BIN2へ接続 volatile int count=0; //LED用のカウンター volatile int RotCounter=0; //現在の回転角(0,1,2,3) volatile int TimeDivCounter=0; //割り込みのカウンター用 volatile int datacount=0; //データ用のカウンター volatile int num[5]; ISR(TIMER1_COMPA_vect){ //1ms(0.001s)で読みだす //18度回転の処理 int i=0; if(TimeDivCounter==0){//==のあとの数字は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; i++; if(i>=6){ i=5; } }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 s; String d; int i=0; while(dataFile.available()){ s=dataFile.read(); if(s=='\r'){//もし改行が来たら d.trim(); //空白文字を取り除く num[i]=d.toInt(); //整数に変換 Serial.println(num[i]); i++; d=""; }else{ d+=s; } } dataFile.close(); }else{ Serial.println(F("error opening data.txt")); } TCCR1A = 0b00000010; TCCR1B = 0b00000011; TIMSK1 = 0b00000010; OCR1A = 24; } void loop(){ }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2020/09/13 21:41

コードを提示しましょう で、現状のコードではどういう不具合があるんでしょうか
退会済みユーザー

退会済みユーザー

2020/09/14 12:19 編集

ファイルからvalに値は入っていますが、ファイルには1500,2500,500...と1行ずつ入っていてvalに順に代入されるんですけど、今の動きというのがファイルにある最後の数1500がvalに入って1.5sおきに回転してしまいます。結局モータ動かす際はファイルの最後の数値のみvalに入ってそれが繰り返される仕様になってしまっているので、最後の値だけではなく、valに値が入ったら回せるようにしたいです。
thkana

2020/09/14 11:56

そのぐらいのコードなら質問に貼り付けられるのではないかと思いますが、出来ませんでしたか? というか、質問内のURLに貼り付けられているコードと違いますね? 「本当のところ」を見せて下さい。
退会済みユーザー

退会済みユーザー

2020/09/14 12:11

質問してからも考えているので直近のコードがURLじゃないコードとなりそれを貼り付けました。URLのコードで修正しておきました。 URL云々よりもコードについて聞いているのですが、、そもそも登録したばかりでこれが初めての質問でURLでもいいのかなと思って貼り付けました。URLよりもコード貼り付けろってことですね
y_waiwai

2020/09/14 12:14

質問を編集し、<code>ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください
退会済みユーザー

退会済みユーザー

2020/09/14 12:17

教えていただきありがとうございます。助かります。これで見えてますでしょうか?
thkana

2020/09/14 22:53

「そもそも登録したばかり」で書き込もうとするなら、どのようにするのか ヘルプ https://teratail.com/help には一通り目を通されたと思います。よそのサイトに貼り付けてURLを示すというようなことは出てこなくて、コードをこのように処置して提示しましょう、というような説明があったでしょう。 あなたの問題を解決することもですが、あとから同様の問題に突き当たったひとの解決に役立つ、というのもこのサイトの目的のひとつのようです。その意味で、他所のサイトに情報が分散していては、リンク切れなどで参照出来なくなるとその目的が果たせなくなってしまいます。
ozwk

2020/09/17 00:30

ファイル読み込みはひとまず置いておいて、 そもそも配列に予め定数でデータを入れておいて、そのとおり動かす、ということは出来ますか?
guest

回答2

0

後半に上げている方のスケッチですけど、
SDの読み取りは出来ていそうな気はしますけど、その読みだした値をステッパーに渡していません。
なので、当然読み出した値とステッパーの動きに関連性はありません。

ステッパー部は単純にそこだけで動いています。

volatile int TimeDivCounter=0;
と初期値が0なので、
ISR(TIMER1_COMPA_vect){
if(TimeDivCounter==0){
//モータ1パルス分回転
TimeDivCounter=0;
}
}
のような感じで、割り込みに入れば必ず1ステップ動きます。
1.5秒は単に、タイマー割り込み自体がそのようになっているのでしょう。
つまり、タイマー割り込みのセット(レジスタ値)も間違えています。

更に言えば、SDを読みだして、閉じてからタイマー割り込みをセットしています。
当然、SDからデータの読み出し→ステッパーの動作→次のデータの読み出し→ステッパー動作→
みたいな動きになるはずもありません。

投稿2020/09/16 19:48

nac_tnk

総合スコア463

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

そのプログラムでは、
ファイルから64文字ずつ読み込んで、valに設定し、最後に読み込めたところで読み込みのループを抜けるようになっています。なので、ループを抜けた時点ではvalは一番最後に取得出来た値になっています。64文字ずつ取得しているので行の途中で切れたりする場合もあるでしょうが、とりあえず最後の1500が取得出来たのでしょう。
その後は、valの値は更新される機会はありません。

改善というよりは作り直しに近くなるかもしれませんが、
なによりもまず一行ずつのデータを取り出すようにすること、
そのあとは方針はいくつか考えられますが、
・(多分試みられていたように)最初にファイルからのデータを全部取り出して配列に格納しておいて順次使用する
・モータの動作が一回分終わったら次のデータを読み出して使用する
などでいかがでしょう。

投稿2020/09/14 23:03

thkana

総合スコア7629

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/09/15 05:27

回答ありがとうございます。 提案してくれた方針で一度、(多分試みられていたように)最初にファイルからのデータを全部取り出して配列に格納しておいて順次使用する というのをやってみたのですが動作からして思うように動いてくれなくて、コードはここで掲示していいのですか?
thkana

2020/09/15 12:24

コメント欄だとインデントが失われたり、そもそも他の人が話を追いにくくなるので、質問に「その後試したこと」として追記するのがベターかと思います。
退会済みユーザー

退会済みユーザー

2020/09/15 13:00

ありがとうございます、改善後のコードを貼り付けたのでよろしくお願いします
thkana

2020/09/15 22:34

最終結果が思い通りでなかったら「思うように動いてくれない」でまとめてしまわないで、一つ一つの段階をふんで確認してください。 データの読み取り途中でせっかくSerialを埋め込んで情報を表示しているので、そこをチェックしてみましょう。そこではどういう表示が得られましたか? 「まとめず、略さず、見たまま」を教えて下さい(よほど大量のデータなら先頭部分とかでもいいですけれど、今回はそういうことはないですね?)。それは期待するものでしょうか。であれば、次の段階に行きましょう。
退会済みユーザー

退会済みユーザー

2020/09/16 18:37 編集

Serial.println(num[i])でみてみましたが、num[0]=1500,num[1]=2500,num[2]=500がえられました。データの個数自体は今4つしかなくて本来ならnum[3]=1500が入るはずですが、num[3]以降は0が入ってました。 動作は最後の値ではなく、初期値int=0より、num[0]に入っている値1500で1.5s毎にずっと動いています。初期値をint=2にしたときも、num[2]に入っている500より0.5s毎にずっと動いていました。 iの初期値をグローバル変数で定義し、Serial.println(num[i])をif(TimeDivCounter){のあとに書いて確認したところ、順に値は入っていることが分かりましたが、モータの動きというのがnum[0]とnum[1]の動きはされず、num[3]の動きが行われました。
thkana

2020/09/16 22:38

> 本来ならnum[3]=1500が入るはずですが、num[3]以降は0が入ってました。 それでいいのですか? よくないなら、なぜそれを解決する前に次の話を始めてしまうのでしょう? 配列numの要素は、ファイルから読み出すところ以外には登場していません。 > 動作は最後の値ではなく、初期値int=0より、num[0]に入っている値1500で1.5s毎にずっと動いています。初期値をint=2にしたときも、num[2]に入っている500より0.5s毎にずっと動いていました。 となる要素はないように思いますが、なにか論理的な説明が出来ますか?(あなたが作ったプログラムなら、なにか言えるでしょう) > num[3]の動きが行われました。 num[3]は0だったのでは? それとも、ファイルから読みだした直後は0だったnum[3]に1500が"湧いてきた"のでしょうか? それと、割り込みルーチン内でSerialは使わない方がいいと思います。Serial自身が割り込みを使うので、ややこしいことになりかねません。 なんだか、質問とはまた違うプログラムをいじっているような気がしてなりませんが、そんなことはないですか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問