LabVIEW Interface for Arduino Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

why do I Receiving inconsistent Serial Data in LabVIEW while make a feedback control?

I'm currently working on a consolidometer system that communicates with an Arduino via LabVIEW. The system takes measurements of axial pressure, distance, and pore pressure, which are sent over serial to LabVIEW for real-time monitoring and control. However, I'm facing a significant issue with the data acquisition:

  • Every other reading received in LabVIEW appears as zero across all channels (weight, axial pressure, distance, pore pressure), alternating with valid data. As a result, the graphs in LabVIEW fluctuate between real values and zero, making it impossible to get a stable reading.

I’ve verified that:

  1. The Arduino serial output is continuous and stable, without intermittent zero values when monitored directly.
  2. The baud rate, data parsing, and byte count settings in LabVIEW match the Arduino configuration.

 

Are there recommended techniques for handling serial data in LabVIEW to ensure that only complete, non-zero readings are processed?

 

Any advice on troubleshooting this issue would be very helpful!

Thank you!

 

this is my arduino program:

#include <HX711.h>

// Definisikan pin untuk motor stepper
const int stepPin = 5;
const int dirPin = 2;
const int enPin = 8;

// Definisikan pin untuk HX711
const int hx711_data_pin = 4;
const int hx711_clock_pin = 3;

// Inisialisasi HX711
HX711 scale;

float Q_raw = 0;
float Q = 0;
float Q_cal = -44.60; // Gunakan nilai kalibrasi yang diperoleh
float Z_off = 0; // Atur offset nol setelah kalibrasi
float Q_filtered = 0; // Nilai yang sudah difilter

const int numReadings = 10;
float readings[numReadings]; // Array untuk nilai pembacaan
int readIndex = 0;
float total = 0;
float average = 0;

char bt = 0; // BT
bool motorRunning = false; // Status motor
int direction = 1; // 1 untuk maju, -1 untuk mundur
unsigned long speedValue = 1152000;

// Definisikan pin untuk dial indicator
#define DataPin A0
#define ClkPin A1

// Dial Indicator resolution: 100 - 0.01mm, 1000 - 0.001mm
#define Resolution 1000

// UART speed
#define UARTBaudRate 115200

// ADC threshold, ADC values greater than this are interpreted as logical 1, see loop()
#define ADC_Threshold 140

// data format
#define DATA_BITS_LEN 24
#define SIGN_BIT 20
#define START_BIT -1 // -1 - no start bit

// Waktu terakhir data diambil
unsigned long lastMillis = 0;
unsigned long motorLastStepTime = 0; // Waktu terakhir langkah motor dilakukan

// Deklarasi pin untuk Pressure Transmitter
const int analogPin = A3; // Pin analog tempat output konverter dihubungkan
float sensorValue = 0; // Variabel untuk menyimpan nilai pembacaan sensor
float pressure = 0; // Variabel untuk menyimpan nilai tekanan yang dihitung

// Rentang tegangan output konverter (disesuaikan dengan konverter yang digunakan)
const float minVoltage = 0.0; // Tegangan minimum (biasanya 0V)
const float maxVoltage = 3.3; // Tegangan maksimum

// Rentang tekanan dari sensor (disesuaikan dengan spesifikasi sensor)
const float minPressure = 0.0; // Tekanan minimum (0 bar)
const float maxPressure = 10.0; // Tekanan maksimum (10 bar)

// Faktor kalibrasi untuk Pressure Transmitter
float pressureCalibrationFactor = 2.2 / 4; // Kalibrasi sensor untuk menyesuaikan dengan nilai kompresor

// Pengaturan filter median untuk dial indicator
const int filterWindowSize = 5; // Ukuran jendela untuk filter median
long filterWindow[filterWindowSize];
int filterIndex = 0;

// Fungsi untuk mendapatkan bit mentah dari dial indicator
bool getRawBit() {
bool data;
while (analogRead(ClkPin) > ADC_Threshold);
while (analogRead(ClkPin) < ADC_Threshold);
data = analogRead(DataPin) > ADC_Threshold;
return data;
}

// Fungsi untuk mendapatkan data mentah dari dial indicator
long getRawData() {
long out = 0;
for (int i = 0; i < DATA_BITS_LEN; i++) {
out |= getRawBit() ? 1L << DATA_BITS_LEN : 0L;
out >>= 1;
}
return out;
}

// Fungsi untuk mendapatkan nilai dari dial indicator
long getValue() {
long out = getRawData();
bool sign = out & (1L << SIGN_BIT);
out &= (1L << SIGN_BIT) - 1L;
out >>= (START_BIT + 1);
if (sign) out = -out;
return out;
}

