/*############################################################################
  # Codigo criado por: sasiskas
  # Dispovivel em: https://www.instructables.com/DIY-Li-On-Capacity-Tester-and-More/
  # Data: 27/12/2023
  # Detalhes do projeto: v2.3.1
  # Modificado e traduzido por: Mario Parente
  ############################################################################*/

//-----------------------------------------------------Testador de capacidade da bateria e mais V2.3.0-----------------------------------------------------------

#include <SPI.h>
#include <stdlib.h>
#include <Adafruit_SSD1306.h>

// Variaveis para utilização no Registro de tempo
float Segundo = 0;
int T_Hora = 0;
int T_Minuto = 0;
int T_Segundo = 0;
char buf[21];

unsigned long previousMillis = 0;            
unsigned long millisPassed = 0;
unsigned long BatFull = 0;

float BatMin = 3.4;
float BatVoltQuiescent = 0;                                             // Tensão da bateria quando não há carga na bateria
float Capacity = 0.0;                                                   // Capacidade calculada da bateria, medida durante a descarga
float mA = 0;
float SetI = 0;                                                         // Ponto de ajuste para a corrente de descarga. Lembre-se que você pode ajustar a corrente de descarga usando o trimpot 500K.
float ChargeI = 0;
float CurTP4056 = 0;
float ResTP4056 = 0;
float ratioRI = 0;
float BatLevel = 0;                                                     // Porcentagem de carga/nível da baterial
float BatVoltCorrected = 0;                                             // Tensão da bateria, medida com base na referência interna do arduino
float A2VoltCorrected = 0;
float VoltTP4056Pin2  = 0;
float Rprog = 0; 
float BatRes = 0;                                                       // Resistência interna da bateria
const float RES = 3.3;   // <--                                         // Valor do seu resistor. O valor sugerido é 1 Ohm. Altere-o, se você usar um valor de resistor diferente

#define CLK 2
#define DT 3
#define SW 4
#define MOSFET_Discharge 9                                              // É um N-MOSFET, então HIGH está ON e LOW está OFF
#define MOSFET_Charge 8                                                 // É um P-MOSFET, então HIGH está OFF e LOW está ON
#define LED 13
#define PinBuz 6

char screen = 0;
char arrowpos = 0;
char BatVoltQuiescentValue = 0;                                          // Se existe um valor para "tensão da bateria sem carga" ou não. 1 para sim e 0 para não.
const unsigned char PS_128 = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
volatile boolean TurnDetected = false;
volatile boolean up = false;
volatile boolean button = false;

#define SCREEN_WIDTH 128                  // Largura da tela OLED, em pixels
#define SCREEN_HEIGHT 64                  // Altura da tela OLED, em pixels
#define OLED_RESET -1                     // Pino de reset # (ou -1 se compartilhar o pino de reset do Arduino)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

static const unsigned char PROGMEM Bateria[] =  {
B11111111, B11111110,
B10000000, B00000010,
B10000000, B00000011,
B10000000, B00000011,
B10000000, B00000011,
B10000000, B00000010,
B11111111, B11111110,
};

static const unsigned char PROGMEM Status_Bateria_Carregar[] =  {
B00000000,B00000000,
B00001000,B00001000,
B00011100,B00010000,
B00111110,B00100000,
B01111111,B01111100,
B00011100,B00001000,
B00011100,B00010000,
B00011100,B00100000,
};

static const unsigned char PROGMEM Status_Bateria_Descarregar[] =  {
B00000000,B00000000,
B00011100,B00001000,
B00011100,B00010000,
B00011100,B00100000,
B01111111,B01111100,
B00111110,B00001000,
B00011100,B00010000,
B00001000,B00100000,
};

static const unsigned char PROGMEM cedinha[] =  {
B00011100,
B00001000,
B00011000,
};

ISR(PCINT2_vect) {
  if (digitalRead(SW) == LOW) {
    button = true;
    tone(PinBuz, 1300, 40);
  }
}

void isr0 () {
  TurnDetected = true;
  up = (digitalRead(CLK) == digitalRead(DT));
}

