Remarks

Sgp40
Status Status badge: working
Source code GitHub
Datasheet(s) GitHub
NuGet package NuGet Gallery for Meadow.Foundation.Sensors.Atmospheric.Sgp40

Code Example

Sgp40? sensor;

public override Task Initialize()
{
    Resolver.Log.Info("Initializing...");

    sensor = new Sgp40(Device.CreateI2cBus());

    Resolver.Log.Info($"Sensor SN: {sensor.SerialNumber:x6}");

    if (sensor.RunSelfTest())
    {
        Resolver.Log.Info("Self test successful");
    }
    else
    {
        Resolver.Log.Warn("Self test failed");
    }

    var consumer = Sgp40.CreateObserver(
        handler: result =>
        {
            Resolver.Log.Info($"Observer: VOC changed by threshold; new index: {result.New}");
        },
        filter: result =>
        {
            return Math.Abs(result.New - result.Old ?? 0) > 10;
        }
    );
    sensor.Subscribe(consumer);

    sensor.Updated += (sender, result) =>
    {
        Resolver.Log.Info($"  VOC: {result.New}");
    };

    return base.Initialize();
}

public override async Task Run()
{
    await ReadConditions();

    sensor?.StartUpdating(TimeSpan.FromSeconds(1));
}

async Task ReadConditions()
{
    if (sensor == null) { return; }

    var result = await sensor.Read();
    Resolver.Log.Info("Initial Readings:");
    Resolver.Log.Info($"  Temperature: {result}");
}

Sample project(s) available on GitHub

Wiring Example

To wire a Sgp40 to your Meadow board, connect the following:

Sgp40 Meadow Pin
GND GND
SCL D08 (SCL)
SDA D07 (SDA)
VCC 3V3
Characteristic Locus
Inheritance object ObservableBase<int> SamplingSensorBase<int> PollingSensorBase<int> ByteCommsSensorBase<int> > Sgp40
Implements IObservable<IChangeResult<int>> ISamplingSensor<int> ISensor<int> IDisposable II2cPeripheral
Inherited Members ByteCommsSensorBase<int>.Init(int, int) ByteCommsSensorBase<int>.Dispose(bool) ByteCommsSensorBase<int>.Dispose() ByteCommsSensorBase<int>.BusComms ByteCommsSensorBase<int>.ReadBuffer ByteCommsSensorBase<int>.WriteBuffer PollingSensorBase<int>.StartUpdating(TimeSpan?) PollingSensorBase<int>.StopUpdating() SamplingSensorBase<int>.samplingLock SamplingSensorBase<int>.Read() SamplingSensorBase<int>.SamplingTokenSource SamplingSensorBase<int>.Conditions SamplingSensorBase<int>.IsSampling SamplingSensorBase<int>.UpdateInterval SamplingSensorBase<int>.Updated ObservableBase<int>.NotifyObservers(IChangeResult<int>) ObservableBase<int>.Subscribe(IObserver<IChangeResult<int>>) ObservableBase<int>.CreateObserver(Action<IChangeResult<int>>, Predicate<IChangeResult<int>>) ObservableBase<int>.observers object.Equals(object) object.Equals(object, object) object.GetHashCode() object.GetType() object.MemberwiseClone() object.ReferenceEquals(object, object) object.ToString()
Namespace Meadow.Foundation.Sensors.Atmospheric
Assembly Sgp40.dll

Syntax

public class Sgp40 : ByteCommsSensorBase<int>, IObservable<IChangeResult<int>>, ISamplingSensor<int>, ISensor<int>, IDisposable, II2cPeripheral

Constructors

Sgp40(II2cBus, byte)

Creates a new SGP40 VOC sensor.

Declaration
public Sgp40(II2cBus i2cBus, byte address = 89)

Parameters

Type Name Description
II2cBus i2cBus

I2CBus.

byte address

Sensor address (default to 0x40).

Remarks

Sgp40
Status Status badge: working
Source code GitHub
Datasheet(s) GitHub
NuGet package NuGet Gallery for Meadow.Foundation.Sensors.Atmospheric.Sgp40

Code Example

Sgp40? sensor;

