Dual Icom CI-V to UDP/IP

1 – l’Idée

Depuis bien longtemps, les transceivers ICOM disposent d’une interface CI-V (Communication interface V) qui permet de piloter certaines fonctions de ces appareils sur une liaison série. Je me souvient que je m’étais déjà bien amusé avec ça et mon IC275e. J’avais développé une belle application graphique qui représentait l’exactitude de la face avant du poste et je pouvais sélectionner la fréquence et les différents modes directement depuis l’écran de l’ordinateur. Le PC était un Goupil G5 286 qui tournait sous Windows 3.1 et le soft était développé en Visual Basic 3 …

30 ans plus tard, je dispose toujours de beau appareils Icom mais beaucoup plus moderne.  Alors pourquoi ne pas jouer encore 😊 ? L’idée, c’est de connecter mes 2 transceivers à un petit serveur local tout en gardant leur connexion USB libre pour les modes numérique. Pour ça, il y avait 2 solutions :

1 –  Tirer du fil depuis le shack jusqu’au serveur qui est dans la baie de brassage pour monter 2 liaisons série (et donc occuper 2 ports rs232 sur le serveur …).

2 – Bricolouiller un truc sans fil en Wifi.

J’ai évidemment choisi la seconde solution et bricolé un petit adaptateur wifi bidirectionnel qui me converti les ports CI-V des 2 transceivers en une liaison Wifi. On va appeler ce truc le ‘Dual Icom CI-V <-> UDP/IP. La suite de l’idée, c’est d’accéder aux 2 postes depuis n’importe quel client local ou distant (pc, smartphone, tablette …) sans rien installer dessus et faire en sorte que les fréquences et modes de mes 2 Icom soit afficher sur ce site en temps reel.

2 – Le hardware

Pour bricoler du Wifi, pas besoin de tout réinventer. En fouillant dans mon bazar, j’ai remis la main sur un ESP32 qui fera parfaitement l’affaire. La seule chose à faire est de convertir ses lignes de données 3v vers du 5v et pour ca, pas besoin de se casser le trognon non plus, on trouve facilement des ‘level converter’ tout fait sur les sites de vente en ligne. Il restait juste à mettre une diode sur chaque ligne série pour s’adapter au mode HalfDuplex du CI-V. Comme l’ESP32 dispose de nombreuse IO, j’en ai profité pour ajouter quelques leds de contrôle (cnx wifi, les activités ci-v 1,ci-v 2 et udp).

Pas de mystère, rien ne remplace la vielle planche à pain et quelques bouts de fils. Un Esp32 VROOM, un level converter (je n’avais que du 8 lignes, mais 4 auraient suffit), une paire de diodes (ici des 1N4148 qui seront par la suite remplacé par des BAS16) et 4 leds rectangulaire avec leur résistance (choisir de préférence des leds 10ma maxi pour ne pas trop tirer sur les sorties de l’ESP32). L’alimentation est assurée par l’USB du module ESP32 et 2 cordons avec une fiche jack 3.5 stéréo au bout pour relier les transceivers. les premiers essais on été fait avec l’IC-7300 et comme je n’avais pas encore l’IC-9700, j’avais utilisé un vieil IC-820h. La bonne nouvelle, c’est que cela fonctionne tout aussi bien avec les appareils moderne qu’avec les anciens.

J’aurais pu souder ca vite fait sur une ‘plakatrou atrou’, mais nous avons la chance aujourd’hui de pouvoir faire graver des circuits imprimés de qualité pro pour vraiment pas cher donc autant faire propre. J’ai trouver une petite boite plastique qui devrait convenir et j’ai tracer un petit pcb qui viendra y prendre place. J’aurais pu ajouter une régulation 5v et piquer le 13.8v sur un des postes, mais j’ais fait le choix de garder l’alimentation par la prise USB de l’ESP avec un petit chargeur de téléphone.

L’assemblage du premier prototype est terminé. J’ai fais le choix d’une prise jack 3.5 Stéréo pour raccorder les 2 Icom et je me suis fabriquer un petit cordon.

Voila, le bazar est fabriqué et il ni a plus qu’a gribouiller quelques lignes de code pour le rendre opérationnel.

