/* Adaptation par F6IDT d'un programme de AD7C. (Suppression de l'indication du pas pour libérer la deuxième ligne et afficher la tension alim, la force du signal reçu et l'indication de mise en mémoire de la fréquence.) Libre à vous de le modifier à votre convenance... ATTENTION ! A la première utilisation suivre les instructions de la ligne 62. Ce VFO a été conçu pour être associé à un récepteur avec une FI à 18 MHz, tri-bandes 80, 40 et 20 m avec mélangeurs à SA612, filtre à quartz et BFO. Il assure le passage BLI-BLS et la commutation des filtres de bande d'entrée. Le pas de scrutation est sélectionné par le poussoir du codeur et la deuxième ligne de l'afficheur indique la tension d'alimentation et la force des signaux reçus par un simple bargraph. Le module DDS avec un AD9850 délivre un signal sinusoïdal d'environ 750 mV càc au moins dans la plage utilisée ici. La consommation est de 170 mA. */ // Chargement des bibliothèques: #include #include #include //Déclaration des entrées-sorties du module DDS #define W_CLK 13 // Pin 13 - Clock (CLK) #define FQ_UD 12 // Pin 12 - Freq update (FQ) #define DATA 11 // Pin 11 - Serial data (DATA) #define RESET 10 // Pin 10 - Reset (RST) //Déclaration des autres entrées-sorties #define Ualim A5 // Entrée ANA Tension alimentation #define Smetre A4 // Entrée ANA S-mètre #define SSB A3 // Sortie DIG pour sélection USB-LSB #define T2 A2 // Sortie DIG pour sélection des filtres #define T1 A1 // Idem (voir table de vérité sur schéma) #define Step A0 // Entrée DIG bouton codeur #define pulseHigh(pin) {digitalWrite(pin, HIGH); digitalWrite(pin, LOW); } Rotary r = Rotary(2,3); // Entrées interruption du codeur // (obligatoirement ces deux broches) // Déclaration des broches de l'afficheur: lcd(RS, E, DB4, DB5, DB6, DB7) LiquidCrystal lcd(4, 5, 8, 7, 6, 9); int_fast32_t rx=14000000; // Fréquence de départ du VFO (première utilisation) int_fast32_t rx2=1; // Variable contenant la nouvelle fréquence int_fast32_t increment = 1000000; // Pas de 1 MHz au lancement du programme int_fast32_t iffreq = 18000000; // FI en MHz (ici 18 MHz) int buttonstate = 0; int buttonstate2 = 0; float Ubatt; // Variable mesure tension alimentation byte ones,tens,hundreds,thousands,tenthousands,hundredthousands,millions ; String freq; int_fast32_t timepassed = millis(); // "millis" depuis le lancement int memstatus = 1; // Situation de la mise en mémoire. //**************************** int ForceFreq = 1; // 1 à l'origine, à remplacer par 0 pour activer l'EEPROM //**************************** // S-meter: int counter = 0; int j = 0; // Barres de hauteur progressive pour l'affichage des points S byte meter_s1[8] = { B00000, B00000, B00000, B00000, B00000, B00000, B11000, B11000 }; byte meter_s3[8] = { B00000, B00000, B00000, B00000, B00000, B00011, B11011, B11011 }; byte meter_s5[8] = { B00000, B00000, B00000, B00000, B11000, B11000, B11000, B11000, }; byte meter_s7[8] = { B00000, B00000, B00000, B00011, B11011, B11011, B11011, B11011, }; byte meter_s9[8] = { B00000, B00000, B11000, B11000, B11000, B11000, B11000, B11000, }; byte meter_s10[8] = { B00000, B00011, B11011, B11011, B11011, B11011, B11011, B11011, }; byte meter_s20[8] = { B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000, }; byte meter_s30[8] = { B11011, B11011, B11011, B11011, B11011, B11011, B11011, B11011, }; void setup() { lcd.begin(16, 2); // LCD 2 lignes de 16 caractères // S-meter: lcd.createChar(7, meter_s30); lcd.createChar(6, meter_s20); lcd.createChar(5, meter_s10); lcd.createChar(4, meter_s9); lcd.createChar(3, meter_s7); lcd.createChar(2, meter_s5); lcd.createChar(1, meter_s3); lcd.createChar(0, meter_s1); lcd.home(); pinMode(Step,INPUT); pinMode(SSB,OUTPUT); pinMode(T2,OUTPUT); pinMode(T1,OUTPUT); digitalWrite(Step,HIGH); digitalWrite(SSB,LOW); digitalWrite(T2,LOW); digitalWrite(T1,LOW); PCICR |= (1 << PCIE2); PCMSK2 |= (1 << PCINT18) | (1 << PCINT19); sei(); pinMode(FQ_UD, OUTPUT); pinMode(W_CLK, OUTPUT); pinMode(DATA, OUTPUT); pinMode(RESET, OUTPUT); pulseHigh(RESET); pulseHigh(W_CLK); pulseHigh(FQ_UD); // Impulsion pour activer le mode série de l'AD9850 // Datasheet page 12. // Chargement de la fréquence en mémoire: if (ForceFreq == 0) { freq = String(EEPROM.read(0))+String(EEPROM.read(1))+String(EEPROM.read(2))+String(EEPROM.read(3))+String(EEPROM.read(4))+String(EEPROM.read(5))+String(EEPROM.read(6)); rx = freq.toInt(); } } //***** DEBUT DE BOUCLE ***** void loop() { // Rafraichissement de l'affichage si la fréquence a changé: if (rx != rx2){ showFreq(); sendFrequency(rx); rx2 = rx; } // Défilement des pas lorsque le bouton du codeur est activé: buttonstate = digitalRead(Step); if(buttonstate == LOW) { setincrement(); } // Mise en mémoire de la fréquence si elle a été // modifiée au cours des dernières 5 secondes if(memstatus == 0){ if(timepassed+5000 < millis()){ storeMEM(); } } { alim(analogRead(Ualim));} { bargraph(analogRead(Smetre));} lcd.noCursor(); } //***** FIN DE BOUCLE ***** // Routine d'interruption pour la gestion du codeur: ISR(PCINT2_vect) { unsigned char result = r.process(); if (result) { if (result == DIR_CW){rx=rx+increment;} else {rx=rx-increment;}; if (rx >=16000000){rx=rx2;}; // Limite supérieure du VFO (16 MHz) if (rx <=2500000){rx=rx2;}; // Limite inférieure du VFO (2,5 MHz) } } // Calcul de la fréquence (datasheet page 8) = * /2^32 void sendFrequency(double frequency) { // BFO et gestion des 3 filtres d'entrée du récepteur (voir schéma): if (frequency > 10000000){ // Bande 14 MHz en BLS digitalWrite(SSB,HIGH);} else digitalWrite(SSB,LOW); if (frequency < 5500000){ // Active le filtre 3,5 MHz digitalWrite(A1,HIGH); digitalWrite(A2,HIGH);} if (frequency >= 5500000 && frequency < 10500000){ // Active le filtre 7 MHz digitalWrite(A1,HIGH); digitalWrite(A2,LOW);} if (frequency >= 10500000){ // Active le filtre 14 MHz digitalWrite(A1,LOW); digitalWrite(A2,HIGH);} frequency=iffreq-frequency; // FI - F car FI supérieure à la bande haute int32_t freq = frequency * 4294967295/125000000; // La fréquence peut être ajustée ici for (int b=0; b<4; b++, freq>>=8) { tfr_byte(freq & 0xFF); } tfr_byte(0x000); // Tous les bits à zéro pour l'AD9850 pulseHigh(FQ_UD); // Terminé! La fréquence est présente en sortie } // Transfert bit par bit (LSB d'abord) dans l'AD9850 via le serial DATA void tfr_byte(byte data) { for (int i=0; i<8; i++, data>>=1) { digitalWrite(DATA, data & 0x01); pulseHigh(W_CLK); // Après chaque bit envoyé on active CLK } } /* void setincrement(){ // Balayage décroissant (1 MHz, 100 kHz,...., 100 Hz, 10 Hz) if (increment == 1000000){increment = 100000; lcd.setCursor(4,0); lcd.cursor();} else if (increment == 100000){increment = 10000; lcd.setCursor(5,0); lcd.cursor();} else if (increment == 10000){increment = 1000; lcd.setCursor(6,0); lcd.cursor();} else if (increment == 1000){increment = 100; lcd.setCursor(8,0); lcd.cursor();} else if (increment == 100){increment = 10; lcd.setCursor(9,0); lcd.cursor();} else{increment = 1000000; lcd.setCursor(2,0); lcd.cursor();} delay(700); // Délai dans le balayage des pas } */ void setincrement(){ // Balayage décroissant (1 MHz, 100 kHz,...., 100 Hz, 10 Hz) if (increment == 1000000){increment = 100000; lcd.setCursor(4,0); lcd.cursor();} // On saute alors le pas de 10 kHz else if (increment == 100000){increment = 1000; lcd.setCursor(6,0); lcd.cursor();} else if (increment == 1000){increment = 100; lcd.setCursor(8,0); lcd.cursor();} else if (increment == 100){increment = 10; lcd.setCursor(9,0); lcd.cursor();} else{increment = 1000000; lcd.setCursor(2,0); lcd.cursor();} delay(700); // Délai dans le balayage des pas } void showFreq(){ millions = int(rx/1000000); hundredthousands = ((rx/100000)%10); tenthousands = ((rx/10000)%10); thousands = ((rx/1000)%10); hundreds = ((rx/100)%10); tens = ((rx/10)%10); ones = ((rx/1)%10); lcd.setCursor(0,0); lcd.print(" "); if (millions > 9){lcd.setCursor(1,0);} else{lcd.setCursor(2,0);} lcd.print(millions); lcd.print(","); lcd.print(hundredthousands); lcd.print(tenthousands); lcd.print(thousands); lcd.print("."); lcd.print(hundreds); lcd.print(tens); lcd.print(ones); lcd.print(" MHz "); timepassed = millis(); memstatus = 0; } void storeMEM(){ //Ecriture dans l'EEPROM EEPROM.write(0,millions); EEPROM.write(1,hundredthousands); EEPROM.write(2,tenthousands); EEPROM.write(3,thousands); EEPROM.write(4,hundreds); EEPROM.write(5,tens); EEPROM.write(6,ones); memstatus = 1; // Indique au programme que la mémoire a été écrite lcd.setCursor(8,2); lcd.print("MEM"); delay(1000); lcd.setCursor(8,2); lcd.print(" "); } void bargraph(int data) { j = map(data / 8, 0, 127, 0, 7); if(j >= counter){ for(counter; counter <= j ; counter++) { lcd.setCursor(12+counter/2,1); lcd.write(counter); lcd.setCursor((12+counter/2)+1,1); lcd.print(" "); } } else { for(counter; counter > j ; counter--); } } void alim(float data){ Ubatt = data * 14 / 1024; lcd.setCursor(1,1); lcd.print("+"); lcd.print(Ubatt, 1); lcd.print("V"); lcd.print(" "); delay(100); }