Bryant Patten
Published © CC BY

Is Mom Okay?

A project that allows you to check on the status of an aging friend or family member which respects their privacy.

IntermediateFull instructions provided6 hours2,285
Is Mom Okay?

Things used in this project

Hardware components

Hologram Nova
Hologram Nova
×1
Raspberry Pi Zero Wireless
Raspberry Pi Zero Wireless
×1
SparkFun Non-Invasive Current Sensor - 30A
×1
SparkFun TRRS 3.5mm Jack Breakout
×1
Adafruit ADS1115 16-Bit ADC
×1
Breadboard (generic)
Breadboard (generic)
The number of breadboards depends upon the number of subscribing circuits. This projects has two. You must have at least one publishing circuit.
×3
Photon
Particle Photon
The photons are used in the subscribing circuits. You could also build subscribing circuits with raspberry pi units and Nova hologram modems.
×2
Adafruit Controllable Four Outlet Power Relay Module version 2 - (Power Switch Tail Alternative)
This is an optional item. Useful if you want to use a plug in device for the subscribing device.
×1
SparkFun LED - RGB Diffused Common Cathode
Any LED will work. Used multicolor for future expansion
×1
LED (generic)
LED (generic)
×1
Resistor 100 ohm
Resistor 100 ohm
×1
Resistor 10k ohm
Resistor 10k ohm
×2
Resistor 330 ohm
Resistor 330 ohm
×4

Story

Read more

Schematics

Publishing Device

This is the center of the project. The Hologram Nova is plugged into the Pi Zero shown in this diagram. Thanks to Shawn Hymel for current sensing circuit.

AIP_Receiver_V1

This is the device which allows the remote care giver have a 120V / wall plug device mimic the device in the elderly person's home

AIP_Receiver_V2

This is a simple device to show the status of the remote device.

AIP Test App Code

This is the code used in the AIP Test App built with App Inventor

Code

AIP_V5.py

Python
This is the main publishing code running on the Raspberry Pi Zero W
import math
import time
import sys
import RPi.GPIO as GPIO


from Hologram.HologramCloud import HologramCloud


# Import the ADS1x15 module.
import Adafruit_ADS1x15


def AIP_Begin():
    print ("Beginning")
    global toggleCount
    global deviceOn
    global refCurrent
    global adc
    global statusLED
    global wildVariance

    
    statusLED = 19
    toggleCount = 0
    deviceOn = False
    # if the device is off, the current value shouldn't vary by more than 2 or 3, so 12 is big enough
    wildVariance = 12


    GPIO.setmode(GPIO.BCM)
    GPIO.setup(statusLED,GPIO.OUT)


    # Create an ADS1115 ADC (16-bit) instance.
    adc = Adafruit_ADS1x15.ADS1115()

    # For this use, we only need to know if current is flowing - not the actual value
    # So we assume the device is off on boot so the current fluctation is minimal.
    # This will allow us to obtain a base or reference voltage that we will use to
    #  determine when the device is switched on.
    tempVarianceCounter = 0
    # Read the value of the current sensor and set it as the reference voltage - assume device is shut off
    refCurrent = adc.read_adc(0, 1)
    
    #now check that the device is shut off.  If there is wild variance in the current
    #  then the device is on.  If that is true, tell the user and exit the program
    for x in range (0,100):
        
        instantCurrent = adc.read_adc(0, 1)
        
        if abs(instantCurrent - refCurrent) > wildVariance :
            toggleCount += 1


    if toggleCount > 10 :
        print("is the device on already?!")
        AIP_End()
    else:
        print("The reference current is %d" % refCurrent)
        time.sleep(3)


def AIP_End():
    print("Ending")
    GPIO.cleanup()
    sys.exit()
    
def AIP_Main():
    global toggleCount
    global deviceOn
    global refCurrent
    global wildVariance


    try:
        while True:
            #  We need to have a delay so we don't overun the ADC1115 sampling
            time.sleep(0.1)
            # Read ADC
            sample = adc.read_adc(0, 1)
            # Check to see if there is a big variation in current (device running)
            if (abs(sample - refCurrent) > wildVariance ):
                # Now check to see if device has changed state
                # if state is OFF then variance should be minimal.  If that is not the case, device has been turned on
                if (deviceOn == False):
                    toggleCount += 1
                    # if this variance has happened 10x, let's take action
                    if (toggleCount > 10):
                        deviceOn = True
                        toggleCount = 0
                        AIP_SendMessage(1)
                        
                else:
                    # This code resets the counter so small variations don't accumulate over time
                    if toggleCount > 0 :
                        toggleCount -= 1
            # Now check for the flip side -> we are expecting variance since device is ON but no variance detected
            elif (deviceOn == True):  # check to see if the device has been turned off
                    toggleCount += 1
                    if (toggleCount > 10):
                        deviceOn = False
                        toggleCount = 0
                        AIP_SendMessage(0) 
                        
            else:
                if toggleCount > 0 :
                    toggleCount -= 1

    # This is how we exit the program
    except KeyboardInterrupt:
        AIP_End()
                        
