PARKinSENSE

Introduction

Parkinson’s Disease is Neurodegenerative disorder that mostly presents in later life with generalized slowing of movements .Freezing of gait (FOG) is one of the most troublesome symptoms of Parkinson’s disease, affecting more than 50% of patients in advanced stages of the disease. Our idea proposes a solution for Parkinson’s disease involving supportive footwear.The footwear analyzes foot pressure of patient using 4 pressure sensors.Based upon analysis it alerts or gives motivation to patient on adverse condition.

An additional feature of this project is the integration of an LED indicator and buzzer to provide feedback on the gait status.

Overview

This technology-driven approach offers a practical and user-friendly solution for managing Parkinson’s disease symptoms, specifically addressing the challenging issue of Freezing of Gait (FOG). The supportive footwear integrates four pressure sensors to analyze foot pressure in real time. Based on this analysis, the system can alert or motivate the patient during adverse conditions, potentially improving mobility and quality of life.

Additionally, the footwear features an LED indicator and a buzzer to provide immediate feedback on gait status. This real-time feedback can help patients and caregivers monitor and manage FOG episodes more effectively, contributing to better symptom management and increased safety.

By leveraging advanced sensor technology and real-time data processing, this project showcases the potential to enhance the lives of Parkinson’s disease patients. Its implementation holds promise for improving mobility, safety, and overall quality of life, demonstrating a significant step forward in supportive healthcare technology for neurodegenerative disorders.

Components Required

  • VSD Squadron Mini developement board with CH32V003F4U6 chip with 32-bit RISC-V core based on RV32EC instruction set
  • Velostat sensor
  • Bread Board
  • Jumper Wires
  • LED
  • Resistors

Circuit Connection Diagram

Pin Connections

VelostatVSD Squadron Mini
DigitalPD2
VCC3.3V
VSD Squadron MiniLEDs
PD4LED Red

Code

#include "debug.h"
#include <math.h> // Include math.h for sqrt function

#define ARRAY_SIZE 10

void ADC_Function_Init(void)
{
    ADC_InitTypeDef  ADC_InitStructure = {0};
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    NVIC_InitTypeDef NVIC_InitStructure = {0};

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // Enable clock for GPIOA
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); // Enable clock for GPIOD
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    RCC_ADCCLKConfig(RCC_PCLK2_Div8);

    // Configure PC4 (ADC Channel 2)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    // Configure PA1 (ADC Channel 1)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // Configure PA2 (ADC Channel 2)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // Configure PD2 (ADC Channel 3)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    ADC_DeInit(ADC1);
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel = 1;
    ADC_Init(ADC1, &ADC_InitStructure);

    // Configure channels with same sample time
    ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_241Cycles);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_241Cycles); // Configure Channel 1
    ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_241Cycles); // Configure Channel 2
    ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 1, ADC_SampleTime_241Cycles); // Configure Channel 3

    /* Higher Threshold:900, Lower Threshold:500 */
    ADC_AnalogWatchdogThresholdsConfig(ADC1, 900, 500);
    ADC_AnalogWatchdogSingleChannelConfig(ADC1, ADC_Channel_2);
    ADC_AnalogWatchdogCmd(ADC1, ADC_AnalogWatchdog_SingleRegEnable);

    NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    ADC_Calibration_Vol(ADC1, ADC_CALVOL_50PERCENT);
    ADC_ITConfig(ADC1, ADC_IT_AWD, ENABLE);
    ADC_Cmd(ADC1, ENABLE);

    ADC_ResetCalibration(ADC1);
    while(ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while(ADC_GetCalibrationStatus(ADC1));
}

void LED_Function_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
}

u16 Get_ADC_Val(u8 ch)
{
    u16 val;

    ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_241Cycles); // Select channel
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);

    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));

    val = ADC_GetConversionValue(ADC1);

    return val;
}

int Calculate_Mean(u16 values[], int size)
{
    int sum = 0;
    for (int i = 0; i < size; i++)
    {
        sum += values[i];
    }
    return sum / size;
}


int Calculate_Variance(u16 values[], int size, int mean)
{
    int variance = 0;
    for (int i = 0; i < size; i++)
    {
        variance += (values[i] - mean) * (values[i] - mean);
    }
    return variance / size;
}


