AVRマイコン

2023年1月18日 (水)

ATmega4809のシリアルポート

Arduino UNOで使われているATmega328Pには
シリアルポート(UART)が一つだけしかありません。
  ※SoftwareSerialは別物

もっと欲しいゾという時は、
ATmega2560が搭載された「Arduino Mega 2560」を
使いました。
  ※RAMも8kに増えますし。
しかし・・・大きい。 基板サイズがデカいのです。

そこで新しいチップ「ATmega4809」のデータシートを
見ますと・・・UARTが4つになってます。 ←エエやん!

4809には40ピンDIPと48ピンのQFPの2種類が存在します。
40ピンのは48ピンのから
  ポートBの6本
  ポートCの2本
が除かれています。

ポートの割り当て表を眺めますと、UART3が配置されているのは
ポートBです。
代替ポートを選択しようとしてもポートB。

Pb

しかし、40ピンではポートBはが全部省かれてます
ということは、40ピンのATmega4809、UARTは3つしか使えない
ということになるのかと。  ・・・アカンやん。

Pb2
  ※英文のデータシートも同じだった
   UART、3コと4コの区分線がミスってる?

Arduino nano every (48ピンのが使われている)
でも買って、触ってみようかと。

| | コメント (0)

2023年1月 2日 (月)

PWMでD/A変換:アナログマルチプレクサの応用で

2020年8月13日:Arduino、analogWriteは捨てちゃえ。ちゃんとしたPWMを使おう
ということで、過去、PWMを使ったDAC(D/A変換回路)を
さまざまなツールで使っています。

例えば、
JIS C8708による充放電サイクル試験回路(トランジスタ技術2010年2月号)
2020年4月10日:JIS C8708:2019対応ニッケル水素電池充放電実験回路(回路図とプログラム)
2022年4月14日:Arduino IDEでRaspberry Pi Pico:PWMでD/A出力してA/D入力を試す
2022年4月15日:Arduino IDEでRaspberry Pi Pico:A/D入力が…あれっ?

これらでは、PWM波からDC電圧を作るのに、
基準電圧ICを使っています。
Vref値とGND間をPWM波でマルチプレックスし、
LPFを通すことで直流に。
デューティ比に比例したDC電圧を得ています。

この応用ということで、Arduino UNOのマイコン
ATmega328PのAREF電圧を取り出した使った実験も
しています。

例えば、この記事。
2022年10月5日:サーミスタ103JTで計った温度をシリアル出力

サーミスタの抵抗値を見るのに、AREF電圧を取り出して
A/D変換します。
  ※これはMPXとは関係なしの用例。

次のこの記事では、AREFをオペアンプでバッファして
PWMし、LPFを通してD/A変換しています。
2022年4月22日:Arduino UNOのA/D入力:PWMでD/A出力してA/D入力を試す

ここで問題に気が付きました。
「なんじゃこれは?」の信号が見えたのです。

こんな模式図を描いてみました。

M10

AREFをオペアンプでバッファして取り出します。
ATmega328Pに関してはこれでうまく基準電圧が
取り出せます。

そのオペアンプ出力を直にマルチプレクサの入力に
つないでいます。
外付け基準電圧ICを使った時のようにコンデンサを
入れたいところなのですが、発振の可能性があるので、
オペアンプの出力にコンデンサは入れられません。

たまたま、このPWM→D/A変換部の波形を見た所、
こんな信号になっていました。

M201m

AREF電圧を出力しているオペアンプ、そこにPWM波に
同期した負パルス(▼マーク位置)が出ているのです。
出力インピーダンスは低いはずなので、MPXの切換
ノイズが飛び込んでいるわけではありません。

そこで、こんな回路を使って実験してみました。
プラス側のIN1入力は1kΩで+5Vに。
マイナス側は1kΩでGNDに。

M12_20230102152301

すると・・・・
まず、1ゲートタイプのマルチプレクサ TC7W53
M302m

3回路入った74HC4053の場合。
M301m

MPXパルスが変化したエッジでIN0、IN1に瞬間的な
電流が流れている様子が見えています。

AREF電圧をバッファした通常速度のオペアンプでは、
この短いパルス(150nsくらい)を抑えきることができない
のでしょう。

