Comunicacion Serial.Write con PC

Quiero crear un código que mueva un motor y que obtenga datos de dos sensores y enviarlos al ordenador para que me cree una grafica, la idea es que cada cierto tiempo envíe un array con varios datos de cada sensor para que se creen nubes de puntos y si es posible no moleste el movimiento del motor en gran medida. En total en cada envio se enviaría 21 datos de 4 bytes cada uno, y la frecuencia de envio pues entre 100-500 ms. El problema es que da igual que utilice Serial.Write o Serial.Print que el tiempo que tarda en enviar los datos es bastante significativo (a ojo unos 200ms) y se aprecia en el movimiento del motor (ya se por como funciona Arduino no puede hacer multitarea y siempre se va a notar). Mi pregunta es si sabéis cual es el problema y si conocéis alguna solución.

Dejo por aqui los codigos:

#include "HX711.h"

// Pines del motor
const int STEP_PIN = 3;   // Pin de pasos
const int DIR_PIN = 4;    // Pin de dirección

// Pines del HX711
const int HX711_DT = 2;   // Pin DT del HX711
const int HX711_SCK = 5;  // Pin SCK del HX711

// Variables de control
long motorPosition = 0; // Posición virtual del motor en pasos
unsigned long lastStepTime = 0; // Tiempo de la última transmisión del motor
int stepDelay = 500;             // Retardo inicial entre pasos (en µs)
unsigned long lastSerialTime = 0; // Tiempo de la última transmisión serial
int serialInterval = 200;   // Intervalo de transmisión serial (ms)

bool stepState = LOW;

// Instancia del HX711
HX711 scale;

// Número de lecturas del sensor
const int numReadings = 3;
long hx711Values[numReadings];

