From c528cdff9b613bc7a8e4763d078b46145140d7a6 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Tue, 28 Jul 2020 07:31:58 -0500 Subject: [PATCH 1/7] CurrentRange_R3: add modal menu for calibration adjustments The keys that adjust calibration constants are too easy to hit by mistake, corrupting the saved value. Also the difference between +/- and is not intuitive. Use a capital letter input to enter a mode to adjust any of the calibration constants, and use +/- consistently within the mode. Use ! to exit the mode since ESC clobbers screen output. Signed-off-by: Peter A. Bigot --- CurrentRanger_R3.ino | 85 ++++++++++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 23 deletions(-) diff --git a/CurrentRanger_R3.ino b/CurrentRanger_R3.ino index f310607..a8d30fc 100644 --- a/CurrentRanger_R3.ino +++ b/CurrentRanger_R3.ino @@ -312,30 +312,67 @@ void loop() uint32_t timestamp=micros(); if (Serial.available()>0) { + #define MODE_DISABLED 0 + #define MODE_GAIN 1 + #define MODE_LDO 2 + static char mode; + char inByte = Serial.read(); switch (inByte) { - case '+': - eeprom_ADCgain.write(++gainCorrectionValue); - analogReadCorrection(offsetCorrectionValue,gainCorrectionValue); - Serial.print("new gainCorrectionValue = "); - Serial.println(gainCorrectionValue); + case '!': + if (mode) { + mode = 0; + Serial.println("exit mode"); + } break; - case '-': - eeprom_ADCgain.write(--gainCorrectionValue); - analogReadCorrection(offsetCorrectionValue,gainCorrectionValue); - Serial.print("new gainCorrectionValue = "); - Serial.println(gainCorrectionValue); + case 'G': + if (mode == MODE_DISABLED) { + mode = MODE_GAIN; + Serial.println("gain adj mode"); + } break; - case '<': - saveLDO(ldoValue-0.001); - Serial.print("new LDO_Value = "); - Serial.println(ldoValue, 3); + case 'L': + if (mode == MODE_DISABLED) { + mode = MODE_LDO; + Serial.println("ldo adj mode"); + } break; - case '>': - saveLDO(ldoValue+0.001); - Serial.print("new LDO_Value = "); - Serial.println(ldoValue, 3); + case '+': + switch (mode) { + case MODE_GAIN: + eeprom_ADCgain.write(++gainCorrectionValue); + analogReadCorrection(offsetCorrectionValue,gainCorrectionValue); + Serial.print("new gainCorrectionValue = "); + Serial.println(gainCorrectionValue); + break; + case MODE_LDO: + saveLDO(ldoValue+0.001); + Serial.print("new LDO_Value = "); + Serial.println(ldoValue, 3); + break; + default: + Serial.println("no mode selected"); + break; + } + break; + case '-': + switch (mode) { + case MODE_GAIN: + eeprom_ADCgain.write(--gainCorrectionValue); + analogReadCorrection(offsetCorrectionValue,gainCorrectionValue); + Serial.print("new gainCorrectionValue = "); + Serial.println(gainCorrectionValue); + break; + case MODE_LDO: + saveLDO(ldoValue-0.001); + Serial.print("new LDO_Value = "); + Serial.println(ldoValue, 3); + break; + default: + Serial.println("no mode selected"); + break; + } break; case 'u': //toggle USB logging USB_LOGGING_ENABLED =! USB_LOGGING_ENABLED; @@ -787,11 +824,13 @@ void printSerialMenu() { Serial.println("s = cycle ADC sampling speeds (average,faster,slower)"); Serial.println("t = toggle touchpad serial output debug info"); Serial.println("u = toggle USB/serial logging"); - Serial.println("< = Calibrate LDO value (-1mV)"); - Serial.println("> = Calibrate LDO value (+1mV)"); - Serial.println("- = Calibrate GAIN value (-1)"); - Serial.println("+ = Calibrate GAIN value (+1)"); + Serial.println("+ = increase mode value"); + Serial.println("- = decrease mode value"); Serial.println("? = Print this menu and calib info"); + Serial.println("\r\nMode commands:"); + Serial.println("G = gain calibration mode (1)"); + Serial.println("L = ldo calibration mode (1 mV)"); + Serial.println("! = exit mode"); Serial.println(); } @@ -807,4 +846,4 @@ void analogReadCorrection(int offset, uint16_t gain) ADC->GAINCORR.reg = ADC_GAINCORR_GAINCORR(gain); ADC->CTRLB.bit.CORREN = 1; while(ADC->STATUS.bit.SYNCBUSY); -} \ No newline at end of file +} From 75f58e650fb7f51ae49ade124965c827852511b7 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Tue, 28 Jul 2020 08:11:21 -0500 Subject: [PATCH 2/7] CurrentRange_R3: make oversampling configuration more flexible Add a modal menu for selecting the oversample configuration (AVGCTRL.SAMPLEN), from 1x to 1024x as supported by the hardware. Set AVGCTRL.ADJRES to preserve 12-bit full-scale output. Remove commented out old code and reduce the size required to store the 8-bit ADC_AVGCTRL register. Signed-off-by: Peter A. Bigot --- CurrentRanger_R3.ino | 74 +++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/CurrentRanger_R3.ino b/CurrentRanger_R3.ino index a8d30fc..c391889 100644 --- a/CurrentRanger_R3.ino +++ b/CurrentRanger_R3.ino @@ -18,7 +18,6 @@ #include //for emulated EEPROM - https://github.com/cmaglie/FlashStorage #include //https://github.com/adafruit/Adafruit_FreeTouch #include //https://github.com/olikraus/u8g2/wiki/u8g2reference fonts:https://github.com/olikraus/u8g2/wiki/fntlistall -//#include //*********************************************************************************************************** #define BIAS_LED 11 #define LPFPIN 4 @@ -40,12 +39,6 @@ #define SENSE_GNDISO A2 #define SENSE_VIN A5 #define ADC_PRESCALER ADC_CTRLB_PRESCALER_DIV16 -//#define ADC_AVGCTRL ADC_AVGCTRL_SAMPLENUM_128 | ADC_AVGCTRL_ADJRES(0x4ul) - //ADC_AVGCTRL_SAMPLENUM_1 | ADC_AVGCTRL_ADJRES(0x00ul); // take 1 sample, adjusting result by 0 - //ADC_AVGCTRL_SAMPLENUM_16 | ADC_AVGCTRL_ADJRES(0x4ul); //take 16 samples adjust by 4 - //ADC_AVGCTRL_SAMPLENUM_256 | ADC_AVGCTRL_ADJRES(0x4ul); //take 256 samples adjust by 4 - //ADC_AVGCTRL_SAMPLENUM_512 | ADC_AVGCTRL_ADJRES(0x4ul); //take 512 samples adjust by 4 - //ADC_AVGCTRL_SAMPLENUM_1024 | ADC_AVGCTRL_ADJRES(0x4ul); //take 1024 samples adjust by 4 #define ADC_SAMPCTRL 0b111 //sample timing [fast 0..0b111 slow] #define ADCFULLRANGE 4095.0 #define VBATREADLOOPS 100 //read vbat every this many OLED_REFRESH_INTERVAL loops @@ -111,10 +104,6 @@ Adafruit_FreeTouch qt[3] = { #define LOGGING_FORMAT_MILLIS 3 //ex: 1234 = 1.234A = 1234000uA = 1234000000nA #define LOGGING_FORMAT_ADC 4 //raw output for each range (0..4095) //*********************************************************************************************************** -#define ADC_SAMPLING_SPEED_AVG 0 -#define ADC_SAMPLING_SPEED_FAST 1 -#define ADC_SAMPLING_SPEED_SLOW 2 -//*********************************************************************************************************** int offsetCorrectionValue = 0; uint16_t gainCorrectionValue = 0; float ldoValue = 0, ldoOptimized=0; @@ -124,8 +113,8 @@ uint8_t TOUCH_DEBUG_ENABLED = false; uint8_t GPIO_HEADER_RANGING = false; uint8_t BT_LOGGING_ENABLED = true; uint8_t LOGGING_FORMAT = LOGGING_FORMAT_EXPONENT; -uint16_t ADC_SAMPLING_SPEED = ADC_SAMPLING_SPEED_AVG; -uint32_t ADC_AVGCTRL; +uint8_t ADC_SAMPLEN = 0; +uint8_t ADC_AVGCTRL; uint8_t calibrationPerformed=false; uint8_t analog_ref_half=true; char rangeUnit = 'm'; @@ -140,7 +129,7 @@ FlashStorage(eeprom_ADCgain, uint16_t); FlashStorage(eeprom_LDO, float); FlashStorage(eeprom_AUTOFF, uint16_t); FlashStorage(eeprom_LOGGINGFORMAT, uint8_t); -FlashStorage(eeprom_ADCSAMPLINGSPEED, uint8_t); +FlashStorage(eeprom_ADCSAMPLEN, uint8_t); //*********************************************************************************************************** void setup() { @@ -213,7 +202,7 @@ void setup() { saveLDO(LDO_DEFAULT); else ldoOptimizeRefresh(); - ADC_SAMPLING_SPEED = eeprom_ADCSAMPLINGSPEED.read(); + ADC_SAMPLEN = eeprom_ADCSAMPLEN.read(); refreshADCSamplingSpeed(); //load correct value into ADC_AVGCTRL if (gainCorrectionValue!=0) //check if anything saved in EEPROM (gain changed via SerialUSB +/-) @@ -315,6 +304,7 @@ void loop() #define MODE_DISABLED 0 #define MODE_GAIN 1 #define MODE_LDO 2 + #define MODE_SAMPLEN 3 static char mode; char inByte = Serial.read(); @@ -338,6 +328,12 @@ void loop() Serial.println("ldo adj mode"); } break; + case 'O': + if (mode == MODE_DISABLED) { + mode = MODE_SAMPLEN; + Serial.println("oversampling adj mode"); + } + break; case '+': switch (mode) { case MODE_GAIN: @@ -351,6 +347,17 @@ void loop() Serial.print("new LDO_Value = "); Serial.println(ldoValue, 3); break; + case MODE_SAMPLEN: + if (ADC_SAMPLEN < ADC_AVGCTRL_SAMPLENUM_1024_Val) { + ++ADC_SAMPLEN; + Serial.print("oversample "); + Serial.println(1U << ADC_SAMPLEN); + eeprom_ADCSAMPLEN.write(ADC_SAMPLEN); + refreshADCSamplingSpeed(); + } else { + Serial.println("at upper limit"); + } + break; default: Serial.println("no mode selected"); break; @@ -369,6 +376,17 @@ void loop() Serial.print("new LDO_Value = "); Serial.println(ldoValue, 3); break; + case MODE_SAMPLEN: + if (ADC_SAMPLEN > ADC_AVGCTRL_SAMPLENUM_1_Val) { + --ADC_SAMPLEN; + Serial.print("oversample "); + Serial.println(1U << ADC_SAMPLEN); + eeprom_ADCSAMPLEN.write(ADC_SAMPLEN); + refreshADCSamplingSpeed(); + } else { + Serial.println("at lower limit"); + } + break; default: Serial.println("no mode selected"); break; @@ -404,14 +422,6 @@ void loop() if (LOGGING_FORMAT==LOGGING_FORMAT_MILLIS) Serial.println("LOGGING_FORMAT_MILLIS"); else if (LOGGING_FORMAT==LOGGING_FORMAT_ADC) Serial.println("LOGGING_FORMAT_ADC"); break; - case 's': - if (++ADC_SAMPLING_SPEED>ADC_SAMPLING_SPEED_SLOW) ADC_SAMPLING_SPEED=ADC_SAMPLING_SPEED_AVG; - if (ADC_SAMPLING_SPEED==ADC_SAMPLING_SPEED_AVG) Serial.println("ADC_SAMPLING_SPEED_AVG"); else - if (ADC_SAMPLING_SPEED==ADC_SAMPLING_SPEED_FAST) Serial.println("ADC_SAMPLING_SPEED_FAST"); else - if (ADC_SAMPLING_SPEED==ADC_SAMPLING_SPEED_SLOW) Serial.println("ADC_SAMPLING_SPEED_SLOW"); - eeprom_ADCSAMPLINGSPEED.write(ADC_SAMPLING_SPEED); - refreshADCSamplingSpeed(); - break; case 'a': //toggle autoOff function if (AUTOFF_INTERVAL == AUTOFF_DEFAULT) { @@ -793,19 +803,9 @@ void saveLDO(float newLdoValue) { } void refreshADCSamplingSpeed() { - if (ADC_SAMPLING_SPEED==ADC_SAMPLING_SPEED_AVG) - ADC_AVGCTRL = ADC_AVGCTRL_SAMPLENUM_64 | ADC_AVGCTRL_ADJRES(0x4ul); - else if (ADC_SAMPLING_SPEED==ADC_SAMPLING_SPEED_FAST) - ADC_AVGCTRL = ADC_AVGCTRL_SAMPLENUM_16 | ADC_AVGCTRL_ADJRES(0x4ul); //take 16 samples adjust by 4 - else if (ADC_SAMPLING_SPEED==ADC_SAMPLING_SPEED_SLOW) - ADC_AVGCTRL = ADC_AVGCTRL_SAMPLENUM_256 | ADC_AVGCTRL_ADJRES(0x4ul); //take 512 samples adjust by 4 - //other combinations: - //ADC_AVGCTRL_SAMPLENUM_128 | ADC_AVGCTRL_ADJRES(0x4ul) - //ADC_AVGCTRL_SAMPLENUM_1 | ADC_AVGCTRL_ADJRES(0x00ul); // take 1 sample, adjusting result by 0 - //ADC_AVGCTRL_SAMPLENUM_16 | ADC_AVGCTRL_ADJRES(0x4ul); //take 16 samples adjust by 4 - //ADC_AVGCTRL_SAMPLENUM_256 | ADC_AVGCTRL_ADJRES(0x4ul); //take 256 samples adjust by 4 - //ADC_AVGCTRL_SAMPLENUM_512 | ADC_AVGCTRL_ADJRES(0x4ul); //take 512 samples adjust by 4 - //ADC_AVGCTRL_SAMPLENUM_1024 | ADC_AVGCTRL_ADJRES(0x4ul); //take 1024 samples adjust by 4 + uint8_t adjres = (ADC_SAMPLEN < 4) ? ADC_SAMPLEN : 4; + ADC_AVGCTRL = ((ADC_SAMPLEN << ADC_AVGCTRL_SAMPLENUM_Pos) & ADC_AVGCTRL_SAMPLENUM_Msk) + | ((adjres << ADC_AVGCTRL_ADJRES_Pos) & ADC_AVGCTRL_ADJRES_Msk); setupADC(); } @@ -814,6 +814,7 @@ void printCalibInfo() { Serial.print("Offset="); Serial.println(offsetCorrectionValue); Serial.print("Gain="); Serial.println(gainCorrectionValue); Serial.print("LDO="); Serial.println(ldoValue,3); + Serial.print("Oversample="); Serial.println(1U << ADC_SAMPLEN); } void printSerialMenu() { Serial.println("\r\nUSB serial commands:"); @@ -830,6 +831,7 @@ void printSerialMenu() { Serial.println("\r\nMode commands:"); Serial.println("G = gain calibration mode (1)"); Serial.println("L = ldo calibration mode (1 mV)"); + Serial.println("O = oversampling rate"); Serial.println("! = exit mode"); Serial.println(); } From cdf272cec9c6c0765be5dccf06c57e6eec39ae21 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Tue, 28 Jul 2020 08:30:11 -0500 Subject: [PATCH 3/7] CurrentRange_R3: display oversample rate on OLED Shift the range and sample display in the upper left corner over to make room for a one character expression of the oversampling rate. Signed-off-by: Peter A. Bigot --- CurrentRanger_R3.ino | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/CurrentRanger_R3.ino b/CurrentRanger_R3.ino index c391889..f5c801c 100644 --- a/CurrentRanger_R3.ino +++ b/CurrentRanger_R3.ino @@ -541,15 +541,24 @@ void loop() else u8g2.drawGlyph(115, 10, 0xE242); //u8g2.drawStr(88,12,"LoBat!"); u8g2.setFont(u8g2_font_6x12_tf); //7us + + // Display oversample exponent in hex + char buf[2] = { + ADC_SAMPLEN < 10 + ? ('0' + ADC_SAMPLEN) + : ('A' - 10 + ADC_SAMPLEN), + }; + u8g2.drawStr(0,12, buf); // ?? us + if (AUTORANGE) { - u8g2.drawStr(0,12, analog_ref_half ? "AUTO\xb7\xbd" : "AUTO"); - u8g2.setCursor(42,12); u8g2.print(readDiff,0); + u8g2.drawStr(12,12, analog_ref_half ? "AUTO\xb7\xbd" : "AUTO"); + u8g2.setCursor(54,12); u8g2.print(readDiff,0); } else { - if (analog_ref_half) u8g2.drawStr(0,12,"\xbd"); - u8g2.setCursor(12,12); u8g2.print(readDiff,0); + if (analog_ref_half) u8g2.drawStr(12,12,"\xbd"); + u8g2.setCursor(24,12); u8g2.print(readDiff,0); } if (autoffBuzz) u8g2.drawStr(5,26,"* AUTO OFF! *"); //autoffWarning From dde1bb46250fb4c2a9a6e2a4cc9d8942fd64e2c6 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Tue, 28 Jul 2020 13:46:27 -0500 Subject: [PATCH 4/7] CurrentRange_R3: allow touchpad setting of sample rate Use "sample rate" instead of oversample rate to get a more natural match to user expectations: increase should increase the sample rate, which means decrease the oversample rate. Add a preferences byte persisted in EEPROM. Use this to record whether the user wants simultaneous touch of uA+mA to toggle offset (bias) mode (default) or to repurpose the nA and mA keys to increase or decrease the sample rate. Changes to sample rate through the serial interface are persisted to EEPROM. Changes to the sample rate from the touchpads are not persisted. A tone is emitted to audibly reflect the selected sample rate. Signed-off-by: Peter A. Bigot --- CurrentRanger_R3.ino | 118 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 94 insertions(+), 24 deletions(-) diff --git a/CurrentRanger_R3.ino b/CurrentRanger_R3.ino index f5c801c..d1b9240 100644 --- a/CurrentRanger_R3.ino +++ b/CurrentRanger_R3.ino @@ -54,13 +54,22 @@ #define LDO_DEFAULT 3.300 //volts, change to actual LDO output (measure GND-3V on OLED header) //*********************************************************************************************************** #define BUZZER 1 // BUZZER pin +#define NOTE_C4 262 +#define NOTE_D4 294 +#define NOTE_E4 330 +#define NOTE_F4 349 +#define NOTE_G4 392 +#define NOTE_A4 440 +#define NOTE_B4 494 #define NOTE_C5 523 #define NOTE_D5 587 #define NOTE_E5 659 #define NOTE_F5 698 #define NOTE_G5 784 +#define NOTE_A5 880 #define NOTE_B5 988 #define NOTE_C6 1047 +#define NOTE_D6 1175 #define TONE_BEEP 4200 //*********************************************************************************************************** #define MODE_MANUAL 0 @@ -104,6 +113,9 @@ Adafruit_FreeTouch qt[3] = { #define LOGGING_FORMAT_MILLIS 3 //ex: 1234 = 1.234A = 1234000uA = 1234000000nA #define LOGGING_FORMAT_ADC 4 //raw output for each range (0..4095) //*********************************************************************************************************** +#define PREFERENCE_MU_SAMPLERATE 0x01 // default BIAS +//*********************************************************************************************************** +static const char samplerate_id[] = "H987654321L"; int offsetCorrectionValue = 0; uint16_t gainCorrectionValue = 0; float ldoValue = 0, ldoOptimized=0; @@ -124,12 +136,14 @@ uint8_t autoffBuzz=0; #ifdef BT_SERIAL_EN uint8_t BT_found=false; #endif +uint8_t PREFERENCES; FlashStorage(eeprom_ADCoffset, int); FlashStorage(eeprom_ADCgain, uint16_t); FlashStorage(eeprom_LDO, float); FlashStorage(eeprom_AUTOFF, uint16_t); FlashStorage(eeprom_LOGGINGFORMAT, uint8_t); FlashStorage(eeprom_ADCSAMPLEN, uint8_t); +FlashStorage(eeprom_PREFERENCES, uint8_t); //*********************************************************************************************************** void setup() { @@ -205,6 +219,8 @@ void setup() { ADC_SAMPLEN = eeprom_ADCSAMPLEN.read(); refreshADCSamplingSpeed(); //load correct value into ADC_AVGCTRL + PREFERENCES = eeprom_PREFERENCES.read(); + if (gainCorrectionValue!=0) //check if anything saved in EEPROM (gain changed via SerialUSB +/-) analogReadCorrectionForced(offsetCorrectionValue, gainCorrectionValue); else { @@ -271,9 +287,9 @@ void setup() { if (STARTUP_MODE == MODE_AUTORANGE) toggleAutoranging(); } -uint32_t oledInterval=0, lpfInterval=0, offsetInterval=0, autorangeInterval=0, btInterval=0, +uint32_t oledInterval=0, lpfInterval=0, modeInterval=0, autorangeInterval=0, btInterval=0, autoOffBuzzInterval=0, touchSampleInterval=0, lastRangeChange=0; -byte LPF=0, BIAS=0, AUTORANGE=0; +byte LPF=0, BIAS=0, AUTORANGE=0, SRADJUST=0; byte readVbatLoop=0; float vbat=0, VOUT=0; float read1=0,read2=0,readDiff=0; @@ -282,6 +298,17 @@ bool rangeSwitched=false; #define RANGE_UA rangeUnit=='u' #define RANGE_NA rangeUnit=='n' +void sampleRateBeep() +{ + static const uint16_t freq_Hz[] = { + NOTE_D6, NOTE_C6, NOTE_B5, NOTE_A5, NOTE_G5, + NOTE_F5, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_B4, + NOTE_A4, + }; + tone(BUZZER, freq_Hz[ADC_SAMPLEN], 200); + delay(100); +} + void rangeBeep(uint16_t switch_delay=0) { uint16_t freq = NOTE_C5; @@ -296,6 +323,29 @@ void rangeBeep(uint16_t switch_delay=0) } } +bool sampleRateAdjust(int8_t delta) +{ + // delta is positive to increase sample rate = decrease oversample rate + bool ok = ((ADC_SAMPLEN - delta) >= ADC_AVGCTRL_SAMPLENUM_1_Val) + && ((ADC_SAMPLEN - delta) <= ADC_AVGCTRL_SAMPLENUM_1024_Val); + if (ok) { + ADC_SAMPLEN -= delta; + refreshADCSamplingSpeed(); + } + return ok; +} + +void sampleRateOutSerial() +{ + char buf[2] = { + samplerate_id[ADC_SAMPLEN], + }; + Serial.print(buf); + Serial.print(" (div "); + Serial.print(1U << ADC_SAMPLEN); + Serial.println(")"); +} + void loop() { uint32_t timestamp=micros(); @@ -328,10 +378,11 @@ void loop() Serial.println("ldo adj mode"); } break; - case 'O': + case 'S': if (mode == MODE_DISABLED) { mode = MODE_SAMPLEN; - Serial.println("oversampling adj mode"); + Serial.print("samplerate adj mode: start "); + sampleRateOutSerial(); } break; case '+': @@ -348,12 +399,9 @@ void loop() Serial.println(ldoValue, 3); break; case MODE_SAMPLEN: - if (ADC_SAMPLEN < ADC_AVGCTRL_SAMPLENUM_1024_Val) { - ++ADC_SAMPLEN; - Serial.print("oversample "); - Serial.println(1U << ADC_SAMPLEN); + if (sampleRateAdjust(1)) { + sampleRateOutSerial(); eeprom_ADCSAMPLEN.write(ADC_SAMPLEN); - refreshADCSamplingSpeed(); } else { Serial.println("at upper limit"); } @@ -377,12 +425,9 @@ void loop() Serial.println(ldoValue, 3); break; case MODE_SAMPLEN: - if (ADC_SAMPLEN > ADC_AVGCTRL_SAMPLENUM_1_Val) { - --ADC_SAMPLEN; - Serial.print("oversample "); - Serial.println(1U << ADC_SAMPLEN); + if (sampleRateAdjust(-1)) { + sampleRateOutSerial(); eeprom_ADCSAMPLEN.write(ADC_SAMPLEN); - refreshADCSamplingSpeed(); } else { Serial.println("at lower limit"); } @@ -392,6 +437,13 @@ void loop() break; } break; + case 'o': //toggle touchpad bias mode/sample rate adjustment + PREFERENCES ^= PREFERENCE_MU_SAMPLERATE; + eeprom_PREFERENCES.write(PREFERENCES); + Serial.println((PREFERENCES & PREFERENCE_MU_SAMPLERATE) + ? "uA+mU toggle adjust sample rate" + : "uA+mU toggle offset mode"); + break; case 'u': //toggle USB logging USB_LOGGING_ENABLED =! USB_LOGGING_ENABLED; Serial.println(USB_LOGGING_ENABLED ? "USB_LOGGING_ENABLED" : "USB_LOGGING_DISABLED"); @@ -543,10 +595,9 @@ void loop() u8g2.setFont(u8g2_font_6x12_tf); //7us // Display oversample exponent in hex - char buf[2] = { - ADC_SAMPLEN < 10 - ? ('0' + ADC_SAMPLEN) - : ('A' - 10 + ADC_SAMPLEN), + char buf[3] = { + samplerate_id[ADC_SAMPLEN], + SRADJUST ? '?' : 0, }; u8g2.drawStr(0,12, buf); // ?? us @@ -603,18 +654,23 @@ void handleTouchPads() { if (MA_PRESSED || UA_PRESSED || NA_PRESSED) lastRangeChange=millis(); //range switching - if (!AUTORANGE) + if (!AUTORANGE && !SRADJUST) { if (MA_PRESSED && !UA_PRESSED && !NA_PRESSED && rangeUnit!='m') { rangeMA(); rangeBeep(); } if (UA_PRESSED && !MA_PRESSED && !NA_PRESSED && rangeUnit!='u') { rangeUA(); rangeBeep(); } if (NA_PRESSED && !UA_PRESSED && !MA_PRESSED && rangeUnit!='n') { rangeNA(); rangeBeep(); } + } else if (!AUTORANGE) { + if (MA_PRESSED && !UA_PRESSED && !NA_PRESSED) { sampleRateAdjust(1); sampleRateBeep(); } + if (!MA_PRESSED && !UA_PRESSED && NA_PRESSED) { sampleRateAdjust(-1); sampleRateBeep(); } } //LPF activation --- [NA+UA] if (UA_PRESSED && NA_PRESSED && !MA_PRESSED && millis()-lpfInterval>1000) { toggleLPF(); Beep(3, false); } - //offset toggling (GNDISO to half supply) --- [MA+UA] - if (MA_PRESSED && UA_PRESSED && !NA_PRESSED && millis()-offsetInterval>1000) { toggleOffset(); Beep(3, false); } + //Alternate mode activation --- [MA+UA] + // PREFERENCE_MU_SAMPLERATE : NA reduce sample rate, MA increase sample rate + // !PREFERENCE_MU_SAMPLERATE : offset sampling (GNDISO to half supply) + if (MA_PRESSED && UA_PRESSED && !NA_PRESSED && millis()-modeInterval>1000) { toggleModeMU(); Beep(3, false); } //AUTORANGE toggling if (MA_PRESSED && NA_PRESSED && !UA_PRESSED && millis()-autorangeInterval>1000) { toggleAutoranging(); Beep(20, false); delay(50); Beep(20, false); } @@ -703,12 +759,22 @@ void toggleLPF() { void toggleOffset() { BIAS=!BIAS; - offsetInterval = millis(); analogWrite(A0, (BIAS ? DAC_HALF_SUPPLY_OFFSET : DAC_GND_ISO_OFFSET)); digitalWrite(BIAS_LED, BIAS); if (AUTORANGE && BIAS) toggleAutoranging(); //turn off AUTORANGE } +void toggleModeMU() { + modeInterval = millis(); + if (PREFERENCES & PREFERENCE_MU_SAMPLERATE) { + SRADJUST=!SRADJUST; + Serial.print("sample rate adjust "); + Serial.println(SRADJUST ? "on" : "off"); + } else { + toggleOffset(); + } +} + void toggleAutoranging() { autorangeInterval = millis(); AUTORANGE=!AUTORANGE; @@ -824,6 +890,10 @@ void printCalibInfo() { Serial.print("Gain="); Serial.println(gainCorrectionValue); Serial.print("LDO="); Serial.println(ldoValue,3); Serial.print("Oversample="); Serial.println(1U << ADC_SAMPLEN); + Serial.print("uA+mA: "); + Serial.println((PREFERENCES & PREFERENCE_MU_SAMPLERATE) + ? "toggle samplerate adjust" + : "toggle offset enable"); } void printSerialMenu() { Serial.println("\r\nUSB serial commands:"); @@ -831,7 +901,7 @@ void printSerialMenu() { Serial.print ("b = toggle BT/serial logging (");Serial.print(SERIAL_UART_BAUD);Serial.println("baud)"); Serial.println("f = cycle serial logging formats (exponent,nA,uA,mA/raw-ADC)"); Serial.println("g = toggle GPIO range indication (SCK=mA,MISO=uA,MOSI=nA)"); - Serial.println("s = cycle ADC sampling speeds (average,faster,slower)"); + Serial.println("o = toggle touchpad offset (bias) / samplerate selection"); Serial.println("t = toggle touchpad serial output debug info"); Serial.println("u = toggle USB/serial logging"); Serial.println("+ = increase mode value"); @@ -840,7 +910,7 @@ void printSerialMenu() { Serial.println("\r\nMode commands:"); Serial.println("G = gain calibration mode (1)"); Serial.println("L = ldo calibration mode (1 mV)"); - Serial.println("O = oversampling rate"); + Serial.println("S = sample rate"); Serial.println("! = exit mode"); Serial.println(); } From e8dce7b2b1ece344a8665f620b29ee709902b15f Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Wed, 29 Jul 2020 10:04:23 -0500 Subject: [PATCH 5/7] CurrentRanger_R3: improve serial representation of sample rate Refactor code that provides a human-readable representation of the sample rate. Display the configured sample rate along with other persisted information in the config/calibration block. Signed-off-by: Peter A. Bigot --- CurrentRanger_R3.ino | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/CurrentRanger_R3.ino b/CurrentRanger_R3.ino index d1b9240..c34e280 100644 --- a/CurrentRanger_R3.ino +++ b/CurrentRanger_R3.ino @@ -115,7 +115,6 @@ Adafruit_FreeTouch qt[3] = { //*********************************************************************************************************** #define PREFERENCE_MU_SAMPLERATE 0x01 // default BIAS //*********************************************************************************************************** -static const char samplerate_id[] = "H987654321L"; int offsetCorrectionValue = 0; uint16_t gainCorrectionValue = 0; float ldoValue = 0, ldoOptimized=0; @@ -298,6 +297,27 @@ bool rangeSwitched=false; #define RANGE_UA rangeUnit=='u' #define RANGE_NA rangeUnit=='n' +const char *sampleRateStr(bool changing = false) +{ + static const char samplerate_id[] = "H987654321L"; + static char buf[3]; + char *bp = buf; + *bp++ = samplerate_id[ADC_SAMPLEN]; + if (changing) { + *bp++ = '?'; + } + *bp = 0; + return buf; +} + +void sampleRateOutSerial() +{ + Serial.print(sampleRateStr()); + Serial.print(" (div "); + Serial.print(1U << ADC_SAMPLEN); + Serial.println(")"); +} + void sampleRateBeep() { static const uint16_t freq_Hz[] = { @@ -335,17 +355,6 @@ bool sampleRateAdjust(int8_t delta) return ok; } -void sampleRateOutSerial() -{ - char buf[2] = { - samplerate_id[ADC_SAMPLEN], - }; - Serial.print(buf); - Serial.print(" (div "); - Serial.print(1U << ADC_SAMPLEN); - Serial.println(")"); -} - void loop() { uint32_t timestamp=micros(); @@ -595,11 +604,7 @@ void loop() u8g2.setFont(u8g2_font_6x12_tf); //7us // Display oversample exponent in hex - char buf[3] = { - samplerate_id[ADC_SAMPLEN], - SRADJUST ? '?' : 0, - }; - u8g2.drawStr(0,12, buf); // ?? us + u8g2.drawStr(0,12, sampleRateStr(SRADJUST)); // ?? us if (AUTORANGE) { @@ -889,7 +894,7 @@ void printCalibInfo() { Serial.print("Offset="); Serial.println(offsetCorrectionValue); Serial.print("Gain="); Serial.println(gainCorrectionValue); Serial.print("LDO="); Serial.println(ldoValue,3); - Serial.print("Oversample="); Serial.println(1U << ADC_SAMPLEN); + Serial.print("SampleRate: "); sampleRateOutSerial(); Serial.print("uA+mA: "); Serial.println((PREFERENCES & PREFERENCE_MU_SAMPLERATE) ? "toggle samplerate adjust" From 6daf76c90eead0f0ff74c0277e02a9e23fd4be4f Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Wed, 29 Jul 2020 10:15:20 -0500 Subject: [PATCH 6/7] CurrentRanger_R3: add display of configured logging format The logging format is preserved in EEPROM, but never displayed, so you can see the selected value only by changing it. Add it to the set of preferences that are displayed in the config/calib block. Also start marking the key documentation for things that are "preferences" that are saved between restarts. Signed-off-by: Peter A. Bigot --- CurrentRanger_R3.ino | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/CurrentRanger_R3.ino b/CurrentRanger_R3.ino index c34e280..4a64821 100644 --- a/CurrentRanger_R3.ino +++ b/CurrentRanger_R3.ino @@ -115,6 +115,13 @@ Adafruit_FreeTouch qt[3] = { //*********************************************************************************************************** #define PREFERENCE_MU_SAMPLERATE 0x01 // default BIAS //*********************************************************************************************************** +static const char *const loggingFormat_str[] = { + [LOGGING_FORMAT_EXPONENT] = "exp (1.23E-3 = 123 mA)", + [LOGGING_FORMAT_NANOS] = "nA (1234 = 1.234 uA)", + [LOGGING_FORMAT_MICROS] = "uA (1234 = 1.234 mA)", + [LOGGING_FORMAT_MILLIS] = "mA (1234 = 1.234 A)", + [LOGGING_FORMAT_ADC] = "adc (0..4095)", +}; int offsetCorrectionValue = 0; uint16_t gainCorrectionValue = 0; float ldoValue = 0, ldoOptimized=0; @@ -477,11 +484,7 @@ void loop() case 'f': //cycle through output logging formats if (++LOGGING_FORMAT>LOGGING_FORMAT_ADC) LOGGING_FORMAT=LOGGING_FORMAT_EXPONENT; eeprom_LOGGINGFORMAT.write(LOGGING_FORMAT); - if (LOGGING_FORMAT==LOGGING_FORMAT_EXPONENT) Serial.println("LOGGING_FORMAT_EXPONENT"); else - if (LOGGING_FORMAT==LOGGING_FORMAT_NANOS) Serial.println("LOGGING_FORMAT_NANOS"); else - if (LOGGING_FORMAT==LOGGING_FORMAT_MICROS) Serial.println("LOGGING_FORMAT_MICROS"); else - if (LOGGING_FORMAT==LOGGING_FORMAT_MILLIS) Serial.println("LOGGING_FORMAT_MILLIS"); else - if (LOGGING_FORMAT==LOGGING_FORMAT_ADC) Serial.println("LOGGING_FORMAT_ADC"); + Serial.println(loggingFormat_str[LOGGING_FORMAT]); break; case 'a': //toggle autoOff function if (AUTOFF_INTERVAL == AUTOFF_DEFAULT) @@ -895,6 +898,7 @@ void printCalibInfo() { Serial.print("Gain="); Serial.println(gainCorrectionValue); Serial.print("LDO="); Serial.println(ldoValue,3); Serial.print("SampleRate: "); sampleRateOutSerial(); + Serial.print("LogFmt: "); Serial.println(loggingFormat_str[LOGGING_FORMAT]); Serial.print("uA+mA: "); Serial.println((PREFERENCES & PREFERENCE_MU_SAMPLERATE) ? "toggle samplerate adjust" @@ -904,9 +908,9 @@ void printSerialMenu() { Serial.println("\r\nUSB serial commands:"); Serial.println("a = toggle Auto-Off function"); Serial.print ("b = toggle BT/serial logging (");Serial.print(SERIAL_UART_BAUD);Serial.println("baud)"); - Serial.println("f = cycle serial logging formats (exponent,nA,uA,mA/raw-ADC)"); + Serial.println("f = cycle serial logging formats (exponent,nA,uA,mA/raw-ADC) [PREF]"); Serial.println("g = toggle GPIO range indication (SCK=mA,MISO=uA,MOSI=nA)"); - Serial.println("o = toggle touchpad offset (bias) / samplerate selection"); + Serial.println("o = toggle touchpad offset (bias) / samplerate selection [PREF]"); Serial.println("t = toggle touchpad serial output debug info"); Serial.println("u = toggle USB/serial logging"); Serial.println("+ = increase mode value"); From 6582dc4ff4e5e13210298ba57de9a136ed1285f5 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Wed, 29 Jul 2020 10:22:12 -0500 Subject: [PATCH 7/7] CurrentRanger_R3: add preference to timestamp samples For USB and BT serial data output add options to preface each sample with the system time at which it was taken, in microseconds. This mitigates the loss of information when the sample rate is changed dynamically. Be aware that the counter will wrap at 2^32 us, so relative calculations should be done using unsigned 32-bit operations. Signed-off-by: Peter A. Bigot --- CurrentRanger_R3.ino | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/CurrentRanger_R3.ino b/CurrentRanger_R3.ino index 4a64821..4c1cebd 100644 --- a/CurrentRanger_R3.ino +++ b/CurrentRanger_R3.ino @@ -114,6 +114,8 @@ Adafruit_FreeTouch qt[3] = { #define LOGGING_FORMAT_ADC 4 //raw output for each range (0..4095) //*********************************************************************************************************** #define PREFERENCE_MU_SAMPLERATE 0x01 // default BIAS +#define PREFERENCE_USB_TIMESTAMP 0x02 // timestamp serial samples +#define PREFERENCE_BT_TIMESTAMP 0x04 // timestamp bluetooth samples //*********************************************************************************************************** static const char *const loggingFormat_str[] = { [LOGGING_FORMAT_EXPONENT] = "exp (1.23E-3 = 123 mA)", @@ -298,6 +300,7 @@ uint32_t oledInterval=0, lpfInterval=0, modeInterval=0, autorangeInterval=0, btI byte LPF=0, BIAS=0, AUTORANGE=0, SRADJUST=0; byte readVbatLoop=0; float vbat=0, VOUT=0; +unsigned long readMicros; float read1=0,read2=0,readDiff=0; bool rangeSwitched=false; #define RANGE_MA rangeUnit=='m' @@ -464,6 +467,14 @@ void loop() USB_LOGGING_ENABLED =! USB_LOGGING_ENABLED; Serial.println(USB_LOGGING_ENABLED ? "USB_LOGGING_ENABLED" : "USB_LOGGING_DISABLED"); break; + case 'U': //toggle USB timestamping + PREFERENCES ^= PREFERENCE_USB_TIMESTAMP; + eeprom_PREFERENCES.write(PREFERENCES); + if (!(PREFERENCES & PREFERENCE_USB_TIMESTAMP)) { + Serial.print("NO "); + } + Serial.println("USB sample timestamps"); + break; case 't': //toggle touchpad serial output debug info TOUCH_DEBUG_ENABLED =! TOUCH_DEBUG_ENABLED; Serial.println(TOUCH_DEBUG_ENABLED ? "TOUCH_DEBUG_ENABLED" : "TOUCH_DEBUG_DISABLED"); @@ -481,6 +492,14 @@ void loop() BT_LOGGING_ENABLED =! BT_LOGGING_ENABLED; Serial.println(BT_LOGGING_ENABLED ? "BT_LOGGING_ENABLED" : "BT_LOGGING_DISABLED"); break; + case 'B': //toggle BT timestamping + PREFERENCES ^= PREFERENCE_BT_TIMESTAMP; + eeprom_PREFERENCES.write(PREFERENCES); + if (!(PREFERENCES & PREFERENCE_BT_TIMESTAMP)) { + Serial.print("NO "); + } + Serial.println("BT sample timestamps"); + break; case 'f': //cycle through output logging formats if (++LOGGING_FORMAT>LOGGING_FORMAT_ADC) LOGGING_FORMAT=LOGGING_FORMAT_EXPONENT; eeprom_LOGGINGFORMAT.write(LOGGING_FORMAT); @@ -535,6 +554,9 @@ void loop() if (!AUTORANGE) readVOUT(); VOUT = readDiff*ldoOptimized*(BIAS?1:OUTPUT_CALIB_FACTOR); VOUTCalculated=true; + if (PREFERENCES & PREFERENCE_USB_TIMESTAMP) { + Serial.print(readMicros); Serial.print(" "); + } if(LOGGING_FORMAT == LOGGING_FORMAT_EXPONENT) { Serial.print(VOUT); Serial.print("e"); Serial.println(RANGE_NA ? -9 : RANGE_UA ? -6 : -3); } else if(LOGGING_FORMAT == LOGGING_FORMAT_NANOS) Serial.println(VOUT * (RANGE_NA ? 1 : RANGE_UA ? 1000 : 1000000)); else if(LOGGING_FORMAT == LOGGING_FORMAT_MICROS) Serial.println(VOUT * (RANGE_NA ? 0.001 : RANGE_UA ? 1 : 1000)); else @@ -556,6 +578,9 @@ void loop() VOUT = readDiff*ldoOptimized*(BIAS?1:OUTPUT_CALIB_FACTOR); VOUTCalculated=true; } + if (PREFERENCES & PREFERENCE_BT_TIMESTAMP) { + SerialBT.print(readMicros); SerialBT.print(" "); + } if(LOGGING_FORMAT == LOGGING_FORMAT_EXPONENT) { SerialBT.print(VOUT); SerialBT.print("e"); SerialBT.println(RANGE_NA ? -9 : RANGE_UA ? -6 : -3); } else if(LOGGING_FORMAT == LOGGING_FORMAT_NANOS) SerialBT.println(VOUT * (RANGE_NA ? 1 : RANGE_UA ? 1000 : 1000000)); else if(LOGGING_FORMAT == LOGGING_FORMAT_MICROS) SerialBT.println(VOUT * (RANGE_NA ? 0.001 : RANGE_UA ? 1 : 1000)); else @@ -822,6 +847,7 @@ void setupADC() { int adcRead(byte ADCpin) { return (int)analogRead(ADCpin); } void readVOUT() { + readMicros = micros(); readDiff = adcRead(SENSE_OUTPUT) - adcRead(SENSE_GNDISO); if (!analog_ref_half && readDiff > RANGE_SWITCH_THRESHOLD_LOW && readDiff < RANGE_SWITCH_THRESHOLD_HIGH/3) @@ -903,16 +929,24 @@ void printCalibInfo() { Serial.println((PREFERENCES & PREFERENCE_MU_SAMPLERATE) ? "toggle samplerate adjust" : "toggle offset enable"); + Serial.print("USB timestamp: "); + Serial.println((PREFERENCES & PREFERENCE_USB_TIMESTAMP) + ? "on" : "off"); + Serial.print("BT timestamp: "); + Serial.println((PREFERENCES & PREFERENCE_BT_TIMESTAMP) + ? "on" : "off"); } void printSerialMenu() { Serial.println("\r\nUSB serial commands:"); Serial.println("a = toggle Auto-Off function"); Serial.print ("b = toggle BT/serial logging (");Serial.print(SERIAL_UART_BAUD);Serial.println("baud)"); + Serial.println("B = toggle timestamp on BT/serial output [PREF]"); Serial.println("f = cycle serial logging formats (exponent,nA,uA,mA/raw-ADC) [PREF]"); Serial.println("g = toggle GPIO range indication (SCK=mA,MISO=uA,MOSI=nA)"); Serial.println("o = toggle touchpad offset (bias) / samplerate selection [PREF]"); Serial.println("t = toggle touchpad serial output debug info"); Serial.println("u = toggle USB/serial logging"); + Serial.println("U = toggle timestamp in USB/serial output [PREF]"); Serial.println("+ = increase mode value"); Serial.println("- = decrease mode value"); Serial.println("? = Print this menu and calib info");