オシロスコープに何でも描画します
コンポーネントと消耗品
> |
| × | 50 | |||
| × | 1 |
アプリとオンラインサービス
> |
|
このプロジェクトについて
R-2R DAC
デジタル-アナログコンバータの最も単純な実装の1つは、R-2RラダーDACを設計することで実現できます。このタイプのDACは、動作するのに抵抗だけが必要であり、非常に初心者に優しいDACです。
このタイプのDACの基本原理は、抵抗に2つの値が必要なだけであるということです。 Rと2R。次に、下の図に示すようにそれらを設定できます。
<図>回路図でRが出現するたびに同じ値である限り、Rは何でもかまいません。
たとえば、R =1kを選択した場合、2Rは2倍の量になります。この場合、2R =2kです。したがって、1kと2kの抵抗だけを使用できます。
R =3.3Kを使用した場合、2R =6.6kなどになります。すべてに同じ値の抵抗を使用したい場合、2Rを取得するには、2つの抵抗を直列に配置するだけで、コンポーネント数が増えます。
ビット数は、2Rの分岐の数によって決まります。このプロジェクトでは、ArduinoUnoまたはNanoに8ビットR-2Rと6ビットR-2Rを使用します。 STM32「ブルーピル」や「ブラックピル」など、少なくとも8ビットのフルポート操作をサポートしていることがわかっている別のマイクロコントローラーを使用している場合は、2つの8ビットDACを使用できます。
DAC ICに関する補足事項:
このプロジェクトはR-2RDACの使用に焦点を当てていますが、DACICを使用して同様のことを自由に実現できます。 DAC ICを使用する場合は、I2Cが遅すぎて詳細な画像を描画できないため、SPIなどの高速通信プロトコルをサポートするものを使用することをお勧めします。この投稿ではDACICの使用方法については説明しませんが、将来的には使用する可能性があります。 R-2R は、より詳細な画像を出力できるため、今でも私の好みの方法です。
ポート操作
マイクロコントローラのパラレルポート操作を使用します。これを行う理由は、出力速度が速くなり、コードが単純になるためです。 Arduinoのポートレジスタの詳細については、このリンクを参照してください。
Arduino UnoとNanoには、ATmega328pマイクロコントローラーが搭載されています。このマイクロコントローラーは、Atmega168と同じピンマッピングを共有しています:
<図>ポートピンとビットは、ラベルPXNで示されます。ここで、Xはポート文字、Nはビット番号です。
例:PB1はポートBビット1用です。同様にPC5はポートCビット5用です。
ピンを調べると、マイクロコントローラーにポートB、C、およびDがあることがわかります。Arduinoリファレンスに戻ると、どのポートに書き込みまたは読み取り、あるいはその両方ができるかがわかります。私たちのアプリケーションでは、書き込みのみを考慮しています。
<図>ドキュメントには、PORTDは読み取り/書き込み可能であり、デジタルピン0〜7にマップされていると記載されています。これにより、書き込み可能なポートの完全な8ビットが得られます。
次に、前述のようにデジタルピン8〜13にマッピングされたPORTBがあります。完全な8ビットを完了する6&7にはアクセスできないという追加のステートメントが作成されます。このポートは、6ビットの書き込みにのみ使用できます。
同じことがPORTCにも当てはまります。アナログピン0〜5にマッピングされますが、2つのピンも予約されており、書き込みに6ビットしか使用できません。
これらの制限があるため、PORTDには8ビットDACを、PORTCまたはPORTBには6ビットDACを組み合わせて使用する必要があります。
PORTDとPORTBを使用し、DACのピンへの配線を開始できるようになります。
組み立て方法について視覚的な補助が必要な場合は、これが私がブレッドボードに両方のR-2Rを組み立てた方法です。 STM32「ブラックピル」でテストしていたので、2つのR-2Rを使用したことに注意してください。オシロスコープのプローブをそれに接続できるように、2本のジャンパー線を突き出して配置しました。また、側面のアース線も接続しました。私はすべての10k抵抗を使用したので、2Rには2つの10k抵抗を直列に配置しました。
<図>これは、Tinkercadを使用したよりクリーンなブレッドボードのセットアップです。出力にXとYのマークを付けました。これは、オシロスコープのプローブが接続されるものになるためです。セットアップについてさらにガイダンスが必要な場合は、同じ抵抗値を持つすべてのR-2Rラダーと、2つの値を持つ別のラダーで構成されるR-2Rラダーを示す回路図を提供します。
<図>必ず根拠を確認してください!このセットアップを組み立てるたびに、私は忘れがちです。また、接続のないギャップが残っていないことを再確認してください。
ArduinoCode
今度はArduinoスケッチの時間です。
まず、ポートを出力に設定する必要があります。ポート操作に関するArduinoリファレンスから。ポートの設定方法を確認できます:
<図>基本的に、ビットの値が1の場合は出力として設定され、値が0の場合は入力として設定されます。 PORTDの場合、すべてのビットにアクセスできるため、直接書き込むことができます。 PORTBの場合、ビット6と7はクリスタルにマッピングされるため、使用できないことに注意してください。設定されないビットの変更を避けるために、値が0のビットごとのORを使用することをお勧めします。
セットアップループでは、これはコードになります:
<図>コードはダウンロード用に添付されるので、手で入力する必要はありません。
構成の下のforループは、6ビットポートの値を再マップするだけです。これらの値は、8ビット範囲の値を持つリストからのものになります。 6ビットに再マッピングするには、最大値は2 ^ 6-1(63)になります。0から2 ^ 8-1(255)の範囲にマッピングしています。Arduinoコードで再マッピングする理由は、ハンドプロッタツールは、xポイントとyポイントを8ビットで出力します。どちらのコードでも変更できますが、使用するマイクロコントローラーで変更することをお勧めします。
基本的に、オシロスコープによっては多少の遅延が必要です。私の場合は1で問題ないことがわかりました。実際、遅延を完全に省略しても問題ありません。ポイントの場合、ハンドプロッターツールによって自動的に生成されるため、数値をコピーして貼り付けることができますが、基本的には、反復変数がポイントを通過できるように、プロットするポイントの数です。とにかく、ここに完全なコードがあります:
<図>x_points配列とy_points配列は、何かを描画するたびに異なり、ツールを使用して自動的に生成されます。
高速PWMに関する補足事項:
マイクロコントローラーの上級ユーザーであれば、速度が気になる場合は おそらく同じことは、高速PWMとクロックレジスタの変更によって達成できます。次に、PWM出力をローパスフィルターに供給して、ピン数を減らすアナログ電圧を取得します。私は両方の方法を試しましたが、これでもより詳細な画像のサポートが向上します。少なくともArduinoUnoでは
描画ツール
このツールは、tkinterを使用してPython3で作成しました。 tkinterがインストールされていない場合は、pipを使用してインストールしてください。
pip install tk
コードは添付されるだけですが、基本的にはカーソルがクリックされたウィンドウの座標を記録します。解像度が変わるため、ウィンドウのサイズを変更しないでください。より正確にしたい場合は、Windowsの虫眼鏡ツールを使用してください。これらはビット範囲の最大値になるため、ウィンドウは255x255に基づいています。もちろん、Arduino UNOを使用している場合は、次元の1つが6ビットにマップされます。
ツールを呼び出すには、この形式を使用するだけです
python drawlog.py> arduino_list.txt
これにより、arduino_list.txtという名前の.txtファイルが作成され、x_points、y_points、およびNUM_POINTSのArduinoリストが生成され、コードにコピーして貼り付ける準備が整います。
例として、これは、開いたときに.txtファイルがどのように表示されるかを示しています。コード内のこれらの行を置き換える必要があります。
<図>開封後の様子です。そこから何でも描くことができます。
<図>私はそれをテストするために次の絵を描きました。コードはウィンドウを閉じると生成されます。
<図>そして、Arduinoにコードをアップロードした後、これはX-Yモードでのように見えました。
<図>重要:
メモリについて話しているコンパイルエラーが発生した場合、これはArduinoUNOで使用可能なメモリが少ないことが原因です。つまり、詳細度の低い画像を描画する必要があります。最大ポイントは400点くらいだったと思いますが、それ以上かもしれません。 STM32「ブルーピル」または「ブラックピル」を使用する場合、この数は4,000以上になります。
オシロスコープのX-Yモード
オシロスコープはx-yモードに設定する必要があります。 8ビットのR-2RDAC出力(PORTD)はチャンネル1に接続され、6ビットのR-2R DAC(PORTB)はチャンネル2に接続されます。そこから画像が表示されるまでノブで調整できます。
それでおしまい!ご不明な点がございましたら、お気軽にお問い合わせください。さらに、青いピルまたは黒いピルで試してみたい場合は、サンプルコードを含むGitHubページへのリンクをご覧ください
これが私がプロットしたいくつかの画像です。
<図> <図> <図> <図>
お気軽に共有してください!!!
編集:
メモリ管理の重要な詳細
ティムがコメントで述べたように
- Arduinoコードでは、ポイントtのイテレータは「バイト」タイプであるため、最大255ポイントしかサポートしません。 「int」にしてみませんか?
- プロッタコードは、x_pointsとy_pointsに対して「constunsigned long」を出力します。これは、後でyポイントを変更するときに機能しません。また、メモリを節約するために「バイト」を使用しないのはなぜですか?
使用しているハードウェアの制限に注意してください。 Arduino Unoの場合はバイトを使用することをお勧めしますが、STM32またはESP32を使用している場合は、プロットできるポイントが増えます。フィードバックをありがとうございました。
ティムスター :
UNOでサポートされるポイントの数を大幅に増やす方法を見つけました。それらをプログラムのストレージスペースに移動します。これは、 PROGMEM
を使用して行うことができます 修飾子。このようにして、約15,000ポイントを保存できます!
したがって、次のように配列を宣言します。
const int NUM_POINTS =...
const byte x_points [NUM_POINTS] PROGMEM ={...
const byte y_points [NUM_POINTS] PROGMEM ={...
セットアップ関数でy_pointsを変更しないでください(つまり、 for
を削除します そこでループします)。代わりに、ループ機能でビットシフトを実行してください。
プログラムメモリ(pgm_read_byte_near)からデータを読み取るための特別なコマンドも必要です。したがって、 void loop()
のforループ 次のようになります:
for(int t =0; t {
PORTD =pgm_read_byte_near(x_points + t);
PORTB =pgm_read_byte_near( y_points + t)>> 2;
delayMicroseconds(FIGURE_DELAY);
}
次に、1つの高解像度画像または複数の小さい画像を保存し、それらの間を循環することができます😃
コード
- Arduinoコード
- プロットツール
Arduinoコード Arduino
ArduinoUnoまたはNanoボードで使用するArduinoスケッチconstバイトFIGURE_DELAY =1; // uSで遅延をトレースします。必要に応じて調整constint NUM_POINTS =87; //図のXYポイントの数//バイトをプロットするためのxおよびy座標x_points [NUM_POINTS] ={106,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91 、90,90,89,88,87,87,87,86,86,86,86,87,89,90,91,93,95,97,99,101,102,102,104,104,105,105,106,106,106,106,106,106,108,109,110,112,113,115,117,119,121,122,123,123,124,124,124,124,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,110,109,109,109,108,107,107};バイトy_points [NUM_POINTS] ={78,80 、81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,98,99,100,101,103,105,106,108,110,112,113,113,114,115,115,115,115,115,115,114,112,112,110,109,107,106,106,108,110,112,114,114,115,116,116,117,117,117,117,117,116,115,113,112,110,108,106,104,103,102,100,99,98,97,96,95,94,93 、92,91,90,89,87,86,84,82,81,80,78}; void setup(){// DDRDを書き込むためにポートDとBを初期化=B11111111; DDRB =B00111111;バイトt; for(t =0; tプロットツール Python
ポイントをプロットするための描画ツールimport tkinter as tkX =[] Y =[] lastx、lasty =0、0#xy and addLineはグラフィカルな目的のみです#on_move_pressは、リストに1つを記録するツールです。 Ydef xy(event)を修正:#マウスがクリックされたときの座標をログに記録するglobal lastx、lasty lastx、lasty =event.x、event.ydef addLine(event):#古いポイントから新しいポイントに線を引くglobal lastx、lasty canvas.create_line ((lastx、lasty、event.x、event.y))#これにより、描画の新しい開始点が作成されますlastx、lasty =event.x、event.y#listdefのクリックされた座標をログに記録しますon_move_press(event):curX、curY =(event.x、event.y)curY =255-curY#tkinterは異なる座標を使用するためX.append(str(curX))Y.append(str(curY))#windowroot =tk.Tk( )root.geometry( "255x255")root.columnconfigure(0、weight =1)root.rowconfigure(0、weight =1)canvas =tk.Canvas(root)canvas.grid(column =0、row =0、sticky =(tk.N、tk.W、tk.E、tk.S))#バインド左クリックしてfuにドラッグnctionsおよびstartloopcanvas.bind( ""、xy)canvas.bind( " "、addLine)root.bind( " "、on_move_press)root.mainloop() #2つおきのエントリを削除して、ポイントを減らし、範囲内のiのトレースrefreshfor iを増やします(1、int(len(X)/ 2)):X.pop(i)Y.pop(i)print( "const int NUM_POINTS =%s; "%str(len(X)))print(" const unsigned long x_points [NUM_POINTS] ={%s}; "% '、' .join(X))print(" const unsigned long y_points [NUM_POINTS] ={ %s}; "% '、' .join(Y))#call python drawlog.py> arduino_list.txt
回路図
製造プロセス