void Config_Ini(){
  arrowpos = 1;
  display.setCursor(0,0); 
  display.print(F("Iniciando config. do testador."));
  while (arrowpos == 1) {
    delay(150);
    if (TurnDetected) {       
       if (up && BatMin > 2.1) {
        BatMin +=0.1;
        }
       else{
        BatMin -=0.1;
        BatMin = max(BatMin, 2.2);
        }
      TurnDetected = false;
    }
    Modo_Configuracao();
    display.display();
    if (digitalRead(SW) == LOW) {
      arrowpos = 0;
      button = false;
    }
  }
  display.display(); 
  delay(50);
}

void setup() {
  pinMode(LED, OUTPUT);
  digitalWrite(LED, HIGH);
  pinMode(MOSFET_Discharge, OUTPUT);
  pinMode(MOSFET_Charge, OUTPUT);
  digitalWrite(MOSFET_Discharge, LOW);
  digitalWrite(MOSFET_Charge, HIGH);
  pinMode(PinBuz, OUTPUT);
  pinMode(SW, INPUT_PULLUP);
  pinMode(CLK, INPUT);
  pinMode(DT, INPUT);
  PCICR |= 0b00000100;
  PCMSK2 |= 0b00010000;   // Desliga PCINT20(D4)
  attachInterrupt(0, isr0, RISING);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  //Inicializa OLED com endereço I2C 0x3C (para 128x64)
  display.clearDisplay();
  display.setTextColor(WHITE,BLACK);  //configura o display para ativar 'branco' no pixel
  display.setTextSize(1); //tamanho do texto


  Config_Ini();
  display.clearDisplay();
  Menu(); //Limpeza e Menu Inicial
  display.setCursor(0,0); 
  display.print(F("Testador de"));    
  display.setCursor(0,8);  
  display.print(F("Capacidade de Bateria"));
  display.setCursor(2, 19);
  display.write(26);
  display.display(); 
   /*  TESTE
  display.contrast(100);
  display.ssd1306_command(SSD1306_SETCONTRAST);
  display.ssd1306_command(contrast);
  display.dim(true);  */  
}