なぜこんなことが起こるのか・・・
TC7W53の内部回路を見ると分かってきます。

M11_20230102152501
IN0とIN1の切換には、2直にしたインバータが
入っています。
IN1側がその後段につながっているので、IN0から
遅れて切換されます。
その一瞬、COM端子につながるOUT0とOUT1を通して
IN0とIN1が短絡するのです。
IN0はGNDにつながっていますので、オペアンプ出力を
つないでいるIN1が一瞬だけGNDに引っ張られることに
なってしまいます。
それがオペアンプ出力に現れた負パルスの原因です。

  ※観察のためIN0とIN1に1kΩの抵抗を入
   れましたが、IN0、IN1とGND間に0.01uF以上、
   0.1uF程度のコンデンサを入れると短絡パルス
   は見えなくなります。
   基準電圧ICを使った時のパスコンは有効という
   ことがわかります。

対策案
・ATmega328PのAREFをオペアンプでバッファして
 基準電圧を得るのはOKだが、それをPWM制御する
 マルチプレクサにつなぐのは×。
・PWMするマルチプレクサでD/A変換する時は、
 パスコンを付加できる基準電圧ICを使う。

こんなところでしょう。
  ※見えなくなるけど、それでも、短絡は発生してる。
   ノイズ発生の要因になるか。

※注1
基準電圧ICに付加するパスコン、こんなことも
ありますので。
2019年9月14日:良かれと思って付けたコンデンサが・・・
  ※AD680・・・発振!

※どうなんだろう
多チャンネル入力A/Dコンバータ、たいていの場合
マルチプレクサが入力。
チャンネル切換時に今回のようなことが起こる心配
は無いのか?
入力に入れたCRフィルタが役立つかも。

※ブレッドボードで実験
002_20230103102701
クロック源はATmega328Pを使ったパルスジェネレータ
拡大。
003_20230103102701


| | コメント (0)

2022年12月20日 (火)

ガレージのLED表示デジタル時計がダウン

昨晩、表示が不自然に点滅しているのに気が付きました。
   ・・・20年以上連続運転してた

資料、vectorにアップしてました。
  ・AVRCLK:AVRマイコンで作るデジタル時計
AVRマイコンAT90S1200を使ったLED表示デジタル時計の製作

おそらく、スイッチング電源が原因。
別のもの交換してみます。

11_20221220093201
回路図
Tokei1

AT90S1200
 ROMが1kバイト。
 RAM無し
  ということで、push、pop命令無し
 スタックは3段だけ。
むちゃ縛りのあるマイコンです。

※追記
ELCOの「ゴリラ」を外して、別の5V定電圧電源に
接続したら・・・OK。
バックアップも働いていて、現時刻をちゃんと表示しました。
   ・・・「たいしたもんや」と自画自賛。
これから、使えそうな電源を探しますわ。

※電源を交換して修理完了
12_20221220104201

「ゴリラ」の中は充填剤でどうなって
いるのか見えません。
13_20221220104201

以前にこんな報告してました。
  ・2019年8月21日:7seg LEDの輝度低下
「電源交換したか?」と記してましたが、昔の写真を
見ると、電源はこのゴリラから換えていませんので、
20年動いたということですわ。





| | コメント (0)

2022年11月15日 (火)

FLUKE 87IV デジタルテスターのデータをIrDAで吸い上げる

2022年7月6日:デジタルテスター「FLUKE 87IV」の赤外線通信ユニット完成
これでいちおう完成してるんですが、IrDAのインターフェース・チップを
テキサス・インスツルメンツの「TIR1000」 に換えて試してみました。

マイクロチップの「MCP2122」 と何が違うのか・・・

図示すると・・・ピンは同じ配列。
Tt11

(1) MCP2122は8pin DIPのがある。 そして安価。
 TIR1000はSOPとTSSOP。

(2) リセット入力の論理レベルが異なる。
 MCP2122はLでリセット。 TIR1000はHでリセット。

(3) 赤外線の自己反射光の処理が違う。
 こちらから出した赤外線、どこかに当たって返ってきて
 受信光としてRXIR信号に入ってきます。
 MCP2122では送信中のRXoutは禁止してくれるので、
 これを考えなくて良いのです。
 ところがTIR1000では筒抜けに。
 自分で処理しなくちゃなりません。

