снова про вольтметр (секретный)

renoshnik
Offline
Зарегистрирован: 11.04.2013

Добрый день !

http://blog.unlimite.net/?p=25

Давно известная тема про измерение опорного Vcc для получения точных значений входного напряжения.

Вот сделал такой код :

 


float VBG = 1.191, R_kft = 5.309, v_bat, ref_volt;
uint32_t data_rf, data_v;

void setup()  {
	Serial.begin (57600);
//  ====================================================================
ADCSRA = 0x85;    //  ADCSRA  1 0 0 0   0 1 0 1     // adc enable , clk/32
ADCSRB = 0x00;    //  ADCSRB  0 0 0 0   0 0 0 0
ADMUX = 0x4F;     //  ADMUX   0 1 0 0   1 1 1 1     // ref = AVCC , input = GND
DIDR0 = 0xFF;     //  DIDR0   1 1 1 1   1 1 1 1     // ADCxD = off
  } 
 
void loop()  { 
Volt_zamer(); 
	ref_volt = (VBG * 16368L)/(float)data_rf;					//	Vcc
  	v_bat = (((float)data_v * ref_volt) / 16368L) * R_kft;		//	Vin
Serial.print("Vcc = ");  Serial.print (ref_volt);  Serial.print(" V  ");
Serial.print("  Vin = ");  Serial.print ( Vac2 );  Serial.println(" V");
  delay(500);	
  }
/* ============================================================================ */
/* =========               блокок функций измерения                   ========= */
/* ============================================================================ */  
uint32_t Ref_zamer()  {
	ADC = 0;	ADMUX = 0x4E;				// ref = Vcc , input = 1.1V (VBG)	
	for (uint16_t n = 0; n < 256; n++ ) { ADCSRA |= (1<<ADSC);  
			while (bit_is_set(ADCSRA, ADSC));	data_rf += ADC; } 
	data_rf >>= 4;				  			// 16368 full scale 14bit  *** ОВЕРСЕМПЛИНГ
  return data_rf;  }

uint32_t Volt_zamer()  {	Ref_zamer(); 
	ADC = 0;	ADMUX = 0x43;           	// ref = Vcc , input = A3	
	for (uint16_t n = 0; n < 256; n++ ) { ADCSRA |= (1<<ADSC);  
			while (bit_is_set(ADCSRA, ADSC));	data_v += ADC; } 
	data_v >>= 4;  							// 16368 full scale 14bit  *** ОВЕРСЕМПЛИНГ	
  return data_v;  }

Но где-то я туплю, а где не пойму ....

 

Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.97 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.09 V
Vcc = 4.98 V    Vin = 12.10 V





Vcc = 4.84 V    Vin = 12.64 V
Vcc = 4.84 V    Vin = 12.65 V
Vcc = 4.84 V    Vin = 12.65 V
Vcc = 4.83 V    Vin = 12.61 V
Vcc = 4.84 V    Vin = 12.64 V
Vcc = 4.84 V    Vin = 12.64 V
Vcc = 4.84 V    Vin = 12.65 V
Vcc = 4.84 V    Vin = 12.62 V
Vcc = 4.84 V    Vin = 12.64 V
Vcc = 4.84 V    Vin = 12.65 V
Vcc = 4.84 V    Vin = 12.63 V
Vcc = 4.84 V    Vin = 12.64 V
Vcc = 4.84 V    Vin = 12.62 V
Vcc = 4.84 V    Vin = 12.62 V
Vcc = 4.84 V    Vin = 12.65 V
Vcc = 4.84 V    Vin = 12.64 V
Vcc = 4.84 V    Vin = 12.64 V
Vcc = 4.84 V    Vin = 12.64 V
Vcc = 4.83 V    Vin = 12.61 V
Vcc = 4.84 V    Vin = 12.64 V
Vcc = 4.84 V    Vin = 12.64 V
Vcc = 4.84 V    Vin = 12.65 V
Vcc = 4.84 V    Vin = 12.64 V
Vcc = 4.84 V    Vin = 12.65 V
Vcc = 4.84 V    Vin = 12.65 V

Vcc измеряет корректно все соответствует измеренному мультиметром.

Но почему при этом скачет значение входного напряжения если в реале оно постоянно..... ???

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

renoshnik пишет:

