@@ -161,12 +161,15 @@ uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aADCChannelNumber, ui
161
161
if ((tOldADMUX & MASK_FOR_ADC_REFERENCE) != tNewReference && (aReference == INTERNAL || aReference == INTERNAL2V56)) {
162
162
#else
163
163
if ((tOldADMUX & MASK_FOR_ADC_REFERENCE) != tNewReference && aReference == INTERNAL) {
164
+ #endif
165
+ #if defined(LOCAL_DEBUG)
166
+ Serial.println (F (" Switch from DEFAULT to INTERNAL" ));
164
167
#endif
165
168
/*
166
169
* Switch reference from DEFAULT to INTERNAL
167
170
*/
168
171
delayMicroseconds (8000 ); // experimental value is >= 7600 us for Nano board and 6200 for Uno board
169
- } else if ((tOldADMUX & 0x0F ) != aADCChannelNumber) {
172
+ } else if ((tOldADMUX & ADC_CHANNEL_MUX_MASK ) != aADCChannelNumber) {
170
173
if (aADCChannelNumber == ADC_1_1_VOLT_CHANNEL_MUX) {
171
174
/*
172
175
* Internal 1.1 Volt channel requires <= 200 us for Nano board
@@ -249,9 +252,10 @@ uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aADCChannelNumber, ui
249
252
250
253
/*
251
254
* Returns sum of all sample values
252
- * Conversion time is defined as 0.104 milliseconds for 16 MHz Arduino by ADC_PRESCALE in ADCUtils.h.
255
+ * Conversion time is defined as 0.104 milliseconds for 16 MHz Arduino by ADC_PRESCALE (=ADC_PRESCALE128) in ADCUtils.h.
256
+ * @ param aNumberOfSamples If > 64 an overflow may occur.
253
257
*/
254
- uint16_t readADCChannelWithReferenceMultiSamples (uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples) {
258
+ uint16_t readADCChannelMultiSamplesWithReference (uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples) {
255
259
uint16_t tSumValue = 0 ;
256
260
ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
257
261
@@ -275,6 +279,65 @@ uint16_t readADCChannelWithReferenceMultiSamples(uint8_t aADCChannelNumber, uint
275
279
return tSumValue;
276
280
}
277
281
282
+ /*
283
+ * Returns sum of all sample values
284
+ * Conversion time is defined as 0.104 milliseconds for 16 MHz Arduino for ADC_PRESCALE128 in ADCUtils.h.
285
+ * @ param aPrescale can be one of ADC_PRESCALE2, ADC_PRESCALE4, 8, 16, 32, 64, 128.
286
+ * ADC_PRESCALE32 is recommended for excellent linearity and fast readout of 26 microseconds
287
+ * @ param aNumberOfSamples If > 16k an overflow may occur.
288
+ */
289
+ uint32_t readADCChannelMultiSamplesWithReferenceAndPrescaler (uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aPrescale,
290
+ uint16_t aNumberOfSamples) {
291
+ uint32_t tSumValue = 0 ;
292
+ ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
293
+
294
+ ADCSRB = 0 ; // Free running mode. Only active if ADATE is set to 1.
295
+ // ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
296
+ ADCSRA = (_BV (ADEN) | _BV (ADSC) | _BV (ADATE) | _BV (ADIF) | aPrescale);
297
+
298
+ for (uint16_t i = 0 ; i < aNumberOfSamples; i++) {
299
+ /*
300
+ * wait for free running conversion to finish.
301
+ * Do not wait for ADSC here, since ADSC is only low for 1 ADC Clock cycle on free running conversion.
302
+ */
303
+ loop_until_bit_is_set (ADCSRA, ADIF);
304
+
305
+ ADCSRA |= _BV (ADIF); // clear bit to enable recognizing next conversion has finished
306
+ // Add value
307
+ tSumValue += ADCL | (ADCH << 8 ); // using WordUnionForADCUtils does not save space here
308
+ // tSumValue += (ADCH << 8) | ADCL; // this does NOT work!
309
+ }
310
+ ADCSRA &= ~_BV (ADATE); // Disable auto-triggering (free running mode)
311
+ return tSumValue;
312
+ }
313
+
314
+ /*
315
+ * Returns sum of all sample values
316
+ * Assumes, that channel and reference are still set to the right values
317
+ * @ param aNumberOfSamples If > 16k an overflow may occur.
318
+ */
319
+ uint32_t readADCChannelMultiSamples (uint8_t aPrescale, uint16_t aNumberOfSamples) {
320
+ uint32_t tSumValue = 0 ;
321
+
322
+ ADCSRB = 0 ; // Free running mode. Only active if ADATE is set to 1.
323
+ // ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
324
+ ADCSRA = (_BV (ADEN) | _BV (ADSC) | _BV (ADATE) | _BV (ADIF) | aPrescale);
325
+
326
+ for (uint16_t i = 0 ; i < aNumberOfSamples; i++) {
327
+ /*
328
+ * wait for free running conversion to finish.
329
+ * Do not wait for ADSC here, since ADSC is only low for 1 ADC Clock cycle on free running conversion.
330
+ */
331
+ loop_until_bit_is_set (ADCSRA, ADIF);
332
+
333
+ ADCSRA |= _BV (ADIF); // clear bit to enable recognizing next conversion has finished
334
+ // Add value
335
+ tSumValue += ADCL | (ADCH << 8 ); // using WordUnionForADCUtils does not save space here
336
+ // tSumValue += (ADCH << 8) | ADCL; // this does NOT work!
337
+ }
338
+ ADCSRA &= ~_BV (ADATE); // Disable auto-triggering (free running mode)
339
+ return tSumValue;
340
+ }
278
341
/*
279
342
* use ADC_PRESCALE32 which gives 26 us conversion time and good linearity
280
343
* @return the maximum value of aNumberOfSamples samples.
@@ -408,7 +471,7 @@ uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aADCChannelNumber, uint8_t
408
471
*/
409
472
float getVCCVoltageSimple (void ) {
410
473
// use AVCC with (optional) external capacitor at AREF pin as reference
411
- float tVCC = readADCChannelWithReferenceMultiSamples (ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4 );
474
+ float tVCC = readADCChannelMultiSamplesWithReference (ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4 );
412
475
return ((1023 * 1.1 * 4 ) / tVCC);
413
476
}
414
477
@@ -419,7 +482,7 @@ float getVCCVoltageSimple(void) {
419
482
*/
420
483
uint16_t getVCCVoltageMillivoltSimple (void ) {
421
484
// use AVCC with external capacitor at AREF pin as reference
422
- uint16_t tVCC = readADCChannelWithReferenceMultiSamples (ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4 );
485
+ uint16_t tVCC = readADCChannelMultiSamplesWithReference (ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4 );
423
486
return ((1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4 ) / tVCC);
424
487
}
425
488
@@ -459,6 +522,9 @@ uint16_t getVCCVoltageMillivolt(void) {
459
522
return ((1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCC);
460
523
}
461
524
525
+ /*
526
+ * Does not set sVCCVoltageMillivolt
527
+ */
462
528
uint16_t printVCCVoltageMillivolt (Print *aSerial) {
463
529
aSerial->print (F (" VCC=" ));
464
530
uint16_t tVCCVoltageMillivolt = getVCCVoltageMillivolt ();
@@ -480,7 +546,7 @@ void readAndPrintVCCVoltageMillivolt(Print *aSerial) {
480
546
*/
481
547
void readVCCVoltageSimple (void ) {
482
548
// use AVCC with (optional) external capacitor at AREF pin as reference
483
- float tVCC = readADCChannelWithReferenceMultiSamples (ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4 );
549
+ float tVCC = readADCChannelMultiSamplesWithReference (ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4 );
484
550
sVCCVoltage = (1023 * (((float ) ADC_INTERNAL_REFERENCE_MILLIVOLT) / 1000 ) * 4 ) / tVCC;
485
551
}
486
552
@@ -491,7 +557,7 @@ void readVCCVoltageSimple(void) {
491
557
*/
492
558
void readVCCVoltageMillivoltSimple (void ) {
493
559
// use AVCC with external capacitor at AREF pin as reference
494
- uint16_t tVCCVoltageMillivoltRaw = readADCChannelWithReferenceMultiSamples (ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4 );
560
+ uint16_t tVCCVoltageMillivoltRaw = readADCChannelMultiSamplesWithReference (ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4 );
495
561
sVCCVoltageMillivolt = (1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4 ) / tVCCVoltageMillivoltRaw;
496
562
}
497
563
@@ -556,7 +622,7 @@ bool isVCCUSBPowered(Print *aSerial) {
556
622
aSerial->print (F (" USB powered is " ));
557
623
bool tReturnValue;
558
624
if (VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT
559
- < sVCCVoltageMillivolt && sVCCVoltageMillivolt < VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT) {
625
+ < sVCCVoltageMillivolt && sVCCVoltageMillivolt < VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT) {
560
626
tReturnValue = true ;
561
627
aSerial->print (F (" true " ));
562
628
} else {
@@ -649,6 +715,7 @@ void resetCounterForVCCUndervoltageMultipleTimes() {
649
715
* Raw reading of 1.1 V is 221 at 5.1 V.
650
716
* Raw reading of 1.1 V is 214 at 5.25 V (+5 %).
651
717
* Raw reading of 1.1 V is 204 at 5.5 V (+10 %).
718
+ * Raw reading of 1.1 V is 1126000 / VCC_MILLIVOLT
652
719
* @return true if 5 % overvoltage reached
653
720
*/
654
721
bool isVCCOvervoltage () {
@@ -660,6 +727,21 @@ bool isVCCOvervoltageSimple() {
660
727
return (sVCCVoltageMillivolt > VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT);
661
728
}
662
729
730
+ // Version not using readVCCVoltageMillivoltSimple()
731
+ bool isVCCTooHighSimple () {
732
+ ADMUX = ADC_1_1_VOLT_CHANNEL_MUX | (DEFAULT << SHIFT_VALUE_FOR_REFERENCE);
733
+ // ADCSRB = 0; // Only active if ADATE is set to 1.
734
+ // ADSC-StartConversion ADIF-Reset Interrupt Flag - NOT free running mode
735
+ ADCSRA = (_BV (ADEN) | _BV (ADSC) | _BV (ADIF) | ADC_PRESCALE128); // 128 -> 104 microseconds per ADC conversion at 16 MHz --- Arduino default
736
+ // wait for single conversion to finish
737
+ loop_until_bit_is_clear (ADCSRA, ADSC);
738
+
739
+ // Get value
740
+ uint16_t tRawValue = ADCL | (ADCH << 8 );
741
+
742
+ return tRawValue < 1126000 / VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT;
743
+ }
744
+
663
745
/*
664
746
* Temperature sensor is enabled by selecting the appropriate channel.
665
747
* Different formula for 328P and 328PB!
@@ -671,18 +753,21 @@ float getCPUTemperatureSimple(void) {
671
753
return 0.0 ;
672
754
#else
673
755
// use internal 1.1 volt as reference. 4 times oversample. Assume the signal has noise, but never verified :-(
674
- uint16_t tTempRaw = readADCChannelWithReferenceOversample (ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL, 2 );
756
+ uint16_t tTemperatureRaw = readADCChannelWithReferenceOversample (ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL, 2 );
675
757
#if defined(LOCAL_DEBUG)
676
758
Serial.print (F (" TempRaw=" ));
677
- Serial.println (tTempRaw );
759
+ Serial.println (tTemperatureRaw );
678
760
#endif
679
761
680
762
#if defined(__AVR_ATmega328PB__)
681
- tTempRaw -= 245 ;
682
- return (float )tTempRaw;
763
+ tTemperatureRaw -= 245 ;
764
+ return (float )tTemperatureRaw;
765
+ #elif defined(__AVR_ATtiny85__)
766
+ tTemperatureRaw -= 273 ; // 273 and 1.1666 are values from the datasheet
767
+ return (float )tTemperatureRaw / 1.1666 ;
683
768
#else
684
- tTempRaw -= 317 ;
685
- return (float ) tTempRaw / 1.22 ;
769
+ tTemperatureRaw -= 317 ;
770
+ return (float ) tTemperatureRaw / 1.22 ;
686
771
#endif
687
772
#endif
688
773
}
@@ -704,7 +789,7 @@ float getCPUTemperature(void) {
704
789
}
705
790
706
791
#else // defined(ADC_UTILS_ARE_AVAILABLE)
707
- // Dummy definition of functions defined in ADCUtils to compile examples without errors
792
+ // Dummy definition of functions defined in ADCUtils to compile examples for non AVR platforms without errors
708
793
/*
709
794
* Persistent storage for VCC value
710
795
*/
0 commit comments