TinyAVR Serie 0 und 1 im Einsatz Kap 5
Dieses einfache Oszilloskop verwendet den Seriellen Plotter der Arduino-IDE als Bildschirm. Über den ADC0 werden die Eingänge AIN7 und AIN8 angefragt und die Daten über die serielle Schnittstelle an den PC gesandt. Entsprechend der Breite des Plotters werden jeweils 500 Messungen dargestellt. Das Programm verwendet eine Zählschleife, in der die beiden AD-Messungen ausgeführt werden und die Daten aufbereitet und gesendet werden. Um eine möglichst hohe Abtastrate zu erreichen, wurden folgende Parameter optimiert:
Die Taktfrequenz wurde auf 20 MHz eingestellt. Der Takt für den AD-Wandler verwendet einen Vorteiler durch 8, was eine Taktrate von 2,5 MHz ergibt. Laut Datenblatt ist bei der vollen Auflösung von 10 Bit eine maximale Taktrate von 1,5 MHz möglich. Hier wird jedoch eine Auflösung von nur 8 Bit verwendet, was mit 2,5 MHz noch gut funktioniert. Bei noch höherer Taktrate versagt der AD-Wandler und liefert nur noch 255-Werte. Die serielle Schnittstelle wurde auf eine hohe Übertragungsrate von 500.000 Baud eingestellt. Die doppelte Baudrate von 1 MBaud ist zwar auch möglich, hat aber im Test zu vereinzelten Übertragungsfehlern geführt.
//Scope2ch3216
#include
<avr/io.h>
#include
<avr/interrupt.h>
#include
<math.h>
#include
<stdlib.h>
#include
<util/delay.h>
#include
<string.h>
#define
F_CPU 20000000
#define
USART0_BAUD_RATE(BAUD_RATE) ((float)(F_CPU * 64 /(16 * (float)BAUD_RATE)) + 0.5)
void
USART0_init(void){
PORTB.DIRSET = 0x04; //TXD an PB2
PORTA.DIRCLR = 0x08; //RXD an PB3
USART0.BAUD = (uint16_t)USART0_BAUD_RATE(500000);
USART0.CTRLB |= USART_TXEN_bm;
}
void
USART0_sendChar(char c){
while (!(USART0.STATUS & USART_DREIF_bm));
USART0.TXDATAL = c;
}
void
USART0_sendString(char *str){
for(size_t i = 0; i < strlen(str); i++){
USART0_sendChar(str[i]);
}
}
int
main(void) {
_PROTECTED_WRITE (CLKCTRL_MCLKCTRLB, 0); // 20 MHz
VREF.CTRLA = VREF_ADC0REFSEL_2V5_gc;
ADC0.CTRLA = ADC_ENABLE_bm | ADC_RESSEL_8BIT_gc;
ADC0.CTRLC = ADC_PRESC_DIV8_gc; //max. ADC-Takt
char buffer[6];
USART0_init();
while (1) {
for (uint16_t i=0; i<500;i++){
ADC0.MUXPOS = ADC_MUXPOS_AIN7_gc;
ADC0.COMMAND = ADC_STCONV_bm;
while (!(ADC0.INTFLAGS & ADC_RESRDY_bm));
uint8_t result1 = ADC0.RES;
ADC0.MUXPOS = ADC_MUXPOS_AIN8_gc;
ADC0.COMMAND = ADC_STCONV_bm;
while (!(ADC0.INTFLAGS & ADC_RESRDY_bm));
uint8_t result2 = ADC0.RES;
itoa(result1,buffer,10);
USART0_sendString(buffer);
itoa(result2,buffer,10);
USART0_sendChar(9);
//TAB
USART0_sendString(buffer);
USART0_sendString("
\r\n");
}
_delay_ms(1000);
}
}
Für die Übertragung an den
Arduino-Plotter wird das folgende Protokoll benötigt: Messwert1, TAB,
Messwert2, Zeilenende. Der Plotter erkennt dann die beiden Kanäle und stellt
sie mit unterschiedlichen Farben dar. Die Messungen, die Übertragung mit 500
kBaud und die Darstellung auf dem Bildschirm dauern nur rund 100 ms. Das Bild
bleibt dann eine Sekunde lang bis zur nächsten Messung stehen. Die Messungen
kann man auch im Seriellen Monitor ansehen.
Das Oszillogramm zeigt zwei 50-Hz-Signale, eines aus dem Netz, das andere aus einem analogen Sinusgenerator, der nach seiner Skala auf 50 Hz eingestellt wurde. Man erkennt, dass die Frequenzen recht gut übereinstimmen, wobei keine feste Phasenbeziehung besteht.
Die Abtastrate liegt nur bei rund
5 kHz. Für noch schnellere Messungen muss man die AD-Abtastung und die
Datenübertragung trennen, was weiter unten demonstriert wird. Aber für viele
Aufgaben ist auch dieses langsame Oszilloskop bereits brauchbar.