def AIP_SendMessage(message) :
    # Here is the heart of the program.  If there is a change in state, publish that message.
    # Because of some configuration bug, the Route is not sending data so it sends two types of messages
    # Ideally it would send only a single message with different data to represent state...oh well
    hologram = HologramCloud(dict(), network = 'cellular')
    
    if (message == 1):
        GPIO.output(statusLED,GPIO.HIGH)
        recv = hologram.sendMessage("1", topics = ['AIP_V2'],timeout =3)
        print("Switched ON")
    else:
        GPIO.output(statusLED,GPIO.LOW)
        recv = hologram.sendMessage("0", topics = ['AIP_V1'],timeout =3)
        print("Switched OFF")
        

    
#run the program
AIP_Begin()
AIP_Main()

AIP Receiver code V1

Arduino
This code runs on a Particle.io photon attached to an Internet Relay. It assumes a working WiFi connectin
//This is the receiver code for the Aging In Place (AIP) Version 1
// BMP 2018-1-01
// This code supports turning on or off an appliance plugged into an IoT Power Relay (https://www.sparkfun.com/products/14236)
// It uses the Particle.io cloud and subscribes to two events  AIP_V1 and AIP_V2
// I added a second event that just turns on the device to deal with certain cases where data wasn't being passed properly.

int OnBoardLED = D7;
int ActivateRelay = D1;


void setup() {

    pinMode(OnBoardLED, OUTPUT);
    pinMode(ActivateRelay, OUTPUT);

    Particle.subscribe("AIP_V1",AIP_V1_Respond);
    Particle.subscribe("AIP_V2",AIP_V2_Respond);


}

void loop() {

}

void AIP_V1_Respond(const char *event, const char *data){
    int curData;
    
    curData = atoi(data);
    switch (curData)
    {
        case 0:
            digitalWrite(OnBoardLED, LOW);
            digitalWrite(ActivateRelay, LOW);
            break;
        case 1:
            digitalWrite(OnBoardLED, HIGH);
            digitalWrite(ActivateRelay, HIGH);
            break;
     
        default:
            digitalWrite(OnBoardLED, LOW);
            digitalWrite(ActivateRelay, LOW);
            break;
     
    } 
    
}

void AIP_V2_Respond(const char *event, const char *data){
    int curData;

            digitalWrite(OnBoardLED, HIGH);
            digitalWrite(ActivateRelay, HIGH);

}

AIP Receiver Code V2

Arduino
This code controls an RGB LED.
//This is the receiver code for the Aging In Place Receiver #2
// BMP 2018-01-13
// This code supports turning on a tri color LED when it receives a AIP event


int red = D1;
int green = D2;
int blue = D3;


void setup() {


pinMode(red, OUTPUT);
pinMode(green, OUTPUT);
pinMode(blue, OUTPUT);

    Particle.subscribe("AIP_V1",AIP_V1_Respond);
    Particle.subscribe("AIP_V2",AIP_V2_Respond);

}

void loop() {

}

void AIP_V1_Respond(const char *event, const char *data){
    int curData;
    
    curData = atoi(data);
    switch (curData)
    {
        case 0:
            digitalWrite(green, LOW);
            digitalWrite(red, LOW);
            digitalWrite(blue, LOW);
            break;
        case 1:
            digitalWrite(green, HIGH);
            digitalWrite(red, HIGH);
            digitalWrite(blue, HIGH);
            break;
        case 2:
            // This message reserved for power out alert
            break;
        case 3:
            
            break;
        default:
            digitalWrite(green, LOW);
            digitalWrite(red, LOW);
            digitalWrite(blue, LOW);
            break;
    } 
    
}

void AIP_V2_Respond(const char *event, const char *data){
    int curData;

    digitalWrite(green, HIGH);
    digitalWrite(red, HIGH);
    digitalWrite(blue, HIGH);

}

Credits

Bryant Patten

Bryant Patten

3 projects • 3 followers

Comments