TheBlue Phoenix
Created March 19, 2020 © GPL3+

Corona Control

A voice-controlled module that monitors AQ, sunlight, temp, etc. to give a score of how habitable is your environment to the COVID-19 virus.

AdvancedFull instructions provided5 days93
Corona Control

Things used in this project

Hardware components

RSL10-SENSE-GEVK
onsemi RSL10-SENSE-GEVK
The miniature module that will act as our audio processor cum BT connectivity provider cum sensor hub.
×1
Arduino Nano R3
Arduino Nano R3
The main processor of our system that will be connected to the RSL10 sensor module using I2C interface.
×1
Adafruit Ultimate GPS Breakout
Adafruit Ultimate GPS Breakout
For GPS location and data
×1

Software apps and online services

onsemi ON Semiconductor IDE
IDE for coding the RSL10 sensor module
onsemi RSL 10 Sense and Control
For bluetooth connection and sensor data monitoring on mobile device
Arduino IDE
Arduino IDE
For arduino MCU coding
J-Scope
To view Audio samples and parameters
J Link RTT viewer
Real-Time Data viewing console

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
For making the GP board

Story

Read more

Schematics

Schematic Block Diagram

It shows the connections between all the major components of the project, with their communication interfaces.

Code

RSL10 Code

C/C++
The RSL10 sensor board code
#include <BDK.h>
#include <BSP_Components.h>
#include <BLE_Components.h>
#include <ansi_color.h>
#include <SEGGER_RTT.h>
//#include <HAL.h>
#include <stdio.h>

#define AUDIO_DMIC0_GAIN                0x800
#define AUDIO_DMIC1_GAIN                0x800
#define AUDIO_OD_GAIN                   0x800

#define AUDIO_CONFIG                    (OD_AUDIOSLOWCLK            | \
                                         DMIC_AUDIOCLK              | \
                                         DECIMATE_BY_64             | \
                                         OD_UNDERRUN_PROTECT_ENABLE | \
                                         OD_DATA_MSB_ALIGNED        | \
                                         DMIC0_DATA_LSB_ALIGNED     | \
                                         DMIC1_DATA_LSB_ALIGNED     | \
                                         OD_DMA_REQ_DISABLE         | \
                                         DMIC0_DMA_REQ_DISABLE      | \
                                         DMIC1_DMA_REQ_DISABLE      | \
                                         OD_INT_GEN_DISABLE         | \
                                         DMIC0_INT_GEN_ENABLE       | \
                                         DMIC1_INT_GEN_DISABLE      | \
                                         OD_DISABLE                 | \
                                         DMIC0_ENABLE               | \
                                         DMIC1_DISABLE)

#define EEPROM_I2C_ADDR       (0x50)
#define EEPROM_PAGE_SIZE      (4)
#define rx_id       (0x00) //change***********
#define tx_id       (0x68) //change***********
#define rsl_id 		(0x10) //I2C slave addr for RSL10

/* All data written to RX characteristic will be echoed back as a notification
 * send from TX characteristic. */
void BLE_CustomServiceEcho(struct BLE_ICS_RxIndData *ind);

/* Prints message into serial terminal when button is pressed / released. */
void PB_TransitionEvent(void *arg);

/* Copies measurement data for printing of status messages. */
void BME680_Callback(struct BME680_ENV_Data *output);

/* Copies measurement data for printing of status messages. */
void BHY_OrientationCallback(bhy_data_generic_t *data, bhy_virtual_sensor_t sensor);
void BHY_AccelerationCallback(bhy_data_generic_t *data, bhy_virtual_sensor_t sensor);
void BHY_GyroCallback(bhy_data_generic_t *data, bhy_virtual_sensor_t sensor);
long absolute(long value);
int32_t noa1305_status = -1;

int32_t bme680_status = -1;
struct BME680_ENV_Data bme680_output = { 0 };

int32_t bhy_status = -1;
bhy_data_vector_t bhy_orientation;
bhy_data_vector_t bhy_acceleration;
bhy_data_vector_t bhy_gyro;

int32_t eeprom_status = -1;
I2CEeprom eeprom;
const uint8_t eeprom_ref[]  = "This is just a test";
const uint8_t eeprom_ref_length = sizeof(eeprom_ref);

int32_t dmic_value = 0;
int32_t dmic_max = 0;
int32_t dmic_min = 600000;

uint8_t aTxBuffer[100] = "";
uint8_t aRxBuffer[100] = "";
uint32_t lux = 0;

