Das Dämpfungsglied PE4302 mit dem Arduino vom vorherigen Beitrag wurde erweitert um einen Rotary Encoder aus diesem Beitrag und ein LCD Display 16×2 wie in diesem Beitrag verwendet.
Der Rotary Encoder kann die Dämpfung in 0,5 dB Schritten verändern. Durch drücken der Taste wird der aktuelle Wert in das EEPROM abgelegt und beim nächsten Einschalten verwendet.
Die PC Steuerung wurde erweitert um die EEPROM Befehle:
e – speichern in EEPROM
r – auslesen aus EEPROM
Die Anschlüsse des 16×2 LCD Displays sind im Programm angegeben. Es wurde die LiquidCrystal.h Library verwendet. Die neue displayupdate Variable wird gesetzt wenn das LCD-Display geschrieben werden soll.
Hier die Schaltung auf den Steckbrettern.

Und das Programm dazu
// PE4302 Digital Step Attentuator
// 1 MHz - 4 GHz Dämpfungsglied 0-31,5dB in 0,5dB Schritten
//
// Seriell vom PC aus einstellbar und auslesbar.
// Rotary Encoder KY-040 kann den Wert einstellen und speichern.
// 16x2 LCD Ausgabe
//
// Matthias Busse 11.2017 Version 2.2
#include <EEPROM.h> // standard Arduino Library
// LCD Display Anschlüsse und Einstellungen
// VSS und RW > GND
// VDD und A > 5V
// K > 1kOhm > GND
// V0 Spannung über Poti 10k einstellbar GND ... 5V
// RS > 12, E > 13
// D4 > 11, D5 > 10, D6 > 9, D7 > 8
#include <LiquidCrystal.h>
const int rs = 12, e = 13, d4 = 11, d5 = 10, d6 = 9, d7 = 8;
LiquidCrystal lcd(rs, e, d4, d5, d6, d7);
bool displayupdate=1;
// PE4302 Einstellungen
int DATA=2; // Pin zu PE4302 Data
int CLOCK=3; // Pin zu PE4302 CL
int LE=4; // Pin zu PE4302 LE
float att=0.0, attmax=31.5, attmin=0.0; // aktuelle Dämpfung und Grenzwerte
// Rotary Encoder Einstellungen
int ra = 5; // Pin zu CLK am KY-040
int rb = 6; // Pin zu DT am KY-040
int sw = 7; // Pin zu SW am KY-040
int alast, aval;
int eeadr=10; // Speicheradresse wird hier gewählt
void setup() {
lcd.begin(16,2);
lcd.setCursor(0,0); // Cursor Zeile 0 setzen
lcd.print("Attentuator 4GHz"); // Text ausgeben
lcd.setCursor(0,1); // Cusor Zeile 1
lcd.print("M.Busse Ver. 2.2");
// delay(3000);
Serial.begin(38400);
pinMode(DATA, OUTPUT); // PE4302 sins Ausgänge
pinMode(CLOCK, OUTPUT);
pinMode(LE, OUTPUT);
pinMode(ra,INPUT); // Rotary Encoder A & B ist in
pinMode(rb,INPUT);
pinMode(sw, INPUT); // Schalter ist in
digitalWrite(sw, HIGH); // interner Pull up Widerstand für Taster
EEPROM.get(eeadr, att);
if(isnan(att)) att=0.0; // wird zu 0 gesetzt bis ein erster Wert im EEPROM liegt.
Serial.println(att);
alast = digitalRead(ra);
if(att > attmax) att=attmax;
if(att < attmin) att=attmin;
setAttenuator(att);
Serial.print("attentuation: ");
Serial.println(att);
delay(3000);
}
void loop() {
int ser, len;
char buf[10];
float attinput;
if(displayupdate) { // neue LCD Ausgabe
lcd.setCursor(0,1); // Cusor Zeile 1
lcd.print(" Att: ");
lcd.setCursor(7,1);
if(att < 10.0) lcd.setCursor(8,1);
lcd.print(att);
lcd.setCursor(11,1);
lcd.print(" dB ");
displayupdate=0;
}
if(digitalRead(sw) == 0) { // Speicher Taste gedrückt?
EEPROM.put(eeadr, att);
Serial.print("saved: ");
Serial.println(att);
while (digitalRead(sw) == 0); // warten bis die Taste losgelassen wird
lcd.setCursor(0,1); // Cusor Zeile 1
lcd.print(" - saved - ");
delay(1000);
displayupdate=1;
}
aval = digitalRead(ra); // Encoder gedreht?
if (aval != alast){ // wenn gedreht
if (digitalRead(rb) != aval) {
if(att < attmax) att+=0.5;
} // rechts rum
else {
if(att > attmin) att-=0.5;
} // sonst links
setAttenuator(att);
Serial.print("attentuation: ");
Serial.println(att);
}
alast = aval;
if (Serial.available() > 0) { // serielle Eingaben ?
ser = Serial.read();
if(ser == 'h') {
Serial.println("help");
Serial.println(" sx.x: set attentuator. Examples: s1.5 | s0 | s 22.5 | s 31 | s 0.0 ");
Serial.println(" g: get actual attentuator value");
Serial.println(" e: write to EEPROM");
Serial.println(" r: read from EEPROM");
Serial.println(" d: device class");
Serial.println(" w: who");
Serial.println(" v: version");
Serial.println(" 1: min. frequency");
Serial.println(" 2: max. frequency");
Serial.println(" 3: min. attentuation");
Serial.println(" 4: max. attentuation");
Serial.println(" 5: attentuator step width");
}
if(ser == 'd') Serial.println("attentuator"); // device ?
if(ser == 'w') Serial.println("PE4302"); // who ?
if(ser == 'v') Serial.println("Version 2.2"); // version ?
if(ser == 'e') {
EEPROM.put(eeadr, att); // in das EEPROM schreiben ?
Serial.print("saved: ");
Serial.println(att);
lcd.setCursor(0,1); // Cusor Zeile 1
lcd.print(" - saved - ");
delay(1000);
displayupdate=1;
}
if(ser == 'r') {
EEPROM.get(eeadr, att); // aus dem EEPROM lesen ?
Serial.print("read: ");
Serial.println(att);
displayupdate=1;
}
if(ser == '1') Serial.println("1000000"); // 1MHz fmin
if(ser == '2') Serial.println("4000000000"); // 4GHz fmax
if(ser == '3') Serial.println("0.0"); // 0dB att. min
if(ser == '4') Serial.println("31.5"); // 31.5dB att. max
if(ser == '5') Serial.println("0.5"); // att. step
if(ser == 'g') Serial.println(att); // get attentuation
if(ser == 's') { // set attentuation s1.5 | s0 | s 22.5 | s 31 | s 0.0
Serial.setTimeout(15);
len = Serial.readBytes(buf,10);
if((len>2) && (len<8)) { // s und was dahinter ?
attinput = atof (buf);
attinput = (round(attinput * 2.0)) /2.0; // auf .0 und .5 runden
if((attinput >= 0.0) && (attinput <= 31.51)) {
att=attinput;
setAttenuator(att);
}
}
}
Serial.setTimeout(500);
}
}
void setAttenuator(float attent){
// Einstellung an den PE4302 übergeben
// MSB (C16) ... LSB (C0.5) werden an den PE4302 seriell übergeben
// max. 25kHz oder alle 0,05 ms aufrufen.
//
// Matthias Busse 10.2017 Version 1.0
int i; // das Datenbit
int attent2 = (int) attent*2.0;
if ((attent2 < 0) || (attent2 > 63)) // Wert im Bereich ?
return;
digitalWrite(LE, LOW); // Daten in das Latch eingeben
digitalWrite(CLOCK,LOW);
for (int b = 6; b > 0; b--) { // die 6 Bits
i=((attent2 << 1) >> b) & 0x01;
digitalWrite(DATA, i); // ein Bit schreiben
digitalWrite(CLOCK, HIGH); // und Bit übernehmen
digitalWrite(CLOCK, LOW);
}
digitalWrite(LE, HIGH); // Serielle Daten an den Chip übergeben
digitalWrite(LE, LOW); // Auf neue Daten warten.
displayupdate=1; // Das LCD Display soll neu geschrieben werden.
}
Verwendet wurden:
Arduino Nano
Arduino Software 1.8.0
Attentuator PE4302
16×2 LCD Display
Rotary Encoder KY-040
von Matthias Busse

