Initialisation d'une connection série

Bonsoir !

J’ai un petit soucis, je n’arrive pas a initialiser une communication PC<->Arduino avec un script Python (en utilisant la lib. pySerial).
Le but est d’envoyer à l’arduino le message ‘START’, lorsqu’il a reçu celui-ci renvoie ‘START_INIT’.

Coté Arduino, en réduisant au nécessaire j’ai ceci :

void setup() {
  Serial.begin(9600);
  String line = "";
  while (line != "START") {
    line = readLine();
  }
  Serial.println("START_INIT");
}

void loop() {

}

String readLine() {
	String message = "";

	while (Serial.available()) {
		delay(3);
		if (Serial.available() > 0) {
			char c = Serial.read();
			message += c;
			if (c == '\n') {
				break;
			}
		}
	}
	delay(50);
	return message;	
}

J’ai le programme en envoyant le ‘START’ à l’aide de l’IDE Arduino et ça fonctionne. Aucun souci de ce coté là à priori.

Au niveau du script Python j’ai ceci :

#!/usr/bin/python
# -*- coding: utf-8 -*-

SERIAL_BAUDS = 9600

import serial
from serial.tools import list_ports

port = list_ports.comports()[-1][0]
print 'Begining serial connexion using port ' + port + '.'
ser = serial.Serial(port, SERIAL_BAUDS)
ser.write('START\n')

while True:
	print '> ' + ser.readline()

ser.close()

Et là rien ne se passe sur la console : je suis toujours en attente du message d’init…
Une idée ?

Bonjour,

A mon avis ta fonction à base de String - en plus d’être dangereuse - est victime d’un problème de timings.

Essaye quelque chose qui ne dépend d’aucun delay(), exemple :

void waitForStart() {
  
  byte state = 0;
  byte running = 1;
  
  /* Boucle infinnie */
  while(running) {
  
    /* Attend un octet */
    while(Serial.available() < 1);
    
    /* Lit l'octet */
    byte c = Serial.read();
  
    /* Super machine à états finis qui attend la chaine S T A R T */
    switch(state) {
      case 0: // Attend S (ou passe à l'état 6)
        if(c == 'S')
          state++;
        else
          state = 6;
        break;
        
      case 1: // Attend T (ou passe à l'état 6)
        if(c == 'T')
          state++;
        else
          state = 6;
        break;
        
      case 2: // Attend A (ou passe à l'état 6)
        if(c == 'A')
          state++;
        else
          state = 6;
        break;
        
      case 3: // Attend R (ou passe à l'état 6)
        if(c == 'R')
          state++;
        else
          state = 6;
        break;
        
      case 4: // Attend T (ou passe à l'état 6)
        if(c == 'T')
          state++;
        else
          state = 6;
        break;
        
      case 5: // Attend \n et quitte la boucle (ou passe à l'état 6)
        if(c == '\n')
          running = 0;
        else
          state = 6;
        break;
        
      case 6: // Attend \n
        if(c == '\n')
          state = 0;
        break;
    }
  }
}

(j’adore les machines à états finis, ça fait intelligent alors que c’est super simple 8))

Merci pour ta réponse !
Ça fonctionne très bien avec ta méthode :slight_smile:

Comme j’essaie en général déviter la redondance de code, je me suis permi d’optimiser un peu le tien (le fonctionnement reste inchangé) :

void waitUntil(char* msg) {
	byte state = 0;
	byte msg_length = 0;
	char c;

	// Calcule la longueur du message
	for (; msg[msg_length] != '\0' ; msg_length++);

	/* Boucle infinie */
	while(state != msg_length) {
		while(Serial.available() < 1); // Attend un octet
		c = Serial.read(); // Lit l'octet
	
		// Machine à états finis qui attend la chaine READY
		if (c == msg[state])
			state++;
		else
			state = 0;
	}
}

Edit : Je me suis aperçu que le pb ne venait pas tellement de là…
Apparement il faut simplement envoyer un message d’init depuis l’Arduino vers le PC (et pas l’inverse). On peut ensuite faire la même chose dans l’autre sens mais je ne pense pas que ce soit nécessaire.

Roipou

Je pense que dans ton 1er code, tu envoies "START\n" avec ton code python et tu compares avec "START" dans le code arduino.

Arf, j’ai encore un petit soucis…

J’arrive à initialiser ma connexion série avec l’IDE Arduino, également avec mon script Python, mais là j’essaie avec Processing et je n’y arrive pas.

Le scénario est : Arduino envoie “READY” au PC, ce dernier, quand il a bien reçu le message, envoie “GO” à l’Arduino.

Mon code Arduino (qui fonctionne) :

void setup() {
  Serial.begin(9600);
  Serial.print("READY");
  waitUntil("GO");
}

void loop() {
  Serial.println("Ok, let's go!");
  while(true);
}

void waitUntil(char* msg) {
	byte state = 0;
	byte msg_length = 0;
	char c;

	// Calcule la longueur du message
	for (; msg[msg_length] != '\0' ; msg_length++);

	/* Boucle infinie */
	while(state != msg_length) {
		while(Serial.available() < 1); // Attend un octet
		c = Serial.read(); // Lit l'octet
	
		// Machine à états finis qui attend la chaine READY
		if (c == msg[state])
			state++;
		else
			state = 0;
	}
}

Mon code Python (qui fonctionne aussi) :

#!/usr/bin/python
# -*- coding: utf-8 -*-

SERIAL_BAUDS = 9600

import serial
from serial.tools import list_ports

def waitUntil(text):
	msg = ""
	while msg.find(text) == -1:

		while ser.inWaiting() == 0:
			pass

		msg = msg + ser.read()

port = list_ports.comports()[-1][0]
print 'Wait for Arduino feedback on ' + port + '.'
ser = serial.Serial(port, SERIAL_BAUDS)

waitUntil("READY")

print "Arduino is ready"
ser.write("GO");

while True:
	print ser.readline(),

ser.close

Mon code Processing (qui ne fonctionne pas du tout) :

import processing.serial.*;

Serial ser; // le port série

void setup()
{
  String port = Serial.list()[0];  
  println("*** Wait for Arduino feedback on " + port + "... ***");
  ser = new Serial(this, port, 9600);

  waitUntil("READY");
  println("Arduino is ready.");
  ser.write("GO");
}

void loop()
{
  while(true)
    print((char)ser.read());
}

void waitUntil(String text)
{
  String msg = "";
  char c;

  while(!msg.contains(text)) {
    while (ser.available() <= 0);
    c = (char)ser.read(); // Lit l'octet
    msg += c;
  }
}

Ce dernier code semble pourtant l’équivalent du code python.
Ici Processing ne cesse d’attendre le message ‘READY’ sans l’obtenir…

Edit : J’ai essayé avec une autre carte Arduino ET en changeant la vitesse à 57600 bauds et là ça fonctionne. Malgrès tout j’ai besoin de faire fonctionner mon code sur la 1ere carte Arduino. Je ne comprends pas pourquoi ce code ne peut fonctionner qu’avec telle carte et telle vitesse de liason série.