2ちゃんねる ■掲示板に戻る■ 全部 1- 最新50    

■ このスレッドは過去ログ倉庫に格納されています

Arduino初心者熱烈大歓迎質問スレ part38

1 :774ワット発電中さん:2024/03/05(火) 10:09:53.62 ID:Oo/qMtqC.net
http://www.arduino.cc/

【質問者心得】
・スレに一応目を通してから質問しましょう
・回答者はエスパーではありません。状況が分かるように詳しく書きましょう
 詳しく書いてくれないと、答える方も困ってしまいます。答えようがないのです
【回答者心得】
・すぐにググレカスと言う前に「○○でググれカス」って言うような大人の余裕を見せつけてやりましょう
・節度ある初心者さんには、特に優しくね

前スレ
Arduino初心者熱烈大歓迎質問スレ part35
https://rio2016.5ch.net/test/read.cgi/denki/1659965751/
Arduino初心者熱烈大歓迎質問スレ part36
https://rio2016.5ch.net/test/read.cgi/denki/1672830085/
Arduino初心者熱烈大歓迎質問スレ part37
https://rio2016.5ch.net/test/read.cgi/denki/1690554248/

過去スレ
Arduino初心者熱烈大歓迎質問スレ part33
https://rio2016.5ch.net/test/read.cgi/denki/1638841974/
Arduino初心者熱烈大歓迎質問スレ part32
https://rio2016.5ch.net/test/read.cgi/denki/1633840724/
Arduino初心者熱烈大歓迎質問スレ part31
https://rio2016.5ch.net/test/read.cgi/denki/1623898761/
Arduino初心者熱烈大歓迎質問スレ part30
https://rio2016.5ch.net/test/read.cgi/denki/1613577696/
Arduino初心者熱烈大歓迎質問スレ part29
http://rio2016.5ch.net/test/read.cgi/denki/1601349163/
Arduino初心者熱烈大歓迎質問スレ part28
https://rio2016.5ch.net/test/read.cgi/denki/1591734520/
Arduino初心者熱烈大歓迎質問スレ part27
http://rio2016.5ch.net/test/read.cgi/denki/1585316143/
Arduino初心者熱烈大歓迎質問スレ part26
http://rio2016.5ch.net/test/read.cgi/denki/1579146318/
Arduino初心者熱烈大歓迎質問スレ part25
http://rio2016.5ch.net/test/read.cgi/denki/1568358922/
Arduino初心者熱烈大歓迎質問スレ part24
http://rio2016.5ch.net/test/read.cgi/denki/1554776918/
Arduino初心者熱烈大歓迎質問スレ part23
http://rio2016.5ch.net/test/read.cgi/denki/1541233445/

952 :774ワット発電中さん:2024/07/18(木) 07:16:22.27 ID:VpRH8XE5.net
>>948
できました!!!!




void setup() {
Serial.begin(9600); // シリアル通信を9600ボーレートで開始
randomSeed(analogRead(0)); // アナログピン0から読み取った値でランダムシードを初期化

int array[8] = {1, 2, 3, 4, 5, 6, 7, 8}; // 1から8までの数字を格納した初期配列を宣言

// 配列をランダムに並び替える
for (int i = 0; i < 8; i++) { // 配列の各要素に対してループを実行
int r = random(0, 8); // 0から7までのランダムなインデックスを生成
// 配列のi番目の要素とランダムに選ばれたr番目の要素を交換
int temp = array[i]; // 一時変数tempに現在のi番目の要素を保存
array[i] = array[r]; // i番目の要素にr番目の要素を代入
array[r] = temp; // r番目の要素にtemp(一時変数)の値を代入
}

// ランダムに並び替えた配列をシリアルモニタに出力
for (int i = 0; i < 8; i++) { // 配列の各要素に対してループを実行
Serial.print(array[i]); // 配列の現在の要素をシリアルモニタに出力
Serial.print(" "); // 配列の各要素の間にスペースを挿入
}
}

void loop() {
// メインループは不要なため空のまま
}

953 :774ワット発電中さん:2024/07/18(木) 09:02:44.10 ID:6DUq6QZv.net
>>951
クラスにすればいいよね。

954 :774ワット発電中さん:2024/07/18(木) 12:08:31.57 ID:n4o4lIgC.net
>>953
イイね

955 :774ワット発電中さん:2024/07/18(木) 18:53:22.66 ID:dfwlIs+g.net
Arduinoプログラミングを本格的にやるなら
atmel-iceかpickit4を買うべきでしょうか?

