Skip to content

9. Input Devices

Hero Shot of the Week

Hero

Summary

First I needed to know which input devices I wanted to probe. I wanted them to be used for my final project so it somehow simplified my choices. Secondly I did some documentation to see how it works and what I need to know. Than there was the experimenting part with the input device.

Sometimes some headbanging the wall because I did not understand what was happening or that it was way more complicated than I had expected and so depression came.

Work Process

This week's music:

Calendar

Date To be done What was done
Thursday - 10h local - local all day
Friday - FabLab normal work - FabLab work
Saturday - research & coding
Sunday
Monday - PCB production & 3D Printing
Tuesday - FabLab normal work - mic tests
Wednesday - 12h Local
- 13h Regional
- 15h Global
- filling in empty space

Introduction

Erwin did an introduction.

Analog signal:

  • continuous signal
  • values are sampled over time
  • signal can be amplified

Digital signal:

  • On / Off

ADC

GPIO

  • General Purpose Input / Output
  • 2 states : Low - High
  • pull-up resistors might be needed to define an undefined state

Interface / Protocol

  • communication between devices
  • one-way VS two-way
  • address, command, value
  • ex:
    • 1 wire / TWI
    • I2C
    • SPI
    • PWM
    • Serial

SI Units

CO2 and VOC Sensors - SGP30

First step was too look up some datasheet:

Than I followed this guide from AdaFruit on how to use this sensor.

I first needed to install the Adafruit SGP30 library.

Than I looked up (again) the pin layout as the example file wanted me to connect to SDA and SCL.

The sensor works but now I need to integrate it into my code. I also want to see if I can use it on other pins.

So I started to dissect the code.

I first looked up the wire library. This is for I2C communication.

The second thing that looked weird to me was uint16_t. Reading the following BadProg seems like it is just to define the bit value of the string that we want to use. In this case it is a string of 16bit.

Difference between Void and uint

Void Vs uint

Void Vs uint

Void Vs uint

I might rewrite me function, or maybe just a return x might work. But for now print is enough.

SGP30
CO2 & VOC Sensor - SGP30
//
#include <Arduino.h>
// I2C Communication
#include <Wire.h>
// SGP30 - CO2 Sensor
#include "Adafruit_SGP30.h"
Adafruit_SGP30 sgp;

// ---------- Function declaration ----------
void CO2S_SGP30(); //CO2 Sensor
int counter = 0; // Counter for CO2 Sensor
uint32_t getAbsoluteHumidity(float, float); // Absolute humidity correction for CO2 Sensor

// ---------- Setup ----------
void setup() {
// put your setup code here, to run once:

Serial.begin(9600);   // Initialize Serial Monitor
while (!Serial) { delay(10); } // Wait for serial console to open!

// Initialize I2C communication for the SGP30
Serial.println("SGP30 test");

if (! sgp.begin()){
    Serial.println("Sensor not found :(");
    while (1);
}
Serial.print("Found SGP30 serial #");
Serial.print(sgp.serialnumber[0], HEX);
Serial.print(sgp.serialnumber[1], HEX);
Serial.println(sgp.serialnumber[2], HEX);

// If you have a baseline measurement from before you can assign it to start, to 'self-calibrate'
//sgp.setIAQBaseline(0x8E68, 0x8F41);  // Will vary for each sensor!
}


// ---------- Loop ----------
void loop() {

CO2S_SGP30();
delay(5000);
}


// ---------- Function definitions ----------
// ---------- CO2 Sensor - Sensirion SGP30 eCO2 & TVOC Sensor

/* return absolute humidity [mg/m^3] with approximation formula
* @param temperature [°C]
* @param humidity [%RH]
*/
uint32_t getAbsoluteHumidity(float temperature, float humidity) {
// approximation formula from Sensirion SGP30 Driver Integration chapter 3.15
const float absoluteHumidity = 216.7f * ((humidity / 100.0f) * 6.112f * exp((17.62f * temperature) / (243.12f + temperature)) / (273.15f + temperature)); // [g/m^3]
const uint32_t absoluteHumidityScaled = static_cast<uint32_t>(1000.0f * absoluteHumidity); // [mg/m^3]
return absoluteHumidityScaled;
}


