PE4302 Attentuator einstellen vom PC & Rotary Encoder, Ausgabe auf LCD Display

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

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.