Project tutorial
Helping the Disabled and Chronic Patients battle the heat

Helping the Disabled and Chronic Patients battle the heat © CC BY-NC-ND

Heat brings along challenges for the differently-abled. Let's build a bladeless fan, wireless pacemaker and communication aid to help them!

  • 14 respects

Components and supplies

Necessary tools and machines

Ultimaker 3D Printer
09507 01
Soldering iron (generic)
Hy gluegun
Hot glue gun (generic)
Screw driver set (generic)

Apps and online services

Cinema 4D
Ide web
Arduino IDE
Autodesk EAGLE
Ibm watson avatar pos
IBM Watson
Bluemix logo
IBM BlueMix

About this project


As technology makes rapid strides in all spheres of everyday life, there arises the enduring demand for health-care aids, preventive technologies and monitoring devices that are not only accurate, but also efficient.

Nearly 800,000 people in the United States suffer a stroke every year. Researches have shown that increased temperature tends to increase the risk of a stroke, whereas hypothermia, or reduced temperature, reduces the risk. Of course, the 21st century poses no lack of facilities to battle heat. But throw in financial constrain, and Air Conditioners get ruled out. What's more is that table fans are increasingly difficult to use, as the movement of and the noise from fan blades can lead to headaches.

Talking about bio-sensors and bio-devices, many of them today are implantable, which means that they are embedded inside the body of the subject. Understandably, then, arises the question of powering such devices. The answer: Wireless Charging. The problem then is being able to access their monitored data to track the patient's progress. An important example is that of Pacemakers. As the heat peaks during the summer, our hearts need to work harder to supply adequate oxygen to all body cells. For people relying on Pacemakers, this is a time when they need to be all the more careful.

Another important problem is faced during this part of the year by people who are disabled or partially-paralysed. Patients suffering from developmental disabilities also find their ability to communicate robbed from them. How, then, do they interact with these aids. From very basic functions like raising the fan speed, to more imperative tasks like updating their caregivers as to their conditions, such people need more advanced technologies to help ease their lives.


This project attempts to solve these problems by invoking the exceptional facilities of the Internet of Things, tapped into using the Onion Omega2 and the Arduino UNO.

The project can be divided into 3 parts:

  • Designing a Bladeless Fan to provide seamless cooling to stroke patients
  • Imparting Wireless Charging Capabilities to Pacemakers and tracking the readings using IBM Watson
  • Building a Communication Aid "Glovvy" for the partially-paralysed that can interface with the Bladeless Fan, and also send SOS messages to caregivers

Part 1 : Bladeless Fan

The standard fans are also hardly as effective as their modern alternatives -- Bladeless Fans. First created by Dyson, bladeless fans have caught the fancy of the masses.

This project instructs the creation of a bladeless fan to help stroke patients combat the heat. Although this won't be as seamless as those commercially produced by Dyson, it comes at a small fraction of the cost.


Bladeless Fans are not entirely "bladeless", and a more accurate connotation is calling them "Air Multipliers".

They possess a tube containing a fan with misaligned wings, that pulls outside air into the tube. This is led into an airfoil-shaped duct within a torus.

Just like the functioning of an airplane, the process creates a difference in air pressures across the fan. This leads to air gushing forward, out of the fan, at a high speed.

In fact, Dyson claims that their fans can pull in up to 5.28 gallons of air per second!

Step 1: Designing the Bladeless Fan

The model is designed on Cinema 4D, although you can also use Autodesk Fusion 360.

The fan has 3 parts -- the tube (with holes for air flow) that holds the fan, an outer torus into which the tube slides, and an inner torus that fits into the outer one while leaving a duct for air flow.

Make sure to accurately measure the dimension of the fan and construct the tube accordingly.

Step 2: Printing

Print the parts, preferably on a hot bed. The simple design should give minimal problem, and once done, ensure that the parts slide in and out of their designed cavities with ease.

Step 3: Preparing the Fan

The recycled computer fan probably has a rectangular case bordering the fan. Unscrew this case and expose the fan. Now fit the fan base-first inside the printed tube.

After ensuring that the fan blades can rotate freely inside the tube, secure the fan using a hot glue gun.

Step 4: Connect the Fan to the Omega2+

Connect the PWM Expansion to the Dock. Now make the following setup:

  • The red wire of the fan is connected to the VCC
  • The black wire of the fan is connected to the transistor's collector
  • Connect the transistor's base to the PWM Expansions's SIGNAL pin through a resistor
  • Ground the transistor's emitter
  • Connect a capacitor across the fan's terminals

Step 5: Temperature Sensing

