Arduino - Pasar delay() a millis()

   
Vista:
Imágen de perfil de Gorka

Pasar delay() a millis()

Publicado por Gorka (6 intervenciones) el 03/01/2018 21:13:30
En este Sketch tengo programado un robot que consta de 2 motores DC controlados por un L298N, un ultrasonido hcsr04 y un buzzer que pita si encuentra un obstaculo.
El robot esta programado para que siga una ruta programada anteriormente con los DC y el L289N.
La idea es que si encuentra un obstaculo, este se pare y emita sonido el buzzer y se encienda un LED, pero unicamente se para antes de que se inicien los motores, cuando estan en funcionamiento no para.


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
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
////////////// DECLARACION PIN MOTORES ////////////////////////
////////////////////////////////////////////
//MOTOR B
int IN3 = 5;
int IN4 = 4;
//MOTOR A
int IN1 = 2;
int IN2 = 3;
//////////////////////////////////////
//////////////////////////////////////
 
//////////////// BUZZER /////////////////////////
/////////////////////////////////////////////////
const int pinBuzzer = 6;
/////////////////////////////////////////
////////////////////////////////////////
 
////////////// HCSR04/////////////////////////////
/////////////////////////////////////////////////
long tiempo;
int disparador = 9;   // triger
int entrada = 8;      // echo
float distancia;
const int ledObstaculo = 26;
////////////////////////////////////
 
 
void setup()
  {
 
//////////////motor/////////////////////
////////////////////////////////////////
  //MOTOR B
  pinMode (IN3, OUTPUT);
  pinMode (IN4, OUTPUT);
  //MOTOR A
  pinMode (IN1, OUTPUT);
  pinMode (IN2, OUTPUT);
////////////////////////////////////////
///////////////////////////////////////
 
 
////////////hcsr04////////////////////
/////////////////////////////////////
  pinMode(disparador, OUTPUT);
  pinMode(entrada, INPUT);
  Serial.begin(9600);
 
///////////////////////////////////////
/////////////////////////////////////
}
 
void Derecha()            //El robot gira en sentido derecho.
{
  // Motor B
  digitalWrite(IN4, LOW);
  analogWrite(IN3, 200);
  //MOTOR A
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  }
void Izquierda()         //El robot gira en sentido izquierdo.
{
  // Motor B
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
  //MOTOR A
  digitalWrite(IN2, LOW);
  analogWrite(IN1, 200);
}
 
 
void Adelante()         //El robot va hacia adelante.
{
  // Motor B
  digitalWrite(IN4, LOW);
  analogWrite(IN3, 255);
  //MOTOR A
  digitalWrite(IN2, LOW);
  analogWrite(IN1, 255);
}
 
void Atras()          //El robot va hacia atrás.
{
  // Motor B
  digitalWrite(IN3, LOW);
  analogWrite(IN4, 255);
  //MOTOR A
  digitalWrite(IN1, LOW);
  analogWrite(IN2, 255);
}
 
 
void Parar()          //Robot para.
{
  // Motor B
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
  //MOTOR A
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
}
 
 
////////////////////////////////// RUTA DE PRUEBA ////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
 
 
void loop()
{
MedidaDistancia();
if(distancia <=30)
{
  SonidoLedObstaculo();
  delay(1000);
}
  else
{
  RutaMotor1();
 
}
 
delay(2000);
 
}
 
 
 
//////////////Void Ruta Motor 1 motores/////////////////////
//////////////////////////////////////////////
 
 
void RutaMotor1()
{
  Adelante();
  delay(5000);           //tiempo que esta funcionando Adelante
  Parar();
  delay(2000);          // tiempo que esta parado hasta la siguiente funcion
 
  Derecha();
  delay(1000);          //tiempo que esta funcionando Derecha
  Parar();
  delay(2000);         // tiempo que esta parado hasta la siguiente funcion
 
  Adelante();
  delay(5000);
  Parar();
  delay(2000);
 
  Derecha();
  delay(2000);
  Parar();
  delay(2000);
 
  Adelante();
  delay(5000);
  Parar();
  delay(2000);
 
  Izquierda();
  delay(1000);
  Parar();
  delay(2000);
 
  Adelante();
  delay(5000);
  Parar();
  delay(2000);
 
  Parar();
  delay(1000);
 
}
////////////////// VOID MEDID DISTANCIA hcsr04 //////////////////////
////////////////////////////////////////////////////////////////////
void SonidoLedObstaculo()
{
  if(distancia <= 30){
 
 {
   digitalWrite(ledObstaculo,HIGH); //Si el sensor mide una distancia más pequeña o igual a 30cm LED ON
   ObstaculoBuzzer();
   delay(1000);
  }
 
  delay(1000);
  }
  else{
    digitalWrite(ledObstaculo,LOW); //Sinó, apaga el LED
  }
}
 