public override Task Initialize()
{
    Resolver.Log.Info("Initializing...");

    sensor = new Sgp40(Device.CreateI2cBus());

    Resolver.Log.Info($"Sensor SN: {sensor.SerialNumber:x6}");

    if (sensor.RunSelfTest())
    {
        Resolver.Log.Info("Self test successful");
    }
    else
    {
        Resolver.Log.Warn("Self test failed");
    }

    var consumer = Sgp40.CreateObserver(
        handler: result =>
        {
            Resolver.Log.Info($"Observer: VOC changed by threshold; new index: {result.New}");
        },
        filter: result =>
        {
            return Math.Abs(result.New - result.Old ?? 0) > 10;
        }
    );
    sensor.Subscribe(consumer);

    sensor.Updated += (sender, result) =>
    {
        Resolver.Log.Info($"  VOC: {result.New}");
    };

    return base.Initialize();
}

public override async Task Run()
{
    await ReadConditions();

    sensor?.StartUpdating(TimeSpan.FromSeconds(1));
}

async Task ReadConditions()
{
    if (sensor == null) { return; }

    var result = await sensor.Read();
    Resolver.Log.Info("Initial Readings:");
    Resolver.Log.Info($"  Temperature: {result}");
}

Sample project(s) available on GitHub

Wiring Example

To wire a Sgp40 to your Meadow board, connect the following:

Sgp40 Meadow Pin
GND GND
SCL D08 (SCL)
SDA D07 (SDA)
VCC 3V3

Properties

DefaultI2cAddress

The default I2C address for the peripheral

Declaration
public byte DefaultI2cAddress { get; }

Property Value

Type Description
byte

Remarks

Sgp40
Status Status badge: working
Source code GitHub
Datasheet(s) GitHub
NuGet package NuGet Gallery for Meadow.Foundation.Sensors.Atmospheric.Sgp40

Code Example

Sgp40? sensor;

public override Task Initialize()
{
    Resolver.Log.Info("Initializing...");

    sensor = new Sgp40(Device.CreateI2cBus());

    Resolver.Log.Info($"Sensor SN: {sensor.SerialNumber:x6}");

    if (sensor.RunSelfTest())
    {
        Resolver.Log.Info("Self test successful");
    }
    else
    {
        Resolver.Log.Warn("Self test failed");
    }

    var consumer = Sgp40.CreateObserver(
        handler: result =>
        {
            Resolver.Log.Info($"Observer: VOC changed by threshold; new index: {result.New}");
        },
        filter: result =>
        {
            return Math.Abs(result.New - result.Old ?? 0) > 10;
        }
    );
    sensor.Subscribe(consumer);

    sensor.Updated += (sender, result) =>
    {
        Resolver.Log.Info($"  VOC: {result.New}");
    };

    return base.Initialize();
}

public override async Task Run()
{
    await ReadConditions();

    sensor?.StartUpdating(TimeSpan.FromSeconds(1));
}

async Task ReadConditions()
{
    if (sensor == null) { return; }

    var result = await sensor.Read();
    Resolver.Log.Info("Initial Readings:");
    Resolver.Log.Info($"  Temperature: {result}");
}

Sample project(s) available on GitHub

Wiring Example

To wire a Sgp40 to your Meadow board, connect the following:

Sgp40 Meadow Pin
GND GND
SCL D08 (SCL)
SDA D07 (SDA)
VCC 3V3

SerialNumber

Serial number of the device

Declaration
public ulong SerialNumber { get; }

Property Value

Type Description
ulong

Remarks

Sgp40
Status Status badge: working
Source code GitHub
Datasheet(s) GitHub
NuGet package NuGet Gallery for Meadow.Foundation.Sensors.Atmospheric.Sgp40

Code Example

Sgp40? sensor;

public override Task Initialize()
{
    Resolver.Log.Info("Initializing...");

    sensor = new Sgp40(Device.CreateI2cBus());

    Resolver.Log.Info($"Sensor SN: {sensor.SerialNumber:x6}");

    if (sensor.RunSelfTest())
    {
        Resolver.Log.Info("Self test successful");
    }
    else
    {
        Resolver.Log.Warn("Self test failed");
    }

    var consumer = Sgp40.CreateObserver(
        handler: result =>
        {
            Resolver.Log.Info($"Observer: VOC changed by threshold; new index: {result.New}");
        },
        filter: result =>
        {
            return Math.Abs(result.New - result.Old ?? 0) > 10;
        }
    );
    sensor.Subscribe(consumer);

    sensor.Updated += (sender, result) =>
    {
        Resolver.Log.Info($"  VOC: {result.New}");
    };

    return base.Initialize();
}

public override async Task Run()
{
    await ReadConditions();

    sensor?.StartUpdating(TimeSpan.FromSeconds(1));
}