void CO2S_SGP30(){
// If you have a temperature / humidity sensor, you can set the absolute humidity to enable the humidity compensation for the air quality signals
//float temperature = 22.1; // [°C]
//float humidity = 45.2; // [%RH]
//sgp.setHumidity(getAbsoluteHumidity(temperature, humidity));

if (! sgp.IAQmeasure()) {
    Serial.println("Measurement failed");
    return;
}
Serial.print("TVOC "); Serial.print(sgp.TVOC); Serial.print(" ppb\t");
Serial.print("eCO2 "); Serial.print(sgp.eCO2); Serial.println(" ppm");

if (! sgp.IAQmeasureRaw()) {
    Serial.println("Raw Measurement failed");
    return;
}
Serial.print("Raw H2 "); Serial.print(sgp.rawH2); Serial.print(" \t");
Serial.print("Raw Ethanol "); Serial.print(sgp.rawEthanol); Serial.println("");

delay(1000);

counter++;
if (counter == 30) {
    counter = 0;

    uint16_t TVOC_base, eCO2_base;
    if (! sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) {
    Serial.println("Failed to get baseline readings");
    return;
    }
    Serial.print("****Baseline values: eCO2: 0x"); Serial.print(eCO2_base, HEX);
    Serial.print(" & TVOC: 0x"); Serial.println(TVOC_base, HEX);
}
//Code from Adafruit SGP30 example
}

I copy-pasted the example code given to my code. But there is two things that I will need to check later on.

  1. I will need a return value that I can send over to another microcontroller. For now I only print and not return any values...
  2. Can I have multiple sensors on the I2C channel (SDA and SCL pins) ? We were told that we are going to see that later on...

Other useful links

Sound Sensor

MAX4466 Microphone

While searching for the datasheet I have found a really nice article on how to use this microphone. The idea of the microphone is that I can measure the dB level of the rooms in the FabLab.

<- this part was added some days later

So I tried using the code given in the article. It works but in a weird way.

Max 4466 Mic test

So when I snap my fingers the sound dips...

And it does not hear my background music playing...
Even when I put it next to my laptop sound bar...
But I can clearly hear my own music...
(check this weeks music at the top)

This was on 3.3V. Lets see what happens with 5V.

Same thing. Value dips when I snap.

So I changed all 1024 to 4096. This made thing look in a better way:

Snap test:

Max 4466 Mic test

Background noise:

Max 4466 Mic test

And it seems to change with my music too.

Now to only see how I can convert all this to noise level measurements.
worksafety 🙃 ->

Datasheet here

Before trying out the code given in the previous article I wanted to found out how to calculate the dB level. I know that it is a logarithmic scale but I have no clue how I go from an analog value from a microphone to the dB level. I have found several interesting pages.

What the heck...
There is at least 3 different dB...
dB, dBA, dBC

Seems like I also will need to calibrate each mic & microprocessor...

It seems that he did not do the noise measurement part :/

He used a complete system (KY-037) and not just a mic :/

I might get somewhere with this one.

This just getting more complicated...

WAIT !!!!

I have that same mic too (almost) !!!

ICS-43434 Microphone

The first issue with using it is that I am at home and there are no pins soldered to it yet...
(I have a box of electronics that I can play with, with me)

Datasheet

YAY
I soldered the pins upside down !
I should have check the guide first...
I can unsolder and resolder.

Done.

Lets continue.

Now I need to know if the ESP32-S3 does I2S (not to be mixed with I2C) communication.
It does but here the mic id connected directly with the B2B connector...

Looking at the pin layout it seems that we have TX and RX connectors.

Really good examples here

Well.
I got the following error in arduino IDE Compilation error: I2S.h: No such file or directory but the doc says it is included in the basic install...

Further research says that it is in fact library version dependent. It is no longer present in newer versions of board manager libraries.

This code resulted in the following data:

This is in real speed. No acceleration. Only scaled down to be in the KB range.

I checked but I did not understand what is happening in the code... But it send the data over to a server. That could be useful for later on.

Maybe I should go back to the previous, simpler mic...

CO2, T and Humidity Sensor - Sensirion SCD30

Datasheet

The two library that I added are

So I took the example given and modified it to make it compatible with my code.

SCD30
CO2, Temperature & Humidity Sensor - SCD30
// SCD30 - CO2 Sensor
#include "SparkFun_SCD30_Arduino_Library.h"
SCD30 airSensor;