Но почему при этом скачет значение входного напряжения если в реале оно постоянно..... ???

постоянное != стабильное

примеры:

- стабилизированный источник постоянного напряжения.

- источник постоянного напряжения.

*и, ещё - гложут меня смутные сомнения, что измерять таким образом напряжения, превышающие напряжение питания камня, небезопасно.

renoshnik
Offline
Зарегистрирован: 11.04.2013

Клапауций 003 пишет:

постоянное != стабильное

примеры:

- стабилизированный источник постоянного напряжения.

- источник постоянного напряжения.

Согласен с замечанием...

Входное это аккумулятор через резистивный делитель.

Клапауций 003 пишет:

*и, ещё - гложут меня смутные сомнения, что измерять таким образом напряжения, превышающие напряжение питания камня, небезопасно.

Помоему такого у меня нет .... 

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

renoshnik пишет:

Помоему такого у меня нет .... 

как же нет?

если напряжение питания камня 5.0V , а ты меряешь напряжение до стабилизатора примерно 12.0V ?

renoshnik
Offline
Зарегистрирован: 11.04.2013

Клапауций 003 пишет:

renoshnik пишет:

Помоему такого у меня нет .... 

как же нет?

если напряжение питания камня 5.0V , а ты меряешь напряжение до стабилизатора примерно 12.0V ?

А резистивный делитель тут, что не катит ?

R_kft = 5.309 - это он и есть....

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

похоже кто-то о таком явлении как наводки не слыхал,или забыл.

renoshnik
Offline
Зарегистрирован: 11.04.2013

qwone пишет:

похоже кто-то о таком явлении как наводки не слыхал,или забыл.

Не понял, при чем тут наводки ?

Два блока результатов это результаты при РАЗЛИЧНЫХ значениях Vcc. Входное измеряемое напряжение (А3) это стабильное напряжение от аккумулятора.

В каждом блоке результатов значения достаточно стабильные, поэтому вопроса к пульсациям и синхронности измерения нет.

Проблема в том, что по идее при ИЗМЕНЕНИИ опорного напряжения (выбрано Vcc) значения измерения входного напряжения от аккумулятора НЕ должны меняться...  А вот этого как раз и не происходит...

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

renoshnik пишет:

А резистивный делитель тут, что не катит ?

R_kft = 5.309 - это он и есть....

ок. что бы не гадать - схему подключения к 12V публикуй.

и, сразу пиши - какое максимальное напряжение можно таким образом измерить?

renoshnik
Offline
Зарегистрирован: 11.04.2013

Клапауций 003 пишет:

renoshnik пишет:

А резистивный делитель тут, что не катит ?

R_kft = 5.309 - это он и есть....

ок. что бы не гадать - схему подключения к 12V публикуй.

и, сразу пиши - какое максимальное напряжение можно таким образом измерить?

Что публиковать ?

Обычный резистивный делитель (два резистора) коэффициент равен 5.309 .

https://www.google.com.ua/search?safe=off&hs=ZiY&q=резистивный+делитель&tbm=isch&source=univ&client=opera&sa=X&ved=2ahUKEwievrDu2MPjAhUks4sKHVRpD3AQsAR6BAgIEAE&biw=1880&bih=980

Максимально измерить можно напряжение Vcc*R_kft соответственно

для первого блока результатов 4.98 * 5.309 = 26.43882 Вольта

для второго блока результатов 4.84 * 5.309 = 25.69556 Вольта

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

renoshnik пишет:

Обычный резистивный делитель (два резистора) коэффициент равен 5.309 .

ок.

вроде выше сказал, что неизвестно, какой источник напряжения у тебя подключен к Vin - скорее всего нестабилизированный, поэтому будет показывать нестабилизированное напряжение, гуляющее в допустимых пределах для нормальной работы стабилизатора напряжения +5.0V.

так и должно быть, т.к. нет смысла стабилизировать напряжение два раза - тебе нужно +5.0V и всё.

но, если ты подключишь стабилизированный блок питания за неимением другого, то будет казать +9.1V допустим.

 

renoshnik
Offline
Зарегистрирован: 11.04.2013

" неизвестно, какой источник напряжения у тебя подключен к Vin "

аккумулятор 12.7 Вольт через резистивный делитель, вполне стабильный источник. 