956 :774ワット発電中さん:2024/07/18(木) 19:11:39.03 ID:Yy2jOwc1.net
それarduinoじゃなくてAVRじゃないの

957 :774ワット発電中さん:2024/07/18(木) 19:33:57.06 ID:Ze65ZrP+.net
鳥(ニワトリ、ハト、カラス)

Arduino(ESP32,STM32,RP2040,AVR)

958 :774ワット発電中さん:2024/07/18(木) 19:40:42.33 ID:23qdE3D/.net
ルネサスRAも忘れないであげて。

959 :774ワット発電中さん:2024/07/18(木) 20:12:06.06 ID:tiSxrF/A.net
RL78もあるでよ

960 :774ワット発電中さん:2024/07/21(日) 07:25:58.40 ID:YMZC3b+s.net
ifにelseを付けると無条件でelseの動作が実行される、参った

961 :774ワット発電中さん:2024/07/21(日) 08:36:26.74 ID:UHGnqc7q.net
>>960
こんな感じ?
if(a==1 && b==1){
 …
}
else{
 …なぜか無条件で実行される…
}
条件式の結果が0になってないか確認と(Serial.print()で値を表示など)、
/**/や//によって大カッコの構成が崩れてないか確認してみては

962 :774ワット発電中さん:2024/07/21(日) 14:50:58.92 ID:YMZC3b+s.net
if (Serial.available()) {
いろいろ
ifのなかにifとか
} else {
実行されてしまうもの
}

こんな感じ
else {
実行されてしまうもの
}
を消したらちゃんと"いろいろ"の方が実行される
Serial.availableをserialで表示させる方法が分からんのとpythonから値を送ってる都合上serialが塞がってるのが難儀

963 :774ワット発電中さん:2024/07/21(日) 15:24:31.82 ID:qYIOlgCV.net
>>962
本体のシリアルが使われてる状態でデバッグする場合、他のピンを使ってソフトウェアシリルで通信する
そのピンと適当なUSB↔シリアル変換を使いPCと接続する

if (Serial.available()) { 処理1 } else { 処理2 }
この様な場合、処理2が頻繁に実行されて、処理1が稀に実行されるんじゃない?

PC系のプログラムだと受信の有無が行単位だったりするけど、Arduino(Serial.available)はバイト単位なので
上記の処理1に行単位でデータが受信出来てる前提のコードになってないだろうか?

気で解決したいなら、全体をpastebinやcodeshare等のサイト使ってここに貼って

964 :774ワット発電中さん:2024/07/21(日) 17:36:06.71 ID:YMZC3b+s.net
>>963
そうか、そもそも前提に間違いがあった
pythonを走らせてる間はdelayとか無いからずっと"いろいろ"の方が実行されると勘違いしてた
うーん、pythonが起動してるかで分岐させたかったけど難しそうだしやめとくわ、ありがとう

965 :774ワット発電中さん:2024/07/21(日) 18:46:48.84 ID:C4eDG/fS.net
やめるという選択肢、なんだかな

966 :774ワット発電中さん:2024/07/21(日) 18:51:08.00 ID:YMZC3b+s.net
まあpythonからシリアル通信が途絶えた場合にバイパスしたかったってだけで無くても通信がある時は動くから良いかってなってしまった
気が向いたらコンデンサーとかとSerial.availableでなんとか動くようにしてみるつもり

967 :774ワット発電中さん:2024/07/21(日) 19:19:44.92 ID:UHGnqc7q.net
>>964
もう解決済みのようなので蛇足ですが・・・
if(Serial.available()){
key1=Serial.read(); //(1)
}
else{
key2=Serial.read(); //(2)
}
みたいにやってたりしませんか。上だと(2)のkey2ばかりに受信データが入る
Serial.read()はブロッキング関数で、動作は「データが来るまで待つ→1文字データ拾う(1文字バッファ消す)」なので
バッファを消した直後にSerial.available()しても戻り値(バッファの残文字数)はほぼ0になるはず、なのでほぼ常にelse{}に飛ぶかと

968 :774ワット発電中さん:2024/07/21(日) 19:37:06.77 ID:YMZC3b+s.net
すみません、ありがとうございます。くだらないことに使う初心者が作ったスケッチですが、見ていただけるならどうすべきかご教授願います。
https://pastebin.com/CXcuY5YP

