EP02 – Feeding Machine Lifehack

In this episode, I shared the details of the Feeding Machine Lifehack project I posted on Instagram on July 29, 2018.  You can find the link to that post below.



The Problem

My 10 years old son was born with Muscular Dystrophy (MD).  Muscular dystrophy is a disease that causes progressive weakness and loss of muscle mass. A disease that keeps progressing as he gets older. Due to his conditions, he barely gets hungry or eats as much. Because of that, he has lost a lot of weight and became a concern to his Doctor and to us.

To help him with the weight loss problem, his GI Doctor inserted a feeding tube aka (G-Tube) into his stomach. 

feeding tube is a medical device used to provide nutrition to people who cannot obtain nutrition by mouth, are unable to swallow safely, or need nutritional supplementation.

Through that feeding tube is how we feed him extra calories at night while he sleeps. To do that we use a Feeding Machine that pumps the Pediasure formula at a slow rate to prevent upsetting his stomach.

The problem we are facing with this Feeding machine is that when the formula finishes, the beep that it emits is not loud enough to reach across the room.

The Solution

The solution I had in mind was to hack the feeding machine to notify me remotely when it finishes feeding or when there is any problem during the feeding. Such as if the machine gets clogged or if the tube gets twisted from moving around while he sleeps.

Getting these notifications helps us sleep better at night. Because we are able to wake up and disconnect the feeding machine from his G-Tube and not have to worry about feeding him air after the feeding is done.

The Technology

I’m used the following technology to make this project.

What is a light sensor?

A light sensor is an electronic device used to detect light. There are several types of light sensors. The most common ones are the photocell or photoresistor which are very small and changes its resistance when light shines on it.

A light sensor may be part of a safety or security device like a garage door opener or a burglary alarm. These devices often work by shining a beam of light from one sensor to another. If this light is interrupted, the garage door won’t close or the alarm will sound.

Several modern electronics, including TV’s, computers and wireless phones use ambient light sensors in order to automatically control the brightness of a screen in situations where light intensity is high or low. These light sensors can detect the amount of light in a room and raise or lower the brightness to a more comfortable level.

Light sensors can also be used in order to automatically turn on lights outside or inside a business or a home at night. 

The Challenges

  • The biggest challenge I faced was hot glueing the light sensor to the Feeding Machine. Because this machine is rented and sometimes we get it replaced a few times. The very next day of completing this project the machine stopped working and the company replaced it with a much bigger version.
  • The other challenge is the fact that this project relies on Wifi to work. In a future version I’m going to change it to use the NRF24L01 modules which doesn’t require internet to work.

Total Cost

  • I think I spent a total of $60 including shipping from different vendors

Photos

The Arduino Source Code

/*
 *  This sketch sends data via HTTP GET requests to data.sparkfun.com service.
 *
 *  You need to get streamId and privateKey at data.sparkfun.com and paste them
 *  below. Or just customize this script to talk to other HTTP servers.
 *
 */

#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include "Timer.h"

Timer t;
const int internalLedPin = 0;         // LED pin 0
const int ledPin =  15;         // LED pin 15
const int buzzerPin = 12;      // Piezo Buzzer pin 12
const int stopButtonPin = 13;  // pushbutton pin 15
unsigned long previousMillis = 0;
const long interval = 1000;
const unsigned long alarmDelayInterval = 300000; // 5 minutes in milliseconds
int ledState = LOW;
bool triggerAlarm = false;
int stopButtonState;

// Wifi Info:
const char* ssid     = "YOUR_WIFI_NETWORK_NAME";
const char* password = "YOUR_WIFI_PASSWORD";

// API Info
const char* host = "api.thingspeak.com";
unsigned long previousEntryID = 0;
const long readingInterval = 30000; //30 seconds, in milliseconds

void stopBeep() {
  digitalWrite(buzzerPin, LOW);       // 0 turns it off
  digitalWrite(ledPin, LOW);

  Serial.println("Stopping the alarm");
}

void beep(unsigned char delayms){

  Serial.println("Beep");
  
  digitalWrite(buzzerPin, HIGH);
  delay(delayms);          // wait for a delayms ms
  digitalWrite(buzzerPin, LOW);       // 0 turns it off
  delay(delayms);          // wait for a delayms ms   

}  