int Calculate_Max(u16 values[], int size)
{
    int max = values[0];
    for (int i = 1; i < size; i++)
    {
        if (values[i] > max)
        {
            max = values[i];
        }
    }
    return max;
}


int Calculate_Min(u16 values[], int size)
{
    int min = values[0];
    for (int i = 1; i < size; i++)
    {
        if (values[i] < min)
        {
            min = values[i];
        }
    }
    return min;
}


int main(void)
{
    u16 ADC_val1, ADC_val2, ADC_val3, ADC_val4;
    u16 values_PC4[ARRAY_SIZE], values_PA1[ARRAY_SIZE], values_PA2[ARRAY_SIZE], values_PD2[ARRAY_SIZE];  // Arrays to store 10 values for each sensor
    int count = 0;  // Counter to keep track of the number of values stored

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    SystemCoreClockUpdate();
    Delay_Init();

    USART_Printf_Init(9600);
    printf("SystemClk:%d\r\n", SystemCoreClock);
    printf( "ChipID:%08x\r\n", DBGMCU_GetDEVID() );

    ADC_Function_Init();
    LED_Function_Init(); // Initialize LED

    while(1)
    {
        ADC_val1 = Get_ADC_Val(ADC_Channel_2); // Get value from PC4
        ADC_val2 = Get_ADC_Val(ADC_Channel_1); // Get value from PA1
        ADC_val3 = Get_ADC_Val(ADC_Channel_2); // Get value from PA2
        ADC_val4 = Get_ADC_Val(ADC_Channel_3); // Get value from PD2
        Delay_Ms(200);
        // printf("PC4:%04d PA1:%04d PA2:%04d PD2:%04d\r\n", ADC_val1, ADC_val2, ADC_val3, ADC_val4);

        // Store the values in the arrays
        values_PC4[count] = ADC_val1;
        values_PA1[count] = ADC_val2;
        values_PA2[count] = ADC_val3;
        values_PD2[count] = ADC_val4;

        count++;

        // If the arrays are full, calculate and print the statistics
        if (count == ARRAY_SIZE)
        {
            int mean_PC4 = Calculate_Mean(values_PC4, ARRAY_SIZE);
            int mean_PA1 = Calculate_Mean(values_PA1, ARRAY_SIZE);
            int mean_PA2 = Calculate_Mean(values_PA2, ARRAY_SIZE);
            int mean_PD2 = Calculate_Mean(values_PD2, ARRAY_SIZE);

            int var_PC4 = Calculate_Variance(values_PC4, ARRAY_SIZE, mean_PC4);
            int var_PA1 = Calculate_Variance(values_PA1, ARRAY_SIZE, mean_PA1);
            int var_PA2 = Calculate_Variance(values_PA2, ARRAY_SIZE, mean_PA2);
            int var_PD2 = Calculate_Variance(values_PD2, ARRAY_SIZE, mean_PD2);

            int max_PC4 = Calculate_Max(values_PC4, ARRAY_SIZE);
            int min_PC4 = Calculate_Min(values_PC4, ARRAY_SIZE);

            int max_PA1 = Calculate_Max(values_PA1, ARRAY_SIZE);
            int min_PA1 = Calculate_Min(values_PA1, ARRAY_SIZE);

            int max_PA2 = Calculate_Max(values_PA2, ARRAY_SIZE);
            int min_PA2 = Calculate_Min(values_PA2, ARRAY_SIZE);

            int max_PD2 = Calculate_Max(values_PD2, ARRAY_SIZE);
            int min_PD2 = Calculate_Min(values_PD2, ARRAY_SIZE);

            printf("Statistics:\r\n");
            printf("PC4 - Mean: %d, Variance: %d, Max: %d, Min: %d\r\n", mean_PC4, var_PC4, max_PC4, min_PC4);
            printf("PA1 - Mean: %d, Variance: %d, Max: %d, Min: %d\r\n", mean_PA1, var_PA1, max_PA1, min_PA1);
            printf("PA2 - Mean: %d, Variance: %d, Max: %d, Min: %d\r\n", mean_PA2, var_PA2, max_PA2, min_PA2);
            printf("PD2 - Mean: %d, Variance: %d, Max: %d, Min: %d\r\n", mean_PD2, var_PD2, max_PD2, min_PD2);

            // Check and print the state
            if (var_PC4 > 10000 && var_PA1 > 10000 && var_PA2 > 10000)
            {
                printf("State: Walking\r\n");
                GPIO_ResetBits(GPIOD, GPIO_Pin_4);
            }
            else if (var_PC4 >= 100 && var_PC4 <= 10000 &&
                     var_PA1 >= 100 && var_PA1 <= 10000 &&
                     var_PA2 >= 100 && var_PA2 <= 10000 )
            {
                printf("State: Shaking\r\n");
                GPIO_SetBits(GPIOD, GPIO_Pin_4);
            }
            else
            {
                printf("State: Standing\r\n");
                GPIO_ResetBits(GPIOD, GPIO_Pin_4);
            }

            count = 0;  // Reset the count to start storing new values
        }
    }
}