async Task ReadConditions()
{
    if (sensor == null) { return; }

    var result = await sensor.Read();
    Resolver.Log.Info("Initial Readings:");
    Resolver.Log.Info($"  Temperature: {result}");
}

Sample project(s) available on GitHub

Wiring Example

To wire a Sgp40 to your Meadow board, connect the following:

Sgp40 Meadow Pin
GND GND
SCL D08 (SCL)
SDA D07 (SDA)
VCC 3V3

VocIndex

The VOC Index, from the last reading

Declaration
public int VocIndex { get; }

Property Value

Type Description
int

Remarks

Sgp40
Status Status badge: working
Source code GitHub
Datasheet(s) GitHub
NuGet package NuGet Gallery for Meadow.Foundation.Sensors.Atmospheric.Sgp40

Code Example

Sgp40? sensor;

public override Task Initialize()
{
    Resolver.Log.Info("Initializing...");

    sensor = new Sgp40(Device.CreateI2cBus());

    Resolver.Log.Info($"Sensor SN: {sensor.SerialNumber:x6}");

    if (sensor.RunSelfTest())
    {
        Resolver.Log.Info("Self test successful");
    }
    else
    {
        Resolver.Log.Warn("Self test failed");
    }

    var consumer = Sgp40.CreateObserver(
        handler: result =>
        {
            Resolver.Log.Info($"Observer: VOC changed by threshold; new index: {result.New}");
        },
        filter: result =>
        {
            return Math.Abs(result.New - result.Old ?? 0) > 10;
        }
    );
    sensor.Subscribe(consumer);

    sensor.Updated += (sender, result) =>
    {
        Resolver.Log.Info($"  VOC: {result.New}");
    };

    return base.Initialize();
}

public override async Task Run()
{
    await ReadConditions();

    sensor?.StartUpdating(TimeSpan.FromSeconds(1));
}

async Task ReadConditions()
{
    if (sensor == null) { return; }

    var result = await sensor.Read();
    Resolver.Log.Info("Initial Readings:");
    Resolver.Log.Info($"  Temperature: {result}");
}

Sample project(s) available on GitHub

Wiring Example

To wire a Sgp40 to your Meadow board, connect the following:

Sgp40 Meadow Pin
GND GND
SCL D08 (SCL)
SDA D07 (SDA)
VCC 3V3

Methods

ClearCompensationData()

Clear the compensation data

Declaration
public void ClearCompensationData()

Remarks

Sgp40
Status Status badge: working
Source code GitHub
Datasheet(s) GitHub
NuGet package NuGet Gallery for Meadow.Foundation.Sensors.Atmospheric.Sgp40

Code Example

Sgp40? sensor;

public override Task Initialize()
{
    Resolver.Log.Info("Initializing...");

    sensor = new Sgp40(Device.CreateI2cBus());

    Resolver.Log.Info($"Sensor SN: {sensor.SerialNumber:x6}");

    if (sensor.RunSelfTest())
    {
        Resolver.Log.Info("Self test successful");
    }
    else
    {
        Resolver.Log.Warn("Self test failed");
    }

    var consumer = Sgp40.CreateObserver(
        handler: result =>
        {
            Resolver.Log.Info($"Observer: VOC changed by threshold; new index: {result.New}");
        },
        filter: result =>
        {
            return Math.Abs(result.New - result.Old ?? 0) > 10;
        }
    );
    sensor.Subscribe(consumer);

    sensor.Updated += (sender, result) =>
    {
        Resolver.Log.Info($"  VOC: {result.New}");
    };

    return base.Initialize();
}

public override async Task Run()
{
    await ReadConditions();

    sensor?.StartUpdating(TimeSpan.FromSeconds(1));
}

async Task ReadConditions()
{
    if (sensor == null) { return; }

    var result = await sensor.Read();
    Resolver.Log.Info("Initial Readings:");
    Resolver.Log.Info($"  Temperature: {result}");
}

Sample project(s) available on GitHub

Wiring Example

To wire a Sgp40 to your Meadow board, connect the following:

Sgp40 Meadow Pin
GND GND
SCL D08 (SCL)
SDA D07 (SDA)
VCC 3V3

Initialize()

Initialize the sensor

Declaration
protected void Initialize()

Remarks

Sgp40
Status Status badge: working
Source code GitHub
Datasheet(s) GitHub
NuGet package NuGet Gallery for Meadow.Foundation.Sensors.Atmospheric.Sgp40

Code Example

