Précédent   Forum du club des développeurs et IT Pro > Général Développement > Programmation système > Embarqué
Embarqué Forum d'entraide sur la programmation des systèmes embarqués
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 20/09/2012, 15h29   #101
Hibernatus34
Membre Expert
 
Inscription : août 2010
Messages : 533
Détails du profil
Informations forums :
Inscription : août 2010
Messages : 533
Points : 1 006
Points : 1 006
Oui, là où j'ai écrit "data" c'était bien "c" que je voulais dire.

Concernant ton test, j'ai un gros doute tout d'un coup : dans l'initialisation, est-ce que tu mets le bit UDRIE0 à 0 ou à 1 ?
Je le répète, UDRIE0 doit être à zéro au démarrage de ton programme.
Il doit être mis à 1 quand on a des données à envoyer.

Dans ton test qui "fonctionne", tu balances des ACK sans arrêt. Essaie côté PC de virer le WriteFile et tu recevras toujours des ACK sans avoir rien demandé.
Hibernatus34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2012, 15h31   #102
arthurdubois
Invité régulier
 
Homme arthur
Étudiant
Inscription : mars 2012
Messages : 110
Détails du profil
Informations personnelles :
Nom : Homme arthur
Localisation : Allemagne

Informations professionnelles :
Activité : Étudiant
Secteur : Enseignement

Informations forums :
Inscription : mars 2012
Messages : 110
Points : 9
Points : 9
Du moins j´ai active UDRIE0 dans le registre UCSR0B et le test a marche.
Code :
1
2
UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0)|(0<<TXCIE0)|(0<<UCSZ02)|(1<<UDRIE0);
J´ai essaye a nouveau ta proposition. Helas le pc ne rcoit rien.
arthurdubois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2012, 15h34   #103
arthurdubois
Invité régulier
 
Homme arthur
Étudiant
Inscription : mars 2012
Messages : 110
Détails du profil
Informations personnelles :
Nom : Homme arthur
Localisation : Allemagne

Informations professionnelles :
Activité : Étudiant
Secteur : Enseignement

Informations forums :
Inscription : mars 2012
Messages : 110
Points : 9
Points : 9
Okay, je vais suivre ta logique.
arthurdubois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2012, 15h59   #104
Hibernatus34
Membre Expert
 
Inscription : août 2010
Messages : 533
Détails du profil
Informations forums :
Inscription : août 2010
Messages : 533
Points : 1 006
Points : 1 006
Je ne comprends pas tes réponses. Il ne s'agit pas de suivre ma logique, mais celle de la doc du µC.
Peut-être que je me plante sur le fonctionnement de l'interruption sur UDRE0 et dans ce cas il faut me l'expliquer. Sinon, fais le test dont je t'ai parlé (ne faire aucun WriteFile côté PC), ça permettra de valider le fait que l'interruption est cyclique.
Hibernatus34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2012, 16h31   #105
arthurdubois
Invité régulier
 
Homme arthur
Étudiant
Inscription : mars 2012
Messages : 110
Détails du profil
Informations personnelles :
Nom : Homme arthur
Localisation : Allemagne

Informations professionnelles :
Activité : Étudiant
Secteur : Enseignement

Informations forums :
Inscription : mars 2012
Messages : 110
Points : 9
Points : 9
J´ai vire "WriteFile" du test et j´ai obtenu ceci:
Citation:
Envoie de :
5359,6121
OK
Envoie de :
2756,4216
OK
............
T´a vu juste. Je me demande bien a quel niveau on se plante !!
arthurdubois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/09/2012, 07h42   #106
Hibernatus34
Membre Expert
 
Inscription : août 2010
Messages : 533
Détails du profil
Informations forums :
Inscription : août 2010
Messages : 533
Points : 1 006
Points : 1 006
Je remets mon code après correction de quelques fautes de frappe et une réorganisation du code de RX.
Si tu modifies à nouveau quelque chose (comme quand tu avais passé le flag UDRIE0 à 1), préviens-moi.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#include <avr/io.h>
#include <avr/interrupt.h> 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h> 


#define FOSC 8000000 // Clock Speed
#define BAUD 115200UL

#define UBRR_VAL ((FOSC+BAUD*8)/(BAUD*16)-1)   // clever runden

#define usart_buffer_max_size 64u
#define usart_command_max_size 10

char usart_command[usart_command_max_size + 1] = {0};
char usart0_tx_buffer[usart_buffer_max_size];
char usart1_tx_buffer[usart_buffer_max_size];
volatile uint8_t usart_command_size = 0;
volatile uint8_t usart0_tx_buffer_size = 0;
volatile uint8_t usart0_tx_buffer_start = 0;
volatile uint8_t usart1_tx_buffer_size = 0;
volatile uint8_t usart1_tx_buffer_start = 0;

void USART_Init(unsigned int ubrr)
{
  UBRR0H = (unsigned char)(ubrr>>8);
  UBRR0L = (unsigned char) ubrr;
  UBRR1H = (unsigned char)(ubrr>>8);
  UBRR1L = (unsigned char) ubrr;
  UCSR0B = (1<<RXEN0) | (0<<TXEN0) | (1<<RXCIE0) | (0<<UDRIE0);
  UCSR0C = (1<<USBS0) | (1<<UCSZ01) | (1<<UCSZ00);
  UCSR1B = (1<<RXEN1) | (0<<TXEN1) | (1<<RXCIE1) | (0<<UDRIE1);
  UCSR1C = (1<<USBS1) | (1<<UCSZ11) | (1<<UCSZ10);
} 