void ADC1_IRQHandler(void) _attribute_((interrupt("WCH-Interrupt-fast")));
/***********************
 * @fn      ADC1_IRQHandler
 *
 * @brief   This function handles analog watchdog exception.
 *
 * @return  none
 */
void ADC1_IRQHandler(void)
{
    if(ADC_GetITStatus( ADC1, ADC_IT_AWD)){
        // printf( "Enter AnalogWatchdog Interrupt\r\n" );
    }

    ADC_ClearITPendingBit( ADC1, ADC_IT_AWD);
}

Video

Fault Injected in input(Sensor analog values)

The sensor values after ADC ranges between 0 to 1023 that is 10bits.If there is attack on one or more analog values of sensor then output get affected.

Fault

Fault Secured

We checked analog values which we are storing in array of size 10 for each sensor for predicting state.If one or more values but total count less than 5 are corrupted then we replace them by mean of other values.If count of corrupted values is greater than 5 then we discard these reading for prediction.

Secured Code

/**** (C) COPYRIGHT *****
 * File Name          : main.c
 * Author             : WCH
 * Version            : V1.0.0
 * Date               : 2023/12/22
 * Description        : Main program body.
 *********
 * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
 * Attention: This software (modified or not) and binary are used for 
 * microcontroller manufactured by Nanjing Qinheng Microelectronics.
 *********/

/*
 *@Note
 *Analog watchdog routine:
 *ADC channels (PC4, PA1, PA2, PD2), detect that the ADC conversion data on the rule group channels is
 *outside 500 - 900 and trigger the simulation Watchdog interrupt.
 *
*/

#include "debug.h"
#include <math.h> // Include math.h for sqrt function
#define FAULT_THRESHOLD 5
#define ARRAY_SIZE 10

/*********
 * @fn      ADC_Function_Init
 *
 * @brief   Initializes ADC collection.
 *
 * @return  none
 */
void ADC_Function_Init(void)
{
    ADC_InitTypeDef  ADC_InitStructure = {0};
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    NVIC_InitTypeDef NVIC_InitStructure = {0};

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // Enable clock for GPIOA
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); // Enable clock for GPIOD
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    RCC_ADCCLKConfig(RCC_PCLK2_Div8);

    // Configure PC4 (ADC Channel 2)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    // Configure PA1 (ADC Channel 1)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // Configure PA2 (ADC Channel 2)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // Configure PD2 (ADC Channel 3)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    ADC_DeInit(ADC1);
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel = 1;
    ADC_Init(ADC1, &ADC_InitStructure);

    // Configure channels with same sample time
    ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_241Cycles);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_241Cycles); // Configure Channel 1
    ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_241Cycles); // Configure Channel 2
    ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 1, ADC_SampleTime_241Cycles); // Configure Channel 3

    /* Higher Threshold:900, Lower Threshold:500 */
    ADC_AnalogWatchdogThresholdsConfig(ADC1, 900, 500);
    ADC_AnalogWatchdogSingleChannelConfig(ADC1, ADC_Channel_2);
    ADC_AnalogWatchdogCmd(ADC1, ADC_AnalogWatchdog_SingleRegEnable);

    NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    ADC_Calibration_Vol(ADC1, ADC_CALVOL_50PERCENT);
    ADC_ITConfig(ADC1, ADC_IT_AWD, ENABLE);
    ADC_Cmd(ADC1, ENABLE);

    ADC_ResetCalibration(ADC1);
    while(ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while(ADC_GetCalibrationStatus(ADC1));
}