The DS18B20 has 3 pins. Connect it in the following way:

  • Connect its VDD to a 3.3V pin on the Expansion
  • Connect its DQ to GP101
  • Connect it GND to the Expansion's Ground
  • Connect the VDD and DQ pins through a 5.1kΩ resistor

Step 6: The Code

Now we use code to bring the electronics to life. We use a Python script, which uses web request to get weather data of the region, especially the temperature. We also read the user's body temperature through the temperature sensor.

For a considerable difference in the body temperature vis-a-vis the environment temperature, the fan runs at a speed proportional to the difference, thereby creating an air conditioning effect.

Part 2: Monitoring the Data from a Pacemaker, made wireless

Pacemakers are used to control abnormal heart-beating rhythms. They are implanted in the chest or abdomen.

Wireless Charging would improve the life of the device, thereby reducing the need for replacing the existing device, which not only poses a risk due to surgery, but also creates additional bio-waste. Keeping the battery of the device fully charged would also result in an increased efficiency of the device.

Apart from attempting this, we will also monitor the data logged by the pacemaker using IBM Watson's IoT interface Bluemix.

How a Pacemaker Works

We deal with a Demand Pacemaker, which provides electrical heart-stimulating pulses only in the absence of natural heartbeat. When it was introduced in 1964, the Demand Pacemaker offered significant advantage over the previously-used pacing devices, which delivered a fixed-rate pulse, thus competing with natural heartbeat and sometimes inducing ventricular fibrillation. The Demand Pacemaker also prolongs battery life because it is only activated when pacing stimuli are needed.

The Demand Pacemaker, connected to the IDT Wireless Power Receiver Board P9025AC-R-EVK, is shown in Schematic Form.

The Pacemaker's PCB Layout is shown.

Note that junctions J1 and J2 connect to the terminals of the P9025AC-R-EVK Receiver board, while the junction J3 leads to the electrodes implanted in the heart.

The Sense Amplifier amplifies and normalizes the cardiac signal. It lets out undesired signals like the P and T waves and 60 Hz stray signals. Q1 and Q2 are Class A amplifiers. AC signals at the collector of Q2 are coupled with capacitor C8 to momentarily turn on Q3, which is the Timing Capcitor (C8) discharge switch.

The Sense Amplifier incorporates a bandpass filter with a bandwidth of 20-30 Hz that limits the low frequency response of the detecting circuit to discriminate against the P and T waves and any other frequencies below 20 Hz.

When the Pacemaker is required to operate in demand mode, each pulse transmitted through capacitor C5 to the base of transistor Q3 causes the transistor to conduct. Capacitor C8 discharges through the collector–emitter circuit of the transistor. In this case, the timing cycle is interrupted and the junction of capacitor C8 and resistor R3 does not increase in potential to the point where transistors Q4 and Q5 are triggered to conduction. After capacitor C8 discharges through transistor Q3, the transistor turns off. The capacitor then starts charging once again and the new cycle begins immediately after the occurrence of the last heartbeat.

Making a Pacemaker Wireless

Since a Pacemaker is not easily available (a condemned machine is officially a bio-hazard) and is fairly expensive, we recreate here the most integral component of a Pacemaker: its Pulse Generating Circuit.

A pulse generating circuit has to deliver electrical pulses at regular intervals of time. Such a circuit can be created as follows.

Step 1: Ready your Supplies!

What you'll need for this is an NE 555 made by Texas Instruments, an LED bulb, a 0.01 μF Capacitor, a 10 μF Capacitor, a 330 Ω Resistor, a 270 kΩ Resistor, a 33 kΩ Resistor, a breadboard and plenty of jumper wires. You'll also need a power source, which includes the IDT P9038-R-EVK - Qi 5W Transmitter and the IDT P9025AC-R-EVK - Qi 5W Receiver.

Step 2: Ready the Working Circuit

Connect the NE 555 to the breadboard. Note the orientation of the small IC using the notch at the top.

(A) NE 555 IC and Receiver Board

Connect the Receiver board's OUT point to the NE 555's Power (8) and Reset (4) pins. Connect the Receiver's GND- terminal to the NE 555's Ground (1). Now connect the 0.01 μF Capacitor between the Ground (1) and Trigger (2) pins of the NE 555. This helps in regulating power flow into the IC and the initiation of the circuit.

(B) Resistors

Now connect the 270 kΩ Resistor between the +VCC (8) and Discharge (7) pins and the 33 kΩ Resistor between the Discharge (7) and Threshold (6) pins. Since I only had 90 kΩ and 22 kΩ resistors, I connected 3 90 kΩ resistors in series and a parallel combination of two 22 kΩ resistors in series with another 22 kΩ resistor to get the desired resistances.

