SoftSerial VS Loop

Bonjour à tous,

J'ai phénomène qui n'est pas banal.
J'alimente en donnée un arduino via la librairie softserial.

Si je règle la vitesse à 9600 baud, le programme marche à peu prés bien, je manque un peu de vitesse sur ma com.
Si je passe ma vitesse à 57600 baud, le programme ne fonctionne plus, en surveillant sur le moniteur série serial et non softserial, je vois bien mes données arrivé propre, mais le programme ne veut pas s’exécuter.

Auriez vous une idée de ce qu'il se passe.

// serie_com_cockpit.ino
#include <SoftwareSerial.h>
#define RX 9
#define TX 8
#define ESCLAVE 7
#define PRIO 6
boolean PRIOINPUT=true;

#define TRAIN_ARG_D 2
#define TRAIN_ARG_U 3
#define TRAIN_ARD_U 5
#define TRAIN_ARD_D 4
#define TRAIN_AV_U 12
#define TRAIN_AV_D 11

SoftwareSerial portOne(RX,TX);


int Buffer_size;
String data2;

char buf [100];//tampon de réception
volatile byte pos;//position dans le tampon
volatile boolean process_it;//information récupérée



void setup() 
	{
		pinMode(PRIO, INPUT);
		pinMode(ESCLAVE, INPUT);
		pinMode(TRAIN_ARG_D, OUTPUT);
		pinMode(TRAIN_ARG_U, OUTPUT);
		pinMode(TRAIN_ARD_D, OUTPUT);
		pinMode(TRAIN_ARD_U, OUTPUT);
		pinMode(TRAIN_AV_D, OUTPUT);
		pinMode(TRAIN_AV_U, OUTPUT);

		Serial.begin(115200);
		portOne.begin(57600);
		
	}

boolean DATA_test(String Buffer)
	{
		int size_buffer=Buffer.length();
		int size_req=(Buffer.substring(0,3)).toInt();
		if(size_buffer==(size_req+2)){return true;}
		else{return false;}

	}

void loop (void)
	{
		if(PRIOINPUT){pinMode(PRIO, INPUT);}
		else{pinMode(PRIO, OUTPUT);}
		if ((digitalRead(ESCLAVE)==HIGH) and (digitalRead(PRIO)==HIGH))
			{
				while (portOne.available()) 
					{
							// get the new byte:
							char inChar = (char)portOne.read();

							byte c = inChar;  
							if (pos < sizeof (buf))
								{
									buf [pos++] = c;
									if (c == '\n')
									process_it = true;
								}
					}
			}
		else
			{
			
			}

		if (process_it)
			{
				buf [pos] = 0;
				pos = 0;

				String Buffer  = buf;
				Serial.println(Buffer);
				
				data2=Buffer.substring(7,(Buffer.length())-2);
				if(DATA_test(Buffer))
					{
						
						if(Buffer.substring(3,7)=="0005")
							{
								if(data2.toInt()<5)
									{
										digitalWrite(TRAIN_AV_D,LOW);
										digitalWrite(TRAIN_AV_U,HIGH);
									}
								else if(data2.toInt()>95)
									{
										digitalWrite(TRAIN_AV_D,HIGH);
										digitalWrite(TRAIN_AV_U,LOW);
									}
								else if ((data2.toInt()<95) and (data2.toInt()>5)){
										digitalWrite(TRAIN_AV_D,HIGH);
										digitalWrite(TRAIN_AV_U,HIGH);
										delay(500);

									}
							}
						if(Buffer.substring(3,7)=="0006")
							{
								if(data2.toInt()<5)
									{
										digitalWrite(TRAIN_ARG_D,LOW);
										digitalWrite(TRAIN_ARG_U,HIGH);
									}
								else if(data2.toInt()>95)
									{
										digitalWrite(TRAIN_ARG_D,HIGH);
										digitalWrite(TRAIN_ARG_U,LOW);
									}
								else if ((data2.toInt()<95) and (data2.toInt()>5)){
										digitalWrite(TRAIN_ARG_D,HIGH);
										digitalWrite(TRAIN_ARG_U,HIGH);
									}
							}

						if(Buffer.substring(3,7)=="0007")
							{
								if(data2.toInt()<5)
									{
										digitalWrite(TRAIN_ARD_D,LOW);
										digitalWrite(TRAIN_ARD_U,HIGH);
									}
								else if(data2.toInt()>95)
									{
										digitalWrite(TRAIN_ARD_D,HIGH);
										digitalWrite(TRAIN_ARD_U,LOW);
									}
								else if ((data2.toInt()<95) and (data2.toInt()>5)){
										digitalWrite(TRAIN_ARD_D,HIGH);
										digitalWrite(TRAIN_ARD_U,HIGH);
									}
							}

						


					}

				String role;
				role=Buffer.substring(0,2);

				

			}
		process_it = false;
	}

