Things used in this project

Hardware components:
Om2 2 gccymndjhc
Onion Corporation Omega2
Arduino UNO
Exp dock2 gvzgfrxkxg
Onion Corporation Expansion Dock
SparkFun Temperature Sensor DS18B20
Computer Fan
P9038 r evk top view 0
IDT Qi 5W Transmitter Prototype Kit
Mfg p9025ac r evk
IDT Qi 5W Receiver Prototype Kit
Chip msp frxx fram
Texas Instruments MSP430 Microcontroller
SparkFun Pulse Sensor SEN-11574
Flex Resistors
398 09
Adafruit RGB Backlight LCD - 16x2
Ad5252 i2cpot 100k a 1 600x400
National Control Devices Analog Devices AD5252 Digital Potentiometer 2-Channel 256-Position I2C Mini Module
Circuit Board (generic)
12002 04
Breadboard (generic)
Software apps and online services:
Cinema 4D
Ide web
Arduino IDE
Autodesk EAGLE
Ibm watson avatar pos
IBM Watson
Bluemix logo
IBM BlueMix
Hand tools and fabrication machines:
Ultimaker 3D Printer
09507 01
Soldering iron (generic)
Hy gluegun
Hot glue gun (generic)
Screw driver set (generic)

Custom parts and enclosures

Bladeless Fan Components - 3DS Format
Bladeless Fan - 3DS Format
Pacemaker in Hermetically Sealed Case
A 3-D Model of the Pacemaker in a hermetically sealed case.
Pacemaker enclosure diagram 0aramlawrr
Pacemaker Components
Representing how the various parts of a Pacemaker bundle up into a single, cohesive life-saving machine!
Pacemaker components i8c4utwl3h
Pacemaker Components - 3DS Format


Pacemaker Circuit - Schematic Diagram
This shows the internal circuitry of a Demand Pacemaker.
Pacemaker schematic cjfilu71fv
Pulse Generating Circuit with Vibration Motor
A Breadboard Representation of the Pulse Generating Circuit using a Vibration Motor as Load.
Pulse generating circuit diagram 1nvuemfmwf
Pulse Generating Circuit PCB
Img 2338 yfa3ccv9wb
Pacemaker PCB
Pm pcb design lpufmkwes7
Pacemaker PCB Gerber Files


The file containing main. This is the code I wrote to operate the bladeless fan depending upon the outside temperature as well as the body temperature of the user.
import os
import sys
import json
import oneWire
import geojson
import dateutil.parser
import datetime
import serial
import pytz
import urllib
from temperatureSensor import TemperatureSensor
from omegaMotors import OmegaPwm, hBridgeMotor

# PWM channels for case fan, plus additional channels for H-bridge operation

oneWireGpio = 3 # mark the sensor GPIO

tempMax = 0
tempMin = 0

dutyMax = 0
dutyMin = 0
dutyStep = 0

def calcFanSpeed (temp):

    # restricting the temperature within the operating range.
    if (temp > tempMax):
        temp = tempMax
    if (temp < tempMin):
        return 0

    tempDelta = temp - tempMin

    duty = dutyMin + (dutyStep * float(tempDelta))

    return duty