969 :774ワット発電中さん:2024/07/21(日) 19:49:24.39 ID:C4eDG/fS.net
通信途絶の監視はウォッチドッグタイマーが一案

970 :774ワット発電中さん:2024/07/21(日) 19:58:01.66 ID:C4eDG/fS.net
if部にタイマークリア、else部にタイマーカウントアップ(上限リミット付き)を入れる
else部またはif elseの外側でタイマー値を監視し、所定値以上だったら通信途絶とみなして途絶時にこうなってほしい処理をさせる

971 :774ワット発電中さん:2024/07/21(日) 20:13:49.20 ID:UHGnqc7q.net
>>968
見ました。綺麗で見やすいソースですね・・・
mapの条件まで読めませんが、analogRead()の値もしくはシリアルから拾った5つの値を元に回転数?を制御しanalogWrite()しているのかなと思いました。
で、これはやはり、Serial.readStringUntil('\n')とループ直後のSerial.available()の関係というかタイミングが原因だと思います。
Serial.readStringUntil()で数値を受信して一瞬だけ指定値になっても、
その後シリアルバッファが空になるのでelse{ pwmValue = map(sensorValue, 125, 990, 0, 255); …}の方ばかり有効になりそうです。
たとえばループの最後にdelay(3000);とか入ってたら動作が違って見えるかもしれません

972 :774ワット発電中さん:2024/07/21(日) 20:13:58.59 ID:C4eDG/fS.net
タイマーを使う場合、途絶判定まで時間余裕ができるから、>>968のソースなら俺はelse部は使わないな
if部をイベントドリブンとみなしてひとかたまり、通信途絶の判定とその時の処理を別のひとかたまりにしてifの外に置く構成にするね

973 :774ワット発電中さん:2024/07/21(日) 20:27:15.60 ID:qYIOlgCV.net
>>968
例えばPCからのデータ受信が一定の時間ない場合に、アナログ値からPWMを設定する

//グローバル変数またはloop内にstatic変数で
uint32_t lastReceiveTime; //グローバル変数の場合
static uint32_t lastReceiveTime; //loop内の場合

//グローバルもしくはloop内に記載
const uint32_t RECEIVE_TIMEOUT_US = 10E6; // タイムアウト時刻を設定(10x1000x1000μ秒 = 10秒)

(Serial.available()) { // の中に追加
lastReceiveTime = micros(); //最後に受信した時刻を記憶
}

//もとのelse内で行ってる処理をこのように置き換える
if ( RECEIVE_TIMEOUT_US < ( micros() - lastReceiveTime ) ){
// PCから一定時間(ここでは10秒)データの受信が無い場合い実行する
}

974 :774ワット発電中さん:2024/07/21(日) 20:42:11.38 ID:C4eDG/fS.net
>>973
micros()のオーバーフローが気になるけど、どうだろうか?
アプリケーションによっては例外処理が1回しか行われないことが気になるかも

俺だったらこうするわ
unsignd long wdtimer = 0;
unsignd long millis_old = millis();

loop {
 if (Serial.available()) {
  //受信時の処理
  wdtimer = 0;
 }

 if (millis_old != millis()) {
  millis_old = millis();
  if (wdtimer < 所定値ms) {
   wdtimer++;
  }
 }
 if (wdtimer == 所定値ms) {
  //通信途絶時の処理
 }
}

975 :774ワット発電中さん:2024/07/21(日) 21:19:19.13 ID:qYIOlgCV.net
>>974
おお!そうだったタイムアウト忘れてた・・・

>>973
if ( RECEIVE_TIMEOUT_US < ( micros() - lastReceiveTime ) ){
// タイムアウト処理後、再度タイムアウトをリセット or 設定する場合は以下を追加
// lastReceiveTime = micros();
//もしくは
// lastReceiveTime += RECEIVE_TIMEOUT_US;
//もしくは
// lastReceiveTime += 100E3; // RECEIVE_TIMEOUT_USの値を超えない範囲で
}

976 :774ワット発電中さん:2024/07/21(日) 21:19:32.90 ID:C4eDG/fS.net
>>974自己レス
//通信途絶時の処理 の後にwdtimer = 0(または適当な値); をいれたほうがいいな
頻繁に例外処理をするのも変だ