void loop() {
  int in0 = analogRead(A0);                                           //lê o valor do pino A0
  int sensorValue1 = analogRead(A1);                                  //lê o valor do pino A1
  float val0 = in0 * 5.0 / 1024.0;               
  float supply = readVcc() / 1000.0;
  SetI = sensorValue1 * (5.00 / 1024.00) / RES * 1000;                // Calcular a taxa de descarga da bateria
  if (SetI <= 1200) {          
    SetI = SetI;
  }

  else{
    SetI = 1200;
  }

  BatVoltCorrected = supply / 5 * val0 * 4.35;                         //Caso você use divisores de tensão diferentes, você precisa alterar o número 4.3 de acordo.
  millisPassed = millis() - previousMillis;
  previousMillis = millis();
  //------------------------------------------------------------------- calcula a corrente de carga ------------------------------------------------------------------------

  int in2 = analogRead(A2);                                             //leia o valor do pino A2
  int in3 = analogRead(A3);                                             //leia o valor do pino A3
  float val2 = in2 * 5.0 / 1024.0; 
  float val3 = in3 * 5.0 / 1024.0; 
  A2VoltCorrected = supply / 5 * val2;                                  //calcula a leitura do pino A2 com base na referência de tensão interna
  VoltTP4056Pin2 = supply / 5 * val3;                             		  //calcula a leitura do pino A3 com base na referência de tensão interna

  Rprog = 1220 + (A2VoltCorrected * 1220 / (VoltTP4056Pin2 - A2VoltCorrected));  //calcula o Rprog do módulo TP4056

                                                                         //calcula a corrente de carregamento com base nos números da folha de dados TP4056
  if (Rprog >= 10000) { 
	  CurTP4056 =130 ;
	  ResTP4056 =10000 ;
	  ratioRI = 0.107 ;
  }
  else if (Rprog < 10000 && Rprog >= 5000) {
    CurTP4056 = 250 ;
	  ResTP4056 = 5000 ;
	  ratioRI = 0.024 ;
  }
  else if (Rprog < 5000 && Rprog >= 4000) {
    CurTP4056 = 300 ;
	  ResTP4056 = 4000 ;
	  ratioRI = 0.050 ;
  }
  else if (Rprog < 4000 && Rprog >= 3000) {
    CurTP4056 = 400 ;
	  ResTP4056 = 3000 ;
	  ratioRI = 0.100 ;
  }
  else if (Rprog < 3000 && Rprog >= 2000) {
    CurTP4056 = 580 ;
	  ResTP4056 = 2000 ;
	  ratioRI = 0.180 ;
  }
  else if (Rprog < 2000 && Rprog >= 1660) {
    CurTP4056 = 690 ;
	  ResTP4056 = 1660 ;
	  ratioRI = 0.324 ;
  }
  else if (Rprog < 1660 && Rprog >= 1500) {
    CurTP4056 = 780 ;
	  ResTP4056 = 1500 ;
	  ratioRI = 0.563 ;
  }
  else if (Rprog < 1500 && Rprog >= 1330) {
    CurTP4056 = 900 ;
    ResTP4056 = 1330 ;
    ratioRI = 0.706 ;
  }
  else if (Rprog >= 1220) {
    CurTP4056 = 995 ;
    ResTP4056 = 1220 ;
   ratioRI = 0.864 ;
  }
  if (Rprog < 1220) {
    ChargeI = 1000 ;
  }
  else {
    ChargeI = (CurTP4056 - ((Rprog - ResTP4056) * ratioRI));
  }  
  if (ChargeI > 0) {
    ChargeI = ChargeI;
  }
  else{
    ChargeI = 0;
  }

  //-------------------------------------------------------------- porcentagem da bateria - cálculo linear baseado na tensão (linear NÃO representa a porcentagem REAL)  
  if (BatVoltCorrected < BatMin) {                                       
    BatLevel = 0;
  }
  else if (BatVoltCorrected > 4.2) {
    BatLevel = 100;
  }
  else {
    BatLevel = map(int(BatVoltCorrected*100), int(BatMin*100), int(420), 0, 100);
  }

  //---------------------------------------------------------- Controle Menu Inicial --------------------------------------------------------------------------------------------
  if (screen == 0) {
    BatVoltQuiescent = BatVoltCorrected;
    BatVoltQuiescentValue = 1;
    BatFull = 0;
    if (TurnDetected) {
      delay(200);
      switch (arrowpos) {
        case 0:
          if (!up) {
            display.setCursor(2, 31);
           arrowpos = 1;
          }
          else {
            display.setCursor(2, 55);
            arrowpos = 3;
          }
        break;

        case 1:
          if (up) {
            display.setCursor(2, 19);
            arrowpos = 0;
          }
          else {
            display.setCursor(2, 43);
            arrowpos = 2;
          }
        break;

        case 2:
          if (up) {
          display.setCursor(2, 31);
          arrowpos = 1;
          }
          else {
            display.setCursor(2, 55);
            arrowpos = 3;
          }
        break;

        case 3:
          if (up) {
            display.setCursor(2, 43);
            arrowpos = 2;
          }
          else {
            display.setCursor(2, 19);
            arrowpos = 0;
          }
        break;
      }

      display.fillRect(0,16,10,63,0);
      display.write(26);
      display.display();      
      tone(PinBuz, 1109, 40);  // mudança de menu
      TurnDetected = false;
    }
  }

//------------------------------------------------------------------------------Modo de teste de capacidade-------------------------------------------------------  
  if (screen == 1) {
    Logo_bat();
    Modo_Teste();
    Tempo();
    
    if (BatVoltCorrected <= BatMin) {
      Capacity = Capacity;
      BatVoltQuiescentValue = 0;
      digitalWrite(MOSFET_Discharge, LOW);  
      tone(PinBuz, 831, 1000);  // Final do Teste de Carga    
      Advertencia (18,20,"TESTE RESULTADO");       
    }

    else if (BatVoltCorrected > BatMin && BatVoltQuiescentValue == 0 ) {
      BatRes = (BatVoltQuiescent - BatVoltCorrected) / (BatVoltCorrected / SetI);  //Calcula a resistência interna da bateria em mOhms  
      Capacity = Capacity + (SetI * (millisPassed / 3600000.0));
      BatVoltQuiescent = BatVoltCorrected;
      BatVoltQuiescentValue = 1;
      digitalWrite(MOSFET_Discharge, HIGH);
      Segundo += (millisPassed / 1000.0);
      display.drawBitmap(85,0,Status_Bateria_Descarregar,16,8,1);      
      Mensagem (0,20,"TESTANDO BATERIA");      
    }

    else if (BatVoltCorrected > BatMin && BatVoltQuiescentValue == 1 ) {
      BatRes = (BatVoltQuiescent - BatVoltCorrected) / (BatVoltCorrected / SetI);  //Calcula a resistência interna da bateria em mOhms    
      Capacity = Capacity + (SetI * (millisPassed / 3600000.0));
      digitalWrite(MOSFET_Discharge, HIGH);
      Segundo += (millisPassed / 1000.0);
      display.drawBitmap(85,0,Status_Bateria_Descarregar,16,8,1);
      Mensagem (0,20,"TESTANDO BATERIA");
    }

    display.display();
    delay(100); 
  }

  //------------------------------------------------------------------------------Modo de carga-------------------------------------------------------  
  else if (screen == 2) {
    Logo_bat();
    Modo_Carregar();
    if (BatVoltCorrected >= 4.15) {
      digitalWrite(MOSFET_Charge, HIGH);   //OFF //É um P-MOSFET, então HIGH está OFF e LOW está ON
      Advertencia(12,30,"Bateria Carregada");
		  BatFull = BatFull + 1;
    }

	  else if (BatVoltCorrected <= 2 ) {
      BatFull = 0;
      digitalWrite(MOSFET_Charge, HIGH);   //É um P-MOSFET, então HIGH está OFF e LOW está ON      
      Advertencia(30,30,"Sem Bateria");
		}

	  else if (BatVoltCorrected < 4.15 && BatFull < 10 && BatVoltCorrected > 0 ) { 
      digitalWrite(MOSFET_Charge, LOW);   //É um P-MOSFET, então HIGH está OFF e LOW está ON
      display.drawBitmap(85,0,Status_Bateria_Carregar,16,8,1);
      Mensagem(0,30,"Carregando ");
      display.print(BatLevel,0);
      display.print(F("%"));
	  }

    else if (BatVoltCorrected < 4.15 && BatFull >= 10) {
      digitalWrite(MOSFET_Charge, HIGH);   //É um P-MOSFET, então HIGH está OFF e LOW está ON
      Advertencia(12,30,"Bateria Carregada!");
    }

    display.display();
    delay(500);
  }

//------------------------------------------------------------------------------Modo de armazenamento-----------------------------------------------------------------------------------------

  //Você precisa ajustar suas tensões de acordo com suas baterias, para baterias de 3400mAh a tensão de armazenamento (50% da capacidade) é de 3,6-3,7V, para baterias abaixo de 2600mAh deve ser maior.
  // Para mais informações, visite: https://lygte-info.dk/info/BatteryChargePercent%20UK.html
   
  else if (screen == 3) {
    delay(100);
    Logo_bat();
    Modo_Armazenamento();

    if (BatVoltCorrected < 1.7 ) {//       01                      Não tem bateria
      Advertencia(30,30,"Sem Bateria");
	    digitalWrite(MOSFET_Discharge, LOW);     //DESLIGADO É um N-MOSFET, então HIGH está ON e LOW está OFF
      digitalWrite(MOSFET_Charge, HIGH);       //DESLIGADO É um P-MOSFET, então HIGH está OFF e LOW está ON
    }

    else if ( BatVoltCorrected > 3.65 && BatVoltCorrected < 3.75  ) {//       02
      Advertencia(1,30,"Pronto para Armazenar");
      digitalWrite(MOSFET_Discharge, LOW);     //DESLIGADO É um N-MOSFET, então HIGH está ON e LOW está OFF
      digitalWrite(MOSFET_Charge, HIGH);       //DESLIGADO É um P-MOSFET, então HIGH está OFF e LOW está ON
    }

    else if (BatVoltCorrected >= 1.7 && BatVoltCorrected < 3.75) {//   03       Bateria baixa > Carregando   por 1 segundo e para a carga para verificar    
      display.drawBitmap(85,0,Status_Bateria_Carregar,16,8,1);
      Mensagem(0,30,"Carregando Aguarde!");
      digitalWrite(MOSFET_Discharge, LOW);   //DESLIGADO É um N-MOSFET, então HIGH está ON e LOW está OFF
      digitalWrite(MOSFET_Charge, LOW);      //LIGADO É um P-MOSFET, então HIGH está OFF e LOW está ON
    }

    else if (BatVoltCorrected > 3.76) {//       04            Bateria Alta> Descarrega por 1 segundo e para a carga para verificar    
      display.drawBitmap(85,0,Status_Bateria_Descarregar,16,8,1);
      Mensagem(0,30,"Descarregando Aguarde");
      digitalWrite(MOSFET_Charge, HIGH);     //DESLIGADO É um P-MOSFET, então HIGH está OFF e LOW está ON
      digitalWrite(MOSFET_Discharge, HIGH);  //LIGADO É um N-MOSFET, então HIGH está ON e LOW está OFF         
    }

    else {                              //       05                                         
      Advertencia(30,30,"Error?");
      digitalWrite(MOSFET_Discharge, LOW);  //DESLIGADO É um N-MOSFET, então HIGH está ON e LOW está OFF
      digitalWrite(MOSFET_Charge, HIGH);       //DESLIGADO É um P-MOSFET, então HIGH está OFF e LOW está ON
		}

    display.display();
    delay(100);
  }

//------------------------------------------------------------------------------Modo de Configuração-----------------------------------------------------------------------------------------
  
  else if (screen == 4) {
    delay(150);
    if (TurnDetected) {       
       if (up && BatMin > 2.1) {
        BatMin +=0.1;
        }
       else{
        BatMin -=0.1;
        BatMin = max(BatMin, 2.2);
        }
      TurnDetected = false;
    }
    Modo_Configuracao();
    display.display();
  }

//--------------------------------------------------------------------------------------------BOTÃO PRESSIONADO--------------------------------------------------------------------------------------------
  if (button) {
    delay(200);
    switch (screen) {
      case 0:
        if (arrowpos == 0) {
          screen = 1;
          screen_clean();
        }
        else if (arrowpos == 1) {
          screen = 2;
          screen_clean();
        }        
        else if (arrowpos == 2) {
          screen = 3;
          screen_clean();
        }
        else {
		      screen = 4;
          screen_clean();
        }
      break;

      case 1:          // Sai do modo teste
        sair();
        Segundo = 0;
        Capacity = 0;
        digitalWrite(MOSFET_Discharge, LOW);
        digitalWrite(MOSFET_Charge, HIGH);
      break;
      
      case 2:          // Sai do modo Carregamento
        sair();
        digitalWrite(MOSFET_Discharge, LOW);
        digitalWrite(MOSFET_Charge, HIGH);
      break;
      
      case 3:          // Sai do modo Armazenamento
        sair();
        digitalWrite(MOSFET_Discharge, LOW);
        digitalWrite(MOSFET_Charge, HIGH);
      break;
      
      case 4:          // Sai do modo Configuração
        sair();
      break;
    }
    arrowpos = 0;
    button = false;
  }
}