" так и должно быть, т.к. нет смысла стабилизировать напряжение два раза - тебе нужно +5.0V и всё. "

смысл в том чтобы использовать напряжения отличные от +5.0 Вольт...

 

Вот тут измеряем извесное напряжение внутренний источник = 1.1 Вольта

uint32_t Ref_zamer()  {
	ADC = 0;	ADMUX = 0x4E;				// ref = Vcc , input = 1.1V (VBG)	
	for (uint16_t n = 0; n < 256; n++ ) { ADCSRA |= (1<<ADSC);  
			while (bit_is_set(ADCSRA, ADSC));	data_rf += ADC; } 
	data_rf >>= 4;				  			// 16368 full scale 14bit
  return data_rf;  }

в качестве опорного напряжения используем Vcc .
соответственно если мы знаем напряжение источника 1.1 В, то можем рассчитать реальное значение Vcc

	ref_volt = (VBG * 16368L)/(float)data_rf;					//	Vcc

 

После этого измеряем напряжение от аккумулятора на входе А3, в качестве опорного напряжения используем Vcc

uint32_t Volt_zamer()  {	Ref_zamer(); 
	ADC = 0;	ADMUX = 0x43;           	// ref = Vcc , input = A3	
	for (uint16_t n = 0; n < 256; n++ ) { ADCSRA |= (1<<ADSC);  
			while (bit_is_set(ADCSRA, ADSC));	data_v += ADC; } 
	data_v >>= 4;  							// 16368 full scale 14bit	
  return data_v;  }

после этого для вычисления значения напряжения используем ранее вычисленное реальное значение Vcc в качестве опорного.

v_bat = (((float)data_v * ref_volt) / 16368L) * R_kft;		//	Vin

 

+++++++++++++++++++++++++++++++++++++

по идее при изменении Vcc корректировка в расчетах должна происходить автоматически но это не так...

Pyotr
Offline
Зарегистрирован: 12.03.2014

uint32_t data_rf, data_v глобальные и нигде не обнуляются. Как там вобще получаются какие-то близкие к реальности значения? Видимо звезды сошлись...

И возвращать из функции глобальные как-то не очень помоему.

renoshnik
Offline
Зарегистрирован: 11.04.2013

Pyotr пишет:

uint32_t data_rf, data_v глобальные и нигде не обнуляются. Как там вобще получаются какие-то близкие к реальности значения? Видимо звезды сошлись...

И возвращать из функции глобальные как-то не очень помоему.

Ок попробую откорректировать.

Pyotr
Offline
Зарегистрирован: 12.03.2014

ADC = 0; зачем?

строки 28, 35 - тоже не нужно деление на 16. Вместо этого другие коэфициенты умножте на 16.

да, и не лепите все в одну строку. Одна операция - одна строка.

renoshnik
Offline
Зарегистрирован: 11.04.2013

Pyotr пишет:

ADC = 0; зачем?

Это издержки копипаста....

Pyotr пишет:

строки 28, 35 - тоже не нужно деление на 16. Вместо этого другие коэфициенты умножте на 16.

как бы оверсемплинг ....

 

 

 

renoshnik
Offline
Зарегистрирован: 11.04.2013

Pyotr пишет:

uint32_t data_rf, data_v глобальные и нигде не обнуляются. Как там вобще получаются какие-то близкие к реальности значения? Видимо звезды сошлись...

И возвращать из функции глобальные как-то не очень помоему.

float VBG = 1.191, R_kft = 5.309, v_bat, ref_volt;
// uint32_t data_rf, data_v;

void setup()  {
	Serial.begin (57600);
//  ====================================================================
ADCSRA = 0x85;    //  ADCSRA  1 0 0 0   0 1 0 1     // adc enable , clk/32
ADCSRB = 0x00;    //  ADCSRB  0 0 0 0   0 0 0 0
ADMUX = 0x4F;     //  ADMUX   0 1 0 0   1 1 1 1     // ref = AVCC , input = GND
DIDR0 = 0xFF;     //  DIDR0   1 1 1 1   1 1 1 1     // ADCxD = off
  } 
 