// Fungsi untuk filter median
long medianFilter(long newValue) {
filterWindow[filterIndex] = newValue;
filterIndex = (filterIndex + 1) % filterWindowSize;

// Buat salinan jendela filter
long sortedWindow[filterWindowSize];
for (int i = 0; i < filterWindowSize; i++) {
sortedWindow[i] = filterWindow[i];
}

// Urutkan jendela
for (int i = 0; i < filterWindowSize - 1; i++) {
for (int j = i + 1; j < filterWindowSize; j++) {
if (sortedWindow[i] > sortedWindow[j]) {
long temp = sortedWindow[i];
sortedWindow[i] = sortedWindow[j];
sortedWindow[j] = temp;
}
}
}

// Kembalikan nilai median
return sortedWindow[filterWindowSize / 2];
}

// Fungsi untuk mencetak nilai dengan format tertentu
void prettyPrintValue(long value) {
double v = value;
Serial.print(v / 1000, 3);
}

// Fungsi untuk mengatur kecepatan motor
void setMotorSpeed(unsigned long newSpeed) {
speedValue = newSpeed;
Serial.print("Speed set to: ");
Serial.println(speedValue);
}

// Fungsi untuk menjalankan motor
void runMotor() {
digitalWrite(dirPin, direction == 1 ? HIGH : LOW);
digitalWrite(stepPin, HIGH);
delayMicroseconds(speedValue);
digitalWrite(stepPin, LOW);
delayMicroseconds(speedValue);
}

// Fungsi untuk menghentikan motor
void stopMotor() {
motorRunning = false;
Serial.println("Stopping");
}

// Fungsi untuk memetakan nilai float seperti fungsi map() untuk integer
float mapFloat(float x, float in_min, float in_max, float out_min, float out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

void setup() {
// set ADC prescale to 16 (set ADC clock to 1MHz)
// this gives us a sampling rate of ~77kSps
bitSet(ADCSRA, ADPS2);
bitClear(ADCSRA, ADPS1);
bitClear(ADCSRA, ADPS0);

Serial.begin(UARTBaudRate);

// Setup HX711
scale.begin(hx711_data_pin, hx711_clock_pin);

// Kalibrasi awal
Serial.println("Calibrating... Please remove all loads.");
delay(1000); // Kurangi delay kalibrasi menjadi 1 detik
Z_off = scale.read();
Serial.print("Zero Offset: ");
Serial.println(Z_off);

// Inisialisasi array readings dengan nol
for (int thisReading = 0; thisReading < numReadings; thisReading++) {
readings[thisReading] = 0;
}

// Setup motor stepper
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(enPin, OUTPUT);
digitalWrite(enPin, LOW);
}

void loop() {
if (Serial.available() > 0) {
char input = Serial.read();
switch (input) {
case '1':
motorRunning = true;
direction = 1;
Serial.println("Moving forwards");
break;
case '2':
stopMotor();
break;
case '3':
motorRunning = true;
direction = -1;
Serial.println("Moving backwards");
break;
case 'S':
char buffer[10];
Serial.readBytesUntil('\n', buffer, sizeof(buffer));
setMotorSpeed(strtoul(buffer, NULL, 10));
break;
case 'D': // True case, step delay negative
Serial.readBytesUntil('\n', buffer, sizeof(buffer));
setMotorSpeed(strtoul(buffer, NULL, 10));
break;

}
}

// Jalankan motor stepper jika perlu
if (motorRunning) {
unsigned long currentMillis = micros();
if (currentMillis - motorLastStepTime >= speedValue) {
motorLastStepTime = currentMillis;
runMotor();
}
}

// Ambil data setiap detik
if (millis() - lastMillis >= 1000) {
lastMillis = millis();

// Pembacaan nilai dari dial indicator dengan filter median
long rawValue = getValue();
long filteredValue = medianFilter(rawValue);

// Filter Moving Average untuk load cell
Q_raw = scale.read();

// Menghapus nilai tertua dari total
total = total - readings[readIndex];

// Menambahkan nilai baru
readings[readIndex] = Q_raw;

// Menambahkan nilai baru ke total
total = total + readings[readIndex];

// Memperbarui indeks
readIndex = (readIndex + 1) % numReadings;

// Menghitung rata-rata
average = total / numReadings;
Q = (average - Z_off) / Q_cal;

// Jika nilai load cell <= 0, set ke 0
if (Q <= 0) {
Q = 0;
}

// Pembacaan nilai dari Pressure Transmitter
sensorValue = analogRead(analogPin);
float voltage = (sensorValue / 1023.0) * maxVoltage;
pressure = mapFloat(voltage, minVoltage, maxVoltage, minPressure, maxPressure);

// Terapkan faktor kalibrasi pada tekanan
pressure *= pressureCalibrationFactor;

// Kirim data load cell, dial indicator (filtered), dan tekanan melalui serial
Serial.print(Q);
Serial.print(",");
prettyPrintValue(filteredValue);
Serial.print(";");
Serial.println(pressure); //

Serial.flush(); // Pastikan buffer serial telah dikirim
}
// Tambahkan delay di akhir loop
delay(100); // Delay 100 ms untuk stabilisasi komunikasi
}

0 Kudos
Message 1 of 1
(21 Views)