void MedidaDistancia()
{
    // lanzamos un pequeño pulso para activar el sensor
  digitalWrite(disparador, HIGH);
  delayMicroseconds(10);
  digitalWrite(disparador, LOW);
 
  // medimos el pulso de respuesta
  tiempo = (pulseIn(entrada, HIGH)/2); // dividido por 2 por que es el 
                                       // tiempo que el sonido tarda
                                       // en ir y en volver
  // ahora calcularemos la distancia en cm
  // sabiendo que el espacio es igual a la velocidad por el tiempo
  // y que la velocidad del sonido es de 343m/s y que el tiempo lo 
  // tenemos en millonesimas de segundo
  distancia = float(tiempo * 0.0343);
  // y lo mostramos por el puerto serie una vez por segundo
  Serial.println(distancia);
  delay(1000);
}
void ObstaculoBuzzer()
{
  //generar tono de 440Hz durante 1000 ms
  tone(pinBuzzer, 150);
  delay(550);
  tone(pinBuzzer, 50);
  delay(700);
  tone(pinBuzzer, 325);
  delay(250);
  tone(pinBuzzer, 50);
  delay(600);
  tone(pinBuzzer, 670);
  delay(200);
  tone(pinBuzzer, 1125);
  delay(200);
  tone(pinBuzzer, 2500);
  delay(800);
  noTone(pinBuzzer);
}
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
 
[/quote]
 
 
Esto creo que se debe a la programacion realizada con los delay().
La solución sería realizar el mismo sketch pero con millis(), cosa que soy incapaz de realizar.
 
A continuacion pongo el sketch unicamente de los motores, realizada la programacion con delay(), que es lo que hay que pasar a millis().
Pero que soy incapaz...
 
[quote]
 
///////////////    DECLARACION PIN MOTORES         ////////////////
/////////////   PARA EL CONTROL DEL MOTOR CON L298N ///////////
 
//MOTOR B
int IN3 = 5;
int IN4 = 4;
//MOTOR A
int IN1 = 2;
int IN2 = 3;
 
//////////////////////////////////////////////
/////////////////////////////////////////////
 
 
 
void setup()
  {
  //MOTOR B
  pinMode (IN3, OUTPUT);
  pinMode (IN4, OUTPUT);
  //MOTOR A
  pinMode (IN1, OUTPUT);
  pinMode (IN2, OUTPUT);
}
 
void Derecha()
{
  // Motor B
  digitalWrite(IN4, LOW);
  analogWrite(IN3, 200);
  //MOTOR A
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  }
void Izquierda()
{
  // Motor B
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
  //MOTOR A
  digitalWrite(IN2, LOW);
  analogWrite(IN1, 200);
}
 
 
void Adelante()
{
  // Motor B
  digitalWrite(IN4, LOW);
  analogWrite(IN3, 255);
  //MOTOR A
  digitalWrite(IN2, LOW);
  analogWrite(IN1, 255);
}
 