Autre petit question sur la communication sérial de base, il existe void serialEvent() , mais pour le soft serial, je n'arrive pas à le faire, es ce normal, es ce possible sur des "faux" port série?

Merci d'avance pour votre aide.

Flo

Salut,

Mon billet que c'est le même problème qu'ici : [résolu]perte de données en serial - #4 by B_tto - Français - Arduino Forum

kit ou double pour le billet, :smiley:

c'est bien pour le même projet mais... sur le post que tu pointe c'était le vrai port série, et la je parle de soft sérial
un delay fait planter la com sur le softserial, à mon avis, pas de tampon existant
et pas moyen de faire de serial event

Lorsque le débit devient important ou que le traitement des données est un peu long, on ne peut pas travailler avec un seul buffer de réception. En effet pendant que tu traites les caractères reçus d'autres commencent à arriver.
Au lieu de faire un gros buffer de réception. En créer 2 que tu utiliseras en bascule. Tu mets les caractères reçus dans l'un pendant que tu traites les données dans l'autre. Ensuite tu échanges les buffers et tu continues.
Si tu ne peux pas créer 2 buffers, il faut bloquer la réception pendant que tu traites le contenu du buffer. Et ensuite resynchroniser la capture des données sur le début du message.

Ne pas oublier non plus qu'une liaison série est sujette à des erreurs de transmission. En particulier ne jamais partir du principe que le premier caractère que tu trouves dans le buffer de réception est le début de la chaîne que tu attends. C'est pour ça que les protocoles de transmission encadrent les données avec un caractère de début et un caractère de fin.

Ne pas oublier non plus qu'un débit de 57600 bauds sollicite pas mal le CPU. Il y a un bit à traiter toutes les 17,36µs.

Entre nous, tu devrais essayer de ne pas utiliser les String je ne pense pas que ce soit bien adapté aux traitements rapides. Et String peut être à la source de fuites de mémoire.

Pour être efficace, je pense que le mieux serait de traiter les données au vol avec une machine à états.
Tu attends le début de chaîne et ensuite tu traites les données au fur et à mesure qu'elles arrivent. Cela évite le gros tampon, le données sont traitées tout de suite ce qui évite un délai, la charge du processeur est mieux répartie dans le temps.

bonjour à tous,

après avoir pris en considération vos conseils, j'ai commençais à refaire le prg
et au stade ou j'en suis la réception des com est nickel, pas la moindre perte, 6000 reception, pas d'erreur.

pour le moment j'ai mis en application:
-multi tampon
-écoute du port série quand il l'arduino est libre, sinon on temporise

Je vous tiens au courant

// link_2_fs_jarvis.ino
boolean debug=false;//si true des données complémentaire seront envoyé sur le port série principal
boolean proced=true;//permet au programme de savoir si le port série à bien été vidé de ses données et ont été éclaté en consignes distinct
boolean wait=false;//étape intermédiaire de l'éclatement des consignes
String transit[50];//tableau de stockage des consignes à transmettre

