MAJ des fréquences
L'accord précis sur une station, décrit dans les pages précédentes, implique de gérer une liste des fréquences régionales. Voici les différentes pistes explorées.
1 - Utiliser un tableau de variables directement dans le programme.
Ma première idée était d'insérer directement dans le code un tableau de type int pour stocker les fréquences locales.
int tabFreqDur[] = {878,884,888,895,901,906,912,920,924,930,942,947,957,961,968,977,981,989,995,999,1009,1013,1018,1024,1029,1034,1038,1043,1047,1055,1062,1067,1072};
- Avantage :
- Simple à mettre en œuvre.
- Inconvénients :
- Occupe beaucoup de place en mémoire. Ce n'est pas gênant si l'on se contente des fonctions de base en radio mais cela devient ingérable en ajoutant un écran Oled et le décodage RDS. La mémoire vive de l'Arduino n'est que de 2Ko et un simple tableau comme ci-dessus occupe déjà facilement une centaine d'octets.
- La mise à jour des fréquences oblige à reflasher le programme dans l'Arduino. Donc ouvrir la radio, se brancher sur l'Arduino, etc. Impossible à faire pour un utilisateur non équipé.
2 - Stocker les fréquences locales dans l'EEProm de l'Arduino
La deuxième piste a été de stocker les fréquences locales dans l'Eeprom interne de l'Arduino (1Ko) avec un programme dédié à l'écriture :
#if ECRITEEPROM // on ecrit une fois le tableau de frequences int tabFreqDur[] = {878,884,888,895,901,906,912,920,924,930,942,947,957,961,968,977,981,989,995,999,1009,1013,1018,1024,1029,1034,1038,1043,1047,1055,1062,1067,1072}; int rangFreq=0; for (int indFreq=4;indFreq<70;indFreq+=2) { EEPROM.write(indFreq,tabFreqDur[rangFreq]); // LSB EEPROM.write(indFreq+1,(tabFreqDur[rangFreq]>>8)); // MSB Serial.print(rangFreq); Serial.println(tabFreqDur[rangFreq]); rangFreq++; delay(1000); } #endif
Puis quelques lignes de code pour le charger en mémoire au démarrage du programme :
// recuperation du tableau des frequences en EEPROM int nbFreqEEPROM=103; // il vaut mieux fixer une borne de 50 frequences max chaque frequence prends deux octets int freqEEPROMLSB, freqEEPROMMSB; nbFreq=0; // prudence ! for(int indEEPROM=4;indEEPROM<nbFreqEEPROM;indEEPROM+=2) { freqEEPROMLSB=EEPROM.read(indEEPROM); // poids faible. La fonction EEPROM.get n'existe plus ? delay(10); // pause! freqEEPROMMSB=EEPROM.read(indEEPROM+1); // poids fort delay(10); // pause! tabFreq[nbFreq]=(freqEEPROMMSB<<8)+freqEEPROMLSB; // tests de fin de lecture des frequences if(tabFreq[nbFreq]==0) break; if(tabFreq[nbFreq]>1900) break; nbFreq++; }
- Avantage :
- Pas grand chose de plus.
- Inconvénients :
- Les mêmes que ci-dessus avec en plus des acrobaties pour découper les int des fréquences en octets car l'Eeprom de l'Arduino doit s'adresser octet par octet.
En gros, un retour à la case départ.
Mais avec quand même la découverte de quelques possibilités :
- La mise à jour de l'Eeprom est possible en cours d'exécution du programme ;
- Il est inutile de stocker les fréquences sur deux octets car il suffit de les écrire modulo 860 (par exemple) pour gagner un octet. C'est toujours cela de pris;
Exemple de code indépendant pour charger dans la mémoire Eeprom de l'Arduino un tableau de fréquences modulo 860.
#define ECRITEEPROM 0 // a valider lorsque pret #include <EEPROM.h> // tableau des fréquences + limites int tabFreqDur[] = {878,884,888,895,901,906,912,920,924,930,942,947,957,961,968,977,981,989,995,999,1009,1013,1018,1024,1029,1034,1038,1043,1047,1055,1062,1067,1072,1090,1090}; byte nbFreqMax=(sizeof(tabFreqDur)/sizeof(int)); void setup() { Serial.begin(115200); Serial.println("\nRadio EEPROM test..."); #if ECRITEEPROM // on ecrit une fois le tableau de frequences Serial.println("\nEcriture EEPROM freq... démarrage dans 10 secondes"); delay(10000); for (int indFreq=0;indFreq<nbFreqMax;indFreq++) { // EEPROM.update n'écrit que si la valeur présente est # de la nouvelle. Evite les cycles d'écriture qui sont limités en nombre. EEPROM.update(indFreq,tabFreqDur[indFreq]-860); // -860 pour tenir sur un entier. Le 860 sera ajouté dans le programme TSF. On économise nbFreqMax octets Serial.print("indFreq : "); Serial.print(indFreq); Serial.print(" Fréquence : "); Serial.println(tabFreqDur[indFreq]); delay(500); } #endif }
3 - Stocker les fréquences dans une mémoire externe.
Pour éviter une usure prématurée de l'Eeprom de l'Arduino (on verra plus bas qu'il n'en est rien) j'ai testé le stockage des fréquences sur une petite mémoire externe 24LC02B facilement disponible et très bon marché. Ce type de mémoire est très simple à utiliser et des bibliothèques de gestion existent pour l'Arduino. Avantage supplémentaire : en l'installant sur un support il devient possible de la remplacer sans trop de difficultés par une autre, programmée pour une région différente.
Illustrations ci-dessous (photo de droite, une vis collée sur le boitier facilite l'échange. Le top !) :
24LC02B sur maquette | 24LC02B in situ (entourée en rouge) |
---|---|
Extraits du code de lecture de l'Eeprom 24LC02B :
byte readbyte(int adressei2c, unsigned int adresseMem ) { byte lecture = 0; Wire.beginTransmission(adressei2c); // adresse i2c du 24LC01B Wire.write(adresseMem); // numéro de l'octet qu'on veut lire Wire.endTransmission(); Wire.requestFrom(adressei2c, 1); // on demande au 24LC01B d'envoyer de l'info delay(2); if (Wire.available()) { // réception de l'info lecture = Wire.read(); } return lecture; } void writebyte(int adressei2c, unsigned int adresseMem, byte data ) { Wire.beginTransmission(adressei2c); //adresse I2C de l'EEPROM Wire.write(adresseMem); // numéro de l'octet à modifier Wire.write(data); // nouvelle valeur que doit prendre l'octet Wire.endTransmission(); // fin de la transmission I2C delay(5); } int lisFreqEeprom(int indice) { // recuperation d'une frequence en EEPROM selon son indice // frequence lue sur un octet = frequence reelle - 860 int freqEEPROM; freqEEPROM=readbyte(adresse_EEPROM,indice)+860; delay(2); // pour ne pas avoir gerer le nombre de frequence en EEPROM (j'y arrive pas !), on positionne la frequence lue en borne sup // sauf quand on passe hors borne de l'EEPROM. Cette freqMAX n'est utilisee que dans la boucle principale if(freqEEPROM<1080) freqMAX=freqEEPROM; return (freqEEPROM); }
4 - Stocker les fréquences dans l'Eeprom de l'Arduino AVEC mise à jour des fréquences directement sur l'appareil.
Les procédures de mise à jour exposées précédemment fonctionnaient correctement mais avaient un inconvénient majeur : la nécessité d'une intervention physique sur la radio.
Si changer une Eeprom sur un ancien transistor alimenté par piles ne présente pas de danger, il en va autrement quand il faut intervenir sur une TSF pleine de haute tension ! De plus, je sais maintenant que seules les opérations d'écriture usent l'Eeprom de l'Arduino, pas celles de lecture. Il est donc tout à fait possible de se passer de l'Eeprom externe.
Enfin, à partir du moment où les radios ont été équipées d'un écran Oled, l'idée d'une procédure de mise à jour l'utilisant a commencé à faire son chemin...
J'ai passé une partie de ma vie à concevoir des IHM en mode texte. Dans ce domaine il faut faire simple et sobre !
Le principe de l'interface devra donc être "Un bouton une valeur".
Il y avait déjà dans le code tout ce qu'il fallait pour afficher une fréquence (la valeur ). Il restait à ajouter le bouton de commande ce qui ne présentait aucune difficulté.
Déclenchement de la procédure de mise à jour
- Au démarrage de la radio, faire une lecture de la valeur du bouton de commande;
- Si le bouton est appuyé, appeler le sous-programme de mise à jour.
Lecture de la valeur du bouton de mise à jour au démarrage :
... // le bouton pour déclencher la mise à jour des stations en EEPROM const uint8_t btnMAJ = A0; // on peut prendre une entrée analog uint8_t btnMAJval=0; ... void setup() { // lecture du bouton de maj avant toutes choses UNE fois dans le setup pinMode(btnMAJ,INPUT_PULLUP); btnMAJval=analogRead(btnMAJ); if(btnMAJval<200){ majEEPROM(); } ...
Notification à l'utilisateur du déclenchement de la mise à jour :
Un petit compte à rebours d'environ 6 secondes s'affiche.
Le code :
void majEEPROM(){ // mise à jour interactive des fréquences stockées en EEPROM // une boucle affiche les xxx fréquences possibles, attend un peu un éventuel appui sur le bouton // si le bouton est appuyé, la valeur affichée est stockée en EEPROM for(uint8_t ind=3;ind>0;ind--){ oled.clear(); oled.setCursor(50,2); oled.setFont(Callibri11); oled.print("MAJ"); oled.setCursor(45,3); oled.print("DANS"); oled.setFont(Callibri11_bold); oled.setCursor(55,4); oled.print(ind); delay(2000); }
Défilement des fréquences.
Après le compte à rebours, les fréquences de 87,5 à 108 Mhz vont défiler sur l'écran. Pour enregistrer une fréquence dans la mémoire de l'Arduino, il suffira - lorsqu'elle s'affiche - d'appuyer sur le bouton jusqu'à l'apparition de la mention "OK" sur l'écran, preuve que la fréquence a bien été prise en compte (Désolé une fois de plus pour la piètre qualité des photos).
Le code.
void majEEPROM(){ ... uint8_t posEEPROM=0; delay(100); oled.clear(); for(float frequence=875;frequence<1081;frequence++){ afficheFreq(frequence); delay(1000); btnMAJval=analogRead(btnMAJ); if(btnMAJval<200){ oled.setCursor(52,4); oled.print("OK"); // EEPROM.update n'écrit que si la valeur présente est # de la nouvelle. Evite les cycles d'écriture qui sont limités en nombre. EEPROM.update(posEEPROM,frequence-860); // -860 pour tenir sur un entier. Le 860 sera ajouté dans le programme TSF. On économise nbFreqMax octets posEEPROM++; delay(500); } delay(500); } // ecriture de deux valeurs talons apres la derniere frequence EEPROM.update(posEEPROM,230); // 1090-860 pour tenir sur un entier. Le 860 sera ajouté dans le programme TSF. On économise nbFreqMax octets EEPROM.update(posEEPROM+1,230); // 1090-860 pour tenir sur un entier. Le 860 sera ajouté dans le programme TSF. On économise nbFreqMax octets }
Une fois la dernière fréquence validée, il faut laisser la procédure aller à son terme car deux bornes supérieures, nécessaires au bon fonctionnement de la recherche des stations, sont écrites.
La procédure prend certes "Un certain temps" mais elle n'est pas à faire très souvent. |
Le bouton de mise à jour est placé de préférence de façon assez discrète. Deux exemples :
Et pour les appareils non équipés d'un écran Oled ?
Un certain nombre de récepteurs ne pouvaient pas être équipés d'un afficheur Oled, parce qu'ils n'avaient pas d'œil magique d'origine et qu'il était impossible physiquement d'en ajouter un. Profitant de la disponibilité d'écrans encore plus petits (0,42 pouce) j'ai réalisé quelques boitiers externes de mise à jour avec un bouton et un petit écran. Le peu d'informations à afficher permet de se satisfaire de cette taille "riquiqui".
Quelques exemples :
Dans un petit boitier rangé dans l'appareil :
Dans un boitier externe que l'on connecte à une prise DIN 5 broches qui n'est plus utilisée sur la radio.