Skip to content

Commit ebaf9fe

Browse files
committed
Documentation
1 parent 0deae77 commit ebaf9fe

File tree

9 files changed

+634
-83
lines changed

9 files changed

+634
-83
lines changed

.github/workflows/TestCompile.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# TestCompile.yml
22
# Github workflow script to test compile all examples of an Arduino library repository.
33
#
4-
# Copyright (C) 2020 Armin Joachimsmeyer
4+
# Copyright (C) 2020-2022 Armin Joachimsmeyer
55
# https://github.com/ArminJo/Github-Actions
66
#
77

@@ -11,6 +11,12 @@ on:
1111
workflow_dispatch: # To run it manually
1212
description: 'manual build check'
1313
push:
14+
paths:
15+
- '**.ino'
16+
- '**.cpp'
17+
- '**.hpp'
18+
- '**.h'
19+
- '**TestCompile.yml'
1420
jobs:
1521
build:
1622
name: Test compiling examples for UNO

SBMInfo/ADCUtils.h

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
*
1414
* This program is distributed in the hope that it will be useful,
1515
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17-
* GNU General Public License for more details.
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17+
* See the GNU General Public License for more details.
1818
*
1919
* You should have received a copy of the GNU General Public License
2020
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
@@ -24,9 +24,10 @@
2424
#ifndef _ADC_UTILS_H
2525
#define _ADC_UTILS_H
2626

27-
#if defined(__AVR__) && (!defined(__AVR_ATmega4809__))
2827
#include <Arduino.h>
29-
#if defined(ADATE)
28+
29+
#if defined(__AVR__) && defined(ADCSRA) && defined(ADATE) && (!defined(__AVR_ATmega4809__))
30+
#define ADC_UTILS_ARE_AVAILABLE
3031

3132
// PRESCALE4 => 13 * 4 = 52 microseconds per ADC conversion at 1 MHz Clock => 19,2 kHz
3233
#define ADC_PRESCALE2 1 // 26 microseconds per ADC conversion at 1 MHz
@@ -111,6 +112,12 @@
111112
#error "No temperature channel definitions specified for this AVR CPU"
112113
#endif
113114

115+
extern float sVCCVoltage;
116+
extern uint16_t sVCCVoltageMillivolt;
117+
118+
extern long sLastVoltageCheckMillis;
119+
extern uint8_t sVoltageTooLowCounter;
120+
114121
uint16_t readADCChannel(uint8_t aChannelNumber);
115122
uint16_t readADCChannelWithReference(uint8_t aChannelNumber, uint8_t aReference);
116123
uint16_t waitAndReadADCChannelWithReference(uint8_t aChannelNumber, uint8_t aReference);
@@ -127,19 +134,30 @@ uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aChannelNumber, uint8_t aDe
127134

128135
uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aChannelNumber, uint8_t aReference);
129136

137+
/*
138+
* readVCC*() functions store the result in sVCCVoltageMillivolt or sVCCVoltage
139+
*/
130140
float getVCCVoltageSimple(void);
141+
void readVCCVoltageSimple(void);
131142
uint16_t getVCCVoltageMillivoltSimple(void);
132-
float getTemperatureSimple(void);
143+
void readVCCVoltageMillivoltSimple(void);
133144
float getVCCVoltage(void);
145+
void readVCCVoltage(void);
134146
uint16_t getVCCVoltageMillivolt(void);
147+
void readVCCVoltageMillivolt(void);
135148
uint16_t getVCCVoltageReadingFor1_1VoltReference(void);
136149
uint16_t printVCCVoltageMillivolt(Print *aSerial);
137-
void printVCCVoltageMillivolt(Print *aSerial, uint16_t aVCCVoltageMillivolt);
150+
void readAndPrintVCCVoltageMillivolt(Print *aSerial);
151+
138152
uint16_t getVoltageMillivolt(uint16_t aVCCVoltageMillivolt, uint8_t aADCChannelForVoltageMeasurement);
139153
uint16_t getVoltageMillivolt(uint8_t aADCChannelForVoltageMeasurement);
140154
uint16_t getVoltageMillivoltWith_1_1VoltReference(uint8_t aADCChannelForVoltageMeasurement);
155+
float getTemperatureSimple(void);
141156
float getTemperature(void);
142157

143-
#endif // defined(ADATE)
144-
#endif // defined(__AVR__)
158+
bool isVCCTooLowMultipleTimes();
159+
void resetVCCTooLowMultipleTimes();
160+
bool isVoltageTooLow();
161+
162+
#endif // defined(__AVR__) ...
145163
#endif // _ADC_UTILS_H

SBMInfo/ADCUtils.hpp

Lines changed: 158 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,30 @@
1515
*
1616
* This program is distributed in the hope that it will be useful,
1717
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19-
* GNU General Public License for more details.
18+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19+
* See the GNU General Public License for more details.
2020
*
2121
* You should have received a copy of the GNU General Public License
2222
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
2323
*/
2424

25-
2625
#ifndef _ADC_UTILS_HPP
2726
#define _ADC_UTILS_HPP
2827

2928
#include "ADCUtils.h"
30-
#if defined(__AVR__) && defined(ADCSRA) && defined(ADATE)
29+
#if defined(ADC_UTILS_ARE_AVAILABLE)
30+
31+
#if !defined(STR_HELPER)
32+
#define STR_HELPER(x) #x
33+
#define STR(x) STR_HELPER(x)
34+
#endif
3135

3236
/*
3337
* By replacing this value with the voltage you measured a the AREF pin after a conversion
3438
* with INTERNAL you can calibrate your ADC readout. For my Nanos I measured e.g. 1060 mV and 1093 mV.
3539
*/
3640
#if !defined(ADC_INTERNAL_REFERENCE_MILLIVOLT)
37-
#define ADC_INTERNAL_REFERENCE_MILLIVOLT 1100L // Value measured at the AREF pin. If value > real AREF voltage, measured values are > real values
41+
#define ADC_INTERNAL_REFERENCE_MILLIVOLT 1100L // Change to value measured at the AREF pin. If value > real AREF voltage, measured values are > real values
3842
#endif
3943

4044
// Union to speed up the combination of low and high bytes to a word
@@ -50,6 +54,16 @@ union WordUnionForADCUtils {
5054
uint8_t *BytePointer;
5155
};
5256

57+
/*
58+
* Persistent storage for VCC value
59+
*/
60+
float sVCCVoltage;
61+
uint16_t sVCCVoltageMillivolt;
62+
63+
// for isVCCTooLowMultipleTimes()
64+
long sLastVoltageCheckMillis;
65+
uint8_t sVoltageTooLowCounter = 0;
66+
5367
/*
5468
* Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h.
5569
*/
@@ -405,11 +419,68 @@ uint16_t printVCCVoltageMillivolt(Print *aSerial) {
405419
return tVCCVoltageMillivolt;
406420
}
407421

422+
void readAndPrintVCCVoltageMillivolt(Print *aSerial) {
423+
aSerial->print(F("VCC="));
424+
sVCCVoltageMillivolt = getVCCVoltageMillivolt();
425+
aSerial->print(sVCCVoltageMillivolt);
426+
aSerial->println(" mV");
427+
}
428+
/*
429+
* !!! Function without handling of switched reference and channel.!!!
430+
* Use it ONLY if you only call getVCCVoltageSimple() or getVCCVoltageMillivoltSimple() in your program.
431+
* !!! Resolution is only 20 millivolt !!!
432+
*/
433+
void readVCCVoltageSimple(void) {
434+
// use AVCC with (optional) external capacitor at AREF pin as reference
435+
float tVCC = readADCChannelWithReferenceMultiSamples(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
436+
sVCCVoltage = (1023 * 1.1 * 4) / tVCC;
437+
}
438+
439+
/*
440+
* !!! Function without handling of switched reference and channel.!!!
441+
* Use it ONLY if you only call getVCCVoltageSimple() or getVCCVoltageMillivoltSimple() in your program.
442+
* !!! Resolution is only 20 millivolt !!!
443+
*/
444+
void readVCCVoltageMillivoltSimple(void) {
445+
// use AVCC with external capacitor at AREF pin as reference
446+
uint16_t tVCCVoltageMillivoltRaw = readADCChannelWithReferenceMultiSamples(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
447+
sVCCVoltageMillivolt = (1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCCVoltageMillivoltRaw;
448+
}
449+
450+
/*
451+
* !!! Resolution is only 20 millivolt !!!
452+
*/
453+
void readVCCVoltage(void) {
454+
sVCCVoltage = getVCCVoltageMillivolt() / 1000.0;
455+
}
456+
457+
/*
458+
* Read value of 1.1 volt internal channel using VCC (DEFAULT) as reference.
459+
* Handles reference and channel switching by introducing the appropriate delays.
460+
* !!! Resolution is only 20 millivolt !!!
461+
* Sets also the sVCCVoltageMillivolt variable.
462+
*/
463+
void readVCCVoltageMillivolt(void) {
464+
uint16_t tVCCVoltageMillivoltRaw = waitAndReadADCChannelWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT);
465+
/*
466+
* Do not switch back ADMUX to enable checkAndWaitForReferenceAndChannelToSwitch() to work correctly for the next measurement
467+
*/
468+
sVCCVoltageMillivolt = (1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCCVoltageMillivoltRaw;
469+
}
470+
471+
/*
472+
* Get voltage at ADC channel aADCChannelForVoltageMeasurement
473+
* aVCCVoltageMillivolt is assumed as reference voltage
474+
*/
408475
uint16_t getVoltageMillivolt(uint16_t aVCCVoltageMillivolt, uint8_t aADCChannelForVoltageMeasurement) {
409476
uint16_t tInputVoltageRaw = waitAndReadADCChannelWithReference(aADCChannelForVoltageMeasurement, DEFAULT);
410477
return (aVCCVoltageMillivolt * (uint32_t) tInputVoltageRaw) / 1023;
411478
}
412479

480+
/*
481+
* Get voltage at ADC channel aADCChannelForVoltageMeasurement
482+
* Reference voltage VCC is determined just before
483+
*/
413484
uint16_t getVoltageMillivolt(uint8_t aADCChannelForVoltageMeasurement) {
414485
uint16_t tInputVoltageRaw = waitAndReadADCChannelWithReference(aADCChannelForVoltageMeasurement, DEFAULT);
415486
return (getVCCVoltageMillivolt() * (uint32_t) tInputVoltageRaw) / 1023;
@@ -419,6 +490,86 @@ uint16_t getVoltageMillivoltWith_1_1VoltReference(uint8_t aADCChannelForVoltageM
419490
uint16_t tInputVoltageRaw = waitAndReadADCChannelWithReference(aADCChannelForVoltageMeasurement, INTERNAL);
420491
return (ADC_INTERNAL_REFERENCE_MILLIVOLT * (uint32_t) tInputVoltageRaw) / 1023;
421492
}
493+
494+
/*
495+
* Default values are suitable for Li-ion batteries.
496+
* We normally have voltage drop at the connectors, so the battery voltage is assumed slightly higher, than the Arduino VCC.
497+
* But keep in mind that the ultrasonic distance module HC-SR04 may not work reliable below 3.7 volt.
498+
*/
499+
#if !defined(VCC_STOP_THRESHOLD_MILLIVOLT)
500+
#define VCC_STOP_THRESHOLD_MILLIVOLT 3400 // Do not stress your battery and we require some power for standby
501+
#endif
502+
#if !defined(VCC_EMERGENCY_STOP_MILLIVOLT)
503+
#define VCC_EMERGENCY_STOP_MILLIVOLT 3000 // Many Li-ions are specified down to 3.0 volt
504+
#endif
505+
#if !defined(VCC_CHECK_PERIOD_MILLIS)
506+
#define VCC_CHECK_PERIOD_MILLIS 10000 // Period of VCC checks
507+
#endif
508+
#if !defined(VCC_CHECKS_TOO_LOW_BEFORE_STOP)
509+
#define VCC_CHECKS_TOO_LOW_BEFORE_STOP 6 // Shutdown after 6 times (60 seconds) VCC below VCC_STOP_THRESHOLD_MILLIVOLT or 1 time below VCC_EMERGENCY_STOP_MILLIVOLT
510+
#endif
511+
512+
/*
513+
* @ return true only once, when VCC_CHECKS_TOO_LOW_BEFORE_STOP (6) times voltage too low -> shutdown
514+
*/
515+
bool isVCCTooLowMultipleTimes() {
516+
/*
517+
* Check VCC every VCC_CHECK_PERIOD_MILLIS (10) seconds
518+
*/
519+
520+
if (millis() - sLastVoltageCheckMillis >= VCC_CHECK_PERIOD_MILLIS) {
521+
sLastVoltageCheckMillis = millis();
522+
523+
# if defined(INFO)
524+
readAndPrintVCCVoltageMillivolt(&Serial);
525+
# else
526+
readVCCVoltageMillivolt();
527+
# endif
528+
529+
if (sVoltageTooLowCounter < VCC_CHECKS_TOO_LOW_BEFORE_STOP) {
530+
/*
531+
* Do not check again if shutdown has happened
532+
*/
533+
if (sVCCVoltageMillivolt > VCC_STOP_THRESHOLD_MILLIVOLT) {
534+
sVoltageTooLowCounter = 0; // reset counter
535+
} else {
536+
/*
537+
* Voltage too low, wait VCC_CHECKS_TOO_LOW_BEFORE_STOP (6) times and then shut down.
538+
*/
539+
if (sVCCVoltageMillivolt < VCC_EMERGENCY_STOP_MILLIVOLT) {
540+
// emergency shutdown
541+
sVoltageTooLowCounter = VCC_CHECKS_TOO_LOW_BEFORE_STOP;
542+
# if defined(INFO)
543+
Serial.println(F("Voltage < " STR(VCC_EMERGENCY_STOP_MILLIVOLT) " mV detected -> emergency shutdown"));
544+
# endif
545+
} else {
546+
sVoltageTooLowCounter++;
547+
# if defined(INFO)
548+
Serial.print(F("Voltage < " STR(VCC_STOP_THRESHOLD_MILLIVOLT) " mV detected: "));
549+
Serial.print(VCC_CHECKS_TOO_LOW_BEFORE_STOP - sVoltageTooLowCounter);
550+
Serial.println(F(" tries left"));
551+
# endif
552+
}
553+
if (sVoltageTooLowCounter == VCC_CHECKS_TOO_LOW_BEFORE_STOP) {
554+
/*
555+
* 6 times voltage too low -> shutdown
556+
*/
557+
return true;
558+
}
559+
}
560+
}
561+
}
562+
return false;
563+
}
564+
565+
void resetVCCTooLowMultipleTimes(){
566+
sVoltageTooLowCounter = 0;
567+
}
568+
569+
bool isVoltageTooLow(){
570+
return (sVoltageTooLowCounter >= VCC_CHECKS_TOO_LOW_BEFORE_STOP);
571+
}
572+
422573
/*
423574
* !!! Function without handling of switched reference and channel.!!!
424575
* Use it ONLY if you only use INTERNAL reference (call getTemperatureSimple()) in your program.
@@ -448,10 +599,10 @@ float getTemperature(void) {
448599
#endif
449600
}
450601

451-
#elif defined(ARDUINO_ARCH_APOLLO3) // defined(__AVR__) && defined(ADATE)
602+
#elif defined(ARDUINO_ARCH_APOLLO3) // defined(ADC_UTILS_ARE_AVAILABLE)
452603
void ADCUtilsDummyToAvoidBFDAssertions(){
453604
;
454605
}
455-
#endif // defined(__AVR__) && defined(ADATE)
606+
#endif // defined(ADC_UTILS_ARE_AVAILABLE)
456607

457608
#endif // _ADC_UTILS_HPP

SBMInfo/MeasureVoltageAndResistance.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
*
1717
* This program is distributed in the hope that it will be useful,
1818
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20-
* GNU General Public License for more details.
19+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20+
* See the GNU General Public License for more details.
2121
*
2222
* You should have received a copy of the GNU General Public License
2323
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
@@ -79,7 +79,7 @@
7979
#define RESISTOR_3_PIN A3
8080

8181
#if !defined(ADC_INTERNAL_REFERENCE_MILLIVOLT)
82-
#define ADC_INTERNAL_REFERENCE_MILLIVOLT 1100L // can be adjusted by measuring the voltage at the AREF pin
82+
#define ADC_INTERNAL_REFERENCE_MILLIVOLT 1100L // Change to value measured at the AREF pin. If value > real AREF voltage, measured values are > real values
8383
#endif
8484

8585
// Fixed attenuator for voltage measurement

0 commit comments

Comments
 (0)