void sair() {  
  screen = 0;
  Menu();
  display.setCursor(2, 19);
  display.write(26);
  display.display();
}

//-----------------------------------------------------------------------------------------------------TELAS-------------------------------------------------------------------------------------
void Menu() {
  digitalWrite(MOSFET_Discharge, LOW);        
  digitalWrite(MOSFET_Charge, HIGH);
  display.fillRect(0,16,127,63,0);
  display.setCursor(10,19);
  display.print(F("Testar Bateria"));
  display.setCursor(10,31);
  display.print(F("Carregar Bateria"));
  display.setCursor(10,43);
  display.print(F("Armazenar Bateria"));
  display.setCursor(10,55);
  display.print(F("Configuracao"));
  display.setCursor(70,54); 
  display.setTextColor(WHITE); 
  display.write(0x7e); 
  display.setTextColor(WHITE, BLACK);
  display.drawBitmap(62,61,cedinha,8,3,1);
}

void screen_clean() {
  display.fillRect(0,17,127,47,0);   //Limpa a tela
}

void Logo_bat() {
  display.fillRect(84,0,32,8,0);   //Limpa a logo_bateria
  display.drawBitmap(100,0,Bateria,16,7,1);
  int intbat = BatVoltCorrected * 10;
  intbat = min(intbat,41);
  intbat = max(intbat,BatMin*10);
  intbat = map(intbat, BatMin*10, 41, 0, 13);
  display.fillRect(101,1, intbat, 5, 1);
}