(C) Capacitor

Next take the 10 μF capacitor; connect its positive terminal to the NE 555's Control Voltage (5) point and its negative terminal to the power sources ground terminal.

(D) LED Bulb

On this connection, attach a 330 Ω resistor which is connected to the negative terminal of the LED bulb. Connect the bulb's positive terminal to the NE 555's Output (3) pin.

The PCB design of the Pulse Generating Circuit is shown for reference.

Note that the magnitudes (values) of C1, R1 and R2 need to be chosen according to the time period of periodicity of the pulse (or equivalently its frequency). Get a conversion chart here.

Step 3: Ready the Powering Mechanism

Now get hold of the amazing Transmitter Board, and plug it in through its Mini USB. As current flutters in through its coil, a green and a red light should come to life atop the board. Now take the Receiver Board close to the Transmitter. At the correct relative orientation of and distance between the two boards, an induction current would be set on in the Receiver's coil, thereby lighting an LED on board. To test this or learn more, see this. Note that the green light on the Transmitter begins to blink and the red light goes off. Phew!

Your LED in the pulsating circuit should now begin to blink.

A device that closely matches the functioning of a pacemaker and heart is a vibration motor, which can be operated using the Pulse Generating Circuit in place of the LED.

The SparkFun Vibration Motor used here vibrates periodically with a time period of 2 seconds given the resistances and capacitance used.

Step 4: Packing the Pacemaker

The Pacemaker is enclosed in a hermetically sealed case. A 3D Model of the Pacemaker and how the various components fit in is given below.

Earlier, the pacemaker needed to be replaced surgically when the battery run out. With wireless charging, the painstaking and risky process is no longer required!

Step 5: Testing

In order to test the working of the system, take the Pulse Generator (with LED) and fasten it inside your shirt. Make sure to keep the back side of the Receiver board PCB away from the body. If the board is kept the other way around, then the insulating sticker on top of the receiver coil would prevent any induction from occurring.

Now connect the Transmitter board to a power source and bring it close to the circuit. Recall the correct orientation of the two coils that we had studied earlier. When the coils are placed correctly, the LED should blink.

Step 6: Monitoring the Data

The values of vibration frequency of the pulse generating circuit can be tracked using IBM Watson.

In order to setup an IoT Platform Organisation (the first step if you are new), refer to the instructions here.

Once you are done, you will have your device ready. Now you can build cards -- charts that will display the data that your device sends to Watson. This is a way of analysing the data without any programming.

You can also use conditional constructs to send alerts. These are called actions. Go ahead and add an action to send an Emergency Alert in case the vibration values cross a certain threshold.

Part 3: Glovvy - a Communication Aid for the Partially-Paralysed

Over 100 million people in the world cannot speak because of a developmental disability or a speech-related disorder. Such people rely on technological developments that enable them to lead normal lives.

Glovvy is an aid to allow the partially-paralysed to utilize hand or feet movements in order to communicate. Particular series of movements are translated into specific words or requirements, which can be expressed seamlessly with Glovvy.

The Flex Sensors

Glovvy consists of flex resistors whose resistance varies as the flex resistance is bent. The Flex Sensor technology is based on resistive carbon elements. As a variable printed resistor, the Flex Sensor achieves great form-factor on a thin flexible substrate. When the substrate is bent, the sensor produces a resistance output correlated to the bend radius—the smaller the radius, the higher the resistance value.

The basic circuit consists of a fixed resistor in series with a variable resistor (Flex sensor) causing the voltage between the two to vary when a fix voltage is given to the combination. The flex sensor/resistance acts as a voltage divider and causes V(out) to vary as the same is bent. V(out) is detected and converted to a digital value, which then displays the information/message that the patient wants to convey according to the following table.


LCDs have a parallel interface, so the microcontroller has to manipulate several interface pins at once to control the display. The interface consists of the following pins:

  • A register select (RS) pin that controls where in the LCD's memory we're writing data to. We can select either the data register, which holds what goes on the screen, or an instruction register, which is where the LCD's controller looks for instructions on what to do next.
  • A Read/Write (R/W) pin that selects reading mode or writing mode
  • An Enable pin that enables writing to the registers
  • 8 data pins (D0 -D7). The states of these pins (high or low) are the bits that we're writing to a register when we write, or the values we're reading when we read.

There's also a display constrast pin (Vo), power supply pins (+5V and Gnd) and LED Backlight (Bklt+ and BKlt-) pins that we can use to power the LCD, control the display contrast, and turn on and off the LED backlight, respectively.