void loop()  { 
	ref_volt = (VBG * 16368L)/(float)Ref_zamer();					//	Vcc
  	v_bat = (((float)Volt_zamer() * ref_volt) / 16368L) * R_kft;		//	Vin
Serial.print("Vcc = ");  Serial.print (ref_volt);  Serial.print(" V  ");
Serial.print("  Vin = ");  Serial.print (v_bat);  Serial.println(" V");
  delay(500);	
  }
/* ============================================================================ */
/* =========               блокок функций измерения                   ========= */
/* ============================================================================ */  
uint32_t Ref_zamer()  {
	uint32_t data_rf = 0;	ADMUX = 0x4E;				// ref = Vcc , input = 1.1V (VBG)	
	for (uint16_t n = 0; n < 256; n++ ) { ADCSRA |= (1<<ADSC);  
			while (bit_is_set(ADCSRA, ADSC));	data_rf += ADC; } 
	data_rf >>= 4;				  			// 16368 full scale 14bit  *** ОВЕРСЕМПЛИНГ
  return data_rf;  }

uint32_t Volt_zamer()  {
	uint32_t data_v = 0;	ADMUX = 0x43;           	// ref = Vcc , input = A3	
	for (uint16_t n = 0; n < 256; n++ ) { ADCSRA |= (1<<ADSC);  
			while (bit_is_set(ADCSRA, ADSC));	data_v += ADC; } 
	data_v >>= 4;  							// 16368 full scale 14bit  *** ОВЕРСЕМПЛИНГ	
  return data_v;  }

 

не помогло


Vcc = 4.99 V    Vin = 11.55 V
Vcc = 4.99 V    Vin = 11.55 V
Vcc = 4.99 V    Vin = 11.55 V
Vcc = 4.99 V    Vin = 11.54 V
Vcc = 4.99 V    Vin = 11.55 V
Vcc = 4.99 V    Vin = 11.55 V
Vcc = 4.99 V    Vin = 11.55 V
Vcc = 4.99 V    Vin = 11.54 V
Vcc = 4.99 V    Vin = 11.54 V
Vcc = 4.99 V    Vin = 11.55 V
Vcc = 4.99 V    Vin = 11.55 V
Vcc = 4.99 V    Vin = 11.55 V


Vcc = 4.86 V    Vin = 11.70 V
Vcc = 4.86 V    Vin = 11.70 V
Vcc = 4.86 V    Vin = 11.70 V
Vcc = 4.86 V    Vin = 11.70 V
Vcc = 4.86 V    Vin = 11.70 V
Vcc = 4.86 V    Vin = 11.70 V
Vcc = 4.86 V    Vin = 11.70 V
Vcc = 4.86 V    Vin = 11.70 V
Vcc = 4.86 V    Vin = 11.69 V
Vcc = 4.86 V    Vin = 11.70 V
Vcc = 4.86 V    Vin = 11.70 V

 

Pyotr
Offline
Зарегистрирован: 12.03.2014

ref_volt = (VBG * 262176L)/(float)data_rf;

data_rf >>= 4; 

ref_volt = (VBG * 16368L)/(float)data_rf;  

 

renoshnik
Offline
Зарегистрирован: 11.04.2013

Pyotr пишет:

ref_volt = (VBG * 262176L)/(float)data_rf;

data_rf >>= 4; 

ref_volt = (VBG * 16368L)/(float)data_rf;  

 

Думаете проблема в оверсемплинге ? а почему ?

 

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

как по мне - здесь http://blog.unlimite.net/?p=25 имеется в виду, что камень питается от батареи, т.е. Vcc == Vbat, т.е. оба находятся в пределах стабильной работы камня, т.е. 4.0-5.0V

актуален такой подход, когда Vcc нестабильно, иначе - если камень питается от стабилизированного напряжения питания, то нет смысла городить огород - Vcc нам известно и оно равно напряжению стабилизатора напряжения, т.е. = 5.05V или измерить мультиметром, допустим 4.95V.

далее - вешаем делитель напряжения на аналоговый вход.

и, всё. о_О

напряжение Vcc схемотехнически стабильно - какая может быть коррекция, если она не нужна?

renoshnik
Offline
Зарегистрирован: 11.04.2013

Pyotr пишет:

ref_volt = (VBG * 262176L)/(float)data_rf;

data_rf >>= 4; 

ref_volt = (VBG * 16368L)/(float)data_rf;  

 

 