/*********
 * @fn      LED_Function_Init
 *
 * @brief   Initializes GPIO for LED.
 *
 * @return  none
 */
void LED_Function_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
}

/*********
 * @fn      Get_ADC_Val
 *
 * @brief   Returns ADCx conversion result data.
 *
 * @param   ch - ADC channel.
 *            ADC_Channel_0 - ADC Channel0 selected.
 *            ADC_Channel_1 - ADC Channel1 selected.
 *            ADC_Channel_2 - ADC Channel2 selected.
 *            ADC_Channel_3 - ADC Channel3 selected.
 *            ADC_Channel_4 - ADC Channel4 selected.
 *            ADC_Channel_5 - ADC Channel5 selected.
 *            ADC_Channel_6 - ADC Channel6 selected.
 *            ADC_Channel_7 - ADC Channel7 selected.
 *            ADC_Channel_8 - ADC Channel8 selected.
 *            ADC_Channel_9 - ADC Channel9 selected.
 *
 * @return  none
 */
u16 Get_ADC_Val(u8 ch)
{
    u16 val;

    ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_241Cycles); // Select channel
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);

    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));

    val = ADC_GetConversionValue(ADC1);

    return val;
}

/*********
 * @fn      Calculate_Mean
 *
 * @brief   Calculates the mean of an array of values.
 *
 * @param   values - Array of values.
 * @param   size - Number of values in the array.
 *
 * @return  Mean of the values.
 */
int Calculate_Mean(u16 values[], int size)
{
    int sum = 0;
    for (int i = 0; i < size; i++)
    {
        sum += values[i];
    }
    return sum / size;
}

/*********
 * @fn      Calculate_Variance
 *
 * @brief   Calculates the variance of an array of values.
 *
 * @param   values - Array of values.
 * @param   size - Number of values in the array.
 * @param   mean - Mean of the values.
 *
 * @return  Variance of the values.
 */
int Calculate_Variance(u16 values[], int size, int mean)
{
    int variance = 0;
    for (int i = 0; i < size; i++)
    {
        variance += ((values[i] - mean) * (values[i] - mean));
    }
    return variance / size;
}

/*********
 * @fn      Calculate_Max
 *
 * @brief   Calculates the maximum of an array of values.
 *
 * @param   values - Array of values.
 * @param   size - Number of values in the array.
 *
 * @return  Maximum of the values.
 */
int Calculate_Max(u16 values[], int size)
{
    int max = values[0];
    for (int i = 1; i < size; i++)
    {
        if (values[i] > max)
        {
            max = values[i];
        }
    }
    return max;
}

/*********
 * @fn      Calculate_Min
 *
 * @brief   Calculates the minimum of an array of values.
 *
 * @param   values - Array of values.
 * @param   size - Number of values in the array.
 *
 * @return  Minimum of the values.
 */
int Calculate_Min(u16 values[], int size)
{
    int min = values[0];
    for (int i = 1; i < size; i++)
    {
        if (values[i] < min)
        {
            min = values[i];
        }
    }
    return min;
}

int Replace_Faulty_Values(u16 *values, int size)
{
    int faulty_count = 0;
    int sum = 0;
    int valid_count = 0;

    for (int i = 0; i < size; i++)
    {
        if (values[i] <= 0 || values[i] >= 1024)
        {
            faulty_count++;
        }
        else
        {
            sum += values[i];
            valid_count++;
        }
    }

    int mean = valid_count > 0 ? sum / valid_count : 0;

    for (int i = 0; i < size; i++)
    {
        if (values[i] <= 0 || values[i] >= 1024)
        {
            values[i] = mean;
        }
    }
    if (faulty_count >= 5 || faulty_count >= 5 || faulty_count >= 5 || faulty_count >= 5)
            {
                printf("Fault is there\r\n");
                // printf("PC4:%04d PA1:%04d PA2:%04d PD2:%04d\r\n", ADC_val1, ADC_val2, ADC_val3, ADC_val4);

                 // Skip the rest of the loop and start collecting new values
            }
    return faulty_count;
}