この(3)せいで、単純なターミナルでの実験だとローカルエコーが
返ってくる感じになります。

マイコンでの処理だと、IrDAへのシリアル送信処理が始める前に、
IrDAからの受信を禁止しちゃって無視するように。
そして、送信完了で受信を再開。
こんな手順を制御プログラムに入れなくてはなりません。

前に紹介したATtiny841のプログラムでは、
「送信データレジスタ空き割り込み」で次データを送り込んで
いたのですが、受信を再開させるには送信完了(全フレームの
送出完了)を知らなければなりません。
送信割り込みの方法を変えなければなりませんでした。

TIR1000を使うメリットって無いぞ、なんですが、
試しに回路を作っちゃったんで、仕上げてしまいました。
ジャンパーを追加してMCP2122かTIR1000かを切り替えられ
るようにしました。

| | コメント (0)

2022年10月 8日 (土)

数値をBCD出力(表示)するルーチン

ROM、RAM容量に余裕のあるマイコンなら
「printf」系の「sprintf」で文字列に
変換してシリアル出力、あるいは液晶表示
という手法が使えます。

しかし・・・
  ROM、RAMに余裕がないなぁ
  BCDにして出力(表示)するだけなのに
てな時に役立つルーチンを紹介しておきます。

・longデータ ということは整数だけ。
・ゼロサプレス付で数値に変換。
・マイナスは最も左側の数字の頭に「-」を付加。
・数値「-12345」の最小桁が0.001を意味する時の
 ため(例えば-12.345Vと表示したい)、整数部桁数
 と小数部桁数を指定できるようにした。
・値が指定桁数より大きくなっても、左にはみ
 出さない。
   液晶表示などでは表示がズレないけれど
   越えた部分の数字は見えない。
・1文字シリアル出力ルーチンの名をtx()として
 記している。
   液晶表示なら1文字書き込みに変える。
・「 -12.345」と出力したいのなら
   (先頭にスペース1コ付けている)
      txbcd(d, 4, 3);
 これで、-999.999 ~ 9999.999 の範囲を
 出力できる。
 -32768 ~ 32767のint値なら(longにキャストして)
   「 -32.678」~ 「  32.767」
  頭にスペース1つ  頭にスペース2つ
 wordなら
   「   0.000」 ~ 「  65.535」
  頭にスペース3つ  頭にスペース2つ

/*****  桁指定BCD出力       *****/
// n:整数部文字数 p:小数部文字数
// 数値は整数を入力 浮動小数点ではない
// 小数部は整数の基数が0.01などの時に用いる
// 12345が123.56を意味する時 (d,3,2)と指定
void txbcd(int32_t d, byte n, byte p)
{
char bff[20]; // 20文字(null入れず)
byte i, m;
byte sgn = 0; // 符号フラグ
memset(bff, ' ', sizeof(bff)); // スペースで埋める
if(d < 0){ // マイナス?
d = -d;
sgn = 1;
}
m = n + p; // 整数+小数 文字数
for(i = 0; i < (sizeof(bff) - 2); i++){ // longで12文字とマイナス
bff[i] = (d % 10) + '0'; // 下位桁から0~9に
d = d / 10; // 1/10して上位桁の処理
if((d == 0) && // 0になったら終わり
(i >= p)) break; // 小数桁ok?
}
if(sgn){ // 元値がマイナス?
bff[i + 1] = '-';
}
for(i = 0; i < m; i++){
tx(bff[m - i - 1]); // バッファを逆順で
if(p){
if(i == (m - p - 1)) tx('.'); // 小数点
}
}
}

例に記した「12345が123.56を意味する時 (d,3,2)と指定」
だと、整数部が3桁だけですのでマイナスを考えると正常に
出力できる(落ち無く)数値の範囲は「-99.99 ~ 999.99」
となります。

プログラムそのものは30行もありませんが、実プログラム
ではこれでも300バイトを越えてしまいます。
もっと小さくしたいときは、
 ・long:int32_t → int16_tに
 ・bffをローカル変数(スタックの処理が入る)で
  はなく関数の外に持ってくる。
てなところでしょうか。