float VBG = 1.121, R_kft = 5.309, v_bat, ref_volt;
// uint32_t data_rf, data_v;

void setup()  {
  Serial.begin (57600);
//  ====================================================================
ADCSRA = 0x85;    //  ADCSRA  1 0 0 0   0 1 0 1     // adc enable , clk/32
ADCSRB = 0x00;    //  ADCSRB  0 0 0 0   0 0 0 0
ADMUX = 0x4F;     //  ADMUX   0 1 0 0   1 1 1 1     // ref = AVCC , input = GND
DIDR0 = 0xFF;     //  DIDR0   1 1 1 1   1 1 1 1     // ADCxD = off
  } 
 
void loop()  { 
  ref_volt = (VBG * 262176L)/(float)Ref_zamer();          //  Vcc
    v_bat = (((float)Volt_zamer() * ref_volt) / 262176L) * R_kft;   //  Vin
Serial.print("Vcc = ");  Serial.print (ref_volt);  Serial.print(" V  ");
Serial.print("  Vin = ");  Serial.print (v_bat);  Serial.println(" V");
  delay(500); 
  }
/* ============================================================================ */
/* =========               блокок функций измерения                   ========= */
/* ============================================================================ */  
uint32_t Ref_zamer()  {
  uint32_t data_rf = 0; ADMUX = 0x4E;       // ref = Vcc , input = 1.1V (VBG) 
  for (uint16_t n = 0; n < 256; n++ ) { ADCSRA |= (1<<ADSC);  
      while (bit_is_set(ADCSRA, ADSC)); data_rf += ADC; } 
//  data_rf >>= 4;                // 16368 full scale 14bit  *** ОВЕРСЕМПЛИНГ
  return data_rf;  }

uint32_t Volt_zamer()  {
  uint32_t data_v = 0;  ADMUX = 0x43;             // ref = Vcc , input = A3 
  for (uint16_t n = 0; n < 256; n++ ) { ADCSRA |= (1<<ADSC);  
      while (bit_is_set(ADCSRA, ADSC)); data_v += ADC; } 
//  data_v >>= 4;               // 16368 full scale 14bit  *** ОВЕРСЕМПЛИНГ 
  return data_v;  }

результат тот же...

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

renoshnik пишет:
Не понял, при чем тут наводки ?

Два блока результатов это результаты при РАЗЛИЧНЫХ значениях Vcc. Входное измеряемое напряжение (А3) это стабильное напряжение от аккумулятора.

Объсняю по рабоче-крестьянски(ну или для нубов).Одному чудаку захотелось точно измерить уровень бассейна с точьностью до миллиметра. Приклеил к борту бассейна рулетку .логично. И нифига уровень в бассейне колеблится. Волны маеть его так . Ну +/- 20 миллиметров. Конечно можно округлить . Но ведь хочется точно уловить момент когда кто-то в бассейн ссыт, или воду на шару забирает. Вот так и у вас. Нога аналоговая у вас к чему подключена. Вот чем больше борода на этом выводе, тем больше он наботает как антенна для всяких волн.

Pyotr
Offline
Зарегистрирован: 12.03.2014

попробуйте так, после строки 14.

analogRead(A3); //отбрасываем первый результат АЦП

v_bat = ((analogRead(A3) * ref_volt) / 1024) * R_kft;   //  Vin

renoshnik
Offline
Зарегистрирован: 11.04.2013

qwone пишет:

renoshnik пишет:
Не понял, при чем тут наводки ?

Два блока результатов это результаты при РАЗЛИЧНЫХ значениях Vcc. Входное измеряемое напряжение (А3) это стабильное напряжение от аккумулятора.

Объсняю по рабоче-крестьянски(ну или для нубов).Одному чудаку захотелось точно измерить уровень бассейна с точьностью до миллиметра. Приклеил к борту бассейна рулетку .логично. И нифига уровень в бассейне колеблится. Волны маеть его так . Ну +/- 20 миллиметров. Конечно можно округлить . Но ведь хочется точно уловить момент когда кто-то в бассейн ссыт, или воду на шару забирает. Вот так и у вас. Нога аналоговая у вас к чему подключена. Вот чем больше борода на этом выводе, тем больше он наботает как антенна для всяких волн.

спасибо.