void setup() {
  // Configuración de pines del motor
  pinMode(STEP_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  digitalWrite(DIR_PIN, HIGH); // Configuramos dirección inicial

  // Inicialización de la comunicación serial
  Serial.begin(2000000);

  // Inicialización del sensor HX711
  scale.begin(HX711_DT, HX711_SCK);
  Serial.println("Iniciando HX711...");
  delay(1000);

  if (!scale.is_ready()) {
    Serial.println("ERROR: HX711 no está listo.");
    while (1);
  }
  Serial.println("HX711 listo.");
}

void loop() {
  // Tiempo actual
  unsigned long currentTime = micros();

  // Movimiento del motor
  if (currentTime - lastStepTime >= stepDelay) {
    lastStepTime = currentTime;
    stepMotor();
  }

  // Enviar datos por Serial cada 300 ms
  if (millis() - lastSerialTime >= serialInterval) {
    //lastSerialTime = millis();

    // Leer valores del sensor HX711
    for (int i = 0; i < numReadings; i++) {
      hx711Values[i] = scale.read();
    }

    // Enviar datos
    sendDataa();

    lastSerialTime = millis();
  }
}

void stepMotor() {
  stepState = !stepState; // Alternar entre HIGH y LOW
  digitalWrite(STEP_PIN, stepState);
  if (stepState == LOW) {
    motorPosition++; // Incrementar la posición virtual del motor
  }
}

void sendData() {
  // Enviar un delimitador para indicar el inicio de un nuevo paquete de datos
  Serial.write(0xFF);

  // Enviar la posición del motor (4 bytes)
  Serial.write((byte*)&motorPosition, 4);
  //sizeof(motorPosition)
  // Enviar los valores del sensor HX711 (10 lecturas de 4 bytes cada una)
  for (int i = 0; i < numReadings; i++) {
    Serial.write((byte*)hx711Values[i], 4);
  }
  //sizeof(hx711Values[i])
}

void sendDataa() {
  // Enviar un delimitador para indicar el inicio de un nuevo paquete de datos
  Serial.write(0xFF);

  // Enviar la posición del motor (4 bytes)
  Serial.write((byte*)&motorPosition, sizeof(motorPosition));

  // Enviar los valores del sensor HX711 (10 lecturas de 4 bytes cada una)
  Serial.write((byte*)hx711Values, sizeof(hx711Values));
}

El otro codigo, solo cambia la parte del "sendData"

#include "HX711.h"

// Pines del motor
const int STEP_PIN = 3;   // Pin de pasos
const int DIR_PIN = 4;    // Pin de dirección

// Pines del HX711
const int HX711_DT = 2;   // Pin DT del HX711
const int HX711_SCK = 5;  // Pin SCK del HX711

// Variables de control
long motorPosition = 0; // Posición virtual del motor en pasos
unsigned long lastStepTime = 0; // Tiempo de la última transmisión motor
int stepDelay = 500;             // Delay inicial entre pasos (en µs)
unsigned long lastSerialTime = 0; // Tiempo de la última transmisión serial
int serialInterval = 100;   // Intervalo de transmisión serial (ms)

bool stepState = LOW;

// Instancia del HX711
HX711 scale;

// Array para almacenar los valores del sensor
const int numReadings = 1;
long hx711Values[numReadings];
int currentReading = 0;

void setup() {
  // Configuración de pines del motor
  pinMode(STEP_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  digitalWrite(DIR_PIN, HIGH); // Configuramos dirección inicial

  // Inicialización de la comunicación serial
  Serial.begin(2000000);

  // Inicialización del sensor HX711
  scale.begin(HX711_DT, HX711_SCK);
  Serial.println("Iniciando HX711...");
  delay(1000);

  if (!scale.is_ready()) {
    Serial.println("ERROR: HX711 no está listo.");
    while (1);
  }
  Serial.println("HX711 listo.");
}

void loop() {
  // Tiempo actual 
  unsigned long currentTime = micros();

  // Movimiento del motor
  if (currentTime - lastStepTime >= stepDelay) {
    lastStepTime = currentTime;
    stepMotor();
  }

  // Lectura del sensor HX711                                  -----------------  ---------------
  /*
  if (scale.is_ready()) {
    hx711Values[currentReading] = scale.read();
    currentReading = (currentReading + 1) % numReadings;
  } else {
    Serial.println("HX711 no está listo.");
  }
  */

  // Enviar datos por Serial
  if (millis() - lastSerialTime >= serialInterval) {
    //lastSerialTime = millis();
    
    for (int i = 0; i < numReadings; i++) {
      hx711Values[i] = scale.read();
    }

    sendData();
    
    lastSerialTime = millis();
  }
}

void stepMotor() {
  stepState = !stepState; // Alternar entre HIGH y LOW
  digitalWrite(STEP_PIN, stepState);
  if (stepState == LOW) {
    motorPosition++; // Incrementar la posición virtual del motor
  }
  /*
  digitalWrite(STEP_PIN, HIGH);
  delayMicroseconds(10); // Duración del pulso
  digitalWrite(STEP_PIN, LOW);
  motorPosition++; // Actualizamos la posición
  */
}

void sendData() {
  // Enviar posición del motor
  //Serial.print("Posicion (pasos): ");
  Serial.println(motorPosition); // Enviamos la posición con 4 decimales

  // Enviar valores del sensor HX711
  //Serial.print("Valores HX711: ");
  for (int i = 0; i < numReadings; i++) {
    Serial.print(hx711Values[i]);
    //if (i < numReadings - 1) {
    //  Serial.print(", ");
    //}
  }
  //Serial.println();
  Serial.println();
}

Su publicacion se MUEVE a su ubicacion actual ya que es mas adecuada.

El HX711 es lento, si no lo tienes a máxima velocidad 80Hz estará a su valor por defecto 10Hz o sea 100mseg por muestra.
Debes hacer que esa operación sea no bloqueante. Que tome muestras pero que lo haga independientemente de lo demás.
Concentrate en medir con micros() antes y despues de la toma de datos de

Serial.print(hx711Values[i]);

esta operación es la que te genera la demora.
Ahora lo estudio y te sugiero cómo hacerlo

Esto lo cambie por un array

// Leer valores del sensor HX711
  if (!dataReady && millis() - lastSerialTime >= serialInterval) {
    lastSerialTime = millis();
    hx711Values[currentReading] = scale.read(); // Leer valor del HX711
    currentReading++;

    if (currentReading >= numReadings) {
      dataReady = true;          // Activar flag cuando se completen las lecturas
      currentReading = 0;        // Reiniciar índice de lectura
    }
  }

entonces cuando tenes los valores los envias y no perdes tiempo esperando a obtenerlos.

 // Enviar datos si están listos
  if (dataReady) {
    sendData();
    dataReady = false; // Resetear el flag después de enviar los datos
  }

El código completo

#include "HX711.h"

// Pines del motor
const int STEP_PIN = 3;   // Pin de pasos
const int DIR_PIN = 4;    // Pin de dirección

// Pines del HX711
const int HX711_DT = 2;   // Pin DT del HX711
const int HX711_SCK = 5;  // Pin SCK del HX711

// Variables de control
long motorPosition = 0;       // Posición virtual del motor en pasos
unsigned long lastStepTime = 0; // Tiempo de la última transmisión del motor
int stepDelay = 500;             // Retardo inicial entre pasos (en µs)
unsigned long lastSerialTime = 0; // Tiempo de la última transmisión serial
int serialInterval = 200;         // Intervalo de transmisión serial (ms)

bool stepState = LOW;

// Instancia del HX711
HX711 scale;

// Variables para lecturas
const int numReadings = 10;       // Número de lecturas por bloque
long hx711Values[numReadings];    // Almacenamiento de lecturas
int currentReading = 0;           // Índice de la lectura actual
bool dataReady = false;           // Flag para indicar que las lecturas están completas

void setup() {
  // Configuración de pines del motor
  pinMode(STEP_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  digitalWrite(DIR_PIN, HIGH); // Configuramos dirección inicial

  // Inicialización de la comunicación serial
  Serial.begin(2000000);

  // Inicialización del sensor HX711
  scale.begin(HX711_DT, HX711_SCK);
  Serial.println("Iniciando HX711...");
  delay(1000);

  if (!scale.is_ready()) {
    Serial.println("ERROR: HX711 no está listo.");
    while (1);
  }
  Serial.println("HX711 listo.");
}

void loop() {
  // Tiempo actual
  unsigned long currentTime = micros();

  // Movimiento del motor
  if (currentTime - lastStepTime >= stepDelay) {
    lastStepTime = currentTime;
    stepMotor();
  }

  // Leer valores del sensor HX711
  if (!dataReady && millis() - lastSerialTime >= serialInterval) {
    lastSerialTime = millis();
    hx711Values[currentReading] = scale.read(); // Leer valor del HX711
    currentReading++;

    if (currentReading >= numReadings) {
      dataReady = true;          // Activar flag cuando se completen las lecturas
      currentReading = 0;        // Reiniciar índice de lectura
    }
  }

  // Enviar datos si están listos
  if (dataReady) {
    sendData();
    dataReady = false; // Resetear el flag después de enviar los datos
  }
}

void stepMotor() {
  stepState = !stepState; // Alternar entre HIGH y LOW
  digitalWrite(STEP_PIN, stepState);
  if (stepState == LOW) {
    motorPosition++; // Incrementar la posición virtual del motor
  }
}

void sendData() {
  // Enviar un delimitador para indicar el inicio de un nuevo paquete de datos
  Serial.write(0xFF);

  // Enviar la posición del motor (4 bytes)
  Serial.write((byte*)&motorPosition, sizeof(motorPosition));

  // Enviar los valores del sensor HX711 (10 lecturas de 4 bytes cada una)
  Serial.write((byte*)hx711Values, sizeof(hx711Values));
}

Coincide el tiempo de espera con la frecuencia de 10 hz que comentas. Pensaba que era un problema de la comunicación y no tanto de los sensores, pero esta equivocado... He visto que se puede aumentar la frecuencia pero acosta de la precisión, en mi caso no merece la pena.
De todas formas, muchas gracias por la aclaración!!! :grin:

Ciertamente pero no me digas que hacer un ciclo que toma 10 lecturas y tarda 100mseg por lectura totalizando 1000 mseg es lo mismo que yo te he hecho.
El mío tarda individualmente lo mismo así que el tiempo de envío será de 100mseg mas todo lo demás, digamos a groso modo 20mseg mas (no hice cuentas).
Si no te gusta, esta opción existe uno de Analog Devices mas caro por cierto que tiene una taza de 1000hz si mal recuerdo.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.