/* ////////////////////////////////////////////////////////////////// ARDUINO/Genuino Project "BOOTS 5009", an Arduino Multimeter https://www.changpuak.ch/electronics/Arduino-Boots-5009.php Software Version 9.9 13.10.2022 by ALEXANDER SSE FRANK ////////////////////////////////////////////////////////////////// */ #include #include #include // CONNECTIONS OLED #define OLED_MOSI 11 #define OLED_CLK 13 #define OLED_CS A3 #define OLED_DC A2 #define OLED_RESET A1 #define BEEP A0 volatile int ModusOperandi = 0 ; double Messwert = 0.0 ; int OHM_RANGE = 0 ; int OHM_RANGE_OLD = 0 ; int AC_RANGE = 1 ; int AC_RANGE_OLD = 1 ; int DC_RANGE = 1 ; // ROTARY ENCODER const int ROTENC1 = 4 ; // PRESSED const int ROTENC2 = 2 ; const int ROTENC3 = 3 ; volatile bool PRESS = false ; volatile bool READY = true ; const int GatePin = 5 ; unsigned int GateTime = 500 ; // Milli Seconds int FreqMulValue = 0 ; unsigned long Counts = 0 ; bool online = true ; float sum = 0.0 ; int AVGMax = 32 ; double AVGValue[33] ; // ///////////////////////////////////////////////////////////////////// // SUBROUTINES DISPLAY. // ///////////////////////////////////////////////////////////////////// Adafruit_SH1106 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS); #if (SH1106_LCDHEIGHT != 64) #error("Height incorrect, please fix Adafruit_SH1106.h!"); #endif long day = 86400000; // 86400000 milliseconds in a day long hour = 3600000; // 3600000 milliseconds in an hour long minute = 60000; // 60000 milliseconds in a minute long second = 1000; // 1000 milliseconds in a second int sign = 1 ; // ADC LTC2400 int LTC2400_DAT = 9 ; int LTC2400_CLK = 8 ; int LTC2400_CS1 = 6 ; // USED FOR DC int LTC2400_CS2 = 7 ; // USED FOR AC float Temperature = 0.0 ; // https://ta-laboratories.com/blog/2018/09/07/recreating-a-7- // segment-display-with-adafruit-gfx-ssd1306-oled/ // DEFINE SEGMENT TRUTH TABLE FOR EACH DIGIT static const int digit_array[10][7] = { {1, 1, 1, 1, 1, 1, 0}, // 0 {0, 1, 1, 0, 0, 0, 0}, // 1 {1, 1, 0, 1, 1, 0, 1}, // 2 {1, 1, 1, 1, 0, 0, 1}, // 3 {0, 1, 1, 0, 0, 1, 1}, // 4 {1, 0, 1, 1, 0, 1, 1}, // 5 {1, 0, 1, 1, 1, 1, 1}, // 6 {1, 1, 1, 0, 0, 0, 0}, // 7 {1, 1, 1, 1, 1, 1, 1}, // 8 {1, 1, 1, 1, 0, 1, 1} // 9 } ; void render_digit(uint8_t pos_x, uint8_t pos_y, uint8_t digit) { unsigned int color = 1 ; // loop through 7 segments for (int i = 0; i < 7; i++) { bool seg_on = digit_array[digit][i]; // if seg_on is true draw segment if (seg_on) { switch (i) { case 0: display.fillRoundRect(2 + pos_x, 0 + pos_y, 9, 3, 2, color); // SEG A break; case 1: display.fillRoundRect(10 + pos_x, 2 + pos_y, 3, 9, 2, color); // SEG B break; case 2: display.fillRoundRect(10 + pos_x, 12 + pos_y, 3, 9, 2, color); // SEG C break; case 3: display.fillRoundRect(2 + pos_x, 20 + pos_y, 9, 3, 2, color); // SEG D break; case 4: display.fillRoundRect(0 + pos_x, 12 + pos_y, 3, 9, 2, color); // SEG E break; case 5: display.fillRoundRect(0 + pos_x, 2 + pos_y, 3, 9, 2, color); // SEG F break; case 6: display.fillRoundRect(2 + pos_x, 10 + pos_y, 9, 3, 2, color); // SEG G break; } seg_on = false; } } } void render_sign(int polarity) { if(polarity < 0) { display.fillRoundRect(1, 30, 4, 4, 2, WHITE); display.fillRoundRect(6, 30, 4, 4, 2, WHITE); display.fillRoundRect(11, 30, 4, 4, 2, WHITE); } if(polarity >= 0) { display.fillRoundRect(1, 30, 4, 4, 2, WHITE); display.fillRoundRect(6, 30, 4, 4, 2, WHITE); display.fillRoundRect(11, 30, 4, 4, 2, WHITE); display.fillRoundRect(6, 25, 4, 4, 2, WHITE); display.fillRoundRect(6, 35, 4, 4, 2, WHITE); } } void UpDateTemperature() { Wire.beginTransmission(0x4A); Wire.write(0x00); Wire.endTransmission(); Wire.requestFrom(0x4A,2); if (Wire.available()>0) { int a = Wire.read(); // integer value int b = Wire.read(); // fractional value int negative = a & 0x80; a = a & 0x7F ; int c = (( a << 8 ) | b ) >> 4 ; Temperature = 0.0 + c * 0.0625 ; if (negative >= 1) Temperature -= 128.0 ; } } void UpDateDisplay(float Wert) { String SignedMeasurement ; if(Wert >= 0.0) SignedMeasurement = "+" + String(Wert, 7) ; else SignedMeasurement = String(Wert, 8) ; display.clearDisplay(); display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(0,0); display.print("BOOTS ASM 5009"); display.setCursor(92,0); display.print(Temperature,1); display.print(" C") ; display.drawCircle(118, 1, 1, WHITE); display.drawLine(0, 12, 128, 12, WHITE); display.setTextSize(3); display.setCursor(0,21); int anfang = 1 ; // CHARACTER 0 = SIGN int xpos = 7 ; int xdelta = 20 ; if(ModusOperandi == 0) anfang = 0 ; // VOLTS DC if(ModusOperandi == 1) anfang = 0 ; // VOLTS DC S+H if(ModusOperandi == 5) anfang = 0 ; // DIODE VOLTS if(ModusOperandi == 6) anfang = 0 ; // TEMPERATURE LM35 for(int i=anfang ; i < (anfang+7); i++) { if(SignedMeasurement[i] == '+') { render_sign(10) ; xpos += xdelta ; } if(SignedMeasurement[i] == '-') { render_sign(-10) ; xpos += xdelta ; } if(SignedMeasurement[i] == '.') { display.fillCircle(xpos, 41, 2, WHITE) ; // COMMA ; xpos += 7 ; } if(SignedMeasurement[i] == '0') { render_digit(xpos, 21, 0) ; xpos += xdelta ; } if(SignedMeasurement[i] == '1') { render_digit(xpos, 21, 1) ; xpos += xdelta ; } if(SignedMeasurement[i] == '2') { render_digit(xpos, 21, 2) ; xpos += xdelta ; } if(SignedMeasurement[i] == '3') { render_digit(xpos, 21, 3) ; xpos += xdelta ; } if(SignedMeasurement[i] == '4') { render_digit(xpos, 21, 4) ; xpos += xdelta ; } if(SignedMeasurement[i] == '5') { render_digit(xpos, 21, 5) ; xpos += xdelta ; } if(SignedMeasurement[i] == '6') { render_digit(xpos, 21, 6) ; xpos += xdelta ; } if(SignedMeasurement[i] == '7') { render_digit(xpos, 21, 7) ; xpos += xdelta ; } if(SignedMeasurement[i] == '8') { render_digit(xpos, 21, 8) ; xpos += xdelta ; } if(SignedMeasurement[i] == '9') { render_digit(xpos, 21, 9) ; xpos += xdelta ; } } display.drawLine(0, 51, 128, 51, WHITE); display.setTextSize(1); display.setCursor(0,56); switch(ModusOperandi) { case 0 : display.print("VOLTS DC-") ; display.print(DC_RANGE,DEC) ; break ; case 1 : display.print("VOLTS S+H") ; break ; case 2 : display.print("VOLTS AC-") ; display.print(AC_RANGE,DEC) ; break ; case 3 : display.print("OHM-") ; display.print(OHM_RANGE,DEC) ; if(OHM_RANGE == 1) display.print(" ") ; if(OHM_RANGE == 2) display.print(" k") ; if(OHM_RANGE == 3) display.print(" k") ; if(OHM_RANGE == 4) display.print(" M") ; display.drawChar(42, 56, 0xE9, WHITE, BLACK, 1) ; break ; case 4 : display.print("FREQ") ; if(FreqMulValue == 0) display.print(" Hz") ; if(FreqMulValue == 3) display.print(" kHz") ; if(FreqMulValue == 6) display.print(" MHz") ; break ; case 5 : display.print("DIODE VOLT") ; break ; case 6 : display.print("TEMP LM35") ; break ; } // https://forum.arduino.cc/t/arduino-timer- // convert-millis-to-days-hours-min/42323 long timeNow = millis(); int days = timeNow / day ; // number of days int hours = (timeNow % day) / hour; // the remainder from days division (in milliseconds) divided by hours, this gives the full hours int minutes = ((timeNow % day) % hour) / minute ; int seconds = (((timeNow % day) % hour) % minute) / second; display.setCursor(62,56); if(days < 10) display.print(" ") ; display.print(days,DEC) ; display.print(":") ; if(hours < 10) display.print("0") ; display.print(hours,DEC) ; display.print(":") ; if(minutes < 10) display.print("0") ; display.print(minutes,DEC) ; display.print(":") ; if(seconds < 10) display.print("0") ; display.print(seconds,DEC) ; display.display() ; delay(49) ; } void OpenLoopDisplay() { display.clearDisplay(); display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(0,0); display.print("BOOTS ASM 5009"); display.setCursor(92,0); display.print(Temperature,1); display.print(" C") ; display.drawCircle(118, 1, 1, WHITE); display.drawLine(0, 12, 128, 12, WHITE); display.setTextSize(3); display.setCursor(0,21); unsigned int color = 1 ; int pos_x = 49 ; int pos_y = 21 ; // Open display.fillRoundRect(2 + pos_x, 0 + pos_y, 9, 3, 2, color); // SEG A display.fillRoundRect(10 + pos_x, 2 + pos_y, 3, 9, 2, color); // SEG B display.fillRoundRect(10 + pos_x, 12 + pos_y, 3, 9, 2, color); // SEG C display.fillRoundRect(2 + pos_x, 20 + pos_y, 9, 3, 2, color); // SEG D display.fillRoundRect(0 + pos_x, 12 + pos_y, 3, 9, 2, color); // SEG E display.fillRoundRect(0 + pos_x, 2 + pos_y, 3, 9, 2, color); // SEG F // Loop pos_x += 21 ; display.fillRoundRect(2 + pos_x, 20 + pos_y, 9, 3, 2, color); // SEG D display.fillRoundRect(0 + pos_x, 12 + pos_y, 3, 9, 2, color); // SEG E display.fillRoundRect(0 + pos_x, 2 + pos_y, 3, 9, 2, color); // SEG F display.drawLine(0, 51, 128, 51, WHITE) ; display.setTextSize(1); display.setCursor(0,56); switch(ModusOperandi) { case 0 : display.print("VOLTS DC-") ; display.print(DC_RANGE,DEC) ; break ; case 1 : display.print("VOLTS S+H") ; break ; case 2 : display.print("VOLTS AC-") ; display.print(AC_RANGE,DEC) ; break ; case 3 : display.print("OHM-") ; display.print(OHM_RANGE,DEC) ; if(OHM_RANGE == 1) display.print(" ") ; if(OHM_RANGE == 2) display.print(" k") ; if(OHM_RANGE == 3) display.print(" k") ; if(OHM_RANGE == 4) display.print(" M") ; display.drawChar(42, 56, 0xE9, WHITE, BLACK, 1) ; break ; case 4 : display.print("FREQ") ; if(FreqMulValue == 0) display.print(" Hz") ; if(FreqMulValue == 3) display.print(" kHz") ; if(FreqMulValue == 6) display.print(" MHz") ; break ; case 5 : display.print("DIODE VOLT") ; break ; case 6 : display.print("TEMP LM35") ; break ; } long timeNow = millis(); int days = timeNow / day ; // number of days int hours = (timeNow % day) / hour; // the remainder from days division (in milliseconds) divided by hours, this gives the full hours int minutes = ((timeNow % day) % hour) / minute ; int seconds = (((timeNow % day) % hour) % minute) / second; display.setCursor(62,56); if(days < 10) display.print(" ") ; display.print(days,DEC) ; display.print(":") ; if(hours < 10) display.print("0") ; display.print(hours,DEC) ; display.print(":") ; if(minutes < 10) display.print("0") ; display.print(minutes,DEC) ; display.print(":") ; if(seconds < 10) display.print("0") ; display.print(seconds,DEC) ; display.display() ; delay(49) ; } // ///////////////////////////////////////////////////////////////////// // SUBROUTINES SERIAL COM // ///////////////////////////////////////////////////////////////////// char tempbuf[80]; // keeps the command temporary until CRLF String buffer; void ScanI2C() { byte error, address ; for(address = 1; address < 127; address++ ) { Wire.beginTransmission(address); error = Wire.endTransmission(); Serial.print("0x") ; if(address < 0x10) Serial.print("0") ; Serial.print(address,HEX) ; Serial.print(" : ") ; if(error == 0) Serial.println("0x00 - I2C device found.") ; if(error == 1) Serial.println("0x01 - data too long.") ; if(error == 2) Serial.println("0x02 - NACK @ address.") ; if(error == 3) Serial.println("0x03 - NACK @ data.") ; if(error == 4) Serial.println("0x04 - unknown error.") ; if(error == 5) Serial.println("0x05 - timeout.") ; } } void MCP23008Write(byte adr, byte reg, byte dat) { Wire.beginTransmission(adr) ; Wire.write(reg) ; Wire.write(dat) ; Wire.endTransmission() ; } byte MCP23017Read(byte adr, byte reg) { byte aux = 0xAF ; Wire.beginTransmission(adr) ; Wire.write(reg) ; // GPIOB address = 0x13, GPIOA address = 0x12 Wire.endTransmission() ; Wire.requestFrom(adr, 1) ; if(Wire.available() > 0) aux = Wire.read() ; return aux ; } void HandleSerial() { while (Serial.available() > 0) { int tmp; char st[20]; char rx = Serial.read(); // read a single character buffer += rx; //add character to the string buffer if ((rx == '\n') || (rx == '\r')) { buffer.toCharArray(tempbuf, 40); if (buffer.startsWith("SET:MODE:0")) ModusOperandi = 0 ; else if (buffer.startsWith("SET:MODE:1")) ModusOperandi = 1 ; else if (buffer.startsWith("SET:MODE:2")) ModusOperandi = 2 ; else if (buffer.startsWith("SET:MODE:3")) ModusOperandi = 3 ; else if (buffer.startsWith("SET:MODE:4")) ModusOperandi = 4 ; else if (buffer.startsWith("SET:MODE:5")) ModusOperandi = 5 ; else if (buffer.startsWith("SET:MODE:6")) ModusOperandi = 6 ; else if (buffer.startsWith("*TEMP?")) { Serial.print("Temperature : ") ; UpDateTemperature() ; Serial.print(Temperature, 2) ; Serial.println(" °C") ; } else if (buffer.startsWith("*MODE?")) { Serial.print("Mode : ") ; Serial.println(ModusOperandi, DEC) ; } else if (buffer.startsWith("*VAL?")) { Serial.print("Value : ") ; Serial.println(Messwert, 4) ; } else if (buffer.startsWith("*IDN?")) { Serial.println("BOOTS 5009 BY CHANGPUAK.CH, 13.10.2022") ; Serial.print("Mode : ") ; Serial.println(ModusOperandi, DEC) ; } buffer = "" ; //erase buffer for next command } } } // ///////////////////////////////////////////////////////////////////// // V O L T S D C F U N C T I O N S // ///////////////////////////////////////////////////////////////////// const int DC_ADR = 0x21 ; int DC_RELAIS = 1 ; int TransferLED = 1 ; float DC_RAW = 0.0 ; float DC_TRG = 1.9 ; float DC_OLD = 0.0 ; float DC_HLD = 0.0 ; float DC_CAL = 0.0023 ; float DC_OFFSET = 0.0 ; void Zero_DC_Cal() { // DISCONNECT INPUT DC_RELAIS = 0 ; // ALL SWITCHES ON DC_RANGE = 5 ; UpDate_DC_Config() ; UpDate_DC_Raw() ; DC_CAL = DC_RAW ; DC_RELAIS = 1 ; DC_RANGE = 0 ; UpDate_DC_Config() ; } void UpDate_DC_Config() { // WE USE ADG413 HERE byte DAT = 0x00 ; if(TransferLED == 1) DAT |= 0x20 ; if(DC_RELAIS == 1) DAT |= 0x10 ; // MSB LSB // S1 = S2 = S3 = S4 // B0110 = ALL SWITCHES OFF if(DC_RANGE == 0) DAT |= B0110 ; // RANGE +/- 5 V if(DC_RANGE == 1) DAT |= B1110 ; // S1 if(DC_RANGE == 2) DAT |= B0010 ; // S2 if(DC_RANGE == 3) DAT |= B0100 ; // S3 if(DC_RANGE == 4) DAT |= B0111 ; // S4 if(DC_RANGE == 5) DAT |= B1001 ; // TEST ALL SWITCHES ON Wire.beginTransmission(DC_ADR) ; Wire.write(0x09) ; // GPIO Wire.write(DAT) ; Wire.endTransmission() ; } void UpDate_DC_Raw() { // Enable the SDO output and wake up the ADC digitalWrite(LTC2400_CS1, LOW) ; // WAIT FOR CONVERSION TO BE READY while(digitalRead(LTC2400_DAT) == 1) delay(1) ; unsigned long RAW_DAT = 0x00000000 ; RAW_DAT = shiftIn(LTC2400_DAT, LTC2400_CLK, MSBFIRST) ; RAW_DAT = RAW_DAT << 8 ; RAW_DAT |= shiftIn(LTC2400_DAT, LTC2400_CLK, MSBFIRST) ; RAW_DAT = RAW_DAT << 8 ; RAW_DAT |= shiftIn(LTC2400_DAT, LTC2400_CLK, MSBFIRST) ; RAW_DAT = RAW_DAT << 8 ; RAW_DAT |= shiftIn(LTC2400_DAT, LTC2400_CLK, MSBFIRST) ; RAW_DAT = (RAW_DAT & 0x0FFFFFFF) >> 3 ; DC_RAW = (5.0 * RAW_DAT / 16777216.0) - 5.0 - DC_CAL ; digitalWrite(LTC2400_CS1, HIGH) ; } double UpDate_AVG(double Wert) { double AVGSum = 0.0 ; for(int i = 1 ; i < AVGMax ; i++) { AVGValue[i] = AVGValue[i+1] ; AVGSum += AVGValue[i] ; } AVGValue[AVGMax] = Wert ; AVGSum += AVGValue[AVGMax] ; return (AVGSum / AVGMax) ; } void Init_AVG(double Wert) { for(int i = 0 ; i < AVGMax ; i++) { AVGValue[i] = Wert ; } } // ///////////////////////////////////////////////////////////////////// // V O L T S A C F U N C T I O N S // ///////////////////////////////////////////////////////////////////// const int AC_ADR = 0x22 ; // MCP23008 int AC_RELAIS = 0 ; float AC_RAW = 0.0 ; float AC_OFFSET = 0.005 ; void UpDate_AC_Config() { // WE USE ADG413 HERE byte DAT = 0x00 ; // MSB LSB // S3 = S2 = S1 = S4 = X = X = X = RELAIS // B1100xxxx = ALL SWITCHES OFF if(AC_RANGE == 0) DAT = B11010000 ; // S4 = SHORT - FOR TEST if(AC_RANGE == 1) DAT = B01000000 ; // S3 = 1:6.03571 if(AC_RANGE == 2) DAT = B10000000 ; // S2 = 1:51.3571 if(AC_RANGE == 3) DAT = B11100000 ; // S1 = 1:504.571 if(AC_RANGE == 9) DAT = B11000000 ; // ALL OFF - TEST AD736 if(AC_RELAIS == 1) DAT |= 0x01 ; Wire.beginTransmission(AC_ADR) ; Wire.write(0x09) ; // GPIO Wire.write(DAT) ; Wire.endTransmission() ; } void UpDate_AC_Raw() { // Enable the SDO output and wake up the ADC digitalWrite(LTC2400_CS2, LOW) ; // WAIT FOR CONVERSION TO BE READY while(digitalRead(LTC2400_DAT) == 1) delay(1) ; unsigned long RAW_DAT = 0x00000000 ; RAW_DAT = shiftIn(LTC2400_DAT, LTC2400_CLK, MSBFIRST) ; RAW_DAT = RAW_DAT << 8 ; RAW_DAT |= shiftIn(LTC2400_DAT, LTC2400_CLK, MSBFIRST) ; RAW_DAT = RAW_DAT << 8 ; RAW_DAT |= shiftIn(LTC2400_DAT, LTC2400_CLK, MSBFIRST) ; RAW_DAT = RAW_DAT << 8 ; RAW_DAT |= shiftIn(LTC2400_DAT, LTC2400_CLK, MSBFIRST) ; RAW_DAT = (RAW_DAT & 0x0FFFFFFF) >> 4 ; AC_RAW = 2.5 * RAW_DAT / 16777216.0 - AC_OFFSET ; digitalWrite(LTC2400_CS2, HIGH) ; } // ///////////////////////////////////////////////////////////////////// // O H M F U N C T I O N S // ///////////////////////////////////////////////////////////////////// const int OHM_ADR = 0x20 ; int OHM_RELAIS = 0 ; int OHM_LED = 0 ; void UpDate_OHM_Config() { byte DAT = 0x00 ; if(OHM_LED == 1) DAT |= B00000001 ; if(OHM_RELAIS == 1) DAT |= B10000000 ; if(OHM_RANGE == 1) DAT |= B00001110 ; if(OHM_RANGE == 2) DAT |= B00010110 ; if(OHM_RANGE == 3) DAT |= B00011010 ; if(OHM_RANGE == 4) DAT |= B00011100 ; Wire.beginTransmission(OHM_ADR) ; Wire.write(0x09) ; // GPIO Wire.write(DAT) ; Wire.endTransmission() ; } // ///////////////////////////////////////////////////////////////////// // F R E Q U E N C Y F U N C T I O N S // ///////////////////////////////////////////////////////////////////// const int FREQ_ADR = 0x23 ; int FREQ_RELAIS = 0 ; int FREQ_NIBBLE = 0 ; int FREQ_RCLK = 0 ; int FREQ_CCLR = 0 ; void UpDate_FREQ_Config() { byte DAT = 0xF0 ; if(FREQ_NIBBLE == 2) DAT = 0xB0 ; // GAU = GPB6 - LSB if(FREQ_NIBBLE == 1) DAT = 0x70 ; // GAL = GPB7 - ACTIVE LOW ! if(FREQ_NIBBLE == 4) DAT = 0xE0 ; // GBU = GPB4 - MSB if(FREQ_NIBBLE == 3) DAT = 0xD0 ; // GBL = GPB5 - ACTIVE LOW ! if(FREQ_RCLK == 1) DAT |= 0x08 ; // GPB3 if(FREQ_CCLR == 1) DAT |= 0x04 ; // GPB2 if(FREQ_RELAIS == 1) DAT |= 0x02 ; // GPB1 MCP23008Write(FREQ_ADR, 0x13, DAT); // WRITE TO PORT B } unsigned long ReadCounts() { unsigned long counts = 0 ; // TAKEOVER BUFFER FREQ_RCLK = 0 ; UpDate_FREQ_Config() ; FREQ_RCLK = 1 ; UpDate_FREQ_Config() ; // READ CONTENTS FREQ_NIBBLE = 4 ; UpDate_FREQ_Config() ; counts = MCP23017Read(FREQ_ADR, 0x12) ; // PORT A counts = counts << 8 ; FREQ_NIBBLE = 3 ; UpDate_FREQ_Config() ; counts |= MCP23017Read(FREQ_ADR, 0x12) ; // PORT A counts = counts << 8 ; FREQ_NIBBLE = 2 ; UpDate_FREQ_Config() ; counts |= MCP23017Read(FREQ_ADR, 0x12) ; // PORT A counts = counts << 8 ; FREQ_NIBBLE = 1 ; UpDate_FREQ_Config() ; counts |= MCP23017Read(FREQ_ADR, 0x12) ; // PORT A // CLEAR COUNTER FREQ_CCLR = 0 ; FREQ_NIBBLE = 0 ; UpDate_FREQ_Config() ; FREQ_CCLR = 1 ; FREQ_NIBBLE = 0 ; UpDate_FREQ_Config() ; // HANDOVER RESULT return counts ; } // ///////////////////////////////////////////////////////////////////// // S E T U P // ///////////////////////////////////////////////////////////////////// void setup() { Serial.begin(115200) ; Wire.begin() ; pinMode(OLED_DC, OUTPUT) ; pinMode(OLED_CS, OUTPUT) ; pinMode(OLED_RESET, OUTPUT) ; pinMode(BEEP, OUTPUT) ; // digitalWrite(BEEP, HIGH) ; delay(1000) ; digitalWrite(BEEP, LOW) ; // INIT OLED display.begin(SH1106_SWITCHCAPVCC); // SHOW STARTUP SCREEN display.clearDisplay(); display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(4,0); display.print("* BOOTS ASM 5009 *"); display.drawLine(0, 12, 128, 12, WHITE); display.setTextSize(1); display.setCursor(0,21); display.println("MULTIMETER FOR LAB"); display.setCursor(0,33); display.println("USE. UNKAPUTTBAR."); display.setCursor(0,45); display.println("(C) ETH QUANTUMOPTICS"); display.setCursor(0,57); display.println("BUILT 26.03.2022"); display.display(); delay(9) ; pinMode(ROTENC1, INPUT_PULLUP) ; pinMode(ROTENC2, INPUT_PULLUP) ; pinMode(ROTENC3, INPUT_PULLUP) ; pinMode(GatePin, OUTPUT) ; attachInterrupt(ROTENC1, ISR1, LOW) ; // 4 x FALLING CRASHES attachInterrupt(ROTENC2, ISR2, FALLING) ; attachInterrupt(ROTENC3, ISR3, FALLING) ; // INIT OHM MODULE MCP23008Write(OHM_ADR, 0x00, 0x00) ; // ALL PINS OUTPUT OHM_LED = 0 ; OHM_RELAIS = 0 ; OHM_RANGE = 0 ; UpDate_OHM_Config() ; // DC BOARD MCP23008Write(DC_ADR, 0x00, 0x00) ; // ALL PINS OUTPUT TransferLED = 0 ; DC_RELAIS = 0 ; UpDate_DC_Config() ; // AC BOARD MCP23008Write(AC_ADR, 0x00, 0x00) ; // ALL PINS OUTPUT AC_RELAIS = 0 ; UpDate_AC_Config() ; delay(999) ; // Zero_DC_Cal() ; // LTC2400 pinMode(LTC2400_DAT, INPUT_PULLUP) ; pinMode(LTC2400_CLK, OUTPUT) ; pinMode(LTC2400_CS1, OUTPUT) ; pinMode(LTC2400_CS2, OUTPUT) ; digitalWrite(LTC2400_CS1, HIGH) ; // DISABLE ADC digitalWrite(LTC2400_CS2, HIGH) ; // DISABLE ADC // TMP-101 on FREQ-MODULE Wire.beginTransmission(0x4A); Wire.write(0x01); // Configuration Register Wire.write(0x60); // R0 and R1 = 1 Wire.endTransmission(); // COUNTER MC23017 0x23 // OUTPUT : GAL = GPB7, GAU = GPB6, GBL = GPB5, GBU = GPB4 // RCLK = GPB3, CCLR = GPB2, RELAIS = GPB1, NC = GPB0 MCP23008Write(FREQ_ADR, 0x01, 0x00) ; // IODIRB PINS OUTPUT // INPUT : Y7 = GPA7 .... Y0 = GPA0 MCP23008Write(FREQ_ADR, 0x00, 0xFF) ; // IODIRA PINS INPUT Serial.println("BOOTS 5009 BY CHANGPUAK.CH - 13.10.2022") ; Serial.println("---------------------------------------") ; ScanI2C() ; Serial.println("---------------------------------------") ; } void loop() { switch(ModusOperandi) { // /////////////////////////////////// // VOLTS DC // /////////////////////////////////// case 0: OHM_LED = 0 ; OHM_RELAIS = 0 ; UpDate_OHM_Config() ; AC_RELAIS = 0 ; UpDate_AC_Config() ; FREQ_RELAIS = 0 ; UpDate_FREQ_Config() ; TransferLED = 1 ; DC_RELAIS = 1 ; UpDate_DC_Config() ; digitalWrite(BEEP, LOW) ; DC_RANGE = 1 ; while(ModusOperandi == 0) { UpDateTemperature() ; UpDate_DC_Raw() ; if(DC_RANGE == 1) Messwert = UpDate_AVG(DC_RAW * 3.2) ; if(DC_RANGE == 2) Messwert = UpDate_AVG(DC_RAW * 13.3) ; if(DC_RANGE == 3) Messwert = UpDate_AVG(DC_RAW * 51.0) ; if(DC_RANGE == 4) Messwert = UpDate_AVG(DC_RAW * 210.0) ; UpDateDisplay(Messwert) ; READY = true ; if(Serial.available() > 0) HandleSerial() ; delay(99) ; } break ; // /////////////////////////////////// // VOLTS DC SAMPLE AND HOLD // /////////////////////////////////// case 1: OHM_LED = 0 ; OHM_RELAIS = 0 ; UpDate_OHM_Config() ; AC_RELAIS = 0 ; UpDate_AC_Config() ; FREQ_RELAIS = 0 ; UpDate_FREQ_Config() ; TransferLED = 0 ; DC_RELAIS = 1 ; UpDate_DC_Config() ; digitalWrite(BEEP, LOW) ; UpDateDisplay(0.00) ; // TO DISPLAY THE S+H SYMBOL DC_HLD = 0.0 ; DC_OLD = 0.0 ; while(ModusOperandi == 1) { UpDateTemperature() ; DC_OLD = DC_RAW ; UpDate_DC_Raw() ; // VALUE IS GREATER -> UPDATE ////////////////// if(DC_RAW > DC_TRG) { TransferLED = 1 ; UpDate_DC_Config() ; UpDateDisplay(DC_RAW) ; DC_HLD = DC_RAW ; // STORE VALUE } // VALUE IS LOWER -> WAIT ////////////////////// if(DC_RAW < DC_TRG) { UpDateDisplay(DC_HLD) ; // UPDATE THE CLOCK } // VALUE IS FALLING -> STORE /////////////////// if((DC_RAW < DC_TRG) && (DC_OLD > DC_TRG)) { digitalWrite(BEEP, HIGH) ; UpDateDisplay(DC_OLD) ; // LENGTH OF BEEP !! digitalWrite(BEEP, LOW) ; TransferLED = 0 ; UpDate_DC_Config() ; } READY = true ; Messwert = DC_OLD ; if(Serial.available() > 0) HandleSerial() ; delay(99) ; } break ; // /////////////////////////////////// // VOLTS AC // /////////////////////////////////// case 2: TransferLED = 1 ; DC_RELAIS = 0 ; UpDate_DC_Config() ; OHM_LED = 0 ; OHM_RELAIS = 0 ; UpDate_OHM_Config() ; FREQ_RELAIS = 0 ; UpDate_FREQ_Config() ; AC_RELAIS = 1 ; AC_RANGE = 3 ; UpDate_AC_Config() ; digitalWrite(BEEP, LOW) ; AC_RANGE = 1 ; while(ModusOperandi == 2) { UpDate_AC_Raw() ; if(AC_RANGE == 0) Messwert = UpDate_AVG(AC_RAW) ; // SHORT - FOR TEST if(AC_RANGE == 1) Messwert = UpDate_AVG(AC_RAW * 6.14683) ; // CALIB if(AC_RANGE == 2) Messwert = UpDate_AVG(AC_RAW * 52.6500) ; // CALIB if(AC_RANGE == 3) Messwert = UpDate_AVG(AC_RAW * 506.799) ; // CALIB if(AC_RANGE == 9) Messwert = UpDate_AVG(AC_RAW) ; // FOR TEST ONLY UpDateTemperature() ; UpDateDisplay(Messwert) ; READY = true ; if(Serial.available() > 0) HandleSerial() ; // AUTORANGE AC_RANGE_OLD = AC_RANGE ; if(AC_RAW > 1.51) AC_RANGE += 1 ; if(AC_RANGE >= 3) AC_RANGE = 3 ; if(AC_RAW < 0.13) AC_RANGE -= 1 ; if(AC_RANGE <= 1) AC_RANGE = 1 ; if(AC_RANGE != AC_RANGE_OLD) UpDate_AC_Config() ; delay(99) ; // OTHERWISE DISPLAY TO NERVOUS } break ; // /////////////////////////////////// // RESISTANCE // /////////////////////////////////// case 3: AC_RELAIS = 0 ; UpDate_AC_Config() ; FREQ_RELAIS = 0 ; UpDate_FREQ_Config() ; DC_RANGE = 1 ; TransferLED = 1 ; DC_RELAIS = 1 ; UpDate_DC_Config() ; OHM_LED = 1 ; OHM_RELAIS = 1 ; UpDate_OHM_Config() ; digitalWrite(BEEP, LOW) ; OHM_RANGE = 1 ; UpDate_OHM_Config() ; AVGMax = 8 ; while(ModusOperandi == 3) { //////////////////////////////////// if(OHM_RANGE == 1) //////////////////////////////////// { UpDate_DC_Raw() ; Messwert = UpDate_AVG(832.75 * DC_RAW - 6.2681) ; // Ohm UpDateDisplay(Messwert) ; // SWITCH UP //////////////////////////////////// if(DC_RAW > 2.39) { OHM_RANGE = 2 ; UpDate_OHM_Config() ; DC_RANGE = 1 ; UpDate_DC_Config() ; } } //////////////////////////////////// if(OHM_RANGE == 2) //////////////////////////////////// { UpDate_DC_Raw() ; Messwert = UpDate_AVG((9211.2 * DC_RAW - 71.136) * 0.001) ; // kOhm UpDateDisplay(Messwert) ; // SWITCH UP //////////////////////////////////// if(DC_RAW > 2.17) { OHM_RANGE = 3 ; UpDate_OHM_Config() ; DC_RANGE = 0 ; UpDate_DC_Config() ; } // SWITCH DOWN ////////////////////////////////// if(DC_RAW < 0.11) { OHM_RANGE = 1 ; UpDate_OHM_Config() ; DC_RANGE = 1 ; UpDate_DC_Config() ; } } //////////////////////////////////// if(OHM_RANGE == 3) //////////////////////////////////// { UpDate_DC_Raw() ; Messwert = UpDate_AVG((4E6*pow(DC_RAW,3)+67838*pow(DC_RAW,2)+(211879*DC_RAW)-1317.6)*0.001) ; UpDateDisplay(Messwert) ; // SWITCH UP //////////////////////////////////// if(DC_RAW > 15.0) { OHM_RANGE = 4 ; UpDate_OHM_Config() ; DC_RANGE = 0 ; UpDate_DC_Config() ; } // SWITCH DOWN ////////////////////////////////// if(DC_RAW < 0.011) { OHM_RANGE = 2 ; UpDate_OHM_Config() ; DC_RANGE = 1 ; UpDate_DC_Config() ; } } //////////////////////////////////// if(OHM_RANGE == 4) //////////////////////////////////// { // NOT USED UpDate_DC_Raw() ; Messwert = UpDate_AVG(DC_RAW) ; // NOT USED } UpDateTemperature() ; READY = true ; if(Serial.available() > 0) HandleSerial() ; delay(19) ; // OTHERWISE DISPLAY TO NERVOUS } break ; // /////////////////////////////////// // FREQUENCY // /////////////////////////////////// case 4: OHM_LED = 0 ; OHM_RELAIS = 0 ; UpDate_OHM_Config() ; AC_RELAIS = 0 ; UpDate_AC_Config() ; DC_RELAIS = 0 ; UpDate_DC_Config() ; FREQ_RELAIS = 1 ; UpDate_FREQ_Config() ; GateTime = 1000 ; digitalWrite(BEEP, LOW) ; while(ModusOperandi == 4) { UpDateTemperature() ; TransferLED = 1 ; DC_RELAIS = 0 ; UpDate_DC_Config() ; digitalWrite(GatePin, HIGH) ; delay(GateTime) ; digitalWrite(GatePin, LOW) ; TransferLED = 0 ; DC_RELAIS = 0 ; UpDate_DC_Config() ; Counts = ReadCounts() ; Messwert = Counts / 1000.0 ; FreqMulValue = 3 ; if (Counts > 1E6) { Messwert = Counts / 1E6 ; FreqMulValue = 6 ; } UpDateDisplay(Messwert) ; READY = true ; if(FreqMulValue == 6) Messwert = Messwert * 1E6 ; if(FreqMulValue == 3) Messwert = Messwert * 1E3 ; if(Serial.available() > 0) HandleSerial() ; } break ; // /////////////////////////////////// // DIODE // /////////////////////////////////// case 5: AC_RELAIS = 0 ; UpDate_AC_Config() ; FREQ_RELAIS = 0 ; UpDate_FREQ_Config() ; DC_RANGE = 1 ; TransferLED = 1 ; DC_RELAIS = 1 ; UpDate_DC_Config() ; OHM_RANGE = 1 ; OHM_LED = 1 ; OHM_RELAIS = 1 ; UpDate_OHM_Config() ; while(ModusOperandi == 5) { UpDateTemperature() ; UpDate_DC_Raw() ; Messwert = DC_RAW * 3.2 ; if(Messwert > 11.5) OpenLoopDisplay() ; else UpDateDisplay(Messwert) ; digitalWrite(BEEP, LOW) ; if(Messwert < 0.15) digitalWrite(BEEP, HIGH) ; READY = true ; if(Serial.available() > 0) HandleSerial() ; delay(99) ; } digitalWrite(BEEP, LOW) ; break ; // /////////////////////////////////// // TEMPERATURE LM35 // /////////////////////////////////// case 6: OHM_LED = 0 ; OHM_RELAIS = 0 ; UpDate_OHM_Config() ; AC_RELAIS = 0 ; UpDate_AC_Config() ; DC_RANGE = 1 ; FREQ_RELAIS = 0 ; UpDate_FREQ_Config() ; TransferLED = 1 ; DC_RELAIS = 1 ; UpDate_DC_Config() ; digitalWrite(BEEP, LOW) ; delay(99) ; AVGMax = 32 ; UpDate_DC_Raw() ; Init_AVG(DC_RAW * 320.0) ; while(ModusOperandi == 6) { UpDateTemperature() ; UpDate_DC_Raw() ; Messwert = UpDate_AVG(DC_RAW * 320.0) ; if(Messwert < 0.1) OpenLoopDisplay() ; else UpDateDisplay(Messwert) ; if(Serial.available() > 0) HandleSerial() ; delay(299) ; } break ; // /////////////////////////////////// } delay(9) ; PRESS = false ; } // ///////////////////////////////////////////////////////////// // INTERRUPT SERVICE ROUTINES // ///////////////////////////////////////////////////////////// void ISR1() { PRESS = true ; } void ISR2() { if(READY) { byte autre = digitalRead(ROTENC3) ; if (autre > 0) ModusOperandi += 1 ; if (autre < 1) ModusOperandi -= 1 ; if(ModusOperandi > 6) ModusOperandi = 0 ; if(ModusOperandi < 0) ModusOperandi = 6 ; READY = false ; } } void ISR3() { if(READY) { byte autre = digitalRead(ROTENC2) ; if (autre > 0) ModusOperandi -= 1 ; if (autre < 1) ModusOperandi += 1 ; if(ModusOperandi > 6) ModusOperandi = 0 ; if(ModusOperandi < 0) ModusOperandi = 6 ; READY = false ; } } // ///////////////////////////////////////////////////////////// // END OF FILE. // /////////////////////////////////////////////////////////////