/*********
 * @fn      main
 *
 * @brief   Main program.
 *
 * @return  none
 */
int main(void)
{
    u16 ADC_val1, ADC_val2, ADC_val3, ADC_val4;
    u16 values_PC4[ARRAY_SIZE], values_PA1[ARRAY_SIZE], values_PA2[ARRAY_SIZE], values_PD2[ARRAY_SIZE];  // Arrays to store 10 values for each sensor
    int count = 0;  // Counter to keep track of the number of values stored

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    SystemCoreClockUpdate();
    Delay_Init();

    USART_Printf_Init(9600);
    printf("SystemClk:%d\r\n", SystemCoreClock);
    printf( "ChipID:%08x\r\n", DBGMCU_GetDEVID() );

    ADC_Function_Init();
    LED_Function_Init(); // Initialize LED

    while(1)
    {
        ADC_val1 = Get_ADC_Val(ADC_Channel_2); // Get value from PC4
        ADC_val2 = Get_ADC_Val(ADC_Channel_1); // Get value from PA1
        ADC_val3 = Get_ADC_Val(ADC_Channel_2); // Get value from PA2
        ADC_val4 = Get_ADC_Val(ADC_Channel_3); // Get value from PD2
        Delay_Ms(200);
        // printf("PC4:%04d PA1:%04d PA2:%04d PD2:%04d\r\n", ADC_val1, ADC_val2, ADC_val3, ADC_val4);

        // Store the values in the arrays
        values_PC4[count] = ADC_val1;
        values_PA1[count] = ADC_val2;
        values_PA2[count] = ADC_val3;
        values_PD2[count] = ADC_val4;

        count++;

        // If the arrays are full, calculate and print the statistics
        if (count == ARRAY_SIZE)
        {
            values_PC4[0]=2048;
            values_PC4[1]=0;
            values_PA1[0]=1024;
            values_PA1[1]=0;
            values_PA2[0]=3000;
            values_PA2[1]=0;
            values_PD2[0]=3500;
            values_PD2[1]=0;
            // values_PC4[2]=0;
            // // values_PC4[3]=0;
            // // values_PC4[4]=0;
            // // values_PC4[5]=0;

            int faulty_PC4 = Replace_Faulty_Values(values_PC4, ARRAY_SIZE);
            int faulty_PA1 = Replace_Faulty_Values(values_PA1, ARRAY_SIZE);
            int faulty_PA2 = Replace_Faulty_Values(values_PA2, ARRAY_SIZE);
            int faulty_PD2 = Replace_Faulty_Values(values_PD2, ARRAY_SIZE);

            for(int i=0;i<10;i++){
                printf("PC$ %04d ",values_PC4[i]);
            }
            printf("%d fault\r\n",faulty_PC4);
            if (faulty_PC4 < 5 && faulty_PA1 < 5 && faulty_PA2 < 5 && faulty_PD2 < 5)
            {
            
                int mean_PC4 = Calculate_Mean(values_PC4, ARRAY_SIZE);
                int mean_PA1 = Calculate_Mean(values_PA1, ARRAY_SIZE);
                int mean_PA2 = Calculate_Mean(values_PA2, ARRAY_SIZE);
                int mean_PD2 = Calculate_Mean(values_PD2, ARRAY_SIZE);

                int var_PC4 = Calculate_Variance(values_PC4, ARRAY_SIZE, mean_PC4);
                int var_PA1 = Calculate_Variance(values_PA1, ARRAY_SIZE, mean_PA1);
                int var_PA2 = Calculate_Variance(values_PA2, ARRAY_SIZE, mean_PA2);
                int var_PD2 = Calculate_Variance(values_PD2, ARRAY_SIZE, mean_PD2);

                int max_PC4 = Calculate_Max(values_PC4, ARRAY_SIZE);
                int min_PC4 = Calculate_Min(values_PC4, ARRAY_SIZE);

                int max_PA1 = Calculate_Max(values_PA1, ARRAY_SIZE);
                int min_PA1 = Calculate_Min(values_PA1, ARRAY_SIZE);

                int max_PA2 = Calculate_Max(values_PA2, ARRAY_SIZE);
                int min_PA2 = Calculate_Min(values_PA2, ARRAY_SIZE);

                int max_PD2 = Calculate_Max(values_PD2, ARRAY_SIZE);
                int min_PD2 = Calculate_Min(values_PD2, ARRAY_SIZE);

                printf("Statistics:\r\n");
                printf("PC4 - Mean: %d, Variance: %d, Max: %d, Min: %d\r\n", mean_PC4, var_PC4, max_PC4, min_PC4);
                printf("PA1 - Mean: %d, Variance: %d, Max: %d, Min: %d\r\n", mean_PA1, var_PA1, max_PA1, min_PA1);
                printf("PA2 - Mean: %d, Variance: %d, Max: %d, Min: %d\r\n", mean_PA2, var_PA2, max_PA2, min_PA2);
                printf("PD2 - Mean: %d, Variance: %d, Max: %d, Min: %d\r\n", mean_PD2, var_PD2, max_PD2, min_PD2);

                // Check and print the state
                if (var_PC4 > 10000 && var_PA1 > 10000 && var_PA2 > 10000)
                {
                    printf("State: Walking\r\n");
                    GPIO_ResetBits(GPIOD, GPIO_Pin_4);
                }
                else if (var_PC4 >= 100 && var_PC4 <= 10000 &&
                        var_PA1 >= 100 && var_PA1 <= 10000 &&
                        var_PA2 >= 100 && var_PA2 <= 10000 )
                {
                    printf("State: Shaking\r\n");
                    GPIO_SetBits(GPIOD, GPIO_Pin_4);
                }
                else
                {
                    printf("State: Standing\r\n");
                    GPIO_ResetBits(GPIOD, GPIO_Pin_4);
                }
            }
            count = 0;  // Reset the count to start storing new values
        }
    }
}

