ACS712 30A no working

why is the ACS712 30A reading always 0 in this code?

Hasil rata-rata offset: 2.25
Max Value: 2908, Min Value: 2658, Vpp: 0.20
Voltage after Offset: -0.56
Arus Fan (AmpsRMS): 0.00
Suhu: 0.00F, Arus Fan: 0.00
#include <Arduino.h>
#include <driver/twai.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// Konfigurasi OLED
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C

// Pin CAN Bus ESP32
#define CAN_TX_PIN 5
#define CAN_RX_PIN 4

// Pin LED dan Buzzer
#define LED_MERAH 13
#define BUZZER_PIN 12

// Pin ACS712 Global
#define ACS712_PIN 35       // Pin analog untuk sensor ACS712
#define MV_PER_AMP 66       // Sesuaikan untuk ACS712 30A (66mV/A)

// Batas suhu kritis
#define BATAS_SUHU_KRITIS 100.0

// Offset global untuk sensor ACS712
float sensorOffset = 2.5; // Nilai default offset (tegangan tengah sensor ACS712)

// Objek OLED
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Variabel Global
float engineTemperature = 0.0;
float fanCurrent = 0.0;
float lastEngineTemp = 0.0;
float lastFanCurrent = 0.0;

// Fungsi kalibrasi ACS712
float kalibrasiACS712() {
  float total = 0;
  for (int i = 0; i < 100; i++) {
    total += analogRead(ACS712_PIN) * 3.3 / 4096.0;
    delay(10); // Tunggu antara pembacaan
  }
  return total / 100; // Rata-rata tegangan
}

// Fungsi filter sederhana (Exponential Moving Average)
float filterNilai(float nilaiBaru, float nilaiLama, float alpha) {
  return (alpha * nilaiBaru) + ((1 - alpha) * nilaiLama);
}

// Fungsi setup pin output
void setupPinOutput() {
  pinMode(LED_MERAH, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);
}

// Fungsi setup CAN bus
void setupCANBus() {
  twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(
    (gpio_num_t)CAN_TX_PIN,
    (gpio_num_t)CAN_RX_PIN,
    TWAI_MODE_NORMAL
  );
  twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS();
  twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();

  if (twai_driver_install(&g_config, &t_config, &f_config) == ESP_OK) {
    Serial.println("CAN Bus Driver Installed");
    twai_start();
  }
}

// Fungsi untuk mengukur tegangan puncak-puncak (Vpp)
float getVPP() {
  int maxValue = 0;
  int minValue = 4096;

  uint32_t start_time = millis();
  while ((millis() - start_time) < 1000) {
    int readValue = analogRead(ACS712_PIN);
    if (readValue > maxValue) {
      maxValue = readValue;
    }
    if (readValue < minValue) {
      minValue = readValue;
    }
  }

  if (maxValue == minValue) {
    Serial.println("Kesalahan pembacaan Vpp: maxValue == minValue");
    return 0;
  }

  float Vpp = ((maxValue - minValue) * 3.3) / 4096.0;

  // Debug: Print nilai maksimum, minimum, dan Vpp
  Serial.print("Max Value: ");
  Serial.print(maxValue);
  Serial.print(", Min Value: ");
  Serial.print(minValue);
  Serial.print(", Vpp: ");
  Serial.println(Vpp);

  return Vpp; // Vpp
}

// Fungsi untuk membaca tegangan offset ACS712
float bacaOffsetACS712() {
  float total = 0.0;
  
  // Loop untuk membaca beberapa sampel
  for (int i = 0; i < 100; i++) {
    float teganganSaatIni = analogRead(ACS712_PIN) * 3.3 / 4096.0;
    total += teganganSaatIni;
    
    // Debugging untuk memantau setiap pembacaan
    Serial.print("Sample ke-");
    Serial.print(i + 1);
    Serial.print(": Tegangan = ");
    Serial.println(teganganSaatIni);

    delay(10); // Tunggu antara pembacaan
  }
  
  float rataRata = total / 100.0;
  
  // Debugging hasil rata-rata
  Serial.print("Hasil rata-rata offset: ");
  Serial.println(rataRata);
  
  return rataRata; // Rata-rata offset
}