sprintfだと、数値の単位や区切り文字を含めて1行
に表記できて便利ですが、これは数字だけ。

longの剰余と除算を使っています。
アセンブラで書くとなると、ここらから始めなければ
なりません。

Arduinoの「print」は数値の桁数を指定できない
ので不便。
数値とゼロサプレスの数を合わせて桁を揃えて
出力したい時は面倒でも「sprintf」。

 

| | コメント (4)

2022年10月 6日 (木)

5chサーミスタ温度計のA/D入力、map関数を使って補正

スカタンな応用例ばかり出てくるArduinoのmap関数
サーミスタ103JTで計った温度をシリアル出力 でのA/D変換値補正
で使ってみました。

まず、A/D入力電圧実測値と基準電圧値から真のA/D値を計算します。
  ツールはデジタルテスター。
  それと電圧発生器、あるいは抵抗を組み合わせて
  安定した入力電圧を得ます。
マイコンにはその時のA/D値をシリアル出力させます。
0に近いある値と1023に近いある値の2点をチェック。
どちらも同じなら補正の必要はありません。
ちょっとのズレなら「直線補間」の出番です。

今回の回路、サーミスタをつなぐch1~ch4はポートAでしたが
ch5だけがポートB。
この間でちょっとズレが出ていました。
まず0Vに近い方。
正値20に対してch1~4が17と-3。
ch5が16と-4と低めの値が出ていました。
フルスケールに近い方は、正値991に対して
ch1~4が992にと+1。ch5は誤差なし。

パラメータのテーブルにはこれらの値を10倍して設定します。
  ※浮動小数点にするとメモリーを食うので。
読み込んだA/D値も10倍してmap関数に食わせて補正を
行い、出てきた値の1の位を見て四捨五入。
10倍することで四捨五入の処理ができます。

これで、ずいぶんと温度測定の調子が良くなりました。
サーミスタの抵抗が低くなる高温域ではA/D値が小さくなります。
A/D入力電圧の低いところで誤差が生じていたのでこの補正が
うまく働いたのでしょう。
80℃付近ではA/D値の1bitが0.3~0.4℃の差になります。

map関数の応用例ということで、ご覧下さい。

//  A/D補正パラメータ
// 四捨五入のためA/D値を10倍にして
// x0とx1に実測値を設定する
// Rs = 10kΩで
// Lo側 200Ωでy0=20  Hi側 300kΩでy1=991
const struct{
const word x0; // in min (Lo)
const word x1; // in max (Hi)
const word y0; // out min
const word y1; // out max
}adj_tbl[] PROGMEM = {
{ 170, 9920, 200, 9910 }, // ch1 ADC1 PA1
{ 170, 9920, 200, 9910 }, // ch2 ADC2 PA2
{ 170, 9920, 200, 9910 }, // ch3 ADC3 PA3
{ 170, 9920, 200, 9910 }, // ch4 ADC7 PA7
{ 160, 9910, 200, 9910 }, // ch5 ADC8 PB0
};
/***** 線形補間 *****/
long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
/***** A/D値補正 *****/
// in ad : 0~1023 A/D値
// ch : 0~4 ch1~ch5
// 10bitの範囲でリターン
word adadj(word ad, byte ch)
{
long a, d;
a = map((long)ad * 10L, // 線形補間
(long)pgm_read_word(&adj_tbl[ch].x0), // in_min
(long)pgm_read_word(&adj_tbl[ch].x1), // in_max
(long)pgm_read_word(&adj_tbl[ch].y0), // out_min
(long)pgm_read_word(&adj_tbl[ch].y1)); // out_max
d = a / 10; // 1の位で四捨五入 10の位を+0か+1,-1
if(a >= 0){ // プラス
if((a % 10) >= 5) d++;
}
else{ // マイナス
if(((-a) % 10) >= 5) d--; // 正にして1の位で判定
}
if(d < 0) d = 0; // マイナスは0に
else if(d > 1023) d = 1023; // 最大は1023
return (word)d; // wordにしてリターン
}


5chの温度測定で重要なのが「Rs」=「神様抵抗」。
今回の製作では「0.1%」精度のを使ったので、
補正テーブルの「y0、y1」(out_min、out_max)は5chとも
同じになっています。
Rsの誤差は、この値の変更で吸収できます。