void ADC1_IRQHandler(void) _attribute_((interrupt("WCH-Interrupt-fast")));
/*********
 * @fn      ADC1_IRQHandler
 *
 * @brief   This function handles analog watchdog exception.
 *
 * @return  none
 */
void ADC1_IRQHandler(void)
{
    if(ADC_GetITStatus( ADC1, ADC_IT_AWD)){
        // printf( "Enter AnalogWatchdog Interrupt\r\n" );
    }

    ADC_ClearITPendingBit( ADC1, ADC_IT_AWD);
}

Fault Injection in output(buzzer and led)

If prediction of state is correct but output (led or buzzer) is altered or at fault then output will be shown wrong.

Fault

Fault Secured

Secured Code

// Define the analog pins
const int analogPin1 = A0; // PA1
const int analogPin2 = A1; // PA2
const int analogPin3 = A2; // PC4
const int analogPin4 = A3; // Extra

// Define the digital pins
const int digitalPin1 = 10; // LED
const int digitalPin2 = 8;  // Buzzer

// Define the number of readings to take
const int numReadings = 10;

// Arrays to store readings
int readings1[numReadings];
int readings2[numReadings];
int readings3[numReadings];
int readings4[numReadings];

void setup() {
  // Initialize serial communication at 9600 bits per second:
  Serial.begin(9600);

  // Set the digital pins as outputs
  pinMode(digitalPin1, OUTPUT);
  pinMode(digitalPin2, OUTPUT);

  // Initialize all readings to 0
  for (int i = 0; i < numReadings; i++) {
    readings1[i] = 0;
    readings2[i] = 0;
    readings3[i] = 0;
    readings4[i] = 0;
  }
}

