Sumit Kumar
Published © GPL3+

MENF - Meet Every New Friend

Engage more with friends without worrying about menopause problems. Active gel cooling, cloud functions, BLE, social interactivity.

IntermediateFull instructions providedOver 1 day679

Things used in this project

Hardware components

Argon
Particle Argon
A very low cost,network enabled IoT device - it is your swiss army knife for all IoT projects. End products or devices for market can be very easily made with it with advanced scaling features and management.In addition to everything it provides a very good documentation for all it's services. It now costs only 27$.
×1
Solar Cockroach Vibrating Disc Motor
Brown Dog Gadgets Solar Cockroach Vibrating Disc Motor
Small low powered vibration motors with greater efficiency and can be found in every smartphone.Unlike protruding shaft vibration motor it is not difficult to install. It is worth few bucks.
×2
Gravity: Analog Soil Moisture Sensor For Arduino
DFRobot Gravity: Analog Soil Moisture Sensor For Arduino
It is one the very basic sensors found in every IoT starter kits.It works on the principle of conductivity,it's analog signal becomes very high when there is less conductivity means increased resistance between it's two probes and analog signals becomes low when there moisture or increased conductivity between the two probes indicating less resistance.
×1
Battery, 3.7 V
Battery, 3.7 V
This battery is used to power Particle Argon and all it's peripherals, it is of 2000mAh capacity enough to run our main device along with all other actuators for several days.
×1
Dual H-Bridge motor drivers L293D
Texas Instruments Dual H-Bridge motor drivers L293D
L293D is one of the components of motor driver family which is used to switch larger loads which becomes unbearable for low power pins on microcontrollers, it is a motor driver but doesn't means it can handle only motors, you can use it to switch any load which draws huge current which would have otherwise fried up your MCUs.
×1
Gravity: Analog LM35 Temperature Sensor For Arduino
DFRobot Gravity: Analog LM35 Temperature Sensor For Arduino
LM35 is used for measuring surface temperature for our application.
×1
TEC1-00703 10mm Peltier Thermoelectric Cooler Elemente mini 10 x 10 C22
This is very tiny low power PELTIER module to be used in our project.It can be used either for heating or for cooling,although in practice the main application is cooling.Thermoelectric coolers operate by the Peltier effect (which also goes by the more general name thermoelectric effect). The device has two sides, and when a DC electric current flows through the device, it brings heat from one side to the other, so that one side gets cooler while the other gets hotter. The "hot" side is attached to a heat sink so that it remains at ambient temperature, while the cool side goes below room temperature. In special applications, multiple coolers can be cascaded together for lower temperature, but overall efficiency drops significantly.
×1

Software apps and online services

Particle Build Web IDE
Particle Build Web IDE
A well built platform to code, debug and integrate application for our Particle devices. It makes your work less cumbersome and reduces development time for any product or end solution.
Losant Platform
Losant Platform
A well designed visualization platform which can also help in data handling and manipulation from the data received through IoT devices.
Yondo
Yondo allows anyone to sell webinars, live online consultations and online videos on their own website.

Hand tools and fabrication machines

Hot glue gun (generic)
Hot glue gun (generic)
Soldering iron (generic)
Soldering iron (generic)
Plier, Long Nose
Plier, Long Nose

Story

Read more

Custom parts and enclosures

MENF

Schematics

Menf actual outllok

Active gel cooling

Night Sweats cooling

MENF BLE social interactivity

MENF device fan control

MENF device circuit

Code

Particle Argon MENF

C/C++
This our device code
/*
 * Project MENF - MEET EVERY NEW FRIEND
 * Description: Solving menopause problems with our Argon powered device
 * Innovation: Active gel cooling technique
 * Author: Sumit @vilaksh
 * Date: 4 May 2020
 */

#include "Particle.h"
#include "MapFloat.h"

// duration for fan 
#define FAN_DURATION (1000 * 60 * 10) // 10 minutes

int VIB_MOTOR1_PIN = 4;
int VIB_MOTOR2_PIN = 6;
int VIB_MOTOR_PWM = 5;
int FAN_PIN = 8;
int PELTIER_PIN = 2;
int SWEAT_SENSOR_PIN = A2;
int TEMP_SENSOR = A5;