float temp = 0;
float press = 0;
float humidity = 0;
float heading = 0;
float yaw = 0;
float pitch = 0;
float ax = 0;
float ay = 0;
float az = 0;
float gx = 0;
float gy = 0;
float gz = 0;
long cum_ampl = 0;
long dmic_abs = 30;
long dmic_abs_old = 30;
int dmic_flag = 0;
long avg_final = 0;
long cum_ampl_1 = 0;
long command_time_1 = 0;
long dmic_diff = 0;
long avg = 0;
//long avg1 = 0;
long timestamp1 = 0;
long command_time = 0;
int status;
float gas_resistance=0;
struct RxIndData
{
	float buffer;
	uint8_t buffer_len;
} *temp1;

int main(void)
{
    int32_t retval = 0;

    /* Initialize BDK library, set system clock (default 8MHz). */
    BDK_InitializeFreq(HAL_CLK_CONF_8MHZ);
    HAL_I2C_SetBusSpeed(HAL_I2C_BUS_SPEED_FAST);

    /* Initialize all LEDs */
    LED_Initialize(LED_RED);
    LED_Initialize(LED_GREEN);
    LED_Initialize(LED_BLUE);

    /* Test LEDs are working */
    LED_On(LED_RED);
    HAL_Delay(500);

    LED_Off(LED_RED);
    LED_On(LED_GREEN);
    HAL_Delay(500);

    LED_Off(LED_GREEN);
    LED_On(LED_BLUE);

    /* Initialize BLE stack */
    BDK_BLE_Initialize();
    BDK_BLE_SetLocalName("RSL10-SENSE-TESTER");
    BLE_ICS_Initialize(NULL);

    /* Initialize Button to call callback function when pressed or released. */
    BTN_Initialize(BTN0);
    BTN_Initialize(BTN1);

    /* AttachScheduled -> Callback will be scheduled and called by Kernel Scheduler. */
    /* AttachInt -> Callback will be called directly from interrupt routine. */
    BTN_AttachScheduled(BTN_EVENT_TRANSITION, &PB_TransitionEvent, (void*)BTN0, BTN0);
    BTN_AttachScheduled(BTN_EVENT_TRANSITION, &PB_TransitionEvent, (void*)BTN1, BTN1);

    /** Initialize NOA1305. */
    retval = NOA1305_ALS_Initialize();
    if (retval == NOA1305_OK)
    {
        retval = NOA1305_ALS_StartContinuous(0, NULL);
        if (retval == NOA1305_OK)
        {
            noa1305_status = 0;
        }
        else
        {
            noa1305_status = 2;
        }
    }
    else
    {
        noa1305_status = 1;
    }

    /** Initialize BME680 */
    retval = BME680_ENV_Initialize();
    if (retval == 0)
    {
        retval = BME680_ENV_StartPeriodic(BME680_Callback, 3000);
        if (retval == 0)
        {
            bme680_status = 0;
        }
        else
        {
            bme680_status = 2;
        }
    }
    else
    {
        bme680_status = 1;
    }

    /** Initialize BHI160 + load BMM150 RAM patch */
    retval = BHI160_NDOF_Initialize();
    if (retval == BHY_SUCCESS)
    {
        retval = BHI160_NDOF_EnableSensor(BHI160_NDOF_S_ORIENTATION, BHY_OrientationCallback, 1);
        if (retval == BHY_SUCCESS)
        {
            bhy_status = 0;
        }
        else
        {
            bhy_status = 2;
        }
        retval = BHI160_NDOF_EnableSensor(BHI160_NDOF_S_LINEAR_ACCELERATION, BHY_AccelerationCallback, 1);
		if (retval == BHY_SUCCESS)
		{
			bhy_status = 0;
		}
		else
		{
			bhy_status = 3;
		}
		retval = BHI160_NDOF_EnableSensor(BHI160_NDOF_S_RATE_OF_ROTATION, BHY_GyroCallback, 1);
		if (retval == BHY_SUCCESS)
		{
			bhy_status = 0;
		}
		else
		{
			bhy_status = 4;
		}

    }
    else
    {
        bhy_status = 1;
    }

    /** DO R/W test for N24RF64 EEPROM memory. */
    retval = I2CEeprom_Initialize(EEPROM_I2C_ADDR, EEPROM_PAGE_SIZE, &eeprom);
    if (retval == I2C_EEPROM_OK)
    {
        retval = I2CEeprom_Write(0, (uint8_t*)eeprom_ref, eeprom_ref_length, &eeprom);
        if (retval == I2C_EEPROM_OK)
        {
            uint8_t eeprom_readback[sizeof(eeprom_ref)];

            retval = I2CEeprom_Read(0, eeprom_readback, eeprom_ref_length, &eeprom);
            if (retval == I2C_EEPROM_OK)
            {
                if (memcmp(eeprom_ref, eeprom_readback, eeprom_ref_length) == 0)
                {
                    memset(eeprom_readback, 0, eeprom_ref_length);
                    I2CEeprom_Write(0, eeprom_readback, eeprom_ref_length, &eeprom);

                    eeprom_status = 0;
                }
                else
                {
                    eeprom_status = 4;
                }
            }
            else
            {
                eeprom_status = 3;
            }
        }
        else
        {
            eeprom_status = 2;
        }
    }
    else
    {
        eeprom_status = 1;
    }

    /** Configure DMIC input to test INMP522 microphone. */

    /* Configure AUDIOCLK to 2 MHz and AUDIOSLOWCLK to 1 MHz. */
    CLK->DIV_CFG1 &= ~(AUDIOCLK_PRESCALE_64 | AUDIOSLOWCLK_PRESCALE_4);
    CLK->DIV_CFG1 |= AUDIOCLK_PRESCALE_4 | AUDIOSLOWCLK_PRESCALE_2;

    /* Configure OD, DMIC0 and DMIC1 */
    Sys_Audio_Set_Config(AUDIO_CONFIG);

    Sys_Audio_Set_DMICConfig(DMIC0_DCRM_CUTOFF_20HZ | DMIC1_DCRM_CUTOFF_20HZ |
                             DMIC1_DELAY_DISABLE | DMIC0_FALLING_EDGE |
                             DMIC1_RISING_EDGE, 0);

    Sys_Audio_DMICDIOConfig(DIO_6X_DRIVE | DIO_LPF_DISABLE | DIO_NO_PULL,
                            10, 6, DIO_MODE_AUDIOCLK);

    /* Configure Gains for DMIC0, DMIC1 and OD */
    AUDIO->DMIC0_GAIN = AUDIO_DMIC0_GAIN;
    NVIC_EnableIRQ(DMIC_OUT_OD_IN_IRQn);

    LED_Off(LED_BLUE);
    printf("APP: Entering main loop.\r\n");
    uint32_t timestamp = 0;




    while (1)
    {
        /* Execute any events that have occurred & refresh Watchdog timer. */
        BDK_Schedule();

        /* Print status information every second */
        if (HAL_TIME_ELAPSED_SINCE(timestamp) >= 1000)
        {
            timestamp = HAL_Time();

            printf(RTT_CTRL_CLEAR "Test status:\r\n");

            printf("NOA1305 initialization: %s\r\n", noa1305_status == 0 ? COLORIZE("OK", GREEN) : COLORIZE("ERROR", RED));
            if (noa1305_status == 0)
            {
                NOA1305_ALS_ReadLux(&lux);
                printf("NOA1305 measured value: " COLORIZE("%lu", YELLOW) " lux\r\n\n", lux);
            }

            printf("BME680 initialization: %s\r\n", bme680_status == 0 ? COLORIZE("OK", GREEN) : COLORIZE("ERROR", RED));
            if (bme680_status == 0)
            {
            	temp = (float)bme680_output.temperature / 100.0f;
            	humidity = (float)bme680_output.humidity / 1000.0f;
            	press = (float)bme680_output.pressure;
                printf("BME680 temperature: " COLORIZE("%.2f", YELLOW) " °C\r\n", temp);
                printf("BME680 humidity: " COLORIZE("%.2f", YELLOW) " %%\r\n", humidity);
                printf("BME680 pressure: " COLORIZE("%.2f", YELLOW) " Pa\r\n\n", press);

            }

            printf("BHI160 (+BMM150) initialization: %s\r\n", bhy_status == 0 ? COLORIZE("OK", GREEN) : COLORIZE("ERROR", RED) );
            if (bhy_status == 0)
            {
            	uint16_t dyn_range = BHI160_NDOF_GetAccelDynamicRange();
                heading = bhy_orientation.x / 32768.0f * 360.0f;
                pitch = bhy_orientation.y / 32768.0f * 360.0f;
                yaw = bhy_orientation.z / 32768.0f * 360.0f;

                ax = bhy_acceleration.x / 32768.0f * dyn_range;
                ay = bhy_acceleration.y / 32768.0f * dyn_range;
                az = bhy_acceleration.z / 32768.0f * dyn_range;

                gx = bhy_gyro.x / 32768.0f * dyn_range;
                gy = bhy_gyro.y / 32768.0f * dyn_range;
				gz = bhy_gyro.z / 32768.0f * dyn_range;


				printf("BHI160 heading=" COLORIZE("%.2f°", YELLOW) ", ", heading);
                printf("pitch=" COLORIZE("%.2f°", YELLOW) ", ", pitch);
                printf("yaw=" COLORIZE("%.2f°", YELLOW) "\r\n\n", yaw);

                printf("BHI160 ax=" COLORIZE("%.2f°", YELLOW) ", ", ax);
                printf("ay=" COLORIZE("%.2f°", YELLOW) ", ", ay);
				printf("az=" COLORIZE("%.2f°", YELLOW) "\r\n\n", az);

				printf("BHI160 gx=" COLORIZE("%.2f°", YELLOW) ", ", gx);
				printf("gy=" COLORIZE("%.2f°", YELLOW) ", ", gy);
				printf("gz=" COLORIZE("%.2f°", YELLOW) "\r\n\n", gz);
            }

            printf("N24RF64 read back test: %s\r\n\n", eeprom_status == 0 ? COLORIZE("OK", GREEN) : COLORIZE("ERROR", RED));

            printf("INMP522: Use J-Scope to see waveform\r\n");
            printf("INMP522: dmic_min=" COLORIZE("%ld", YELLOW) ", dmic_max=" COLORIZE("%ld", YELLOW) "\r\n", dmic_min, dmic_max);

            //dmic_abs = absolute(dmic_value);
            if (dmic_flag == 2) {
				avg = absolute(cum_ampl_1/(command_time_1*dmic_diff));
				cum_ampl_1 = 0;
				command_time_1 = 0;
				dmic_flag = 0;
            }
			printf("dmic_abs: %d\r\n",dmic_abs);
            sprintf(aTxBuffer, "%d,%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,%d\r\n", lux, temp, humidity, press, heading, yaw, pitch, ax, ay, az, gx, gy, gz,avg);
            printf("Buffer: %s",aTxBuffer);
            BLE_ICS_Notify((uint8_t)temp, 4);
        }
        SYS_WAIT_FOR_INTERRUPT;
    }
    return 0;
}

