Archiv des Autors: admin

6dB Leistungsteiler bis 2100 MHz

Ich habe einen Resistiven Leistungsteiler bis in den GHz Bereich aufgebaut. Er besteht aus 50 Ohm Microstrip Leitungen und in der Mitte 3 x 16 Ohm Widerständen im Stern geschaltet.
Idealerweise wird die Eingangsleistung vom Eingang zur Hälfte in den Widerständen in Hitze umgewandelt und der Rest / 2 steht an jedem Ausgang zur Verfügung, das sind 6dB Durchgangsdämpfung.

Der Vorteil gegenüber einem Wilkinson Teiler mit 3dB Durchgangsdämpfung ist, dass der Resistive Teiler auch schon bei wenigen Herz funktioniert und sehr einfach aufzubauen ist.

Der Nachteil ist daß er 6dB Durchgangsdämpfung hat.

Ich habe drei gleiche 0805 SMD Widerstände verwendet mit ausgesuchten 16,2 Ohm, ideal wären 16,666 Ohm, aber das ist nicht sehr kritisch. Sie sind kopfüber verlötet, dadurch liegt die Widerstandsschicht auf der Platine und es sind etwas höhere Frequenzen erreichbar.

Ich habe die Schaltung 2x aufgebaut und vermessen. Weiterlesen

Ein Microstrip Tiefpaß 2200 MHz entworfen und aufgebaut.

Mein nächstes Projekt ist ein Tiefpaß Filter für 2,2 GHz. Bis zu dieser Frequenz sind auch diskrete L und C Elemente einsetzbar. Hier kann man aber auch schon Streifenleitungsfilter aufbauen.

Dazu werden zum einen dünne (hochohmige) Leitungen in Reihe verwendet, die einer Induktivität in Reihe entsprechen. Und zum anderen breite (niederohmige) offene Stichleitungen parallel die besonders mit den offenen Enden einer Kapazität gegen Masse entsprechen.

Das kann in der Simulation im Ansoft Designer dann so aussehen

Und hier das Simulationsergebnis im Ansoft Designer Weiterlesen

Arduino als Frequenzteiler

Der Arduino kann als Frequenzteiler verwendet werden. Mich hat dabei interessiert bis zu welcher Frequenz das möglich ist.

Der Eingang : Dazu muß an einem Eingang das Signal als TTL Pegel anliegen (0/5V beim UNO, NANO, MEGA oder 0/3V beim DUE…) Ich habe hier den Eingang Pin 7 verwendet.

Das Programm: Der Arduino erkennt mit pulsIn(inPin, HIGH) eine steigende Flanke des Eingangssignals.

Der Ausgang: Als schnellen Ausgang habe ich den PORT B genommen und mit dem Assembler Befehl PORTB^=B11111111 umgeschaltet. Weiterlesen

RX String mit serialEvent einlesen und als Integer oder Float ausgeben

Mit serialEvent() können Zeichen von RX oder der USB Schnittstelle in den Arduino eingelesen werden. serialEvent() wird außerhalb von loop() ausgeführt und liest hier den Seriellen Buffer mit standardmäßig bis zu 64 Zeichen aus.

Das Programm basiert auf der Erklärung hier.

Sollten 64 Zeichen nicht reichen kann man den Buffer vergrößern, siehe hier.

Die Zeichen werden in einem String abgelegt. Das Zeilenende wird mit \n erkannt und dann wird stringComplete auf true gesetzt.

Im Hauptprogramm wird bei stringComplete==true der String ausgegeben. Zusätzlich wird der String in Integer und Float umgewandelt und ausgegeben.

Hier das Programm

// Seriell auf RX ( oder USB ) reinkommende Daten per event auslesen und das Zeilenende erkennen
// serialEvent() ist nicht kompatible mit Arduino Esplora, Leonardo oder Micro
//
// Matthias Busse 17.12.2018 Version 1.0

String inputString="";            // Eingabe String Daten
bool stringComplete=false;        // String abgeschlossen

