Proyecto de mesa sísmica: Motor se ralentiza al conectar acelerómetro por I2C

Hola a todos.

Estoy realizando un proyecto de mesa sísmica utilizando una placa ESP32 D1 R32.

Consiste en utilizar un motor NEMA17 que mueve una estructura, a la cual se le conectan unos acelerómetros MPU9250 para tomar algunas medidas y enviarlas a Thingspeak.

Creo que tanto el montaje como el conexionado de los componentes lo tengo bien hecho, pero el problema lo tengo en el código que es donde menos conocimiento tengo, la verdad.

Al principio he creado los códigos de los distintos actuadores y sensores por separado para probar y que funcionen de la manera que quiero y todo bien. Sin embargo cuando uno todo en el mismo código comienza a darme problemas.

Añado código y os comento:


//Librerías
#include <AccelStepper.h>   
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <MPU9250.h>
#include <WiFi.h>
#include <ThingSpeak.h>


//Pines de la placa y constantes
#define pinDIR 26   
#define pinPUL 25
#define tipoMotor 1
#define FREC 1        //Valor de Frecuencia a introducir en Hz


//WiFi
const char* ssid = "xxxxxx"; //const char para que estos valores no se puedan modificar
const char* password = "xxxxxx";

//ThingSpeak
unsigned long channelID = xxxxxx;
const char* WriteAPIKey = "xxxxxx";

//Objetos 
AccelStepper motor = AccelStepper(tipoMotor, pinPUL, pinDIR);
LiquidCrystal_I2C lcd(0x27,16,2);
MPU9250 IMU1(Wire , 0x68);
MPU9250 IMU2(Wire , 0x69);      
WiFiClient Client; 

void setup() { //Código que se ejecuta una vez
  
  motor.setMaxSpeed(1000);    //Velocidad máxima
  motor.setSpeed(FREC*200);   //Velocidad en pps (pulsos por segundo) 2Hz*200 pulsos/vuelta = 400

  lcd.init();
  lcd.backlight();

  Serial.begin(9600);           //Inicializa puerto serie a 9600 baudios
  IMU1.begin();                  //Inicializa el acelerómetro (objeto llamado IMU)
  IMU2.begin();

  WiFi.begin(ssid,password);

  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print("Conectando...");
  }
  Serial.println("WiFi conectado");

  ThingSpeak.begin(Client);
}

void loop() { //Código que se repite
                  
  motor.runSpeed();
                                

  lcd.setCursor(0,0); //Pone el cursor en la posición indicada. La pantalla es de 16x2 (Fila 0-15, Columna 0-1).
  lcd.print("Frecuencia:"); 
  lcd.setCursor(11,0); 
  lcd.print(FREC);
  lcd.setCursor(14,0); 
  lcd.print("Hz");
                            
  IMU1.readSensor();   //Lee todos los valores de los sensores del MPU1         
  IMU2.readSensor();   //Lee todos los valores de los sensores del MPU2         

  //Código que muestra los valores del acelerómetro en los tres ejes en m/s^2

  Serial.print("Acelerómetro1 Eje X: ");   
  Serial.print(IMU1.getAccelX_mss(), 3);     // el 3 indica el número de decimales
  Serial.print("Acelerómetro1 Eje Y: ");
  Serial.print(IMU1.getAccelY_mss(), 3);
  Serial.print("Acelerómetro1 Eje Z: ");
  Serial.println(IMU1.getAccelZ_mss(), 3); 

  Serial.print("Acelerómetro2 Eje X: ");   
  Serial.print(IMU2.getAccelX_mss(), 3);     // el 3 indica el número de decimales
  Serial.print("Acelerómetro2 Eje Y: ");
  Serial.print(IMU2.getAccelY_mss(), 3);
  Serial.print("Acelerómetro2 Eje Z: ");
  Serial.println(IMU2.getAccelZ_mss(), 3); 

  //Para enviar los valores a Thingspeak (NO FUNCIONA. VER COMO ENVIAR VALORES DE LAS FUNCIONES A VARIABLES)

  //float Acel_X = (IMU.getAccelX_mss(), 3);
  //float Acel_Y = (IMU.getAccelY_mss(), 3);
  //float Acel_Z = (IMU.getAccelZ_mss(), 3); 
  
  //ThingSpeak.setField(1,Acel_X);
  //ThingSpeak.setField(2,Acel_Y);
  //ThingSpeak.setField(3,Acel_Z);

  //Código que muestra los valores  del magnetómetro en los tres ejes en microTeslas
  
 
  Serial.println("    ");  //Espacios para separar los valores en el monitor serie
  Serial.println("    ");
  
  delay(3000);     //Retardo para tomar las muestras del sensor cada 3 segundos

  ThingSpeak.writeFields(channelID,WriteAPIKey);
  Serial.println("Datos enviados a ThingSpeak");
  //delay(14000); //Retardo ya que thingspeak recoge los datos cada 14seg ¿necesario?

}