int DELAY_TIME = 1000;
int pwm = 200;
int adc_value = 0;
int counter = 0;

unsigned long previousMillis = 0;

float temp = 0.0;
float peltierTemp = 0.0;
float voltage = 0.0;
float sweatRate = 0.0;

int fatigue = 0;
int hotFlash = 0;
int nightSweat = 0;
bool standbyMode = true;

// setup() runs once, when the device is first turned on.
void setup()
{
  // All Particle functions exposed to be used with losant
  Particle.function("fatigueMode", fatigueMode);
  Particle.function("nightSweatMode", nightSweatMode);
  Particle.function("hotFlashesMode", hotFlashesMode);
  Particle.function("setPWM", setPWM);
  
  Serial.begin(115200);
  // Device pin initialization
  pinMode(VIB_MOTOR1_PIN, OUTPUT);
  pinMode(VIB_MOTOR2_PIN, OUTPUT);
  pinMode(VIB_MOTOR_PWM, OUTPUT); 
  pinMode(FAN_PIN, OUTPUT);
  pinMode(PELTIER_PIN, OUTPUT);
  pinMode(TEMP_SENSOR, INPUT);
  pinMode(SWEAT_SENSOR_PIN, INPUT);
  
  delay(DELAY_TIME);
  
  /**making all actuators turn off when the device starts, don't get confused by HIGH for vibration motors,it will turn off since it was
  * due to my mistake while soldering,the polarity of motor got reversed,making motor turn ON when signal is LOW,off when signal is HIGH
  **/
  
  digitalWrite(VIB_MOTOR1_PIN, HIGH);
  digitalWrite(VIB_MOTOR2_PIN, HIGH);
  digitalWrite(FAN_PIN, LOW);
  digitalWrite(PELTIER_PIN, LOW);
  
  delay(DELAY_TIME);
}

// loop() runs over and over again, as quickly as it can execute.
void loop()
{
  // The core of your code will likely live here.
  voltage = analogRead(BATT) * 0.0011224;

  if (fatigue == 1)
  {
    Particle.publish("menf_sensor", (String)'f' + ":" + (String)voltage + ":" + (String) fatigue);
    
    analogWrite(VIB_MOTOR_PWM, pwm);
    
    delay(DELAY_TIME);
  }
  
  else if (nightSweat == 1)
  {
    sweatRate = analogRead(SWEAT_SENSOR_PIN);
    sweatRate = ((sweatRate / 4095.0) * 100.0);  //sweat rate is converted into percent form to make data understanding simple
    
    // mapping the sensor values as sensor gives high analog values for no sweat and low analog values for sweat
    // so to make data more sensible I will send it in a form of %age to dashboard so that greator values means sweating
    sweatRate = mapFloat(sweatRate,0.0,100.0,100.0,0.0);  
    
    if (sweatRate > 28 ) // if person's sweating rate is above 28%
    {
      if(counter == 1)
      {
        ++counter;
        digitalWrite(FAN_PIN, HIGH); // fan  gets activated when the user is perspiring too much making sleep uncomfortable
        previousMillis = millis();
      }
     
    }
    else if(millis() - previousMillis >= FAN_DURATION and counter > 1)
    {
      digitalWrite(FAN_PIN, LOW); // fan gets deactivated after 10 minutes
    }
    else
    {
      digitalWrite(FAN_PIN, LOW); // fan gets deactivated
    }
    
    Particle.publish("menf_sensor", (String)'n' + ":" + (String)voltage + ":" + (String) nightSweat + ":" + (String) sweatRate);
    delay(DELAY_TIME);
  }
  
  else if (hotFlash == 1)
  {
    peltierTemp = temperature();
    Particle.publish("menf_sensor", (String)'h' + ":" + (String)voltage + ":" + (String) hotFlash + ":" + (String) peltierTemp);
    
    if (temperature() > 50.0)   // if peltier hot side temperature is above 50 C    {
      digitalWrite(PELTIER_PIN, LOW);
    }
    
    delay(DELAY_TIME);
  }
  
  else
  {
    // do nothing
  }
  
   
}