The process of controlling the display involves input of image forming data into the data registers, and further input of instructions to the instruction register. The Liquid Crystal Library simplifies this for us so we don't need to know the low-level instructions.

The Hitachi-compatible LCD used in my case can be controlled in two modes: 4-bit or 8-bit. The 4-bit mode requires seven I/O pins from the Arduino, while the 8-bit mode requires 11 pins. For displaying text on the screen, we can do almost everything in 4-bit mode.

Step 1: Flex Sensors

The flex sensors are mounted in a glove worn by the patient. Two flex sensors are attached to the index and the middle fingers of the glove.

Each sensor is connected in series with a 1K resistance. Each combination of flex sensor and 1K resistor is connected to a DC power source. Each of these then give input to the Arduino at A0 and A2 pins.

Step 2: LCD

The microcontroller is given +5V Power and the ground pin of the same is connected to Ground. The digital-out from the Arduino (Pins no. D8-D12) is fed to the digital-in (Pins DB4-DB7) of the LCD.

The 'LED -' pin of LCD is grounded and 'LED +' Pin of the LCD is given +5V. The Rx and Tx of the GSM module are connected to the Tx and Rx of the microcontroller respectively.

A potentiometer (10K) is attached in series with the LCD Pin V(ee) to control the brightness of the LCD (Back light brightness).

Step 3: Code

Note that this process involves understanding the flex sensors, because different sensors return different values when bent to the same level.

The Arduino IDE is used to program the microcontroller which then displays the particular message for a particular range of V(out) on the LCD. At the same time, a message is sent to a predefined mobile number to the attendant in case of an emergency message. Otherwise, this is used to vary the speed of the bladeless fan.

As the flex sensor is bent, the resistance of the flex sensor is changes. Thus if a constant voltage is applied to the combination of a fixed resistance (1K) and the flex sensor, as the sensor bends the total resistance of the combination keeps on changing thereby changing the voltage at the junction between the two resistors. A particular voltage at the analogue pins of the Arduino will result in a particular binary code in the internal registers of the microcontroller. In the software code, a particular range of this binary code is assigned to a pre-defined output displayed on the LCD, e.g. when the V(out) is half of V(in) on bending the flex sensor, the LCD displays “Increasing Speed”, and the corresponding message is passed to the Omega2.

The patient is expected to bend his/her finger(s), keeping them either half-bent or fully-bent. Thus for each finger there will be two resistance values which are cnsidered in the project. For this prototype, I programmed for the fully-bent state of each finger. I also utilized the event when the patient will bend more than one finger at any given time (for example clinching the fist). The three events were then programmed to mean -- increase speed, decrease speed and emergency. It may be noted that using 5 sensors, 31 events can be programmed considering only one bent state for each finger.


Thus we have achieved our engineering goals. We have built a communication aid for the partially-paralysed that utilises an Arduino docked to the Omega2. It can also alter the speed of a unique Bladeless Fan that we built to help stroke patients battle the heat. The fan otherwise uses web requests to calculate the region's temperature, compares it with the user's body temperature, and conditions the air accordingly. We also took an essential implantable bio-device -- the pacemaker -- and added wireless charging capabilities to it. We also used the IBM Watson IoT Interface to wirelessly track the number of vibrations the pacemaker needed to make to supplement the heart's natural rhythms, so that the patient's condition can be monitored regularly and seamlessly.

If you have followed through and completed the entire project, heartiest congratulations! The essential condition to be a good samaritan is to use one's own skills for the benefit of others. And by completing this project, you have created a combination of three aids that hold the potential to greatly improve the lives of those who rely on aids to lead equal lives.


The Omega2+ Project Book (Vol. 1) is an excellent resource to learn more about using the wonderful computer-on-a-chip and helped me through this project! A must read for Omega2+ developers.

The IBM Developer recipes are extensive in their dealings of IBM Watson and were of great help.

Occasionally throughout the project, forums and communities like Hackster, StackOverflow and Instructables proved to be of great help in debugging.


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"

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


Similar projects you might like

Connected Weight Scale Using Sigfox

Project in progress by Polytech Sorbonne - EISE5 - Levert, Maury, Rosanne

  • 4 respects

Wi-Fi RC Car - Qi Enabled

Project tutorial by Ioannis Kydonis

  • 32 respects

Laser Pointer Panther Tank

Project tutorial by Arduino “having11” Guy

  • 1 comment
  • 12 respects

Remote Lamp

Project tutorial by Kutluhan Aktar

  • 7 respects

Binary Wristwatch

Project showcase by thallia

  • 9 respects
Add projectSign up / Login