void PB_TransitionEvent(void *arg)
{
    ButtonName btn = (ButtonName)arg;

    switch (btn)
    {
    case BTN0:
        LED_Toggle(LED_RED);
        break;
    case BTN1:
        LED_Toggle(LED_GREEN);
        break;
    default:
        return;
    }

    /* Read current Push Button state. */
    bool button_pressed = BTN_Read(btn);

    /* Print current button state to serial terminal. */
    printf("PB: Button %s state: %s [%lu ms]\r\n", (btn == BTN0) ? "0" : "1",
            (button_pressed == BTN_PRESSED) ? "PRESSED" : "RELEASED",
            HAL_Time());
}

void BME680_Callback(struct BME680_ENV_Data *output)
{
    memcpy(&bme680_output, output, sizeof(struct BME680_ENV_Data));
}

void BHY_OrientationCallback(bhy_data_generic_t *data, bhy_virtual_sensor_t sensor)
{
    memcpy(&bhy_orientation, &data->data_vector, sizeof(bhy_data_vector_t));
}

void BHY_AccelerationCallback(bhy_data_generic_t *data, bhy_virtual_sensor_t sensor)
{
    memcpy(&bhy_acceleration, &data->data_vector, sizeof(bhy_data_vector_t));
}

void BHY_GyroCallback(bhy_data_generic_t *data, bhy_virtual_sensor_t sensor)
{
    memcpy(&bhy_gyro, &data->data_vector, sizeof(bhy_data_vector_t));
}

