This research was conducted as a self-study by three students in the department of Information Science and Culture. As one of them, I participated in the whole process of research and development for 4 months. (July to October, 2016)

The study aims to improve user experiences in CPR training. We set the target user as people who are getting retraining, so that they can be remind on how to conduct CPR more effectively.
It is designed to help participants decide whether the CPR is needed or not in particular situations.
For example, There are three situations: drunken, epilepsy, and cardiac arrest.
Participants should do CPR only when the manikin is on cardiac arrest situation. If he/she does CPR when the manikin is in a drunken or epileptic state, the device will die. Also when the trainee makes a good choice and then does CPR, whether he/she pressed the chest appropriately will be checked (in matters of both depth and speed). In case of success, the manikin will be revived and its face becomes bright with a burst of applause. X)



Components


    CPR manikin, 2 Arduinos, Arduino-music-maker-shield, LED, pressure sensor, speaker


Description


  • LED : is for showing manikin's face color - dark when it is dying, bright when being saved, flushed when revived
  • Pressure sensor : is made up of the velostat(conductive fabric) with foil for covering the area of manikin's chest
  • Sound systems : 3 status of manikin(drunken/epilepsy/cardiac arrest), 2 kinds of 100bpm music during CPR, error sound(died), applause(success)


Design Structure


design structure

Design structure for interactive CPR manikin



  • Pressure Sensor : inside the chest of manikin
  • LED : attached on the cheek of manikin
  • Sound Shield : attached on the Arduino board to play sounds
  • Connect all things : Arduino board, Pressure Sensor, LED and Speaker


circuit image

Arduino circuit image


Installation


installation images

installation pictures


Demonstration


    Storyboard
  1. The user approaches the Manikin.
  2. Listen to the sound of the Manikin,
    determine whether it is epilepsy, dead drunken or cardiac arrest.
  3. If the situation is epileptic or drunken, do not take any action.
  4. If the situation is cardiac arrest, perform CPR 100 times.
  5. Music of 100bpm is played when CPR begins.
  6. Successful CPR would get applause.
  7. If CPR doesn't last more than a few seconds with due to insufficient pressure or strength, get failure with the sound of dead.


    Rehearsal

rehearsal image1&2

rehearsal image3&4

5 conditions of manikin

different face colors according to conditions



  • a. off LED : before the incident / dead
  • b. white : epilepsy
  • c. purple : cardiac arrest
  • d. light red : dead drunk
  • e. strong red : successfully cope with all the situations including CPR




Source Codes


Arduino source code 1: Setting sound systems and the status of manikin

#include "stdio.h"

// Library: SPI, MP3, SD
#include <SPI.h>
#include <Adafruit_VS1053.h>
#include <SD.h>

//LED Library
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

//Set up Library Pins
#define BREAKOUT_RESET  9
#define BREAKOUT_CS     10
#define BREAKOUT_DCS    8
#define SHIELD_RESET  -1
#define SHIELD_CS     7
#define SHIELD_DCS    6
#define CARDCS 4
#define DREQ 3

#define FACE_PIN 2
#define CHEST_PIN 5

#define PRESSURE_PIN A3
#define MANIKINSTATE_PIN A0
#define MANIKINSTATECONFIRM_PIN A1


//Music player shield
Adafruit_VS1053_FilePlayer musicPlayer =
  Adafruit_VS1053_FilePlayer(SHIELD_RESET, SHIELD_CS, SHIELD_DCS, DREQ, CARDCS);

//LED set
Adafruit_NeoPixel point = Adafruit_NeoPixel(2, FACE_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel ring = Adafruit_NeoPixel(24, CHEST_PIN, NEO_GRB + NEO_KHZ800);


//The real status of manikin (setting situations)
boolean started = false;
boolean isHeartAttack = false;
boolean isEpilepsy = false;
boolean isDrunk = false;
boolean inAction = false;

const int STATECOUNT = 3;

// Setting up the status button, LED, speaker, timer and variables of pressure sensor
int manikinState = 0;
int manikinStateConfirm = 0;
int ledColor[3] = {0, 0, 0};
int sound = 0;
int pressure = 0;
int pressCount = 0;
int hotime = 0; // hands-off time
boolean action = false;

boolean startPlay = true;
boolean counthelp = false;
boolean counthelp2 = false;

// Timer
unsigned long startTime = 0;
unsigned long actionTime = 0;
unsigned long timePast = 0;
unsigned long timeCount = 0;


void setup() {

  //Sound
  Serial.begin(9600);
  Serial.println("Adafruit VS1053 Simple Test");
  if (! musicPlayer.begin()) {
    Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
    while (1);
  }
  Serial.println(F("VS1053 found"));

  // sd-card setting
  SD.begin(CARDCS);

  // The lower the numer, the louder the sound
  musicPlayer.setVolume(20, 20);

  // audio playing
  musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT);  // DREQ int

#if defined (__AVR_ATtiny85__)
  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif

  // Pin setup
  pinMode(PRESSURE_PIN, INPUT);
  pinMode(MANIKINSTATE_PIN, INPUT);
  pinMode(MANIKINSTATECONFIRM_PIN, INPUT);

  point.begin();
  point.show();
  ring.begin();
  ring.show();
}