void Modo_Teste() {
  display.setCursor(0,30);
  display.print(F("V:")); 
  display.print(BatVoltCorrected); 
  display.print(F("V  "));
  display.setCursor(70,30);
  display.print(F("I:")); 
  display.print(SetI,0); 
  display.print(F("mA   "));
  display.setCursor(0,41);
  display.print(F("C:")); 
  display.print(Capacity,0); 
  display.print(F("mAh   "));
  display.setCursor(70,41);
  display.print(F("R:")); 
  display.print(BatRes,0); 
  display.print(F("m")); 
  display.write(233); 
  display.print(F("   "));
}

void Tempo() {
  T_Segundo = int (Segundo) % 60;
  T_Minuto = Segundo / 60;
  T_Hora = T_Minuto / 60;
  display.setCursor(0,52);
  sprintf(buf,"Tempo:%02d:%02d:%02d ",T_Hora,T_Minuto,T_Segundo);
  display.print(buf);                                
}

void Modo_Carregar() {
  display.setCursor(0,20);
  display.print(F("MODO: CARREGAMENTO"));
  display.setCursor(0,41);
  display.print(F("Tensao bateria: "));
  display.print(BatVoltCorrected);
  display.print(F("V "));
  display.setCursor(0,52); 
  display.print(F("Velocidade: ")); 
  display.print(ChargeI,0); 
  display.print(F("mA"));
  display.setCursor(24,40); 
  display.setTextColor(WHITE); 
  display.write(0x7e); 
  display.setTextColor(WHITE, BLACK);
}