void setup() {
  Serial.begin(38400);            // Baud
  inputString.reserve(64);        // 64 Byte Platz für den Seriellen Text
  Serial.println("Bitte Text eingeben und mit Enter bestaetigen:");
}

void loop() {
  if(stringComplete) {
    stringComplete=false;
    Serial.print("String : ");      // String ausgeben
    Serial.println(inputString);  
    Serial.print("Integer: ");      // Integer ausgeben
    Serial.println(inputString.toInt());
    Serial.print("Float  : ");      // Float ausgeben
    Serial.println(inputString.toFloat());
    inputString="";
  }
}

void serialEvent() {
// Wird aufgerufen wenn an RX Daten angekommen sind, ausserhalb von loop().
// Ein delay() in loop() kann die Datenübernahme verzögern.
// Der Arduino RX Buffer ist standardmässig 64 Zeichen groß, kann aber ggf. vergrößert werden.
  while(Serial.available()) {        // bis alle Zeichen im RX Buffer ausgelesen sind
    char inChar=(char)Serial.read(); // ein Zeichen im RX Buffer auslesen
    if(inChar == '\n') {             // String Ende erkennen
      stringComplete=true; 
    }
    else {                            // Zeichen anhängen
      inputString+=inChar; 
    }
  }
}

Verwendet wurden :
Arduino Uno
Arduino Programm Version 1.8.0

von Matthias Busse

Arduino Funktionen zur Vektor Rechnung

Für die Vektorrechnung habe ich die Funktionen in einem Unterprogramm vektor.c zusammengefasst.

// Funktionen für die Vektor Rechnung 
//
// Matthias Busse 1.10.2018 Version 1.0

// Inhalt:
// vAdd(v1, v2, v3)           : v1+v2=v3
// vSub(v1, v2, v3)           : v1-v2=v3
// vMultF(v1, f, v2)          : v1*f=v2
// f=vBetrag(v1)              : |v1|=f
// f=vSkalarprodukt(v1, v2)   : v1 * v2=f
// f=vWinkelGrad(v1, v2)      : Winkel zwischen v1 und v2 in Grad
// vVektorprodukt(v1, v2, v3) : v1 x v2 = v3
// vEinheitsvektor(v1, v2)    : v1 / |v1| = v2, Länge=1
// vRichtungscosinusX(v1)     : v1 Winkel zur X-Achse in Grad
// vRichtungscosinusY(v1)     : v1 Winkel zur Y-Achse in Grad
// vRichtungscosinusZ(v1)     : v1 Winkel zur Z-Achse in Grad

//      z |
//        |
//        |
//        ---------- y
//       /
//    x /


void vAdd(float v1[3], float v2[3], float v3[3]) {
// Vektoren Addieren v1+v2=v3 
// Matthias Busse Version 1.0 vom 30.9.2018
  v3[0]=v1[0]+v2[0];
  v3[1]=v1[1]+v2[1];
  v3[2]=v1[2]+v2[2];
}

void vSub(float v1[3], float v2[3], float v3[3]) {
// Vektoren Subtrahieren v1-v2=v3 
// Matthias Busse Version 1.0 vom 30.9.2018
  v3[0]=v1[0]-v2[0];
  v3[1]=v1[1]-v2[1];
  v3[2]=v1[2]-v2[2];
}

void vMultF(float v1[3], float z, float v2[3]) {
// Vektor multiplizieren mit Zahl v1*z=v2 
// Matthias Busse Version 1.0 vom 30.9.2018
  v2[0]=v1[0]*z;
  v2[1]=v1[1]*z;
  v2[2]=v1[2]*z;
}

float vBetrag(float v1[3]) {
// Vektor Betrag (Länge) von v1 oder |v1|=z 
// Matthias Busse Version 1.0 vom 30.9.2018
  float z;
  z=sqrt(v1[0]*v1[0] + v1[1]*v1[1] + v1[2]*v1[2]);
  return z;
}