El problema principal es que al ejecutar todo el motor no gira correctamente. Sé que el problema está en el delay (que podría omitir) pero también debido a los serial. Eliminando el delay y sustituyendo la parte del código del lcd que hay en el loop() en el setup() me funcionaba bien (esto antes de añadir la parte de WiFi y ThingSpeak).

¿Hay alguna opción de "independizar" el motor.runSpeed(); para que no interfiera en el bucle del loop()? He probado a meterlo en un bulce infinito con while(1) pero con esto se detiene todo el programa.

Por favor, ¿alguien puede arrojarme un poco de luz en el tema? Gracias!!

Ok. Veo que luego dices haber eliminado el delay() antes de añadir el WIFI y ThingSpeak.
este

delay(3000);

debe desaparecer.
Usa millis(). Ahora te indico cómo.
Debes darle prioridad a secciones de tu código.
No hace falta estar viendo en cada loop datos del Acelerómetro o si?
Eres libre de modificar los tiempos indicados a los que te plazcan.

#include <Arduino.h>

//Librerías
#include <AccelStepper.h>   
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <MPU9250.h>
#include <WiFi.h>
#include <ThingSpeak.h>


//Pines de la placa y constantes
#define pinDIR 26   
#define pinPUL 25
#define tipoMotor 1
#define FREC 1        //Valor de Frecuencia a introducir en Hz


//WiFi
const char* ssid = "xxxxxx"; //const char para que estos valores no se puedan modificar
const char* password = "xxxxxx";

//ThingSpeak
unsigned long channelID = xxxxxx;
const char* WriteAPIKey = "xxxxxx";

//Objetos 
AccelStepper motor = AccelStepper(tipoMotor, pinPUL, pinDIR);
LiquidCrystal_I2C lcd(0x27,16,2);
MPU9250 IMU1(Wire , 0x68);
MPU9250 IMU2(Wire , 0x69);      
WiFiClient Client; 

// millis()
unsigned long timeThingSpeak, timeLecturas;

void setup() { //Código que se ejecuta una vez
  
  motor.setMaxSpeed(1000);    //Velocidad máxima
  motor.setSpeed(FREC*200);   //Velocidad en pps (pulsos por segundo) 2Hz*200 pulsos/vuelta = 400

  lcd.init();
  lcd.backlight();

  Serial.begin(9600);           //Inicializa puerto serie a 9600 baudios
  IMU1.begin();                  //Inicializa el acelerómetro (objeto llamado IMU)
  IMU2.begin();

  WiFi.begin(ssid,password);

  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print("Conectando...");
  }
  Serial.println("WiFi conectado");
  ThingSpeak.begin(Client);
}