// Fungsi untuk membaca arus kipas menggunakan ACS712
bool bacaArusFan() {
  static unsigned long lastCurrentReadTime = 0;

  // Baca arus setiap 500ms
  if (millis() - lastCurrentReadTime >= 500) {
    // Baca tegangan offset terbaru
    sensorOffset = bacaOffsetACS712();

    float Voltage = getVPP(); // Ambil Vpp
    Voltage -= sensorOffset;  // Kompensasi offset

    // Filter tegangan untuk meredam noise
    static float voltageFiltered = 0;
    voltageFiltered = filterNilai(Voltage, voltageFiltered, 0.1);
    Voltage = voltageFiltered;

    // Debug: Print nilai tegangan setelah kompensasi offset
    Serial.print("Voltage after Offset: ");
    Serial.println(Voltage);

    // Abaikan noise kecil
    if (Voltage < 0.01) {
      fanCurrent = 0.0;
    } else {
      // Konversi Vpp ke RMS
      float VRMS = (Voltage / 2.0) * 0.707;
      float AmpsRMS = (VRMS * 1000) / MV_PER_AMP;

      fanCurrent = fabs(AmpsRMS);

      // Debug: Print nilai VRMS dan AmpsRMS
      Serial.print("VRMS: ");
      Serial.print(VRMS);
      Serial.print(", AmpsRMS: ");
      Serial.println(AmpsRMS);
    }

    Serial.print("Arus Fan (AmpsRMS): ");
    Serial.println(fanCurrent);

    lastCurrentReadTime = millis();
    return true;
  }
  return false;
}

// Fungsi untuk membaca suhu mesin dari CAN bus
bool bacaSuhuECT() {
  static unsigned long lastTempReadTime = 0;

  // Baca suhu setiap 500ms
  if (millis() - lastTempReadTime >= 500) {
    twai_message_t message;
    uint32_t targetID = 0x7E0;

    if (twai_receive(&message, pdMS_TO_TICKS(100)) == ESP_OK) {
      if (message.identifier == targetID) {
        engineTemperature = ((message.data[2] - 40.0) * 1.8) + 32.0;
        lastTempReadTime = millis();
        return true;
      }
    }
  }
  return false;
}

// Fungsi kontrol peringatan
void kontrolPeringatan() {
  if (engineTemperature > BATAS_SUHU_KRITIS) {
    digitalWrite(LED_MERAH, HIGH);

    static unsigned long previousMillis = 0;
    unsigned long currentMillis = millis();
    static bool buzzerState = false;

    if (currentMillis - previousMillis >= 500) {
      previousMillis = currentMillis;
      buzzerState = !buzzerState;
      digitalWrite(BUZZER_PIN, buzzerState);
    }
  } else {
    digitalWrite(LED_MERAH, LOW);
    digitalWrite(BUZZER_PIN, LOW);
  }
}

// Fungsi untuk menampilkan data di OLED
void tampilkanDisplay() {
  display.clearDisplay();
  display.setTextColor(WHITE);

  // Tampilkan suhu mesin
  display.setCursor(0, 0);
  display.setTextSize(1);
  display.print("Suhu Mesin: ");
  display.print(engineTemperature, 1);
  display.print(" F");

  // Tampilkan arus kipas
  display.setCursor(0, 16);
  display.print("Arus Fan: ");
  display.print(fanCurrent, 2);
  display.print(" A");

  // Tampilkan peringatan jika suhu kritis
  if (engineTemperature > BATAS_SUHU_KRITIS) {
    display.setCursor(90, 16);
    display.print("KRITIS!");
  }

  display.display();
}

void setup() {
  analogReadResolution(12);  // Resolusi ADC 12-bit
  analogSetPinAttenuation(ACS712_PIN, ADC_0db); // Input 0-3.3V
  Serial.begin(115200);

  setupPinOutput();

  Wire.begin();
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("Gagal inisialisasi OLED"));
    for (;;);
  }

  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.display();

  setupCANBus();

  // Kalibrasi nilai offset dari ACS712
  sensorOffset = kalibrasiACS712();
  Serial.print("Offset Sensor setelah Kalibrasi: ");
  Serial.println(sensorOffset);
}

void loop() {
  bool tempRead = bacaSuhuECT();
  bool currentRead = bacaArusFan();

  if (tempRead || currentRead) {
    Serial.print("Suhu: ");
    Serial.print(engineTemperature);
    Serial.print("F, Arus Fan: ");
    Serial.println(fanCurrent);

    tampilkanDisplay();
    kontrolPeringatan();
  }

  delay(50); // Delay minimal untuk memberikan waktu proses
}

