Arduino初心者熱烈大歓迎質問スレ part22
■ このスレッドは過去ログ倉庫に格納されています
>>38
ESP-WROOM-02かな。
電池駆動とかどのくらいの距離離すかとかも書いた方が良いと思う。
LTEやLoRaじゃないと無理だわ、ってことも有るし。 >>39-44
ありがとうございます。電池駆動で距離は30cm程度です。
外で使うのでwifiモジュールは適していないのかなと思いました。
それとあまり距離は出さなくていいので今のところ赤外線モジュールが視野に入ってます。 距離30cm程度で無線の必要性がよく分からんけど
赤外線モジュールだと、位置関係もある程度制限されるし
片方をポケットとかバックパックに入れるわけにもいかんよね 赤外線は屋外だと太陽光の影響を受けて距離が短くなるよ。
と言っても30cmなら大丈夫と思うけど! ESP32を5個買って、青歯接続が無難かなぁ…
あとでパソコンへデータ送信するのも、無線LAN経由でらくらく送れるし。 青歯という隠語みるたびにどうしても青ノリが思い浮かぶ・・・ 最近の青歯は省電力じゃないの?
CR2032で半年とか持たせられるし。 使ったことないからあれだけど
電波飛ばすんだからその間は飛距離に応じた電気はくうよね? カシオのスマートウオッチ、3年ほど使ってるけど電池交換は半年に1回だけ、もちろんCR2032を1個使用。
詳しい仕組みはわからないけど、電気をバカ喰いすることはないんじゃないかと。 PCのワイヤレスキーボードとか単4電池一本で1年以上もったりするけど
あれどうなってんの?1.5vで動いてるの?3vに昇圧してんの?? >>56
大体は昇圧してる。
電波に関しては、スペクトラム拡散技術のおかげで、
かなり弱い電波でも受送信できるようになってる。 >>45
その程度なら、リモコンみたいな方式で赤外線で飛ばすのが手っ取り早くて消費電力も小さくて良いんじゃない?
主要なマイコンならちょっと調べればリモコンの製作記事見つかるだろう。
センサ側は16F1のpic@100円前後、受け側はnanoとかで十分。
使うセンサーによっては受け側以外はマイコンすら不要かも。
リモコン専用のチップ有るし。 ありがとうございます。
基本的には赤外線で、ストップウィッチの方にブルートゥースも乗っけて読み取りを楽にしようと思います。
まずはunoで地道に勉強しようと思います ブレッドボード上で抵抗の足同士が接触してVccとGndショートさせてUSBポート壊したんだけど
ポートを保護する方法を教えてください 青歯とか書いて悦に入ってるヤツって
いまだにすし屋でアガリとかオアイソとかガリ
とか言ってヒンシュク買ってそうだよなw 青歯が恥ずかしいのは当て字の中二臭さ、今時じゃなく始めから恥ずかしい。
寿司屋隠語は業界用語なので客が使うのは恥ずかしい。 中国では蓝牙というらしい
蓝は藍かな >>63
>>64
よかった
嫌な感じがするのは俺だけじゃなかったんだ processingとの連携を勉強中で教えて頂きたいです。
xbeeとxbeeシールドを使い、xctuを起動したPCへ無線で繋げたいと思っています。processing1.5.1を指定している数年前のページがあったりするんですが今だと最新版でも良いのでしょうか? TeensyってArduinoのvariantなん? do文の中にanalogRead入れたら値が全く読み込めない
なんで?
for文なら動いてます >>71
もしかしたらdo文が繰り返さず
1回で抜けてるかも知れない
whileの時間増やしても速さが変わらない >>70
ふたつのプログラムを見ないと何ともだけど、while文の抜け出し条件が未成率で無限に抜け出せてないとか?
do文が無しで1回のみ実行だとアナログ値は読めてる?
そもそも読めないって、読みに行ったら戻ってこないの? int analogpin = 0;
int count = 10;
void setup() {
Serial.begin(9600);
}
void loop() {
unsigned long clocks = millis();
int MAX = 0, MIN = 1023;
int data = 0;
int total = 0;
float ave = 0;
float mA = 0;
for (int i = 0; count < i; i++) {
unsigned long start = millis();
do {
data = analogRead(analogpin);
// Serial.println(data);
MAX = max(data , MAX);
MIN = min(data , MIN);
}
while(millis() - start <= 22); //50hz1サイクル20msプラス10%
total += int(MAX - MIN);
}
ave = total / count;
mA = ave / 2.0 / sqrt(2) * (5000 / 1024);
Serial.println(mA);
}
初心者だから読みにくいのは許してね
交流電流をクランプ式のセンサーで読み取りたいのです
電源は5vを4.7キロオーム2つで分圧してクランプの片側へ
クランプのもう片側はA0へ
クランプと並列に補助抵抗200オームをつけて
これだけの回路です
シンプルだけどfor文では動きました
質問のアナログ値1回は読めてるかどうかですが
スケッチ上にdo文の中にprintln置いていますが
それを生かすと止まります
故に読めてるかどうかは分かりません
出力はゼロをひたすら出力します 説明しますね
交流50hzなのでワンサイクル20ms
1割多めで22msワンサイクル分の最大最低を読み出します
それの10回分の平均を出して
計算して実際の電圧にします
最後の電圧から電流に変換する式が抜けてましたが float b = 0, c = 0;
int COUNT = 200;
int g[200];
void setup() {
Serial.begin(9600);
// analogReference(INTERNAL);
// ADCSRA = ADCSRA & 0xf8;
// ADCSRA = ADCSRA | 0x04;
}
void loop() {
float a = 0;
int MAX = 0, MIN = 32767;
for (int k = 0; k < 50 ; k++) {
for (int i = 0; i < COUNT; i++) {
g[i] = analogRead(0);
if (MAX < g[i])MAX = g[i];
if (MIN > g[i])MIN = g[i];
// Serial.println(g[i]);
}
a += MAX - MIN;
}
b = a / 50;
c = b * (5000.0 / 1024.0) / 2.0 / sqrt(2) * 10.0 - 500.0;
Serial.println(c);
}
これは成功と思われますが誤差は大きいです >>75
追記ですが最後の出力とはm Aのことです >>75
スマホで読んでて、しかも老眼なんで見間違えもあるかも知れないけど、for文の条件式が count < i になってると初期値が count = 10と i = 0 だと中身を実行しないんじゃない?
違ってたらゴメンなさい。 ちょっと関係ないけど、Loopの中で下記の変数が再定義されまくっても良いのかな?
ループする度に変数のアドレスを保持するパフォーマンス的によろしくないと思うんだけど?
コンパイラがどういうコードを生成してるか知らないので、これでも良いのかもしれないけど・・・
unsigned long clocks = millis(); <ーこれ
int MAX = 0, MIN = 1023; <ーこれ
int data = 0; <ーこれ
int total = 0; <ーこれ
float ave = 0; <ーこれ
float mA = 0; <ーこれ
for (int i = 0; count < i; i++) {
unsigned long start = millis(); <ーこれ 変数は結局コンパイラに全部関数の最外スコープにまとめて定義する形にされるのでは? >>75
for (int i = 0; count < i; i++) { あんま気にしなくて良いんですね・ありがとうございます。
引き続き、>>70さんのdo-while内のanalogRead問題をどうぞ for (int i = 0; count < i; i++)
じゃなく、こうだ
for (int i = 0; i < count ; i++) >>85
動きましたー
ありがとうございます
よかったー お騒がせしました
みなさんありがとうございます
また色々参考になるご意見今後の参考にします
またご質問させていただくことがあると思います ほんといろいろな意味で気持ち悪いコード
adcサンプリング周期とか無視かよ
millis() の使い方それでいいのか
analogReadは ADSCでのポーリング読み込みだから
あらかじめハード的に周期を観測して決めなければならない
というか、はあ、初心者はそういう発想で来るのねという感想 >>90
ど素人なのでご容赦ください
サンプリング周期??
ネットで調べたらアルデュイーノのanalogReadは量子化を考えてサンプリング定理でローパスフィルター入れてって書いてあったから
入れてみたけど失敗しました Arduino電力計 - 回路図とスケッチ
でググれ 床屋行ったので書いてみた
timerone ライブラリを使用しているので、gitからダウンロードしてね
/*
50Hz meas
use lib :
github.com/PaulStoffregen/TimerOne.git
1/50Hz = 0.02 (1 period)
0.02 / 100 =0.0002 =200u ( 100 sample = 1 period)
*/
#include <TimerOne.h>
#define SAMPLE_SZ 100
#define SAMPLE_PERIOD 200 // us
#define BLOCK_SZ 50
#define BLOCK_SZ_INV (1.0/50.0)
int sample_buf[SAMPLE_SZ];
int sample_buf_p;
int sample_buf_ready;
void isr_timer1() {
int data;
if( sample_buf_p < SAMPLE_SZ ){
data = analogRead(0); // wait for ADC
sample_buf[ sample_buf_p ] = data;
sample_buf_p++;
}
if( sample_buf_p == SAMPLE_SZ ){
sample_buf_ready = 1;
sample_buf_p++;
}
}
void setup() {
Serial.begin(9600);
sample_buf_p = 0;
sample_buf_ready = 0;
Timer1.initialize(SAMPLE_PERIOD); // unit=usec
Timer1.attachInterrupt(isr_timer1);
}
void loop() {
int i,j; int data;
int max; int min;
float sum; float avr;
float val;
sum = 0;
for (j = 0; j < BLOCK_SZ; j++) {
while( sample_buf_ready == 0 ) ;
max = 0;
min = 32767;
for (i = 0; i < SAMPLE_SZ; i++) {
data = sample_buf[i];
if (max < data) max = data;
if (min > data) min = data;
}
sample_buf_p = 0;
sample_buf_ready = 0;
sum += ( max - min );
}
avr = sum * BLOCK_SZ_INV; // outer loop sz
val = avr * (5000.0 / 1024.0) / 2.0 / sqrt(2) * 10.0 - 500.0;
Serial.println(val);
} ああ、ダブルバッファにしてなかったから
これはボツだ
まあ、参考にして書いてみて >>97
感動しました
ありがとうございます
参考にさせていただきます インデント無いのはまったく見る気しないね。
次のテンプレにこれ入れて。
http://codepad.org/ 蛇足
コンパイラがどう解釈するかだけど
sqrt(2) が定数にならないかもしれないので
1.4142135とか数値で書いたほうがいいかも //(5000.0 / 1024.0) / 2.0 / sqrt(2) * 10.0
17.2633491501
そんなとこまで気にするならいっそのこと固定値 Ethernet PHY付けて通信する時はSPIから線を延ばせば良いのね?
遅そうだけど 長文ですみません。複数のアナログ値の読み込み時の動作ついて教えてください。
今作っている装置では、ArduinoNanoのA0,A1,A2,A3,A6のポートに合計5つのセンサーが取り付けられています。(4と5はI2C)
AD変換完了割り込みベクタを使って、ADMUX書込み(チャネル変更)→ADSRAのADSCをセット(変換開始)して最速で回しているのですが
これで全5つセンサーのデータを正しく読み込めているんでしょうか?動きはしますが、他のポートに繋いだセンサの影響が出ています。
(例えばA0のセンサを外して1kΩ経由で5Vに繋いだりGNDに繋いだりすると、関係ないA1やA2の値が引き摺られて変わります。)
サンプルプログラムを掲載している先人のウェブサイト(ArduinoだけでなくAVRマイコンの物も含む)を見ると
『ADMUXレジスタに書き込んで、マルチプレクサが安定するまで待つ』と言った記述をしているサイトが見受けられます。
これは経験則から来るものでしょうか?または、どこか公式の文献に記載されている所がありますか?
ATmega328Pのデータシートや、Atmel(今はMicrochip?)が発行しているADコンバーターに関する応用記述を読むと
基準電圧を切り変えた場合は最初のAD変換の結果は不正確なためこれを破棄することが推奨されていますが
マルチプレクサを(シングルエンド入力チャネル内において)切り変えた場合については特に言及されていませんでした。
ADコンバーターの設定はArduinoデフォルトのままなので16MHzが1/128されて125kHzが変換クロックですよね。
ADMUXに書き込んだ後ADSCが上がって即変換クロックのタイミングだった場合、マルチプレクサ変更から即ADCが始まったとして
データシートの仕様を見ると通常変換モードで、ADSC立ち上がり認識からサンプルホールド開始まで1.5変換クロックとあるので
この今のスケッチだと、マルチプレクサのレジスタが書き換えられてから、最速の場合でおよそ12μ秒後にサンプルホールドが始まっています。
この時間はマルチプレクサの切り替えに十分でないのでしょうか?(切り替えに10秒も掛かるマルチプレクサ...?)切り替えに必要な動作時間の記述が見つけられませんでした。
AD変換周期をカット&トライで伸ばして行けば、今回の結果が前回の結果に引き摺られる量が減ることを確認したので
値の引き摺りが我慢できるところまでサンプリング周期をテキトウに伸ばしちゃっていますが、サンプリング周期を設定する根拠が欲しいのです。
出来ればサンプリング周期は下げたくないので、もし、そもそも自分が何かミスをしていて上記問題を解決できる方法があれば教えてください。
サンプルホールド回路の入力インピーダンスに対してセンサーの出力インピーダンスが高いのかと思いましたがそうでもないようでした。 >>105
ミス:10秒もかかる→10μ秒もかかる 切り替え初回はゴミが入るかADC再起動しないと
正しい値は入らないだろうね
(チャージがリセットされない)
>根拠
データシートにしかないだろうね
丹念に読んで該当する項目内無いならあきらめるしかない
(無いとすれば)
メーカーも(ばらつき大きい等の理由で)保証しないのだろう
マルチプレクサをADCに外付けで多チャンネル化したことはある。
このときは、MPXの出力をオシロで見て波形確認したよ Arduinoって、micropythonをインスコして使えますか? >>105
データシートの28.5章(Page 310)以降を読むべし >>110
それに準拠して設計してあんじゃん
データシートと質問を読んで意味がわからないならレベルなら無理に答えなくていいよ これだけじゃどうせなんか言われるんで
>>105
ダイに印刷されてるようなマルチプレクサがそんな遅い訳あるか 切り替えに数十ナノ秒すらかからん
データシートに書いて無いのはそのマイコンの最速20MHzでも次の命令実行前に切り替えが終わってて無視できるほど速いから
単にS/Hキャパシタに前回の値が残ってるだけ 外部回路の出力Zは低いと言い張ってるが本当にそうか?
例えばLM35なんかはシンク駆動Zめちゃ高いぞ(データシートは低インピと謳っているがちゃんと見るとソース駆動の話だ)
センサーの出力段がプッシュプルじゃないんだろ LM35みたいなハイサイド+プルダウンじゃシンク側が間に合わん
抵抗分圧のPTCサーミスタやCSDセルなんかもダメな ADCを共用して入力するにはZが高い
このサイト読んでみ ↑と同じ話が書いてある 解決策も
http://siesta.la.coocan.jp/zk/AVR_ADC/AVR_ADC.html LM35Dには自分も半日トラブった。
資料は隅から隅までキチンと読まないと、と反省した。 >>109
MycroPython乗せたらAruduinoじゃなくなるよ。
以前はAVR用の有ったみたいだから、無理やり乗せようと思えばできないことも無いんだろう。
少なくとも現在は公式には無い。
Python on the chipとか、circuit pythonとかが有るみたい。 >>112>>113
センサーの出力なんて
「自分の出力値よりかなり高いレベルまで充電済みの容量性負荷」
に繋ぐことなんて想定してないってことか
横からだけど勉強になった
頭の片隅にいれとこう 入出力の端子全部使うとかはやめといた方がいいのかな やめといた方がいいような数のポートなんか付けたりしないのでは?
つまり全部使っても問題ないと思う。
実際はどうなのか知らないけど。 >>105
蛇足かもしれんけど、>>112さんのを補足すると
>『ADMUXレジスタに書き込んで、マルチプレクサが安定するまで待つ』と言った記述
の「マルチプレクサが安定するまで待つ」は間違いで、
「マルチプレクサ切り替えに伴って生じる回路の過渡応答が収まるまで待つ」という
ほうが正しい
また、AVRのマルチプレクサ切り替えのタイミングは、ADMUXレジスタに書き込んだ時では
なくて、変換開始(ADSC立ち上がり認識)時だから、
・ADMUXレジスタに(新しいチャンエル番号を)書き込み
・100us 待つ
・変換開始・終了を待ってデータ取得
のようなことをしても、事態はあまり改善しないはず
「AD変換周期をカット&トライで伸ばした」っていうのが、実際にはどうやったのか分からないけど
単純に待つかわりに、変換結果を一回読み飛ばすとかしないとダメだと思う
そうすれば、マルチプレクサ切り替えからサンプルホールド開始までの時間は
10倍くらいとれるから、センサーの出力インピーダンスはデータシート推奨上限
10kΩの10倍、100kΩくらい行けると思う あ、長文書いたけど間違ってるな orz
・ADSC立ち上がりでチャンネル変更
・ホールドキャパシタはADSC立ち上がりから1.5クロックの時間だけ入力に接続され
その後切り離される
・ホールドキャパシタの保持している電圧をAD変換
・変換終了した時点でホールドキャパシタは再度入力に接続っていう流れだな
(データシートにははっきり書いてないけど)
そうだとすると、一回目のAD変換を読み飛ばすだけじゃだめで、変換終了後
delayを入れてホールドキャパシタを充放電しなきゃダメだな
まさか、変換開始から1.5クロックの時間だけしか入力に接続されないようになってるって
ことはないと思うけど、そこはデータシートからは読み取れない(と思う) >>123
検証したら分かるがAVRマイコンのs/hキャパシタが入力回路に繋がってる時間は1ADCクロックだけ
Arduinoで言えば125kHzだから8μ秒ね
なんで外部回路の出力インピーダンスはこの時間でs/hキャパシタを充放電出来るようになっているべき
要するに
ADSCが1なことを確認したADCクロックの立ち下がりでマルチプレクサ確定してサンプリング開始
1ADCクロック経過後にサンプリングが終了して保持に入る
データシートに
・少なくともADSCを書いてから1変換クロックはマルチプレクサは弄るべきでない
・ADC入力のナイキスト周波数はADCクロックの1/2である
ことか記されているのはこの為
データシートに保持のタイミング(ADSC認識の立ち上がりの次の立ち上がり)しか書いてないのはAtmelが悪く、不親切だと思う
https://www.avrfreaks.net/comment/759794#comment-759794
検証方法はこの人と全く一緒(mcuをmega328でやっただけ) 追記
なので、当然ADCを使用しない場合は内部回路の漏れ電流でしか放電されないので時間を空けたところであまり好転しない
例に挙げられているLM35のようにソース側のみ強力に稼働できるものを繋げて正確に読み取りたい場合は
一度s/hキャパシタをGNDに低インピーダンスで繋げて放電してやれば次の初回変換でも正確な値を返す
Arduinoの関数にはないがADMUXのMUXには入力ピンでなくGNDに直結する設定値が用意されてる
これを使えばピンを無駄にしなくてもs/hキャパシタがディスチャージ出来る
GNDでADC→センサー1でADC→GNDでADC→センサー2でADC→GNDでADC→センサー3でADC→……
センサーのソース駆動インピーダンスが十分に低ければこれで正確な値を返す(シンク駆動インピーダンスは高くていい)
もちろん回路全体のセンサーサンプリング周波数は半減する
多少の測定誤差が増えても平気ならAVRのADCは1MHzまで動作が保証されてるからADCクロックを高速化したらいい
200kHzまでなら誤差が最大2LSBだが1MHzでは倍の4LSBになる(データシートより)
(サンプルホールド回路のサンプリング時間はさらに減るので駆動インピーダンスに注意) ほっといても放電されないね。変換したときしかサンプルしないから。
何かAD変換したあとフローティングのピンを測ると前と同じ値をずっと言ってくるよ。
>>120
マルチプレクサが固定されるのがADSCを拾ったときなだけで、変更自体はいつでもされてるから中段は間違いだよ。 早い話、MPX切り替えた時にADC状態初期化が要る
というだけなんだがな
(一回空読みでもよい)
だから、fsがあげられるなら2倍にしてやればよい
というだけなんだがな どうしてホールドするとき以外は外につなぐようになってないの? マイコンのピンはADCだけじゃないんだから他の回路の特性に影響が出るじゃん
ポートの交換機能たくさんあるだろ?目的の機能が作動する時しか繋がないよ >>132
たぶん>>131はポートに繋がってる時間(=サンプリング時間)が短いことが言いたいワケじゃなくて
>>125の解決法みたいに自動的にGNDにディスチャージしとけば?って言いたいんじゃねーかなと思った
>>131
連続変換だと13ADclkごとにADCが掛かるわけで、2ADclk目でサンプルホールドは終わってるけど
残りの11ADclkはホールドした電荷をAD変換に使っているわけだからホールドしてなきゃ意味ない時間だろ
そして質問者>>105の使い方は13ADclk毎にずっとAD変換させてるわけで「サンプリング中」と「ホールド中」以外の時間はほぼ無いじゃん?
質問者のように出来るだけ高速でセンサー連続監視する使い方じゃなく、必要なときだけAD変換すればいいなら
使い終わった後ADENを0に(AD変換をオフに)すれば次回起動時にはちゃんとディスチャージされてるよ(>>128が書いてる解決法ね)
連続変換でこの手を使うと毎回初回変換扱いになるから12ADclk伸びて25ADclkの変換時間がかかる事になるから
>>125の1回GNDを測るのとAD変換のサンプリング周波数はほぼ同じようなもんになっちゃうけどね 111から後、すっごいためになった
こういう情報もらえるのがArduino(AVR?)のいいところだね
マイナーなマイコンだとこうはいかない
まあ、LM35DZ使う場合に限ってだと、1k抵抗通して0.1uFくらいのコンデンサ入れて
おくだけでいいかも 秋月の pro mini 互換で動いてたけど
壊してしまった。 電気的な壊れではなく 踏んづけて・・・
また 買ってきたのだが 書き込みがうまくできない
なんでだろ・・ >>135
pro mini は書き込み時のリセットのタイミングがシビアな個体があった気がする。手でリセットボタンをタイミングよく押すか、USBシリアルのどこかににコンデンサ挟むとか、検索すると色々出てくるよ。 有難う エラーはこんな感じ
avrdude: stk500_recv(): programmer is not responding
.
.
.
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x00 ■ このスレッドは過去ログ倉庫に格納されています