void getRemoteData() {

  Serial.print("connecting to ");
  Serial.println(host);
  
  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }
  
  // We now create a URI for the request
  String url = "/channels/78255/feeds/last.json?api_key=YOUR_THINGSPEAK_API_KEY&timezone=America%2FNew_York";
  
  Serial.print("Requesting URL: ");
  Serial.println(url);
  
  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
  delay(10);
  
  // Read all the lines of the reply from server and print them to Serial
  String response = "";
  bool begin = false;
  while(client.available() || !begin){
    char in = client.read();

    if (in == '{') {
        begin = true;
    }

    if (begin) response += (in);

    if (in == '}') {
        break;
    }

    delay(1);
  }

  StaticJsonBuffer<200> jsonBuffer;
  JsonObject& root = jsonBuffer.parseObject(response);
  const unsigned long entry_id = root["entry_id"];
  const float sensor_value = root["field1"];

  if (previousEntryID != entry_id && sensor_value > 0.05) {
    Serial.println("We got a new ID, ring the alarm");

    // set the alart to true and the next loop cycle it will beep.
    triggerAlarm = true;
    
    previousEntryID = entry_id;
  } 
  
  Serial.println(entry_id);
  Serial.println(sensor_value);
  Serial.println();
  Serial.println("closing connection");
}


void setup() {
  
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);
  pinMode(internalLedPin, OUTPUT);
  pinMode(stopButtonPin, INPUT_PULLUP);
  pinMode(buzzerPin, OUTPUT);
  
  Serial.begin(115200);
  delay(10);

  // We start by connecting to a WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  t.every(readingInterval, getRemoteData);
  getRemoteData();
}

void loop() {
  t.update();

  digitalWrite(internalLedPin, LOW);
  
  stopButtonState = digitalRead(stopButtonPin);
  delay(100);
  if (stopButtonState == LOW) {
     Serial.println("Pressing Button");
     
     if (triggerAlarm == true) {
       // Stop the buzzer sound
       // Turn off LED
       stopBeep();
       triggerAlarm = false;

       // Let's delay for 5 minutes while we turn the feeding machine off.
       digitalWrite(internalLedPin, HIGH);
       delay(alarmDelayInterval);
     }
  }

  if (triggerAlarm == true) {
    unsigned long currentMillis = millis();
    while (currentMillis - previousMillis >= interval) {
        // save the last time you blinked the LED
        previousMillis = currentMillis;
  
        if (ledState == LOW) {
          ledState = HIGH;
        } else {
          ledState = LOW;
        }
        // set the LED with the ledState of the variable:
        digitalWrite(ledPin, ledState);
  
        // trigger the buzzer
        beep(500);
  
        Serial.println("Alarm triggered");
    }
  }
}

The Electric Imp Source Code

Agent.nut

local thingSpeakUrl = "http://api.thingspeak.com/update";

local headers = {
  "Content-Type" : "application/x-www-form-urlencoded",
  "X-THINGSPEAKAPIKEY" : "YOUR_THINGSPEAK_API_KEY"
};

local field = "field1";

function httpPostToThingSpeak (data) {
  local request = http.post(thingSpeakUrl, headers, data);
  local response = request.sendsync();
  return response;
}
 
device.on("sendAnalogInput", function(analog_value) {
    if (analog_value > 0) {
        local response =  httpPostToThingSpeak(field+"="+analog_value);
        server.log(response.body);
    } else {
        server.log("Skipping because value is less than 0");
    }
});

Device.nut

// initialize pins
local light_sensor = hardware.pin8;
light_sensor.configure(ANALOG_IN);

// function returns voltage from pin
function getSensor() {
    server.log("getting light");
    local supplyVoltage = hardware.voltage();
    local voltage = supplyVoltage * light_sensor.read() / 65535.0;
    return (voltage);
}

// Send Sensor Data to be plotted
function sendDataToAgent() {
    local sensor_voltage = getSensor();

    server.log(sensor_voltage);

    agent.send("sendAnalogInput", sensor_voltage);
}


// Initialize Loop
imp.onidle(function() {
  sendDataToAgent();
  server.sleepfor(30);
});