void loop() { //Código que se repite
                  
  motor.runSpeed();
                                

  lcd.setCursor(0,0); //Pone el cursor en la posición indicada. La pantalla es de 16x2 (Fila 0-15, Columna 0-1).
  lcd.print("Frecuencia:"); 
  lcd.setCursor(11,0); 
  lcd.print(FREC);
  lcd.setCursor(14,0); 
  lcd.print("Hz");

  if (millis() - timeLecturas > 1000UL) {
      IMU1.readSensor();   //Lee todos los valores de los sensores del MPU1         
      IMU2.readSensor();   //Lee todos los valores de los sensores del MPU2         

      //Código que muestra los valores del acelerómetro en los tres ejes en m/s^2

      Serial.print("Acelerómetro1 Eje X: ");   
      Serial.print(IMU1.getAccelX_mss(), 3);     // el 3 indica el número de decimales
      Serial.print("Acelerómetro1 Eje Y: ");
      Serial.print(IMU1.getAccelY_mss(), 3);
      Serial.print("Acelerómetro1 Eje Z: ");
      Serial.println(IMU1.getAccelZ_mss(), 3); 

      Serial.print("Acelerómetro2 Eje X: ");   
      Serial.print(IMU2.getAccelX_mss(), 3);     // el 3 indica el número de decimales
      Serial.print("Acelerómetro2 Eje Y: ");
      Serial.print(IMU2.getAccelY_mss(), 3);
      Serial.print("Acelerómetro2 Eje Z: ");
      Serial.println(IMU2.getAccelZ_mss(), 3); 
      timeLecturas = millis();
  }
  //Para enviar los valores a Thingspeak (NO FUNCIONA. VER COMO ENVIAR VALORES DE LAS FUNCIONES A VARIABLES)

  //float Acel_X = (IMU.getAccelX_mss(), 3);
  //float Acel_Y = (IMU.getAccelY_mss(), 3);
  //float Acel_Z = (IMU.getAccelZ_mss(), 3); 
  
  //ThingSpeak.setField(1,Acel_X);
  //ThingSpeak.setField(2,Acel_Y);
  //ThingSpeak.setField(3,Acel_Z);

  //Código que muestra los valores  del magnetómetro en los tres ejes en microTeslas
  
 
  Serial.println("    ");  //Espacios para separar los valores en el monitor serie
  Serial.println("    ");
  
  //delay(3000);     //Retardo para tomar las muestras del sensor cada 3 segundos
  if (millis() - timeThingSpeak > 3000UL) {
      ThingSpeak.writeFields(channelID,WriteAPIKey);
      Serial.println("Datos enviados a ThingSpeak");
      timeThingSpeak = millis();
  }
  
  //delay(14000); //Retardo ya que thingspeak recoge los datos cada 14seg ¿necesario?

}

1 Like

Hola Surbyte, gracias por responder.

He probado el código con los cambios que has indicado pero el motor sigue sin girar correctamente. No gira a velocidad constante, sino que se va interrumpiendo en algunos pasos.

He modificado el código con tus cambios y también lo he organizado con dos funciones, pero sigue igual. No sé si al meter las funciones cambia algo de la parte de código que has añadido tú.

//Librerías
#include <AccelStepper.h>   
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <MPU9250.h>
#include <WiFi.h>
#include <ThingSpeak.h>


//Pines de la placa y constantes
#define pinDIR 26   
#define pinPUL 25
#define tipoMotor 1
#define FREC 1.2        //Valor de Frecuencia a introducir en Hz

//WiFi
const char* ssid = "JesusLC"; //const char para que estos valores no se puedan modificar
const char* password = "12si450v";

//ThingSpeak
unsigned long channelID = 1567081;
const char* WriteAPIKey = "J0FWE60A9NQ406FM";


//Objetos 
AccelStepper motor = AccelStepper(tipoMotor, pinPUL, pinDIR);
LiquidCrystal_I2C lcd(0x27,16,2);

MPU9250 IMU1 (Wire , 0x68);
MPU9250 IMU2 (Wire , 0x69);     

WiFiClient Client; 

// millis()
unsigned long timeThingSpeak, timeLecturas;