使っているAVRマイコンは14ピンのATtiny841。
ROMが8kバイトにRAMが512バイト。
現在のプログラムサイズが3826バイト。
このうち2048バイトが10bit ADC→0.1℃温度データ
の変換テーブル。
プログラムは実質1778バイト。BSSエリアが58バイト。

浮動小数点使わず。sprintf使わず。
この結果だと。

ROM、RAM容量半分のATtiny441にも入るかしら。

| | コメント (0)

2022年10月 5日 (水)

サーミスタ103JTで計った温度をシリアル出力

サーミスタ103JTで計った温度をアナログ出力
この製作で使ったマイコンは8ピンのATtiny85
内蔵タイマーが8ビットで、PWM出力でD/Aするには
分解能不足。
そこで、DACを使ってアナログ電圧を出力しました。

今回の「ダイソー ミニケース 5個組」を使った工作
やはりサーミスタ103JTを使った温度計なのですが、
シリアル出力でデータを得ようと目論見ました。

14ピンのATtiny841を使って、5つのサーミスタを
つなげられるようにしています。

ブロックダイヤグラム
C51_20221005170901
1秒間隔で測定値を出力します。
先頭が6桁数字が連番。
  データ抜けをチェックできます。
スペース区切りで5つの温度を出力。

セミテックの103JT温度・抵抗値表が元データ。
-30.0℃~125.0℃をテーブルにしています。

  ※10bit A/D値から温度データテーブルを
   直に呼び出すことで、浮動小数点関数計算
   を使わなくて済みます。
   ATtiny841のROMサイズは8kバイトしかあり
   ません。
   浮動小数点や「sprintf」による数値→文字列
   変換関数を使うと、ROM領域が足らなくなって
   しまいます。
   可能ならROM半分のATtiny441でも動くようにと。

ところが・・・ここでも失敗に遭遇。
  ATmega328Pを使ったピピちゃん温度計
では、外に取り出した内蔵基準電圧1.1Vを使っての
サーミスタ抵抗測定がうまく行ったので、ATtiny841でも
大丈夫だろうと考えたのです。

  ※ATtiny841と同じ14ピンのATtiny84は
   内蔵基準電圧を外に取り出せない。
   そして、外部からの基準電圧も2.0Vが
   最低というスペックで断念。
   ・回路設計はデータシートの熟読から。 スペックをちゃんと調べろ!

こんな接続をしたかった。 (ATmega328Pでは実績あり)
C52_20221005171201
ATtiny841のAREFピンからちゃんと1.1Vは出てきました。
これを低オフセット電圧のオペアンプでバッファします。
しかし、この出力を「神様抵抗」のプラス側としてA/D変換
すると・・・オープンにしても(10kΩでAREF電圧につながる)
フルスケールの「1023」が出てこないのです。
5つのチャンネルとも、計算値より低い値が出るのです。
フルスケールに近い電圧の高い所だと2~3。
電圧が低い所だと、3~4、出てくるA/D値が小さいのです。

全体に下へシフトしてる感じです。
  ※ATmega328Pではこんなことには
   ならなかった・・・

そこで、外部から基準電圧を供給してみることに
しました。
  ※基準電圧を出力するAREF端子。
   ノイズ低減のためにパスコンを入れる
   ためのもの。この電圧出力を利用
   できるとは、データシートには記され
   てない。
  ※ATtiny85や84では2.0Vが最低電圧
   という制限あり。
C53
そうすると大丈夫に。
  ※完璧に誤差がないというわけではく
   そこそこエエ感じ。

ということで、
 「同じシリーズのチップでうまいこと行った
  経験があっても、始めて使うチップは、何が
  あるかわからへんでぇ」
と、あたりまえの結果に。

ダイソーのプラケースに入れるとこんな感じ。
Cc1_20221005171601

  ※L型ダブルのピンヘッダーが無かったんで、
   オムロンのツメ付ヘッダーを切断改造。

| | コメント (0)

2022年10月 3日 (月)

サーミスタ103JTで計った温度をアナログ出力

失敗談、2022年9月28日:回路設計はデータシートの熟読から。 スペックをちゃんと調べろ!
この発端の製作物です。