int fatigueMode(String command)
{
  /**This function is used to handle the situation in case of muscle fatigue,when user triggers this function it activates vibration motor
     which provides relief over painful areas,actually it is proven medical fact that slight vibration and force movements over painful areas
     reduces the pain sensation.It is more better if accompanied with cold or heat therapy->we might add support for peltier module too here.**/
  if (command == "true")
  {
    Serial.println("Fatigue Mode activated");
    fatigue = 1;         // we will send value 1 on dashboard to track the duration for this symptom
    
    // due to opposite polarity of motors while making connections on pcb made it activated when signal low
    digitalWrite(VIB_MOTOR1_PIN, LOW);
    digitalWrite(VIB_MOTOR2_PIN, LOW);
    return 1;
  }
  else if (command == "false")
  {
    Serial.println("Fatigue Mode de-activated");
    fatigue = 0;
    
    // due to opposite polarity of motors while making connections on pcb made it deactivated when signal high
    digitalWrite(VIB_MOTOR1_PIN, HIGH);
    digitalWrite(VIB_MOTOR2_PIN, HIGH);
    return 0;
  }
  
  else
  {
    // If wrong command is sent the device will be still be safe or in standby mode or in zero state
    standbyMode = true;
    return -1;
  }
}

int nightSweatMode(String command)
{
  /**This function is used to handle the situation in case of night sweats,our custom night sweat detectg sensor logs the sweat analysis on losant
     dashboard which is used to study for signs of any other disease through AI&ML. Also we have provided a threshold method here which activates
     the fan near the user's bed for instant drying and providing comfortness for a healthy and happy sleep.                                   **/
  if (command == "true")
  {
    Serial.println("Night sweats Mode activated");
    nightSweat = 1;        // we will send value 1 on dashboard to track the duration for this symptom 
    ++counter;
    
    return 1;
  }
  else if (command == "false")
  {
    Serial.println("Night sweats Mode de-activated");
    nightSweat = 0;
    counter = 0;
    
    return 0;
  }
  else
  {
    standbyMode = true;
    return -1;
  }
}

int hotFlashesMode(String command)
{
  /** Whenever the user experience hot flushes this method gets activated which brings into action our active gel cooling mechanism
   * which cools the gel and turns on the vibration motor at default pwm to allow user to gently message over her skin surface and let
   * gel cool surface as well as evaporate from the skin surface giving user long lasting 2X cooling effect.
   *  **/
  if (command == "true")
  {
    Serial.println("Hot Flashes Mode activated");
    hotFlash = 1;           // we will send value 1 on dashboard to track the duration for this symptom
    
    // setting pwm signal for vibration motors to 200
    analogWrite(VIB_MOTOR_PWM, 200);
    // due to opposite polarity of motors while making connections on pcb made it activated when signal low
    digitalWrite(VIB_MOTOR1_PIN, LOW);
    digitalWrite(VIB_MOTOR2_PIN, LOW);
    
    // activating the 10mm*10mm,2.8v,0.7A peltier module to cool down the gel to provide instant relief
    digitalWrite(PELTIER_PIN, HIGH);
    return 1;
  }
  
  else if (command == "false")
  {
    Serial.println("Hot Flashes Mode de-activated");
    hotFlash = 0;
    
    // due to opposite polarity of motors while making connections on pcb made it deactivated when signal high
    digitalWrite(VIB_MOTOR1_PIN, HIGH);
    digitalWrite(VIB_MOTOR2_PIN, HIGH);
    
    // deactivating the 10mm*10mm,2.8v,0.7A peltier module ensuring no wastage of energy
    digitalWrite(PELTIER_PIN, LOW);
    return 0;
  }
  else
  {
    standbyMode = true;
    return -1;
  }
}

int setPWM (String command)
{
    pwm = atoi(command);   // convert string payload to integer to be used with motor pwm settings
    return 1;
}

