Как измерять напряжение автономного питания на Arduino Nano.

aloyen
Offline
Зарегистрирован: 28.12.2021

Я сейчас делаю что-то наподобие геймпада на Arduino Nano. Питается в се это дело от аккумулятора 3.7V. Как измерять напряжение на аккумуляторе, не подключая внешний источник питания?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

AnalogRead()

aloyen
Offline
Зарегистрирован: 28.12.2021

При таком способе всегда возвращается значение 1023.

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

И analogReference(INTERNAL)
И через делитель

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

aloyen пишет:

При таком способе всегда возвращается значение 1023.


Потому что по умолчанию в качечтве опорного напряжения используется напряжение питания.

aloyen
Offline
Зарегистрирован: 28.12.2021

v258 пишет:
И analogReference(INTERNAL) И через делитель

Делитель на резисторах 1кОм-1кОм подойдет?

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Делитель нужно такой что бы 4.2 привелось к 1.1

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

aloyen пишет:

v258 пишет:
И analogReference(INTERNAL) И через делитель

Делитель на резисторах 1кОм-1кОм подойдет?

нет

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

aloyen пишет:

v258 пишет:
И analogReference(INTERNAL) И через делитель

Делитель на резисторах 1кОм-1кОм подойдет?


Нет. Внутренний источник опорного - 1,1В, поэтому на аналоговый вход должно приходить не больше. Нужен делитель 1/4 хотя бы.

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

И еще - раз делается автономное устройство, то нужно понимать, что через делитель постоянно будет протекать ток, что не есть хорошо для автономности. Стало быть и сопротивления делителя нужно подбирать для минимизации этого тока

Green
Offline
Зарегистрирован: 01.10.2015

Гугль: секретный вольтметр.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Какой делитель? Ничего не нужно!

Замеряешь внутренне опорное напряжение как можно тщательнее, записываешь. Это можно сделать очень просто, установить аналогрефференс на внутреннее 1,1В и на пине реф замерить сколько там на самом деле. Как можно точнее. Лучше несколько раз и усреднить.

Затем, уже в коде, программно измеряешь значение внутреннего опорного (от питания) и, зная какое там опорное (не зря измеряли), вычисляешь питание. Делов-то на копейку.

static inline void adcChooseVBG(void) { ADMUX = (ADMUX & 0xF0) | 14; }
static inline void adcStart(void) { ADCSRA |= bit(ADSC); }
static inline bool adcInProgress(void) { return ADCSRA & bit(ADSC); }
static inline unsigned adcGet(void) { return ADC; }


// Возвращает напряжение питания в десятых долях вольта
inline static int getBatteryVoltage(const int internalRefference) {
	adcChooseVBG();
	_delay_ms(1); // пусть "пропитается"
	adcStart(); // плевать на первый замер
	while (adcInProgress());
	adcStart(); // теперь замеряем
	while (adcInProgress());
	const int adc = adcGet();
	return (((internalRefference * 1024L + adc / 2) / adc) + 500) / 1000;
}

Функции нужно передать замеренное ранее значение внутреннего опорного напряжения, умноженное на 10000 (т.е. если оно 1,1В, то передавать надо 11000).

Строка №10 может и не нужна, у меня просто прямо здесь же включается питание ADC через PRR. Вот и даю ему время стабилизироваться.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

ЕвгенийП пишет:

... и на пине реф замерить сколько там на самом деле...

Физически (прибором) замерить как я понимаю.

b707
Offline
Зарегистрирован: 26.05.2017

только вчера же был вопрос про то как измерить напряжение питания на СТМ32 :

http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/izmerenie-vdd-na-stm32-v-arduino

на Нано все измеряется точно по такому же принципу, никакие внешние делители нафик не нужны

b707
Offline
Зарегистрирован: 26.05.2017

ЕвгенийП, а зачем измеряемое значение adc описано const? (строка 15)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

Какой делитель? Ничего не нужно!

Замеряешь внутренне опорное напряжение как можно тщательнее, записываешь. Это можно сделать очень просто, установить аналогрефференс на внутреннее 1,1В и на пине реф замерить сколько там на самом деле. Как можно точнее. Лучше несколько раз и усреднить.

Затем, уже в коде, программно измеряешь значение внутреннего опорного (от питания) и, зная какое там опорное (не зря измеряли), вычисляешь питание. Делов-то на копейку.

static inline void adcChooseVBG(void) { ADMUX = (ADMUX & 0xF0) | 14; }
static inline void adcStart(void) { ADCSRA |= bit(ADSC); }
static inline bool adcInProgress(void) { return ADCSRA & bit(ADSC); }
static inline unsigned adcGet(void) { return ADC; }


// Возвращает напряжение питания в десятых долях вольта
inline static int getBatteryVoltage(const int internalRefference) {
	adcChooseVBG();
	_delay_ms(1); // пусть "пропитается"
	adcStart(); // плевать на первый замер
	while (adcInProgress());
	adcStart(); // теперь замеряем
	while (adcInProgress());
	const int adc = adcGet();
	return (((internalRefference * 1024L + adc / 2) / adc) + 500) / 1000;
}