3 – Le Software

L’avantage des mini-cartes à microcontrôleurs et des petits modules tout prêt, c’est que l’on simplifie énormément la partie électronique et finalement, c’est le programme qui fait tout le boulot. La aussi, des outils de développement très simple à utiliser nous offre des possibilités qui n’ont comme limite que notre imagination.  Concernant l’ESP32, on peut utiliser une multitude de langage de programmation et tout autant de méthodes pour injecter le programme dans la ‘puce’.

Pour programmer mon ESP32, j’ai utilisé Arduino IDE. En synthèse, Il y a dans ce bout de code un écouteur UDP et 2 écouteurs série. Quand des données sont présentées sur un des port série, elles sont poussées sur la liaison UDP et quand des données arrivent sur l’UDP elles sont envoyées vers un des port série. La sélection du bon port série est faite automatiquement en décodant l’adresse du transceiver qui a émis. Ajoutons à cela la connexion wifi avec reconnexion automatique et quelques lignes pour les leds et c’est tout. Avec des petits carrés, ça donne un truc comme ca :

Tout ça est fait dans une première version de test qui demande encore à être améliorée, mais pour les premiers essais, cela fera l’affaire. Pour la connexion wifi, j’ai fait le choix pour l’instant de la laisser en DHCP plutôt que de lui imposer une adresse fixe. Toute les 10 secondes, l’esp balance un broadcast UDP sur le réseau local pour informer de son adresse IP. Tous les hosts à l’écoute s’adaptent ainsi automatiquement pour transmettre vers cette IP. De cette façon, on se fout de savoir quelles sont les IP des tout ces trucs, l’important c’est qu’il soit sur le même réseaux.

Le code injecté dans le bazar :

#include <Arduino.h>
#include <WiFi.h>
#include <esp_wifi.h>
#include <WiFi.h>
#include <AsyncUDP.h>

#define debug Serial
#define UDP_LEDTX 22
#define WIFI_LED 23
#define BUFFERSIZE 256

/*************************  COM Port 0 *******************************/
#define UART_BAUD1 19200         
#define SERIAL_PARAM1 SERIAL_8N1  
#define SERIAL1_TXPIN 17      
#define SERIAL1_RXPIN 16
#define SERIAL1_LEDTX 5

/*************************  COM Port 1 *******************************/
#define UART_BAUD2 9600          
#define SERIAL_PARAM2 SERIAL_8N1   
#define SERIAL2_TXPIN 4    
#define SERIAL2_RXPIN 15 
#define SERIAL2_LEDTX 0

/*********************** Custom Config ***********/
#define SSID "theboxssid"  // SSID de la box
#define PASSWD "thepassword" // password wifi
#define UDP_PORT 27000 // N° de Port UDP 
#define ICOM1_ADDRESS 0x94 //Adresse CI-V Tx1 
#define ICOM2_ADDRESS 0x42 //Adresse CI-V Tx2 
/**************************************************/

AsyncUDP udp;

HardwareSerial Serial_one(1);
HardwareSerial Serial_two(2);
HardwareSerial* COM[2] = { &Serial_one, &Serial_two};

uint8_t buffer[2][128];
uint16_t ix[2] = {0, 0};
uint8_t serial_led_tx [2] =  {SERIAL1_LEDTX,SERIAL2_LEDTX};
uint8_t icom_adress [2] =  {ICOM1_ADDRESS, ICOM2_ADDRESS};
unsigned long startMillis;
unsigned long currentMillis;
const unsigned long sendip = 10000;