void Atras()
{
  // Motor B
  digitalWrite(IN3, LOW);
  analogWrite(IN4, 255);
  //MOTOR A
  digitalWrite(IN1, LOW);
  analogWrite(IN2, 255);
}
 
 
void Parar()
{
  // Motor B
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
  //MOTOR A
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
}
 
 
////////////////////////////////// RUTA DE MOTOR ////////////////////////////////////
////////////////////////////////  RUTA DE PRUEBA  ////////////////////////////////
void loop() {
  Adelante();
  delay(5000);        //tiempo que esta funcionando Adelante
  Parar();
  delay(2000);        // tiempo que esta parado hasta la siguiente funcion
 
  Atras();
  delay(5000);        //tiempo que esta funcionando Atras
  Parar();
  delay(2000);
 
  Derecha();
  delay(5000);        //tiempo que esta funcionando Dereccha
  Parar();
  delay(2000);
 
  Izquierda();        //tiempo que esta funcionando Izquierda
  delay(5000);
  Parar();
  delay(2000);
 
  Parar();
  delay(1000);
 
}
 
///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

Pasar delay() a millis()

Publicado por Manuel L. (15 intervenciones) el 06/01/2018 14:13:53
Efectivamente, te sucede eso por usar delay. Esa función hace «hibernar» al Arduino, cuando debería estar comprobando periódicamente si hay obstáculos o no.

He preparado un código que hace lo que pides, solo que con temática diferente (menos entradas y salidas, básicamente). Si lo que te faltaba para implementar el programa con millis era la «lista estática» (hecha con array), probablemente, si quisieras hacer programas más complejos, te conviniese ojear los principios básicos de los Tipos Abstractos de Datos, así como los Tipos «Cola», «Pila» y «Listas». Al menos, en su versión estática.

Sin más, te dejo el código. Ocupa mucho, pero porque tiene mucho comentario.

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
/*************
 * SIN DELAY *
 *************/
 
 
/* Este programa realiza dos trabajos al mismo tiempo: el primero,
hacer parpadear un intermitente; el segundo, ejecutar una lista de
tareas. En este caso, se considera cada tarea terminada una vez se
acaba el tiempo que se supone lleva realizarla.

   La secuencia de una ejecucion es como sigue: no hay accion has-
ta que no se activa el pulsador de marcha. Una vez dado, se ejecu-
ta la lista de tareas. Mientras no esten terminadas, el piloto in-
termitente parpadeara con T=0,5s; y el pulsador de marcha se igno-
rara. Una vez se haya concluido, todo se apagara de nuevo. Por ca-
da tarea hay una luz indicadora de realizacion que permanecera en-
cendida el tiempo que dure dicha actividad. La secuencia se repite
tantas veces como se desee. */
 
 
/* ENTRADAS
   ======== */
 
#define E_MARCHA 2
 
 
/* SALIDAS
   ======= */
 
#define S_INTERMITENTE 3
#define S_ADELANTE 4
#define S_ATRAS 5
#define S_SONREIR 6
 
 
/* INFORMACION DEL ESTADO DEL SISTEMA
   ================================== */
 
// Informacion generica
boolean enMarcha = false; // Saber si hay tareas pendientes
long tActual = 0; // Llevar cuenta del tiempo transcurrido
 
// Informacion sobre el intermitente
#define T_INTERMITENCIA 625 // Tiempo de cambio: 625ms
long tUltimoCambio = 0; // Tiempo del ultimo cambio
boolean itmttOn = false; // ¿Esta el intermitente encendido?
 
// Lista de tareas: con sus identificadores de tareas, ...
#define TAREA_ADELANTE 0
#define TAREA_ATRAS 1
#define TAREA_SONREIR 2
// ... la lista propiamente dicha, y ...
#define NO_TAREAS 7 // Numero de tareas en la lista
byte lTareas[NO_TAREAS] = {
  TAREA_ADELANTE,
  TAREA_ATRAS,
  TAREA_SONREIR,
  TAREA_ATRAS,
  TAREA_ADELANTE,
  TAREA_SONREIR,
  TAREA_ADELANTE
};
// ... y llevar la cuenta sobre las tareas
long tInicioTarea = 0; // Tiempo de inicio de la tarea actual
byte noTareaActual = 0; // Numero de la tarea actual en la lista
 
 
/* FUNCIONES
   ========= */
 