/* Ajout dans une file */
void USART0_QueueIn(char c)
{
  int i;

  if (usart0_tx_buffer_size < usart_buffer_max_size)
  {
    i = (usart0_tx_buffer_size + usart0_tx_buffer_start) % usart_buffer_max_size;
    usart0_tx_buffer[i] = c;
    ++usart0_tx_buffer_size;
  }
}

/* Sortie d'une file */
/* J'utilise le caractère nul pour dire qu'il ne reste rien dans la file */
/* Ca signifie que la file n'est pas prête à recevoir du binaire */
char USART0_QueueOut(void)
{
  char c;

  if (usart0_tx_buffer_size == 0)
    return 0;
  c = usart0_tx_buffer[usart0_tx_buffer_start];
  --usart0_tx_buffer_size;
  usart0_tx_buffer_start = (usart0_tx_buffer_start + 1) % usart_buffer_max_size;
  return c;
}

/* Ajout dans une file */
void USART1_QueueIn(char c)
{
  int i;

  if (usart1_tx_buffer_size < usart_buffer_max_size)
  {
    i = (usart1_tx_buffer_size + usart1_tx_buffer_start) % usart_buffer_max_size;
    usart1_tx_buffer[i] = c;
    ++usart1_tx_buffer_size;
  }
}

/* Sortie d'une file */
/* J'utilise le caractère nul pour dire qu'il ne reste rien dans la file */
/* Ca signifie que la file n'est pas prête à recevoir du binaire */
char USART1_QueueOut(void)
{
  char c;

  if (usart1_tx_buffer_size == 0)
    return 0;
  c = usart1_tx_buffer[usart1_tx_buffer_start];
  --usart1_tx_buffer_size;
  usart1_tx_buffer_start = (usart1_tx_buffer_start + 1) % usart_buffer_max_size;
  return c;
}

/* Envoie une réponse sur l'USART0 via la file de transfert */
static void USART0_Send(const char *s)
{
  int i;
  
  for (i = 0; s[i] != 0; ++i)
    USART0_QueueIn(s[i]);
  if (usart0_tx_buffer_size > 0)
    UCSR0B |= 1 << UDRIE0;
}

/* Envoie une commande sur l'USART1 via la file de transfert */
static void USART1_Send(const char *s)
{
  int i;
  
  for (i = 0; s[i] != 0; ++i)
    USART1_QueueIn(s[i]);
  if (usart1_tx_buffer_size > 0)
    UCSR1B |= 1 << UDRIE1;
}

/* Traitement de la commande */
static void ProcessCommand(void)
{
  int i;
  int x;
  int y;
  char x_moteur[12];
  char y_moteur[12];

  /* On extrait le X et le Y, puis on génère les commandes moteurs */
  for (i = 0; i < usart_command_size; ++i)
    if (usart_command[i] == ',')
      break;
  if (i <= 0 || i >= usart_command_size - 1)
  {
    /* On n'a pas trouvé la virgule au milieu de la chaîne -> erreur */
    USART0_Send("\x15");  /* NAK */
    usart_command_size = 0;
    return;
  }
  /* Je transforme volontairement x et y en int pour te permettre des contrôles ou des calculs */
  usart_command[i] = 0;
  usart_command[usart_command_size] = 0;
  x = atoi(usart_command);
  y = atoi(usart_command + i + 1);
  usart_command_size = 0;
  /* Envoi des commandes moteurs */
  itoa(x, x_moteur, 10);
  itoa(y, y_moteur, 10);
  USART1_Send("#1s");
  USART1_Send(x_moteur);
  USART1_Send("\r");
  USART1_Send("#2s");
  USART1_Send(y_moteur);
  USART1_Send("\r");
  /* TODO:
  Le moteur répond par un écho pour confirmer la commande
  Il faut le gérer, mais pas directement ici, car ici on ne doit pas rester trop longtemps */
  USART0_Send("\x06");  /* ACK */
}

/* La fonction d´interruption de reception du byte */
/* Cette fonction est active lorsque RXCIE0 = 1 */ 
ISR(USART0_RX_vect)
{
  char data;

  data = UDR0;
  if (data == '\r')
    /* Traitement de la commande */
    ProcessCommand();
  else if (data == '\n')
    /* Démarrage d'une nouvelle commande */
    usart_command_size = 0;
  else
    /* Quand on ne reçoit ni \r ni \n, on enregistre le caractère dans la commande */
    if (usart_command_size < usart_command_max_size)
    {
      usart_command[usart_command_size] = data;
      ++usart_command_size;
    }
}

/* La fonction d´interruption d´envoi de byte */
/* Cette fonction est active lorsque UDRIE0 = 1 */
ISR(USART0_UDRE_vect)
{
  UDR0 = USART0_QueueOut();
  /* S'il n'y a plus de données à envoyer on arrete l'emission */
  if (usart0_tx_buffer_size == 0)
    UCSR0B &= ~(1 << UDRIE0);
}

/* La fonction d´interruption d´envoi de byte */
/* Cette fonction est active lorsque UDRIE1 = 1 */
ISR(USART1_UDRE_vect)
{
  UDR1 = USART1_QueueOut();
  /* S'il n'y a plus de données à envoyer on arrete l'emission */
  if (usart1_tx_buffer_size == 0)
    UCSR1B &= ~(1 << UDRIE1);
}