void setup() {

  motor.setMaxSpeed(1000);    //Velocidad máxima
  motor.setSpeed(FREC*200);   //Velocidad en pps (pulsos por segundo) Ej: 2Hz*200 pulsos/vuelta = 400pps

  lcd.init();                 
  lcd.backlight(); 
  lcd.setCursor(0,0); //Pone el cursor en la posición indicada. La pantalla es de 16x2 (Fila 0-15, Columna 0-1).
  lcd.print("Frecuencia:"); 
  lcd.setCursor(11,0); 
  lcd.print(FREC);
  lcd.setCursor(14,0); 
  lcd.print("Hz");        

  Serial.begin(9600);   
       
  IMU1.begin();                  
  IMU2.begin();                  
  
  WiFi.begin(ssid,password);      

  while (WiFi.status() != WL_CONNECTED){
  delay(500);
  Serial.println("Conectando...");
  }
  Serial.println("WiFi conectado");
  
  ThingSpeak.begin(Client);

}

void loop() {

  motor.runSpeed();  

  if (millis() - timeLecturas > 1000UL) {

  IMU1.readSensor();   //Lee todos los valores del sensor1    
  IMU2.readSensor();   //Lee todos los valores del sensor2 


  leerAC1();          //Llamada a la función leerAC1
  leerAC2();          //Llamada a la función leerAC2
  
  timeLecturas = millis();
  }
  
  Serial.println("    ");
  Serial.println("    ");
  
  if (millis() - timeThingSpeak > 3000UL) {
      ThingSpeak.writeFields(channelID,WriteAPIKey);
      Serial.println("Datos enviados a ThingSpeak");
      timeThingSpeak = millis();
  }

}

void leerAC1(){   //Función que toma los valores del acelerómetro1 y los envía a Thingspeak

  float acX1 = IMU1.getAccelX_mss(); 
  float acY1 = IMU1.getAccelY_mss(); 
  float acZ1 = IMU1.getAccelZ_mss(); 

  Serial.print("Acelerómetro1 eje X: ");   
  Serial.println(acX1);
  Serial.print("Acelerómetro1 eje Y: ");   
  Serial.println(acY1);
  Serial.print("Acelerómetro1 eje Z: ");   
  Serial.println(acZ1);
 
  ThingSpeak.setField(1,acX1);  
  ThingSpeak.setField(2,acY1);  
  ThingSpeak.setField(3,acZ1); 
  
}

void leerAC2(){   //Función que toma los valores del acelerómetro2 y los envía a Thingspeak

  float acX2 = IMU2.getAccelX_mss(); 
  float acY2 = IMU2.getAccelY_mss(); 
  float acZ2 = IMU2.getAccelZ_mss(); 

  Serial.print("Acelerómetro2 eje X: ");   
  Serial.println(acX2);
  Serial.print("Acelerómetro2 eje Y: ");   
  Serial.println(acY2);
  Serial.print("Acelerómetro2 eje Z: ");   
  Serial.println(acZ2);


  ThingSpeak.setField(4,acX2);  
  ThingSpeak.setField(5,acY2);  
  ThingSpeak.setField(6,acZ2);
}

Realmente no necesito que se muestren los datos por el monitor serie, sólo que los valores recogidos por los acelerómetros se envíen a thingspeak, por lo que podría eliminar los print de las funciones. He probado a eliminarlos pero continúa el motor igual.

Otro cambio que he probado es poner toda la programación del LCD en el setup para que esos print no interfieran en el bucle y provoquen retardos, pero tampoco he dado con la tecla así.

¿A qué te refieres con darle prioridad a secciones del código?

Creo que sobre la teoría es un código bastante sencillo: simplemente que un motor gire constante y a la vez se recojan valores de un sensor (acelerómetro), y me frustra ver que no lo consigo.

Gracias.

En estos casos yo hago STOP al código en curso y me concentro en el problema.
Tu problema es la velocidad constante, asi que trabajemos al revés.
Primero haz que el motor gire a velocidad constante y luego vamos introduciendo partes del código necesarias para tener las demas funcionalidades.
Asi que olvida este código y vuelve a lo mas simple.
Motor a Velocidad constante.
Si funciona entonces de a poco introduce otras cosas.