// SCD30 - CO2 Sensor
void CO2S_SCD30_STAR(bool); //function to initialize the CO2 Sensor - SCD30
void CO2S_SCD30(); //CO2 Sensor - SCD30

void setup() {
    // put your setup code here, to run once:

    Serial.begin(9600);   // Initialize Serial Monitor
    while (!Serial) { delay(10); } // Wait for serial console to open!
    // Initialize the CO2 Sensor - SCD30
    CO2S_SCD30_STAR(true);
}

void loop() {
    CO2S_SCD30();
}

// ---------- CO2, T and Humidity Sensor - Sensirion SCD30

void CO2S_SCD30_STAR(bool initialize){
Serial.println("SCD30 Example");
    Wire.begin(); // Initialize I2C communication

    //Start sensor using the Wire port, but disable the auto-calibration
    if (airSensor.begin(Wire, false) == false){
        Serial.println("Air sensor not detected. Please check wiring. Freezing...");
        while (1); // Do nothing more
    }

    uint16_t settingVal; // The settings will be returned in settingVal

    if (airSensor.getForcedRecalibration(&settingVal) == true){ // Get the setting
        Serial.print("Forced recalibration factor (ppm) is ");
        Serial.println(settingVal);
    }
    else{
        Serial.print("getForcedRecalibration failed! Freezing...");
        while (1); // Do nothing more
    }

    if (airSensor.getMeasurementInterval(&settingVal) == true){ // Get the setting
        Serial.print("Measurement interval (s) is ");
        Serial.println(settingVal);
    }
    else{
        Serial.print("getMeasurementInterval failed! Freezing...");
        while (1); // Do nothing more
    }

    if (airSensor.getTemperatureOffset(&settingVal) == true){ // Get the setting
        Serial.print("Temperature offset (C) is ");
        Serial.println(((float)settingVal) / 100.0, 2);
    }
    else{
        Serial.print("getTemperatureOffset failed! Freezing...");
        while (1); // Do nothing more
    }

    if (airSensor.getAltitudeCompensation(&settingVal) == true){ // Get the setting
        Serial.print("Altitude offset (m) is ");
        Serial.println(settingVal);
    }
    else{
        Serial.print("getAltitudeCompensation failed! Freezing...");
        while (1)
        ; // Do nothing more
    }

    if (airSensor.getFirmwareVersion(&settingVal) == true){ // Get the setting
        Serial.print("Firmware version is 0x");
        Serial.println(settingVal, HEX);
    }
    else{
        Serial.print("getFirmwareVersion! Freezing...");
        while (1); // Do nothing more
    }

    Serial.print("Auto calibration set to ");
    if (airSensor.getAutoSelfCalibration() == true)
        Serial.println("true");
    else
        Serial.println("false");

//The SCD30 has data ready every two seconds
}

void CO2S_SCD30(){
    if (airSensor.dataAvailable())
    {
        Serial.print("co2(ppm):");
        Serial.print(airSensor.getCO2());

        Serial.print(" temp(C):");
        Serial.print(airSensor.getTemperature(), 1);

        Serial.print(" humidity(%):");
        Serial.print(airSensor.getHumidity(), 1);

        Serial.println();
    }
    else
        Serial.println("Waiting for new data");

    delay(500);
}

Other Sensirion projects:

3D Printing

So for each of my sensors I made a 3D "case" so that I can put them into my giant breadboard.

SCD30

So for the SCD30 Sensor my soldering wasn't straight so the sensor hit the case (left bottom and right bottom). For me 3D printing is easier than soldering so instead of straightening my soldering I just made a new case with bigger error acceptance / space. In the end I made 3 iterations on the case (left top is the last iteration).

Mic + SGP30

In this image you can see that I soldered the ICS microphone in the wrong direction.

I tried to make a general case & sensor PCB so I can switch them more easily. The idea is that my work is not not sensor specific and is (supposed to be) modular.


Learning Outcome

Sometimes it is more complicated than just plug&play.
🥲



Assignment Check

  • group assignment:
    • probe an input device's analog levels and digital signals
      • Done
  • individual assignment:
    • measure something: add a sensor to a microcontroller board that you have designed and read it
      • Done