Функции нужно передать замеренное ранее значение внутреннего опорного напряжения, умноженное на 10000 (т.е. если оно 1,1В, то передавать надо 11000).

Строка №10 может и не нужна, у меня просто прямо здесь же включается питание ADC через PRR. Вот и даю ему время стабилизироваться.

Евгений! Вы старому киповцу сломали мозг, я то по наивности думал, что AREF аналогичен ИОНу, ан нет... )))

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Komandir пишет:

ЕвгенийП пишет:

... и на пине реф замерить сколько там на самом деле...

Физически (прибором) замерить как я понимаю.

Да, там по даташиту 1,1В но допустим разброс от экземпляра к экземпляру. Так чтобы результат был точнее, лучше замерять у конкретного экземпляра.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

b707 пишет:

ЕвгенийП, а зачем измеряемое значение adc описано const? (строка 15)

Ну, мы же не собираемся его менять? Просто, общеполезное правило: не собираешься менять - пиши const. Чаще всего не влияет ни на что, но бывают случаи, когда это помогает оптимизатору.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ua6em пишет:

Евгений! Вы старому киповцу сломали мозг, я то по наивности думал, что AREF аналогичен ИОНу, ан нет... )))

Так, вроде, так и есть. А в чём беда?

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

Замеряем внутреннее опорное мультиметром, потом замеряем внутреннее опорное программно и, зная внутреннее опорное (замеренное), вычисляем напряжение питания... Мой мозг никак не вернётся в исходное состояние после таких вывертов. А можно поподробнее, для нубов? ))

aloyen
Offline
Зарегистрирован: 28.12.2021

ЕвгенийП пишет:

Какой делитель? Ничего не нужно!

Замеряешь внутренне опорное напряжение как можно тщательнее, записываешь. Это можно сделать очень просто, установить аналогрефференс на внутреннее 1,1В и на пине реф замерить сколько там на самом деле. Как можно точнее. Лучше несколько раз и усреднить.

Затем, уже в коде, программно измеряешь значение внутреннего опорного (от питания) и, зная какое там опорное (не зря измеряли), вычисляешь питание. Делов-то на копейку.

static inline void adcChooseVBG(void) { ADMUX = (ADMUX & 0xF0) | 14; }
static inline void adcStart(void) { ADCSRA |= bit(ADSC); }
static inline bool adcInProgress(void) { return ADCSRA & bit(ADSC); }
static inline unsigned adcGet(void) { return ADC; }


// Возвращает напряжение питания в десятых долях вольта
inline static int getBatteryVoltage(const int internalRefference) {
	adcChooseVBG();
	_delay_ms(1); // пусть "пропитается"
	adcStart(); // плевать на первый замер
	while (adcInProgress());
	adcStart(); // теперь замеряем
	while (adcInProgress());
	const int adc = adcGet();
	return (((internalRefference * 1024L + adc / 2) / adc) + 500) / 1000;
}

Функции нужно передать замеренное ранее значение внутреннего опорного напряжения, умноженное на 10000 (т.е. если оно 1,1В, то передавать надо 11000).

Строка №10 может и не нужна, у меня просто прямо здесь же включается питание ADC через PRR. Вот и даю ему время стабилизироваться.

А не так давно у меня поломался мультиметр... Ладно, буду другой платой замерять.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

ЕвгенийП В формуле из 16 строки нет ошибки ??? если adc в диапазоне 0-1023, то результат очень странный !

b707
Offline
Зарегистрирован: 26.05.2017

Komandir пишет:

ЕвгенийП В формуле из 16 строки нет ошибки ??? если adc в диапазоне 0-1023, то результат очень странный !

да, какая-то странная формула. Я обычно считаю проще

 VCC = Vref *1024/adc;

b707
Offline
Зарегистрирован: 26.05.2017

v258 пишет:
Замеряем внутреннее опорное мультиметром, потом замеряем внутреннее опорное программно и, зная внутреннее опорное (замеренное), вычисляем напряжение питания... Мой мозг никак не вернётся в исходное состояние после таких вывертов. А можно поподробнее, для нубов? ))

тююю мужики...