1 Like

Sí, esa ha sido mi idea desde el comienzo. Ir probando los sensores individualmente y después juntando el código.

#include <AccelStepper.h>   
#include <LiquidCrystal_I2C.h>
#include <MPU9250.h>

#define pinDIR 26   
#define pinPUL 25
#define tipoMotor 1
#define FREC 2        //Valor de Frecuencia a introducir en Hz

AccelStepper motor = AccelStepper(tipoMotor, pinPUL, pinDIR);
LiquidCrystal_I2C lcd(0x27,16,2);
MPU9250 IMU1 (Wire , 0x68);
MPU9250 IMU2 (Wire , 0x69);  

void setup() {

  motor.setMaxSpeed(1000);    //Velocidad máxima
  motor.setSpeed(FREC*200);   //Velocidad en pps (pulsos por segundo) Ej: 2Hz*200 pulsos/vuelta = 400pps

  lcd.init();                 
  lcd.backlight(); 
  lcd.setCursor(0,0); //Pone el cursor en la posición indicada. La pantalla es de 16x2 (Fila 0-15, Columna 0-1).
  lcd.print("Frecuencia:"); 
  lcd.setCursor(11,0); 
  lcd.print(FREC);
  lcd.setCursor(14,0); 
  lcd.print("Hz");  

  IMU1.begin();                  
  IMU2.begin();  
}

void loop() {

  motor.runSpeed();  

  IMU1.readSensor();   //Lee todos los valores del sensor1    
  IMU2.readSensor();   //Lee todos los valores del sensor2 
}

Hasta aquí todo funciona correctamente: el motor gira a la velocidad indicada (400pps), la pantalla muestra la frecuencia y supuestamente (porque no puedo comprobarlo) los dos acelerómetros recogen los datos.

El problema de la velocidad constante viene cuando se coloca en el loop() algún print. Esto lo he comprobado porque con el mismo código de arriba pero colocando en el loop esto:

 lcd.setCursor(0,0); //Pone el cursor en la posición indicada. La pantalla es de 16x2 (Fila 0-15, Columna 0-1).
  lcd.print("Frecuencia:"); 
  lcd.setCursor(11,0); 
  lcd.print(FREC);
  lcd.setCursor(14,0); 
  lcd.print("Hz");  

ya deja de funcionar correctamente el motor.

De hecho, hasta aquí me funciona perfectamente, añadiendo ya las librerías de WiFi y Thingspeak:

#include <AccelStepper.h>   
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <MPU9250.h>
#include <WiFi.h>
#include <ThingSpeak.h>

#define pinDIR 26   
#define pinPUL 25
#define tipoMotor 1
#define FREC 2.4        //Valor de Frecuencia a introducir en Hz

//WiFi
const char* ssid = "xxxxxxxx"; //const char para que estos valores no se puedan modificar
const char* password = "xxxxxxxx";

//ThingSpeak
unsigned long channelID = xxxxxxx;
const char* WriteAPIKey = "xxxxxx";

AccelStepper motor = AccelStepper(tipoMotor, pinPUL, pinDIR);
LiquidCrystal_I2C lcd(0x27,16,2);
MPU9250 IMU1 (Wire , 0x68);
MPU9250 IMU2 (Wire , 0x69);  
WiFiClient Client; 


void setup() {

  motor.setMaxSpeed(1000);    //Velocidad máxima
  motor.setSpeed(FREC*200);   //Velocidad en pps (pulsos por segundo) Ej: 2Hz*200 pulsos/vuelta = 400pps

  lcd.init();                 
  lcd.backlight(); 
  lcd.setCursor(0,0); //Pone el cursor en la posición indicada. La pantalla es de 16x2 (Fila 0-15, Columna 0-1).
  lcd.print("Frecuencia:"); 
  lcd.setCursor(11,0); 
  lcd.print(FREC);
  lcd.setCursor(14,0); 
  lcd.print("Hz");  

  IMU1.begin();                  
  IMU2.begin(); 
  WiFi.begin(ssid,password);  
  ThingSpeak.begin(Client);
}

