
RPi Pico DDS und Scope
Elektronik-Labor
Projekte
Mikrocontroller
Raspberry
Inzwischen
habe ich einen etwas besseren Eindruck von der Genauigkeit und Auflösung des
AD-Wandlers bekommen. Für die neuen Versuche habe ich Thonny in der Versuin
3.3.13 verwendet. Dass dadurch eine Verbesserung eingetreten ist, kann ich
nicht ausschließen. Zusätzlich habe ich einen anderen Masse-Pin, nämlich AGND
am Pin 33 verwendet. Beim letzten Versuche war es GND am Pin 38. Dadurch
könnten zusätzliche Störungen vom Spannungsregler induziert worden sein.
import machine
from machine import Pin
import utime
import time
u2 = machine.ADC(2)
ad_in = Pin(28, Pin.IN)
freq = machine.freq()
#Spannungwandler im PWM Mode sauberer:
p23 = Pin(23, Pin.OUT)
p23.value(1)
while True:
u=u2.read_u16()//16
print(u)
utime.sleep(1)
Der
Versuch wurde mit unterschiedlichen Taktraten von 10 MHz bis 250 MHz
getestet. Aber dabei war kein Unterschied in der AD-Auflösung
feststellbar, weil der AD-Wandler grundsätzlich mit 48 MHz getaktet
wird. Die Referenz wurde mit 100 µF abgeblockt, und an A2 lag ein Elko
mit 22 k, der über 10 k geladen und entladen wurde. Die Ladespannung
vom Netzteil war nur 160 mV, womit der 12-Bit-Messwert bis 204 stieg.
Nachgerechnet: 204 /4095 * 3300 mV = 164 mV.
Das Flattern der AD-Werte beträgt jetzt nur noch eine Stufe. Was
bleibt, ist der Offsetfehler von 15 mV am unteren Rand nahe 0 V. Wenn
man den Bereich bis 3,3 V ausnutzt, sieht es gar nicht so schlecht aus.
Ein Versuch mit der Arduino-IDE und der Boarderweiterung von Earle F.
Philhower (https://arduino-pico.readthedocs.io/_/downloads/en/latest/pdf/) hatte das Ziel, eine schnelle Messung mit einem DDS-Generator
zu verbinden. Dabei habe ich mich an der Software zum Arduino-Messlabor
orientiert. Erreicht wurde eine Abtastrate von rund 50 kHz. DDS-Ausgabe
und Messung laufen in einem Timer-Interrupt. Im Beispiel wird ein
Sinussignal mit einer Frequenz von 300 Hz erzeugt und gleich wieder
gemessen. Weil 500 Messwerte an den PC übertragen werden, können sie
direkt im seriellen Plotter dargestellt werden.
//50-kHz-DDS + Scope
#include "RPi_Pico_TimerInterrupt.h"
#include <math.h>
unsigned char dds[256];
unsigned int ad[1000];
unsigned int f, n, i, j, a1, a2, ph1, ph2, adn;
// Init RPI_PICO_Timer
RPI_PICO_Timer ITimer0(0);
RPI_PICO_Timer ITimer1(1);
bool TimerHandler0(struct repeating_timer *t)
{
digitalWrite (2,1);
a1+=ph1; //256;
a1&=65535;
analogWrite(0, (dds[a1>>8]));
if (adn<1000){
ad[adn] = analogRead(A2);
adn++;
}
digitalWrite (2,0);
return true;
}
void setup() {
Serial.begin(115200);
pinMode(2,OUTPUT);
analogWriteFreq(125000000);
analogWriteRange(255);
for (n=0;n<256;n++) dds[n]= 128+127.9*sin(PI*n/128.0);
ITimer0.attachInterruptInterval(13, TimerHandler0); //50 kHz
}
void loop() {
f=300;
ph1 = f*256/195;
adn=0;
delay(1000);
for(n=0;n<500;n++)Serial.println (ad[n+500]);
}
Das PWM-Signal entsteht am Pin 0 und wurde über 10 k und 100 nF
geglättet an AD2 geleitet und für das Oszilloskop gemessen. Alles
funktioniert schon ähnlich wie bei der Arduino-Vorlage. Einige Fragen
bleiben noch offen. Warum liefert der AD-Wandler 10-Bit-Werte bis 1023?
Und warum liefert der Timer-Interrupt relativ krumme Zeiten? Es gibt
noch viel zu tun. Vermutlich sind beim Einsatz des DMA-Systems noch
wesentlich höhere Abtastraten möglich.
Nachtrag
Martin Müller hat mich darauf hingewiesen, dass die AD-Auflösung von 10
Bit in der Arduino-Umgebung Standard ist. Und die Timing-Probleme mit
dem Interrupt hat er auch beobachtet und führt sie darauf zurück, dass
im Hintergrund die Zeit im Mikrosekundentakt erfasst wird.
Elektronik-Labor
Projekte
Mikrocontroller
Raspberry