Sgp40? sensor;

public override Task Initialize()
{
    Resolver.Log.Info("Initializing...");

    sensor = new Sgp40(Device.CreateI2cBus());

    Resolver.Log.Info($"Sensor SN: {sensor.SerialNumber:x6}");

    if (sensor.RunSelfTest())
    {
        Resolver.Log.Info("Self test successful");
    }
    else
    {
        Resolver.Log.Warn("Self test failed");
    }

    var consumer = Sgp40.CreateObserver(
        handler: result =>
        {
            Resolver.Log.Info($"Observer: VOC changed by threshold; new index: {result.New}");
        },
        filter: result =>
        {
            return Math.Abs(result.New - result.Old ?? 0) > 10;
        }
    );
    sensor.Subscribe(consumer);

    sensor.Updated += (sender, result) =>
    {
        Resolver.Log.Info($"  VOC: {result.New}");
    };

    return base.Initialize();
}

public override async Task Run()
{
    await ReadConditions();

    sensor?.StartUpdating(TimeSpan.FromSeconds(1));
}

async Task ReadConditions()
{
    if (sensor == null) { return; }

    var result = await sensor.Read();
    Resolver.Log.Info("Initial Readings:");
    Resolver.Log.Info($"  Temperature: {result}");
}

Sample project(s) available on GitHub

Wiring Example

To wire a Sgp40 to your Meadow board, connect the following:

Sgp40 Meadow Pin
GND GND
SCL D08 (SCL)
SDA D07 (SDA)
VCC 3V3

RaiseEventsAndNotify(IChangeResult<int>)

Inheritance-safe way to raise events and notify observers.

Declaration
protected override void RaiseEventsAndNotify(IChangeResult<int> changeResult)

Parameters

Type Name Description
IChangeResult<int> changeResult

Overrides

Remarks

Sgp40
Status Status badge: working
Source code GitHub
Datasheet(s) GitHub
NuGet package NuGet Gallery for Meadow.Foundation.Sensors.Atmospheric.Sgp40

Code Example

Sgp40? sensor;

public override Task Initialize()
{
    Resolver.Log.Info("Initializing...");

    sensor = new Sgp40(Device.CreateI2cBus());

    Resolver.Log.Info($"Sensor SN: {sensor.SerialNumber:x6}");

    if (sensor.RunSelfTest())
    {
        Resolver.Log.Info("Self test successful");
    }
    else
    {
        Resolver.Log.Warn("Self test failed");
    }

    var consumer = Sgp40.CreateObserver(
        handler: result =>
        {
            Resolver.Log.Info($"Observer: VOC changed by threshold; new index: {result.New}");
        },
        filter: result =>
        {
            return Math.Abs(result.New - result.Old ?? 0) > 10;
        }
    );
    sensor.Subscribe(consumer);

    sensor.Updated += (sender, result) =>
    {
        Resolver.Log.Info($"  VOC: {result.New}");
    };

    return base.Initialize();
}

public override async Task Run()
{
    await ReadConditions();

    sensor?.StartUpdating(TimeSpan.FromSeconds(1));
}

async Task ReadConditions()
{
    if (sensor == null) { return; }

    var result = await sensor.Read();
    Resolver.Log.Info("Initial Readings:");
    Resolver.Log.Info($"  Temperature: {result}");
}

Sample project(s) available on GitHub

Wiring Example

To wire a Sgp40 to your Meadow board, connect the following:

Sgp40 Meadow Pin
GND GND
SCL D08 (SCL)
SDA D07 (SDA)
VCC 3V3

ReadSensor()

Reads data from the sensor

Declaration
protected override Task<int> ReadSensor()

Returns

Type Description
Task<int>

The latest sensor reading

Overrides

Meadow.Foundation.SamplingSensorBase<int>.ReadSensor()

Remarks

Sgp40
Status Status badge: working
Source code GitHub
Datasheet(s) GitHub
NuGet package NuGet Gallery for Meadow.Foundation.Sensors.Atmospheric.Sgp40

Code Example

Sgp40? sensor;