void loop() {
  // Take 10 readings for each analog pin
  for (int i = 0; i < numReadings; i++) {
    readings1[i] = analogRead(analogPin1);
    readings2[i] = analogRead(analogPin2);
    readings3[i] = analogRead(analogPin3);
    readings4[i] = analogRead(analogPin4);
    delay(100); // Delay to allow for stable readings
  }

  // Calculate mean and variance for each set of readings
  float mean1 = calculateMean(readings1);
  float variance1 = calculateVariance(readings1, mean1);
  
  float mean2 = calculateMean(readings2);
  float variance2 = calculateVariance(readings2, mean2);

  float mean3 = calculateMean(readings3);
  float variance3 = calculateVariance(readings3, mean3);

  float mean4 = calculateMean(readings4);
  float variance4 = calculateVariance(readings4, mean4);

  // Serial.print("Analog 1 Mean: ");
  // Serial.print(mean1);
  Serial.print("\tVariance: ");
  Serial.print(variance1);
  Serial.print(" ");
  Serial.print("Analog 2 Mean: ");
  Serial.print(mean2);
  Serial.print("\tVariance: ");
  Serial.print(variance2);
  Serial.print(" ");
  Serial.print("Analog 3 Mean: ");
  Serial.print(mean3);
  Serial.print("\tVariance: ");
  Serial.print(variance3);
  Serial.print(" ");
  Serial.print("Analog 4 Mean: ");
  Serial.print(mean4);
  Serial.print("\tVariance: ");
  Serial.println(variance4);

  int flag = 0;
  int flag1 = 0;

  // XOR operation on flags
  

  // If XOR result is 1, determine the state and update flags


  // Check conditions and set digital outputs accordingly
  if (variance3 > 1500 || variance1 > 1500 || variance2 > 1500) {
    Serial.println("State: Walking");
    flag=0;
    flag1=0;
    digitalWrite(digitalPin1, flag); // Turn off LED
    digitalWrite(digitalPin2, flag1); // Turn off Buzzer
  } else if ((variance3 >= 200 && variance3 <= 1500) ||
             (variance1 >= 200 && variance1 <= 1500) ||
             (variance2 >= 200 && variance2 <= 1500)) {
              flag=0;
    flag1=1;
    Serial.println("State: Shaking");
    
  } else {
    flag=0;
    flag1=0;
    Serial.println("State: Standing");
    
  }
  int xorResult = flag ^ flag1;
    if (xorResult == 1) {
    flag= determineState(mean1, variance1, mean2, variance2, mean3, variance3, mean4, variance4, flag, flag1);
  }
    digitalWrite(digitalPin1, flag); // Turn off LED
    digitalWrite(digitalPin2, flag); // Turn off Buzzer
  // Wait for a second before repeating the loop
  delay(200);
}

// Function to calculate mean
float calculateMean(int readings[]) {
  float sum = 0;
  for (int i = 0; i < numReadings; i++) {
    sum += readings[i];
  }
  return sum / numReadings;
}

// Function to calculate variance
float calculateVariance(int readings[], float mean) {
  float sum = 0;
  for (int i = 0; i < numReadings; i++) {
    sum += pow(readings[i] - mean, 2);
  }
  return sum / numReadings;
}

// Function to determine the state and update flags
int determineState(float mean1, float variance1, float mean2, float variance2, float mean3, float variance3, float mean4, float variance4, int &flag, int &flag1)
 {
  if (variance3 > 1500 || variance1 > 1500 || variance2 > 1500)
   {
    flag = 0;
    flag1 = 0;
  } else if ((variance3 >= 500 && variance3 <= 2000) ||
             (variance1 >= 500 && variance1 <= 2000) ||
             (variance2 >= 500 && variance2 <= 2000)) {
    flag = 1;
    flag1 = 1;
  } else 
  {
    flag = 0;
    flag1 = 0;
  }
  return flag;
}

Registration for Ethical RISC-V IoT Workshop

Welcome to Ethical RISC-V IoT Workshop

The “Ethical RISC-V IoT Workshop” at IIIT Bangalore, organized in collaboration with VSD, is a structured, educational competition aimed at exploring real-world challenges in IoT and embedded systems. Participants progress through three stages: building an application, injecting and managing faults, and enhancing application security. The event spans from May 9 to June 15, 2024, culminating in a showcase of top innovations and an award ceremony. This hands-on hackathon emphasizes learning, testing, and securing applications in a collaborative and competitive environment.

Rules :
  1. Only for Indian Student whose college is registered under VTU
  2. Only team of 2 members can Register
  3. Use only VSDSquadron Mini resources for product development
Awards :
  1. Prize money for final 10 Team
  2. 3 Winner team’s Product will be evaluated for Incubation
  3. 7 consolation prizes
  4. Completion Certificate to final round qualifier
  5. Chance to build a Proud Secured RISC-V Platform for India

Date for Registration : 9th May - 22nd May, 2024
Hackathon Inauguration : 23rd May 2024