「温度→電圧」変換はLM35やTMP35あたりのセンサーが
便利なんですが、ブツに接触させて温度を測るときにちょいと
問題があるんです。
 ・形状のせいか応答が遅い。(TO-92パッケージ)
 ・足から熱が逃げるのか、低い目の温度が出る

  ※型番、LM35は、昔はナショセミ。今はTIに。
   そしてTMP35はアナログ・デバイセズに。
   ややこしいぞ。

応答が早くて間違いなくブツに接触できる温度センサーという
ことで、「セミテックのサーミスタ103JT」を使って、
 ・センサーの抵抗値から温度を算出。
 ・温度をD/A出力。
という方法で、アナログ値を得るようにしました。
  ※単純なことをするのに、むちゃたいそうな回路。

Tn85_thm1

ATtiny85を選んだんがそもそも失敗。
でも、作りかけたんで、完成形に仕上げてみました。

測定温度範囲は0~80℃。
10bit分解能のA/Dで温度を得てますんで、分解能は
ざっと0.1℃。
これを0.0V~4.0Vの電圧に変換します。
1℃あたり0.05Vのスケールです。

AVR studioでプログラムを組んでます。
フォルダーごと圧縮。
   ・ダウンロード - thm_85_da1.zip

10bitのA/D値から2kバイトのテーブルで温度に変換
という手抜き手法。
複雑な算術関数は使っていません。

回路を組み込んだプラケースはダイソーの「ミニケース5個組」
M31
M32

この回路の電源は、
Arduino-UNO 12bit×4chアナログ SDカードデータロガー完成形
から供給します。

さて、温度センサーIC:LM35(TMP35)とサーミスタ103JTの
違い、どんなもんかと調べますと・・・

15Ωのホーロー抵抗の側面にセンサーをくっつけて、
抵抗を通電して発熱させます。
その時の温度変化を電圧として記録しました。

M11_20221003101301

M12_20221003101301

まずは、センサーを軽く貼り付けした状態から。
M13_20221003101301
すると・・・
Cap004_20221003101401
センサーICとサーミスタの出力に差が生じます。
時間が経過してもそれが埋まりません。

M14_20221003101301
テープでぐるぐる巻きにして、温度が逃げないように
したつもりでも・・・
Cap005_20221003101401
途中で段ボール箱をかぶせましたが、時間が経っても
2℃くらいの差が埋まりません。

そこで、2017年11月6日:液晶表示器「焼き鈍し」
で使った「保温箱」で試してみました。
この2種以外にも、センサーICとサーミスタを加えます。
M21
2と4が今回のセンサー。
1はセンサーICの外周を熱収縮チューブで覆っています。
4は同じ103JTですが、先端近くまで熱収縮チューブが来ています。

センサー部分はむき出しのまま、電線のところでマスキングテープを
巻いてまとめました。

65℃で保温された箱の中に投入しますと、数分で4つとも温度が
安定、収束します。
  ※電線部分、およそ20cmは保温箱の中に入っていて、
   先端のセンサー部と同じ温度になっているかと。
Cap006_20221003103401

また、4つのセンサーを箱に入れたまま、箱を室温
から加熱した場合も20分ほどで65℃に到達し、
その後の温度差はそれほど感じません。

Cap007_20221003103401
  赤:保温箱温度制御センサー
  緑:サーミスタ 4
  青:サーミスタ 3
  マゼンタ:センサIC 2
  シアン: センサIC 1

発熱体に直接接触させて温度を測る場合と、周囲の空気ごと
温度を測るということで差が生じるのでしょう。

このあたりをもうちょい勉強しようとすれば、何を
調べれば良いでしょうか?

| | コメント (6)

2022年9月29日 (木)

103JTサーミスタの自己発熱。 5Vで10kΩはちょっとなぁ

前記事2022年9月28日:回路設計はデータシートの熟読から。 スペックをちゃんと調べろ!
は、サーミスタを使った温度測定に絡みます。

Arduinoにサーミスタをつないで温度測定・・・
複雑な計算式も入るし、サーミスタを指で触れば温度変化が
出てくるし。
マイコンを活用してる気分になれます。

