@J-M-L
avec ce code :
const byte brochePioche = 2;
const byte brocheBuzzer = 3;
struct Morse {
uint16_t caractere : 7; // Code ASCII (7 bits)
uint16_t longueur : 3; // Longueur du code Morse (3 bits)
uint16_t code : 6; // Code Morse (6 bits) - le point est représenté par un 1 - le trait par un 0
};
const Morse codeMorse[] PROGMEM = { // soit 38 éléments - pour chaque caractère j'ai mis la représentation graphique
{ 'A', 2, 0b10 }, // .- (2) // ainsi que la valeur décimale de la valeur binaire
{ 'B', 4, 0b0111 }, // -... (7)
{ 'C', 4, 0b0101 }, // -.-. (5)
{ 'D', 3, 0b011 }, // -.. (3)
{ 'E', 1, 0b1 }, // . (1)
{ 'F', 4, 0b1101 }, // ..-. (13)
{ 'G', 3, 0b001 }, // --. (1)
{ 'H', 4, 0b1111 }, // .... (15)
{ 'I', 2, 0b11 }, // .. (3)
{ 'J', 4, 0b1000 }, // .--- (8)
{ 'K', 3, 0b010 }, // -.- (2)
{ 'L', 4, 0b1011 }, // .-.. (11)
{ 'M', 2, 0b00 }, // -- (0)
{ 'N', 2, 0b01 }, // -. (1)
{ 'O', 3, 0b000 }, // --- (0)
{ 'P', 4, 0b1001 }, // .--. (9)
{ 'Q', 4, 0b0010 }, // --.- (2)
{ 'R', 3, 0b101 }, // .-. (5)
{ 'S', 3, 0b111 }, // ... (7)
{ 'T', 1, 0b0 }, // - (0)
{ 'U', 3, 0b110 }, // ..- (6)
{ 'V', 4, 0b1110 }, // ...- (14)
{ 'W', 3, 0b100 }, // .-- (4)
{ 'X', 4, 0b0110 }, // -..- (6)
{ 'Y', 4, 0b0100 }, // -.-- (4)
{ 'Z', 4, 0b0011 }, // --.. (3)
{ '0', 5, 0b00000 }, // ----- (0)
{ '1', 5, 0b10000 }, // .---- (16)
{ '2', 5, 0b11000 }, // ..--- (24)
{ '3', 5, 0b11100 }, // ...-- (28)
{ '4', 5, 0b11110 }, // ....- (30)
{ '5', 5, 0b11111 }, // ..... (31)
{ '6', 5, 0b01111 }, // -.... (15)
{ '7', 5, 0b00111 }, // --... (71)
{ '8', 5, 0b00011 }, // ---.. (3)
{ '9', 5, 0b00001 }, // ----. (1)
{ ',', 6, 0b110111}, // ..-... (55)
{ '.', 6, 0b010101}, // -.-.-. (21)
};
const byte nbCodes = sizeof codeMorse / sizeof * codeMorse;
const unsigned long dureeDeBase = 150; // Durée habituelle d'un point en millisecondes
unsigned long dureePoint = dureeDeBase; // Durée d'un point en millisecondes
unsigned long dureeTrait = dureePoint * 3; // Durée d'un trait
unsigned long dureeIntraLettre = dureePoint; // Durée entre les symboles d'une même lettre
unsigned long dureeInterLettre = dureePoint * 3; // Durée entre les lettres
unsigned long dureeInterMot = dureePoint * 7; // Durée entre les mots
enum EtatBouton : uint8_t {DEBUT, PIOCHE_DOWN, PIOCHE_UP, ERREUR_DOWN, LONG_UP};
enum TypeDuree : uint8_t {POINT, TRAIT, INTERVALLE, TOTAL};
const byte nbEchantillonsMax = 50; // Taille maximale des échantillons
const byte nbTypeEchantillonsMax = 50;
//unsigned long echantillons[TOTAL][nbEchantillonsMax]; // Tableau des durées
char aOouR[nbEchantillonsMax];
unsigned long echantillons[nbEchantillonsMax];
byte indexEchantillons = 0;
EtatBouton etatCourant = DEBUT;
void ajusterTiming(const unsigned long d) {
dureePoint = d;
dureeTrait = dureePoint * 3;
dureeIntraLettre = dureePoint;
dureeInterLettre = dureePoint * 3;
dureeInterMot = dureePoint * 7;
}
// Fonction pour ajuster dynamiquement la durée des symboles Morse
// on capture les temps considérés comme points, traits et Intervalles
void ajusterDureeAdaptative(unsigned long deltaT, TypeDuree td) {
if (td == POINT || td == TRAIT) aOouR[indexEchantillons] = 'a';
else if (td == INTERVALLE) aOouR[indexEchantillons] = 'r';
echantillons[indexEchantillons] = deltaT;
indexEchantillons++;
// Vérifier si le tableau est plein
if (indexEchantillons >= nbEchantillonsMax) {
// si le tableau est plein, on affine les timing
Serial.print('\n');
for (indexEchantillons = 0 ; indexEchantillons < nbEchantillonsMax ; indexEchantillons++) {
Serial.print(aOouR[indexEchantillons]) ; Serial.print("(");
Serial.print(echantillons[indexEchantillons]) ; Serial.println(")");
}
indexEchantillons = 0; // Réinitialiser l'index
// Ajuster les durées en fonction d'un algo spécifique
// *********************************
// ************ A FAIRE ************
// *********************************
}
}
inline uint32_t seuilPoint() {
return dureePoint * 1.2;
}
inline uint32_t seuilTrait() {
return dureeTrait * 1.2;
}
bool trouverCaractere(Morse& recherche) {
Morse unCode;
for (uint8_t i = 0; i < nbCodes; i++) {
memcpy_P(&unCode, &codeMorse[i], sizeof unCode);
if (unCode.longueur == recherche.longueur && unCode.code == recherche.code) {
recherche.caractere = unCode.caractere;
return true;
}
}
return false;
}
void ecouter() {
static unsigned long debut = 0;
static Morse morseRecu = { '\0', 0, 0 };
int etatPioche = digitalRead(brochePioche);
unsigned long maintenant = millis();
switch (etatCourant) {
case DEBUT:
if (etatPioche == LOW) { // début appui
debut = maintenant; // prise en compte du temps d'appui
tone(brocheBuzzer, 1000); //son buzzer
etatCourant = PIOCHE_DOWN; // on change d'état
}
break;
case PIOCHE_DOWN:
if (etatPioche == HIGH) { // on vient de relâcher
noTone(brocheBuzzer); // plus de son
unsigned long deltaT = maintenant - debut; // deltaT = durée entre un appui et un relaché
debut = maintenant; //debut prend la valeur de millis()
morseRecu.longueur++; // longueur + 1
etatCourant = PIOCHE_UP; // si on vient de relacher (etatPioche == HIGH) et on passe à PIOCHE_UP dans la prochaine loop()
// on rajoute le symbole au code courant ou erreur
if (deltaT <= seuilPoint()) {
Serial.write('.');
morseRecu.code = (morseRecu.code << 1) | 0b1; // Ajouter un point
ajusterDureeAdaptative(deltaT, POINT); // Ajustement de la durée pour un point
} else if (deltaT <= seuilTrait()) {
Serial.write('-');
morseRecu.code = (morseRecu.code << 1); // Ajouter un trait
ajusterDureeAdaptative(deltaT, TRAIT); // Ajustement de la durée pour un trait
} else {
Serial.println('?'); // Erreur si le temps est trop long
morseRecu = { '\0', 0, 0 }; // Réinitialiser après le caractère trouvé
ajusterTiming(dureeDeBase); // Réinitialisation en cas d'erreur
etatCourant = ERREUR_DOWN;
}
}
else if (maintenant - debut >= dureeInterLettre) {
Serial.println('?'); // Erreur si le temps est trop long
morseRecu = { '\0', 0, 0 }; // Réinitialiser après le caractère trouvé
ajusterTiming(dureeDeBase); // Réinitialisation en cas d'erreur
etatCourant = ERREUR_DOWN;
}
break;
case PIOCHE_UP:
if (etatPioche == LOW) { // début appui
tone(brocheBuzzer, 1000);
unsigned long deltaT = maintenant - debut;
debut = maintenant;
ajusterDureeAdaptative(deltaT, INTERVALLE); // Ajustement de la durée pour un intervalle
etatCourant = PIOCHE_DOWN;
} else {
unsigned long deltaT = maintenant - debut;
if (deltaT >= dureeInterLettre) {
if (trouverCaractere(morseRecu)) {
Serial.print("➜ ");
Serial.println((char)morseRecu.caractere); // Affichage du caractère décodé
} else {
Serial.print("➜ inconnu : ");
byte nbBits = morseRecu.longueur;
for (int8_t i = nbBits - 1; i >= 0; i--) {
Serial.write(bitRead(morseRecu.code, i) ? '1' : '0'); // Afficher chaque bit
}
Serial.println();
}
morseRecu = { '\0', 0, 0 }; // Réinitialiser après le caractère trouvé
etatCourant = LONG_UP;
}
}
break;
case ERREUR_DOWN:
if (etatPioche == HIGH) { // on vient de relâcher
noTone(brocheBuzzer);
etatCourant = DEBUT;
}
break;
case LONG_UP:
if (etatPioche == LOW) { // début appui
tone(brocheBuzzer, 1000);
unsigned long deltaT = maintenant - debut;
debut = maintenant;
ajusterDureeAdaptative(deltaT, INTERVALLE); // Ajustement de la durée pour un intervalle
etatCourant = PIOCHE_DOWN;
} else {
unsigned long deltaT = maintenant - debut;
if (deltaT >= dureeInterMot) {
Serial.println("➜ ESPACE");
etatCourant = DEBUT;
}
}
break;
}
}
void setup() {
pinMode(brochePioche, INPUT_PULLUP);
pinMode(brocheBuzzer, OUTPUT);
Serial.begin(115200);
}
void loop() {
ecouter();
}
on obtient ça :
.-➜ A
➜ ESPACE
-...➜ B
➜ ESPACE
-.-.➜ C
➜ ESPACE
-..➜ D
➜ ESPACE
.➜ E
➜ ESPACE
..-.➜ F
➜ ESPACE
--.➜ G
➜ ESPACE
....➜ H
➜ ESPACE
..➜ I
➜ ESPACE
.--
a(72)
r(157)
a(237)
a(258)
r(141)
a(48)
r(121)
a(49)
r(102)
a(48)
a(218)
r(148)
a(54)
r(154)
a(230)
r(189)
a(45)
a(231)
r(131)
a(43)
r(115)
a(57)
a(108)
a(74)
r(119)
a(70)
r(76)
a(300)
r(267)
a(20)
a(258)
r(98)
a(225)
r(138)
a(63)
a(102)
r(133)
a(50)
r(137)
a(78)
r(131)
a(46)
a(71)
r(128)
a(77)
a(36)
r(156)
a(206)
r(133)
a(247)
-➜ J
➜ ESPACE
Maintenant pour le traitement on pourrait utiliser une structure ?