#include <LCD5110_Graph.h>
#include <stdlib.h>
LCD5110 myGLCD(8, 9, 10, 11, 12);
extern uint8_t SmallFont[]; // Indicamos el tipo de fuente SmallFont
//variables para el voltimetro
int analogInput = 0;
float vout = 0.0;
float vin = 0.0;
float R1 = 100000.0; //R1 100K
float R2 = 10000.0; //R2 10K
int value = 0;
char string[8];
//****************************
void setup() {
//Serial.begin(9600);
pinMode (analogInput, INPUT); //PIN A0 = ENTRADA voltimetro
myGLCD.InitLCD(); //inicia la pantalla
myGLCD.setFont(SmallFont);
myGLCD.clrScr(); //borra la pantalla
}
void loop() {
value = analogRead(analogInput);
vout = (value * 5.0) / 1024.0;
vin = vout / (R2 /(R1 + R2));
myGLCD.print("VOLTAJE: ", 4,10);
myGLCD.print(dtostrf(vin,5,2,string), 50, 10); //Transforma el float vin en cadena de caracteres para mostrarlo en el display.
myGLCD.update();
delay(100);
}
Ahora si modifico el voltaje de alimentacion de arduino por ejemplo 6v, el voltimetro ya no funciona como devería, sera cuestion de la simulación o las operaciones matematicas etarán mal?
//VOLTIMETRO********************************
float voltaje_entrada = 0.0;
voltaje_entrada = (readVcc() / 1000); // Ejemplo 6v me entrega 5985.0. A su vez / 1000, teoricamente quedaría 5.9850
char buffer[8];
String s = dtostrf(voltaje_entrada, 1, 2, buffer);
myGLCD.print("VOLTAJE: ", 4,10);
myGLCD.print(s, 55, 10);
myGLCD.update();
//******************************************
long readVcc() {
// Read 1.1V reference against AVcc
// set the reference to Vcc and the measurement to the internal 1.1V reference
#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); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Start conversion
while (bit_is_set(ADCSRA,ADSC)); // measuring
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both
long result = (high<<8) | low;
result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
return result; // Vcc in millivolts
}
Encontre la funcion, pero tengo un problema al convertir float a string.
//VOLTIMETRO********************************
float voltaje_entrada = 0.0;
voltaje_entrada = readVcc(); // Ejemplo 6v me entrega 5985.0
voltaje_final = ((voltaje_entrada * 1000) / 1000) / 1000;
String s = String(voltaje_final, 2);
myGLCD.print("VOLTAJE: ", 4,10);
myGLCD.print(s, 55, 10);
myGLCD.update();
//******************************************
long readVcc() {
// Read 1.1V reference against AVcc
// set the reference to Vcc and the measurement to the internal 1.1V reference
#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); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Start conversion
while (bit_is_set(ADCSRA,ADSC)); // measuring
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both
long result = (high<<8) | low;
result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
return result; // Vcc in millivolts
}
Lamentablemente ese divisor resistivo tiene una impedancia muy alta respecto de la impedancia de entrada del microcontrolador.
Por lo tanto la tensión en el punto medio se vendrá abajo.
La idea es muestrear la tensión a intervalos, con un transistor MOSFET de muy baja potencia y bajo Vgs. Así puedes accionarlo con 3.3V
La idea es muestrear la tensión a intervalos, con un transistor MOSFET de muy baja potencia y bajo Vgs. Así puedes accionarlo con 3.3V
Al parecer la impedancia de entrada del ADC, es de 10K aprox. por lo tanto la resistencia pull-up del divisor resistivo debe tener al menos el mismo valor, así podrás leer la mitad del valor de la tensión de alimentación.
La idea de usar un MOSFET y no un BJT, es que el primero consume una corriente despreciable de Gate.
Al parecer la impedancia de entrada del ADC, es de 10K aprox. por lo tanto la resistencia pull-up del divisor resistivo debe tener al menos el mismo valor, así podrás leer la mitad del valor de la tensión de alimentación.
La idea de usar un MOSFET y no un BJT, es que el primero consume una corriente despreciable de Gate.
Los 10K o menor son la impedancia de salida del dispositivo que cuelgues en la entrada del ADC, y es por la capacidad de la entrada.
Esto tiene importancia solamente cuando se hacen lecturas multiplexando varias entradas a alta velocidad , o la señal tiene componentes de alta frecuendcia.
Creo que te estás complicando con el montaje externo.
Si mides la tensión interna de referencia (por ejemplo FVR=2.048V) mientras la tensión de referencia del ADC está conectada a la alimentación (Aref = Vdd), a partir de esa medida se puede calcular fácilmente la tensión de alimentación.
Posteriormente desconectas el módulo de tensión de referencia interno (FVR) y el módulo ADC para que no consuman corriente.
Así tienes todo incluido dentro del microcontrolador y con un consumo mínimo.
Un saludo.
Por lo que yo conozco, no es necesario habilitar el BROWNOUTDETECTOR.
Solo necesitas habilitar el ADC y luego lo puedes volver a desabilitar.
Saludos.
¿Qué pic estás utilizando?
No lo conozco lo suficiente como para aconsejarte sobre los fuses.
De todas formas puedes utilizar Vdd como tensión de referencia del ADC. Creo que estabas regulando la alimentación desde la batería, de manera que tendrás una tensión constante.
Un saludo.