if __name__ == '__main__':
    dirName = os.path.dirname(os.path.abspath(__file__))
    with open( '/'.join([dirName, 'config.json']) ) as f:
        config = json.load(f)

    dutyMin = float(config['dutyMin'])
    dutyMax = float(config['dutyMax'])

    tempMin = float(config['tempMin'])
    tempMax = float(config['tempMax'])

    dutyStep = (dutyMax - dutyMin)/(tempMax - tempMin )

    fan = OmegaPwm(FAN_PWM_CHANNEL)

    if not oneWire.setupOneWire(str(oneWireGpio)):
        print "Kernel module could not be inserted. Please reboot and try again."


    sensorAddress = oneWire.scanOneAddress()

	# instantiate the temperature sensor object
    sensor = TemperatureSensor("oneWire", { "address": sensorAddress, "gpio": oneWireGpio })
    success = sensor.ready


    if not success:
        print "Sensor was not set up correctly. Please make sure that your sensor is firmly connected to the GPIO specified above and try again."
        # read temp value
        temp1 = sensor.readValue() # body temperature

        dock = serial.Serial(port="/dev/ttyS1", baudrate=57600)
        now ='US/Pacific'))
        print datetime.datetime.strftime(now, "%x")
        #dock.write(datetime.datetime.strftime(now, "%x") + "   |   ")
        weatherUrl = ",-122.1661/forecast"
        response = urllib.urlopen(weatherUrl)
        forecast = geojson.loads(
        summary = forecast["properties"]["periods"]
        for period in summary:
            startTime = dateutil.parser.parse(period['startTime'])
            endTime = dateutil.parser.parse(period['endTime'])
            if ( < endTime) and ( > startTime):
                print str(period["detailedForecast"]) + "\n"
                #dock.write(str(period['detailedForecast']) + "\n")
                temp2 = period["temperature"] # outside temperature
                print temp2
        arduino = serial.Serial(port="/dev/tty.usbserial", baudrate=9600)
        # respond if glovvy sends an input to alter fan speed
        while true:
            choice = arduino.readline()
            if temp1 > temp2:
                duty = calcFanSpeed(temp1 - temp2)
            if choice == "Increase":
                duty += 1
            elif choice == "Decrease":
                duty -= 1
This is the code that runs on the Arduino and reads user input from the flex sensors.
#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
SoftwareSerial SIM900(2, 3);  //rx,tx

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
int timesTosend=1;
int count=0;

void setup() {

  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("Manan’s Smart Glove Project");
  lcd.setCursor(0, 1);
  Serial.begin(9600); //All Serial. commands are for testing purpose only for the developer like you and me
  Serial.println("Hello ");
  SIM900.println("AT+CMGF=1"); //set GSM to text mode

void loop() {
  // the  main code is put here , to run repeatedly:
  Serial.print(" ");
  Serial.println(" ");

  if((analogRead(A0) >= 200 && analogRead(A0) <= 240) && (analogRead(A2) >= 80 && analogRead(A2) <= 120))
       lcd.setCursor(0, 1);
    lcd.print("Food       ");
  SIM900.println("AT+CMGF=1"); //set GSM to text mode
  while (!='>');
    Serial.println("msg sent food");
  SIM900.print("Food Requirement Alert!");  //SMS body
  SIM900.write(0x1A);  // sends ctrl+z end of message
      SIM900.write(0x0D);  // Carriage Return in Hex
  SIM900.write(0x0A);  // Line feed in Hex
  //The 0D0A pair of characters is the signal for the end of a line and beginning of another.
  else if((analogRead(A2) >= 20 && analogRead(A2) <= 70) && (analogRead(A0) >= 160 && analogRead(A0) <= 190))
    lcd.setCursor(0, 1);
    lcd.print("Decrease Speed   ");
    SIM900.println("AT+CMGF=1"); //set GSM to text mode
        SIM900.print("9810115814"); // PUT THE ATTENDANTS PHONE NUMBER HERE 
        while (!='>');
            Serial.println("msg sent medicine");
            SIM900.print("Medicine Requirement Alert!");  //SMS body
            SIM900.write(0x1A);  // sends ctrl+z end of message
            SIM900.write(0x0D);  // Carriage Return in Hex
            SIM900.write(0x0A);  // Line feed in Hex
        //The 0D0A pair of characters is the signal for the end of a line and beginning of another.
  else if((analogRead(A2) >= 80 && analogRead(A2) <= 120) && (analogRead(A0) >= 160 && analogRead(A0) <= 190))
    Serial.println("emergency ");
    lcd.setCursor(0, 1);
    lcd.print("Emergency   ");
    SIM900.println("AT+CMGF=1"); //set GSM to text mode
        while (!='>');
            Serial.println("msg sent emergency");
            SIM900.print("Emergency Alert!");  //SMS body
            SIM900.write(0x1A);  // sends ctrl+z end of message
            SIM900.write(0x0D);  // Carriage Return in Hex
            SIM900.write(0x0A);  // Line feed in Hex
        //The 0D0A pair of characters is the signal for the end of a line and beginning of another.
  else if((analogRead(A0) >= 200 && analogRead(A0) <= 240) && (analogRead(A2) >= 20 && analogRead(A2) <= 70))
    lcd.setCursor(0, 1);
    lcd.print("Increase Speed     ");	
    count = 0;
from OmegaExpansion import pwmExp

__version__ = "0.1"

SERVO_MIN_PULSE = 600  # 600us 	= 0.6ms
SERVO_MAX_PULSE = 2400  # 2400us 	= 2.4ms


class OmegaPwm:
    """Base class for PWM signal"""

    def __init__(self, channel): = channel
        self.frequency = SERVO_FREQUENCY

        # check that pwm-exp has been initialized
        bInit = pwmExp.checkInit()

        if (bInit == 0):
            # initialize the expansion
            ret = pwmExp.driverInit()
            if (ret != 0):
                print 'ERROR: pwm-exp init not successful!'

            # set to default frequency

    def _setFrequency(self, freq):
        """Set frequency of pwm-exp oscillator"""
        self.frequency = freq
        ret = pwmExp.setFrequency(freq);
        if (ret != 0):
            print 'ERROR: pwm-exp setFrequency not successful!'

        return ret

    def getFrequency(self):
        """Get frequency of pwm-exp oscillator"""
        return self.frequency

    def setDutyCycle(self, duty):
        """Set duty cycle for pwm channel"""
        ret = pwmExp.setupDriver(, duty, 0)
        if (ret != 0):
            print 'ERROR: pwm-exp setupDriver not successful!'

        return ret

class DigitalPin:
    """Class that uses PWM signals as 0 or 1"""

    def __init__(self, channel):
        # initialize a pwm channel = channel
        self.pwmDriver = OmegaPwm(

    def set(self, value):
        """Set the PWM signal to either OFF (0%) or ON (100%)"""
        if (value == 0):
            duty = 0
            duty = 100

        ret = self.pwmDriver.setDutyCycle(duty)
        return ret

    def turnOff(self):
        """Set the PWM signal to OFF (0%)"""
        ret = self.set(0)
        return ret

    def turnOn(self):
        """Set the PWM signal to ON (100%)"""
        ret = self.set(100)
        return ret

class Servo:
    """Class that uses PWM signals to drive a servo"""

    def __init__(self, channel, minPulse, maxPulse):
        # initialize a pwm channel = channel
        self.pwmDriver = OmegaPwm(

        # note the min and max pulses (in microseconds)
        self.minPulse = minPulse
        self.maxPulse = maxPulse

        # calculate the total range
        self.range = self.maxPulse - self.minPulse

        # calculate the us / degree
        self.step = self.range / float(180)

        # calculate the period (in us)
        self.period = (1000000 / self.pwmDriver.getFrequency())

        # initialize the min and max angles
        self.minAngle = 0
        self.maxAngle = 180

    def getSettings(self):
        """Return an object with all settings"""
        settings = {}
        settings['channel'] =
        settings['minPulse'] = self.minPulse
        settings['maxPulse'] = self.maxPulse

        settings['range'] = self.range
        settings['step'] = self.step
        settings['period'] = self.period

        settings['minAngle'] = self.minAngle
        settings['maxAngle'] = self.maxAngle

        return settings

    def setupMinAngle(self, angle):
        """Program a minimum angle"""
        self.minAngle = angle

    def setupMaxAngle(self, angle):
        """Program a maximum angle"""
        self.maxAngle = angle

    def setAngle(self, angle):
        """Move the servo to the specified angle"""
        # check against the minimum and maximium angles
        if angle < self.minAngle:
            angle = self.minAngle
        elif angle > self.maxAngle:
            angle = self.maxAngle

        # calculate pulse width for this angle
        pulseWidth = angle * self.step + self.minPulse

        # find the duty cycle percentage of the pulse width
        duty = (pulseWidth * 100) / float(self.period)

        # program the duty cycle
        ret = self.pwmDriver.setDutyCycle(duty)
        return ret

class hBridgeMotor:
    """Class that two digital signals and a pwm signal to control an h-bridge"""

    def __init__(self, pwmChannel, fwdChannel, revChannel):
        # note the channels
        self.pwmChannel = pwmChannel
        self.fwdChannel = fwdChannel
        self.revChannel = revChannel

        # setup the objects
        self.pwmDriver = OmegaPwm(self.pwmChannel)
        self.fwdDriver = DigitalPin(self.fwdChannel)
        self.revDriver = DigitalPin(self.revChannel)

        # setup the limitations
        self.minDuty = 0
        self.maxDuty = 100

    def setupMinDuty(self, duty):
        """Set the minimum allowed duty cycle for pwm"""
        self.minDuty = duty

    def setupMaxDuty(self, duty):
        """Set the maximum allowed duty cycle for pwm"""
        self.maxDuty = duty

    def reset(self):
        """Set the PWM to 0%, disable both h-bridge controls"""
        ret = self.pwmDriver.setDutyCycle(0)
        ret |= self.fwdDriver.turnOff()
        ret |= self.revDriver.turnOff()

        return ret

    def drive(self, direction, duty):
        """Set the PWM to the specified duty, and in the specified direction"""
        ret = 0

        # 0 - forward, 1 - reverse
        if (direction == H_BRIDGE_MOTOR_FORWARD):
        elif (direction == H_BRIDGE_MOTOR_REVERSE):
            ret = -1

        if (ret == 0):
            # check against the minimum and maximium pwm
            if duty < self.minDuty:
                duty = self.minDuty
            elif duty > self.maxDuty:
                duty = self.maxDuty

            # program the duty cycle
            ret = self.pwmDriver.setDutyCycle(duty)
        return ret

    def spinForward(self, duty):
        ret =, duty)
        return ret

    def spinReverse(self, duty):
        ret =, duty)
        return ret
import os
import subprocess
import time

# specify delay duration to be used in the program
setupDelay = 3

# variables to hold filesystem paths
oneWireDir = "/sys/devices/w1_bus_master1"
paths = {
    "slaveCount": oneWireDir + "/w1_master_slave_count",
    "slaves": oneWireDir + "/w1_master_slaves"

## a bunch of functions to be used by the OneWire class
# insert the 1-Wire kernel module
# it's also called a "module", but it's actually software for the Omega's firmware!
def insertKernelModule(gpio):
    argBus = "bus0=0," + gpio + ",0"["insmod", "w1-gpio-custom", argBus])

# check the filesystem to see if 1-Wire is properly setup
def checkFilesystem():
    return os.path.isdir(oneWireDir)

# function to setup the 1-Wire bus
def setupOneWire(gpio):
    # check and retry up to 2 times if the 1-Wire bus has not been set up
    for i in range (2):
        if checkFilesystem():
            return True # exits if the bus is setup
            # no else statement is needed after this return statement

        # tries to insert the module if it's not setup
        # wait for a bit, then check again
        # could not set up 1-Wire on the gpio
        return False

# check that the kernel is detecting slaves
def checkSlaves():
    with open(paths["slaveCount"]) as slaveCountFile:
        slaveCount ="\n")[0]

    if slaveCount == "0":
        # slaves not detected by kernel
        return False
    return True

# check if a given address is registered on the bus
def checkRegistered(address):
    slaveList = scanAddresses()
    registered = False
    for line in slaveList:
        if address in line:
            registered = True
    return registered

# scan addresses of all connected 1-w devices
def scanAddresses():
    if not checkFilesystem():
        return False

    with open(paths["slaves"]) as slaveListFile:
        slaveList ="\n")
        # last element is an empty string due to the split
        del slaveList[-1]
    return slaveList

# use to get the address of a single connected device
def scanOneAddress():
    addresses = scanAddresses()
    return addresses[0]

# class definition for one wire devices
class OneWire:
    def __init__(self, address, gpio=19):      # use gpio 19 by default if not specified
        self.gpio = str(gpio)
        self.address = str(address)
        self.slaveFilePath = oneWireDir + "/" + self.address + "/" + "w1_slave"
        self.setupComplete = self.__prepare()

    # prepare the object
    def __prepare(self):
        # check if the system file exists
        # if not, set it up, then check one more time
        if not setupOneWire(self.gpio):
            print "Could not set up 1-Wire on GPIO " + self.gpio
            return False

        # check if the kernel is recognizing slaves
        if not checkSlaves():
            print "Kernel is not recognizing slaves."
            return False

        # check if this instance's device is properly registered
        if not checkRegistered(self.address):
            # device is not recognized by the kernel
            print "Device is not registered on the bus."
            return False

        # the device has been properly set up
        return True

	# function to read data from the sensor
    def readDevice(self):
        # read from the system file
        with open(self.slaveFilePath) as slave:
            message ="\n")
        	# return an array of each line printed to the terminal
        return message