public override Task Initialize()
{
    Resolver.Log.Info("Initializing...");

    sensor = new Sgp40(Device.CreateI2cBus());

    Resolver.Log.Info($"Sensor SN: {sensor.SerialNumber:x6}");

    if (sensor.RunSelfTest())
    {
        Resolver.Log.Info("Self test successful");
    }
    else
    {
        Resolver.Log.Warn("Self test failed");
    }

    var consumer = Sgp40.CreateObserver(
        handler: result =>
        {
            Resolver.Log.Info($"Observer: VOC changed by threshold; new index: {result.New}");
        },
        filter: result =>
        {
            return Math.Abs(result.New - result.Old ?? 0) > 10;
        }
    );
    sensor.Subscribe(consumer);

    sensor.Updated += (sender, result) =>
    {
        Resolver.Log.Info($"  VOC: {result.New}");
    };

    return base.Initialize();
}

public override async Task Run()
{
    await ReadConditions();

    sensor?.StartUpdating(TimeSpan.FromSeconds(1));
}

async Task ReadConditions()
{
    if (sensor == null) { return; }

    var result = await sensor.Read();
    Resolver.Log.Info("Initial Readings:");
    Resolver.Log.Info($"  Temperature: {result}");
}

Sample project(s) available on GitHub

Wiring Example

To wire a Sgp40 to your Meadow board, connect the following:

Sgp40 Meadow Pin
GND GND
SCL D08 (SCL)
SDA D07 (SDA)
VCC 3V3

RunSelfTest()

This command triggers the built-in self-test checking for integrity of both hotplate and MOX material

Declaration
public bool RunSelfTest()

Returns

Type Description
bool

true on successful test, otherwise false

Remarks

Sgp40
Status Status badge: working
Source code GitHub
Datasheet(s) GitHub
NuGet package NuGet Gallery for Meadow.Foundation.Sensors.Atmospheric.Sgp40

Code Example

Sgp40? sensor;

public override Task Initialize()
{
    Resolver.Log.Info("Initializing...");

    sensor = new Sgp40(Device.CreateI2cBus());

    Resolver.Log.Info($"Sensor SN: {sensor.SerialNumber:x6}");

    if (sensor.RunSelfTest())
    {
        Resolver.Log.Info("Self test successful");
    }
    else
    {
        Resolver.Log.Warn("Self test failed");
    }

    var consumer = Sgp40.CreateObserver(
        handler: result =>
        {
            Resolver.Log.Info($"Observer: VOC changed by threshold; new index: {result.New}");
        },
        filter: result =>
        {
            return Math.Abs(result.New - result.Old ?? 0) > 10;
        }
    );
    sensor.Subscribe(consumer);

    sensor.Updated += (sender, result) =>
    {
        Resolver.Log.Info($"  VOC: {result.New}");
    };

    return base.Initialize();
}

public override async Task Run()
{
    await ReadConditions();

    sensor?.StartUpdating(TimeSpan.FromSeconds(1));
}

async Task ReadConditions()
{
    if (sensor == null) { return; }

    var result = await sensor.Read();
    Resolver.Log.Info("Initial Readings:");
    Resolver.Log.Info($"  Temperature: {result}");
}

Sample project(s) available on GitHub

Wiring Example

To wire a Sgp40 to your Meadow board, connect the following:

Sgp40 Meadow Pin
GND GND
SCL D08 (SCL)
SDA D07 (SDA)
VCC 3V3

SetCompensationData(RelativeHumidity, Temperature)

Set the compensation data

Declaration
public void SetCompensationData(RelativeHumidity humidity, Temperature temperature)

Parameters

Type Name Description
RelativeHumidity humidity

Humidity compensation

Temperature temperature

Temperature compensation

Remarks

Sgp40
Status Status badge: working
Source code GitHub
Datasheet(s) GitHub
NuGet package NuGet Gallery for Meadow.Foundation.Sensors.Atmospheric.Sgp40

Code Example

Sgp40? sensor;

public override Task Initialize()
{
    Resolver.Log.Info("Initializing...");

    sensor = new Sgp40(Device.CreateI2cBus());

    Resolver.Log.Info($"Sensor SN: {sensor.SerialNumber:x6}");

    if (sensor.RunSelfTest())
    {
        Resolver.Log.Info("Self test successful");
    }
    else
    {
        Resolver.Log.Warn("Self test failed");
    }

    var consumer = Sgp40.CreateObserver(
        handler: result =>
        {
            Resolver.Log.Info($"Observer: VOC changed by threshold; new index: {result.New}");
        },
        filter: result =>
        {
            return Math.Abs(result.New - result.Old ?? 0) > 10;
        }
    );
    sensor.Subscribe(consumer);

    sensor.Updated += (sender, result) =>
    {
        Resolver.Log.Info($"  VOC: {result.New}");
    };

    return base.Initialize();
}