VSDSquadron (Educational Board)

VSDSquadron, a cutting-edge development board based on the RISC-V architecture that is fully open-source. This board presents an exceptional opportunity for individuals to learn about RISC-V and VLSI chip design utilizing only open-source tools, starting from the RTL and extending all the way to the GDSII. The possibilities for learning and advancement with this technology are limitless.

Furthermore, the RISC-V chips on these boards should be open for VLSI chip design learning, allowing you to explore PNR, standard cells, and layout design. And guess what? vsdsquadron is the perfect solution for all your needs! With its comprehensive documentation and scalable labs, thousands of students can learn and grow together.

VSD HDP (Hardware Design Program) Duration-10 Week

With VSD Hardware Design Program (VSD-HDP),  you have the opportunity to push the boundaries of what exist in open source and establish the new benchmark for tomorrow.

It will leverage your degree in Electrical or Computer Engineering to work with

  • Programmable logic
  • Analog/ digital IP
  • RISC-V
  • Architecture & microprocessors
  • ASICs and SoCs on high-density digital or RF circuit cards
  • Gain hands-on knowledge during design validation and system integration.

Sounds exciting to just get started with expert mentors, doesn’t it? But we are looking for the next generation of learners, inventors, rebels, risk takers, and pioneers.

“Spend your summer working in the future !!”

Outcomes of VSD Online Research IP Design Internship Program

  1. Job opportunities in Semiconductor Industry
  2. Research work can be submitted to VLSI International journals
  3. Participate in Semiconductor International Conference with Internship Research Work
  4. Paper Publications in IEEE Conference and SIG groups
  5. Tape out opportunity and IP Royalty
  6. Interact with world class Semiconductor designer and researchers
  7. Academic professions where more research projects are encouraged.
  8. All the above research and publication work will help colleges and institutes to improve accreditation levels.

Know More Information

VSD – Intelligent Assessment Technology (VSD-IAT)

VSD – Intelligent Assessment Technology (VSD-IAT) is expertly built training platform and is suited for designer requirements. Semiconductor companies understand the value of training automation and Engineer performance enhancement, and do not need to be convinced of the impact of a virtual platform for learning. VSD trainings are quick, relevant, and easy to access from any device at any time zone.

VSD Intern Webinars

VSD Interns made it happen !!

VSD is working towards creating innovative talent pool who are ready to develop design and products for the new tech world. VSD believes in “Learning by doing principle” , and always prepare the student to apply the knowledge learned in the workshops, webinars and courses. We always push our students to work on new designs, test it and work continuously till it becomes the best performing design. Any student who enrolls to VSD community starts working with small design and grows with us and develops a tapeout level design with complete honesty and dedication towards the Work !!

Check out VSD Interns Achievement!

VSDOpen Online Conference

Welcome to the World’s only online conference in Semiconductor Industry VSDOpen Conference. With enormous support and global presence of audience from different segments of industrial lobby and academia made a highly successful event. Evolution is change in the genetic makeup of a population over time, online conference is one kind evaluation everyone adapt soon. 

  • VSDOpen 2022 is an online conference to share open-source research with the community and promote  hardware design mostly done by the student community.
  • VSDOpen 2022 is based on the theme “How to lower the cost to learn, build, and tapeout chips ?”  , which will provide a platform to community to build stronger designs and strengthen the future of Chip design.
  • VSDOpen is envisioned to create a community based revolution in semiconductor hardware technology.
  • The open source attitude is required to bring out the talent and innovation from the community who are in remote part of world and have least access to the technologies.  And now Google support will help to bring the vision to execution by VSD team

VSD Online Course by Kunal Ghosh

VSD offers online course in complete spectrum of vlsi backend flow from RTL design, synthesis and Verification, SoC planning and design, Sign-off analysis, IP Design, CAD/EDA automation and basic UNIX/IT, Introduction to latest technology – RISC-V, Machine intelligence in EDA/CAD, VLSI Interview FAQ’s.

Current Reach – As of 2021, VSD and its partners have released 41 online VLSI courses and was successfully able to teach  ~35900 Unique students around 151 countries in 47 different languages, through its unique info-graphical and technology mediated learning methods.

Enquiry Form