しかし・・・ちょっと待てぇ
  そのやり方は正しくない。
  サーミスタが持つ性能をつぶしているぞ。
という例を見かけるのです。
  ネットでも初心者向けの本でも。

安価で入手しやすいからとよく出てくるのが
セミテックの「103JT」
  応答性が良いので私も愛用しています。

このサーミスタの特性を分かって「こんなもんだ」と
使っているのなら仕方ないのですが、きっと分かって
ないのだろうなぁというスペックが「熱放散定数」。

サーミスタに電流を流した時、その消費電力で自分が
発熱してしまい、測定温度に誤差が生じます。
その影響度合いで、単位が「mW/℃」。
「ンmWの測定電力で1℃上がる」という指標です。
103JTだと「約0.7mW/℃」というスペックが出ています。

  ※形状の大きな103AT-11だと3mW/℃、
   103AT-2だと2mW/℃。
   大きくなると頑丈になりますが、応答が
   遅くなります。

103JTの約0.7mW/℃、これ、なかなかキツいスペックなんです。
よく出てくる例がこの図のような接続。
【図1】
T1_20220929114401
サーミスタに直列に10kΩの抵抗を入れて5V電源に接続。
ArduinoのADCは、基準電圧=5Vで変換。
   ※
サーミスタを使って温度測定という解説記事、
    たいていはこれ。

これだとどうなるか。
サーミスタの抵抗値とRsが同じ値になったときが
最大の消費電力になります。
   ※103JTだったら10kΩの25℃
どれだけの発熱があるかをグラフに。
Cap036
各温度での抵抗値からサーミスタの消費電力を算出し、
熱放散定数で温度上昇を計算しました。
  ※5Vだけでなく、3.3V、2.5V、2.0V、1.25Vの
   電圧の時も示しています。

測定電圧=5V、Rs=10kΩだと10~40℃の温度域で
およそ0.8℃の温度上昇が生まれると。
Arduino UNOの10bit ADCだと、0.1~0.2℃が
分解能です。
それに0.8℃が積み重なるのは・・・ちょっとなぁ。です。
  ※これをどうにかしたいと思うか、
   こんなもんでエエやんと置いとくか・・・

この温度測定方法でサーミスタの消費電力=発熱を
減らすには・・・
 ・測定するときだけ通電する
 ・測定電圧を下げる
 ・Rsを大きくする
この3つです。

Rsを変えた時の様子がこのグラフ。
15kΩと20kΩにした時の発熱です。
Cap037
Cap038
Rsを大きくするより、サーミスタへの供給電圧を
下げる方が効果があります。
   (電力の計算式 ExE/R、IxIxR)

※Rsを4.7kΩにしたら・・・
Cap001_20220930145401
40~50℃あたりで、自己発熱が1.9℃ほど積み
上がってしまいます。

~~~~~~~~~~~~~~~~~~~~~~~~
サーミスタへの供給電圧を下げての測定方法、
どんなのが・・・
例えば、こんな回路。
【図2】
T2_20220929114901

サーミスタへの供給電圧とA/Dコンバータの基準電圧
を分けてやると、測定温度範囲が自由に決められます。
ところが、この回路だとやっかいな問題が出てくるの
です。
VthmとVzが変動したら、それが測定系の誤差に
つながります。
サーミスタの抵抗値を正しく算出するにはVthmとVzの
絶対値が必要なのです。
どちらかの電圧が動くとアウト。誤差が生じます。
  ※動くなら二つが比例して。
  ※VthmをそのADC測定系で計るのも方法。

それを改善するのがこの方法。
【図3】
T3

【図1】は5V電源でしたが、ADCの基準電圧と
サーミスタへの供給電圧を両方とも下げて発熱を
防ぎます。
二つを同じ電圧にというのが重要で、サーミスタの
抵抗値はRsを基準に算出でき、Vzは計算式から除け
ます。
このRsは「神様抵抗」(俺が正しい!)となります。

Arduino UNOで使っているATmega328Pマイコンのように
Vref電圧が外に取り出せるなら、こんな方法も可能です。
【図4】
T4
Arduino UNOだと「1.1V」が取り出せます。
  ※測定電圧が低い方が自己発熱が小さくできる。