977 :774ワット発電中さん:2024/07/21(日) 22:37:21.02 ID:YMZC3b+s.net
所々変なスケッチになっていて申し訳無いです
皆さんありがとうございます。delayを入れてしまうとおそらく次のアナログ値の更新まで時間が出来てしまうという認識で大丈夫ですか?このスケッチはできるだけリアルタイムで動作する必要があるのでdelay等は恐らく使えないです
そうなると試してみるべきなのは書いていただいているタイマーとタイムアウトでしょうか?
arduinoはほぼ初心者なのでタイマーやタイムアウトを調べながら修正してみます

978 :774ワット発電中さん:2024/07/21(日) 22:48:35.64 ID:UHGnqc7q.net
>>977
delay()と書いたのはアナログ値の更新までの時間稼ぎという認識で合っています。
delay(3000);はSerial.available()判定までの動作をわかりやすくするために、デバッグで極端な値を指定しました(現実的ではない)
else{}=「シリアル通信が途絶えた時のバイパス」という使い方だと、他の方の通りmillis()等で経過時間を読んでタイムアウトがベストと思います。

979 :774ワット発電中さん:2024/07/21(日) 23:39:55.20 ID:C4eDG/fS.net
まったく別の観点だけど、Serial.readStringUntilの終端文字が来る前に通信途絶した場合どうなるかの検証が必要かもね
具体的には、デフォルトの1secでタイムアウトして次に移るので良いか、その場合に処理される変数の値で不具合が起きないか、あたり

断線などハードウェア要因、相手側ドライバハングアップなどソフトウェア要因のどちらも、その時の動作はチップに依存するのでやってみるしかない

980 :774ワット発電中さん:2024/07/25(木) 23:52:12.11 ID:hhwHqrH9.net
現在、アナログ入力に繋いだボリュームによりLEDの消灯間隔を変更するコードを書いています。

シンプルにdelayにアナログ入力の数値を10倍したものを代入しているのですが、これだと10秒→1秒にしても10秒消灯が終わらないと1秒消灯に移行しません。

変更した時点で変更が適用されるようにするにはどのようなコードにすべきでしょうか?割り込み、もしくはタイマーになるのでしょうか?

981 :774ワット発電中さん:2024/07/25(木) 23:52:12.11 ID:hhwHqrH9.net
現在、アナログ入力に繋いだボリュームによりLEDの消灯間隔を変更するコードを書いています。

シンプルにdelayにアナログ入力の数値を10倍したものを代入しているのですが、これだと10秒→1秒にしても10秒消灯が終わらないと1秒消灯に移行しません。

変更した時点で変更が適用されるようにするにはどのようなコードにすべきでしょうか?割り込み、もしくはタイマーになるのでしょうか?

982 :774ワット発電中さん:2024/07/26(金) 01:00:32.97 ID:up6lCzMa.net
>>980をそのままChatGPTにコピペしただけでコードを書いてくれた
すごいなあ

const int ledPin = 13; // LEDピン番号
const int analogPin = A0; // アナログ入力ピン番号
unsigned long previousMillis = 0; // 前回のタイムスタンプ
int ledState = LOW; // LEDの状態

void setup() {
pinMode(ledPin, OUTPUT);
}

void loop() {
int analogValue = analogRead(analogPin); // アナログ入力を読み取る
unsigned long currentMillis = millis(); // 現在の時間を取得
unsigned long interval = analogValue * 10; // 消灯間隔を計算

if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis; // タイムスタンプを更新
ledState = (ledState == LOW) ? HIGH : LOW; // LEDの状態を切り替える
digitalWrite(ledPin, ledState); // LEDに新しい状態を設定
}
}

ループごとに間隔を新たに設定して、その間隔と現在までの経過時間を比較してるのだな

983 :774ワット発電中さん:2024/07/26(金) 01:38:56.04 ID:bZAs6kma.net
>>982
ありがとうございます、早速試してみます。
やはりmillisで周期毎のif文作ると、例えば消灯時間10秒→1秒にしてもその場で上書き実行される感じなんですね。

984 :774ワット発電中さん:2024/07/26(金) 06:51:33.17 ID:4yak6CML.net
delayなんて糞命令とっとと廃止すりゃいいのにな

985 :774ワット発電中さん:2024/07/26(金) 06:59:18.01 ID:/7Vl35rF.net
>>982で正解なんだろうけど、
delay(10);をfor(i=0; i<analogRead(analogPin); i++)のループで回す方が頭に浮かんだ

986 :774ワット発電中さん:2024/07/26(金) 06:59:18.10 ID:/7Vl35rF.net
>>982で正解なんだろうけど、
delay(10);をfor(i=0; i<analogRead(analogPin); i++)のループで回す方が頭に浮かんだ