float temperature()
{
  /**This function is used to read the temperature of PELTIER module to prevent it from overheating, it simply ensures that the device does not
     gets damaged due to excess heating. Later on we will compare the current reading with threshold value to limit the current through PELTIER
     or switch it off.**/
  adc_value = analogRead(TEMP_SENSOR);      /* Read Temperature */
  temp = (adc_value * 0.80);	/* Convert adc value to equivalent voltage */
  /* 3.3V/4095= 0.80 */
  temp = (temp/10);            /* LM35 gives output of 10mv/°C */
  
  return temp;
}

MENF Update code: BLE Addition

C/C++
MENF BLE mode for devices social interactivity
/*
 * Project MENF - MEET EVERY NEW FRIEND
 * Description: Solving menopause problems with our Argon powered device
 * Innovation: Active gel cooling technique along with BLE broadcasting and 
 * auto symptoms mode control and symptoms monitoring
 * Author: Sumit @vilaksh
 * Date: 4 May 2020
 */

#include "Particle.h"
#include "MapFloat.h"

// duration for fan 
#define FAN_DURATION (1000 * 60 * 10) // 10 minutes
SerialLogHandler logHandler(LOG_LEVEL_TRACE);
BleUuid serviceUUID("240d5183-819a-4627-9ca9-1aa24df29f18");

void setAdvertisingData();

int VIB_MOTOR1_PIN = 4;
int VIB_MOTOR2_PIN = 6;
int VIB_MOTOR_PWM = 5;
int FAN_PIN = 8;
int PELTIER_PIN = 2;
int SWEAT_SENSOR_PIN = A2;
int TEMP_SENSOR = A5;

int DELAY_TIME = 1000;
int pwm = 200;
int adc_value = 0;
int counter = 0;

unsigned long previousMillis = 0;

float temp = 0.0;
float peltierTemp = 0.0;
float voltage = 0.0;
float sweatRate = 0.0;

int fatigue = 0;
int hotFlash = 0;
int nightSweat = 0;
bool standbyMode = true;

// setup() runs once, when the device is first turned on.
void setup()
{
  // All Particle functions exposed to be used with losant
  Particle.function("fatigueMode", fatigueMode);
  Particle.function("nightSweatMode", nightSweatMode);
  Particle.function("hotFlashesMode", hotFlashesMode);
  Particle.function("setPWM", setPWM);
  
  Serial.begin(115200);
  // Device pin initialization
  pinMode(VIB_MOTOR1_PIN, OUTPUT);
  pinMode(VIB_MOTOR2_PIN, OUTPUT);
  pinMode(VIB_MOTOR_PWM, OUTPUT); 
  pinMode(FAN_PIN, OUTPUT);
  pinMode(PELTIER_PIN, OUTPUT);
  pinMode(TEMP_SENSOR, INPUT);
  pinMode(SWEAT_SENSOR_PIN, INPUT);
  
  delay(DELAY_TIME);
  
  /**making all actuators turn off when the device starts, don't get confused by HIGH for vibration motors,it will turn off since it was
  * due to my mistake while soldering,the polarity of motor got reversed,making motor turn ON when signal is LOW,off when signal is HIGH
  **/
  
  digitalWrite(VIB_MOTOR1_PIN, HIGH);
  digitalWrite(VIB_MOTOR2_PIN, HIGH);
  digitalWrite(FAN_PIN, LOW);
  digitalWrite(PELTIER_PIN, LOW);
  delay(DELAY_TIME);
  
  (void)logHandler; // Does nothing, just to eliminate the unused variable warning
  setAdvertisingData();
  
}

void setAdvertisingData() 
{
    BleAdvertisingData advdata;   // advertsing data buffer object
    
    advdata.appendLocalName("MENF"); 
    advdata.appendServiceUUID(serviceUUID); 
    // Advertise every 1 seconds.
    BLE.setAdvertisingInterval(1600);
    // Continuously advertise
    BLE.advertise(&advdata); 
}