float vSkalarprodukt(float v1[], float v2[]) {
// Vektoren Skalar multiplizieren v1 * v2 = z 
// |V1| * |V2| * cos winkel_dawischen = z
// Wenn das Ergebis 0 ist, dann sind die Vektoren senkrecht zueinander
// Matthias Busse Version 1.0 vom 30.9.2018
  float z;
  z= (v1[0]*v2[0]) + (v1[1]*v2[1]) + (v1[2]*v2[2]);
  return z;
}

float vWinkelGrad(float v1[], float v2[]) {
// Den Winkel in Grad zwischen zwei Vektoren berechnen  
// Matthias Busse Version 1.0 vom 30.9.2018
  float z, w;
  z=vSkalarprodukt(v1, v2);
  w = z / vBetrag(v1) / vBetrag(v2);
  return acos(w)*57.296; // Rad zu Grad
}

void vVektorprodukt(float v1[3], float v2[3], float v3[3]) {
// Vektorprodukt v1 x v2 = v3
// v3 steht senkrecht auf v1 und v2
// v3 Betrag |v3| ist die Fläche vom v1 und v2 Parallelogramm
// Winkel zwischen v1 und v2 ist 
// |v1 x v2| = |v3| = |A| * |B| * sin winkel_dawischen
// Matthias Busse Version 1.0 vom 30.9.2018
  v3[0]= (v1[1]*v2[2]) - (v1[2]*v2[1]);
  v3[2]= (v1[0]*v2[1]) - (v1[1]*v2[0]);
  v3[1]= -1.0 * ((v1[0]*v2[2]) - (v1[2]*v2[0]));
}

void vEinheitsvektor(float v1[3], float v2[3]) {
// Einheitsvektor v1 / |v1| = v2
// Ergibt den Vektor mit der Länge 1
// Matthias Busse Version 0.1 vom 01.10.2018
  float betrag;
  betrag=vBetrag(v1);
  v2[0]=v1[0]/betrag;
  v2[1]=v1[1]/betrag;
  v2[2]=v1[2]/betrag;
}

float vRichtungscosinusX(float v1[3]) {
// Der RichtungskosinusX bildet den Winkel zwischen dem Vektor und der X Achse
// cos(w) = vx / |v|
// Matthias Busse Version 1.0 vom 01.10.2018
  float winkel;
  winkel=acos(v1[0]/vBetrag(v1));
  return winkel*57.296; // Rad zu Grad
}

float vRichtungscosinusY(float v1[3]) {
// Der RichtungskosinusY bildet den Winkel zwischen dem Vektor und der Y Achse
// cos(w) = vy / |v|
// Matthias Busse Version 1.0 vom 01.10.2018
  float winkel;
  winkel=acos(v1[1]/vBetrag(v1));
  return winkel*57.296; // Rad zu Grad
}

float vRichtungscosinusZ(float v1[3]) {
// Der RichtungskosinusZ bildet den Winkel zwischen dem Vektor und der Z Achse
// cos(w) = vz / |v|
// Matthias Busse Version 1.0 vom 01.10.2018
  float winkel;
  winkel=acos(v1[2]/vBetrag(v1));
  return winkel*57.296; // Rad zu Grad
}

Hier das Programm um die Vektor Funktionen zu testen.
Weiterlesen

Der I2C Bus Scanner. Die Adressen von Geräten am I2C Bus ausgeben.

Der I2C Bus ist ein 2-Draht Bus mit den Leitungen SCL (clock) und SDA (data). Er wird auf Platinen zwischen zwei Geräten / ICs verwendet. Die Hersteller der ICs geben die I2C Bus Adresse vor, manchmal können die unteren Bits angepasst werden, da theoretisch nur 128 Adressen zu Verfügung stehen und zwei ICs auf der selben Adresse liegen könnten.
Der Bus hat einen Master (hier der Arduino) und bis zu 112 Slaves (verschiedene ICs mit unterschiedlichen Adressen).