void setup() { // Inicializar el programa
  pinMode(E_MARCHA,INPUT);
  pinMode(S_INTERMITENTE,OUTPUT);
  pinMode(S_ATRAS,OUTPUT);
  pinMode(S_SONREIR,OUTPUT);
}
 
 
/* Todo loop (ciclo) empieza leyendo las entradas (informacion del
entorno y recepcion de ordenes), para inmediatamente hacer aquello
que se desee teniendo en cuenta lo que se recuerda que sucede y lo
que las  entradas han contado. */
void leerEntradas() { // Poner al dia la informacion del estado
   if(enMarcha) tActual = millis(); // Toca cronometrar
   else // En reposo, pero... ¿toca trabajar?
      if(digitalRead(E_MARCHA) == HIGH) {
        enMarcha = true; // A trabajar, ...
        noTareaActual = 0; // ..., empezando por la primera tarea, y ...
        tInicioTarea = millis(); // ... y ya. ¡Crono andando!
      }
}
 
 
void trabajoParpadeo() { // Hacer que parpadee la salida
   // Comprobacion de si toca parpadear
   if(tActual - tUltimoCambio >= T_INTERMITENCIA) { // ¿ya toca?
     itmttOn = ! itmttOn; // Cambio de iluminacion
     tUltimoCambio = tActual; // Reiniciamos la cuenta
   }
   // Mostrar lo que sea que toque
   if(itmttOn) digitalWrite(S_INTERMITENTE,HIGH);
   else digitalWrite(S_INTERMITENTE,LOW);
}
 
 
void trabajoLTareas() { // Haciendo tareas
   // Seleccionar la tarea actual correspondiente
   byte tareaActual = lTareas[noTareaActual];
   if(tareaActual == TAREA_ADELANTE) irAdelante();
   else if(tareaActual == TAREA_ATRAS) irAtras();
   else if(tareaActual == TAREA_SONREIR) sonreir();
   else enMarcha = false; // Tipo de tarea desconocida. ¡Alto!
}
 
 
void irAdelante() {
   // Codigo de avance
   digitalWrite(S_ADELANTE,HIGH);
 
   // Tras avanzar, ¿se ha terminado la tarea?
   if(tActual - tInicioTarea > 2200) {
      digitalWrite(S_ADELANTE,LOW);
      siguienteTarea();
   }
}
 
 
void irAtras() {
   // Codigo de retroceso
   digitalWrite(S_ATRAS,HIGH);
 
   // Tras retroceder, ¿se ha terminado la tarea?
   if(tActual - tInicioTarea > 2200) {
      digitalWrite(S_ATRAS,LOW);
      siguienteTarea();
   }
}
 
 
void sonreir() {
   // Codigo de hacer sonar la sirena
   digitalWrite(S_SONREIR,HIGH);
 
   // Tras sonar la sirena, ¿se ha terminado la tarea?
   if(tActual - tInicioTarea > 500) {
      digitalWrite(S_SONREIR,LOW);
      siguienteTarea();
   }
}
 
 
void siguienteTarea() {
   // Pasar a la siguiente tarea
   ++noTareaActual;
   tInicioTarea = tActual;
 
   // Porque... ¿hay tarea, verdad?
   enMarcha = noTareaActual != NO_TAREAS;
}
 
 
void loop() {
  leerEntradas();
  if(enMarcha) {
     trabajoParpadeo();
     trabajoLTareas();
  }
}

Como habrás imaginado, el piloto intermitente equivale al control de obstáculos y la lista de tareas es una forma sencilla de escribir una ruta. Si me permites un consejo, te sugiero los siguientes ejercicios:
a) Conseguir el programa que deseas a partir del código de arriba (dificultad escasa).
b) Modificar el código para que las tareas puedan parametrizarse. No indicar solamente el sentido, sino también el tiempo que deseas que emplee en ese sentido (dificultad media).
c) Si encuentra un obstáculo, además de pitar, que espere cuatro segundos por si el obstáculo se va (ha detectado un viandante), y posteriormente reanude las tareas donde había quedado (dificultad elevada).
d) Si el obstáculo no se va, rodearlo si resulta sencillo, y si no pitar (dificultad elevada).
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Gorka

Pasar delay() a millis()

Publicado por Gorka (6 intervenciones) el 06/01/2018 17:28:52
Muchisimas gracias.
Ahora mismo me pongo a trabajar sobre ello a ver si saco algo en claro adaptado a lo mio.
Un gran saludo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar