Skip to content

Resistivímetro DC de Baixo Custo — Tutorial DIY

Disciplinas: Ciências Ambientais · Hidrogeologia · Geofísica Aplicada
Plataforma: Arduino Mega 2560 · Interface Android via Bluetooth
Baseado em: OhmPi (INRAE, 2020) · Clark & Page (2011) · Vega et al. (2021)


Sumário

  1. Introdução e Viabilidade
  2. Princípio Físico
  3. Arquitetura do Sistema
  4. Lista de Componentes
  5. Diagrama de Circuito
  6. Firmware Arduino
  7. Interface Android via Bluetooth
  8. Caixa em Impressão 3D
  9. Procedimento de Campo
  10. Calibração e Validação
  11. Processamento dos Dados
  12. Referências e Recursos

1. Introdução e Viabilidade

Contexto

A sondagem elétrica por resistividade (DC resistivity) é uma técnica geofísica não-invasiva fundamental em hidrogeologia, ciências ambientais e engenharia geotécnica. Equipamentos comerciais (ABEM Terrameter, Iris Syscal, AGI SuperSting) custam entre R$ 25.000 e R$ 120.000, tornando o acesso inviável para a maioria dos grupos de pesquisa e ensino em universidades brasileiras.

O avanço dos microcontroladores de baixo custo (Arduino, Raspberry Pi) e a disponibilidade de componentes eletrônicos via AliExpress e Mercado Livre criaram condições reais para construção de instrumentos DIY funcionais com base científica sólida.

Conclusão de Viabilidade

Sim, é plenamente viável. Projetos validados em periódicos como Geophysics (SEG), Earth and Space Science (AGU) e SoftwareX (Elsevier) demonstram erros relativos de 0,6% a 5,5% em relação a equipamentos comerciais — suficiente para pesquisa acadêmica e aplicações ambientais.

Comparação com projetos científicos publicados

Projeto Custo aprox. Microcontrolador Profundidade máx. Publicação
Clark & Page (2011) ~US$ 250 Sem MCU ~35 m Hydrogeology Journal
OhmPi v2023 ~US$ 500 Raspberry Pi 4 Variável SoftwareX (2020)
Vega et al. (2021) ~US$ 300 Arduino DUE ~20 m Earth and Space Science
Sirota & Roth (2022) ~US$ 400 Arduino + RPi ~40 m Geophysics (SEG)
Este tutorial ~R$ 600 Arduino Mega ~30–50 m DIY / educacional

Limitações importantes

⚠️ Este instrumento NÃO substitui equipamentos profissionais para prospecção comercial. As principais restrições são: - Profundidade investigada menor (< 50 m em solos típicos) - Maior susceptibilidade a ruído elétrico ambiental - Sem tomografia automática multieletrodo (versão básica) - Para publicações científicas, recomenda-se validação cruzada com equipamento de referência em pelo menos uma campanha de campo


2. Princípio Físico

O método de resistividade elétrica DC

O método baseia-se na Lei de Ohm generalizada aplicada ao meio geológico. Uma corrente contínua I é injetada no solo através de dois eletrodos de corrente A e B. Dois eletrodos de potencial M e N medem a diferença de potencial ΔV resultante. A resistividade aparente ρ é calculada como:

ρ (Ω·m) = K · (ΔV / I)

onde K é o fator geométrico, que depende exclusivamente do arranjo e do espaçamento dos eletrodos.

Arranjo Wenner (recomendado para educação)

O arranjo mais simples: os quatro eletrodos são igualmente espaçados de a metros.

A ———————— M ———————— N ———————— B
|←—— a ——→|←—— a ——→|←—— a ——→|

Fator geométrico:   K = 2π · a

Resistividade:      ρ = 2π · a · (ΔV / I)

Vantagens: simples de implementar, boa sensibilidade lateral, amplamente documentado.
Desvantagem: AB precisa ser movido a cada leitura — mais trabalhoso para SEV.

Arranjo Schlumberger (recomendado para SEV)

Os eletrodos MN permanecem fixos no centro enquanto AB é afastado progressivamente para investigar maiores profundidades.

A ——————————————— M — N ——————————————— B
|←——————————————— L ————————————————→|
                  |←a→|

Fator geométrico:   K = π · (L²/2a − a/2)

Resistividade:      ρ = π · (L²/2a − a/2) · (ΔV / I)

onde:  L = AB/2  (metade do espaçamento AB)
       a = MN/2  (metade do espaçamento MN)

Regra prática: manter MN ≤ AB/5. Quando AB/2 ≥ 5 × MN/2, reposicionar MN para MN = AB/5.

Vantagens: MN fixo reduz o trabalho de campo; ideal para Sondagem Elétrica Vertical (SEV).

O que o microcontrolador realmente mede

O Arduino não mede resistividade diretamente. Ele mede grandezas elétricas brutas:

Grandeza Componente medidor Precisão típica
Corrente I (A) ACS712 — sensor efeito Hall ±1,5% FS
Tensão ΔV (V) ADS1115 16-bit + INA128 ~7,8 µV/bit
Fator K Calculado por software Exato (geométrico)

A resistividade é então calculada no firmware por: ρ = K × (ΔV / I).

Por que a inversão de polaridade é necessária

Ao injetar corrente DC diretamente no solo, ocorre polarização eletrolítica nos eletrodos: íons acumulam-se na interface metal-solo, criando um potencial parasita que soma ao sinal real. Para mitigar isso:

  1. Realiza-se uma medição com polaridade direta → obtém-se V₁ e I₁
  2. Inverte-se a polaridade da injeção → obtém-se V₂ e I₂
  3. Calcula-se a média: ΔV = (|V₁| + |V₂|) / 2 e I = (I₁ + I₂) / 2

Isso cancela o potencial de polarização, que tem sinal oposto nas duas medições.


3. Arquitetura do Sistema

┌─────────────────────────────────────────────────────────────────┐
│                        BATERIA 12V 7Ah                          │
└──────────────────┬──────────────────────────┬───────────────────┘
                   │                          │
          ┌────────▼────────┐        ┌────────▼────────┐
          │  Boost Converter│        │  Regulador 5V   │
          │  MT3608         │        │  LM7805 / LM317 │
          │  12V → 60–120V  │        │  5V para MCU    │
          └────────┬────────┘        └────────┬────────┘
                   │                          │
          ┌────────▼────────┐        ┌────────▼──────────────────┐
          │  H-Bridge       │        │   Arduino Mega 2560        │
          │  2× IRF540N     │◄───────│                            │
          │  Inversão polar.│ ctrl   │  ADS1115 (I2C, ADC 16-bit) │
          └──┬──────────┬───┘        │  INA128 (amp. instrumentação)│
             │          │            │  ACS712 (sensor de corrente) │
      ┌──────▼──┐  ┌────▼───────┐   │  HC-05 (Bluetooth serial)   │
      │ Shunt   │  │ Relés SSR  │   │  LCD 20×4 I2C               │
      │ 0,33Ω  │  │ A  B  M  N │   │  Micro SD Card              │
      └──┬──────┘  └────┬───────┘   │  RTC DS3231                 │
         │               │           └────────────────────────────┘
   ┌─────▼───────────────▼───────────────┐
   │           ELETRODOS NO SOLO          │
   │      A        M      N        B      │
   │      ●────────●──────●────────●      │
   └──────────────────────────────────────┘

   ACS712 mede corrente I no circuito AB
   INA128 + ADS1115 mede diferença de potencial ΔV em MN

Fluxo de dados

Campo           Eletrodos → Amplificação → ADC → Arduino
                    ↓
Firmware        Média de N amostras → Cálculo ρ = K·ΔV/I
                    ↓
Saída           LCD (tempo real) + SD Card (CSV) + Bluetooth (Android)
                    ↓
Pós-campo       Exportar CSV → IPI2WIN / ResIPy → Inversão → Perfil

4. Lista de Componentes

💡 Todos os componentes podem ser encontrados no Mercado Livre, AliExpress (10–20 dias) ou lojas como FilipeFlop, Baú da Eletrônica e Casa da Robótica.

4.1 Núcleo de controle e aquisição

Componente Qtd. Preço est. (R$) Função
Arduino Mega 2560 (ou clone) 1 90 MCU principal — I/O e processamento
ADS1115 (módulo I2C breakout) 1 25 ADC 16-bit para medição de ΔV com alta precisão
INA128 ou INA126 (DIP-8) 1 18 Amplificador de instrumentação para sinal MN
ACS712 módulo 30A 1 15 Sensor de corrente por efeito Hall
Módulo Bluetooth HC-05 1 35 Comunicação serial wireless com Android
Display LCD 20×4 com módulo I2C 1 30 Interface de campo
Módulo RTC DS3231 1 20 Timestamp automático nos dados
Módulo Micro SD Card 1 15 Log de dados em campo (formato CSV)
Subtotal ~248

4.2 Circuito de injeção de corrente

Componente Qtd. Preço est. (R$) Função
Boost Converter MT3608 (módulo ajustável) 1 12 Eleva 12V → 60–120V DC para injeção
MOSFET IRF540N (TO-220) 2 6 H-bridge para inversão de polaridade
Relé de estado sólido 5A DC (SSR) 4 60 Chaveamento ABMN sem bounce mecânico
Resistor shunt 0,33 Ω 5W (cimento) 1 8 Referência de corrente para ACS712
Diodo 1N4007 4 3 Proteção contra picos de tensão reversa
Capacitor eletrolítico 100 µF 200V 2 12 Filtro de ripple na saída do boost
Resistor 100 kΩ 1% (par casado) 2 4 Divisor de tensão — proteção entrada MN
Resistor 10 kΩ 1% (par casado) 2 4 Divisor de tensão — proteção entrada MN
Diodo TVS SMAJ5.0A 2 6 Proteção ESD nas entradas M e N
Regulador LM7805 (TO-220) 1 5 5V estabilizado para Arduino e sensores
Bateria selada 12V 7Ah (VRLA) 1 120 Fonte de campo — ~4h de operação
Subtotal ~240

4.3 Eletrodos e material de campo

Item Qtd. Preço est. (R$) Observações
Varão roscado inox 1/2" × 40 cm 4 40 Cortar em ~40 cm; rosca para fixar terminal
Cabo PP 2×1,5 mm² (carretel 100 m) 1 130 Ligação eletrodos ↔ instrumento
Conectores banana 4 mm macho+fêmea 8 pares 30 Terminais A, B, M, N no painel
Terminais tipo jacaré com cabo 30 cm 4 12 Conexão rápida nos eletrodos em campo
Fita isolante autofusão 1 rolo 15 Vedação das emendas no campo
Trena de fibra 100 m 1 40 Medição precisa dos espaçamentos
Subtotal ~267

4.4 Custo total estimado

Categoria Custo (R$)
Eletrônica (núcleo + injeção) ~488
Eletrodos e campo ~267
Total sem caixa ~755
Filamento PETG 1 kg (caixa 3D) +80–150
Total com caixa impressa ~835–905

💡 Usando caixa de PVC elétrica (~R$ 25) em vez de impressão 3D, o custo cai para ~R$ 780.


5. Diagrama de Circuito

5.1 Circuito de injeção (alta tensão — ATENÇÃO)

🚨 SEGURANÇA: O circuito de injeção opera com 60–120V DC. Nunca toque nos terminais A e B durante a medição. Use caixa fechada e sinalize os bornes de alta tensão.

BATERIA 12V
    │
    ├──────────────────────────────────────────────┐
    │                                              │
┌───▼──────────┐                           ┌──────▼──────┐
│ Boost MT3608 │                           │  LM7805     │
│ 12V → 100V   │                           │  12V → 5V   │
│ Ajustar trim │                           └──────┬──────┘
└───┬──────────┘                                  │
    │                                           GND + 5V
┌───▼──────────────────────────┐           para Arduino
│  H-Bridge com IRF540N        │
│                              │
│  Q1 ─── Drain: V+boost       │  ← PWM D22 (INJECT_EN)
│  Q2 ─── Gate: GND            │  ← PWM D23 (INJECT_POL)
│                              │
│  Saída +: via Shunt 0,33Ω → eletrodo A  │
│  Saída −: eletrodo B                    │
└──────────────────────────────┘

Shunt 0,33Ω em série no circuito AB:
  Ponto antes do shunt → ACS712 IP+
  Ponto depois do shunt → ACS712 IP−
  ACS712 OUT → Arduino A0

5.2 Circuito de medição (baixa tensão)

Eletrodo M ──┬── Divisor 100k/10k ──┬── INA128 pino 1 (−IN)
             └── Diodo TVS SMAJ5    │
                                    │
Eletrodo N ──┬── Divisor 100k/10k ──┴── INA128 pino 8 (+IN)
             └── Diodo TVS SMAJ5

INA128:
  Pino 1 (−IN)   → eletrodo M (via proteção)
  Pino 8 (+IN)   → eletrodo N (via proteção)
  Pino 1─8 (Rg)  → Resistor 499 Ω  (ganho = 1 + 50k/499 ≈ 101×)
  Pino 5 (OUT)   → ADS1115 pino A0
  Pino 7 (VS+)   → +5V
  Pino 4 (VS−)   → GND

ADS1115:
  SDA  → Arduino Mega pino 20 (SDA)
  SCL  → Arduino Mega pino 21 (SCL)
  ADDR → GND (endereço I2C = 0x48)
  VDD  → 3,3V
  Ganho configurado por software: GAIN_SIXTEEN (±0,256V → 7,8 µV/bit)

5.3 Divisor de tensão para proteção dos pinos M e N

Os eletrodos M e N podem receber tensões inesperadamente altas (> 5V) em solos muito resistivos. O divisor de tensão reduz a tensão de entrada do INA128 para níveis seguros:

Eletrodo M/N
     │
   100kΩ (1%)
     │
     ├──────────── Saída para INA128 (−IN ou +IN)
     │
   10 kΩ (1%)
     │
    GND

Razão do divisor: 10k / (100k + 10k) = 1/11 ≈ 0,0909
Faixa útil: até ±11 × 0,256V = ±2,8V no eletrodo (sem o ganho INA128)
Compensar no software multiplicando a leitura por 11.

5.4 Pinagem completa Arduino Mega

Pino Arduino Função Componente
D20 (SDA) I2C dados ADS1115 + LCD + RTC
D21 (SCL) I2C clock ADS1115 + LCD + RTC
D22 INJECT_EN — habilita injeção Gate MOSFET Q1
D23 INJECT_POL — controla polaridade Gate MOSFET Q2
D10 (RX2) Bluetooth RX HC-05 TX
D11 (TX2) Bluetooth TX HC-05 RX
D53 (SS) Chip Select SD Módulo Micro SD
D51 (MOSI) SPI dados Módulo Micro SD
D50 (MISO) SPI dados Módulo Micro SD
D52 (SCK) SPI clock Módulo Micro SD
A0 Leitura corrente ACS712 OUT

6. Firmware Arduino

6.1 Dependências

Instale via Ferramentas → Gerenciar Bibliotecas na IDE Arduino:

  • Adafruit ADS1X15 (por Adafruit) — ADC 16-bit
  • LiquidCrystal I2C (por Frank de Brabander) — display
  • SD (built-in) — cartão SD
  • RTClib (por Adafruit) — relógio de tempo real

6.2 Código principal

// ================================================================
// resistivimetro_diy.ino
// Resistivímetro DC de Baixo Custo — Wenner / Schlumberger
// Baseado em OhmPi (INRAE) e Clark & Page (2011)
// Versão 1.0 — Uso educacional e de pesquisa
// ================================================================

#include <Wire.h>
#include <Adafruit_ADS1X15.h>
#include <LiquidCrystal_I2C.h>
#include <SD.h>
#include <RTClib.h>
#include <SoftwareSerial.h>

// ── Pinos ────────────────────────────────────────────────────────
#define PIN_INJECT_EN    22    // Habilita injeção de corrente
#define PIN_INJECT_POL   23    // Controla polaridade (H-bridge)
#define PIN_ACS712       A0    // Saída analógica do sensor de corrente
#define PIN_SD_CS        53    // Chip Select do cartão SD

// ── Constantes de calibração ─────────────────────────────────────
#define ACS712_SENSITIVITY   0.066   // V/A (modelo 30A; ajustar após calibração)
#define ACS712_OFFSET        2.5     // V (VCC/2; medir com corrente zero)
#define ACS712_VCC           5.0     // Tensão de referência do sensor
#define INA128_GAIN          101.0   // Ganho = 1 + 50k/Rg com Rg = 499Ω
#define DIVISOR_RATIO        11.0    // Divisor 100k/10k = razão 1/11
#define NUM_SAMPLES          64      // Amostras para média (reduz ruído)
#define INJECT_STABILIZE_MS  300     // ms para estabilização após injeção

// ── Objetos ───────────────────────────────────────────────────────
Adafruit_ADS1115    ads;
LiquidCrystal_I2C   lcd(0x27, 20, 4);
RTC_DS3231          rtc;
SoftwareSerial      bluetooth(10, 11);   // RX=10, TX=11 → HC-05

// ── Estado do instrumento ─────────────────────────────────────────
enum Arranjo { WENNER, SCHLUMBERGER };
Arranjo arranjoAtual = WENNER;

float param_a = 1.0;     // Espaçamento 'a' em metros (Wenner) ou MN/2 (Schlumberger)
float param_L = 5.0;     // AB/2 em metros (apenas Schlumberger)
int   medicao_num = 0;   // Contador de medições

// ════════════════════════════════════════════════════════════════
// SETUP
// ════════════════════════════════════════════════════════════════
void setup() {
  Serial.begin(9600);
  bluetooth.begin(9600);

  // Pinos de controle
  pinMode(PIN_INJECT_EN,  OUTPUT);
  pinMode(PIN_INJECT_POL, OUTPUT);
  digitalWrite(PIN_INJECT_EN,  LOW);   // Injeção desligada por padrão
  digitalWrite(PIN_INJECT_POL, LOW);

  // ADS1115
  ads.setGain(GAIN_SIXTEEN);  // ±0.256V → 7.8125 µV/LSB
  if (!ads.begin()) {
    Serial.println("ERRO: ADS1115 não encontrado!");
  }

  // LCD
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0); lcd.print("ResistivDIY v1.0");
  lcd.setCursor(0, 1); lcd.print("Inicializando...");

  // SD Card
  if (!SD.begin(PIN_SD_CS)) {
    lcd.setCursor(0, 2); lcd.print("SD: FALHA");
    Serial.println("AVISO: SD Card não encontrado. Log desabilitado.");
  } else {
    // Cria cabeçalho do CSV se arquivo não existe
    if (!SD.exists("dados.csv")) {
      File f = SD.open("dados.csv", FILE_WRITE);
      if (f) {
        f.println("num,timestamp,arranjo,a_m,L_m,I_mA,dV_mV,K,rho_ohm_m,qualidade");
        f.close();
      }
    }
  }

  // RTC
  if (!rtc.begin()) {
    Serial.println("AVISO: RTC DS3231 não encontrado.");
  }

  lcd.setCursor(0, 1); lcd.print("Pronto.         ");
  lcd.setCursor(0, 2); lcd.print("Arranjo: Wenner ");
  lcd.setCursor(0, 3); lcd.print("a=1.0m          ");

  Serial.println("=== ResistivDIY v1.0 ===");
  Serial.println("Comandos: MEDIR | SET_A:[m] | SET_L:[m] | WENNER | SCHLUMBERGER | STATUS | AJUDA");
  enviarBT("PRONTO");
}

// ════════════════════════════════════════════════════════════════
// FUNÇÕES DE MEDIÇÃO
// ════════════════════════════════════════════════════════════════

// Mede corrente pelo ACS712 (média de N amostras)
float medirCorrente() {
  long soma = 0;
  for (int i = 0; i < NUM_SAMPLES; i++) {
    soma += analogRead(PIN_ACS712);
    delayMicroseconds(200);
  }
  float tensao  = (soma / (float)NUM_SAMPLES) * (ACS712_VCC / 1023.0);
  float corrente = (tensao - ACS712_OFFSET) / ACS712_SENSITIVITY;
  return abs(corrente);  // Amperes
}

// Mede tensão diferencial MN pelo ADS1115 + INA128
float medirTensao() {
  long soma = 0;
  for (int i = 0; i < NUM_SAMPLES; i++) {
    soma += ads.readADC_Differential_0_1();
    delay(2);  // Aguarda próxima conversão ADS1115
  }
  float raw       = soma / (float)NUM_SAMPLES;
  float vADS      = raw * 0.0000078125;    // 7.8125 µV/bit com GAIN_SIXTEEN
  float vMN_amp   = vADS / INA128_GAIN;   // Desfaz ganho INA128
  float vMN_real  = vMN_amp * DIVISOR_RATIO; // Desfaz divisor de tensão
  return vMN_real;  // Volts
}

// Calcula o fator geométrico K para o arranjo configurado
float calcularK() {
  if (arranjoAtual == WENNER) {
    return 2.0 * PI * param_a;
  } else {
    // Schlumberger: K = π · (L²/2a − a/2)
    return PI * ((param_L * param_L) / (2.0 * param_a) - param_a / 2.0);
  }
}

// Realiza medição completa com inversão de polaridade
// Retorna resistividade em Ω·m, ou -1 em caso de erro
float medirResistividade(float &I_out, float &dV_out) {
  // ── Polaridade direta ────────────────────────────────────────
  digitalWrite(PIN_INJECT_POL, LOW);
  digitalWrite(PIN_INJECT_EN,  HIGH);
  delay(INJECT_STABILIZE_MS);

  float I1  = medirCorrente();
  float dV1 = medirTensao();

  // ── Polaridade invertida (cancela polarização eletrolítica) ──
  digitalWrite(PIN_INJECT_POL, HIGH);
  delay(INJECT_STABILIZE_MS);

  float I2  = medirCorrente();
  float dV2 = medirTensao();

  // ── Desliga injeção ──────────────────────────────────────────
  digitalWrite(PIN_INJECT_EN, LOW);

  // ── Médias ───────────────────────────────────────────────────
  I_out  = (I1 + I2) / 2.0;
  dV_out = (abs(dV1) + abs(dV2)) / 2.0;

  if (I_out < 0.001) return -1.0;  // Corrente abaixo de 1 mA: erro

  float K   = calcularK();
  float rho = K * (dV_out / I_out);
  return rho;
}

// ════════════════════════════════════════════════════════════════
// LOG E SAÍDA
// ════════════════════════════════════════════════════════════════

void enviarBT(String msg) {
  bluetooth.println(msg);
}

void logCSV(float rho, float I, float dV) {
  File f = SD.open("dados.csv", FILE_WRITE);
  if (!f) return;

  DateTime now = rtc.now();
  medicao_num++;

  f.print(medicao_num); f.print(",");
  f.print(now.timestamp(DateTime::TIMESTAMP_FULL)); f.print(",");
  f.print(arranjoAtual == WENNER ? "Wenner" : "Schlumberger"); f.print(",");
  f.print(param_a, 3); f.print(",");
  f.print(param_L, 3); f.print(",");
  f.print(I * 1000.0, 3); f.print(",");   // mA
  f.print(dV * 1000.0, 4); f.print(",");  // mV
  f.print(calcularK(), 3); f.print(",");
  f.print(rho, 2); f.print(",");
  f.println(rho > 0 ? "OK" : "ERRO");
  f.close();
}

void atualizarLCD(float rho, float I, float dV) {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(arranjoAtual == WENNER ? "Wenner a=" : "Schlumb L=");
  lcd.print(arranjoAtual == WENNER ? param_a : param_L, 1);
  lcd.print("m");
  lcd.setCursor(0, 1);
  lcd.print("Rho: ");
  lcd.print(rho < 0 ? 0 : rho, 1);
  lcd.print(" Om.m");
  lcd.setCursor(0, 2);
  lcd.print("I="); lcd.print(I * 1000.0, 1); lcd.print("mA");
  lcd.setCursor(10, 2);
  lcd.print("dV="); lcd.print(dV * 1000.0, 2); lcd.print("mV");
  lcd.setCursor(0, 3);
  lcd.print("Med#"); lcd.print(medicao_num);
}

// ════════════════════════════════════════════════════════════════
// LOOP PRINCIPAL — interpretação de comandos
// ════════════════════════════════════════════════════════════════
void loop() {
  String cmd = "";

  if (Serial.available())    cmd = Serial.readStringUntil('\n');
  if (bluetooth.available()) cmd = bluetooth.readStringUntil('\n');

  if (cmd.length() == 0) return;
  cmd.trim();
  cmd.toUpperCase();

  // ── MEDIR ────────────────────────────────────────────────────
  if (cmd == "MEDIR") {
    lcd.clear();
    lcd.print("Injetando...");
    Serial.println("Iniciando medicao...");

    float I = 0, dV = 0;
    float rho = medirResistividade(I, dV);

    atualizarLCD(rho, I, dV);
    logCSV(rho, I, dV);

    String resp = "RHO:" + String(rho, 2)
                + ",I:" + String(I * 1000.0, 2)
                + ",dV:" + String(dV * 1000.0, 3)
                + ",K:" + String(calcularK(), 3)
                + ",A:" + String(param_a)
                + ",L:" + String(param_L)
                + ",N:" + String(medicao_num);

    Serial.println(resp);
    enviarBT(resp);

  // ── SET_A ────────────────────────────────────────────────────
  } else if (cmd.startsWith("SET_A:")) {
    param_a = cmd.substring(6).toFloat();
    lcd.setCursor(0, 3); lcd.print("a=" + String(param_a, 2) + "m    ");
    String r = "OK:A=" + String(param_a, 3);
    Serial.println(r); enviarBT(r);

  // ── SET_L ────────────────────────────────────────────────────
  } else if (cmd.startsWith("SET_L:")) {
    param_L = cmd.substring(6).toFloat();
    lcd.setCursor(0, 3); lcd.print("L=" + String(param_L, 2) + "m    ");
    String r = "OK:L=" + String(param_L, 3);
    Serial.println(r); enviarBT(r);

  // ── WENNER / SCHLUMBERGER ────────────────────────────────────
  } else if (cmd == "WENNER") {
    arranjoAtual = WENNER;
    lcd.setCursor(0, 2); lcd.print("Arranjo: Wenner ");
    String r = "OK:WENNER";
    Serial.println(r); enviarBT(r);

  } else if (cmd == "SCHLUMBERGER") {
    arranjoAtual = SCHLUMBERGER;
    lcd.setCursor(0, 2); lcd.print("Arranjo: Schlumb");
    String r = "OK:SCHLUMBERGER";
    Serial.println(r); enviarBT(r);

  // ── STATUS ───────────────────────────────────────────────────
  } else if (cmd == "STATUS") {
    String resp = "STATUS:"
                + String(arranjoAtual == WENNER ? "Wenner" : "Schlumberger")
                + ",A:" + String(param_a, 3)
                + ",L:" + String(param_L, 3)
                + ",N:" + String(medicao_num);
    Serial.println(resp); enviarBT(resp);

  // ── AJUDA ────────────────────────────────────────────────────
  } else if (cmd == "AJUDA") {
    String h = "Comandos:\n"
               "  MEDIR          → realiza medicao\n"
               "  SET_A:[metros] → define espac. a (Wenner) ou MN/2\n"
               "  SET_L:[metros] → define AB/2 (Schlumberger)\n"
               "  WENNER         → seleciona arranjo Wenner\n"
               "  SCHLUMBERGER   → seleciona arranjo Schlumberger\n"
               "  STATUS         → exibe configuracao atual\n"
               "  AJUDA          → esta mensagem";
    Serial.println(h); enviarBT(h);

  } else {
    Serial.println("CMD_DESCONHECIDO: " + cmd);
  }
}

6.3 Formato do arquivo CSV de saída

O cartão SD grava dados.csv com o seguinte formato:

num,timestamp,arranjo,a_m,L_m,I_mA,dV_mV,K,rho_ohm_m,qualidade
1,2025-06-15T09:23:11,Schlumberger,0.500,1.000,45.230,12.3450,3.141,0.86,OK
2,2025-06-15T09:24:05,Schlumberger,0.500,1.500,43.110,28.7610,11.00,7.33,OK
3,2025-06-15T09:25:18,Schlumberger,0.500,2.000,41.890,55.2300,22.78,29.94,OK

7. Interface Android via Bluetooth

7.1 Configuração do módulo HC-05

Antes de usar em campo, configure o HC-05 no modo AT (segurar o botão ao energizar; LED pisca lentamente):

// Comunicação com HC-05 em modo AT: 38400 baud, sem paridade
// Use monitor serial do Arduino IDE ou terminal serial

AT                          → OK  (testa comunicação)
AT+NAME=ResistivDIY         → OK  (define nome Bluetooth)
AT+PSWD=1234                → OK  (define senha de pareamento)
AT+UART=9600,0,0            → OK  (baud rate para modo normal)
AT+ROLE=0                   → OK  (modo escravo — aguarda conexão)

Após configurar, reinicie o HC-05 normalmente (sem segurar o botão). O LED passa a piscar rapidamente quando aguardando conexão.

7.2 Opção 1: MIT App Inventor 2 (recomendado — sem programação)

Acesse appinventor.mit.edu e crie um novo projeto. Componentes necessários:

Designer (interface visual):

Componente Tipo Propriedade relevante
ListPickerBT ListPicker Para selecionar dispositivo BT
BtClient BluetoothClient Gerencia conexão
BtnMedir Button Text: "MEDIR"
BtnWenner Button Text: "Wenner"
BtnSchlumb Button Text: "Schlumberger"
TxtA TextBox Hint: "Espaçamento a (m)"
TxtL TextBox Hint: "AB/2 = L (m)"
LblRho Label FontSize: 24, Text: "ρ = --- Ω·m"
LblI Label Text: "I = --- mA"
LblDV Label Text: "ΔV = --- mV"
Clock1 Clock TimerInterval: 500 ms
TinyDB1 TinyDB Armazenamento local

Blocos de lógica (pseudocódigo):

// Conectar ao HC-05
quando ListPickerBT.AfterPicking:
  BtClient.Connect(ListPickerBT.Selection)

// Botão MEDIR
quando BtnMedir.Click:
  se BtClient.IsConnected:
    BtClient.SendText("MEDIR\n")

// Botão SET arranjo
quando BtnWenner.Click:
  BtClient.SendText("WENNER\n")

// Definir espaçamento a
quando TxtA.LostFocus:
  BtClient.SendText("SET_A:" + TxtA.Text + "\n")

// Definir L (Schlumberger)
quando TxtL.LostFocus:
  BtClient.SendText("SET_L:" + TxtL.Text + "\n")

// Receber dados (Clock a cada 500ms)
quando Clock1.Timer:
  se BtClient.IsConnected e BtClient.BytesAvailableToReceive > 0:
    texto = BtClient.ReceiveText(512)

    se texto.contains("RHO:"):
      partes = texto.split(",")
      rho = partes[0].split(":")[1]   // "RHO:XX.X" → "XX.X"
      I   = partes[1].split(":")[1]   // "I:XX.X"
      dV  = partes[2].split(":")[1]   // "dV:XX.X"

      LblRho.Text = "ρ = " + rho + " Ω·m"
      LblI.Text   = "I = " + I + " mA"
      LblDV.Text  = "ΔV = " + dV + " mV"

      // Salvar no TinyDB
      TinyDB1.StoreValue(tag: "med_" + Clock1.Now, value: texto)

7.3 Opção 2: Serial Bluetooth Terminal (sem programação alguma)

O app Serial Bluetooth Terminal (gratuito, Play Store) permite uso imediato:

  1. Instalar o app
  2. Parear o celular com o HC-05 (senha: 1234)
  3. Abrir o app → conectar ao "ResistivDIY"
  4. Digitar comandos manualmente: MEDIR, SET_A:1.5, etc.
  5. O log completo de texto pode ser exportado via email ou salvo como .txt

Configurar atalhos no app: - Macro 1: MEDIR\n - Macro 2: STATUS\n - Macro 3: SCHLUMBERGER\n - Macro 4: WENNER\n

7.4 Opção 3: App Python com Buildozer (avançado)

Para quem deseja um app dedicado com gráfico de curva SEV em tempo real, é possível usar Kivy + python-for-android:

# Instalar dependências no PC de desenvolvimento (Linux recomendado):
# pip install buildozer kivy
# sudo apt install android-sdk

# arquivo main.py (Kivy)
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.garden.matplotlib import FigureCanvasKivyAgg
import matplotlib.pyplot as plt
import numpy as np

class ResistivLayout(BoxLayout):
    def __init__(self, **kw):
        super().__init__(orientation='vertical', **kw)
        self.medicoes = []  # lista de (L, rho)

        self.lbl = Label(text='ρ = --- Ω·m', font_size='20sp', size_hint_y=0.1)
        self.add_widget(self.lbl)

        self.fig, self.ax = plt.subplots()
        self.ax.set_xlabel('AB/2 (m)')
        self.ax.set_ylabel('ρ aparente (Ω·m)')
        self.ax.set_xscale('log')
        self.ax.set_yscale('log')
        self.ax.grid(True, which='both', alpha=0.4)
        self.canvas_widget = FigureCanvasKivyAgg(self.fig)
        self.add_widget(self.canvas_widget)

        btn = Button(text='MEDIR', size_hint_y=0.1)
        btn.bind(on_press=self.medir)
        self.add_widget(btn)

    def medir(self, *args):
        # Enviar comando via BT e parsear resposta
        # (implementar conexão BT via jnius ou bleak)
        pass

    def atualizar_grafico(self, L, rho):
        self.medicoes.append((L, rho))
        Ls   = [m[0] for m in self.medicoes]
        rhos = [m[1] for m in self.medicoes]
        self.ax.clear()
        self.ax.loglog(Ls, rhos, 'bo-', markersize=6)
        self.ax.set_xlabel('AB/2 (m)')
        self.ax.set_ylabel('ρ aparente (Ω·m)')
        self.ax.grid(True, which='both', alpha=0.4)
        self.canvas_widget.draw()

class ResistivApp(App):
    def build(self):
        return ResistivLayout()

if __name__ == '__main__':
    ResistivApp().run()

8. Caixa em Impressão 3D

8.1 Parâmetros de impressão recomendados

Parâmetro Valor recomendado
Dimensões externas 220 × 160 × 90 mm (corpo + tampa)
Espessura da parede 3–4 mm
Material PETG (resistência UV + calor) ou ASA (UV exterior)
Infill 40%, padrão gyroid
Temperatura bico (PETG) 230–240°C
Temperatura mesa 70–80°C com brim
Suportes Sim, para furos laterais dos conectores
Camada inicial 0,2–0,3 mm
Acabamento vedação Borracha EPDM 10×3 mm no friso + 4× parafusos M3 inox
Inserts metálicos M3 heat-set para postes do Arduino e PCB

8.2 Elementos do design

Tampa (face superior):

- Janela recortada 98×40 mm para encaixe do LCD 20×4
  (borda de 2 mm ao redor do visor, chanfro 45°)
- 4× furos M3 passantes nos cantos para fechamento
- Ranhura lateral 6×3 mm para saída do cabo da antena HC-05
- Texto em relevo: "ResistivDIY" + seta de aterramento
- Friso perimetral 3×3 mm para gaxeta EPDM

Corpo (base):

- 4× postes Ø6 mm H=10 mm com insert M3 heat-set para Arduino Mega
- 2× postes menores para PCB de medição (espaçamento: medir antes)
- Painel frontal com furos:
    - 6× furo Ø4,2 mm para conectores banana 4 mm (A, B, M, N + 2 reservas)
    - 1× furo Ø12 mm para chave gangorra 220V/15A (LIGA/DESLIGA)
    - 1× janela 30×15 mm para LED de status (vermelho = injeção ativa)
    - 1× furo Ø6 mm para conector DC 5,5/2,1 mm (entrada bateria)
- Painel traseiro:
    - 1× furo Ø6 mm para slot cartão SD (acesso externo)
    - Saída de cabo PP para eletrodos (prensa-cabo M16)
- Compartimento interno direito: 80×50×60 mm para bateria 12V
- Canal de roteamento de cabos em relevo no fundo (H=5 mm)
- 4× pés Ø12×3 mm na base (imprimir em TPU, ou colar borracha autoadesiva)

8.3 Onde encontrar modelos de referência

Fonte Busca sugerida Observações
gitlab.irstea.fr/reversaal/OhmPi Repositório oficial Arquivos STL da caixa OhmPi v2023
Thingiverse.com "Arduino Mega enclosure field" Templates adaptáveis
Printables.com "IP65 electronics enclosure" Modelos com vedação
GrabCAD "geophysics field instrument box" Modelos CAD paramétricos

8.4 Alternativa sem impressora 3D

Caixas de PVC para instalações elétricas (padrão ABNT NBR 5410):

  • Legrand/Schneider 200×150×80 mm — ~R$ 25 em lojas de material elétrico
  • Furar com serra-copo Ø32 mm para os conectores banana
  • Usar prensa-cabos M16/M20 para entrada dos cabos de eletrodos
  • Vedar tampas com fita autofusão ou silicone neutro

9. Procedimento de Campo

9.1 Preparação pré-campo

  • [ ] Carregar bateria 12V completamente (verificar com multímetro: ≥ 12,6V)
  • [ ] Formatar cartão SD (FAT32) e verificar espaço livre
  • [ ] Verificar RTC (hora e data corretas via STATUS)
  • [ ] Testar conexão Bluetooth com o celular/tablet
  • [ ] Preparar planilha de campo impressa (ver modelo na seção 9.4)
  • [ ] Carregar carretel de cabo PP (100 m)
  • [ ] Verificar eletrodos: sem oxidação severa, rosca funcional
  • [ ] Preparar solução salina (30 g NaCl por litro d'água) para umedecer eletrodos

9.2 Sequência de medição — SEV Schlumberger

Passo 1 — Marcação e instalação inicial

1. Escolha uma linha reta de ~200 m em terreno aberto (evite cercas metálicas,
   postes de energia e estruturas metálicas a menos de 30 m da linha).

2. Marque o centro (ponto C) com uma estaca.

3. Instale os eletrodos MN:
   - M: 0,25 m a OESTE do centro
   - N: 0,25 m a LESTE do centro
   (MN = 0,5 m → a = MN/2 = 0,25 m)

4. Instale A e B simetricamente:
   - A: 1,0 m a OESTE do centro (AB/2 = L = 1,0 m)
   - B: 1,0 m a LESTE do centro

5. Umedeça os 4 eletrodos com solução salina (reduz resistência de contato).

6. Conecte os cabos: A→terminal A, B→terminal B, M→terminal M, N→terminal N.

Passo 2 — Sequência de espaçamentos

Sequência padrão para SEV com MN = 0,5 m (a = 0,25 m):

Passo AB/2 = L (m) MN (m) a = MN/2 (m) K Schlumberger Ação MN?
1 1,0 0,5 0,25 11,78
2 1,5 0,5 0,25 27,49
3 2,0 0,5 0,25 49,74
4 3,0 0,5 0,25 113,9
5 5,0 0,5 0,25 313,7 Mover MN para 2,0 m
6 5,0 2,0 1,00 74,61
7 7,0 2,0 1,00 151,0
8 10,0 2,0 1,00 313,1 Mover MN para 5,0 m
9 10,0 5,0 2,50 119,4
10 15,0 5,0 2,50 277,5
11 20,0 5,0 2,50 497,0 Mover MN para 10,0 m
12 20,0 10,0 5,00 232,5
13 30,0 10,0 5,00 534,1
14 50,0 10,0 5,00 1492

Regra: Quando L ≥ 5 × a, mover MN para MN_novo = L/5 × 2. Repetir a medição com o novo MN antes de continuar avançando AB.

Passo 3 — Medição em cada ponto

Para cada espaçamento AB/2 = L:

  1. Enviar SET_L:[valor] pelo app Android (ou digitar no Serial Monitor)
  2. Se MN foi reposicionado, enviar SET_A:[novo_a]
  3. Verificar tensão da bateria no LCD (deve ser ≥ 11,5V)
  4. Pressionar MEDIR (ou enviar comando "MEDIR")
  5. Aguardar ~3–5 s para a medição com inversão de polaridade
  6. Anotar na planilha: ρ_ap, I (mA), ΔV (mV)
  7. Repetir 3× — verificar consistência (desvio < 5% entre leituras)
  8. Usar a média das 3 repetições como valor final

Passo 4 — Controle de qualidade em campo

Situação Causa provável Ação
I < 1 mA Solo muito resistivo ou contato ruim Umedecer eletrodos; aumentar V_boost
ΔV > ADS_RANGE (saturação) Ganho INA128 muito alto Reduzir ganho (aumentar Rg para 100 Ω → ganho ~501)
Desvio entre repetições > 10% Ruído elétrico ou eletrodo solto Verificar contatos; aguardar horário com menos RFI
ρ negativo Polarização residual Aumentar INJECT_STABILIZE_MS para 500 ms
LCD mostra ERRO Corrente < 1 mA Ver linha acima

9.3 Planilha de campo

Projeto: ________________________  Data: ________  Operador: _______________
Localização: ___________________  Coord. GPS: _____________________________
Solo: __________________  Chuva nas últimas 24h: Sim / Não
Obs. gerais: ____________________________________________________________

Ponto C (sondagem): ___________________________________________________

  AB/2   MN/2    K        I (mA)   ΔV (mV)   ρ_ap (Ω·m)   Rep1   Rep2   Rep3   Média
  (m)    (m)    (calc)
  ----   ----   ------   ------   -------   ----------   ----   ----   ----   -----
  1,0    0,25   11,78    ____     ____      ____         ____   ____   ____   ____
  1,5    0,25   27,49    ____     ____      ____         ____   ____   ____   ____
  2,0    0,25   49,74    ____     ____      ____         ____   ____   ____   ____
  3,0    0,25   113,9    ____     ____      ____         ____   ____   ____   ____
  5,0    0,25   313,7    ____     ____      ____         ____   ____   ____   ____
  5,0    1,00   74,61    ____     ____      ____         ____   ____   ____   ____
  7,0    1,00   151,0    ____     ____      ____         ____   ____   ____   ____
  10,0   1,00   313,1    ____     ____      ____         ____   ____   ____   ____
  10,0   2,50   119,4    ____     ____      ____         ____   ____   ____   ____
  15,0   2,50   277,5    ____     ____      ____         ____   ____   ____   ____
  20,0   2,50   497,0    ____     ____      ____         ____   ____   ____   ____
  20,0   5,00   232,5    ____     ____      ____         ____   ____   ____   ____
  30,0   5,00   534,1    ____     ____      ____         ____   ____   ____   ____
  50,0   5,00   1492     ____     ____      ____         ____   ____   ____   ____

10. Calibração e Validação

10.1 Calibração do ACS712 (sensor de corrente)

Passo 1 — Verificar offset em repouso:
  - Com injeção DESLIGADA (PIN_INJECT_EN = LOW)
  - Medir tensão no pino OUT do ACS712 com multímetro
  - Deve ser exatamente VCC/2 = 2,500V
  - Se diferir, atualizar ACS712_OFFSET no firmware

Passo 2 — Verificar sensibilidade:
  - Conectar resistor de carga conhecido (ex: 100 Ω 5W)
  - Medir corrente com amperímetro de referência
  - Comparar com o valor calculado pelo firmware
  - Ajustar ACS712_SENSITIVITY se necessário
  - Valor nominal: 0,066 V/A (modelo 30A)

10.2 Calibração do circuito de tensão (INA128 + ADS1115)

Passo 1 — Ganho do INA128:
  - Aplicar tensão conhecida (ex: 100 mV de uma fonte ou divisor de precisão)
  - Verificar saída esperada: 100 mV × 101 = 10,1 V
  - Comparar com leitura do ADS1115 reconvertida no Serial Monitor
  - Se diferir > 2%, medir Rg real com multímetro e atualizar INA128_GAIN

Passo 2 — Divisor de tensão:
  - Aplicar tensão conhecida no eletrodo M (ex: 1,000V de fonte estabilizada)
  - Esperado no ADS1115: 1,000 / 11 / 101 = ~900 µV
  - Verificar na saída do Serial Monitor: "dV = 1,000 V"
  - Ajustar DIVISOR_RATIO se necessário

10.3 Validação em cuba com água salina

Procedimento:
  1. Preparar solução de NaCl de condutividade conhecida
     (ex: 1 g/L → σ ≈ 1,5 mS/cm → ρ ≈ 6,7 Ω·m)
  2. Medir condutividade com condutivímetro de referência
  3. Converter: ρ_ref (Ω·m) = 10 / σ (mS/cm)
  4. Montar arranjo Wenner dentro da cuba com eletrodos de inox
     (espaçamento a = 5 cm, por exemplo)
  5. Medir com o resistivímetro DIY
  6. Comparar: erro aceitável < 10% para uso educacional

Soluções de referência:
  - 0,5 g NaCl/L: σ ≈ 0,7 mS/cm → ρ ≈ 14 Ω·m
  - 1,0 g NaCl/L: σ ≈ 1,5 mS/cm → ρ ≈ 6,7 Ω·m
  - 5,0 g NaCl/L: σ ≈ 7,0 mS/cm → ρ ≈ 1,4 Ω·m
  - 35 g NaCl/L: σ ≈ 53 mS/cm  → ρ ≈ 0,19 Ω·m (água do mar)

10.4 Validação cruzada em campo

Para publicações científicas:

  1. Realizar levantamento SEV no mesmo perfil com o instrumento DIY e com equipamento comercial de referência (Syscal, ABEM Terrameter, ou similar)
  2. Comparar curvas de ρ_ap × AB/2 em gráfico bilogarítmico
  3. Calcular RMSE e desvio relativo por ponto
  4. Critério de aceitação: RMSE < 10% e desvio relativo médio < 5%
  5. Documentar diferenças sistemáticas e possíveis causas (ruído, resolução ADC, polarização residual)

11. Processamento dos Dados

11.1 Pré-processamento do CSV

# pre_processa_sev.py
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# Ler dados do SD Card
df = pd.read_csv("dados.csv")

# Filtrar apenas medições OK
df = df[df["qualidade"] == "OK"].copy()

# Converter unidades
df["I_A"]   = df["I_mA"] / 1000.0
df["dV_V"]  = df["dV_mV"] / 1000.0
df["rho"]   = df["K"] * (df["dV_V"] / df["I_A"])

# Quando MN muda, o mesmo L foi medido com dois MN diferentes:
# usar a média ponderada ou o valor com MN menor
df_sev = df.groupby("L_m").agg({"rho": "mean"}).reset_index()
df_sev.columns = ["AB2_m", "rho_ohm_m"]
df_sev = df_sev.sort_values("AB2_m")

print(df_sev)

# Plot da curva SEV
fig, ax = plt.subplots(figsize=(8, 5))
ax.loglog(df_sev["AB2_m"], df_sev["rho_ohm_m"], "bo-", markersize=7, linewidth=1.5)
ax.set_xlabel("AB/2 (m)", fontsize=12)
ax.set_ylabel("ρ aparente (Ω·m)", fontsize=12)
ax.set_title("Curva SEV — Resistividade Aparente × Espaçamento", fontsize=13)
ax.grid(True, which="both", alpha=0.4)
ax.grid(True, which="minor", linestyle=":", alpha=0.3)
plt.tight_layout()
plt.savefig("curva_sev.png", dpi=150)
plt.show()

# Salvar para IPI2WIN (formato .wf)
with open("sev_ipi2win.wf", "w") as f:
    f.write("SEV ResistivDIY\n")
    f.write("Schlumberger\n")
    for _, row in df_sev.iterrows():
        f.write(f"{row['AB2_m']:.3f}  {row['rho_ohm_m']:.3f}\n")

print("Arquivo sev_ipi2win.wf exportado.")

11.2 Softwares de inversão gratuitos

Software Tipo Sistema Download Uso
IPI2WIN SEV 1D Windows geol.msu.ru Inversão Schlumberger/Wenner — interface simples
ResIPy ERT 2D/3D Python/Win/Linux hkex.ac.uk/ResIPy Open source, inversão avançada com interface gráfica
RES2DINV ERT 2D Windows geotomosoft.com Versão demo (limitada a 300 pontos)
ZondRes2d ERT 2D Windows zond-geo.ru Versão demo disponível
pyGIMLi ERT 2D/3D Python pygimli.org Open source, altamente configurável

11.3 Interpretação básica de curvas SEV

Padrões típicos de curvas Schlumberger:

Tipo A  (ρ₁ < ρ₂ < ρ₃):  curva sempre crescente
                           → camadas progressivamente mais resistivas
                           Ex: argila → areia → rocha sã

Tipo H  (ρ₁ > ρ₂ < ρ₃):  mínimo intermediário
                           → camada condutora entre duas resistivas
                           Ex: solo → aquífero → rocha

Tipo K  (ρ₁ < ρ₂ > ρ₃):  máximo intermediário
                           → camada resistiva entre duas condutoras
                           Ex: argila → areia seca → argila saturada

Tipo Q  (ρ₁ > ρ₂ > ρ₃):  curva sempre decrescente
                           → camadas progressivamente mais condutoras
                           Ex: rocha → saprólito → argila

12. Referências e Recursos

Projetos científicos de referência

  1. Clark, L. & Page, R. (2011)
    Geophysical characterisation of groundwater resources in semi-arid regions of sub-Saharan Africa.
    Hydrogeology Journal, 19(8), 1479–1492.
    DOI: 10.1007/s10040-010-0692-0
    → Design seminal de resistivímetro DIY DC por ~US$250. Validado em campo em Chad, Tanzania, Nigéria e Ruanda.

  2. Clément, R. et al. (2020)
    OhmPi: An open source data logger for dedicated applications of electrical resistivity imaging.
    SoftwareX, 11, 100455.
    DOI: 10.1016/j.softx.2020.100455
    → Projeto OhmPi com Raspberry Pi. Até 32 eletrodos por ~US$500. Código Python open source.
    Site oficial: ohmpi.org

  3. Vega, M. de la et al. (2021)
    Design of a Low‐Cost Electrical Resistivity Meter for Near Surface Surveys.
    Earth and Space Science, 8(12), e2020EA001575.
    DOI: 10.1029/2020EA001575
    → Arduino DUE. Arranjos Dipolo-Dipolo, Wenner-Schlumberger e Wenner. Erro relativo 0,6–5,5% vs. comercial.

  4. Sirota, D. & Roth, G. (2022)
    Development and validation of a low-cost direct current resistivity meter for humanitarian geophysics applications.
    Geophysics, 87(1), WA1–WA14.
    DOI: 10.1190/geo2021-0058.1
    → Redesenho e validação do instrumento Clark & Page com data logger Raspberry Pi.

  5. Fauzi, M. et al. (2019)
    Low-cost multi electrode resistivity meter based on microcontroller for electric resistivity tomography purpose.
    IOP Conf. Series: Journal of Physics, 1153, 012022.
    DOI: 10.1088/1742-6596/1153/1/012022
    → Arduino Mega 2560 com multiplexação via IC74HC595 e relés para ERT multieletrodo.

Recursos de software

Bibliotecas Arduino utilizadas

Adafruit ADS1X15     → github.com/adafruit/Adafruit_ADS1X15
LiquidCrystal I2C    → github.com/johnrickman/LiquidCrystal_I2C
RTClib               → github.com/adafruit/RTClib
SD                   → (built-in na IDE Arduino)
Wire                 → (built-in na IDE Arduino)
SoftwareSerial       → (built-in na IDE Arduino)

Documentação elaborada com base em projetos científicos publicados e validados. Para uso educacional e de pesquisa. Não substitui equipamentos profissionais para prospecção comercial.

Baseado em: OhmPi (INRAE France), Clark & Page (2011), Vega et al. (2021), Sirota & Roth (2022).