サーミスタを使った測定で、もう一つのグラフを示しておきます。
ADCの分解能を変えた時、測定温度の最小値がどう変化するかを
描いています。
神様抵抗Rsを10k、15k、20kにした時を計算してみました。
Cap039_20220929115501
Cap040_20220929115501
Cap041_20220929115601

Arduino UNOの10bit A/Dだと、常温域で0.1~0.2℃の
分解能がギリギリになることが見えます。
発熱の影響を小さくしようと、Rsを大きくすると、
サーミスタの抵抗値が小さくなる高温域での分解能が
落ちてしまいます。
  ※Vz=ADCの基準電圧=Vthmとしてのグラフです。
   Vz=Vthmが変わっても分解能は変わりません。

 

※関連
2021年8月11日:サーミスタ温度計、何ビットのA/Dコンバータがいるか?
2021年7月31日:16bit A/Dコンバータ LTC2460 サーミスタ103JTを使った温度測定で・・・
2018年2月13日:ピピちゃん温度計・ヒータ制御

※ネット検索
ラジオペンチ:Arduiono を使ってサーミスタで温度を測る(2019-11-08)
ラジオペンチ:ペルチェ温度コントローラーの製作 (温度センサーをサーミスタに変更)(2019-11-11)
セッピーナの趣味の天文計算:サーミスタで正確な温度を測るコツ - 基準抵抗(R0)、B定数、熱拡散係数(2015年2月18日)
マカロニペンギンの健忘録:#arduino で温度測定-自己発熱対応版(2011年11月17日)

あれこれ見てますと・・・
サーミスタの抵抗測定の手順で、A/D電圧を求める時、
件の「1/1023」 が多く出現しています。
例えば、
Decent dress:Arduino Nano と NTCサーミスタで温度計測 (2018/11/29)

本来、Rsを神様抵抗としての測定系では、A/D変換の
基準電圧値は数式から除外されます。
しかし、電圧計算の1/1024を1/1023にしてしまうと
「‰」単位の誤差が生じます。   ※10bitのADCで

jh4vaj:Arduinoでサーミスタを使って温度計を作るのに、電圧を求める必要はない(2021/3/9)
jh4vaj:ArduinoのADコンバータ、1023?1024?( )

| | コメント (0)

2022年9月28日 (水)

回路設計はデータシートの熟読から。 スペックをちゃんと調べろ!

8ピンのATtiny85、14ピンのATtiny84のA/D入力絡みで
ちょいと失敗。

◆状況
・テスト用ジグ作り。
・内蔵のADCを使ってアナログ電圧を測定。
   サーミスタで温度測定
・基準電圧はできるだけ低くしたい。
   サーミスタの自己発熱の防止
・内蔵基準電圧の1.1Vを外に引っ張り出せれれば
 良いんだが、tiny85もtiny84もそれはできない。
   Arduino UNOのATmega328Pは可能
・基準電圧を外部に持たせて、Arefピンに供給か。

こんな考えで回路を組んだのです。

◆参考:基準電圧の切換
ATtiny85の場合
VccかArefか、内部の1.1Vあるいは2.56V。
85_0

ATtiny84の場合
VccかArefか、内部の1.1V
84_0

この基準電圧選択で
 「内部の1.1Vが使えるんだから、Arefピンに外部の
  基準電圧として1.1Vを加えてもかまわないだろう」
と、勝手に推測。

これが間違い。
A/D変換のスペック表を見ますと・・・
ATtiny85
85_1

ATtiny84
84_1

いずれのチップもAref:外部基準電圧の最小値は「2.0V」

外部から1.1Vを入れると・・・
  A/Dから全ビットHのデータが出てきます。

Arefに入れてる電圧が低いんやぁ」の原因に到達するのに
えらく手間取りました。
I/Oの初期化ルーチンで、A/Dの基準電圧をVccや内部電圧に
切り替えると正しく変換。
おもわく通りのデータが出てきます。
ところがArefにして外部からの1.1Vだとアウト。

その後、データシートを熟読したら「最小2.0V」という
記述を発見
したという次第です。
  Aref電圧も徐々にアップすると、1.5Vくらいから
  データが出始め、2.0Vのちょい手前から安定になる
  という挙動でした。

 

| | コメント (0)