Hallo lieber Matthias, deine Aufbaugeschichte mit dem Abschwächer gefäfft mir ganz gut, ich habe hier ebenfalls schon so etwas realisiert. Eigendlich wäre es doch toll, wenn man 2 stk dieser Abschwächer hintereinander schaltet und dann als gesammtdämpfung einen Wert bis 64 db bekommt.Auch wenn die Durchgangsdämpfung bei den Bausteinen recht hoch ist und auch der Frequenzgang recht mies ist.
Man müßte oberhalb von 32 Bit nur den 2. auf 32 db setzen und den ersten noch eimal zählen lassen von 0 bis 32 Bit und den Wert in der Anzeige plus dem Grundwert von 32 db zur Anzeige bringen. Der Zähler kann ja den gesammten wertebereich von 0 bis 128 Schritte laufen, wenn > 32 db oder 64 Schritte, bringe den 2 mit ins spiel und wenns runter geht unter 32 zähle den wieder ab. Was häst du davon, Kannst ja mal ne mail nach NF in der Nähe von Husum schicken wenn du magst
Christian DD7LP OVV DARC Husum M04
Hallo,
habe versucht diese Projekt mit einem Sparkfun Pro Micro und einem I2C 16 x 2 LCD nachzubauen,
kann aber an den Anschlüssen des PE4302 Moduls keine Pegeländerungen beim Drehen des Encoders
feststellen. Sollte man an den Anschlüssen nicht irgendwann 3 V messen können? Weiter macht der Encoder bei mir von einer Rastung zur nächsten immer 1db, nur wenn ich sachte zwischen zwei Rastungen drehe bekomme ich einen 0,5 db Schritt.
Hoffentlich kannst du mir weiterhelfen, denn ich stehe irgendwie auf dem Schlauch.