987 :774ワット発電中さん:2024/07/26(金) 09:03:01.81 ID:bZAs6kma.net
自分もそっちの方がなんかイメージしやすいんですよねw
とりあえず下記の記述に替えたら目的通りに動くようになったんですが、結局ディレイ使ってて少しもやもやしてます。後、ボリューム1周1024を最大30秒にするにはunsigned long interval = analogValue / 102.4 * 10;?

if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis; // タイムスタンプを更新
digitalWrite(ledPin, HIGH); // LEDに新しい状態を設定
delay(300);
digitalWrite(ledPin, LOW);
delay(300);
}

988 :774ワット発電中さん:2024/07/26(金) 09:05:10.07 ID:4yak6CML.net
ボリュームを1秒ごとに2秒から10秒に切り替えまくってると
永久に終わりが来ないな

光ってる累積を記録しないと

989 :774ワット発電中さん:2024/07/26(金) 09:07:06.31 ID:4yak6CML.net
毎ループで光ってる時間を積算していって
単純に現在のボリュームと比較してオーバーしたら消灯させるほうがすっきり簡単

990 :774ワット発電中さん:2024/07/26(金) 09:44:32.73 ID:bZAs6kma.net
1.LED消灯時間を1.25秒とかじゃなくて1秒、2秒と記述する計算は難しいですか?
とりあえずanalogValue / 102.3 * 600;で思い通りの動作にはなってます、
この0.5秒とかを切り捨てたいんですが。
2.点灯自体は確実に行いたいのでdelayを使ってもよいのですが、
その後の消灯時間delay(300);が少しもやっとする。

>>989
すいません、つまりどういうことだってばよ?

991 :774ワット発電中さん:2024/07/26(金) 10:24:42.58 ID:cMXP+Zhd.net
>ボリューム1周1024を最大30秒
キリの悪い数字ですねw
32秒にしてはどうですか?
1024/32=32 ですし
int(AnalogValue/32)

ただし Analog値が 32以下の時は、0になって不都合が出そうなので
そこはテーブル(配列)にすると良いかもしれませんね
ポテンショメータのカーブを補正できるようにするとか最大値を30にするなどなど

uint8 Table[32] = { 1, 1, 2, 2, … 30, 30 }; // 32個分の値を決めておく
uint8 Target = Table[int(AnalogValue/32)];

こんな感じ

992 :774ワット発電中さん:2024/07/26(金) 14:03:37.24 ID:Dg8WjJul.net
>>991
32で割る方が全然正しいですねw
かなり参考になりました、すぐにやり直します。

993 :774ワット発電中さん:2024/07/26(金) 15:19:28.16 ID:ByUcQ6cQ.net
1024/32=32 だけど、AD変換の結果に1024は出ないよ。
「32以下」じゃなくて「32未満」だろうし。

994 :774ワット発電中さん:2024/07/26(金) 15:27:32.62 ID:bZAs6kma.net
1024/32+1にしてそれを×1000したら1〜32秒に綺麗に別れました。大満足です。

995 :774ワット発電中さん:2024/07/26(金) 15:30:47.21 ID:bZAs6kma.net
結果32になってるんですが、これなんで33にならないんでしょう。

996 :774ワット発電中さん:2024/07/26(金) 16:12:55.74 ID:cMXP+Zhd.net
>>993 にもあるように 1024(2^10) と言う値は出力されないからです
10bit1024個の値は、範囲は 0 から 1023 までの1024個の値という意味です

997 :774ワット発電中さん:2024/07/26(金) 16:18:02.31 ID:F4sgykL4.net
Re:ゼロから始める電子工作

998 :774ワット発電中さん:2024/07/26(金) 16:27:40.72 ID:Xspd8qT1.net
1024段階ときけば、あー0から1023の1024個(1024は含まない)と
自然と考えてしまう
たまに数値幅が0~100(101段階)とか出てくると逆に困る

999 :774ワット発電中さん:2024/07/26(金) 22:56:33.43 ID:ByUcQ6cQ.net
画像扱ってると255が1.0だからややこしくなる。

1000 :774ワット発電中さん:2024/07/27(土) 08:51:08.86 ID:3/DFGKBO.net
1oooゲトー

1001 :2ch.net投稿限界:Over 1000 Thread
2ch.netからのレス数が1000に到達しました。

総レス数 1001
277 KB
掲示板に戻る 全部 前100 次100 最新50
read.cgi ver.24052200