int main (void)
{ 
  USART_Init(UBRR_VAL);
  sei();
  /* TODO: Ici il faut paramétrer les moteurs (mode de positionnement etc.) */
  while (1)
  {
  }
}
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include <fstream>
#include <string>
#include <iostream>
#include <sstream>

#include <Windows.h>

using namespace std;

// Envoie une commande caractère par caractère, et teste la réception d'un ACK
static bool EnvoieCommande(HANDLE h, string s)
{
	DWORD	length;
	char	c;

	// S'il y avait des réponses à lire depuis la dernière commande,
	// trop tard, on les supprime.
	PurgeComm(h, PURGE_RXCLEAR);
	if (!WriteFile(h, s.c_str(), s.size(), &length, 0) || length != s.size())
	{
		cout << "Erreur de WriteFile" << endl;
		return false;
	}
	if (!ReadFile(h, &c, 1, &length, 0) || length != 1)
	{
		cout << "Erreur de ReadFile (time-out)" << endl;
		return false;
	}
	cout << "Réponse : " << (int)c << endl
	return c == '\x06';	// ACK
}

int main(void)
{
	ifstream file("koordinaten.txt", ios::in | ios::binary);
	string line;

	if (!file)
	{
		cout << "Erreur: Impossible d´ouvrir le fichier en mode lecture" << endl;
		return 1;
	}
	// Ouverture du port COM (c'est votre code tel quel)
	HANDLE h = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	if (h == INVALID_HANDLE_VALUE)
	{
		cout << "Erreur: Impossible d´ouvrir le port série" << endl;
		return 1;
	}
	DCB dcb = { 0 };
	BOOL dcbOk = GetCommState(h, &dcb);
	dcb.BaudRate = CBR_115200;
	dcb.ByteSize = 8;
	dcb.Parity = NOPARITY;
	dcb.StopBits = TWOSTOPBITS;
	dcbOk = SetCommState(h, &dcb);
	COMMTIMEOUTS timeouts = { 0 };
	timeouts.ReadIntervalTimeout = 100;
	timeouts.ReadTotalTimeoutMultiplier = 100;
	timeouts.ReadTotalTimeoutConstant = 100;
	timeouts.WriteTotalTimeoutMultiplier = 100;
	timeouts.WriteTotalTimeoutConstant = 100;
	if (!SetCommTimeouts(h, &timeouts))
	{
		cout << "Erreur: SetCommTimeouts" << endl;
		CloseHandle(h);
		return 1;
	}
	// Lecture ligne par ligne
	while (getline(file, line))
	{
		int x;					// x, y du texte
		int y;
		int x_steps;			// x, y en pas moteur
		int y_steps;
		stringstream input;		// flux d'entrée (une ligne du texte)
		stringstream output;	// flux de sortie (une paire de coordonnées)

		// Une ligne devient un flux d'entrée
		input.str(line);
		// Extraction du X et du Y.
		if (input.get() != 'X')
			continue;
		input >> x;
		if (input.get() != 'Y')
			continue;
		input >> y;
		// Conversion de la position en pas moteur
		// J'ai rendu le calcul compatible avec le type int. (et je le trouve plus lisible)
		x_steps = x * 127 / 500;
		y_steps = y * 127 / 500;
		// Envoi des coordonnées par le port série
		output << '\n';
		output << x_steps;
		output << ',';
		output << y_steps;
		output << '\r';
		cout << "Envoi de : " << output.str() << endl;
		if (EnvoieCommande(h, output.str()))
			cout << "OK" << endl;
		else
			cout << "ERREUR" << endl;
	}
	CloseHandle(h);
	return 0;
}
Hibernatus34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/09/2012, 10h26   #107
arthurdubois
Invité régulier
 
Homme arthur
Étudiant
Inscription : mars 2012
Messages : 110
Détails du profil
Informations personnelles :
Nom : Homme arthur
Localisation : Allemagne

Informations professionnelles :
Activité : Étudiant
Secteur : Enseignement

Informations forums :
Inscription : mars 2012
Messages : 110
Points : 9
Points : 9
Bonjour Hibernatus34,

tout d´abord je tiens a m´escuser pour mon silence. En fait j´ai revu en integralite les codes et je n´ai decele aucune erreurs de notre part. Bref je ne comprenais pas ce qui clôchait. Alors j´ai decide de tester a nouveau la communication entre le pc et le µC. Mais le test n´a pas marche. C´est alors que j´ai compris que l´erreur ne venait pas des codes, mais de mon circuit electronique. En fait, une entree de mon circuit ne recevait pas assez de courant. Au lieu de recevoir 5volt, l´entree en question du circuit recevait moins de 1Volt. Bref j´ai remedie au probleme et j´ai teste a nouveau les derniers codes que tu as postes. Le resultat donne ceci:

Citation:
Envoi de:
5359,6121
Reponse: 6
OK
Envoi de:
2756,4216
Reponse: 6
OK
Le µC recoit en effet les positions et en suite il retourne au pc la reponse 'ACK' pour confirmer la reception.

Cependant, j´ai teste les codes precedents et ils fonctionnent aussi.

Dire que mon circuit me jouait un sale tour.

merci.
arthurdubois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/09/2012, 11h46   #108
arthurdubois
Invité régulier
 
Homme arthur
Étudiant
Inscription : mars 2012
Messages : 110
Détails du profil
Informations personnelles :
Nom : Homme arthur
Localisation : Allemagne

Informations professionnelles :
Activité : Étudiant
Secteur : Enseignement

Informations forums :
Inscription : mars 2012
Messages : 110
Points : 9
Points : 9
Une fois de plus bonjour,