вы что, в первый раз этот способ видите? Он же во всех книжках "ардуино для чайников" есть...

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018
0	#ДЕЛ/0!
1	11264.5005
2	5632.5005
3	3755.167167
4	2816.5005
5	2253.3005
6	1877.833833
7	1609.643357
8	1408.5005
9	1252.056056
10	1126.9005
11	1024.5005
12	939.1671667
13	866.9620385
14	805.0719286
15	751.4338333
16	704.5005
17	663.0887353
18	626.2782778
19	593.3426053
20	563.7005
21	536.8814524
22	512.5005
23	490.2396304
24	469.8338333
25	451.0605
26	433.7312692
27	417.6856852
28	402.7862143
29	388.9142931
30	375.9671667
31	363.8553387
32	352.5005
33	341.8338333
34	331.7946176
35	322.3290714
36	313.3893889
37	304.9329324
38	296.9215526
39	289.3210128
40	282.1005
41	275.2322073
42	268.6909762
43	262.4539884
44	256.5005
45	250.8116111
46	245.3700652
47	240.1600745
48	235.1671667
49	230.378051
50	225.7805
51	221.3632451
52	217.1158846
53	213.0288019
54	209.0930926
55	205.3005
56	201.6433571
57	198.1145351
58	194.7073966
59	191.4157542
60	188.2338333
61	185.1562377
62	182.1779194
63	179.2941508
64	176.5005
65	173.7928077
66	171.1671667
67	168.619903
68	166.1475588
69	163.7468768
70	161.4147857
71	159.1483873
72	156.9449444
73	154.8018699
74	152.7167162
75	150.6871667
76	148.7110263
77	146.7862143
78	144.9107564
79	143.0827785
80	141.3005
81	139.5622284
82	137.8663537
83	136.2113434
84	134.5957381
85	133.0181471
86	131.4772442
87	129.9717644
88	128.5005
89	127.0622978
90	125.6560556
91	124.2807198
92	122.9352826
93	121.6187796
94	120.3302872
95	119.0689211
96	117.8338333
97	116.6242113
98	115.4392755
99	114.2782778
100	113.1405
101	112.0252525
102	110.9318725
103	109.8597233
104	108.8081923
105	107.7766905
106	106.7646509
107	105.771528
108	104.7967963
109	103.8399495
110	102.9005
111	101.9779775
112	101.0719286
113	100.1819159
114	99.30751754
115	98.44832609
116	97.60394828
117	96.77400427
118	95.95812712
119	95.15596218
120	94.36716667
121	93.59140909
122	92.82836885
123	92.07773577
124	91.33920968
125	90.6125
126	89.8973254
127	89.19341339
128	88.5005
129	87.81832946
130	87.14665385
131	86.48523282
132	85.83383333
133	85.19222932
134	84.56020149
135	83.93753704
136	83.32402941
137	82.7194781
138	82.12368841
139	81.53647122
140	80.95764286
141	80.38702482
142	79.82444366
143	79.26973077
144	78.72272222
145	78.18325862
146	77.65118493
147	77.12635034
148	76.60860811
149	76.09781544
150	75.59383333
151	75.09652649
152	74.60576316
153	74.12141503
154	73.64335714
155	73.17146774
156	72.70562821
157	72.24572293
158	71.79163924
159	71.3432673
160	70.9005
161	70.46323292
162	70.0313642
163	69.60479448
164	69.18342683
165	68.76716667
166	68.35592169
167	67.9496018
168	67.54811905
169	67.15138757
170	66.75932353
171	66.37184503
172	65.98887209
173	65.61032659
174	65.23613218
175	64.86621429
176	64.5005
177	64.13891808
178	63.78139888
179	63.4278743
180	63.07827778
181	62.7325442
182	62.39060989
183	62.05241257
184	61.7178913
185	61.38698649
186	61.05963978
187	60.73579412
188	60.41539362
189	60.0983836
190	59.78471053
191	59.47432199
192	59.16716667
193	58.8631943
194	58.56235567
195	58.26460256
196	57.96988776
197	57.67816497
198	57.38938889
199	57.10351508
200	56.8205
201	56.540301
202	56.26287624
203	55.98818473
204	55.71618627
205	55.44684146
206	55.18011165
207	54.91595894
208	54.65434615
209	54.39523684
210	54.13859524
211	53.88438626
212	53.63257547
213	53.38312911
214	53.13601402
215	52.89119767
216	52.64864815
217	52.4083341
218	52.17022477
219	51.93428995
220	51.7005
221	51.46882579
222	51.23923874
223	51.01171076
224	50.78621429
225	50.56272222
226	50.34120796
227	50.12164537
228	49.90400877
229	49.68827293
230	49.47441304
231	49.26240476
232	49.05222414
233	48.84384764
234	48.63725214
235	48.43241489
236	48.22931356
237	48.02792616
238	47.82823109
239	47.63020711
240	47.43383333
241	47.23908921
242	47.04595455
243	46.85440947
244	46.66443443
245	46.4760102
246	46.28911789
247	46.10373887
248	45.91985484
249	45.73744779
250	45.5565
251	45.37699402
252	45.1989127
253	45.02223913
254	44.84695669
255	44.67304902
256	44.5005
257	44.32929377
258	44.15941473
259	43.99084749
260	43.82357692
261	43.65758812
262	43.49286641
263	43.32939734
264	43.16716667
265	43.00616038
266	42.84636466
267	42.68776592
268	42.53035075
269	42.37410595
270	42.21901852
271	42.06507565
272	41.91226471
273	41.76057326
274	41.60998905
275	41.4605
276	41.3120942
277	41.16475993
278	41.01848561
279	40.87325986
280	40.72907143
281	40.58590925
282	40.44376241
283	40.30262014
284	40.16247183
285	40.02330702
286	39.88511538
287	39.74788676
288	39.61161111
289	39.47627855
290	39.34187931
291	39.20840378
292	39.07584247
293	38.94418601
294	38.81342517
295	38.68355085
296	38.55455405
297	38.42642593
298	38.29915772
299	38.1727408
300	38.04716667
301	37.92242691
302	37.79851325
303	37.67541749
304	37.55313158
305	37.43164754
306	37.31095752
307	37.19105375
308	37.07192857
309	36.95357443
310	36.83598387
311	36.71914952
312	36.6030641
313	36.48772045
314	36.37311146
315	36.25923016
316	36.14606962
317	36.03362303
318	35.92188365
319	35.81084483
320	35.7005
321	35.59084268
322	35.48186646
323	35.37356502
324	35.2659321
325	35.15896154
326	35.05264724
327	34.94698318
328	34.84196341
329	34.73758207
330	34.63383333
331	34.53071148
332	34.42821084
333	34.32632583
334	34.2250509
335	34.1243806
336	34.02430952
337	33.92483234
338	33.82594379
339	33.72763864
340	33.62991176
341	33.53275806
342	33.43617251
343	33.34015015
344	33.24468605
345	33.14977536
346	33.05541329
347	32.9615951
348	32.86831609
349	32.77557163
350	32.68335714
351	32.59166809
352	32.5005
353	32.40984844
354	32.31970904
355	32.23007746
356	32.14094944
357	32.05232073
358	31.96418715
359	31.87654457
360	31.78938889
361	31.70271607
362	31.6165221
363	31.53080303
364	31.44555495
365	31.36077397
366	31.27645628
367	31.19259809
368	31.10919565
369	31.02624526
370	30.94374324
371	30.86168598
372	30.78006989
373	30.69889142
374	30.61814706
375	30.53783333
376	30.45794681
377	30.37848408
378	30.2994418
379	30.22081662
380	30.14260526
381	30.06480446
382	29.98741099
383	29.91042167
384	29.83383333
385	29.75764286
386	29.68184715
387	29.60644315
388	29.53142784
389	29.4567982
390	29.38255128
391	29.30868414
392	29.23519388
393	29.16207761
394	29.08933249
395	29.0169557
396	28.94494444
397	28.87329597
398	28.80200754
399	28.73107644
400	28.6605
401	28.59027556
402	28.5204005
403	28.45087221
404	28.38168812
405	28.31284568
406	28.24434236
407	28.17617568
408	28.10834314
409	28.0408423
410	27.97367073
411	27.90682603
412	27.84030583
413	27.77410775
414	27.70822947
415	27.64266867
416	27.57742308
417	27.51249041
418	27.44786842
419	27.38355489
420	27.31954762
421	27.25584442
422	27.19244313
423	27.12934161
424	27.06653774
425	27.00402941
426	26.94181455
427	26.8798911
428	26.81825701
429	26.75691026
430	26.69584884
431	26.63507077
432	26.57457407
433	26.51435681
434	26.45441705
435	26.39475287
436	26.33536239
437	26.27624371
438	26.21739498
439	26.15881435
440	26.1005
441	26.04245011
442	25.9846629
443	25.92713657
444	25.86986937
445	25.81285955
446	25.75610538
447	25.69960515
448	25.64335714
449	25.58735969
450	25.53161111
451	25.47610976
452	25.42085398
453	25.36584216
454	25.31107269
455	25.25654396
456	25.20225439
457	25.14820241
458	25.09438646
459	25.04080501
460	24.98745652
461	24.93433948
462	24.88145238
463	24.82879374
464	24.77636207
465	24.72415591
466	24.67217382
467	24.62041435
468	24.56887607
469	24.51755757
470	24.46645745
471	24.41557431
472	24.36490678
473	24.31445349
474	24.26421308
475	24.21418421
476	24.16436555
477	24.11475577
478	24.06535356
479	24.01615762
480	23.96716667
481	23.91837942
482	23.86979461
483	23.82141097
484	23.77322727
485	23.72524227
486	23.67745473
487	23.62986345
488	23.58246721
489	23.53526483
490	23.4882551
491	23.44143686
492	23.39480894
493	23.34837018
494	23.30211943
495	23.25605556
496	23.21017742
497	23.1644839
498	23.1189739
499	23.07364629
500	23.0285
501	22.98353393
502	22.93874701
503	22.89413817
504	22.84970635
505	22.8054505
506	22.76136957
507	22.71746252
508	22.67372835
509	22.63016601
510	22.58677451
511	22.54355284
512	22.5005
513	22.45761501
514	22.41489689
515	22.37234466
516	22.32995736
517	22.28773404
518	22.24567375
519	22.20377553
520	22.16203846
521	22.12046161
522	22.07904406
523	22.03778489
524	21.99668321
525	21.9557381
526	21.91494867
527	21.87431404
528	21.83383333
529	21.79350567
530	21.75333019
531	21.71330603
532	21.67343233
533	21.63370826
534	21.59413296
535	21.55470561
536	21.51542537
537	21.47629143
538	21.43730297
539	21.39845918
540	21.35975926
541	21.3212024
542	21.28278782
543	21.24451473
544	21.20638235
545	21.16838991
546	21.13053663
547	21.09282176
548	21.05524453
549	21.01780419
550	20.9805
551	20.94333122
552	20.9062971
553	20.86939693
554	20.83262996
555	20.7959955
556	20.75949281
557	20.72312118
558	20.68687993
559	20.65076834
560	20.61478571
561	20.57893137
562	20.54320463
563	20.5076048
564	20.47213121
565	20.43678319
566	20.40156007
567	20.3664612
568	20.33148592
569	20.29663357
570	20.26190351
571	20.2272951
572	20.19280769
573	20.15844066
574	20.12419338
575	20.09006522
576	20.05605556
577	20.02216378
578	19.98838927
579	19.95473143
580	19.92118966
581	19.88776334
582	19.85445189
583	19.82125472
584	19.78817123
585	19.75520085
586	19.722343
587	19.6895971
588	19.65696259
589	19.62443888
590	19.59202542
591	19.55972166
592	19.52752703
593	19.49544098
594	19.46346296
595	19.43159244
596	19.39982886
597	19.36817169
598	19.3366204
599	19.30517446
600	19.27383333
601	19.24259651
602	19.21146346
603	19.18043367
604	19.14950662
605	19.11868182
606	19.08795875
607	19.0573369
608	19.02681579
609	18.99639491
610	18.96607377
611	18.93585188
612	18.90572876
613	18.87570392
614	18.84577687
615	18.81594715
616	18.78621429
617	18.7565778
618	18.72703722
619	18.69759208
620	18.66824194
621	18.63898631
622	18.60982476
623	18.58075682
624	18.55178205
625	18.5229
626	18.49411022
627	18.46541228
628	18.43680573
629	18.40829014
630	18.37986508
631	18.35153011
632	18.32328481
633	18.29512875
634	18.26706151
635	18.23908268
636	18.21119182
637	18.18338854
638	18.15567241
639	18.12804304
640	18.1005
641	18.0730429
642	18.04567134
643	18.01838491
644	17.99118323
645	17.96406589
646	17.93703251
647	17.91008269
648	17.88321605
649	17.8564322
650	17.82973077
651	17.80311137
652	17.77657362
653	17.75011715
654	17.72374159
655	17.69744656
656	17.67123171
657	17.64509665
658	17.61904103
659	17.59306449
660	17.56716667
661	17.5413472
662	17.51560574
663	17.48994193
664	17.46435542
665	17.43884586
666	17.41341291
667	17.38805622
668	17.36277545
669	17.33757025
670	17.3124403
671	17.28738525
672	17.26240476
673	17.23749851
674	17.21266617
675	17.18790741
676	17.16322189
677	17.13860931
678	17.11406932
679	17.08960162
680	17.06520588
681	17.04088179
682	17.01662903
683	16.99244729
684	16.96833626
685	16.94429562
686	16.92032507
687	16.89642431
688	16.87259302
689	16.84883091
690	16.82513768
691	16.80151302
692	16.77795665
693	16.75446825
694	16.73104755
695	16.70769424
696	16.68440805
697	16.66118867
698	16.63803582
699	16.61494921
700	16.59192857
701	16.56897361
702	16.54608405
703	16.5232596
704	16.5005
705	16.47780496
706	16.45517422
707	16.4326075
708	16.41010452
709	16.38766502
710	16.36528873
711	16.34297539
712	16.32072472
713	16.29853647
714	16.27641036
715	16.25434615
716	16.23234358
717	16.21040237
718	16.18852228
719	16.16670306
720	16.14494444
721	16.12324619
722	16.10160803
723	16.08002974
724	16.05851105
725	16.03705172
726	16.01565152
727	15.99431018
728	15.97302747
729	15.95180316
730	15.93063699
731	15.90952873
732	15.88847814
733	15.86748499
734	15.84654905
735	15.82567007
736	15.80484783
737	15.78408209
738	15.76337263
739	15.74271922
740	15.72212162
741	15.70157962
742	15.68109299
743	15.66066151
744	15.64028495
745	15.61996309
746	15.59969571
747	15.5794826
748	15.55932353
749	15.53921829
750	15.51916667
751	15.49916844
752	15.4792234
753	15.45933134
754	15.43949204
755	15.4197053
756	15.3999709
757	15.38028864
758	15.36065831
759	15.34107971
760	15.32155263
761	15.30207687
762	15.28265223
763	15.26327851
764	15.2439555
765	15.22468301
766	15.20546084
767	15.18628879
768	15.16716667
769	15.14809428
770	15.12907143
771	15.11009792
772	15.09117358
773	15.07229819
774	15.05347158
775	15.03469355
776	15.01596392
777	14.9972825
778	14.9786491
779	14.96006354
780	14.94152564
781	14.92303521
782	14.90459207
783	14.88619604
784	14.86784694
785	14.84954459
786	14.8312888
787	14.81307942
788	14.79491624
789	14.77679911
790	14.75872785
791	14.74070228
792	14.72272222
793	14.70478752
794	14.68689798
795	14.66905346
796	14.65125377
797	14.63349875
798	14.61578822
799	14.59812203
800	14.5805
801	14.56292197
802	14.54538778
803	14.52789726
804	14.51045025
805	14.49304658
806	14.4756861
807	14.45836865
808	14.44109406
809	14.42386218
810	14.40667284
811	14.38952589
812	14.37242118
813	14.35535855
814	14.33833784
815	14.3213589
816	14.30442157
817	14.2875257
818	14.27067115
819	14.25385775
820	14.23708537
821	14.22035384
822	14.20366302
823	14.18701276
824	14.17040291
825	14.15383333
826	14.13730387
827	14.12081439
828	14.10436473
829	14.08795476
830	14.07158434
831	14.05525331
832	14.03896154
833	14.02270888
834	14.0064952
835	13.99032036
836	13.97418421
837	13.95808662
838	13.94202745
839	13.92600656
840	13.91002381
841	13.89407907
842	13.87817221
843	13.86230308
844	13.84647156
845	13.83067751
846	13.8149208
847	13.7992013
848	13.78351887
849	13.76787338
850	13.75226471
851	13.73669271
852	13.72115728
853	13.70565826
854	13.69019555
855	13.67476901
856	13.6593785
857	13.64402392
858	13.62870513
859	13.613422
860	13.59817442
861	13.58296225
862	13.56778538
863	13.55264368
864	13.53753704
865	13.52246532
866	13.50742841
867	13.49242618
868	13.47745853
869	13.46252532
870	13.44762644
871	13.43276177
872	13.41793119
873	13.40313459
874	13.38837185
875	13.37364286
876	13.35894749
877	13.34428563
878	13.32965718
879	13.315062
880	13.3005
881	13.28597106
882	13.27147506
883	13.25701189
884	13.24258145
885	13.22818362
886	13.21381828
887	13.19948534
888	13.18518468
889	13.1709162
890	13.15667978
891	13.14247531
892	13.12830269
893	13.11416181
894	13.10005257
895	13.08597486
896	13.07192857
897	13.0579136
898	13.04392984
899	13.0299772
900	13.01605556
901	13.00216482
902	12.98830488
903	12.97447564
904	12.96067699
905	12.94690884
906	12.93317108
907	12.91946362
908	12.90578634
909	12.89213916
910	12.87852198
911	12.86493469
912	12.85137719
913	12.8378494
914	12.8243512
915	12.81088251
916	12.79744323
917	12.78403326
918	12.77065251
919	12.75730087
920	12.74397826
921	12.73068458
922	12.71741974
923	12.70418364
924	12.69097619
925	12.6777973
926	12.66464687
927	12.65152481
928	12.63843103
929	12.62536545
930	12.61232796
931	12.59931847
932	12.58633691
933	12.57338317
934	12.56045717
935	12.54755882
936	12.53468803
937	12.52184472
938	12.50902878
939	12.49624015
940	12.48347872
941	12.47074442
942	12.45803715
943	12.44535684
944	12.43270339
945	12.42007672
946	12.40747674
947	12.39490338
948	12.38235654
949	12.36983614
950	12.35734211
951	12.34487434
952	12.33243277
953	12.32001731
954	12.30762788
955	12.2952644
956	12.28292678
957	12.27061494
958	12.25832881
959	12.2460683
960	12.23383333
961	12.22162383
962	12.20943971
963	12.19728089
964	12.1851473
965	12.17303886
966	12.16095549
967	12.1488971
968	12.13686364
969	12.12485501
970	12.11287113
971	12.10091195
972	12.08897737
973	12.07706732
974	12.06518172
975	12.05332051
976	12.04148361
977	12.02967093
978	12.01788241
979	12.00611798
980	11.99437755
981	11.98266106
982	11.97096843
983	11.95929959
984	11.94765447
985	11.93603299
986	11.92443509
987	11.91286069
988	11.90130972
989	11.8897821
990	11.87827778
991	11.86679667
992	11.85533871
993	11.84390383
994	11.83249195
995	11.82110302
996	11.80973695
997	11.79839368
998	11.78707315
999	11.77577528
1000	11.7645
1001	11.75324725
1002	11.74201697
1003	11.73080907
1004	11.71962351
1005	11.7084602
1006	11.69731909
1007	11.6862001
1008	11.67510317
1009	11.66402825
1010	11.65297525
1011	11.64194411
1012	11.63093478
1013	11.61994719
1014	11.60898126
1015	11.59803695
1016	11.58711417
1017	11.57621288
1018	11.56533301
1019	11.55447448
1020	11.54363725
1021	11.53282125
1022	11.52202642
1023	11.51125269

 

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

