Bu proje F1CJN’nin Arduino projesine dayanmaktadır . Düşük maliyetli 35-4400 Mhz bir sinyal kaynağı yapmak isteyenler için gayet başarılı sonuçlar veriyor. ADF4351 modülünü kullanır. ADF4351, 5 dBm’lik maksimum çıkış seviyesinde 10 KHz adımlarla çalışabilir. ADF4351, bu durumda Arduino ile arayüz oluşturan bir SPI arayüzüne sahiptir.
F1CJN’nin tasarımı, frekansı görüntülemek için bir LCD Düğme Kalkanı kullanır ve düğmeler gerekli frekansı ve modu ayarlamak için kullanılır. Frekansın USB aracılığıyla ana bilgisayara bağlanan seri port üzerinden ayarlanmasına izin vermek için kodu değiştirdim. Ek olarak USB, Arduino ve ADF4351 kartına güç sağlar. Ayrı bir 5V güç kaynağı spektral saflığı artırabilir, ancak bunun bir sorun olduğunu görmedim. RSPduoEME uygulaması, gerekli kalibrasyon frekansını Arduino seri portuna göndererek ADF4351’i kontrol eder. Kalibrasyon, frekansı bant dışına 4000MHz olarak ayarlayarak etkili bir şekilde kapatılır. Aşağıdaki şema, ara bağlantıları gösterir, 560/1K dirençler, Arduino 5V’u ADF4351 için 3,3V mantık seviyelerine dönüştürmek için kullanılır. Arduino projesinin tüm yapısal ayrıntıları F1CJN web makalesinde verilmiştir.
Değiştirilen kod, harici referansın 24MHz olarak ayarlanmasına izin verir, RSPduo harici referansı da 24MHz olduğundan kullanışlıdır. Harici referans kullanılırsa, XTAL osilatörüne bağlanan direncin ADF4351 modülünde çıkarılması gerekir. Kalibratör referans giriş modu, F1CJN makalesinde açıklandığı gibi kalkan üzerindeki basmalı düğmeler kullanılarak ayarlanır. LCD referans göstergesinin düzgün çalışmadığını ve referans uygulanmadığında bile kilit durumunu gösterdiğini unutmayın. Yazılım Mux çıkışının durumunu doğru şekilde gösterdiğinden, bu bir ADF4351 donanım sorunu gibi görünüyor. Değiştirilen Arduino Sketch, RSPduoEME indirme zip dosyasından edinilebilir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 |
#include <LiquidCrystal.h> #include <EEPROM.h> #include <SPI.h> #define ADF4351_LE 3 LiquidCrystal lcd(8, 9, 4, 5, 6, 7); byte poscursor = 0; //position curseur courante 0 à 15 byte line = 0; // ligne afficheur LCD en cours 0 ou 1 byte memoire,RWtemp; // numero de la memoire EEPROM uint32_t registers[6] = {0x4580A8, 0x80080C9, 0x4E42, 0x4B3, 0xBC803C, 0x580005} ; // 437 MHz avec ref à 25 MHz //uint32_t registers[6] = {0, 0, 0, 0, 0xBC803C, 0x580005} ; // 437 MHz avec ref à 25 MHz int address,modif=0,WEE=0; int lcd_key = 0; int adc_key_in = 0; int timer = 0,timer2=0; // utilisé pour mesurer la durée d'appui sur une touche unsigned int i = 0; double RFout, REFin, INT, PFDRFout, OutputChannelSpacing, FRACF; double RFoutMin = 35, RFoutMax = 4400, REFinMax = 250, PDFMax = 32; unsigned int long RFint,RFintold,INTA,RFcalc,PDRFout, MOD, FRAC; byte OutputDivider;byte lock=2; unsigned int long reg0, reg1; #define btnRIGHT 0 #define btnUP 1 #define btnDOWN 2 #define btnLEFT 3 #define btnSELECT 4 #define btnNONE 5 //**************************** SP LECTURE BOUTONS ******************************************** int read_LCD_buttons() { adc_key_in = analogRead(0); // read the value from the buttons if (adc_key_in < 790)lcd.blink(); if (adc_key_in < 50)return btnRIGHT; // pour Afficheur ROBOT V1.0 if (adc_key_in < 195)return btnUP; if (adc_key_in < 380)return btnDOWN; if (adc_key_in < 555)return btnLEFT; if (adc_key_in < 790)return btnSELECT; // Fin Afficheur ROBOT1.1 //if (adc_key_in < 50)return btnRIGHT; // pour Afficheur ROBOT 1.1 //if (adc_key_in < 250)return btnUP; //if (adc_key_in < 450)return btnDOWN; //if (adc_key_in < 650)return btnLEFT; //if (adc_key_in < 850)return btnSELECT; // fin Afficheur ROBOT 1.1 return btnNONE; // touches non appuyees } //***************************** SP Affichage Fréquence sur LCD ******************************** void printAll () { //RFout=1001.10 // test lcd.setCursor(0, 0); lcd.print("RF = "); if (RFint < 100000) lcd.print(" "); if (RFint < 10000) lcd.print(" "); lcd.print(RFint/100);lcd.print("."); RFcalc=RFint-((RFint/100)*100); if (RFcalc<10)lcd.print("0"); lcd.print(RFcalc); lcd.print(" MHz"); lcd.setCursor(0,1); if (WEE==0) {lcd.print("REE=");} else {lcd.print("WEE=");} if (memoire<10)lcd.print(" "); lcd.print(memoire,DEC); if ((digitalRead(2)==1))lcd.print(" LOCKED "); else lcd.print(" NOLOCK "); lcd.print(PFDRFout,DEC); lcd.setCursor(poscursor,line); } void WriteRegister32(const uint32_t value) //Programme un registre 32bits { digitalWrite(ADF4351_LE, LOW); for (int i = 3; i >= 0; i--) // boucle sur 4 x 8bits SPI.transfer((value >> 8 * i) & 0xFF); // décalage, masquage de l'octet et envoi via SPI digitalWrite(ADF4351_LE, HIGH); digitalWrite(ADF4351_LE, LOW); } void SetADF4351() // Programme tous les registres de l'ADF4351 { for (int i = 5; i >= 0; i--) // programmation ADF4351 en commencant par R5 WriteRegister32(registers[i]); } // *************** SP ecriture Mot long (32bits) en EEPROM entre adress et adress+3 ************** void EEPROMWritelong(int address, long value) { //Decomposition du long (32bits) en 4 bytes //trois = MSB -> quatre = lsb byte quatre = (value & 0xFF); byte trois = ((value >> 8) & 0xFF); byte deux = ((value >> 16) & 0xFF); byte un = ((value >> 24) & 0xFF); //Ecrit 4 bytes dans la memoire EEPROM EEPROM.write(address, quatre); EEPROM.write(address + 1, trois); EEPROM.write(address + 2, deux); EEPROM.write(address + 3, un); } // *************** SP lecture Mot long (32bits) en EEPROM situe entre adress et adress+3 ************** long EEPROMReadlong(long address) { //Read the 4 bytes from the eeprom memory. long quatre = EEPROM.read(address); long trois = EEPROM.read(address + 1); long deux = EEPROM.read(address + 2); long un = EEPROM.read(address + 3); //Retourne le long(32bits) en utilisant le shift de 0, 8, 16 et 24 bits et des masques return ((quatre << 0) & 0xFF) + ((trois << 8) & 0xFFFF) + ((deux << 16) & 0xFFFFFF) + ((un << 24) & 0xFFFFFFFF); } //************************************ Setup **************************************** void setup() { lcd.begin(16, 2); // two 16 characters lines lcd.display(); analogWrite(10,255); //Luminosite LCD Serial.begin (19200); // Serial to the PC via Arduino "Serial Monitor" at 9600 lcd.print(" GENERATEUR "); lcd.setCursor(0, 1); lcd.print(" ADF4351 "); poscursor = 7; line = 0; delay(1000); lcd.setCursor(0, 0); lcd.print(" par F1CJN "); delay(1000); pinMode(2, INPUT); // PIN 2 en entree pour lock pinMode(ADF4351_LE, OUTPUT); // Setup pins digitalWrite(ADF4351_LE, HIGH); SPI.begin(); // Init SPI bus SPI.setDataMode(SPI_MODE0); // CPHA = 0 et Clock positive SPI.setBitOrder(MSBFIRST); // poids forts en tête if (EEPROM.read(100)==55){PFDRFout=EEPROM.read(20*4);} // si la ref est ecrite en EEPROM, on la lit else {PFDRFout=25;} if (EEPROM.read(101)==55){RFint=EEPROMReadlong(memoire*4);} // si une frequence est ecrite en EEPROM on la lit else {RFint=7000;} RFintold=1234;//pour que RFintold soit different de RFout lors de l'init RFout = RFint/100 ; // fréquence de sortie OutputChannelSpacing = 0.01; // Pas de fréquence = 10kHz WEE=0; address=0; lcd.blink(); printAll(); delay(500); } // Fin setup //*************************************Loop*********************************** void loop() { RFout=RFint; RFout=RFout/100; if ((RFint != RFintold)|| (modif==1)) { //Serial.print(RFout,DEC);Serial.print("\r\n"); if (RFout >= 2200) { OutputDivider = 1; bitWrite (registers[4], 22, 0); bitWrite (registers[4], 21, 0); bitWrite (registers[4], 20, 0); } if (RFout < 2200) { OutputDivider = 2; bitWrite (registers[4], 22, 0); bitWrite (registers[4], 21, 0); bitWrite (registers[4], 20, 1); } if (RFout < 1100) { OutputDivider = 4; bitWrite (registers[4], 22, 0); bitWrite (registers[4], 21, 1); bitWrite (registers[4], 20, 0); } if (RFout < 550) { OutputDivider = 8; bitWrite (registers[4], 22, 0); bitWrite (registers[4], 21, 1); bitWrite (registers[4], 20, 1); } if (RFout < 275) { OutputDivider = 16; bitWrite (registers[4], 22, 1); bitWrite (registers[4], 21, 0); bitWrite (registers[4], 20, 0); } if (RFout < 137.5) { OutputDivider = 32; bitWrite (registers[4], 22, 1); bitWrite (registers[4], 21, 0); bitWrite (registers[4], 20, 1); } if (RFout < 68.75) { OutputDivider = 64; bitWrite (registers[4], 22, 1); bitWrite (registers[4], 21, 1); bitWrite (registers[4], 20, 0); } INTA = (RFout * OutputDivider) / PFDRFout; MOD = (PFDRFout / OutputChannelSpacing); FRACF = (((RFout * OutputDivider) / PFDRFout) - INTA) * MOD; FRAC = round(FRACF); // On arrondit le résultat registers[0] = 0; registers[0] = INTA << 15; // OK FRAC = FRAC << 3; registers[0] = registers[0] + FRAC; registers[1] = 0; registers[1] = MOD << 3; registers[1] = registers[1] + 1 ; // ajout de l'adresse "001" bitSet (registers[1], 27); // Prescaler sur 8/9 bitSet (registers[2], 28); // Digital lock == "110" sur b28 b27 b26 bitSet (registers[2], 27); // digital lock bitClear (registers[2], 26); // digital lock SetADF4351(); // Programme tous les registres de l'ADF4351 RFintold=RFint;modif=0; printAll(); // Affichage LCD } lcd_key = read_LCD_buttons(); // read the buttons switch (lcd_key) // Select action { case btnRIGHT: //Droit poscursor++; // cursor to the right if (line == 0) { if (poscursor == 9 ) { poscursor = 10; line = 0; } //si curseur sur le . if (poscursor == 12 ) { poscursor = 0; line = 1; }; //si curseur à droite } if (line == 1) { if (poscursor == 1 ) {poscursor = 5; line = 1; } //si curseur sur le chiffre memoire if (poscursor == 6 ) {poscursor = 15; line = 1; } //si curseur sur le chiffre memoire if (poscursor==16) {poscursor=5; line=0;}; } //Serial.print (" RIGHT Button\r\n"); lcd.setCursor(poscursor, line); break; case btnLEFT: //Gauche poscursor--; // décalage curseur if (line == 0) { if (poscursor == 4) {poscursor = 15; line = 1; }; if (poscursor == 9) { poscursor = 8; line=0;} } if(line==1){ if (poscursor==255) {poscursor=11; line=0;}; if (poscursor==4) {poscursor=0; line=1;}; if (poscursor==14) {poscursor=5; line=1;}; } //Serial.print(poscursor,DEC); lcd.setCursor(poscursor, line); break; case btnUP: //Haut if (line == 0) { // RFoutfrequency //Serial.print(oldRFint,DEC); if (poscursor == 5) RFint = RFint + 100000 ; if (poscursor == 6) RFint = RFint + 10000 ; if (poscursor == 7) RFint = RFint + 1000 ; if (poscursor == 8) RFint = RFint + 100 ; if (poscursor == 10) RFint = RFint + 10 ; if (poscursor == 11) RFint = RFint + 1 ; if (RFint > 440000)RFint = RFintold; //Serial.print(RFint,DEC); //Serial.print(" \r\n"); } if (line == 1) { if (poscursor == 5){ memoire++; if (memoire==20)memoire=0; if (WEE==0){RFint=EEPROMReadlong(memoire*4); // lecture EEPROM et Affichage if (RFint>440000) RFint=440000; } } if (poscursor==15){ if( PFDRFout==10){PFDRFout=25;} //reglage FREF else if ( PFDRFout==25){PFDRFout=10;} else PFDRFout=25;// au cas ou PFDRF different de 10 et 25 modif=1; } if( (poscursor==0) && (WEE==1))WEE=0; else if ((poscursor==0) && (WEE==0))WEE=1; } printAll(); break; // fin bouton up case btnDOWN: //bas if (line == 0) { if (poscursor == 5) RFint = RFint - 100000 ; if (poscursor == 6) RFint = RFint - 10000 ; if (poscursor == 7) RFint = RFint - 1000 ; if (poscursor == 8) RFint = RFint - 100 ; if (poscursor == 10) RFint = RFint - 10 ; if (poscursor == 11) RFint = RFint - 1 ; if (RFint < 3450) RFint = RFintold; if (RFint > 440000) RFint = RFintold; break; } if (line == 1) { if (poscursor == 5){memoire--; if (memoire==255)memoire=19; if (WEE==0){RFint=EEPROMReadlong(memoire*4); // lecture EEPROM et Affichage if (RFint>440000) RFint=440000; // Serial.print(RFint,DEC); } } // fin poscursor =5 if (poscursor==15){ if( PFDRFout==10){PFDRFout=25;} //reglage FREF else if ( PFDRFout==25){PFDRFout=10;} else PFDRFout=25;// au cas ou PFDRF different de 10 et 25 modif=1; } if( (poscursor==0) && (WEE==1))WEE=0; else if ((poscursor==0)&&(WEE==0))WEE=1; printAll(); // Serial.print (" DOWN Button \r\n"); break; // fin bouton bas } case btnSELECT: do { adc_key_in = analogRead(0); // Test release button delay(1); timer2++; // timer inc toutes les 1 millisecondes if (timer2 > 600) { //attente 600 millisecondes if (WEE==1 || poscursor==15){ if (line==1 && poscursor==15){ EEPROMWritelong(20*4,PFDRFout);EEPROM.write(100,55);} // ecriture FREF else if (WEE==1) {EEPROMWritelong(memoire*4,RFint);EEPROM.write(101,55);}// ecriture RF en EEPROM à adresse (memoire*4) lcd.setCursor(0,1); lcd.print(" MEMORISATION ");} lcd.setCursor(poscursor,line); delay(500);timer2=0; printAll(); }; // mes } while (adc_key_in < 900); // attente relachement break; // Fin bouton Select case btnNONE: { break; }; break; }// Fin LCD keys do { adc_key_in = analogRead(0); delay(1);} while (adc_key_in < 900); // attente relachement touche delay (10);timer++; // inc timer //Serial.print(timer,DEC); if (timer>1000){lcd.noBlink();timer=0;} // curseur off } // fin loop |