/* ******************************************************************************** Sommeren 2016, de OZ6YM, Palle A. Andersen - Ver: 2.0.0 ******************************************************************************** Arduino UNO eksperimenter: http://www.planker.dk/Projects/Arduino/MyProject.htm ******************************************************************************** Denne version er udbygget med en omskifter, således, at der tages højde for,hvis der indskydes et dæmpeled på -40 dBm, eller -60 dBm, foran målehovedet, så viser skalaen 0 dBm, hvor der normalt står -40/-60 dBm. Hermed er milliwatt-meteret udbygget til et watt-meter op til 1000 watt. Omskifteret er en 4-polet omskifter med 3 stillinger. Programmet benytter Analog-port A4 og A5 til at skifte mellem -40 og -60 dBm, med midterstillingen som normal. 2 af de 4 skifte bruges i forbindelse med Arduino-programmet. ******************************************************************************** * * Målehoved med AD8307, til måling af dBm, mWatt, dBmVolt og rms_mVolt, i 50 Ohm * * Der benytter standard 4 bit interface til display * * Formler og konstanter er hentet på nettet hos Rohde & Schwartz: * http://www.planker.dk/Projects/Arduino/AD8307/ConvCalc.pdf * ******************************************************************************** Display forbindelser: pin 11 LCD pin D4 til Arduino digital pin 5 pin 12 LCD pin D5 til Arduino digital pin 6 pin 13 LCD pin D6 til Arduino digital pin 7 pin 14 LCD pin D7 til Arduino digital pin 8 pin 3 LCD til stel = fuld kontrast pin 4 LCD pin RS til Arduino digital pin 9 pin 6 LCD pin En til Arduino digital pin 10 pin 5 LCD pin RW til stel AD8307 output forbindes til analog pin A1 ******************************************************************************** ** Her starter definitioner ******************************************************************************** ** Vælg dit display-interface ******************************************************************************** */ #include LiquidCrystal lcd(9, 10, 5, 6, 7, 8); // Check dine interface-pinne... //****************************************************************************** // Globale variable: //****************************************************************************** // Definer display antal linier og kollonner #define culom 20 #define rows 4 #define LEDBLINK_PIN 13 // I/O pin connected to the LED. #define LEDBLINK_MS 300 // Blink rate (in milliseconds). //****************************************************************************** // andre variable static unsigned int ledStatus = LOW; // Last set LED mode. static unsigned long ledBlinkTime = 0; // LED blink time. //****************************************************************************** float dBm; float mW; float skrivmW; float dBmV; float rmsV; int AD_data = 0; // det vi får fra AD8307 int sumfelt = 0; // mellemregning //****************************************************************************** // ARDUINO UNO processorens AREF pin 21 bestemmer refferancepunktet for // AD-converterens delepunkter. Standard er "INTERNAL" CPU-spænding, (5 Volt) // delt i 1023 Punkter. // Hvis AREF tilføres en anden spænding, bliver denne ny Refferance, // f.eks. 2,5575 Volt, som så deles med 1023. dette giver en højere AD-opløsning. // analogReference(EXTERNAL); //****************************************************************************** // NOTE: AREF sat EXTERN 2.5575 Volt // EXTERNAL refferancespænding dannes med en 4,7K trimmer mellem // + 5 Volt og stel (GND). // Midterarmen tilsluttes AREF på Arduino, eller ben 21 på ATmega328P, og med // et højimpedans Voltmeter, indstilles spændingen til præcis 2,5575 Volt. // // Refferance: 2.5575 Volt / 1023 = 0,0025 Volt pr. punkt ~ 0,1 dBm pr. punkt // ***************************************************************************** // Måling begynder først ved punkt 78 = ca. -74 dBm men er ikke præcis før vi // når til punkt 133 = -70 dBm, herefter vises ca.10 dBm for hver 100 punkter, // indtil MAX er nået med 1023 punkter og ca. +18 dBm. // //****************************************************************************** // Der er indført en omskifter med 6 stillinger, til indlæg af kompensation for // den misvisning over frekvensområdet op til 500 MHz. // Målt i forhold til en AGILENT 8648 Signalgenerator. // ----------------------------------------------------------------------------- // Programmet tillægger værdier til udjævning af disse afvigelser, og // misvisningen er således under 1 dBm over hele dækningsområdet. // Se sidst i programmet. //****************************************************************************** // Arduino aflæser med punkter fra Min: 133 til Max: 1022 -> 889 punkter // efter databladet er dynamikområdet 92 dB, men 889 giver 88,9 dB, // og viser således u-liniaritet i begge ender af skalaen, //****************************************************************************** int analogPin = A0; // Kompensation for frekvens differancer int adinputpin = A1; // AD8307-port A1 = input-port int meterPin = 3; // udskriv dBm på meter PWM, Atmega328p-pin5 // Define Attenuator-ports with 10 K resistor as PULL-DOWN = false int Att1 = A4; // Attenuator -40 dBmW int Att2 = A5; // Attenuator -60 dBmW int att = 0; // INIT Value int attx = 0; // -do- // Define kompensation for difference in frequens-output float Komp = 0.00; // holder Frekvens kompensationsværdien.. int Komp1 = 0; // Kompens af analog meter int val = 0; // som reff. fra porten A0 int nyval = 0; // mellemregning int val1 = 0; // meterudskrivning //------------------------------------------------------------------------------ // slut på definitioner //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // start på setup //------------------------------------------------------------------------------ void setup() { lcd.begin(culom, rows); delay (100); // Vent på, at display et ordentligt initialiceret analogReference(EXTERNAL); pinMode(LEDBLINK_PIN, OUTPUT); pinMode(Att1, INPUT); // Set Attenuator-ports to INPUT (ATmega328P-port 18) pinMode(Att2, INPUT); // -do- (ATmega328P-port 19) pinMode(meterPin,OUTPUT); Overskrift(); // skriv overskrift i display udskriv(); } //------------------------------------------------------------------------------ // slut på setup //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // start på loop hvor vi arbjder //------------------------------------------------------------------------------ void loop() { hentaddata(); omregn_dBm(); omregn_mW(); omregn_dBmV(); omregn_rmsV(); // Display alle nye data LCDPrint(" ", 8, 0); // slet altid fortegn (+ eller -) lcd.setCursor(8, 0); lcd.print(dBm, 1); // dBm udskrives med 2 decimaler LCDPrint(" ", 8, 1); lcd.setCursor(8, 1); lcd.print(skrivmW, 3); // mW udskrives med 7 decimaler LCDPrint(" ", 8, 2); lcd.setCursor(8, 2); lcd.print(dBmV, 3); // dBmV udskrives med 5 decimaler LCDPrint(" ", 8, 3); lcd.setCursor(8, 3); lcd.print(rmsV, 3); // RMS Volt udskrives med 5 decimaler delay (300); // pause, sat så det ikke flimre for meget på displayet } //****************************************************************************** // slut på loop //****************************************************************************** //****************************************************************************** // print a string at specified position x,y ** //****************************************************************************** void LCDPrint(char *str, byte column, byte row) { lcd.setCursor(column, row); lcd.print(str); } // END of Print //****************************************************************************** // Update LCD med overskrifter //****************************************************************************** void udskriv() // plads til forbedring { LCDPrint("dBm,50= ", 0, 0); // ALT er med refferance til LOAD på 50 Ohm LCDPrint("Watt = ", 1, 1); // der kan udskrives pW-uW-mW, derfor er den rykket LCDPrint("dBmV = ", 0, 2); LCDPrint("mVrms = ", 0, 3); } //****************************************************************************** // start på functions, her gøres arbejdet //****************************************************************************** void hentaddata() // Læs data 10 gange, og tag gennemsnittet { sumfelt = 0.0; for ( int i = 0; i < 10; i++ ) { AD_data = analogRead(adinputpin); // indlæs data fra AD8307 ~ 0 - 1023 sumfelt = sumfelt + AD_data; delay(5); // Lad AD-porten falde til ro } AD_data = sumfelt / 10; } //****************************************************************************** // Alle omregninger herefter er i forhold til 50 Ohm's belastning fra dBm ** //****************************************************************************** /* AREF er sat til EXTERNAL, og justeret således, at der er sammenfald mellem den værdi AD8307 leverer til AD-converteren. Dette sammenfald udlæses med 0,1 dBm for hver punkt i processorens opløsning. 2.5575 / 1023 = 0.0025 ~ 0.1 dBm pr. opløsnings-enhed ******************************************************************************** dBm AD8307 Analog meter ------------------ ---------------------- 17.9 1020 255 10 937 235 0 832 208 -10 728 182 -20 623´ 156 -30 519 130 -40 414 104 -50 310 78 -60 205 52 -70 101 26 -72,6 70 19 */ //****************************************************************************** void omregn_dBm() { att = 0; attx = 0; dBm = map(AD_data,72,1023,-730,180); dBm = (dBm/10); if ( digitalRead(Att1) >= 1 ) // har vi en -40 db's powertab? { att = -40; } if ( digitalRead(Att2) >= 1 ) // har vi en -60 db's powertab? { att = -60; } Kompensation(); dBm = dBm + Komp; //----------------- // set analog meter //-------------------------------------------------------------------- val1 = (AD_data / 4)+ ( Komp * 10 / 4 ); // val1 = data til analog 200 mikroamp.meter // incl. kompensering for skiftenden frekvens //-------------------------------------------------------------------- // analog meter må ikke gå ud over top og bund-limit, derfor... // ... her er tilføjet en LED-diode som advarsel..... //-------------------------------------------------------------------- if ( digitalRead(Att1) == 0 && digitalRead(Att2) == 0 ) { digitalWrite(LEDBLINK_PIN, LOW); goto goon; } if ( digitalRead(Att1) == 1 && val1 >= 104 ) { val1 = val1 - 104; digitalWrite(LEDBLINK_PIN, LOW); goto goon; } if ( digitalRead(Att1) == 1 && val1 < 104 ) { ledBlink(); } if ( digitalRead(Att2) == 1 && val1 >= 156 ) { val1 = val1 - 156; digitalWrite(LEDBLINK_PIN, LOW); goto goon; } if ( digitalRead(Att2) == 1 && val1 < 156 ) { ledBlink(); } goon: if ( val1 == 256 ){ val1 = val1 - 1;} // MAX analog udskrivning = +18 dBm. analogWrite(meterPin,val1); // skriv værdi til meteret // ----------------------------------------------------------------------------- // ved udskrivning skal denne linie også aktiveres // lcd.setCursor(16,0); lcd.print(" "); // Aktiver kun een af de efterfølgende linjer ad gangen // ----------------------------------------------------------------------------- // lcd.setCursor(16,0); lcd.print(val1); // udskriv værdien til meteret // lcd.setCursor(16,0); lcd.print(AD_data); // udskriv læst værdi fra AD8307 } //****************************************************************************** void omregn_mW() { mW = ( pow ( 10.0, ( dBm / 10.0 ))); // allerede milli... // udskriv som mW, uW eller nW = milli, micro eller nano - som decimaltal //**************************************************************************** if (mW < 0.000001 ) { skrivmW = (mW * 1000000000); LCDPrint("p", 0, 1); } // picoWatt else { if (mW < 0.001 ){ skrivmW = (mW * 1000000);LCDPrint("n", 0, 1); }// nanoWatt else { if (mW < 1 ){ skrivmW = mW * 1000; LCDPrint("u", 0, 1); } // microWatt else { skrivmW = mW; LCDPrint("m", 0, 1); } // milliWatt } } } //****************************************************************************** void omregn_dBmV() // omregn med reff. til 50 Ohm { dBmV = 46.9897 + dBm; // Her benytter vi en konstant i omregningen } //****************************************************************************** void omregn_rmsV() { rmsV = (sqrt( (mW / 1000) * 50 )); // omregn med reff. til 50 Ohm } //****************************************************************************** // Overskrifte skrives kun ved opstart af mWatt-meter //****************************************************************************** void Overskrift() // du er velkommen til at skrive din egen overskrift { lcd.clear(); LCDPrint(" MICRO-WATT MED ", 0, 0); LCDPrint(" ARDUINO ATMEGA328P ", 0, 1); LCDPrint(" VER. 2.0.0 - 2016 ", 0, 2); LCDPrint(" WWW.PLANKER.DK ", 0, 3); delay(2000); lcd.clear(); } //****************************************************************************** // // LED Heartbeat routine - ADVARSEL om Attenuator //****************************************************************************** void ledBlink() { if ( (long)(millis()-ledBlinkTime) >= 0 ) { ledStatus = (ledStatus==HIGH ? LOW : HIGH); // Toggle LED. digitalWrite(LEDBLINK_PIN, ledStatus); // Set LED pin status. ledBlinkTime = millis()+LEDBLINK_MS; // Reset "next time to toggle" time. } } //****************************************************************************** // End of ledBlink() //****************************************************************************** // Kompensation for skiftende frekvens-område //****************************************************************************** void Kompensation() { val = analogRead(analogPin); // Læs den ANALOGE input pin A0 = 23 nyval = int(val/10); // her vil værdien 511 /10 f. eks. blive 51 switch(nyval) { case 48: Komp = 0.4; break; // 48 case 65: Komp = 1.4; break; // 65 case 74: Komp = 2.4; break; // 74 case 79: Komp = 3.9; break; // 79 case 83: Komp = 5.1; break; // 82 case 85: Komp = 6.5; break; // 85 } // lcd.setCursor(16,0); lcd.print(" "); // lcd.setCursor(16,0); lcd.print(nyval); } //****************************************************************************** // END of PROGRAM ** //****************************************************************************** // OBS: check kompilering: // Sketch uses 7.760 bytes (25%) of program storage space. Maximum is 30.720 bytes. // Global variables use 255 bytes (12%) of dynamic memory, leaving 1.793 bytes for // local variables. Maximum is 2.048 bytes.