b707 пишет:

v258 пишет:
Замеряем внутреннее опорное мультиметром, потом замеряем внутреннее опорное программно и, зная внутреннее опорное (замеренное), вычисляем напряжение питания... Мой мозг никак не вернётся в исходное состояние после таких вывертов. А можно поподробнее, для нубов? ))

тююю мужики...

вы что, в первый раз этот способ видите? Он же во всех книжках "ардуино для чайников" есть...


Первый. Но мне физика процесса непонятна. Я считал, что внутреннее опорное напряжение от напряжения питания не зависит ))

b707
Offline
Зарегистрирован: 26.05.2017

v258 пишет:
мне физика процесса непонятна. Я считал, что внутреннее опорное напряжение от напряжения питания не зависит ))

так этот способ и основан именно на том, что опорное от питания не зависит.

А математически это обычная пропорция. Измеряем опорник относительно питания. Получаем, скажем, 200 единиц. Зная. что эти 200 единиц должны соответвовать опорному напряжению 1.1в , легко посчитать. сколько вольт соответвуют полной шкале ADC 1023 единицы

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

b707 именно по этому и усомнился в формуле

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

Ага, значит в описании таки пропущено, что программно меряем опорное при analogReference(DEFAULT). Тогда все становится на свои места ))
Не, приписку "от питания" я видел, но не сообразил...

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

