From c6c641310f6de21b7e467eecc7e204fa0936f12b Mon Sep 17 00:00:00 2001 From: Thomas O Fredericks Date: Tue, 24 Oct 2023 15:36:12 -0400 Subject: [PATCH] Documentation pour MicroOsc UDP --- rel-electro-immersif-src/SUMMARY.md | 3 +- .../microosc/_osc_common.md | 93 +++++++++++++++++++ rel-electro-immersif-src/microosc/osc_slip.md | 51 ++-------- rel-electro-immersif-src/microosc/osc_udp.md | 92 ++++++++++++++++++ 4 files changed, 194 insertions(+), 45 deletions(-) create mode 100644 rel-electro-immersif-src/microosc/_osc_common.md create mode 100644 rel-electro-immersif-src/microosc/osc_udp.md diff --git a/rel-electro-immersif-src/SUMMARY.md b/rel-electro-immersif-src/SUMMARY.md index 72272a5..b690c23 100644 --- a/rel-electro-immersif-src/SUMMARY.md +++ b/rel-electro-immersif-src/SUMMARY.md @@ -55,7 +55,7 @@ # OSC - [OSC : Open Sound Control ](./osc/osc.md) -- [MicroOsc](./microosc/microosc.md) +- [OSC : MicroOsc](./microosc/microosc.md) # OSC SLIP - [OSC SLIP : MicroOsc](./microosc/osc_slip.md) @@ -68,6 +68,7 @@ - [Relais SLIP⇄UDP avec Max](./max/relais_osc_slip_udp.md) # OSC UDP +- [OSC UDP : MicroOsc](./microosc/osc_udp.md) - [OSC UDP : Pure Data](./pd/pd_osc_udp.md) - [OSC UDP : Cycling '74 Max](./max/max_osc_udp.md) - [OSC UDP : VCV Rack](./vcv_rack/vcv_rack_osc.md) diff --git a/rel-electro-immersif-src/microosc/_osc_common.md b/rel-electro-immersif-src/microosc/_osc_common.md new file mode 100644 index 0000000..c9c2096 --- /dev/null +++ b/rel-electro-immersif-src/microosc/_osc_common.md @@ -0,0 +1,93 @@ +Créez une variable pour mesurer le temps pour contrôler la vitesse à laquelle nous envoyons les messages: +```arduino +unsigned long myChronoStart = 0; // VARIABLE USED TO LIMIT THE SPEED OF THE SENDING OF OSC MESSAGES +``` + + +### Fonction personnalisée à ajouter avant *loop()* + +Il est nécessaire de définir une fonction qui va être appelée lorsqu'un nouveau message OSC va être reçu : + +```arduino +// FUNCTION THAT WILL BE CALLED WHEN AN OSC MESSAGE IS RECEIVED: +void myOscMessageParser( MicroOscMessage& receivedOscMessage) { + // ADD MESSAGE PARSING CODE HERE +} +``` + + +À **l'intérieur de la fonction que vous venez de créer** l'adresse du message peut être validée avec *checkOscAddress()* ainsi : +```arduino +if ( receivedOscMessage.checkOscAddress("/address") ) { + // MESSAGE ADDRESS IS "/address" +} +``` + +Lorsque l'adresse du message a été validée, il est possible de récuprer les données. Par exemple, pour récupérer un entier: +```arduino +int32_t intArgument = receivedOscMessage.nextAsInt(); +``` + +Voici comment récupérer les autres types de données : +```arduino +// PARSE AN INT +int32_t intArgument = receivedOscMessage.nextAsInt(); +// PARSE A FLOAT +float floatArgument = receivedOscMessage.nextAsFloat(); +// PARSE A STRING +const char * s = receivedOscMessage.nextAsString(); +// PARSE A BLOB +const uint8_t* blob; +uint32_t length = receivedOscMessage.nextAsBlob(&blob); +// PARSE MIDI +const uint8_t* midi; +receivedOscMessage.nextAsMidi(&midi); + +``` + +### Code à intégrer dans *loop()* + +#### Déclencher la réception des messages + +Dans *loop()* nous devons déclencher la réception des messages OSC avec la méthode *onOscMessageReceived()* à laquelle nous passons le nom de la fonctione personnalisée créée précédemment: +```arduino +myMicroOsc.onOscMessageReceived( myOscMessageParser ); +``` +#### Envoyer des messages + +Avant d'envoyer des messages, il faut limiter la vitesse d'envoi selon un intervalle de temps : +```arduino +// EVERY 50 MILLISECONDS : +if (millis() - myChronoStart >= 50) { + myChronoStart = millis(); // RESTART CHRONO + + // SEND OSC MESSAGES HERE +} +``` + +À **l'intérieur de la fonction que vous venez de créer** vous pouvez envoyer des messages. Par exemple un entier ainsi : +```arduino +int myIntToSend = 100; +myMicroOsc.sendInt("/address", myIntToSend); +``` + +Voici les autres méthodes pour envoyer les autres types de données : +```arduino +// SEND AN INT(32) +myMicroOsc.sendInt(const char *address, int32_t i); +// SEND A FLOAT +myMicroOsc.sendFloat(const char *address, float f); +// SEND A STRING +myMicroOsc.endString(const char *address, const char *str); +// SEND A BLOB +myMicroOsc.sendBlob(const char *address, unsigned char *b, int32_t length); +// SEND DOUBLE +myMicroOsc.sendDouble(const char *address,double d); +// SEND MIDI +myMicroOsc.sendMidi(const char *address,unsigned char *midi); +// SEND INT64 +myMicroOsc.sendInt64(const char *address, uint64_t h); +// SEND A MIXED TYPE VARIABLE LENGTH MESSAGE +myMicroOsc.sendMessage(const char *address, const char *format, ...); + +``` \ No newline at end of file diff --git a/rel-electro-immersif-src/microosc/osc_slip.md b/rel-electro-immersif-src/microosc/osc_slip.md index d8c357a..699c8c7 100644 --- a/rel-electro-immersif-src/microosc/osc_slip.md +++ b/rel-electro-immersif-src/microosc/osc_slip.md @@ -18,6 +18,12 @@ Idéallement, nous utiliserions l'OSC UDP qui voyage par Ethernet. Cependant, pa ![Schéma de connectique OSC SLIP et du relais OSC SLIP ⇄ UDP](./osc_slip_connectique.svg) +## Connexion sérielle + +### Code à ajouter à *setup()* + +Il est nécessaire d'initialiser la communication sérielle si elle ne l'a pas été faite avec `Serial.begin(115200);`. + ## MicroOsc SLIP ### Code à ajouter à l'espace global @@ -30,50 +36,7 @@ Il faut ajouter la bibliothèque *MicroOscSlip* qui fait partie de *MicroOsc* et MicroOscSlip<64> myMicroOsc(&Serial); ``` -### Code à ajouter à *setup()* - -Il n'y a rien de spécial à ajouter à *setup()* sauf un rappel qu'il est nécessaire d'avoir unitialisé la communication sérielle si elle ne l'a pas été faite avec `Serial.begin(115200);`. - - -## Fonction personnalisée à ajouter avant *loop()* - -Il est nécessaire de définir une fonction qui va être appelée lorsqu'un nouveau message OSC va être reçu : - -```arduino -// FUNCTION THAT WILL BE CALLED WHEN AN OSC MESSAGE IS RECEIVED: -void myOscMessageParser( MicroOscMessage& receivedOscMessage) { - // ADD MESSAGE PARSING CODE HERE -} -``` - -Dans cette fonction l'adresse du message peut être validée avec *checkOscAddress()* ainsi : -```arduino -if ( receivedOscMessage.checkOscAddress("/address") ) { - // MESSAGE ADDRESS IS "/address" -} -``` - -Lorsque l'adresse du message a été validée, il est possible de récuprer les données.Par exemple, pour récupérer un entier: -```arduino -int32_t intArgument = receivedOscMessage.nextAsInt(); -``` - - - -### Code à intégrer dans *loop()* - - -Dans *loop()* nous devons déclencher la réception des messages OSC avec la méthode *onOscMessageReceived()* à laquelle nous passons le nom de la fonctione personnalisée créée précédemment: - -```arduino -myMicroOsc.onOscMessageReceived( myOscMessageParser ); -``` - -Nous pouvons aussi envoyer des messages, par exemple un entier ainsi : -```arduino -int myIntToSend = 100; -myMicroOsc.sendInt("/address", myIntToSend); -``` +{{#include ./_osc_common.md}} ## Exemple MicroOsc SLIP pour M5Stack Atom Lite diff --git a/rel-electro-immersif-src/microosc/osc_udp.md b/rel-electro-immersif-src/microosc/osc_udp.md new file mode 100644 index 0000000..1616605 --- /dev/null +++ b/rel-electro-immersif-src/microosc/osc_udp.md @@ -0,0 +1,92 @@ +# OSC UDP : MicroOsc + +## Problématique + +![Illustration de la problématique : comment relier l'Arduino à l'espace immersif?](./scenario_problematique.svg) + +Nous voulons une méthode robuste, fiable et universelle pour l'intégration de l'Arduino à l'espace immersif dans un contexte de création multimédia. C'est-à-dire l’intégration de capteurs et actionneurs dans un grand espace où l'ordinateur multimédia, qui doit coordonner les aspects audiovisuels (les projections visuelles, les éclairages, les effets et les diffusions sonores), est distant. + + +## Solution de connectique + +La solution proposée essaie de rester peu onéreuse et accessible tout en demeurant fiable (en éliminant les sources d’erreurs potentielles des communications) et très compatible avec les outils de création multimédia. + +Dans cette optique, nous choisissons d'utiliser le protocole [OSC](../osc/osc.html). La plupart des protocoles (COBS, JSON, FUDI, etc.) permettent une trop grande latitude dans la manière d'organiser les données, et s'appuient donc sur des architectures personnalisées spécifiques à chaque développeur. L'OSC impose une structure particulière de l'information que toutes les applications doivent supporter ce qui rend toute communication plus universelle : tout le monde parle la même langue! + +Dans ce cas-ci, nous allons utiliser la version UDP de l'OSC. Pour établir cette connexion, vous devez : +1. Établir une connexion UDP +2. Intégrer MicroOsc UDP + +## Connexion UDP + +Il est possible d'établir une connexion UDP de deux manières: +* Une connexion UDP par Ethernet, plus fiable et simple. +* Une connexion UDP par WiFi, moins fiable et plus complexe. + +### Connexion UDP Ethernet + +#### Code à ajouter à l'espace global pour une connexion UDP Ethernet + +Modifiez les adreses et les ports pour que cela corresponde à votre configuration réseau : +```arduino +#include +#include +EthernetUDP myUdp; + +IPAddress myDestinationIp(10, 1, 2, 3); +unsigned int myDestinationPort = 7001; + +IPAddress myIp(10, 1, 2, 101); +unsigned int myPort = 7000; +``` + +#### Code à ajouter à *setup()* pour une connexion UDP Ethernet + +Initialisation et configuration de la connexion Etheret UDP : +```arduino +// CONFIGURE ETHERNET HARDWARE : +// THE NUMBERS ARE THE HARDWARE PINS FOR THE ATOM POE. +SPI.begin(22, 23, 33, 19); +Ethernet.init(19); +// GET FACTORY DEFINED ESP32 MAC : +uint8_t myMac[6]; +esp_efuse_mac_get_default(myMac); +// START ETHERNET WITH STATIC IP +Ethernet.begin(myMac, myIp); +myUdp.begin(myReceivePort); +``` + +Déboguer les détails de la connexion dans le moniteur série : + +```arduino +Serial.println(); +Serial.println(__FILE__); +Serial.print("myDestinationIp: "); +Serial.println(myDestinationIp); +Serial.print("myDestinationPort: "); +Serial.println(myDestinationPort); +Serial.print("myIp: "); +Serial.println(Ethernet.localIP()); +Serial.print("myPort: "); +Serial.println(myPort); +``` + +## MicroOsc UDP + +### Code à ajouter à l'espace global pour MicroOsc UDP + +Il faut ajouter la bibliothèque *MicroOscUdp* qui fait partie de *MicroOsc* et initialiser une instance de MicroOscUdp : +```arduino +#include +// The number 1024 between the < > below is the maximum number of bytes reserved for incomming messages. +// Outgoing messages are written directly to the output and do not need more reserved bytes. +MicroOscUdp<1024> myOsc(&myUdp, mySendIp, mySendPort); +``` + +### Code à ajouter à *setup()* pour MicroOsc UDP + +{{#include ./_osc_common.md}} + +## Exemple MicroOsc UDP Ethernet à adresse statique pour M5Stack Atom Lite + +L'exemple [microosc_ethernet_static_m5stack_atom_poe dans le GitHub de MicroOsc](https://github.com/thomasfredericks/MicroOsc/blob/main/examples/microosc_ethernet_static_m5stack_atom_poe/microosc_ethernet_static_m5stack_atom_poe.ino) démontre comment effectuer l'intégration de MicroOsc UDP à une connexion Ethernet avec une adresse statique. \ No newline at end of file