Arduino初心者熱烈大歓迎質問スレ part25
■ このスレッドは過去ログ倉庫に格納されています
float total = 0; for(int i=0;i<10;i++){ val = analogRead(A0); // 温度センサーの出力値を読み取る volt = map(val, 0, 1023, 0, 5000); // センサの出力値を電圧に変換 temp = map(volt, 300, 1600, -30, 100); // 電圧を温度に変換 total += temp ; delay(適当に); } Serial.print(total/10); >>7 概略だけど、大域変数を宣言してsetup()で初期値を0にする 次にloop()内で局所変数の配列を宣言して、その配列[大域変数]に各回のセンサー値を代入しては、大域変数をインクリメントする これを大域変数が9になるまで繰り返し、配列[0]から[9]まで加算して10で割り、Serial.print()で出力して大域変数を0に戻す と言うのでは? >>8 どううまくないのか書かないと。 あとスケッチは全部書く。 各行の間にserial出力を入れてSerial Monitorで値を見る。 /* 温度センサーDS18B20で10回計測した平均 */ #include <DallasTemperature.h> OneWire oneWire(4); // 温度センサーのDATピン DallasTemperature sensors(&oneWire); float Tempdata[10]; // 取得データ列 int TempdataMax=0; // 取得データ数 int TempdataCnt=0; // リングバッファのポインタ void setup() { Serial.begin(9600); sensors.begin(); // 温度センサー初期化 } void loop() { sensors.requestTemperatures(); // 温度取得要求 188ms Tempdata[TempdataCnt]=sensors.getTempCByIndex(0); if (TempdataMax<10) TempdataMax++; float tmpavr=0; // 平均の算出 for (int i=0;i<TempdataMax;i++) tmpavr+=Tempdata[i]; tmpavr=tmpavr/TempdataMax; Serial.print("datacnt="); Serial.print(TempdataMax); Serial.print(" new="); Serial.print(Tempdata[TempdataCnt]); Serial.print(" average="); Serial.print(tmpavr); Serial.println(""); TempdataCnt=(TempdataCnt+1) % 10; delay(300); } インデント崩れると思うので CTRL+t で整形してちょ 配列組むとプログラムサイズが大きくなるから 単純に10回足して割る10ではどう? そうだね、移動平均を使えば1000個の平均も取れる 近似値になってしまうけど、ピーキーな値を取り除くなら有効 /* 温度センサーDS18B20で100回計測した擬似移動平均 */ #include <DallasTemperature.h> #define SAMPLE_COUNT 100 // サンプル数 OneWire oneWire(4); // 温度センサーのDATピン DallasTemperature sensors(&oneWire); float tmptotal; // 取得データの合計値 int TempdataMax = 0; // 取得データ数 void setup() { Serial.begin(9600); sensors.begin(); // 温度センサー初期化 } void loop() { float tmpavr; sensors.requestTemperatures(); // 温度取得要求 188ms float tmpnew = sensors.getTempCByIndex(0); if (TempdataMax < SAMPLE_COUNT) { TempdataMax++; tmptotal += tmpnew; } else { tmptotal = tmptotal / SAMPLE_COUNT * (SAMPLE_COUNT - 1) + tmpnew; } tmpavr = tmptotal / TempdataMax; Serial.print("datacnt="); Serial.print(TempdataMax); Serial.print(" new="); Serial.print(tmpnew); Serial.print(" average="); Serial.print(tmpavr); Serial.println(""); delay(300); } >>13 センサーの中には計測に0.7秒かかるのもあるから DS18B20を高精度12bitモードで使用した場合がそれなんだけど それだと7秒後に結果がでる 用途によるけどあまり実用的では無いよね おお!こんなにレスが… 徹夜で悩んでたので寝てしまっていました… >>10 さんのやり方で計測を20回にして少し精度の高い値を取れました ありがとうございます! >>13 さんもありがとうございます!こんな高度なコードは自分には まだ無理そうですが今後の為に保存しておきます。 他の皆さんもありがとうございました! 最終コードは以下のようになりました void setup() { Serial.begin(9600); void loop() { float total = 0; for (int i = 0; i < 20; i++){ int val = analogRead(A0); float volt = map(val, 0, 1023, 0, 5000); float temp = map(volt, 300, 1600, -30, 100); total += temp; delay(100); } Serial.println(total / 20); } 間違えました >>8 さんのやり方でうまく行きました >>12 さんのやり方はまだ自分には少しコードでしたの誤りです 他の回答くれた皆さんもありがとう! サンプルコードは少ないコードで解りやすく簡潔にが鉄則 Pro Microで、MsTimer2による割り込みで呼ばれた関数内でWireによるI2Cを行うと Wire.endTransmission実行時に固まり、PCとの接続もできなくなって RSTピンを2回GNDに落として接続と書き込みをし直さないといけなくなるんだけど WireとMsTimer2を一緒に使っちゃいけないとか何かある? このあとTimerOneも同時に別の目的で走らせようと思ってるんだけど・・・ >>20 サンキュー同じの見つけてた 確かにsei()を入れたら意図した動作をするようになった リファレンスにsei()とcli()が載ってないなあ どうしても必要な場合以外、通信の記述はメインループでやるように書くのが吉 割り込み処理中に別の割り込みの記述するとか 長い処理書くとか頭おかしいのか? 割り込み処理内にはフラグ立てるとか カウンターのインクリメント程度に留めて メイン側でフラグ見て処理すべきだろ 割り込み処理内に色んなことしてたら スタックの消費もバカにならんし デバッグもめんどくさいだろうに 初心者なんだからそんなもんだろ わけのわからんエラーが山のように出たり 場当たり対応して他の割り込みころしてたり 色々痛い目にあって成長してくもんだ 質問です! 3つの信号出力を持っているセンサーが2つあって、Arduinoへの入力は3本1系統しかないから、レールを切り替えるように手動で切り替えられるようにしたい。 ピンヘッダを考えたけど、もっと省スペースで済ませられる方法はある? スケッチの質問なんですが関数を作成した時、LOOPの前と後どちらに書いた方がいいとかありますか?色々とスケッチを見ていると決まりはないように見えるのですが気になっていまして。 前に書かないとエラーになった時あったな だからいつも前に書いてる >>28 暗黙の宣言、暗黙の関数宣言 とかでググってみてください。 Arduino IDEでは>>29 の言うように一時期あったけど、いまはどうでもいいみたい、好みで。 水温センサーをarduinoで利用したい。 amazonとかで買える汎用のセンサーをお湯とか使って何度でいくつの抵抗値か調べようと思ってる。 調べた特性をグラフにしてarduinoのアナログ入力で読み取る予定。そこで気になったんだけど、グラフが比例してれば、プログラムの対応は出来る。 もしグラフがしっかり比例していなかった場合は、どうプログラムを組めばいいのかな? どんなセンサー使うつもり? 熱電対でやったことあるけど誤算範囲でほぼ完璧にリニアだった。 補正すること自体を体験的にやってみたいなら別だけど意味無くね? >>33 普通にXYグラフ描くつもりでいい グラフ描くときに比例してるとこで区切って座標とって描くだろ? データとしてはその点の数だけのXY座標があるじゃん で、入力値がX座標のどこにあるか判別して その両側の2点を得る あとはmap命令で済むだろ >>33 温度センサーはDS18B20がオススメ 抵抗値や電圧じゃなくて温度がデジタルで読める 校正とかいらない 防水ステンレスキャップで延長コードついたのも200円くらい >>35 まだ調査してないから、リニアか分からないけど、車の社外水温メータpivotに付いてた水温センサーをそのまま使いたかったんだよ。 他の人が教えてくれたデジタルのセンサーでもいいんだけど、センサー先端のネジとかをどうやって作ればいいんだろう? >>36 この方法が自分の知識で今すぐ出来るやり方だと思う。変換テーブルはまだ使ったことないけど、勉強してみます。 ありがとう。 >>29 >>31 遅くなりましたがありがとうございます >>33 ExcelとかRで回帰分析して回帰式を用意するのが良いと思う。 プログラムは1次式ではなく、求めた回帰式を利用するだけなので簡単。 33が回帰式のモデルとなる式(2次式、3次式、etc)を用意する必要があるのと回帰分析の知識が必要。 ググればなんとかなるとは思う。 >>36 の書き方だとプログラムするのに誤解しちゃうかもな 両側の2点を得る、じゃなく分岐処理するだけでよい せいぜいグラフは3つの直線で済むだろう そうすると3つのmap命令を用意して あとは入力値で分岐処理、だな >>42 入力値で分岐して、その中のmap関数で数値を出すんですね。グラフの特性に合わせて分岐を増やせばいいのか・・・ なんとかやれそうです。 ありがとう! >>41 回帰分析をググったけど、まだarduinoにスケッチするとこまで行くのは難しそう。 みんなこんなすごいのを、さらっとやっちゃうんですか?スゴいです。 >>44 Arudinoでは回帰分析はしないよ。多分できなくはないけど大変だよ。 調べたサンプルの回帰分析はPCでして、読み取り値のxからyを推定する回帰式を作るんだよ。 33は比例と書いているけど、回帰分析ならば、1次式以外にも3次式とか対数式に近似する回帰式も作れるよ。 回帰式さえ作っちゃえば、Arudino側は回帰式に読み取り値xを入れれば、yが返ってくるので、読み取り値で条件分岐するとかが不要になるよ。 >>45 仕事の合間に回帰式を勉強してきました。重回帰分析じゃないんで、一次関数でいけるかな。式さえ出来れば関数作ってコールしてデータ入れれば結果が出せますね。式が出来るかなぁ。まずはグラフを作るか。テスターと温度計用意だね。 >>46 1次ならググるとExcelのデータ分析を利用する例がたくさん出るから頑張って。 最低でも10から20はサンプル必要だろうから、実際の特性調査の方が時間が掛かると思うよ。 折れ線グラフを扱う汎用的なのを作っておくといろいろ便利だよん みんな凄いなあ 初心者から見るとカッコいい〜 オレも頑張るぞっと pythonも少しやり始めたんだけど 分析してグラフ化はこっちに任せたほうが良さそうだね >>33 自分もDS18B20が楽で良いと思う。 ただ、校正はいらないけど個体毎の誤差は結構あるので、最初にまとめて温度とアドレス控えておいた方が良いかも。5個買って1℃位の差があったので、そこは補正してる。 技術的な質問じゃなくて、法律・倫理的な質問なんだけど、 LeonardとかでVIDやPIDを書き換えるのって違法になる? メーカーが金を出して所得した番号を使う時点で違法確定なのか、 販売はNGだが、個人ならokなレベルなのか、 それとも技適警察みたいにネット上では批判される程度のものなのか。 業界団体規格なので違法にはならんでしょう。USBx.x準拠とかうたったら優良錯誤で違法になるかもしれんけど。 Arduino UNOの回路をばくって、USB付きの目覚し時計を自作して売ったら、何か駄目な事ってある? >>54 基本的に回路に著作権はない arduinoに関してはarduinoと名乗らなければ問題ない 逆にarduinoの回路はavrにusbシリアルくっつけただけに過ぎないわけだが ブートローダーやusbシリアル変換に使ってるavrのファームは別な話になるけどね >>38 車載の水温センサーなんかは基本的にサーミスタでB特性の値から計算するのが普通だけどね 安いしただの抵抗だから耐久性も高いし必要十分な精度あるし 自作しようとするならネジに穴開けて埋め込むだけでいいし 昔の車なんかで見かけたのは精度いらなきゃ線1本で引き回しておしまい >>57 車載だと壊れにくくシンプルなの優先するだろうから ラジエターの冷却液の沸騰上限と凍結下限さえわかれば 途中の温度狂っててもなんでもいいのでは? CPUの内部温度もサーミスタですよね >>58 燃料の噴射量にも関わるので、あまり雑にはできない。 車内の水温計ならそんなレベル。 >>58 >CPUの内部温度もサーミスタですよね PN接合の順方向電圧を使います。 >>58 まぁ水温で何をするかというと燃料補正 水温が低いときの増量や水温上がってきたときの補正とか せいぜい10度単位とかだよ シリアルモニタのウインドウが表示されないのですが、どうすれば良いでしょうか。 ポート認識はしていて、(windowsタスクバーを見る限り)シリアルモニタ起動もしている様なのですが。 互換品のelegoo uno r3で、ソフトの再インストールはしました。 ARDUINO 1.8.10 2019.09.13 [ide] *ライブフォントのサイズ変更がコンソールとシリアルモニターにも適用されるようになりました@ Pieter12345 * Windows @ Pieter12345のソースからIDEを簡単に構築できます *超小型画面に適した、より小さな設定ウィンドウ *ダウンロードしたjsonをキャッシュし、@ mattiabertorelloを変更した場合にのみ取得します *ボードが突然切断された場合、シリアルモニターを一時停止する *ライブラリは、libインストール中に提案される依存関係を宣言できるようになりました * SerialPlotter:@chromhelmラベルの追加を許可 * Board Manager @vowstarのtar.xzアーカイブをサポート * SerialMonitor:コマンド履歴を追加(矢印キーを使用)@ Pieter12345 *アクセシビリティ:設定@ joew46167でアクセシビリティを有効にするチェックボックスを追加 このモードでは、ナレーションとキーボードナビゲーションが大幅に改善されます。 例えば。リンクはアクセス可能なボタンになり、リストは苦痛なく矢印キーでスクロールできます [wifi-updater] *最新のNINAファームウェアを追加 [ハードウェア] *新しいavrツールチェーンをバンドル(5.4.0および64ビットの互換性を今後のmacOS Catalinaと修正) [arduino -buidler] * 1.4.7 への更新(新しいarduino-cliに基づく) タスクマネージャーで、起動してる(けど見えない)シリアルモニタウインドウを最大化したら見えるようになりました。 最大化をやめたらまたすぐ消えたんですが、少しいじっている間に直りました。 原因が分かりませんでしたが、とりあえず良かったです。 >>67 ディスプレイの表示範囲の外に表示されてただけでしょ。 arduino云々の話じゃなくwindowsの基本操作の範疇じゃね? タスクバーにはシリアルモニタ表示ってやったときにarduinoIDEの二つ目のアイコンが重なって表示されてたはずだからそれのシリアルモニタ側のアイコンにカーソルあわせてちょっと上にカーソル移動するとシリアルモニタのサムネイル画像(っていうのかな?)が表示される。 この時右クリックのコンテキストメニューから移動って選ぶとカーソルキーとかで自由に画面外のwindowでも動かせるようになるんでそれで画面内に戻せばいい。 注意点としてアイコンの上右クリックじゃなくてサムネイルのうえで右クリックね。 すみません やりたいことが有り、まだ座学なのですが、電子工作で可能なら始めたいと思っていて、 そのための情報集めている段階なのでテストなど出来ないのですが質問させてください arduinoをコアに 8chのマルチプレクサ10個をデイジーチェーンでコントロールしたいと思っています TC4051Bのようにデイジーチェーンの仕組みのないマルチプレクサでそのようなコントロールする場合、 I2CやSPIなどで通信するのがスマートな気がするのですが、 後付でそのような機能を提供するような汎用チップのようなものはありますか? また、他にもっと簡単な方法がありましたら教えて下さい 用語などを間違っていましたらすみません 74HC595を4個直列にしてシリアル-32bit出力を作って 3bit毎に4051を10個ぶらさげればいけるけど 単純に595を10個並べて80bit出力にしたほうがシンプルだよな 16chの74HC4067も入手しやすいはず こっちならIC9個で実現できる >>69 のコピペ元の大本質問者です 初心者質問スレ その134 https://rio2016.5ch.net/test/read.cgi/denki/1566321111/753 コピペしたのは私じゃないす >>72 ありがとうございます 元スレにて、 アドレスデコーダー シフトレジスター という情報いただき、調べる過程でIOエキスパンダーでも行けそう という感じになっています で、マルチプレクサなんですが、 実際にはデマルチプレクサとして使用で8チャンネル10個が必要な回路になります >>73 だったら4051じゃなくて14051じゃね 16bit IOエキスパンダー MCP23017 8bit IOエキスパンダー PCF8574 (LCD*I2Cアダプタに搭載してるやつ) とかでも別にいいと思う 配線大変そうだけどがんばってね M5.Lcd.drawJpg(const uint8_t *jpg_data, size_t jpg_len, uint16_t x, uint16_t y); xを-10、yを-20にしたいんですが、uint16_t となってるから負の値は指定出来ないんでしょうか? int16_tならいいのかな int16_tの負の数ってどう表現したらいいのかな >>77 なぜスクリーン上の座標をマイナスにしたい? 画像の描画範囲をずらしたいなら、引数 offX offYで操作するんじゃないの? >>78 x, yは画像の描画の原点でデフォだと左上の0, 0になるんですが、 スクリーンのサイズよりも画像が大きいため、画像の右側と下側が見切れてしまいます そのため、画像の中心がスクリーンの中心に来るようにx, yをマイナス値に出来ればなと思いました >>79 Docsを見るとメンバ関数はこうなんだが void drawJpg(const uint8_t *jpg_data, size_t jpg_len, uint16_t x = 0, uint16_t y = 0, uint16_t maxWidth = 0, uint16_t maxHeight = 0, uint16_t offX = 0, uint16_t offY = 0, jpeg_div_t scale = JPEG_DIV_NONE); 引数 offX offYでjpegの描画開始位置を変えられない?ダメだった? >>80 わあ!ありがとうございます ライブラリ見てたら M5.Lcd.drawJpg(const uint8_t *jpg_data, size_t jpg_len, uint16_t x, uint16_t y); しか載ってなかったのでsdカードから画像を読み込む関数と違って使える引数がほとんどないんだと思っていました。 試してみます >>80 うまく行きました ありがとうございました M5Stackの画面に1秒間隔で時計を更新して表示する関数と5秒間隔で気温の測定とラズパイのデータベースをチェックする関数を作ってマルチタスクで動かしてみました。 画面には時計と気温が表示されていてラズパイのデータベースの値は画面には表示させてないです。 もし、ラズパイのデータベースの値があらかじめ設定した値を超えた場合は時計と気温を非表示にしてデータベースの方だけを画面いっぱいに表示させたいんですがそういうことって可能ですか? 時計の方の更新間隔を伸ばさないと無理ですか? 割り込み処理っていうの使えばいいのかなと思ったんですがそれってボタンやセンサーのような外部入力だけですか? タイマー割り込みを使えばいい。 "arduino 時間 割り込み"でぐぐってみたまい。 というかそもそも君のそのマルチタスクのプログラムというのは タイマー割り込みを使用しないで出来ているのか? 割込み使ってれば>>84 の書き込みにはならない ポーリングなら>>83 の質問にはならない いろいろ謎w データベース値が設定値超えたら 時計表示をパスすりゃいいだろ 更新と表示を一緒くたにして作るからそうなる ど素人の俺からすると 単純にインタラプト入れればいいだけのように思う レスありがとうございます 現状ですが、 https://nagatani.github.io/posts/m5stack-dht12-temptoifttt/ を参考にxTaskCreatePinnedToCoreっていう関数を使いました。 んでsetup関数に以下を書きました。 xTaskCreatePinnedToCore(clockTask, "clockTask", 4096, NULL, 1, NULL, 0); xTaskCreatePinnedToCore(tempTask, "tempTask", 4096, NULL, 2, NULL, 0); clockTaskは1秒ごとに時間の表示、tempTaskは5秒ごとに気温の表示とラズパイへのアクセスです。 loop関数にはM5.update();だけ書いてあります。 arduino 時間 割り込み ググってみました 現状は関数の中で例えばディレイを1000として時計を動かしていますが、そうじゃなくて、 まず5秒毎にラズパイのデータの確認をして設定値より低ければタイマー割り込みという機能を使って1秒毎に時計を表示する関数(clockTask)を動かす、5秒毎にtempTaskを動かすって感じでしょうか? タスク間で通信をするんだよ。一番初心者にも解りやすいのはグローバル変数で作ったフラグやデーターを使う事です。 まず、1秒毎に起動するタスクと5秒毎に起動するタスクをつくる。 1秒の方では現在時刻の取得、最新温度とデーターベースから取得された値の確認をして、条件に合致しなければ時刻表示、合致したらアラート表示。 5秒毎の方では温度の計測と保存、データーベースへのアクセスと値の取得を行う。 みたいにすればいい(一例です)。 割り込みを使わず泥縄式にloop(){delay(1000);every1sec();if(count++%5==0)every5sec();}でも 各時間毎の処理内容は同じで出来ます。どうするのが良いかはスキルとプログラムの要求仕様や規模などによる。よく考えてみてw timeInfoで201910062143って今の時間を変数に入れるのってどうやるんですか? dday = timeInfo.tm_mday;って取り出したら06じゃ無くて6になっちゃう >>95 String imaNoJikan = ""; imaNoJikan = String(sprintf("%04d%02d%02d%02d%02d%02d", timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday, timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec)); ってやったら invalid conversion from 'int' to 'const char*' [-fpermissive] こんなエラーが出ました >>96 そらそやろ。sprintf の戻り値はintだからやで。しかも引数も間違えてるよ。 sprintfの出力文字列は第一引数にchar配列を入れて受けるんだよ ググればすぐ出てくるだろに >>96 sprintfの戻り値ってintだから当然そうなる。あと第1引数は文字列を格納するバッファー。 char imaNoJikan[14]; sprintf(imaNoJikan, "%04d%02d%02d%02d%02d%02d", timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday, timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec); Serial.print(imaNoJikan); コンパイルのエラーは出ないけどシリアル見てたら再起動繰り返してるっぽいです >>101 今やったらちゃんとimaNoJikanの中に入っていました >>97 >>98 >>100 どうもありがとうございました >>101 今の時間の2秒前ってどうやって求めるんですか? 1970/1/1からの秒数のまま計算するんじゃない? 今の時間の2秒前のUnix時間を作ってそこから >>101 みたいに変換する感じですかね?調べてみます >>105 JST変換するとき9時間足すのを 8時間59分58秒足す感じで DCモータ2軸制御のためにArduinoシールドを探しています。 動かしたいモータはマブチのRS-280RA-2865で、特性は URLのような感じになります。 https://i.imgur.com/wbAO6r0.jpg モータは起動時には最大出力で回り、以降はバランスをとるためにほぼ0rpmあたりになる予定です。 ざっと見た感じ、AdafruitのServoShieldしか見つかりませんでしたが、 これでも十分動作できそうですか? 電源電圧何ボルトなの? 静止時に流れる電流に耐えられれば使える 3ボルトで4.7Aとはまあ結構流れちゃうねぇ。 ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる