The Sensor

A notable characteristic of a silicon diode is its temperature sensitivity: its forward voltage decreases by roughly 2 mV for each degree Celsius rise, maintaining a fairly linear behavior between 0 and 100 °C. Because the base-emitter junction of a transistor behaves just like a diode, individual transistors can be conveniently used as simple and reliable temperature sensors.

Okay, let's write a Python script that reads our values from the ADC first. As our XAIO board has SAMD21G18 MCU, it has a nice 1.0V reference source inside, and we will use it, as it has  1% tolerance, and we may measure precisely. Added an 1-wire thermosensor to calibrate our own (made from transistor). Arduino code is below 

#include <arduino.h>

#define OW_PIN 2
#define D0_PIN 0
#define A1_PIN A1

#define SAMPLE_INTERVAL_MS 200
#define PRINT_INTERVAL_MS 10000  // 10 sec

// Bus control
void    ow_low()  { pinMode(OW_PIN, OUTPUT); digitalWrite(OW_PIN, LOW); }
void    ow_rel()  { pinMode(OW_PIN, INPUT); }
int     ow_rd()   { return digitalRead(OW_PIN); }

bool ow_reset() {
    ow_low(); delayMicroseconds(480);
    ow_rel(); delayMicroseconds(70);
    bool p = !ow_rd();
    delayMicroseconds(410);
    return p;
}

void ow_write_bit(uint8_t b) {
    ow_low(); delayMicroseconds(b ? 6 : 60);
    ow_rel(); delayMicroseconds(b ? 64 : 10);
}

uint8_t ow_read_bit() {
    ow_low(); delayMicroseconds(6);
    ow_rel(); delayMicroseconds(9);
    uint8_t b = ow_rd();
    delayMicroseconds(55);
    return b;
}

void    ow_write(uint8_t v)  { for(int i=0;i<8;i++) ow_write_bit((v>>i)&1); }

uint8_t ow_read_byte()       { uint8_t v=0; for(int i=0;i<8;i++) v|=ow_read_bit()<<i; return="" v;="" }="" uint8_t="" crc8(uint8_t="" *d,="" len)="" {="" crc="0;" for(uint8_t="" i="0;i<len;i++)" b="d[i];" j="0;j<8;j++)" m="(crc^b)&1;">>=1; if(m) crc^=0x8C; b>>=1; }
    }
    return crc;
}

// Accumulators
float voltageAccum = 0;
float tempAccum = 0;
int sampleCount = 0;
unsigned long startTime = 0;
unsigned long nextPrintTime = 0;

float readTemperature() {
    uint8_t rom[8], scratch[9];

    if(!ow_reset()) return NAN;

    ow_write(0x33);
    for(int i=0;i<8;i++) rom[i]=ow_read_byte();
    if(crc8(rom,8) != 0 || rom[0] != 0x28) return NAN;

    ow_reset();
    ow_write(0xCC); ow_write(0x44);
    pinMode(OW_PIN, OUTPUT); digitalWrite(OW_PIN, HIGH);
    delay(750);
    ow_rel();

    ow_reset();
    ow_write(0xCC); ow_write(0xBE);
    for(int i=0;i<9;i++) scratch[i]=ow_read_byte();
    if(crc8(scratch,9) != 0) return NAN;

    int16_t raw = (scratch[1]<<8)|scratch[0];
    return raw / 16.0f;
}

void printTime(unsigned long elapsedSec) {
    unsigned int minutes = elapsedSec / 60;
    unsigned int seconds = elapsedSec % 60;
    if (minutes < 10) Serial.print("0");
    Serial.print(minutes);
    Serial.print(":");
    if (seconds < 10) Serial.print("0");
    Serial.print(seconds);
}

void setup() {
    Serial.begin(115200);
    while(!Serial) delay(10);
    pinMode(OW_PIN, INPUT);

    pinMode(D0_PIN, OUTPUT);
    digitalWrite(D0_PIN, LOW);

    // XIAO SAMD21: MUST set 12-bit explicitly — default is 10-bit!
    analogReadResolution(12);
    analogReference(AR_INTERNAL1V0);  // 1.0V internal reference

    startTime = millis();
    nextPrintTime = startTime + PRINT_INTERVAL_MS;
    nextPrintTime = ((nextPrintTime + PRINT_INTERVAL_MS - 1) / PRINT_INTERVAL_MS) * PRINT_INTERVAL_MS;

    Serial.println("Time,Voltage[mV],Temperature[C]");
}

void loop() {
    unsigned long now = millis();

    // Sample every 200 ms
    static unsigned long lastSampleTime = 0;
    if (now - lastSampleTime >= SAMPLE_INTERVAL_MS) {
        lastSampleTime = now;

        // Read voltage: 1.0V ref, 12-bit ADC (0–4095)
        int a1_raw = analogRead(A1_PIN);
        float voltage = a1_raw * (1000.0 / 4095.0);
        voltageAccum += voltage;

        // Read temperature
        float temp = readTemperature();
        if (!isnan(temp)) {
            tempAccum += temp;
        }

        sampleCount++;
    }

    // Print every 10 seconds
    if (now >= nextPrintTime && sampleCount > 0) {

        float avgVoltage = voltageAccum / sampleCount;
        float avgTemp = tempAccum / sampleCount;
        unsigned long elapsedSec = (nextPrintTime - startTime)...
Read more »