from oneWire import OneWire

# main class definition
class TemperatureSensor:
    def __init__(self, interface, args):
        self.supportedInterfaces = ["oneWire"]
        self.interface = interface
        self.ready = False

        # if specified interface not supported
        if self.interface not in self.supportedInterfaces:
            print "Unsupported interface."

        # set up a driver based on the interface type
        # you can extend this class by adding more drivers! (eg. serial, I2C, etc)
        if self.interface == "oneWire":
            self.driver = OneWire(args.get("address"), args.get("gpio", None))
            # signal ready status
            self.ready = self.driver.setupComplete
            # match the return value to
            self.readValue = self.__readOneWire;

    def listInterfaces(self):
        print "The supported interfaces are:"
        for interface in self.supportedInterfaces:
            print interface

    # read one-wire devices
    def __readOneWire(self):
        # device typically prints 2 lines, the 2nd line has the temperature sensor at the end
        # eg. a6 01 4b 46 7f ff 0c 10 5c t=26375
        rawValue = self.driver.readDevice()

        # grab the 2nd line, then read the last entry in the line, then get everything after the "=" sign
        value = rawValue[1].split()[-1].split("=")[1]

        # convert value from string to number
        value = int(value)

        # DS18B20 outputs in 1/1000ths of a degree C, so convert to standard units
        value /= 1000.0
        return value

    # add more __read() functions for different interface types later!
    "tempMax" : "40",
    "tempMin" : "18",
    "dutyMin" : "60",
    "dutyMax" : "100",
    "frequency" : "1000",
    "fanType" : "case"


Manan Rai
0 projects • 7 followers


Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback


Sign up / LoginProjectsPlatformsTopicsContestsLiveAppsBetaBlog