void DMIC_OUT_OD_IN_IRQHandler(void)
{
	dmic_value = (int32_t)AUDIO->DMIC0_DATA;

	dmic_abs_old = dmic_abs;
    dmic_abs = absolute(dmic_value);
    if (dmic_flag == 1) {
    	cum_ampl = cum_ampl + dmic_abs;
		command_time++;
		if(command_time_1 < command_time) {
			command_time_1 = command_time;
		}
		if(cum_ampl_1 < cum_ampl) {
			cum_ampl_1 = cum_ampl;
		}
    }
	else if (dmic_flag == 0) {
		cum_ampl = 0;
		command_time = 0;
		dmic_min = 0;
		dmic_max = 0;
    }

	if (dmic_abs > 20) {
		dmic_flag = 1;
		if (dmic_abs_old < dmic_abs) {
			dmic_max = dmic_abs;
			dmic_min = dmic_abs_old;
		}
		else if (dmic_abs_old > dmic_abs) {
			dmic_max = dmic_abs_old;
			dmic_min = dmic_abs;
		}
	}
	else if (dmic_abs_old < 20) {
		dmic_flag = 2;
		dmic_diff = absolute(dmic_max - dmic_min);
	}

}

static int8_t tele_I2C_Write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{
    int32_t status;

    uint8_t *write_data = malloc(len + 1);
    if (write_data == NULL)
    {
        return -1;
    }
    write_data[0] = reg_addr;
    memcpy(write_data + 1, reg_data, len);

    status = HAL_I2C_Write(dev_id, write_data, len + 1, false);

    free(write_data);
    return status;
}

long absolute(long value) {
	if(value<0) {
		value = value*(-1);
	}
	return value;
}

Credits

TheBlue Phoenix

TheBlue Phoenix

7 projects • 32 followers
I have represented India Internationally. I have knowledge of various boards and embedded coding, FPGAs, TI, ADI, On Semi, RPi, SBCs etc.

Comments