public override async Task Run()
{
    await ReadConditions();

    sensor?.StartUpdating(TimeSpan.FromSeconds(1));
}

async Task ReadConditions()
{
    if (sensor == null) { return; }

    var result = await sensor.Read();
    Resolver.Log.Info("Initial Readings:");
    Resolver.Log.Info($"  Temperature: {result}");
}

Sample project(s) available on GitHub

Wiring Example

To wire a Sgp40 to your Meadow board, connect the following:

Sgp40 Meadow Pin
GND GND
SCL D08 (SCL)
SDA D07 (SDA)
VCC 3V3

TurnHeaterOff()

This command turns the hotplate off and stops the measurement. Subsequently, the sensor enters idle mode.

Declaration
public void TurnHeaterOff()

Remarks

Sgp40
Status Status badge: working
Source code GitHub
Datasheet(s) GitHub
NuGet package NuGet Gallery for Meadow.Foundation.Sensors.Atmospheric.Sgp40

Code Example

Sgp40? sensor;

public override Task Initialize()
{
    Resolver.Log.Info("Initializing...");

    sensor = new Sgp40(Device.CreateI2cBus());

    Resolver.Log.Info($"Sensor SN: {sensor.SerialNumber:x6}");

    if (sensor.RunSelfTest())
    {
        Resolver.Log.Info("Self test successful");
    }
    else
    {
        Resolver.Log.Warn("Self test failed");
    }

    var consumer = Sgp40.CreateObserver(
        handler: result =>
        {
            Resolver.Log.Info($"Observer: VOC changed by threshold; new index: {result.New}");
        },
        filter: result =>
        {
            return Math.Abs(result.New - result.Old ?? 0) > 10;
        }
    );
    sensor.Subscribe(consumer);

    sensor.Updated += (sender, result) =>
    {
        Resolver.Log.Info($"  VOC: {result.New}");
    };

    return base.Initialize();
}

public override async Task Run()
{
    await ReadConditions();

    sensor?.StartUpdating(TimeSpan.FromSeconds(1));
}

async Task ReadConditions()
{
    if (sensor == null) { return; }

    var result = await sensor.Read();
    Resolver.Log.Info("Initial Readings:");
    Resolver.Log.Info($"  Temperature: {result}");
}

Sample project(s) available on GitHub

Wiring Example

To wire a Sgp40 to your Meadow board, connect the following:

Sgp40 Meadow Pin
GND GND
SCL D08 (SCL)
SDA D07 (SDA)
VCC 3V3

Events

VocIndexUpdated

Provides access to the Sensirion SGP40 VOC sensor

Declaration
public event EventHandler<ChangeResult<int>> VocIndexUpdated

Event Type

Type Description
EventHandler<ChangeResult<int>>

Remarks

Sgp40
Status Status badge: working
Source code GitHub
Datasheet(s) GitHub
NuGet package NuGet Gallery for Meadow.Foundation.Sensors.Atmospheric.Sgp40

Code Example

Sgp40? sensor;

public override Task Initialize()
{
    Resolver.Log.Info("Initializing...");

    sensor = new Sgp40(Device.CreateI2cBus());

    Resolver.Log.Info($"Sensor SN: {sensor.SerialNumber:x6}");

    if (sensor.RunSelfTest())
    {
        Resolver.Log.Info("Self test successful");
    }
    else
    {
        Resolver.Log.Warn("Self test failed");
    }

    var consumer = Sgp40.CreateObserver(
        handler: result =>
        {
            Resolver.Log.Info($"Observer: VOC changed by threshold; new index: {result.New}");
        },
        filter: result =>
        {
            return Math.Abs(result.New - result.Old ?? 0) > 10;
        }
    );
    sensor.Subscribe(consumer);

    sensor.Updated += (sender, result) =>
    {
        Resolver.Log.Info($"  VOC: {result.New}");
    };

    return base.Initialize();
}

public override async Task Run()
{
    await ReadConditions();

    sensor?.StartUpdating(TimeSpan.FromSeconds(1));
}

async Task ReadConditions()
{
    if (sensor == null) { return; }

    var result = await sensor.Read();
    Resolver.Log.Info("Initial Readings:");
    Resolver.Log.Info($"  Temperature: {result}");
}

Sample project(s) available on GitHub

Wiring Example

To wire a Sgp40 to your Meadow board, connect the following:

Sgp40 Meadow Pin
GND GND
SCL D08 (SCL)
SDA D07 (SDA)
VCC 3V3