J´ai parametrer les moteurs de commande dans le code du µC comme ceci:

Code :
1
2
3
4
5
6
7
8
9
void ParametrageMoteur(void)
 { 
   USART1_Send("#2D\r"); // Considerer la position actuelle comme origine du repere sur l´axe x 
   USART1_Send("#3D\r"); // Considerer la position actuelle comme origine du repere sur l´axe y
   
   USART1_Send("#2p2\r");// Mode de travail: deplacement absolu --> p = 2
   USART1_Send("#3p2\r");	      
 }
Dans la fonction ProcessCommand(), j´ai ajoute:
Code :
1
2
3
 - USART1_Send("#2A\r"); // Activation de l´envoi sur l´axe x
 - USART1_Send("#3A\r"); // Activation de l´envoi sur l´axe y
J´ai aussi modifie la configuration de l´USART0 et l`USART1 de la maniere suivante:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void USART_Init (unsigned int ubrr)
{
  UBRR0H = (unsigned char)(ubrr>>8);
  UBRR0L = (unsigned char) ubrr;
  UBRR1H = (unsigned char)(ubrr>>8);
  UBRR1L = (unsigned char) ubrr;
  
/* Enable receiver and transmitter and set frame format: 8data, 2stop bit */ 

  UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0)|(0<<TXCIE0)|(0<<UCSZ02)|(0<<UDRIE0);
  UCSR0C = (1<<USBS0) | (1<<UCSZ01)|(1<<UCSZ00);

  UCSR1B = (0<<RXEN1)|(1<<TXEN1)|(0<<RXCIE1)|(0<<TXCIE1)|(0<<UCSZ12)|(0<<UDRIE1);
  UCSR1C = (1<<USBS1) |(1<<UCSZ11)|(1<<UCSZ10);
  
}
Code du µC en integralite:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
#include <avr/io.h>
#include <avr/interrupt.h> 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h> 
#include <avr/pgmspace.h>

#define FOSC 8000000 // Clock Speed
#define BAUD 115200UL

// Berechnungen zur Baudrate:

#define UBRR_VAL ((FOSC+BAUD*8)/(BAUD*16)-1)   // clever runden

#define usart_buffer_max_size 64u
#define usart_command_max_size 10

/***************************************************/

char usart_command[usart_command_max_size + 1] = {0};
char usart0_tx_buffer[usart_buffer_max_size ];
char usart1_tx_buffer[usart_buffer_max_size ];
volatile uint8_t usart_command_size = 0;
volatile uint8_t usart0_tx_buffer_size = 0;
volatile uint8_t usart0_tx_buffer_start = 0;
volatile uint8_t usart1_tx_buffer_size = 0;
volatile uint8_t usart1_tx_buffer_start = 0;


/****************************************************/
    /* Set baud rate */

void USART_Init (unsigned int ubrr)
{
  UBRR0H = (unsigned char)(ubrr>>8);
  UBRR0L = (unsigned char) ubrr;
  UBRR1H = (unsigned char)(ubrr>>8);
  UBRR1L = (unsigned char) ubrr;
  
/* Enable receiver and transmitter and set frame format: 8data, 2stop bit */ 

  UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0)|(0<<TXCIE0)|(0<<UCSZ02)|(0<<UDRIE0);
  UCSR0C = (1<<USBS0) | (1<<UCSZ01)|(1<<UCSZ00);

  UCSR1B = (0<<RXEN1)|(1<<TXEN1)|(0<<RXCIE1)|(0<<TXCIE1)|(0<<UCSZ12)|(0<<UDRIE1);
  UCSR1C = (1<<USBS1) |(1<<UCSZ11)|(1<<UCSZ10);
  
} 

/*********************************************************

/**********************************************************/

/*-Aktivierung der Datenübertragung über RS485 von USART1-*/

 void RS485_Init (void)
{
  DDRD = (1<<PD4)|(1<<PD3)|(1<<PD5); //Steuer- und Datenausgang aktivieren
  PORTD = (1<<PD4);	//auf Senden stellen (Aktivierung Datensendung)
}

/* Ajout dans une file */
void USART0_QueueIn(char c)
{
  int i;
  

  if (usart0_tx_buffer_size < usart_buffer_max_size)
  {
    i = (usart0_tx_buffer_size + usart0_tx_buffer_start) % usart_buffer_max_size;
    usart0_tx_buffer[i] = c;
    ++usart0_tx_buffer_size;
  }
}

/* Sortie d'une file */
/* J'utilise le caractère nul pour dire qu'il ne reste rien dans la file */
/* Ca signifie que la file n'est pas prête à recevoir du binaire */
char USART0_QueueOut(void)
{
  char c;

  if (usart0_tx_buffer_size == 0)
    return 0;
  c = usart0_tx_buffer[usart0_tx_buffer_start];
  --usart0_tx_buffer_size;
  usart0_tx_buffer_start = (usart0_tx_buffer_start + 1) % usart_buffer_max_size;
  return c;
}

/* Ajout dans une file */
void USART1_QueueIn(char c)
{
  int i;
  
  if (usart1_tx_buffer_size < usart_buffer_max_size)
  {
    i = (usart1_tx_buffer_size + usart1_tx_buffer_start) % usart_buffer_max_size;
    usart1_tx_buffer[i] = c;
    ++usart1_tx_buffer_size;
  }
}

/* Sortie d'une file */
/* J'utilise le caractère nul pour dire qu'il ne reste rien dans la file */
/* Ca signifie que la file n'est pas prête à recevoir du binaire */
char USART1_QueueOut(void)
{
  char c;

  if (usart1_tx_buffer_size == 0)
    return 0;
  c = usart1_tx_buffer[usart1_tx_buffer_start];
  --usart1_tx_buffer_size;
  usart1_tx_buffer_start = (usart1_tx_buffer_start + 1) % usart_buffer_max_size;
  return c;
}

/* Envoie une réponse sur l'USART0 via la file de transfert */
static void USART0_Send(const char *s)
{
  int i;
  
  for (i = 0; s[i] != 0; ++i)
    USART0_QueueIn(s[i]);
  if (usart0_tx_buffer_size > 0)
    UCSR0B |= 1 << UDRIE0;
}

/* Envoie une commande sur l'USART1 via la file de transfert */
static void USART1_Send(const char *s)
{
  int i;
  
  for (i = 0; s[i] != 0; ++i)
    USART1_QueueIn(s[i]);
  if (usart1_tx_buffer_size > 0)
    UCSR1B |= 1 << UDRIE1;
}

/* Traitement de la commande */
static void ProcessCommand(void)
{
  int i;
  int x;
  int y;
  char x_moteur[12];
  char y_moteur[12];

  /* On extrait le X et le Y, puis on génère les commandes moteurs */
  for (i = 0; i < usart_command_size; ++i)
    if (usart_command[i] == ',')
      break;
  if (i <= 0 || i >= usart_command_size - 1)
  {
    /* On n'a pas trouvé la virgule au milieu de la chaîne -> erreur */
    USART0_Send("\x15");  /* NAK */
    usart_command_size = 0;
    return;
  }
  /* Je transforme volontairement x et y en int pour te permettre des contrôles ou des calculs */
  usart_command[i] = 0;
  usart_command[usart_command_size] = 0;
  x = atoi(usart_command);
  y = atoi(usart_command + i + 1);
  usart_command_size = 0;
  /* Envoi des commandes moteurs */
  itoa(x, x_moteur, 10);
  itoa(y, y_moteur, 10);
  USART1_Send("#2s");
  USART1_Send(x_moteur);
  USART1_Send("\r");
  USART1_Send("#2A\r"); // Activation de l´envoi de x_moteur via USART1
  USART1_Send("#3s");
  USART1_Send(y_moteur);
  USART1_Send("\r");
  USART1_Send("#3A\r"); // Activation de l´envoi de y_moteur via USART1
  /* TODO:
  Le moteur répond par un écho pour confirmer la commande
  Il faut le gérer, mais pas directement ici, car ici on ne doit pas rester trop longtemps */
  USART0_Send("\x06");  /* ACK */
}

/* La fonction d´interruption de reception du byte */
/* Cette fonction est active lorsque RXCIE0 = 1 */ 
ISR(USART0_RX_vect)
{
  char data;

  data = UDR0;
  if (data == '\r')
    /* Traitement de la commande */
    ProcessCommand();
  else if (data == '\n')
    /* Démarrage d'une nouvelle commande */
    usart_command_size = 0;
  else
    /* Quand on ne reçoit ni \r ni \n, on enregistre le caractère dans la commande */
    if (usart_command_size < usart_command_max_size)
    {
      usart_command[usart_command_size] = data;
      ++usart_command_size;
    }
}

/*
ISR(USART0_RX_vect)
{
  char data;
  data = UDR0;

  if (data == '\r')
    UCSR0B |= 1 << UDRIE0;
}

ISR(USART0_UDRE_vect)
{
  
  UDR0 = '\x06';
  //  UCSR0B |= 0 << UDRIE0;
  UCSR0B &= ~(1 << UDRIE0);
}
*/

/* La fonction d´interruption d´envoi de byte */
/* Cette fonction est active lorsque UDRIE0 = 1 */
ISR(USART0_UDRE_vect)
{
  UDR0 = USART0_QueueOut();
  /* S'il n'y a plus de données à envoyer on arrete l'emission */
  if (usart0_tx_buffer_size == 0)
    UCSR0B &= ~(1 << UDRIE0);
}

/* La fonction d´interruption d´envoi de byte */
/* Cette fonction est active lorsque UDRIE1 = 1 */
ISR(USART1_UDRE_vect)
{
  UDR1 = USART1_QueueOut();
  /* S'il n'y a plus de données à envoyer on arrete l'emission */
  if (usart1_tx_buffer_size == 0)
    UCSR1B &= ~(1 << UDRIE1);
}

void ParametrageMoteur(void)
 { 
   USART1_Send("#2D\r"); // Considerer la position actuelle comme origine du repere sur l´axe x 
   USART1_Send("#3D\r"); // Considerer la position actuelle comme origine du repere sur l´axe y
   
   USART1_Send("#2p2\r");// Mode de travail: deplacement absolu --> p = 2
   USART1_Send("#3p2\r");	      
 }


int main (void)
{ 
  USART_Init(UBRR_VAL);
  RS485_Init();
/* TODO: Ici il faut paramétrer les moteurs (mode de positionnement etc.) */
  ParametrageMoteur();
  sei();
 
  while (1)
  {	 
  }
  
}
Qu´en penses-tu ? Dois-je proceder autrement ou bien ma proposition est bonne ?
arthurdubois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/09/2012, 15h01   #109
Hibernatus34
Membre Expert
 
Inscription : août 2010
Messages : 533
Détails du profil
Informations forums :
Inscription : août 2010
Messages : 533
Points : 1 006
Points : 1 006
Content que ça marche.
Je pense que tu es sur les rails maintenant, tu n'as plus tellement besoin de moi.
Hibernatus34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/09/2012, 15h17   #110
arthurdubois
Invité régulier
 
Homme arthur
Étudiant
Inscription : mars 2012
Messages : 110
Détails du profil
Informations personnelles :
Nom : Homme arthur
Localisation : Allemagne

Informations professionnelles :
Activité : Étudiant
Secteur : Enseignement

Informations forums :
Inscription : mars 2012
Messages : 110
Points : 9
Points : 9
Citation:
Je pense que tu es sur les rails maintenant, tu n'as plus tellement besoin de moi.
J´ai interêt a être sur les rails, car je ressens deja la pression. Neanmoins, je vais te tenir informer de la suite.

Merci encore .
arthurdubois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/10/2012, 21h07   #111
arthurdubois
Invité régulier
 
Homme arthur
Étudiant
Inscription : mars 2012
Messages : 110
Détails du profil
Informations personnelles :
Nom : Homme arthur
Localisation : Allemagne

Informations professionnelles :
Activité : Étudiant
Secteur : Enseignement

Informations forums :
Inscription : mars 2012
Messages : 110
Points : 9
Points : 9
Bonsoir Hibernatus,

j´ai quelques soucis avec le pc, le µC et les deux moteurs de commande.

J´ai envoye en integralite les positions X et Y du pc vers le µC. L´envoi des donnees fonctionnent, mais les deux moteurs (axe X et Y) de la platine relies aux deux moteurs de commande ne recoivent pas toutes les positions envoyees par le microcontrôleur.

Pour être plus clair, si le pc envoie 15 couples (X,Y) de position, alors la platine effectue uniquement le deplacement d´un couple de position. Pourtant la platine devrait aussi effectuer le deplacement de 15 couples de position qui lui ont ete transmis par le µC . Mais la platine ne recoit pas toutes les 15 positions, elle(platine) recoit seulement une position.


J´ai verifie la configuration du pc et du µC et tout semble être ok. Helas la platine n´effectue pas le deplacement de toutes les positions qui sont envoyes par le pc et puis le microcontrôleur. Se pourrait-il que le microcontrôleur et le pc soient trop rapide pour les deux moteurs de commande? Ou bien on doit diminuer la vitesse d´envoi des positions du pc vers le microcontrôleur ?? j´ai essaye de regler le probleme, mais je n´y arrive pas !!

Sais-tu comment on pourrais ressoudre ce probleme ?

Merci d´avance et bonne soiree.
arthurdubois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/10/2012, 15h56   #112
Hibernatus34
Membre Expert
 
Inscription : août 2010
Messages : 533
Détails du profil
Informations forums :
Inscription : août 2010
Messages : 533
Points : 1 006
Points : 1 006
Salut,

Il y a plusieurs possibilités.
Évidemment le buffer d'entrée des moteurs n'est pas infini, mais surtout il pourrait être limité à une commande. Dans ce cas il faut attendre la réponse du moteur avant d'en envoyer une autre.
Je n'en sais rien, c'est à toi de te renseigner sur ces moteurs, mais de toute façon, à moins que le débit d'envoi temporise lui-même suffisamment, il est certain que tu ne peux pas envoyer une infinité de commandes en continu.

Je crois que les moteurs renvoient un écho à chaque commande.
Il est probable que cet écho suffise à dire "je suis prêt à recevoir une autre commande" (même si la rotation n'est pas terminée, le buffer de commande est prêt). Sinon, il y a peut-être une fonction de polling pour demander au moteur "es-tu prêt ?".

Tu peux par exemple renvoyer le ACK au PC uniquement quand tu as reçu l'écho des moteurs. Puisque le PC attend ce ACK après chaque commande, ça temporisera automatiquement. (sous réserve d'un réglage du time-out)
Pour ça il faut gérer une ISR sur le RX de l'USART1.

Quand on reçoit \r sur l'USART0, au lieu de renvoyer ACK à la fin, on stocke les 2 échos qu'on attend dans des chaînes statiques.
Quand on reçoit \n sur l'USART0, on vide ces 2 chaînes (machaîne[0] = 0). C'est pour le cas d'un time-out ou d'un redémarrage.
Quand on reçoit quelque chose sur l'USART1, on le compare à l'écho attendu, et quand on l'a reçu, on envoie un ACK sur l'USART0.
Si on reçoit autre chose que ce qui était attendu, je pense qu'il faut l'ignorer.

Je ne connais pas le RS-485, je ne sais pas ce qui garantit que tu reçois une réponse complète de chaque moteur, sans entrelacement entre les deux.
Faisons comme si c'était géré pour l'instant, donc il suffit d'un buffer d'entrée etc. (comme le buffer de commande qu'on utilise sur l'USART0, ou une file pour ignorer facilement des reliquats d'une autre réponse)

Là il faudrait l'avis de quelqu'un qui a de l'expérience dans ce domaine.
Hibernatus34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/10/2012, 16h47   #113
Hibernatus34
Membre Expert
 
Inscription : août 2010
Messages : 533
Détails du profil
Informations forums :
Inscription : août 2010
Messages : 533
Points : 1 006
Points : 1 006
PS. J'ai cherché un peu des infos sur le RS-485, visiblement c'est du half-duplex géré en "software". Je suis pas sûr d'avoir compris, mais j'ai l'impression il faudrait donc envoyer une commande à un moteur, attendre sa réponse, envoyer celle de l'autre moteur et attendre sa réponse. Et pas envoyer les 2 commandes d'un coup et attendre les 2 réponses après.
Si quelqu'un connaissant le RS-485 peut te renseigner, ça sera mieux.
Ou peut-être que c'est expliqué dans la doc du moteur.
Hibernatus34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/10/2012, 12h35   #114
arthurdubois
Invité régulier
 
Homme arthur
Étudiant
Inscription : mars 2012
Messages : 110
Détails du profil
Informations personnelles :
Nom : Homme arthur
Localisation : Allemagne

Informations professionnelles :
Activité : Étudiant
Secteur : Enseignement

Informations forums :
Inscription : mars 2012
Messages : 110
Points : 9
Points : 9
Bonjour Hibernatus,

J´ai recueuillis les infos et j´aimerais te communiquer le concept.

1er etape: Le pc envoie sucessivement les positions ligne par ligne au µC

2ieme etape:
-si le µC ne recoit pas les positions , il retourne "NAK" au pc

-si le µC recoit les positions, alors il retourne "ACK" au pc

-Ensuite le µC envoie sucessivement les positions (X,Y)
simultanement vers les deux moteurs de commande.

3ieme etape:

-Des lors que les deux moteurs de commande recoivent sucessivement une position (X,Y), alors les moteurs de commande retournent respectivement les reponses pour confirmer si oui ou non la position recue a ete parcourue par la platine sur les deux axes x et y.

- Une fois que la platine aura atteint la position (X,Y) envoyee, il va falloir faire une courte pause, afin que un trou soit perce sur la platine.

- En suite on peut passer a l´envoie de la 2nde position, 3ieme position, 4ieme position, ainsi de suite. Biensûr toutes les positions envoyees par le pc devront respecter le protocol que je viens de decrire.

En bref, il faut qu´on envoie une position (X,Y) d´un coup, ensuite les deux moteurs de commande retournent les reponses pour confirmer si oui ou non la platine s´est deplaacee a la position (X,Y). Apres il va falloir faire une courte pause pour faire un trou sur la platine correspondant a la position (X,Y) parcourue par la platine. En suite on passe a partir du pc a l´envoi de la 2nde, 3ieme , 4ieme position ...etc

En fait, c´est le protocol qu´on m´a propose afin qu´il n y ait plus de conflit pendant le transfert des positions entre le pc, le µC et les deux moteurs de commande. Je crois que ce concept suit aussi tes idees. Mais c´est vraiment primordial qu´une position soit envoyee d´un coup. Je me suis renseigne et on m´a dit que le RS485 peut le faire.

Qu´en penses-tu ?
arthurdubois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/10/2012, 14h33   #115
Hibernatus34
Membre Expert
 
Inscription : août 2010
Messages : 533
Détails du profil
Informations forums :
Inscription : août 2010
Messages : 533
Points : 1 006
Points : 1 006
Il faut m'expliquer comment le RS-485 peut le faire.
Sur ce sujet, si je ne comprends pas comment ça marche, je vais partir du principe que ça ne marche pas.
D'après ce que j'ai lu (ou plutôt survolé), c'est au maître (ton µC) de faire respecter un protocole. Quand il envoie un message à une adresse spécifique, il doit attendre sa réponse avant d'envoyer tout autre message.

Là, si on envoie une commande à chaque moteur presque en même temps, et si le décalage inverse est produit par un moteur plus long que l'autre à répondre (oui c'est un peu tiré par les cheveux), il vont se retrouver à vouloir émettre en même temps une réponse. Donc il faut m'expliquer pourquoi et comment ça va marcher quand même.

Concernant le reste, tu sembles dire au début de la 3ème étape que la réponse du moteur est envoyée à la fin du mouvement. Tu es sûr de ce point ? C'est important à savoir.

Ce qui ne va pas dans ton protocole, c'est que rien ne permet au PC de savoir quand il peut envoyer une nouvelle commande, car il reçoit le ACK trop tôt.
Hibernatus34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/10/2012, 15h33   #116
arthurdubois
Invité régulier
 
Homme arthur
Étudiant
Inscription : mars 2012
Messages : 110
Détails du profil
Informations personnelles :
Nom : Homme arthur
Localisation : Allemagne

Informations professionnelles :
Activité : Étudiant
Secteur : Enseignement

Informations forums :
Inscription : mars 2012
Messages : 110
Points : 9
Points : 9
salut hibernatus,

ce que tu dis est vraiment pertinent. Pourrais-tu me suggerer une amelioration du protocol que je t´ai presente.

Citation:
Il faut m'expliquer comment le RS-485 peut le faire.
En fait le µC et les deux moteurs de commande sont connectes par un câble. le bout du câble connecte a l´USART1 du µC possede une entree RS485 et l´autre bout du câble connecte aux deux moteurs de commande possedes deux sorties RS485. Car chaque Moteur de commande possede une entree RS485.
Lorsque j´ai effectue le deboggage en transferant les positions du fichier texte en direction des deux moteurs de commande, j´ai remarque que la platine effectue uniquement le deplacement d´une position (X,Y) simultanement sur l´axe x et y. Biensûre c´est grâce a tes codes du pc et µC que j´ai observe cela. C´est pourquoi je pense que c´est possible d´envoyer simultanement une position (X,Y) via le RS485 du µC en direction des deux moteurs de commande.

Citation:
Concernant le reste, tu sembles dire au début de la 3ème étape que la réponse du moteur est envoyée à la fin du mouvement. Tu es sûr de ce point ? C'est important à savoir.
Bon, je ne suis pas sûre a 100%. J´ai regarde dans le doc du moteur de commande pour connaître l´instruction qui permet de retourner une reponse lorsque le moteur recoit une position. Helas j´ai pas trouve. Peut-être que je suis passe a côte. Mais je vais encore chercher, car se serait embêtant qu´il n´est pas pense a cela. Cependant, il y a une instruction qui permet de connaître la distance parcourue par la platine. Je ne sais pas si cela peut nous aider. En clair, c´etait une proposition !!

Qu´en dis-tu ? Apparement, il faut a tout prix que les moteurs de commande nous fournissent des reponses. Mais je ne sais pas si cela doit se faire avant ou apres le deplacement de la platine !! Tout compte fait, je pense que la reponse doit intervenir avant le deplacement de la platine.
arthurdubois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/10/2012, 17h03   #117
Hibernatus34
Membre Expert
 
Inscription : août 2010
Messages : 533
Détails du profil
Informations forums :
Inscription : août 2010
Messages : 533
Points : 1 006
Points : 1 006
Ton explication n'est pas suffisante.
D'après ce que j'ai cru comprendre, le RS-485 ne ferait que du half-duplex (un seul point émet à la fois, donc le µC ne pourrait pas émettre une commande Y en même temps qu'il reçoit l'écho de X).
Et, toujours d'après ce que j'ai cru comprendre, l'orchestration se fait par la couche supérieure, en général avec un système maître/esclaves :
- Le maître peut envoyer des trames nominatives, il attend alors la réponse de chacune avant d'émettre à nouveau.
- Il peut aussi envoyer des trames en broadcast, et là il ne doit pas y avoir de réponse.
- Enfin, les esclaves ne doivent émettre que pour répondre aux trames du maître (l'écho renvoyé par les moteur, qui ne commence pas par #, d'ailleurs).

Mais bon, je peux pas te garantir que j'ai bien tout compris.
Hibernatus34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/10/2012, 17h10   #118
arthurdubois
Invité régulier
 
Homme arthur
Étudiant
Inscription : mars 2012
Messages : 110
Détails du profil
Informations personnelles :
Nom : Homme arthur
Localisation : Allemagne

Informations professionnelles :
Activité : Étudiant
Secteur : Enseignement

Informations forums :
Inscription : mars 2012
Messages : 110
Points : 9
Points : 9
Okay, essayons ta proposition. C´est fort probable que mon explication ne soit pas suffisant!!!
arthurdubois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/10/2012, 07h48   #119
arthurdubois
Invité régulier
 
Homme arthur
Étudiant
Inscription : mars 2012
Messages : 110
Détails du profil
Informations personnelles :
Nom : Homme arthur
Localisation : Allemagne

Informations professionnelles :
Activité : Étudiant
Secteur : Enseignement

Informations forums :
Inscription : mars 2012
Messages : 110
Points : 9
Points : 9
Bonjour Hibernatus34,

J´ai relus la doc du moteur de commande et il s´avere effectivement que le moteur de commande
retourne une reponse lorsqu´il recoit une commande valide ou invalide. J´ai recueillis ces
explications a la page 10 de la doc (Controller response).

- Si le moteur de commande reconnaît une commande comme etant valide, alors le moteur de
commande confirme la reception en retournant la commande recue comme echo, mais sans le
caractere '#' , qui marque le debut d´une commande.

Exemple: Commande envoyee au moteur de commande ------> '#1G10000000\r'
Reponse du moteur de commande ------> '1G10000000\r'

- Si le moteur de commande reconnaît une commande qu´il recoit comme etant une commande
invalide, alors le moteur de commande retourne comme reponse la commande recue en incluant
un point d´interrogation '?' avant le caractere '\r', qui marque la fin d´une commande.

Exemple: Commande envoyee au moteur de commande ------> '#1°\r'
Reponse du moteur de commande - -----> '#1°?\r'

D´apres ces explications, je pense qu´il est preferable que les deux moteurs de commande
retournent une reponse lorsqu´il recoivent une commande valide ou invalide avant que la
platine se deplace. Une fois les reponses retournees par les deux moteurs de commande, le uc
retourne "ACK" ou "NAK" au pc et la platine se deplace a la position de la commande qu´il
a recue. Puis une courte pause sera effectuee pour percer un trou sur la platine. Dans la
même lancee, les prochaines positions qui seront envoyees respecteront ce procesus.

En clair, tes propositions etaient les bonnes. Dis Hibernatus34, comment
va-t-on s´y prendre pour la programmation. Elle sera a coup sûre complexe.
arthurdubois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/10/2012, 09h35   #120
Hibernatus34
Membre Expert
 
Inscription : août 2010
Messages : 533
Détails du profil
Informations forums :
Inscription : août 2010
Messages : 533
Points : 1 006
Points : 1 006
Citation:
Dis Hibernatus34, comment va-t-on s´y prendre pour la programmation. Elle sera a coup sûre complexe.
A un moment donné il faut savoir dire stop, parce que j'ai aussi un boulot, et parce que je t'ai déjà trop aidé.

Une remarque, quand même :
Je ne sais pas ce qu'est cette histoire de trou, mais si tu dois déclencher une autre action à la fin du positionnement, il te faudra interroger les moteurs pour savoir quand ils ont terminé leur mouvement.
Hibernatus34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 07h00.


 
 
 
 
Partenaires

Hébergement Web