void loop() {
  // Choose initial status
  if (!started) setState();
  if (isHeartAttack) {
    currentState(0);
    if (millis() - startTime > 60000 && !inAction) dead();

    if (takeAction()) {
      inAction = true;
      actionTime = millis();
    }
    if (inAction) {
      musicPlay();
      startPlay = false;
      pressure = readFlex();
      countPress(pressure);

      //Show current state of pressure
      for (int i = ring.numPixels() - 1; i >= 0; i--) {
        ring.setPixelColor(i, ring.Color(0, 0, 0));
        ring.show();
      }
      chestColor(pressure);
      Serial.println(pressCount);
      if (millis() - actionTime > 10000) dead();
      if (pressCount > 30) recovery();
    }
  }
  else if (isEpilepsy) {
    currentState(1);
    if (millis() - startTime > 30000 && !inAction) recovery();
    pressure = readFlex();
    countPress(pressure);
    if (pressCount > 4) hurt();
  }
  else if (isDrunk) {
    currentState(2);
    if (millis() - startTime > 30000 && !inAction) recovery();
    pressure = readFlex();
    countPress(pressure);
    if (pressCount > 4) hurt();
  }
}


Arduino source code 2: Setting the LED color for the face of manikin

  

void currentState(int state) {
  if (state == 0) {//heartattack
    cheekColor(point.Color(127, 0, 127));
    //sound
    if (!inAction && musicPlayer.playingMusic == false) {
      musicPlayer.stopPlaying();
      Serial.println(F("Playing track 005"));
      musicPlayer.startPlayingFile("track005.mp4");
    }
  }
  else if (state == 1) { //epilepsy
    cheekColor(point.Color(127, 127, 127));
    //sound
    if (musicPlayer.playingMusic == false) {
      musicPlayer.stopPlaying();
      Serial.println(F("Playing track 004"));
      musicPlayer.startPlayingFile("track004.mp3");
    }
  }
  else if (state == 2) { //drunk
    cheekColor(point.Color(250, 50, 50));
    //sound
    if (musicPlayer.playingMusic == false) {
      musicPlayer.stopPlaying();
      Serial.println(F("Playing track 003"));
      musicPlayer.startPlayingFile("track003.mp3");
    }
  }
}

void musicPlay() {
  if (musicPlayer.playingMusic == false || startPlay) {
    musicPlayer.stopPlaying();

    Serial.println(F("Playing track 002"));
    musicPlayer.startPlayingFile("track002.mp3");
  }
}

void recovery() {
  cheekColor(point.Color(255, 0, 0));
  //sound
  musicPlayer.stopPlaying();
  Serial.println(F("Playing track 006"));
  musicPlayer.startPlayingFile("track006.mp3");
  reset();

}
void hurt() {
  cheekColor(point.Color(30, 30, 30));
  //sound
  musicPlayer.stopPlaying();
  Serial.println(F("Playing track 007"));
  musicPlayer.startPlayingFile("track007.mp3");
  reset();
}
void dead() {
  cheekColor(point.Color(0, 0, 0));
  //sound
  musicPlayer.stopPlaying();
  Serial.println(F("Playing track 008"));
  musicPlayer.startPlayingFile("track008.mp3");
  reset();
}

void reset() {
  isHeartAttack = false;
  isEpilepsy = false;
  isDrunk = false;
  inAction = false;
  started = false;
  pressCount = 0;
  Serial.println(String(millis()));
  for (int i = ring.numPixels() - 1; i >= 0; i--) {
    ring.setPixelColor(i, ring.Color(0, 0, 0));
    point.setPixelColor(i, point.Color(0,0,0));
  }
  ring.show();
  point.show();
}

void cheekColor(uint32_t c) {
  for (int i = 0; i < point.numPixels(); i++) {
    point.setPixelColor(i, c);
    point.show();
  }
}

void chestColor(int pressure) {
  int converted = map(pressure, 0, 1023, 0, 24);
  //Serial.println("converted:" + String(converted));
  uint16_t i;
  for (i = 0; i < converted; i++) {
    ring.setPixelColor(i, ring.Color(127, 0, 0));
    ring.show();
    delay(1);
  }
}


Arduino source code 3: Setting the pressure sensor of manikin

  

void setState() {
  manikinStateConfirm = analogRead(MANIKINSTATECONFIRM_PIN);
  while (manikinStateConfirm < 500) {
    Serial.println(manikinStateConfirm);
    manikinStateConfirm = analogRead(MANIKINSTATECONFIRM_PIN);
    manikinState = (int) map(analogRead(MANIKINSTATE_PIN), 0, 1024, 0, STATECOUNT);
    Serial.println(manikinState);
  }
  switch (manikinState) {
    case 0: // cardiac arrest true
      isHeartAttack = true;
      break;
    case 1:
      isEpilepsy = true;
      break;
    case 2:
      isDrunk = true;
      break;
  }
  started = true;
  startTime = millis();
  Serial.println(String(startTime));
}

int readFlex() {
  int sensorpin = PRESSURE_PIN;
  int value = analogRead(sensorpin);
  Serial.println("pressure : " + String(value));
  delay(1);
  return value;
}

boolean takeAction() {
  if (readFlex() > 900) {
    action = true;
  }
  else {
    action = false;
  }

  return action;
}

void countPress(int temp) {
  if (temp > 900) counthelp = true;
  if (temp < 500) counthelp2 = true;
  if (counthelp && counthelp2) {
    pressCount++;
    counthelp = false;
    counthelp2 = false;
  }
}


You can see the research report(Korean) here.

Here is our Github repository.