void Modo_Armazenamento() {
  display.setCursor(0,20);
  display.print(F("Modo: ARMAZENAMENTO"));
  display.setCursor(0,41);
  display.print(F("Tensao bateria: "));
  display.print(BatVoltCorrected);
  display.print(F("V "));
  display.setCursor(0,52);
  display.print(F("Velocidade: "));
  display.print(ChargeI,0);
  display.print(F("mA   "));
  display.setCursor(24,40); 
  display.setTextColor(WHITE); 
  display.write(0x7e); 
  display.setTextColor(WHITE, BLACK);
}

void Modo_Configuracao() {
  display.setCursor(0,20);
  display.print(F("Modo: CONFIGURA"));
  display.write(128);
  display.print(F("AO"));  
  display.setCursor(0,30);
  display.print(F("Valor Minimo da"));
  display.setCursor(0,40);
  display.print(F("Bateria: "));
  display.print(BatMin,2);
  display.print(F("V"));
 display.setTextColor(WHITE);
  display.setCursor(96,17);
  display.write(126);
  display.setTextColor(WHITE, BLACK);
  }

void Advertencia (int N,int M ,char *T) {
  display.fillRect(0,(M-1),127,9,1);
  display.setTextColor(2);
  display.setCursor(N,M);
  display.print(T);
  display.setTextColor(WHITE, BLACK);
}

void Mensagem (int N,int M ,char *T) {
  display.fillRect(0,(M-1),127,9,0);
  display.setCursor(N,M);
  display.print(T);
}

//-------------------------------------------------------------------tensão com base na referência interna-------------------------------------------------------------
long readVcc() {
  long result;
  // Leia a referência de 1,1 V contra AVcc
  #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  ADMUX = _BV(MUX5) | _BV(MUX0);
  #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
  ADMUX = _BV(MUX3) | _BV(MUX2);
  #else
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #endif
  delay(2);                                                // Aguarde Vref resolver
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA, ADSC));
  result = ADCL;
  result |= ADCH << 8;
  result = 1126400L / result;                              // Calcular Vcc (em mV); 1126400 = 1,1*1024*1000
  return result;
}