ua6em пишет:

Евгений! Вы старому киповцу сломали мозг, я то по наивности думал, что AREF аналогичен ИОНу, ан нет... )))

Так, вроде, так и есть. А в чём беда?

да думал, что опорные напряжения подгоняются на каждом экземпляре контроллера, наивен был...
PS вот вчера, впервые за 7 лет выбил один порт, A0, а до сего момента не сжёг ни одной ардуины и ни одного порта... )))

aloyen
Offline
Зарегистрирован: 28.12.2021

ЕвгенийП пишет:

Какой делитель? Ничего не нужно!

Замеряешь внутренне опорное напряжение как можно тщательнее, записываешь. Это можно сделать очень просто, установить аналогрефференс на внутреннее 1,1В и на пине реф замерить сколько там на самом деле. Как можно точнее. Лучше несколько раз и усреднить.

Затем, уже в коде, программно измеряешь значение внутреннего опорного (от питания) и, зная какое там опорное (не зря измеряли), вычисляешь питание. Делов-то на копейку.

static inline void adcChooseVBG(void) { ADMUX = (ADMUX & 0xF0) | 14; }
static inline void adcStart(void) { ADCSRA |= bit(ADSC); }
static inline bool adcInProgress(void) { return ADCSRA & bit(ADSC); }
static inline unsigned adcGet(void) { return ADC; }


// Возвращает напряжение питания в десятых долях вольта
inline static int getBatteryVoltage(const int internalRefference) {
	adcChooseVBG();
	_delay_ms(1); // пусть "пропитается"
	adcStart(); // плевать на первый замер
	while (adcInProgress());
	adcStart(); // теперь замеряем
	while (adcInProgress());
	const int adc = adcGet();
	return (((internalRefference * 1024L + adc / 2) / adc) + 500) / 1000;
}

Функции нужно передать замеренное ранее значение внутреннего опорного напряжения, умноженное на 10000 (т.е. если оно 1,1В, то передавать надо 11000).

Строка №10 может и не нужна, у меня просто прямо здесь же включается питание ADC через PRR. Вот и даю ему время стабилизироваться.

Сейчас проверил. Оно возвращает всегда 0...

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

aloyen пишет:

Сейчас проверил. Оно возвращает всегда 0...

а так:
 

ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
ADCSRA |= _BV(ADSC); // Начало преобразований
while (bit_is_set(ADCSRA,ADSC)); // измерение
uint8_t low  = ADCL; // сначала нужно прочесть ADCL - это запирает ADCH
uint8_t high = ADCH; // Разлочить оба
float result = (high<<8) | low;
result = (1.1 * 1023 * 1000) / result; //Результат Vcc в милливольтах

 

b707
Offline
Зарегистрирован: 26.05.2017

aloyen пишет:

Сейчас проверил. Оно возвращает всегда 0...

пробуйте вот это

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(75); // 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
}

взято вот отсюда:

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

b707 пишет:

Komandir пишет:

ЕвгенийП В формуле из 16 строки нет ошибки ??? если adc в диапазоне 0-1023, то результат очень странный !

да, какая-то странная формула. Я обычно считаю проще

 VCC = Vref *1024/adc;

Точно такая же формула, только прежде, чем делить на adc я прибавляю половину adc - для более точного округления

(((internalRefference * 1024L + adc / 2) / adc) + 500) / 1000;

А потом делю на 1000 (предварительно прибавив 500, тоже для более точного округления).

Деление на 1000 объясняется так. Vref мы взяли умноженным на 10000, а результат делим на 1000. Значит, окончательный результат получается в десятых долях вольта, что мне и нужно было.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

aloyen пишет:

Сейчас проверил. Оно возвращает всегда 0...

Вы бредите. У меня это работает годами во всех батарейных устройствах.

Давайте Ваш код целиком.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

ЕвгенийП а умножение на 1024? посмотрите #24

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ua6em пишет:

а так:
 

result = (1.1 * 1023 * 1000) / result; //Результат Vcc в милливольтах

С float? Не стыдно?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Komandir пишет:

ЕвгенийП а умножение на 1024? посмотрите #24

Что умножение? Так же, как и у b707 

А что в №24, я не знаю про что это.

aloyen
Offline
Зарегистрирован: 28.12.2021

b707 пишет:

aloyen пишет:

Сейчас проверил. Оно возвращает всегда 0...

пробуйте вот это

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(75); // 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
}

взято вот отсюда:

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

Результат есть. Но он "прыгает" с одного значения на другое, но это не критично (~+-15mV). Про точность значения я еще не знаю, не проверял, но полуразряженный аккумулятор показывает более-менее корректно.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

ЕвгенийП пишет:

...результат получается в десятых долях вольта...

Вот этого не разглядел и запутался 

aloyen
Offline
Зарегистрирован: 28.12.2021

Komandir пишет:

ЕвгенийП пишет:

...результат получается в десятых долях вольта...

Вот этого не разглядел и запутался 

Вы не один такой)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

aloyen, так где Ваш код, какие там нули? Или сами разобрались с косяками?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Komandir, так это удобно, точнее-то нафиг не нужно.

aloyen
Offline
Зарегистрирован: 28.12.2021

ЕвгенийП пишет:

aloyen, так где Ваш код, какие там нули? Или сами разобрались с косяками?

Я делал замеры в loop() каждые 0.5 секунд, затем их выводил на oled экран (библа OLED_I2C), предварительно переведя все это в String. На экране просто выводилось значение 0.00 и ничего более.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

aloyen пишет:

Я делал замеры в loop() каждые 0.5 секунд, затем их выводил на oled экран (библа OLED_I2C), предварительно переведя все это в String. На экране просто выводилось значение 0.00 и ничего более.

Я же Вам сказал, что если она выводит 0, значит Вы что-то накосячили с её использованием. Покажете код - скажу где косяк. Не покажете - мне пофиг.

aloyen
Offline
Зарегистрирован: 28.12.2021

ЕвгенийП пишет:

aloyen пишет:

Я делал замеры в loop() каждые 0.5 секунд, затем их выводил на oled экран (библа OLED_I2C), предварительно переведя все это в String. На экране просто выводилось значение 0.00 и ничего более.

Я же Вам сказал, что если она выводит 0, значит Вы что-то накосячили с её использованием. Покажете код - скажу где косяк. Не покажете - мне пофиг.

 

#include <OLED_I2C.h>

OLED  oled(SDA, SCL, 8);
extern uint8_t SmallFont[];

void setup() {
  oled.begin();
  oled.setFont(SmallFont);
}


static inline void adcChooseVBG(void) { ADMUX = (ADMUX & 0xF0) | 14; }
static inline void adcStart(void) { ADCSRA |= bit(ADSC); }
static inline bool adcInProgress(void) { return ADCSRA & bit(ADSC); }
static inline unsigned adcGet(void) { return ADC; }


// Возвращает напряжение питания в десятых долях вольта
inline static int getBatteryVoltage(const int internalRefference) {
	adcChooseVBG();
	_delay_ms(1); // пусть "пропитается"
	adcStart(); // плевать на первый замер
	while (adcInProgress());
	adcStart(); // теперь замеряем
	while (adcInProgress());
	const int adc = adcGet();
	return (((internalRefference * 1024L + adc / 2) / adc) + 500) / 1000;
}

void loop() {
  float volt = getBatteryVoltage(1);
  oled.print(String(volt), 0, 0);
  oled.update();
  delay(500);
}
Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

int volt = getBatteryVoltage(110000);

aloyen
Offline
Зарегистрирован: 28.12.2021

Komandir пишет:

int volt = getBatteryVoltage(110000);

Воо. Теперь заработало и довольно точно (погрешность около 10mV). Спасибо.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Komandir пишет:

int volt = getBatteryVoltage(110000);

Нет. 11000

Я же писал

ЕвгенийП пишет:

Функции нужно передать замеренное ранее значение внутреннего опорного напряжения, умноженное на 10000 (т.е. если оно 1,1В, то передавать надо 11000).

Чего ж никто читать-то не умеет?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

С float? Не стыдно?

ни капельки, идея была чтобы ТС удостоверился, что накосячил... и таки да, тут косячить практически негде, а вот если подставить измеренное значение ИОН будет даже почти прилично считать...
 

void setup() {
  Serial.begin(115200);
}

void loop() {
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  ADCSRA |= _BV(ADSC); // Начало преобразований
  while (bit_is_set(ADCSRA, ADSC)); // измерение
  uint8_t low  = ADCL; // сначала нужно прочесть ADCL - это запирает ADCH
  uint8_t high = ADCH; // Разлочить оба
  float result = (high << 8) | low;
  result = (1.1 * 1023 * 1000) / result; //Результат Vcc в милливольтах
  Serial.print("Vcc = ");
  Serial.println(result, 2);
  delay(1000);
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

В общем, мне это надоело. Я добавил полную инициализацию ADC, чтобы ни от кого и ни от чего не зависеть (какой там референс до меня был и т.п.) и убрал маленькие функции.

Вот полный, готовый для запуска тест - всё нормально работает.

//
// Возвращает напряжение питания в десятых долях вольта
// Параметр - внутреннее опорное напряжение, умноженное на 10000
//
inline static int getBatteryVoltage(const int internalRefference = 11000) {
	ADCSRA = (bit(ADPS2) | bit(ADPS1) | bit(ADPS0));
	ADCSRA |= bit(ADEN);
	ADMUX = 0;
	ADCSRB = 0;
	ADMUX = (ADMUX & 0x2F) | 0x40;
	ADMUX &= ~bit(ADLAR);
	ADMUX = (ADMUX & 0xF0) | 14;
	_delay_ms(1); // пусть "пропитается"
	for (ADCSRA |= bit(ADSC); ADCSRA & bit(ADSC);); // Первый замер ни о чём
	for (ADCSRA |= bit(ADSC); ADCSRA & bit(ADSC);); // Замеряем
	while (ADCSRA & bit(ADSC));
	const int adc = ADC;
	return (((internalRefference * 1024L + adc / 2) / adc) + 500) / 1000;
}


void setup(void) {
  Serial.begin(115200);
}

void loop(void){
	Serial.println(getBatteryVoltage(11000));
	delay(2000);
}