Balise CW
par Michel Vonlanthen HB9AFO
Une petite balise bien utile pour signaler sa présence là où il n'y a pas trop de monde, sur 10 GHz par exemple. Petite, alimentée par piles et suffisamment fûtée pour rendre bien des services! |
Cela faisait longtemps que j'avais envie de me construire une petite balise pour mes longs essais sur 10 GHz, notamment lors de la journée de trafic contre le Mont Blanc. C'est suite à une discussion sur une liste web que j'ai pris le mors aux dents et une semaine plus tard la balise était opérationnelle. C'est ça le grand avantage de l'Arduino: pouvoir passer très rapidement de l'idée à la réalisation. D'une part parce que l'électronique est très simple et donc compréhensible, et d'autre part parce qu'il y a des millions d'utilisateurs dans le monde qui ont développé des applications pour l'Arduino et les ont mises à disposition de la communauté. On trouve toujours tout ou partie du code sur le Net. Et comme le langage de programmation de la base de développement Arduino est le C, point n'est besoin d'apprendre un nouveau langage lors de chaque changement de processeur comme c'était le cas auparavant avec les PIC.
Ma construction a donc été facilitée par le découverte du code source de Nicola Salsotto IN3GJH prévu pour un microordinateur Arduino. J'ai donc encapsulé la partie "génération de code télégraphique" dans mon propre code et programmé le reste afin d'obtenir exactement ce que je désirais:
Fig 2: balise vue de l'arrière.
Fig 3: Arduino Pro Mini Fig 5: et son programmateur
Dans le logiciel de programmation de l'Arduino, il faut sélectionner "Arduino Pro ou Pro Mini" dans l'option "Type de carte" du menu "Outils". Dans l'option "Processeur" c'est "ATMega328 (5V, 16MHz)" qui est indiqué. Dans l'option "Programmateur" il faut choisir "AVR ISP".
Fig 6: schéma de la balise
Il est très simple et se passe de commentaires. Les pins d'entrée et de sortie se retrouvent dans le code source. A noter que l'Arduino Pro Mini supporte tout à fait bien l'alimentation en 6 Volts au lieu de 5.
Fig 7: Le boîtier ouvert pour la programmation.
Le programmateur se branche sur l'Arduino. Une fois la programmation terminé, on peut le retirer et refermer le boîtier. La balise fonctionne ensuite toute seule. A noter que le programmateur est alimenté par le port USB et alimente à son tour la balise. Lorsque le programmateur est retiré, ce sont les 4 piles de 1,5V qui font fonctionner la balise.
Le code source du logiciel est ci-dessous
Michel Vonlanthen HB9AFO Août 2017 |
//**************************************** //* * //* BALISE CW * //* * //* de Michel Vonlanthern HB9AFO * //* Version 1.5 du 3 août 2017 * //**************************************** // // inspiré du "Arduino Morse Beacon" // de Nicola Salsotto IN3GJH #define SPEED (16) // vitesse en mots/minute. Defaut: 16 #define DOTLEN (1200/SPEED) // defaut: 1200 #define DASHLEN (3*(1200/SPEED)) // defaut: 3 #define PAUSE 10 // Temps en secondes, temps entre transmissions (CQ)et longueur porteuse (balise). defaut: 10 int commut1Pin = 2; // commutateur, contact 1 int commut2Pin = 3; // commutateur, contact 2 int commut3Pin = 4; // commutateur, contact 3 int tonePin = 5; // tonalité manipulée int pttPin = 6; // PTT int autoPin = 7; // inter auto-manuel (avec sidetone) int keyPin = 8; // manipulateur int pttSWPin = 9; // int ledPin = 13; // manipulation + led int toneFreq = 700; // Fréquence de la tonalité entre 500 et 900 Hz int interState =0; // Etat interrupteur "mode" balise ou CQ int autoState = 0; // Etat interrupteur "manip auto" ou "manip manuelle" int keyState = 1; // Etat manip externe, LOW = key down int pttSWState =1; // Etat inter PTT void sendMsg(char*); void dash(); void dot(); void setup() { pinMode(commut1Pin, INPUT); pinMode(commut2Pin, INPUT); pinMode(commut3Pin, INPUT); pinMode(tonePin, OUTPUT); pinMode(pttPin, OUTPUT); pinMode(keyPin, INPUT); pinMode(autoPin, INPUT); pinMode(pttSWPin, INPUT); pinMode(ledPin, OUTPUT); } void loop() { autoState=digitalRead(autoPin); // manip auto ou manuelle if (autoState == HIGH) // = manipulation manuelle { // MANIPULATION MANUELLE pttSWState=digitalRead(pttSWPin); if (pttSWState==LOW) // PTT ON { digitalWrite(pttPin, HIGH); } // TX ON else { digitalWrite(pttPin, LOW); } // TX OFF keyState=digitalRead(keyPin); if (keyState==LOW) // key down { digitalWrite(ledPin, HIGH); tone(tonePin, toneFreq); } else { digitalWrite(ledPin, LOW); // = key up noTone(tonePin); } } else // = manipulation auto { // MANIULATION AUTOMATIQUE interState=digitalRead(commut1Pin); if (interState == HIGH) // Mode balise { // MODE BALISE pttSWState=digitalRead(pttSWPin); if (pttSWState==LOW) // PTT ON { digitalWrite(pttPin, HIGH); } // TX ON else { digitalWrite(pttPin, LOW); } // TX OFF sendMsg("HB9AFO HB9AFO HB9AFO JN36GN JN36GN JN36GN"); // Longue porteuse delay(1000); digitalWrite(ledPin, HIGH); tone(tonePin, toneFreq); delay(PAUSE*2000); digitalWrite(ledPin, LOW); noTone(tonePin); delay(1000); } interState=digitalRead(commut2Pin); if (interState == HIGH) // Mode CQ { // MODE CQ pttSWState=digitalRead(pttSWPin); if (pttSWState==LOW) // PTT ON { digitalWrite(pttPin, HIGH); } // TX ON else { digitalWrite(pttPin, LOW); } // TX OFF sendMsg("CQ CQ CQ DE HB9AFO HB9AFO HB9AFO PSE K"); digitalWrite(pttPin, LOW); // TX OFF delay(PAUSE*1000); // Période d'écoute } interState=digitalRead(commut3Pin); if (interState == HIGH) // Mode phrase enregistree { } } } // fin de loop // ----------- ROUTINES ------------- //----------------------------------- void dash() { digitalWrite(ledPin, HIGH); tone(tonePin, toneFreq); delay(DASHLEN); digitalWrite(ledPin, LOW); noTone(tonePin); tone(tonePin, 21000); delay(DOTLEN); noTone(tonePin); } //----------------------------------- void dot() { digitalWrite(ledPin, HIGH) ; tone(tonePin, toneFreq); delay(DOTLEN); digitalWrite(ledPin, LOW); noTone(tonePin); tone(tonePin, 21000); delay(DOTLEN); noTone(tonePin); } //----------------------------------- void sendMsg(char *str) { int i; tone(tonePin, 21000); delay(500); noTone(tonePin); for(i=0;i<strlen(str);i++) { switch (str[i]) { case 'A': dot();dash();break; case 'B': dash();dot();dot();dot();break; case 'C': dash();dot();dash();dot();break; case 'D': dash();dot();dot();break; case 'E': dot();break; case 'F': dot();dot();dash();dot();break; case 'G': dash();dash();dot();break; case 'H': dot();dot();dot();dot();break; case 'I': dot();dot();break; case 'J': dot();dash();dash();dash();break; case 'K': dash();dot();dash();break; case 'L': dot();dash();dot();dot();break; case 'M': dash();dash();break; case 'N': dash();dot();break; case 'O': dash();dash();dash();break; case 'P': dot();dash();dash();dot();break; case 'Q': dash();dash();dot();dash();break; case 'R': dot();dash();dot();break; case 'S': dot();dot();dot();break; case 'T': dash();break; case 'U': dot();dot();dash();break; case 'V': dot();dot();dot();dash();break; case 'W': dot();dash();dash();break; case 'X': dash();dot();dot();dash();break; case 'Y': dash();dot();dash();dash();break; case 'Z': dash();dash();dot();dot();break; case ' ': tone(tonePin, 21000); delay(DOTLEN*5); noTone(tonePin); break; case '.': dot();dash();dot();dash();dot();dash();break; case ',': dash();dash();dot();dot();dash();dash();break; case ':': dash();dash();dash();dot();dot();break; case '?': dot();dot();dash();dash();dot();dot();break; case '\'': dot();dash();dash();dash();dash();dot();break; case '-': dash();dot();dot();dot();dot();dash();break; case '/': dash();dot();dot();dash();dot();break; case '(': case ')': dash();dot();dash();dash();dot();dash();break; case '\"': dot();dash();dot();dot();dash();dot();break; case '@': dot();dash();dash();dot();dash();dot();break; case '=': dash();dot();dot();dot();dash();break; case '0': dash();dash();dash();dash();dash();break; case '1': dot();dash();dash();dash();dash();break; case '2': dot();dot();dash();dash();dash();break; case '3': dot();dot();dot();dash();dash();break; case '4': dot();dot();dot();dot();dash();break; case '5': dot();dot();dot();dot();dot();break; case '6': dash();dot();dot();dot();dot();break; case '7': dash();dash();dot();dot();dot();break; case '8': dash();dash();dash();dot();dot();break; case '9': dash();dash();dash();dash();dot();break; } delay(2*DOTLEN); } } |