Show a schematic of your complete circuit (not fritzing) include power supplies and terminal numbers etc. etc.

1 Like

What else can you expect here?

1 Like

Is this a plain ESP32 or one of the S or C versions?

1 Like

esp32 wroom 32

You mean?

analogSetPinAttenuation(ACS712_PIN, ADC_0db); // Input 0-3.3V

ADC_0db: That will limit the input range to 100mV to 950mV
ADC_11db will enable you to read 150mV to 3100mV

The ACS712 runs on 5V so it will be out of range of the ESP ADC. You need to externally scale the ACS712 output.

Your code forcefully assign the value of current to zero if the Voltage is less than 0.01v.
The Voltage in your example is -0.56v ... so it less than 0.01.

Why are you surprised that your current is zero? That's how it should be.

I've added a voltage divider resistor but the sensor still doesn't work, it's still 0 amperes

does that mean I have to reduce the value so it can read 0.001A?

Need to see how you have this connected. Can you draw a simple schematic.

Are you measuring AC or DC?
How much current are you trying to measure?

No
Your Voltage has a negative value, so even lowering the threshold to zero won't help.

You should review the whole logic of the code. Negative voltage means that the current flows in the opposite direction. I don't know how much sense this makes in your circuit. Maybe you did the calibration wrong?

I changed the code and it worked, but this code has to remove the load first, it can't be done directly while the load is attached

20:14:56.754 -> === Data Kalibrasi ===
20:14:56.754 -> Raw ADC Avg: 2829.85
20:14:56.754 -> Raw ADC Min: 2790.00
20:14:56.754 -> Raw ADC Max: 2989.00
20:14:56.754 -> Mid Point: 2.280
20:14:56.754 -> Mid point setelah kalibrasi: 2.280
20:14:58.970 -> 
20:14:58.970 -> === Debug Info ===
20:14:58.970 -> Raw ADC Avg: 2829.89
20:14:58.970 -> Raw ADC Min: 2790.00
20:14:58.970 -> Raw ADC Max: 2890.00
20:14:58.970 -> Peak-to-Peak (V): 0.081
20:14:58.970 -> Valid Samples: 1000.00
20:14:58.970 -> Voltage: 2.280V
20:14:58.970 -> Mid Point: 2.280V
20:14:58.970 -> Voltage Offset: 0.0mV
20:14:58.970 -> Calculated Current: 0.000A
20:14:58.970 -> --------------------
20:14:59.002 -> Suhu: 0.00F, Arus Fan: 0.000A
20:12:57.989 -> 
20:12:57.989 -> === Debug Info ===
20:12:57.989 -> Raw ADC Avg: 2826.08
20:12:57.989 -> Raw ADC Min: 2783.00
20:12:57.989 -> Raw ADC Max: 2917.00
20:12:57.989 -> Peak-to-Peak (V): 0.108
20:12:57.989 -> Valid Samples: 1000.00
20:12:57.989 -> Voltage: 2.277V
20:12:57.989 -> Mid Point: 2.275V
20:12:57.989 -> Voltage Offset: 2.2mV
20:12:58.021 -> Calculated Current: 0.022A
20:12:58.021 -> --------------------
20:12:58.021 -> Suhu: 0.00F, Arus Fan: 0.009A
#include <Arduino.h>
#include <driver/twai.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// Konfigurasi OLED
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C

// Pin CAN Bus ESP32
#define CAN_TX_PIN 5
#define CAN_RX_PIN 4

// Pin LED dan Buzzer
#define LED_MERAH 13
#define BUZZER_PIN 12

// Pin dan Konfigurasi ACS712
#define ACS712_PIN 34
#define MV_PER_AMP 100     // untuk ACS712 20A
#define VREF 3.3           
#define ADC_RESOLUTION 4096 
#define NUM_SAMPLES 1000   // Ditingkatkan untuk akurasi lebih baik
#define NOISE_THRESHOLD 0.02 // Diturunkan untuk mendeteksi arus kecil

// Batas suhu kritis
#define BATAS_SUHU_KRITIS 100.0

// Variabel Global
float midPoint;
float engineTemperature = 0.0;
float fanCurrent = 0.0;
float lastEngineTemp = 0.0;
float lastFanCurrent = 0.0;

// Objek OLED
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void hitungMidPoint() {
  float total = 0;
  float maxValue = 0;
  float minValue = 4096;
  
  Serial.println("Menghitung titik tengah ACS712...");
  Serial.println("Pastikan tidak ada arus mengalir melalui sensor");
  
  for (int i = 0; i < 1000; i++) {
    float rawValue = analogRead(ACS712_PIN);
    total += rawValue;
    maxValue = max(maxValue, rawValue);
    minValue = min(minValue, rawValue);
    delay(1);
  }
  
  float avgRaw = total / 1000.0;
  midPoint = (avgRaw * VREF) / ADC_RESOLUTION;
  
  Serial.println("=== Data Kalibrasi ===");
  Serial.print("Raw ADC Avg: "); Serial.println(avgRaw);
  Serial.print("Raw ADC Min: "); Serial.println(minValue);
  Serial.print("Raw ADC Max: "); Serial.println(maxValue);
  Serial.print("Mid Point: "); Serial.println(midPoint, 3);
}

float filterNilai(float nilaiBaru, float nilaiLama, float alpha) {
  return (alpha * nilaiBaru) + ((1 - alpha) * nilaiLama);
}

void setupPinOutput() {
  pinMode(LED_MERAH, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);
}

void setupCANBus() {
  twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(
    (gpio_num_t)CAN_TX_PIN,
    (gpio_num_t)CAN_RX_PIN,
    TWAI_MODE_NORMAL
  );
  twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS();
  twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();

  if (twai_driver_install(&g_config, &t_config, &f_config) == ESP_OK) {
    Serial.println("CAN Bus Driver Installed");
    twai_start();
  }
}

bool bacaArusFan() {
  static unsigned long lastCurrentReadTime = 0;
  
  if (millis() - lastCurrentReadTime >= 100) {
    float totalRaw = 0;
    float maxRaw = 0;
    float minRaw = 4096;
    int zeroCount = 0;
    
    // Averaging dengan teknik yang lebih baik
    for(int i = 0; i < NUM_SAMPLES; i++) {
      float rawValue = analogRead(ACS712_PIN);
      if(rawValue > 0) { // Hanya nilai valid yang dihitung
        totalRaw += rawValue;
        maxRaw = max(maxRaw, rawValue);
        minRaw = min(minRaw, rawValue);
      } else {
        zeroCount++;
      }
      delayMicroseconds(50); // Waktu sampling dipercepat
    }
    
    // Koreksi jumlah sampel jika ada pembacaan nol
    float validSamples = NUM_SAMPLES - zeroCount;
    float avgRaw = (validSamples > 0) ? totalRaw / validSamples : 0;
    
    float voltage = (avgRaw * VREF) / ADC_RESOLUTION;
    float voltageOffset = voltage - midPoint;
    
    // Menggunakan sensitivitas yang lebih tepat untuk ACS712 20A
    float current = (voltageOffset * 1000.0) / MV_PER_AMP;
    
    // Tambahkan pemrosesan peak-to-peak untuk noise reduction
    float peakToPeak = (maxRaw - minRaw) * VREF / ADC_RESOLUTION;
    
    Serial.println("\n=== Debug Info ===");
    Serial.print("Raw ADC Avg: "); Serial.println(avgRaw);
    Serial.print("Raw ADC Min: "); Serial.println(minRaw);
    Serial.print("Raw ADC Max: "); Serial.println(maxRaw);
    Serial.print("Peak-to-Peak (V): "); Serial.println(peakToPeak, 3);
    Serial.print("Valid Samples: "); Serial.println(validSamples);
    Serial.print("Voltage: "); Serial.print(voltage, 3); Serial.println("V");
    Serial.print("Mid Point: "); Serial.print(midPoint, 3); Serial.println("V");
    Serial.print("Voltage Offset: "); Serial.print(voltageOffset * 1000.0, 1); Serial.println("mV");
    Serial.print("Calculated Current: "); Serial.print(current, 3); Serial.println("A");
    
    // Perbaikan noise filtering
    if (abs(current) < NOISE_THRESHOLD || peakToPeak < 0.01) {
      current = 0.0;
    } else {
      // Tambahkan koreksi arah arus jika diperlukan
      current = abs(current); // Mengambil nilai absolut jika arah terbalik
    }
    
    fanCurrent = filterNilai(current, lastFanCurrent, 0.15); // Smoothing yang lebih halus
    lastFanCurrent = fanCurrent;
    
    lastCurrentReadTime = millis();
    return true;
  }
  return false;
}