Hier die I2C Beschreibung bei Wikipedia.
Beim Arduino wird die Library Wire.h für die I2C Befehle eingebunden.
Der TWI Bus ist identisch mit dem standard I2C Bus.

Ein einfaches Arduino Programm scannt alle Adressen im I2C Bus und gibt die verwendeten Adressen aus.

// I²C Scanner aus dem Arduino.cc forum
// Netzfund, unbekannter Autor.
// Sucht I2C Geräte an den Adressen 0...127 und gibt bei gefundenen Geräten die Adresse aus.
//
// Matthias Busse 22.9.2018 Version 1.0

#include <Wire.h>

void setup() {
  Wire.begin();
  Serial.begin(38400);
  while (!Serial);
  Serial.println("\nI2C Scanner");
}

void loop() {
  byte error, address;
  int nDevices;
     
  Serial.println("scannen...");
  nDevices = 0;
  for(address = 1; address < 127; address++ ) {
    // Der i2c Scanner nimmt den Rückgabewert von Write.endTransmisstion um zu schauen ob ein Gerät auf dieser Adresse antwortet.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if (error == 0) {
      Serial.print("I2C Geraet gefunden an Adresse 0x");
      if (address<16) Serial.print("0");
      Serial.println(address,HEX);
      nDevices++;
    }
    else if (error==4) {
      Serial.print("Unbekannter Fehler an Addresse 0x");
      if (address<16) Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0) Serial.println("Kein I2C Geraet gefunden\n");
  else Serial.println("fertig\n");
  delay(5000);           // 5 Sekunden warten bis zum nächsten durchlauf
}

Und hier die Ausgabe

I2C Scanner
scannen...
I2C Geraet gefunden an Adresse 0x68
fertig

von Matthias Busse

Platinen abzugeben aus meinen Projekten

Von meinen Projekten habe ich hier noch einige Platinen.

Ich habe immer ein paar Platinen mehr machen lassen. Wenn also jemand die Schaltungen nachbauen möchte oder eigene Ideen hat kann ich die Platinen im Brief in Deutschland für 2 Euro verschicken. Ich verschicke nicht ins Ausland.

Die Platinen sind unbestückt und neu, ohne Stecker und andere Bauteile, nur die Platinen.

1. Platine CPWG 1.1
50 Ohm Leitung durchgehend, Masse Fläche durchkontaktiert daneben,
SMA Anschluß an beiden Seiten.
Material FR4, Dicke 1 mm, Außenmaß 14 x 50 mm
Aus dem Beitrag: Tiefpass 5. Ordnung für 190 MHz simuliert und aufgebaut

Preis pro Platine: 5,00 €, Anzahl verfügbar: 3 Stück Weiterlesen

Ich habe meine China Dämpfungsglieder vermessen

Nach den ernüchternden Messergebnissen vom Abschlußwiderstand habe ich heute meine verschiedenen Dämpfungsglieder vermessen. Es sind welche von Mini Circuits und einfache China Versionen dabei. Hier nun meine Messergebnisse. Bei 1,3 GHz ist ein Messfehler im System nach der Kalibrierung des NWT4000, den vernachlässige ich hier.

Fangen wir mit dem Mini Circuits VAT-3 an mit 3dB Dämpfung
Bis auf zwei kleine Ausreißer von 2.5dB bei 3,8 GHz und 4,4 GHz ist es für den vollen Messbereich geeignet. Weiterlesen

Tiefpass 5. Ordnung für 190 MHz simuliert und aufgebaut

Ich habe eine Chebychev Tiefpaß 5. Ordnung entworfen mit diskreten L / C Elementen.
Chebychev Filter haben die größte Flankensteilheit.
Bei Kapazitäten habe ich hier eine größere Auswahl, deshalb wurde die 3 C und 2 L Struktur gewählt und simuliert.

Das Ergebnis der Simulation im Ansoft Designer.

Die 9,4pF wurden mit 8pF und 1,5pF aufgebaut und die 30pF mit 2 x 15pF.
Hier der fertige Aufbau im Gehäuse. Weiterlesen