void connect(){  
    uint8_t count = 0;
    
    debug.print("Connecting to ");
    debug.print(SSID);
    debug.print("...\n");
    
    WiFi.begin(SSID, PASSWD);
    while (WiFi.status() != WL_CONNECTED) { 
        digitalWrite(WIFI_LED,!digitalRead(WIFI_LED));      
        delay(500);
        debug.print("*"); 
        count ++; 
        if (count == 40 && WiFi.status() != WL_CONNECTED){
          debug.print("\nTimeout Wifi Connect : System restart !\n");
          ESP.restart();
        }
    }

    digitalWrite(WIFI_LED,HIGH);
    debug.print("\nWifi connected."); 
    debug.print("\nIP Address : ");
    debug.print(WiFi.localIP());
    debug.print("\n");

    bool listening = false;
    if (udp.listen(UDP_PORT)){ 
      listening = true;  
      debug.printf("Listening on port %d\n", UDP_PORT);
    }

    if (listening) {
      udp.onPacket([](AsyncUDPPacket packet) {
          digitalWrite(UDP_LEDTX,HIGH);
          debug.print("\nUDP Receive");         
            for (uint16_t i = 0; i < 2; i++){                 
              if (packet.data()[2] == icom_adress[i]){                              
                COM[i]->write(packet.data(), packet.length());
                break;
              }                     
          }
        delay(10);
        digitalWrite(UDP_LEDTX,LOW);               
      });
    }

}

void WiFi_Disconnected(WiFiEvent_t event, WiFiEventInfo_t info) {
    debug.print("\nWiFi disconnected !\n");
    connect();
}
    
void setup() { 
    delay(500);
    
    pinMode (serial_led_tx[0],OUTPUT);  
    pinMode (serial_led_tx[1],OUTPUT);  
    pinMode (UDP_LEDTX,OUTPUT);   
    pinMode (WIFI_LED,OUTPUT); 
    digitalWrite(serial_led_tx[0],LOW);
    digitalWrite(serial_led_tx[1],LOW);  
    digitalWrite(UDP_LEDTX,LOW);
    digitalWrite(WIFI_LED,LOW);  

    Serial.begin(9600);
    COM[0]->begin(UART_BAUD1, SERIAL_PARAM1, SERIAL1_RXPIN, SERIAL1_TXPIN);
    COM[1]->begin(UART_BAUD2, SERIAL_PARAM2, SERIAL2_RXPIN, SERIAL2_TXPIN);

    debug.print("\n\nDual Port Icom CI-V <-> UDP");
    debug.println("F1RTD - 2024");
  
    WiFi.mode(WIFI_STA);
    WiFi.onEvent(WiFi_Disconnected, ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
    connect();

    //for v2, read pin for set low wifi
    esp_err_t esp_wifi_set_max_tx_power(50);  
}

void loop() {
  currentMillis = millis();
  for (int i = 0; i < 2; i++) {       
  if (COM[i] != NULL) {           
    if (COM[i]->available()) {
      digitalWrite(serial_led_tx[i],HIGH);               
      while (COM[i]->available()) {
        buffer[i][ix[i]] = COM[i]->read();
        ix[i]++;
        if (buffer[i][ix[i]-1] == 253){
          udp.broadcastTo(buffer[i], ix[i], UDP_PORT);
          ix[i] = 0;
          break;
        }
      }
      digitalWrite(serial_led_tx[i],LOW);
    }  
    else { 
      //TODO, peu faire mieu ...         
      if (currentMillis - startMillis >= sendip) {           
        udp.broadcastTo(".",UDP_PORT);          
        startMillis = currentMillis;
        }             
      }        
    }
  }
} 

Voila, à ce stade, le machin est fabriqué et programmé. Il à même déjà trouvé une petite place provisoire et est prêt à dialoguer.

La led verte clignote jusqu’à ce que la connexion wifi soit établie puis devient fixe et la led rouge qui correspond à chaque appareil bagote bien quand je tourne les vfo (c’est joli et c’est déjà ca de pris 🙂 ).

Les composants utilisés :

J’ai fait avec ce que j’avais dans mes tiroirs et voila ce que cela donne : 1 module ESP32 VROOM (38 pins), 1 Level Converter 8 voies (10 pins), 2 diodes BAS16, 4 résistance 1206 330 ohms, 4 leds rectangulaires (1 verte pour le wifi, 1 jaune pour l’activité UDP, et 2 rouges pour l’activité série des 2 postes), un petit bornier à vis au pas de 2.54, une prise jack stéréo 3.5 et une petite boite en plastok.

Un prochain article sera dédié aux différents cas d’usages.

image_print
Ce contenu a été publié dans Bricolouillage, avec comme mot(s)-clé(s) . Vous pouvez le mettre en favoris avec ce permalien.