void loop() {

  motor.runSpeed();  

  IMU1.readSensor();   //Lee todos los valores del sensor1    
  IMU2.readSensor();   //Lee todos los valores del sensor2 

  //float acX1 = IMU1.getAccelX_mss(); 
  //ThingSpeak.setField(1,acX1); 
  //ThingSpeak.writeFields(channelID,WriteAPIKey);
}

Cuando añado las tres últimas líneas que hay comentadas:

  float acX1 = IMU1.getAccelX_mss(); 
  ThingSpeak.setField(1,acX1); 
  ThingSpeak.writeFields(channelID,WriteAPIKey);

es cuando deja de funcionar, incluso añadiendo sólo la última.

Por tanto creo que una solución sería (que no sé si es posible) independizar el motor.runSpeed(); de alguna manera para que no se mezcle en el loop() con el resto del código en bucle. Meter sólo esa línea en un bucle infinito o algo así...

Tengo la sensación de que al final será más sencillo de todo lo que estoy pensando. :thinking:

Que raro lo que comentas porque si algo tiene de ventajoso usar AccelStepper es que se trata de una rutina non-blocking.
Lo que demuestra que lo demás estar bloqueando duramente el loop.
Vamos a medir cuantos milisegundos consumen estas tres lineas.
Ya sabemos que el stepper funcionará mal pero tenemos que establecer que ocurre y luego por mas que midamos algo negativo tomar o pensar en alguna solución.

Analizando en detalle me surge una duda con tu inicialización del objeto AccelStepper.
Segun los ejemplos en lugar de :

#define pinDIR       26   
#define pinPUL      25
#define tipoMotor 1
AccelStepper motor = AccelStepper(tipoMotor, pinPUL, pinDIR);

debes poner

AccelStepper motor (AccelStepper::DRIVER, pinPUL, pinDIR);

Prueba a ver si cambia el comportamiento.

1 Like

He probado a cambiar el código que has indicado pero sigue funcionando exactamente igual.
Creo que es similar poner el 1 o DRIVER, ya que ambos hacen referencia a lo mismos según la librería. Por cierto, el driver que estoy utilizando es el TB6600, aunque creo que eso es indiferente.

Ahora bien, lo que acabo de ver justo en la página de la librería es lo siguiente:

Caution: DRIVER implements a blocking delay of minPulseWidth microseconds (default 1us) for each step. You can change this with setMinPulseWidth().
He probado a poner esa función en el código tanto en el setup como en el loop pero todo sigue igual. He puesto un tiempo de 20 microseg.

He creado unas variables para medir con millis() el tiempo entre las tres líneas (espero haberlo hecho bien):

#include <AccelStepper.h>   
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <MPU9250.h>
#include <WiFi.h>
#include <ThingSpeak.h>

#define pinDIR 26   
#define pinPUL 25
//#define tipoMotor 1
#define FREC 1        //Valor de Frecuencia a introducir en Hz

//WiFi
const char* ssid = "xxxxx"; //const char para que estos valores no se puedan modificar
const char* password = "xxxxxxx";

//ThingSpeak
unsigned long channelID = xxxxxxxx;
const char* WriteAPIKey = "xxxxxxxxx";

AccelStepper motor (AccelStepper::DRIVER, pinPUL, pinDIR);
LiquidCrystal_I2C lcd(0x27,16,2);
MPU9250 IMU1 (Wire , 0x68);
MPU9250 IMU2 (Wire , 0x69);  
WiFiClient Client; 

unsigned long tiempo1 = 0;
unsigned long tiempo2 = 0;
unsigned long diferenciaTiempo = 0;