bool bacaSuhuECT() {
  static unsigned long lastTempReadTime = 0;

  if (millis() - lastTempReadTime >= 500) {
    twai_message_t message;
    uint32_t targetID = 0x7E0;

    if (twai_receive(&message, pdMS_TO_TICKS(100)) == ESP_OK) {
      if (message.identifier == targetID) {
        float tempRaw = ((message.data[2] - 40.0) * 1.8) + 32.0;
        engineTemperature = filterNilai(tempRaw, lastEngineTemp, 0.2);
        lastEngineTemp = engineTemperature;
        lastTempReadTime = millis();
        return true;
      }
    }
  }
  return false;
}

void kontrolPeringatan() {
  if (engineTemperature > BATAS_SUHU_KRITIS) {
    digitalWrite(LED_MERAH, HIGH);

    static unsigned long previousMillis = 0;
    unsigned long currentMillis = millis();
    static bool buzzerState = false;

    if (currentMillis - previousMillis >= 500) {
      previousMillis = currentMillis;
      buzzerState = !buzzerState;
      digitalWrite(BUZZER_PIN, buzzerState);
    }
  } else {
    digitalWrite(LED_MERAH, LOW);
    digitalWrite(BUZZER_PIN, LOW);
  }
}

void tampilkanDisplay() {
  display.clearDisplay();
  display.setTextColor(WHITE);

  display.setCursor(0, 0);
  display.setTextSize(1);
  display.print("Suhu: ");
  display.print(engineTemperature, 1);
  display.print(" F");

  display.setCursor(0, 16);
  display.print("Arus: ");
  display.print(fanCurrent, 2);
  display.print(" A");

  if (engineTemperature > BATAS_SUHU_KRITIS) {
    display.setCursor(90, 16);
    display.print("KRITIS!");
  } else if (fanCurrent < 0.2) {
    display.setCursor(90, 16);
    display.print("FAN OFF");
  } else {
    display.setCursor(90, 16);
    display.print("NORMAL");
  }

  display.display();
}

void setup() {
  Serial.begin(115200);
  while(!Serial) {
    delay(100);
  }
  
  analogReadResolution(12);
  analogSetPinAttenuation(ACS712_PIN, ADC_11db);
  analogSetWidth(12);
  
  delay(1000);
  
  Serial.println("\nMemulai sistem...");
  
  setupPinOutput();
  
  Wire.begin();
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("Gagal inisialisasi OLED"));
    for(;;);
  }
  
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.println("Initializing...");
  display.display();
  
  setupCANBus();
  
  Serial.println("\nMemulai kalibrasi...");
  hitungMidPoint();
  Serial.print("Mid point setelah kalibrasi: ");
  Serial.println(midPoint, 3);
  
  display.clearDisplay();
  display.setCursor(0, 0);
  display.println("Calibration done!");
  display.println("Mid Point: ");
  display.print(midPoint, 3);
  display.println(" V");
  display.display();
  delay(2000);
}

void loop() {
  bool tempRead = bacaSuhuECT();
  bool currentRead = bacaArusFan();

  if (tempRead || currentRead) {
    Serial.println("--------------------");
    Serial.print("Suhu: ");
    Serial.print(engineTemperature);
    Serial.print("F, Arus Fan: ");
    Serial.print(fanCurrent, 3);
    Serial.println("A");
    
    tampilkanDisplay();
    kontrolPeringatan();
  }

  delay(50);
}

I suggest you use this library for the ACS712. It work well with the ACS712 for AC and DC
See the section on Voltage Dividers and the ESP32
You need to make corrections for the sensitivity and offset values.

Why did you change the ADC pin?
Are you measuring AC or DC?
What current range are you trying to measure?

2 images that I used


I didn't use the library because later I would use the acs712 code for acs758

The first image with the resistors is correct. The second image without will damage the ESP input

Up to you but you need to take into account the affect of the voltage divider when calculating the current and offset.

Your code won't work for AC

I also tested the first image and it still failed the output remained 0 but when I changed the new code it worked but only ran when the load was removed first and then installed

yes, I know it doesn't work for AC, I tried it for 12v lights

Well I asked several time about what you are trying to measure AC, DC, range etc but you never gave an answer.
So exactly what are you trying to accomplish here?

I just want to be able to read the current and display it on the LCD with the acs712 and acs758 sensors without libraries. Several tutorials on the internet did not work

AC OR DC?
WHAT RANGE OF CURRENT?
WHICH ACS758 Sensor?