/////////////////////////////////////////////////////////////////////////////////////////// // DECLARATIONS DES VARIABLES - BIBLIOTHEQUES - INITIALISATION // /////////////////////////////////////////////////////////////////////////////////////////// #include // Déclaration de la librairie de gestion de l’afficheur LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // Mode de connexion de l'afficheur (objet appelé lcd) // Déclaration variables et entrées/sorties du clavier analogique #define ClavierAnalog 1 // Définition de la constante ClavierAnalog égale à 1 int tensionClav = 0; // tensionClav est la variable qui sera lue sur l'entrée analogique 1 boolean avant [8] = {false}; // Tableau contenant les états précédents des boutons poussoirs (false = bouton relaché) // Déclaration des variables des boutons poussoirs : bouton relaché = false, bouton enfoncé = true boolean bouton_0 = false; // Non câblé sur la maquette boolean bouton_1 = false; // BLI, BLS boolean bouton_2 = false; // 40 m ou 10 m boolean bouton_3 = false; // RIT boolean bouton_4 = false; // Pas en fréquence boolean bouton_5 = false; // Provisoirement inutilisé boolean bouton_6 = false; // Provisoirement inutilisé // Déclaration des variables pour sélectionner fréquence, pas en fréquence, fréquence émission, fréquence réception, FI, OL int pas_en_freq [] = {10, 100, 1000, 10000}; // Tableau contenant les 4 pas en fréquence possibles : 10, 100, 1000 ou 10000 Hz int pef; // Variable pas en fréquence (pef) byte index_pef; // Déclaration de l'index "pas en fréquence" unsigned long freq40; // Fréquence courante bande 40 m unsigned long freq10; // Fréquence courante bande 10 m unsigned long freq; // Variable fréquence émission servant aux calculs unsigned long freqFI; // Fréquence FI. Non utilisée dans la partie 1. unsigned long freqOL; // Non utilisée dans la partie 1. // Déclaration des variables pour sélectionner le mode BLI/BLS char* mode_BLU[] = {"BLI", "BLS"}; // Tableau contenant 2 chaînes de caractères BLI et BLS byte index_BLU; // Variable de l'index_BLU (0 = BLI, 1 = BLS) // Déclaration des variables pour sélectionner la bande 40 m ou 10 m byte bande; // Variable bande (0 pour le 40 m, 1 pour le 10 m) byte pos_freq; // La fréquence sur 10 m s'affichera sur le 6ème digit (pos_freq = 5), le 5ème pour le 10 m. Valeur calculée // Déclaration des variables du S-mètre et du ROS-mètre #define Smetre 0 // Définition de la constante Smetre (= 0) #define Rosmetre 0 // Définition de la constante Rosmetre (= 0) int tensionA0 = 0; // Initialisation à 0 de la variable tensionA0 // Déclaration de la variable émission/réception byte RxTx = 0; // En réception RxTx = 0, en émission RxTx = 1 // Déclaration des variables du RIT byte etat_RIT; // RIT actif : etat_RIT = 1, sinon 0 int Rit; //Décalage en fréquence positif ou négatif // Déclaration AD9851 #define DDS_CLOCK 179996860 // Constante à ajuster pour calibrer le DDS (initialement 180000000) byte LOAD = 12; // Port digital 12 affecté à LOAD byte CLOCK = 13; // Port digital 13 affecté à CLOCK byte DATA = 11; // Port digital 11 affecté à DATA // Déclaration des ports et des variables de l'encodeur optique #define encodeur_A 2 // Voie A de l'encodeur sur le port digital D2 #define encodeur_B 3 // Voie B de l'encodeur sur le port digital D3 boolean etat_A; // Etat de A boolean etat_B; // Etat de B ///////////////////////////////////////////////////////////////////////// //////////////////////////// SETUP ///////////////////////////////// ///////////////////////////////////////////////////////////////////////// void setup() { lcd.begin(16, 2); // Initialisation de l'afficheur (16 caractères, 2 lignes) pinMode (10, OUTPUT); // Port digital D10 configuré en sortie pour commande BLI/BLS pinMode (0, OUTPUT); // Port digital D0 configuré en sortie pour commande 40 m/10 m pinMode (1, INPUT); // Port digital D1 configuré en entrée pour RX ou TX // Initialisation du DDS, de l'encodeur et des interruptions pinMode (DATA, OUTPUT); // Port digital D11 configuré en sortie (ves DDS-D7) pinMode (CLOCK, OUTPUT); // Port digital D13 configuré en sortie (DDS-WCLK) pinMode (LOAD, OUTPUT); // Port digital D12 configuré en sortie (DDS-FQUP) pinMode(encodeur_A, INPUT); // Port digital D2 configuré en entrée (encodeur optique voie A) pinMode(encodeur_B, INPUT); // Port digital D3 configuré en entrée (encodeur optique voie B) attachInterrupt(0, Traitement_A, CHANGE); // Interruption provoquée par le changement d'état du port digital D2 attachInterrupt(1, Traitement_B, CHANGE); // Interruption provoquée par le changement d'état du port digital D3 // Chargement des paramètres initiaux freq40 = 7100000; // Fréquence initiale sur 40 m (modifiable) freq10 = 28480000; // Fréquence initiale sur 10 m (modifiable) freq = freq40; // Fréquence à la mise sous tension (modifiable en freq10) bande = 0; // Bande des 40 m la mise sous tension (modifiable en bande = 1) index_BLU = 0; // BLI à l'allumage (modifiable en index_BLU = 1) pos_freq = 5; // Affichage de la fréquence sur le digit 6 (si bande des 40 m, sinon digit 5) etat_RIT = 0; // RIT inactif (modifiable) Rit = 0; // Décalage nul (modifiable) index_pef = 0; // Index du tableau des pas en fréquence (0, 1, 2 ou 3) pef = pas_en_freq [index_pef]; // index_pef = 0 correspond à 10 Hz (modifiable) } ///////////////////// FIN DE SETUP //////////////// /////////////// PROGRAMME PRINCIPAL void() //////////// void loop() { lcd.clear(); // Effacement de l'afficheur lcd.setCursor (0,0); // Positionnement du curseur position 0, ligne 0 lcd.print (mode_BLU[index_BLU]); // Affichage de BLI ou BLS RXTX (); // Appel de la fonction RXTX () définie en fin de programme (à ne pas confondre avec la variable RxTx) PAS_FREQUENCE (); // Appel de la fonction PAS_FREQUENCE () définie en fin de programme RIT(); // Appel de la fonction RIT () définie en fin de programme CLAVIER (); // Appel de la fonction CLAVIER() définie en fin de programme // Sélection BLI ou BLS if ((bouton_1 == true) && (avant[1] == false)) { digitalWrite (5,HIGH); index_BLU = index_BLU + 1; avant[1] = bouton_1; if(index_BLU > 1)// La variable index_BLU ne peut prendre que 2 valeurs (0 ou 1) { index_BLU = 0; // Remise à 0 } } if ((bouton_1 == false) && (avant[1] == true)) { avant[1] = false; } BLU (); // Commutation 40m /10m if ((bouton_2 == true) && (avant[2] == false)) { digitalWrite (0,HIGH); bande = bande + 1; etat_RIT = 0; Rit = 0; avant[2] = bouton_2; // Sélection de la bande à afficher if (bande == 1) // 10 m { index_BLU = 1; freq = freq10 ; // Fréquences sur la bande des 10m pos_freq = 4; } else // 40 m { index_BLU = 0; freq = freq40;// Fréquences sur la bande des 40m pos_freq = 5; } if (bande > 1) { bande = 0; digitalWrite (0,LOW); } } if ((bouton_2 == false) && (avant[2] == true)) { avant[2] = false; } /////////////////// Fin de Fréquence ↓ et Fréquence ↑ et RIT////////////////////////// envoyerFrequence(freq); // Appel de la fonction envoyerFrequence (DDS) } /// FIN DE void() /////////////////////////////////////////////////////////////////// ////////////// DEFINITION DES FONCTIONS ////////////////////////// /////////////////////////////////////////////////////////////////// // RXTX void RXTX() { lcd.setCursor (pos_freq,0); // Positionnement du curseur sur le 5ème ou 6ème digit RxTx = digitalRead (1); // Lecture de l'état émission ou réception sur le port digital A1 if (RxTx==HIGH)// Le transceiver est en mode émission { lcd.print(float(freq)/1000); // Affiche la fréquence d'émission AFF_RIT (); // Affichage du RIT (si activé) lcd.setCursor(0,1); // Positionnement du curseur position 0, ligne 1 pour afficher le ROS-mètre ROSMETRE (); // Ne pas confondre Rosmetre en tant que variable et ROSMETRE en tant que fonction } else { RIT (); // Appel de la fonction RIT AFF_RIT (); // Affichage du RIT (si activé) if ((Rit != 0) && (etat_RIT == 1)) { lcd.setCursor (pos_freq,0); lcd.print(float(freq + Rit)/1000); // Affiche la fréquence de réception en kHz avec 2 chiffres après la virgule } else { lcd.setCursor (pos_freq,0); lcd.print(float(freq)/1000); // Affiche la fréquence de réception sans RIT en kHz avec 2 chiffres après la virgule } lcd.setCursor(0,1); // Positionnement du curseur position 0, ligne 1 pour afficher le S-mètre SMETRE (); // Ne pas confondre Smetre en tant que variable et SMETRE en tant que fonction } } ////////////////////////////////////////////////////////////////////////// //Commutation du port 10 (BLI/BLS) void BLU() { if(index_BLU == 0)// BLI { digitalWrite (10,LOW); // Le port digital D10 est mis à l'état bas (BLI) } else { digitalWrite (10,HIGH); // Sinon, le port digital D10 est mis à l'état haut (BLS) } } //////////////////////////////////////////////////////////////////////////// // // Traitement de l'interruption générée par le changement d'état de A void Traitement_A() { // Transition montante? if ((digitalRead(encodeur_A) == HIGH)&(!etat_B)) { etat_A = true; /////////////////////////////////////////////////////////////////////////// // Instructions à exécuter : if (etat_RIT == 0) // Teste si le RIT est hors service { if (bande == 1) { freq = freq10; freq = freq + pef; // La fréquence est augmentée du pas défini par l'utilisateur freq10 = freq; } else { freq = freq40; freq = freq + pef; // La fréquence est augmentée du pas défini par l'utilisateur freq40 = freq; } } else // Le RIT est activé { if (RxTx==LOW) // Le réglage du décalage du RIT n'est possible qu'en mode réception { Rit = Rit + 10; // La fréquence est augmentée de 10 Hz (modifiable) } } } // Fin des instructions à exécuter. /////////////////////////////////////////////////////////////////////////// // Transition descendante? if (digitalRead(encodeur_A) == LOW) { etat_A = false; } } // Traitement de l'interruption générée par le changement d'état de B void Traitement_B() { // Transition montante? if ((digitalRead(encodeur_B) == HIGH)&(!etat_A)) { etat_B = true; ///////////////////////////////////////////////////////////////////////////// // Instructions à exécuter : if (etat_RIT == 0) // Teste si le RIT est hors service { if (bande == 1) { freq = freq10; freq = freq - pef; // La fréquence est augmentée du pas défini par l'utilisateur freq10 = freq; } else { freq = freq40; freq = freq - pef; // La fréquence est augmentée du pas défini par l'utilisateur freq40 = freq; } } else // Le RIT est activé { if (RxTx==LOW) // Le réglage du décalage du RIT n'est possible qu'en mode réception { Rit = Rit - 10; // La fréquence est diminuée de 10 Hz (modifiable) } } } // Fin des instructions à exécuter. /////////////////////////////////////////////////////////////////////////// // Transition descendante? if (digitalRead(encodeur_B) == LOW) { etat_B = false; } } //////////////////////////////////////////////////////////////////// //Détermination du pas en fréquence (10, 100, 1000 ou 10000 Hz) void PAS_FREQUENCE () { if ((bouton_4 == true) && (avant[4] == false)) { avant[4] = bouton_4; index_pef = index_pef + 1; if(index_pef > 3) // le compteur_pef peut prendre les valeurs 0, 1, 2 ou 3 { index_pef = 0; } if (index_pef == 0 || index_pef == 1) { lcd.setCursor (11 - index_pef, 0); // Positionne le curseur sur le chiffre 100 Hz ou 10 Hz } else { lcd.setCursor (11 - index_pef-1, 0); // Positionne le curseur sur le chiffre des 10 kHz ou kHz } lcd.print (char (255)); delay (200);// Noircit pendant 2/10ème de seconde le chiffre sélectionné pour indiquer le pas en fréquence pef = pas_en_freq [index_pef]; // Le pas en fréquence devient 10, 100, 1000 ou 10000 Hz } if ((bouton_4 == false) && (avant[4] == true)) { avant[4] = false; } } ////////////////////////////////////////// // Gestion du RIT void RIT () { if ((bouton_3 == true) && (avant[3] == false)) { avant[3] = bouton_3; etat_RIT = etat_RIT + 1; if(etat_RIT > 1) { etat_RIT = 0; } } if ((bouton_3 == false) && (avant[3] == true)) { avant[3] = false; } } // Affichage RIT void AFF_RIT () { if (etat_RIT == 1) { lcd.setCursor (12, 0); if (Rit==0) { lcd.print ("="); } if (Rit > 0) { lcd.print ("+"); } if (Rit < 0) { lcd.print ("-"); } } } /////////////////////////////////////////// // Gestion du clavier analogique void CLAVIER() { tensionClav = analogRead(ClavierAnalog); // La variable tensionClav prend la valeur lue sur l'entrée A0 (car ClavierAnalog = 0) if (tensionClav > 117 && tensionClav < 137) // Si la valeur convertie de la tension lue est entre 117 et 137... { bouton_6 = true; // ...le bouton est considéré comme enfoncé } else { bouton_6 = false; } if (tensionClav > 246 && tensionClav < 266) // idem pour tous les autres valeurs { bouton_5 = true; } else { bouton_5 = false; } if (tensionClav > 374 && tensionClav < 394) { bouton_4 = true; } else { bouton_4 = false; } if (tensionClav > 502 && tensionClav < 522) { bouton_3 = true; } else { bouton_3 = false; } if (tensionClav > 630 && tensionClav < 650) { bouton_2 = true; } else { bouton_2 = false; } if (tensionClav > 758 && tensionClav < 778) { bouton_1 = true; } else { bouton_1 = false; } if (tensionClav > 890 && tensionClav < 900) { bouton_0 = true; } else { bouton_0 = false; } } /////////////////////////////////////////// // Gestion du S-mètre void SMETRE () { tensionA0 = map(analogRead(Smetre), 0, 1023, 0, 500); // Port A0, plage 0 à 1023 ramenée de 0 à 500 (voir explication dans l'article) if (tensionA0 < 7) // Si la valeur de la tension convertie est < 7... { lcd.print("<"); // ...le caractère < est affiché lcd.setCursor(10,1); // Le curseur est positionné après la fin de la barre graphique lcd.print(" 6 && tensionA0 < 47) { lcd.print(char (255)); // ...le caractère ■ est affiché lcd.setCursor(11,1); lcd.print("S1"); } if (tensionA0 > 46 && tensionA0 < 76) // idem pour tous les autres valeurs { lcd.print(char (255)); lcd.print(char (255)); lcd.setCursor(11,1); lcd.print("S2"); } if (tensionA0 > 75 && tensionA0 < 110) { lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.setCursor(11,1); lcd.print("S3"); } if (tensionA0 > 109 && tensionA0 < 146) { lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.setCursor(11,1); lcd.print("S4"); } if (tensionA0 > 145 && tensionA0 < 181) { lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.setCursor(11,1); lcd.print("S5"); } if (tensionA0 > 180 && tensionA0 < 216) { lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.setCursor(11,1); lcd.print("S6"); } if (tensionA0 > 215 && tensionA0 < 249) { lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.setCursor(11,1); lcd.print("S7"); } if (tensionA0 > 248 && tensionA0 < 290) { lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.setCursor(11,1); lcd.print("S8"); } if (tensionA0 > 289 && tensionA0 < 350) { lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.setCursor(11,1); lcd.print("S9"); } if (tensionA0 > 349 && tensionA0 < 400) { lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(">"); lcd.setCursor(11,1); lcd.print("S9+10"); } if (tensionA0 > 399) { lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(">>"); lcd.setCursor(11,1); lcd.print("S9+20"); } } /////////////////////////////////////////// // Gestion du ROS-mètre // même fonctionnement que le S-mètre, avec des seuils et affichages différents void ROSMETRE () { tensionA0 = map(analogRead(Rosmetre), 0, 1023, 0, 500); // Port analogique A0, plage 0 à 1023 ramenée à 500 if (tensionA0 < 7) { lcd.setCursor(8,1); lcd.print("ROS=1"); } if (tensionA0 > 6 && tensionA0 < 47) { lcd.print(char (255)); lcd.setCursor(8,1); lcd.print("ROS=1.1"); } if (tensionA0 > 46 && tensionA0 < 76) { lcd.print(char (255)); lcd.print(char (255)); lcd.setCursor(8,1); lcd.print("ROS=1.3"); } if (tensionA0 > 75 && tensionA0 < 110) { lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.setCursor(8,1); lcd.print("ROS=1.7"); } if (tensionA0 > 109 && tensionA0 < 146) { lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.setCursor(8,1); lcd.print("ROS=2"); } if (tensionA0 > 145 && tensionA0 < 181) { lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.setCursor(8,1); lcd.print("ROS=2.5"); } if (tensionA0 > 180 && tensionA0 < 216) { lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.setCursor(8,1); lcd.print("ROS=3"); } if (tensionA0 > 215) { lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.print(char (255)); lcd.setCursor(7,1); lcd.print(">3 DANGER"); } } ////////////////////////////////////////////////////////////////////////////// // Gestion DDS // // Original code from Peter Marks // // http://blog.marxy.org/2008/05/controlling-ad9851-dds-with-arduino.html // // Modified par George Smart, M1GEO - 12 Feb 2012 // ////////////////////////////////////////////////////////////////////////////// void envoyerFrequence(unsigned long freq) { unsigned long tuning_word = (freq * pow(2, 32)) / DDS_CLOCK; digitalWrite (LOAD, LOW); for(int i = 0; i < 32; i++) { if ((tuning_word & 1) == 1) outOne(); else outZero(); tuning_word = tuning_word >> 1; } byte_out(0x09); digitalWrite (LOAD, HIGH); } void byte_out(unsigned char byte) { int i; for (i = 0; i < 8; i++) { if ((byte & 1) == 1) outOne(); else outZero(); byte = byte >> 1; } delay (10); // initialement à 200. Ajuster cette valeur pour augmenter ou diminuer la vitesse de synthèse en fréquence } void outOne() { digitalWrite(CLOCK, LOW); digitalWrite(DATA, HIGH); digitalWrite(CLOCK, HIGH); digitalWrite(DATA, LOW); } void outZero() { digitalWrite(CLOCK, LOW); digitalWrite(DATA, LOW); digitalWrite(CLOCK, HIGH); }