void setup() {

  motor.setMaxSpeed(1000);    //Velocidad máxima
  motor.setSpeed(FREC*200);   //Velocidad en pps (pulsos por segundo) Ej: 2Hz*200 pulsos/vuelta = 400pps
  motor. setMinPulseWidth(20);


  lcd.init();                 
  lcd.backlight(); 
  lcd.setCursor(0,0); //Pone el cursor en la posición indicada. La pantalla es de 16x2 (Fila 0-15, Columna 0-1).
  lcd.print("Frecuencia:"); 
  lcd.setCursor(11,0); 
  lcd.print(FREC);
  lcd.setCursor(14,0); 
  lcd.print("Hz");  
  
  Serial.begin(9600);
  IMU1.begin();                  
  IMU2.begin(); 
  WiFi.begin(ssid,password);  
  ThingSpeak.begin(Client);
}

void loop() {

  motor.runSpeed();  

  IMU1.readSensor();   //Lee todos los valores del sensor1    
  IMU2.readSensor();   //Lee todos los valores del sensor2 

  tiempo1 = millis();
  
  float acX1 = IMU1.getAccelX_mss(); 
  ThingSpeak.setField(1,acX1); 

  ThingSpeak.writeFields(channelID,WriteAPIKey);
  Serial.println("Datos enviados a ThingSpeak");

tiempo2 = millis();
diferenciaTiempo = tiempo2 - tiempo1;
Serial.println(tiempo1);
Serial.println(tiempo2);
Serial.print("La diferencia de tiempo (en ms) es: ");
Serial.println(diferenciaTiempo);
}```
Y estos datos son los que marca el monitor serie:

02:01:36.649 -> 3989
02:01:36.649 -> 3989
02:01:36.649 -> La diferencia de tiempo (en ms) es: 0
02:01:36.827 -> Datos enviados a ThingSpeak
02:01:36.827 -> 4189
02:01:36.874 -> 4189
02:01:36.874 -> La diferencia de tiempo (en ms) es: 0
02:01:37.390 -> Datos enviados a ThingSpeak
02:01:37.390 -> 4389
02:01:37.437 -> 4766
02:01:37.437 -> La diferencia de tiempo (en ms) es: 377
02:01:38.233 -> Datos enviados a ThingSpeak
02:01:38.233 -> 4966
02:01:38.233 -> 5568
02:01:38.233 -> La diferencia de tiempo (en ms) es: 602
02:01:39.218 -> Datos enviados a ThingSpeak
02:01:39.218 -> 5768
02:01:39.265 -> 6571
02:01:39.265 -> La diferencia de tiempo (en ms) es: 803
02:01:40.343 -> Datos enviados a ThingSpeak
02:01:40.343 -> 6771
02:01:40.343 -> 7682
02:01:40.343 -> La diferencia de tiempo (en ms) es: 911
02:01:41.135 -> Datos enviados a ThingSpeak
02:01:41.135 -> 7882
02:01:41.135 -> 8480
02:01:41.135 -> La diferencia de tiempo (en ms) es: 598
02:01:41.932 -> Datos enviados a ThingSpeak
02:01:41.932 -> 8680
02:01:41.979 -> 9292
02:01:41.979 -> La diferencia de tiempo (en ms) es: 612
02:01:42.541 -> Datos enviados a ThingSpeak
02:01:42.541 -> 9492
02:01:42.541 -> 9886
02:01:42.541 -> La diferencia de tiempo (en ms) es: 394
02:01:43.345 -> Datos enviados a ThingSpeak
02:01:43.345 -> 10086
02:01:43.345 -> 10686
02:01:43.345 -> La diferencia de tiempo (en ms) es: 600
02:01:44.142 -> Datos enviados a ThingSpeak
02:01:44.142 -> 10886
02:01:44.188 -> 11489
02:01:44.188 -> La diferencia de tiempo (en ms) es: 603
02:01:44.938 -> Datos enviados a ThingSpeak
02:01:44.938 -> 11689
02:01:44.985 -> 12292
02:01:44.985 -> La diferencia de tiempo (en ms) es: 603

Son diferencias importantes. 600 mseg incluso hay momentos de casi 1seg. Bueno.
Por otro lado hay codigos con delay(1000) y pareceria que no pierde la velocidad.
Algo pasa y no se que es.