Partage
  • Partager sur Facebook
  • Partager sur Twitter

Communication WIFI entre RPI et Arduino

Domotique

    7 mars 2016 à 11:38:54

    Bonjour.

    Je travaille sur un projet de Terminale STI2D SIN. Notre projet est de faire de la domotique avec Arduino et Raspberry le tout via WiFi.

    Je dispose d'une Raspberry Pi 2 Type B, de 3 cartes Arduino UNO et de 3 modules WiFi ESP8266.

    Le but serait de connecter les cartes Arduino à la RPi via wifi. J'ai reconfiguré le dongle wifi de la RPi afin qu'elle émette et que je puisse connecter mes cartes Arduino dessus.

    Seulement à partir de là, je ne sais pas comment communiquer entre RPi et UNO. J'aimerai envoyer des commandes à exécuter aux UNO. Ou alors envoyer un fichier txt qui contiendrai le code à compiler pour les UNO.

    Après pas mal de recherche sur Internet que ce soit en anglais ou en français, je ne trouve toujours rien qui pourrait m'aider.

    N'hésitez pas à me poser des questions pour clarifier mon problèmes.

    Dans l'espoir d'être aidé.

    Merci.

    • Partager sur Facebook
    • Partager sur Twitter
      7 mars 2016 à 12:32:26

      Salut,

      Je fais exactement ce que tu veux faire, mais avec un câble Ethernet (c'est la même chose en soi), je te mets sur le chemin : sur l'arduino tu dois faire un serveur mais aussi client. Au moins tu peux recevoir des données et en renvoyées, sur le RPi, j'utilise un serveur Node.Js avec Express.js qui simplifie grandement les choses !

      Moi-même j'utilise plusieurs Arduino, ça fonctionne à merveille. Voici un bout de code qui marche avec l'ETHERNET sur arduino donc modifie pour que cela marche avec du Wi-Fi.


      void loop() {
      	handleClient();
      }
      
      // je prend en charge la requête
      void handleClient()
      {
      	// listen for incoming clients
      	EthernetClient client = server.available();
      	if (client) {
      		Serial.println("-----------------------------------------");
      		Serial.println("new client");
      		boolean currentLineIsBlank = true;
      		while (client.connected()) {
      			if (client.available()) {
      				char c = client.read();
      				if(HTTPrequest.length() < 100 && !HTTPrequest.endsWith("HTTP")){
      					HTTPrequest += c;
      				}
      				Serial.write(c);
      				if (c == '\n' && currentLineIsBlank) {
      					HTTPrequest = HTTPrequest.substring(0); // retire le préfixe de l'en-tête
      					HTTPrequest = HTTPrequest.substring(0, HTTPrequest.length()-5); // retire le suffixe de l'en-tête
      					
      					client.println("HTTP/1.1 200 OK");
      					client.println("Content-Type: text/html");
      					client.println("Connection: close");
      					client.println();
      
      					if(HTTPrequest.indexOf("getEtat") >= 0){
      						getEtat(HTTPrequest);
      					}
                else if(HTTPrequest.indexOf("getTemp") >= 0){
                  getTemp(HTTPrequest);
                }
      					else if(HTTPrequest.indexOf(".ico") < 0){
      						interrupteur(HTTPrequest);
      					}
      					
      					break;
      				}
      				if (c == '\n') {
      					currentLineIsBlank = true;
      				} else if (c != '\r') {
      					currentLineIsBlank = false;
      				}
      			}
      		}
      
      		delay(1);
      
      		client.stop();
      		Serial.println("client disconnected");
      		Serial.println("-----------------------------------------");
      		HTTPrequest = "";
      		Ethernet.maintain();
      	}
      }
      
      // ici je parse mes trucs
      void interrupteur(String param)
      {
        Serial.println("Fonction interrupteur");
      	String pin = HTTPrequest.substring(HTTPrequest.indexOf("?")+5, HTTPrequest.indexOf("&"));
      	String type = HTTPrequest.substring(HTTPrequest.indexOf("&")+6, HTTPrequest.indexOf("&nb"));
      	String nb = HTTPrequest.substring(HTTPrequest.indexOf("&nb")+4, HTTPrequest.indexOf("&cmd"));
      	String cmd = HTTPrequest.substring(HTTPrequest.indexOf("&cmd")+5);
      
      // retour -> RPi
      sendRetour(nb.toInt() + jsonPin + "&cmd=" + cmd + "&type=simple&mega="+MEGA);
      
      }
      
      void sendRetour(String json)
      {
      	client.stop();
      
      	// Connexion
      	if (client.connect(rpi, 80)) {
      
      		Serial.println("connected");
      		// Requête HTTP
      		client.println("GET /retour?nb=" + json + " HTTP/1.1");
      		client.println("Host: 192.168.1.5");
      		client.println("Connection: close");
      		client.println();
      	} else {
      		Serial.println("connection failed");
      	}
      
      	delay(500);
      }

      Sorry pour l'indentation mais l'éditeur OCR ne prend pas en charge [TAB]

      • Partager sur Facebook
      • Partager sur Twitter
        Staff 7 mars 2016 à 13:44:15

        Ce que te propose Wayz est basé sur du HTTP ce qui offre :

        • Des avantages : c'est un protocole normalisé donc n'importe quel navigateur pour l'utiliser
        • Des inconvénients : c'est plus complexe à mettre en œuvre.

        Si la RPi doit envoyer des commandes aux UNO, le plus simple serait de faire une application serveur sur le UNO et d'écouter les ordres reçu.

        Coté arduino, ça fait donc un code de ce genre :

        1/ Se connecter au réseau Wifi du RPi
        
        2/ Lancer un serveur 
        
        3/ Accepter tous les nouveaux clients
        
        4/ Lire les données des clients et les interpréter

        Coté RPi, ça fait un code de ce genre :

        1/ Ouvrir un socket sur le serveur de l'arduino
        
        2/ Envoyer la commande
        
        3/ Lire la réponse




        • Partager sur Facebook
        • Partager sur Twitter
          7 mars 2016 à 20:48:35

          Déjà merci pour vos réponses :)

          Le truc c'est que les cartes arduino doivent être "libres", en gros elle doivent avoir comme seule restriction de position, le secteur, mais pas d'ethernet. En fait, pas de câblage si ce n'est pour les alimenter et les relier aux modules. Du coup pour relier UNO et RPi ce serait donc par WiFi, mais comment la RPi envoie des commandes aux UNO, quelles commandes/"applications" RPi il faut utiliser ?

          Et n'y a-t-il pas un moyen pour le faire via Ip, genre comme je l'ai dit, la RPi envoie, par exemple "azerty123" à une UNO qui a pour adresse 192.168.10.xx, la carte arduino reconnait cette chaîne de caractères et exécute un code ?

          Si je mets ma RPi en serveur et les UNO en clients, les cartes arduino peuvent-elles tout de même renvoyer des données au serveur, les mesures d'un capteur par exemple ?

          Je sais ça fait beaucoup de questions mais je préfère les poser histoire, déjà, de donner une meilleure idée de ce que je veux faire, et aussi pour éviter de manquer de détails et d'informations. N'hésitez pas à me proposer d'autres idées, tant que je peux "contrôler" les UNO avec ma RPi en WiFi, c'est l’essentiel. Après pas besoin de passer par Internet si je n'ai pas besoin de pouvoir le faire à l'autre bout du monde ?

          -
          Edité par Istovir 7 mars 2016 à 20:50:38

          • Partager sur Facebook
          • Partager sur Twitter
            Staff 7 mars 2016 à 21:33:05

            Sous Linux, la commande lp sert à imprimer un fichier donc je ne vois pas trop ce qu'elle vient faire ici...


            Sur une application client/serveur, il faut savoir que c'est toujours le client qui initialise la connexion au serveur et jamais l'inverse.

            Une fois que le client s'est connecté au serveur, alors la connexion est bidirectionnelle et asynchrone.

            En clair, le client peut prendre l'initiative d'envoyer des données au serveur et le serveur peut faire de même à tout moment.

            Vu que c'est toujours les clients qui établissent les connexions, il parait normal que ce soit la carte qui exécute les ordres qui soit serveur.

            Ainsi, dès que ton programme veut exécuter un ordre, il lui suffit de se connecter au serveur et d'envoyer l'ordre.

            Le serveur pourra ensuite exécuter cette ordre et éventuellement répondre sur la connexion précédemment établit.


            En mettant la carte arduino serveur, on peut voir la chose de 2 façons :

            • Soit la carte arduino met en plus un serveur HTTP (c'est la solution de Wayz)

            Dans ce cas, tu peut n'importe qu'elle navigateur WEB peut envoyer un ordre en chargeant une page.

            Par exemple, charger la page internet http://ip-arduino/led?val=ON pourrait allumer la LED.

            Et cette page pourrait contenir soit OK, soit ERROR pour informer l'utilisateur que la LED a bien été allumée, ou non.

            A noter que pour charger une page HTTP sur Rpi, tu as la commande wget http://ip-arduino/commande

            Cela offre l'avantage d'être assez généraliste et ça permet à n'importe qu'elle navigateur WEB d'envoyer des ordres (tu pourrais envoyer un ordre depuis le navigateur WEB de ton téléphone par exemple).

            En revanche, le code arduino sera complexe car il faut traiter toutes les données que génère le protocole HTTP.


            • Soit la carte arduino met en plus un serveur beaucoup plus classique (ma solution)

            Ce serveur s'occuperait d'accepter les connexion, de lire les caractères reçus jusqu'à trouver un \n puis interpréter la commande.

            Le code de l'arduino sera donc beaucoup plus simple mais ce ne sera pas compatible avec les navigateurs WEB.

            Pour envoyer ta commande sur arduino, tu peux utiliser la commande echo commande > /dev/tcp/ip-arduino/port-arduino

            Mais tu peux aussi utiliser des sockets pour te connecter au serveur pour envoyer/recevoir des données.

            -
            Edité par lorrio 7 mars 2016 à 21:33:38

            • Partager sur Facebook
            • Partager sur Twitter
              7 mars 2016 à 22:18:41

              Ok, merci pour cette réponse qui me permet de m'orienter sur pleins de guides, notamment celui-ci : 

              http://eskimon.fr/2597-arduino-803-arduino-et-ethernet-serveur

              Qui m'a l'air très bien fait et qui conviendrai parfaitement à la solution n°2.

              Je vous recontacte si je croise un souci, si je ne trouve pas de réponse toute faite ailleurs bien évidemment.

              Honnêtement, merci infiniment parce que je butais sur ce problème et ça fait plaisir d'avoir une direction à prendre pour continuer mon projet.

              Merci :)

              • Partager sur Facebook
              • Partager sur Twitter
                14 mars 2016 à 9:47:22

                lorrio a écrit:

                Ce serveur s'occuperait d'accepter les connexion, de lire les caractères reçus jusqu'à trouver un \n puis interpréter la commande.

                -
                Edité par lorrio le 7 mars 2016 à 21:33:38


                Finalement le guide que j'ai trouvé ne m'aide pas vraiment. Tu aurais pas un code, un morceau de code (ou un guide) pour effectuer ce que tu dis stp ?

                • Partager sur Facebook
                • Partager sur Twitter
                  Staff 14 mars 2016 à 10:29:05

                  Le tutoriel que tu montres consiste à réaliser un serveur WEB donc c'est la solution 1 et non la solution 2.

                  Je ne penses pas qu'il existe de guide pour cette solution mais tu peux t'inspirer du tutoriel que tu as trouvé pour la mettre en place.

                  Tu auras besoin de :

                  • La classe Ethernet pour initialiser le shield
                  • La classe EthernetServer pour mettre en place le serveur
                  • La classe EthernetClient pour gérer les connexions des clients

                  Une fois que le shield est initialisé, à toi d'appeler les fonctions pour faire ton application :

                  • EthernetServer::begin() : te permet de démarrer le serveur
                  • EthernetServer::available() : te renvoie le client qui s'est connecté
                  • EthernetClient::available() : te permet de savoir si le client a envoyé un caractère
                  • EthernetClient::read() : te permet de lire le caractère
                  • EthernetClient::connected() : te permet de savoir si le client est toujours connecté


                  -
                  Edité par lorrio 14 mars 2016 à 10:30:03

                  • Partager sur Facebook
                  • Partager sur Twitter
                    13 juin 2019 à 14:08:02

                    Bonjour, j'ai un problème avec mon mémoire surtout avec le matériel. Mon projet porte sur l'éclairage public intelligent via un réseau 6LoWPAN. je dois mettre en place un réseau 6lowpan et pour cela j'ai pensé à utiliser des cartes arduino nano pour les nœuds du réseau et à RPI 3 comme passerelle. Mon problème est comment faire communiquer mes Arduino nano au RPI 3. Il est aussi prévu de faire une maquette pour le test. J'espère avoir des réponses qui pourront m'aider pour avancer. Merci.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      Staff 17 juin 2019 à 8:10:40

                      Tu ferais mieux d'ouvrir un nouveau sujet plutôt que de te greffer à un vieux sujet qui date de pratiquement 3 ans et dont le titre n'est pas adapté (Wifi et 6LoWPAN, ce n'est pas tout à fait la même chose).
                      • Partager sur Facebook
                      • Partager sur Twitter

                      Communication WIFI entre RPI et Arduino

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      • Editeur
                      • Markdown