// loop() runs over and over again, as quickly as it can execute.
void loop()
{
  // The core of your code will likely live here.
  voltage = analogRead(BATT) * 0.0011224;

  if (fatigue == 1)
  {
    Particle.publish("menf_sensor", (String)'f' + ":" + (String)voltage + ":" + (String) fatigue);
    
    analogWrite(VIB_MOTOR_PWM, pwm);
    
    delay(DELAY_TIME);
  }
  
  else if (nightSweat == 1)
  {
    sweatRate = analogRead(SWEAT_SENSOR_PIN);
    sweatRate = ((sweatRate / 4095.0) * 100.0);  //sweat rate is converted into percent form to make data understanding simple
    
    // mapping the sensor values as sensor gives high analog values for no sweat and low analog values for sweat
    // so to make data more sensible I will send it in a form of %age to dashboard so that greator values means sweating
    sweatRate = mapFloat(sweatRate,0.0,100.0,100.0,0.0);  
    
    if (sweatRate > 28 ) // if person's sweating rate is above 28%
    {
      if(counter == 1)
      {
        ++counter;
        digitalWrite(FAN_PIN, HIGH); // fan  gets activated when the user is perspiring too much making sleep uncomfortable
        previousMillis = millis();
      }
     
    }
    else if(millis() - previousMillis >= FAN_DURATION and counter > 1)
    {
      digitalWrite(FAN_PIN, LOW); // fan gets deactivated after 10 minutes
    }
    else
    {
      digitalWrite(FAN_PIN, LOW); // fan gets deactivated 
    }
    
    Particle.publish("menf_sensor", (String)'n' + ":" + (String)voltage + ":" + (String) nightSweat + ":" + (String) sweatRate);
    delay(DELAY_TIME);
  }
  
  else if (hotFlash == 1)
  {
    peltierTemp = temperature();
    Particle.publish("menf_sensor", (String)'h' + ":" + (String)voltage + ":" + (String) hotFlash + ":" + (String) peltierTemp);
    
    if (temperature() > 40.0)   // for temp of 40 C there would be atleast 15 C temp difference on both plates, it is just my approximation
    {
      digitalWrite(PELTIER_PIN, LOW);
    }
    
    delay(DELAY_TIME);
  }
  
  else
  {
    
  }
  
   
}


int fatigueMode(String command)
{
  /**This function is used to handle the situation in case of muscle fatigue,when user triggers this function it activates vibration motor
     which provides relief over painful areas,actually it is proven medical fact that slight vibration and force movements over painful areas
     reduces the pain sensation.It is more better if accompanied with cold or heat therapy->we might add support for peltier module too here.**/
  if (command == "true")
  {
    Serial.println("Fatigue Mode activated");
    fatigue = 1;         // we will send value 1 on dashboard to track the duration for this symptom
    
    // due to opposite polarity of motors while making connections on pcb made it activated when signal low
    digitalWrite(VIB_MOTOR1_PIN, LOW);
    digitalWrite(VIB_MOTOR2_PIN, LOW);
    return 1;
  }
  else if (command == "false")
  {
    Serial.println("Fatigue Mode de-activated");
    fatigue = 0;
    
    // due to opposite polarity of motors while making connections on pcb made it deactivated when signal high
    digitalWrite(VIB_MOTOR1_PIN, HIGH);
    digitalWrite(VIB_MOTOR2_PIN, HIGH);
    return 0;
  }
  
  else
  {
    // If wrong command is sent the device will be still be safe or in standby mode or in zero state
    standbyMode = true;
    return -1;
  }
}

int nightSweatMode(String command)
{
  /**This function is used to handle the situation in case of night sweats,our custom night sweat detectg sensor logs the sweat analysis on losant
     dashboard which is used to study for signs of any other disease through AI&ML. Also we have provided a threshold method here which activates
     the fan near the user's bed for instant drying and providing comfortness for a healthy and happy sleep.                                   **/
  if (command == "true")
  {
    Serial.println("Night sweats Mode activated");
    nightSweat = 1;        // we will send value 1 on dashboard to track the duration for this symptom 
    ++counter;
    
    return 1;
  }
  else if (command == "false")
  {
    Serial.println("Night sweats Mode de-activated");
    nightSweat = 0;
    counter = 0;
    
    return 0;
  }
  else
  {
    standbyMode = true;
    return -1;
  }
}

