步驟1:以每秒1M個樣本進行采樣
我們稱這個示波器為“ArdOsc”(因為這是INO文件的名稱)。
六年前,Cristiano Lino Fontana為他的Girino設計發布了一個Instructable。
它有點工作但有問題。特別是,它的最大可靠采樣率約為37ksps(75ksps偶爾會凍結)并且觸發器似乎無法正常工作。它也沒有顯示。
Girino很慢,因為它使用中斷。由于保存和恢復寄存器所需的代碼,中斷很慢。中斷是危險的,因為它們可能導致軟件出現錯誤,而且很少發生錯誤。我已經編寫了40年的嵌入式代碼,我盡可能避免中斷。輪詢好,中斷不好。注意我的話。
因此,ArdOsc禁用所有中斷,進入緊密循環并在需要時從ADC中獲取數據。如果ADC沒有完成:太糟糕了 - 只要給我你所擁有的。它抓取1000個樣本(每個一個字節),然后重新啟用中斷并通過串行端口以115200波特率將字節發送到PC - 或者它抓取128個樣本并將其顯示在屏幕上。
Girino Instructable詳細描述了Arduino ADC。如果您有興趣,請閱讀并閱讀Atmega328p數據表。我只想告訴你大綱。
Arduino ADC使用“逐次逼近”。它測量最重要的位 - 是0還是1?得到它之后,它將其“到目前為止的答案”與輸入電壓進行比較并測量下一個最重要的位。接下來。等等10位。這些位存儲在ADCH寄存器(前8位)和ADCL(后兩位。我只想要8位,所以我忽略了ADCL。
ADC測量全部10位時設置一個標志。但我只想要8位,所以我忽略了標志并讀取ADCH是否ADC完成。我原本以為這意味著我會得到“答案到目前為止”但我沒有。到目前為止的“答案”存儲在其他地方,我們得到的是上傳到ADCH的最后一個答案。這意味著在1Msps模式下,每個連續的4個樣本集都是相同的。 Arduino草圖使它們平滑,因此它們看起來很好但不會被愚弄:你看到250ksps。 (感謝AndrewJ177指出這一點 - 請參閱下面的討論。)
測量每個位需要時間。該定時脈沖來自于將Atmega的時鐘(16MHz)除以“預分頻器”值:2,4,8,16,32,64或128.如果將預分頻器設置為2,則為0.125uS,這對于ADC正確地進行比較 - 質量很差。預分頻器= 4,表示0.25uS哪種工作 - 結果有噪聲。預分頻器= 8,表示0.5uS,對于8位非常合理。一般來說,每位給ADC的時間越長,工作效果就越好。
但如果你允許ADC,比如每位1uS那么它每個字節需要8uS,即125ksps - 相當慢。如果將預分頻器設置得太低,則只能正確轉換前幾位,并且得到的圖形具有大的鋸齒狀步長。如果將預分頻器設置得過高,則需要等待很長時間才能進行轉換。
因此,這是每比特時間和每秒采樣之間的權衡。
我們還必須考慮輸入信號需要多長時間才能改變ADC采樣保持電容的電壓。我們不會在每次轉換之前更改通道,因此充電時間不必與Atmel文檔建議的時間一樣長,但仍有效果。示波器可以達到20kHz,但響應會下降。您可以看到一個50kHz的正弦波,但它的大小應該是它的四分之一。
ArdOsc代碼只有一個完全正確的長度,以1Msps的速度采樣 - 即它需要16個時鐘周期環。另一個更復雜的循環會占用更長的采樣時間。
第2步:最簡單的示波器
最簡單的ArdOsc由Arduino Nano(328p 16MHz)4個電阻和3個電容組成。
示波器由USB連接供電并傳輸幀通過USB將數據傳送到PC。
輸入信號被送入ADC A0引腳。在極端電壓情況下,10k電阻可為Atmega提供一些保護。 Atmega引腳具有二極管,可防止其輸入超過Vcc(5V)或低于0V。二極管可以傳導高達1mA的電流,因此示波器的輸入信號可以安全地在-10V和+ 15V之間變化。 ADC引腳的輸入阻抗約為100M和14pF,因此額外的10k對ADC的精度影響不大。
ADC使用Vcc作為參考電壓讀取A0引腳電壓 - 因此測量范圍為0V至5V。 (實際上它是0到Vcc * 254/255。)不幸的是,Vcc很少是5V,所以程序讀取Vcc的實際值并適當地繪制“示波器顯示”的格線。
輸入是也通過一個100nF電容饋入ADC A1引腳。 A1通過1M電阻連接到0.55V。因此,A1引腳看到輸入信號的交流分量以0.55V為中心。
ADC使用內部1.1V參考電壓讀取A1引腳電壓 - 因此測量值為-0.55V至+ 0.55V。
0.55V是由Nano的3V3引腳的分壓器產生的。 3V3引腳電壓比USB連接的“5V”穩定得多。 3V3引腳的輸出不完全是3.3V,因此您必須修整分壓器以提供0.55V的電壓。將示波器輸入連接到地,然后查看AC范圍顯示的“電壓”。調整R1直到線位于屏幕中心 - 我需要R1 = 33k。
我已經展示了電路的條形板布局。條形板與Arduino Nano的尺寸相同,形成三明治。 Nano的底面位于條形板的銅側(因此在圖中,Nano從下方顯示)。將一些引腳焊接到條板上,然后將Nano安裝在引腳上并將它們焊接到Nano上。在我的圖表中,條形板的銅以青色顯示。紅線是條形板上的導線或柔性導線從電路板上傳出信號和電源。
步驟3:放大信號
“最簡單”示波器有兩個輸入范圍:
0V至5V
-0.55 V至+ 0.55V
但我們感興趣的許多信號都小于此值。因此我們可以添加兩個放大級。
LM358雙運算放大器放大A1的AC信號。運算放大器采用交流耦合,兩個輸入均以0.55V為中心。兩個運算放大器級的增益都不到5倍。它們的輸出轉到A2和A3,因此Atmega可以選擇要采樣的信號。
示波器現在有四個輸入范圍:
0V到5V
-0.55V至+ 0.55V
-117mV至+ 117mV
-25mV至+ 25mV
它使用相同的INO文件并且作為“最簡單”的執行。
將交流信號對中在0.55V附近的優點是運算放大器信號保持低電平。 LM258輸出不能在Vcc的1.5V范圍內;所以它的范圍是0V到3.5V - 可怕。
我已經展示了電路的條形板布局。有兩個條板 - 一個用于Nano,另一個用于LM358。他們應該形成三明治。電路板從元件側顯示。精細的柔性電線連接兩塊板。將電路板與粘墊,焊接支架或其他任何東西連在一起。在我的圖表中,條形板的銅以青色顯示。紅線是條形板上的線鏈或將板連接在一起的柔性線。我沒有顯示“測試引線”。
再一次,你可能需要修整分壓器給0.55V。將示波器輸入連接到地并調整R9直到線位于屏幕中央 - 我需要R9 = 33k。
LM358可能存在問題。如果信號大于LM358可以處理LM358的輸出失真。您應該使用較高增益設置來查看小信號。如果你在大信號上使用它們,它們就會變形。你可以嘗試更好的芯片 - 如果你有一個 - LM358是一個相當差的芯片。
第4步:邏輯顯示
通常你在處理邏輯電平 - 示波器是否可以顯示幾個“邏輯”通道。是的 - 這比搞亂ADC更容易。
值得嗎?可能不是,但很容易這樣做為什么不呢?
示波器現在有五個輸入范圍:
0V到5V
-0.55V到+ 0.55V
-117mV至+ 117mV
-25mV至+ 25mV
邏輯
在“邏輯”中“模式,四個邏輯通道可以連接到Arduino引腳D8,D9,D10和D11。它們在顯示屏上顯示為四行。
D8至D11對應于Atmega328p芯片的端口B引腳0至3.芯片將整個端口B讀入其采樣緩沖器而不是ADC輸出在ADCH寄存器中。
在1Msps模式下,你能看到的理論最大頻率是500kHz - 但你得到的只是一個“狀態變化”的實心條。實際上,250kHz信號更容易看到。
如果您不想要“邏輯”輸入,則不要將連接器包括在D8到D11中。在INO文件中,將bool常量bHasLogic設置為false。 (我嘗試重新編寫代碼以使用#define而不是bool const但是它很亂。)
步驟5:觸發器
假設您正在查看重復波形,例如正弦波。如果示波器在每次掃描時在屏幕上的相同位置顯示它,那就太好了。因此,示波器掃描應該被啟動,就像波從負變為正。
首先我嘗試使用比較器來觸發掃描(即開始收集數據)吉里諾做到了。它似乎很理想,但結果卻有缺點。我決定使用0.55V的固定觸發電壓 - 交流信號的中間位置。 Atmel允許您將比較器連接到當前ADC通道。聽起來不錯。但您必須關閉ADC,并在觸發發生時再次將其重新打開。 ADC需要一段時間才能啟動。不太好。
所以我采取簡單的方法 - 運行ADC并觀察它產生的值。當它們從中途下降到中途時,開始掃描。
在“邏輯”模式下,D8用作觸發器。
如果沒有信號則示波器應該是自由運行的。在等待一段時間后開始掃描。我選擇了最長等待250毫秒。程序初始化Timer1(一個16位定時器),然后等待,直到它計算了足夠數量的滴答。我只是看著Timer1的計數器 - 應該有一個更好的方法來使用標志,但它非常復雜,我無法讓它100%可靠地工作。
步驟6:測試信號輸出
您偶爾需要一個信號來測試您正在構建的任何電路。很多人已經有了信號發生器。
ArdOsc電路可以提供以下頻率的方波:
31250/1 = 31250Hz
31250/8 = 3906Hz
31250/32 = 977Hz
31250/64 = 488Hz
31250/128 = 244Hz
31250/256 = 122Hz
31250/1024 = 31Hz
測試信號在引腳D3上生成。
如果您不想要“測試信號”輸出,則不要包含連接器D3。在INO文件中,將bool常量bHasTestSignal設置為false。
步驟7:串行協議
示波器通過USB電纜將數據幀傳輸到PC,就好像它是115200波特,8位,無奇偶校驗的串行數據流一樣。
PC可以將兩種命令發送到示波器。小寫命令是單個字節:
‘a’將x軸設置為“1mS”= 1Msps
‘b’將x軸設置為“2mS”
‘c’將x軸設置為“5mS”
‘d’將x軸設置為“10mS”
‘e’將x軸設置為“ 20mS“
‘f’將x軸設置為”50mS“
‘g’將x軸設置為”100mS“
‘j’set y -axis to 5V
‘k’設置y軸為0.5V
‘l’設置y軸為0.1V‘m’設置y軸為200mV
‘n’將模式設置為“邏輯”
‘p’將觸發設置為下降
‘q’將觸發設置為上升
‘r ’設置測試信號關閉
‘s’設置測試信號31250Hz
‘t’設置測試信號3906Hz
‘u’設置測試信號976Hz
‘v’設置測試信號488Hz
‘w’設置測試信號244Hz
‘x’設置測試信號122Hz
‘y’設置測試信號30Hz
‘z’掃描并發送數據
掃描數據發送如下:
0xAA
0xBB
0xCC
1000字節數據
程序通過發送響應每個命令一個Ack字節 - “@”。
Arduino串行庫使用中斷來讀取串行輸入。掃描期間輸入關閉,因此輸入字節保留在Atmega的串行輸入寄存器中。掃描結束時,串行庫收集字節,程序可以讀取它。但是如果在掃描期間到達第二個字節,它將被丟棄。
大寫命令可以包含幾個字節,因此如果在掃描期間發送,則會損壞。在發送大寫命令之前,停止發送‘z’并等待結果。大寫命令僅用于調試和測試。有幾個可以包含整數十進制值‘n’:
‘A’n將ADC通道設置為n
‘B’報告“電池”電壓= Vcc
‘D’報告狀態
‘F’n設置頻率pwm
‘R’n設置Vref為ADC
‘T’n觸發上升或下降
‘U’n設置預分頻器并發送掃描數據
‘V’n設置ADC的采樣周期
步驟8:添加顯示
示波器可以有自己的內置顯示器--1.3“OLED。雖然1.3”聽起來很小,但這些顯示器非常清晰。
顯示器有1.3“OLE運行在3.3V時,由SH1106芯片通過I2C總線控制。(SPI版本可用,但我使用Arduino SPI引腳作為“邏輯”。)
我需要一個非常快速的Arduino庫和它最好是小的.U8glib庫很慢而且很大,所以我自己編寫。它只有很少的命令所以它叫做“SimpleSH1106”。
SH1106有一個內置緩沖區,每像素一位。它被安排為128列7個條帶(其他尺寸可用)。每個樣本高8像素,頂部有lsb。在SH1106文檔中,swathes稱為“pages”,但“swathe”是計算機圖形學中的標準術語。您可以寫入的最小單位是一個字節 - 從8像素邊界開始的8像素列。
我的庫在Arduino上沒有屏幕緩沖區所以所有命令都基于將整個字節寫入頁面。它不太方便,但你獲得1k的RAM。
Atmel328p內置I2C驅動程序連接到A4(SDA)和A5(SCL)引腳。 SDA和SCL需要上拉電阻;內置的I2C驅動程序使用Atmel328p弱上拉電阻約50kohm。 50k上拉電阻在低速下工作,但上升沿的速度不夠快,因此我在Nano的3V3引腳上增加了1k的上拉電阻。
Arduino IDE有一個名為Wire.h的I2C驅動程序庫。這是一個不錯的小型快速庫,但正如您對Arduino所期望的那樣,文檔記錄很少。該庫初始化I2C硬件以100kHz運行,但我想要更快。因此在調用Wire.begin()之后,我將Atmel328p TWBR寄存器設置為較小的值。
生成的庫很快 - 示波器的掃描顯示在40mS內繪制。可以使用以下命令:
void clearSH1106()用0字節(黑色)填充屏幕。
void DrawByteSH1106 繪制一個字節(一個8像素的列)。
int DrawImageSH1106 繪制圖像。
int DrawCharSH1106 繪制一個角色。
int DrawStringSH1106 繪制一個字符串。
int DrawIntSH1106 繪制一個整數。
圖像在程序存儲器(PROGMEM)中聲明。提供了一個Windows程序,用于將BMP文件轉換為SimpleSH1106的游程編碼圖像。
庫中給出了完整的描述。
我展示了一個條形板電路布局。有三個條形板 - 一個用于Nano,一個用于顯示器,一個用于LM358。他們應該形成三明治。電路板從元件側顯示。精細的柔性電線連接兩塊板。將電路板與焊接的支架連接在一起。在我的圖表中,條形板的銅以青色顯示。紅線是條形板上的線鏈或將板連接在一起的柔性線。我沒有展示“測試線索”。
有些顯示器的引腳似乎有不同的順序。檢查它們。
我購買的0.9“顯示器的像素的x坐標從x = 0到127運行。使用1.3”顯示器它們是從x = 2到129.該庫包含一個常量“colOffset”,允許您調整顯示器的偏移量。
我已經為SM PCB附加了Gerber文件和EasyPC源文件。這些尚未經過測試,因此使用它們需要您自擔風險。
步驟9:不同的屏幕
模擬顯示屏顯示帶有刻度的波形。橫軸表示時間im mS。縱軸表示伏特,虛線為4V,0.5V,0.1V和20mV;在DC模式下,0V位于底部;在AC模式下,0V在中間顯示為虛線。
邏輯顯示屏顯示四個通道位。 D8是頂部通道,D11是底部通道。橫軸表示以mS為單位的時間。
有兩個按鈕:一個用于調整時基軸的“水平”按鈕和一個用于調整增益軸的“垂直”按鈕。如果您按住任一按鈕1秒鐘,則會出現一個菜單屏幕。
當菜單顯示時,“垂直”按鈕會滾動瀏覽不同的設置,“水平”按鈕會設置每個設置的值。 。如果您沒有按任何一個按鈕2秒鐘,程序將返回顯示波形。
步驟10:頻率計數器
通過使用Timer1和Timer2,ArdOsc也可以充當頻率計數器。頻率計有兩種工作方式:在一秒鐘內計算上升沿的數量,或者測量從一個上升沿到下一個上升沿的時間。
再一次,值得嗎?也許。我不記得我需要一個頻率計數器的時間。為什么不這樣做很容易?
為了計算D8“邏輯”信號的邊沿,程序選擇D5作為Timer1的時鐘輸入(16位計數器/定時器)。 D5外部連接到D8 - “邏輯”輸入之一。 Timer0(一個8位定時器)設置為每毫秒溢出一次。每次Timer0溢出時,都會產生中斷。 1000次中斷后,Timer1中的計數顯示為“頻率”。如果Timer1計數超過65536,則會產生中斷并記錄此類中斷的數量。
要測量從一個邊沿到下一個AC信號的時間,定時器1被設置為空閑 - 運行16MHz計時器。 ICR1寄存器設置為在比較器變為高電平時捕獲Timer1中的當前值。比較器的負輸入連接到A3,正輸入連接到D6。每次比較器變為高電平時,都會產生中斷。一個中斷和下一個中斷之間的時間是周期(1/頻率)。程序顯示一秒鐘內測量的平均頻率。比較器意味著在上升沿觸發,但沒有雜音,因此如果有噪聲,下降沿將被視為上升沿。這在低頻時尤其重要,因此,例如,10Hz信號將被報告為20Hz。
同時,Timer2可能產生“測試信號”。因此沒有定時器可用,我們不能使用正常的Arduino函數delay(),millis()等。
頻率計數器的代碼基于Nick Gammon的優秀網頁。
如果您不想輸入“頻率計數器”,則不需要從D5到D8的連接。在INO文件中,將bool常量bHasFreq設置為false。
步驟11:電壓表
示波器還可以作為電壓表,可以測量大約-20V和+ 20V之間的電壓。它使用Atmega328p的內置帶隙電壓參考,因此相當準確。
值得嗎?功能的數量越來越荒謬。好的,為什么不呢?
在A6測量電壓,ADC使用Vcc(即大約5V)作為參考。因為“5V”是近似值,我們還通過將其與1.1V帶隙進行比較來測量Vcc的實際值。根據數據表,帶隙僅為10%準確,但我嘗試的幾個接近1.1V。
要測量的輸入電壓通過電阻網絡。我選擇了上面顯示的值
Ra = 120k
Rb = 150k
Rc = 470k
你會在MeasureVoltage()函數的開頭附近找到這些常數。
Rc告訴你電壓表的輸入阻抗。與便宜的數字萬用表相比,470k是低的,但是足夠高,可以使用。
電壓表可以測量的最低電壓是
-5 * Rc/Ra = -19.6V
它可以測量的最高值是
5 * Rc/Rb + 5 = 20.7V
如果需要,可以選擇不同的電阻。
如果超過這些電壓怎么辦?沒事的。如果Arduino輸入引腳上的電壓高于Vcc或低于0V,保護二極管可以承受1mA電流。使用470k意味著理論上可以測試470V的電壓。但是我不相信在470V的條形板絕緣,你不應該玩這樣的電壓和這種原油電路。
如果想要精確的測量,你需要校準電壓表。將電壓表輸入“探頭”連接到0V,看看電壓表報告的內容。調整calibrateZero常數,直到電壓表讀數為“0.00V”。現在將電壓表輸入連接到已知電壓源 - 如果你有一個不錯的萬用表,那么測量一個9V電池的電壓。調整calibrateVolts常數直到電壓表給出正確的答案。
如果您不想要“電壓表”輸入,那么您不需要連接到D6的電阻。在INO文件中,將bool常量bHasVoltmeter設置為false。
步驟12:測試引線
示波器通常具有花哨的測試引線。我通常使用無焊接面包板,所以我只是附加了一種用于面包板的插入式電線。由于示波器由5V供電,我將其連接到我在面包板上使用的任何5V和0V電源以及更多的插入式電線。
步驟13:添加信號發生器
信號發生器是一個非常有用的部分測試裝備這個使用AD9833模塊。我在這里描述了一個獨立的版本;此步驟描述如何將一個添加到ArdOsc。 (此步驟是對此原始Instructable的編輯。)
AD9833可以生成0.1 MHz至12.5 MHz的正弦波,三角波和方波 - 本項目中的軟件限制為1Hz至100kHz。它可以用作掃描發生器。掃頻發生器有助于測試濾波器,放大器等的頻率響應。
我選擇的AD9833模塊與此類似。我不是說這是最好或最便宜的供應商,但你應該買一張看起來像那張照片。
模塊之間的連接是:
地面連接在一起
5V = AD9833的Vcc
D2 = FSync
D13 = Clk
D12 =數據
上面的示意圖是步驟8中的原理圖的補充。您可以使用另一塊stripboard將另一層添加到步驟8中描述的三明治中。
我已在步驟中更新了INO文件8包括控制AD9833的代碼。如果添加AD9833,則應將bHasSigGen變量設置為true(我將其保留為false,因為大多數人沒有AD9833)。
新菜單控制AD9833。它允許您選擇頻率和波形以及是否掃描頻率。
掃描發生器在1,5或20秒內反復輸出逐漸增加的頻率。它以“min”頻率開始,1,5或20秒后處于“最大”頻率。頻率變化是對數的,并且每毫秒改變一次。在掃描頻率時,示波器無法顯示頻率。
在不同模式下,掃描發生器輸出頻率,顯示示波器輸入,更改頻率,顯示示波器輸入等。頻率從“min”變為“max”超過這些步驟的20,100或500(或稱為“幀”)。頻率變化比“掃描”模式更加粗糙,但您可以觀察正在發生的事情。
步驟14:未來發展
可能是電池供電?是的,只需添加連接到Nano的RAW引腳的9V PP3。它通常使用25mA。
它可以由單個鋰電池供電嗎?這不是那么簡單,因為3.7V可能還不夠。在DC模式下顯示電壓的代碼已經讀取Vcc電壓,因此它將調整刻度位置。 Nano可以在3.7V(進入“5V”引腳)上運行。但是,3V3輸出可能不會達到3.3V;監管機構的輟學率太大了。你可以直接從鋰電池的3.7V開始運行顯示器,但是你從哪里獲得0.55V的參考電壓?它需要穩定。也許您可以使用LM317(如果將其Adjust引腳連接到0V,則可提供穩定的1.25V電壓 - 該電流下降應該足夠低)。或者您可以使用LED作為齊納。或者,只要您汲取微小電流,就可以使用Vref引腳上的電壓 - 將其連接到發射極跟隨器。您可能需要將LM358替換為工作電壓較低的運算放大器。
觸發器可以更好嗎?數字示波器在觸發之前將數據收集到循環緩沖區中。觸發水平可以變化嗎?你能一次掃一掃嗎?是的,你可以做所有這些,但你可能更好只需購買“適當的”示波器。
你能使用Pro Mini嗎?是的,但這不值得。您需要為顯示器和0.55V參考電壓制作自己的3V3信號。如果您要將數據發送到PC,那么您將需要一個串口轉USB。只需使用Nano。
它可以是無線的嗎?是。添加自己的藍牙與HC-05(Instructables可用)并連接到PC或Android手機。 ESP 8266對于這個項目來說會更麻煩。
你能用更大的顯示器嗎?是的,但為什么這么麻煩,質量不是那么好。只需買一臺示波器。
你能做得比LM358好嗎?是。如果您的組件抽屜中有各種運算放大器,請嘗試使用它們。讓我知道哪一個效果最好。
-
示波器
+關注
關注
113文章
6441瀏覽量
187603
發布評論請先 登錄
相關推薦
電源盒的應用場景
火柴盒大小的開發板duos做輕NAS體驗

示波器探頭和示波器需要匹配嗎
虛擬示波器還是數字示波器好用
電子示波器和數字示波器的比較

評論