unsigned long time=0;//mémoire du temps passé, capacité 50 jours grossiérement
unsigned long time_S=0;//mémoire du temps passé pour les seconde

//réglages des entrés sorties pour la communication maitre esclave
#include <SoftwareSerial.h>//intégration de la libraire pour un second port de communication
#define RX 8 //définition de la pin de réception
#define TX 9 //définition de la pin de d'émission
SoftwareSerial portOne(RX,TX);//création du second port communication
#define PRIO 7
#define ESCLAVE1 6
#define ESCLAVE2 5
#define ESCLAVE3 4
#define ESCLAVE4 3
#define ESCLAVE5 2



void setup() 
	{
		Serial.begin (115200);//démarrage de la communication principal
		portOne.begin(9600);//démarrage vers les esclaves
	}
void send(int role, int esclave, int para,String& name)
	{
		Serial.print(name);Serial.println(" START ");
		
		Serial.print(" Data ");Serial.println(para);
		
		Serial.print(name);Serial.println(" END");
	}
void explode(String& data)//aprés la récupération des données elles sont éclaté en consignes disctintes dans cette fonction
	{
		int transit_count=0;
		String tampon;
		char Bloc;
		for(int i=0; i<data.length(); i++)
			{
				Bloc=data.charAt(i);

				if(tampon.length()==0)
					{
						tampon= "";
						if((Bloc == '=') || (Bloc == '#') || (Bloc == '<') || (Bloc == '?') || (Bloc == '/'))
							{
								tampon+= Bloc;
							}
					}

				else
					{
						if((Bloc == '=') || (Bloc == '#') || (Bloc == '<') || (Bloc == '?') || (Bloc == '/') || (Bloc == '\r') || (Bloc == '\n'))
							{
								transit_count++;
								transit[transit_count]=tampon;
								if(debug){Serial.println(tampon);}
								tampon= "";
								tampon+= Bloc;
							}
						else{tampon+= Bloc;}
					}
			}
		wait=true;
	}

void receive()//récupération des données présente dans le buffer du port sérial principal et purge de celui-ci
	{
		
		String inputString;
		while (Serial.available()) 
			{
				delay(5);
				char Bloc = (char)Serial.read(); 
				inputString+= Bloc;
				
				if(debug){Serial.println(Bloc);}
			}
		explode(inputString);
		if(wait){proced=true; wait=false;}
	}
void loop()
	{
		time = millis();//mise en mémoire du temps
		if(proced)//si aucune récupération est en cours
		{
			proced=false;//on bloc la récupération pour ne pas quelle se lance tant l'encours n'est pas finis
			receive();//démarrage de l'encours de récupération
		}
		

		delay(10);
		if((time-time_S)>1000)
		{
			if(debug){Serial.print("time: ");Serial.println(time);}
			time_S=time;
		}

		for(int i=0; i<50; i++)
		{
			if(transit[i].length()>2)
				{
					int para=(transit[i].substring(2)).toInt();
					String name=transit[i].substring(0,2);
					if(debug){Serial.println(transit[i]);}
					if(transit[i].substring(0,2)=="<D"){send(1,1,para,name);}
					else if(transit[i].substring(0,2)=="<L"){send(1,2,para,name);}
					else if(transit[i].substring(0,2)=="=b"){send(1,3,para,name);}
					else if(transit[i].substring(0,2)=="=c"){send(1,4,para,name);}
					else if(transit[i].substring(0,2)=="<A"){send(2,1,para,name);}
					else if(transit[i].substring(0,2)=="<B"){send(2,2,para,name);}
					else if(transit[i].substring(0,2)=="<C"){send(2,3,para,name);}
					else if(transit[i].substring(0,2)=="<G"){send(3,1,para,name);}
					else{}
				}
			
			transit[i]="";
		}

		
	}

.