int hotFlashesMode(String command)
{
  /** Whenever the user experience hot flushes this method gets activated which brings into action our active gel cooling mechanism
   * which cools the gel and turns on the vibration motor at default pwm to allow user to gently message over her skin surface and let
   * gel cool surface as well as evaporate from the skin surface giving user long lasting 2X cooling effect.
   *  **/
  if (command == "true")
  {
    Serial.println("Hot Flashes Mode activated");
    hotFlash = 1;           // we will send value 1 on dashboard to track the duration for this symptom
    
    // setting pwm signal for vibration motors to 200
    analogWrite(VIB_MOTOR_PWM, 200);
    // due to opposite polarity of motors while making connections on pcb made it activated when signal low
    digitalWrite(VIB_MOTOR1_PIN, LOW);
    digitalWrite(VIB_MOTOR2_PIN, LOW);
    
    // activating the 10mm*10mm,2.8v,0.7A peltier module to cool down the gel to provide instant relief
    digitalWrite(PELTIER_PIN, HIGH);
    return 1;
  }
  
  else if (command == "false")
  {
    Serial.println("Hot Flashes Mode de-activated");
    hotFlash = 0;
    
    // due to opposite polarity of motors while making connections on pcb made it deactivated when signal high
    digitalWrite(VIB_MOTOR1_PIN, HIGH);
    digitalWrite(VIB_MOTOR2_PIN, HIGH);
    
    // deactivating the 10mm*10mm,2.8v,0.7A peltier module ensuring no wastage of energy
    digitalWrite(PELTIER_PIN, LOW);
    return 0;
  }
  else
  {
    standbyMode = true;
    return -1;
  }
}

int setPWM (String command)
{
    pwm = atoi(command);   // convert string payload to integer to be used with motor pwm settings
    return 1;
}

float temperature()
{
  /**This function is used to read the temperature of PELTIER module to prevent it from overheating, it simply ensures that the device does not
     gets damaged due to excess heating. Later on we will compare the current reading with threshold value to limit the current through PELTIER
     or switch it off.**/
  adc_value = analogRead(TEMP_SENSOR);      /* Read Temperature */
  temp = (adc_value * 0.80);	/* Convert adc value to equivalent voltage */
  /* 3.3V/4095= 0.80 */
  temp = (temp/10);            /* LM35 gives output of 10mv/°C */
  
  return temp;
}

MapFloat.cpp

C/C++
/*
	MapFloat.cpp
	Based on the Arduino Map function but parameters are float
*/


#include "MapFloat.h"

float mapFloat(float value, float fromLow, float fromHigh, float toLow, float toHigh) {
  return (value - fromLow) * (toHigh - toLow) / (fromHigh - fromLow) + toLow; 
}

MapFloat.h

C/C++
/*
	MapFloat.h
	Based on the Arduino Map function but parameters are float
*/


#ifndef MapFloat_h
#define MapFloat_h

float mapFloat(float value, float fromLow, float fromHigh, float toLow, float toHigh);

#endif

Losant function node

JavaScript
Parsing payload to be used for visualizing data in losant dashboard
var parts = payload.data.data.split(':');
// we will be matching symbol send for each mode data at index 0
var s = parts[0];    

// if index 0(var s) contain 'h' it refers to hot flashes data
if(s === 'h')
{
  payload.data.voltage = parts[1];
  payload.data.hotFlash = parts[2];
  payload.data.peltierTemp = parts[3];
}
// if index 0(var s) contain 'n' it refers to night sweats data
if(s === 'n')
{
  payload.data.voltage = parts[1];
  payload.data.nightSweat = parts[2];
  payload.data.sweatRate = parts[3];
}
// if index 0(var s) contain 'f' it refers to fatigue data
if(s ==='f')
{
  payload.data.voltage = parts[1];
  payload.data.fatigue = parts[2];
}

Credits

Sumit Kumar

Sumit Kumar

32 projects • 98 followers
19 y/o. My daily routine involves dealing with electronics, code, distributed storage and cloud APIs.

Comments