Contact Us

Use the form on the right to contact us.

You can edit the text in this area, and change where the contact form on the right submits to, by entering edit mode using the modes on the bottom right. 


Oak Ridge, TN, 37830
United States

Lyf-Hacking

Shortcuts, easter eggs, and the exaustingly fun pursuit of solving lifes problems in unconventional ways.

FOC.US EEG - Saving ALL the data!

Wade Cantley

First post in the middle of things..

Before we get started, it's important to note that I am posting in the middle of my research and will retro post more about the device, how to set it up, some of the challenges of this great product that is still rolling out updates to fulfill its potential.

The device is the Focus EEG and to get the full rundown of this nifty cutting edge tech, go to foc.us/eeg

I purchased this device in order to evaluate the effects the tES (transcranial electric stimulation) which equates to home brain hacking by routing very low electrical signals in and out of the brain through specific areas for targeted effects.

Faster learning? stronger memory? Sharpened focus in that state of flow? Heightened spiritual inspiration?
TES is the doorway to doing all that without drugs.

Improving working memory capacity TEDx

What would you do if you were limitless? Maarten Frens at TEDxDelft

DARPA use of tDCS to increase response and accuracy in combat.

So as a 43 year old programmer trying to keep up with an industry that is changing at breakneck speeds, I have an interest in being able to keep up with my younger and more mentally flexible peers.  But I am not gullible and frankly, I need some convincing because it is hard to evaluate myself while knowing I should expect a given result. (aka Placebo).  

So the EEG / tDCS combo is perfect for evaluating the kinds of effects that are being produced, if any, and possibly what negative effects might also be produced.


Let's get started...

At the time of this writing, FOC.US has not yet setup the means to download the data from your EEG BUT there is a way to intercept the data and record it. Granted, this is not ideal because it creates A LOT OF DATA but it is a step in the direction of evaluating that data over a stretch of time rather than live.

But why do we want to save it?

Think of it like this.

If you listen to a song that has highs and lows over time, you can only really monitor it in the moment.  But if you look at the wave for for the entire song, you can see where exactly the highs and lows are.

When doing tests, you want to see the waveform over time so that you can say "I started the test 90 seconds in" and see if there is a difference from before 90 seconds.

To do this, first we must collect the channel data.

Lets get started!


screenshot39.jpg

So when you go to the website you see something like this.  And that IS pretty cool, but for this to be useful you need to see it over time so that you can clearly see the difference between when you started your experiment and when it ended.

You need the data!


Charles-Proxy.png

Enter Charles Proxy.

Charles Proxy is a nifty debugging app that allows you to see what is coming and going from your computer.  And this is important because it will capture all that data which is creating the graphs.

screenshot43.jpg

Download and install Charles Proxy, and when it opens up it will start recording your traffic.  You will know this because the record button will be red.

You want to go to Foc.us/me  , login, and open up your Raw Streaming Data Access. 

screenshot41.jpg

screenshot40.jpg

You're looking for an address that looks kinda like this. 

You want to click on the last "/" because that is the most recent and it should show that it is still recording.

 


..which should look something like this!

screenshot42.jpg

What matters most is that you see the "Duration" and the number of"Websockets" going up.

This is because you are receiving a constant stream of data that the Javascript on the website is using to create the flowing chart of data.

At this point, AVOID PRESSING ANY OF THE OPTIONS such as WebSocket, Response, etc... This is because you are recording a lot of data and it will take forever for it to show anything.


screenshot44.jpg

For now, you just want to record for a few minutes to get a sample and when your done, right-click on the "/" and save the response.  Be sure to save it with a name and "txt" extension.  So something like "MyVeryFirstEEG.txt".

 

 

 


Now you're wondering, ok, what's in this thing?  A few minutes of data could be quite a lot so open it up in a basic text editor.

(if you open it in something other than a simple text editor, it is going to freak out or not show you all the data.  That's because there are some strangely formatted characters in the data we need to get rid of)

It should look something like this!

screenshot45.jpg

This is one packet of data is pretty big but it has some parts to it that are important.

‚ ‚‚~'?0¼N!303730313334510A003F003B/afe/json{"fs": 250, "devID": 14921998972674668356255547451, "ts": 1506786354797, "chs": [1452.2558359374962, 1452.7449726562481, 1454.0901757812535, 0.0, ........

Let's break it down.

First, this is JSON which is just a format for sending data between computers that Javascript is really good at consuming.

  • "fs":250 - I don't know what this means but it is repeated so It isn't useful to me at the moment.

  • "devID" : 14921998972674668356255547451 - This is probably unique to me  as a user, but again, repetitive and not useful for our purposes.

  • "ts" : 1506786354797 - This is a timestamp that is simply a countdown since a specific date.  It is a very simple way to order data by a date time that isn't formatted in any special way.  To give you an idea, you can take that number and put it into this website ( https://www.epochconverter.com/timezones?q=1506786519&tz=America%2FNew_York ) and get the Date/Time that relates to that moment. 

    THIS field is important.  every chunk of data is going to be ordered by this time stamp and if I am going to organize the data chronologically, I need to order it by the time stamp.

  • "chs" : [ 1452.2558359374962, 1452.7449726562481, 1454.0901757812535, 0.0......] - This is where it appears that all the node data resides.  And it seems like there is a repetition of data for every JSON package.

[1452.2558359374962, 1452.7449726562481, 1454.0901757812535, 0.0, -9975.9495175781194, 0.0, -4723.5024736328123, -16336.904160156249, -1455.3066640625038, -1456.5128398437519, -1456.7613867187465, 0.0, 927.26923242188059, 0.0, 5319.7162763671877, 16736.189589843751, -1512.9472890625038, -1514.0440898437519, -1514.3551367187465, 0.0, 3492.0661074218806, 0.0, 2102.7436201171877, 14433.892714843751, 1545.2792734374962, 1546.2215351562481, 1547.0667382812535, 0.0, -5630.4417050781194, 0.0, -6747.9438798828123, -17375.029160156249, 2037.0214609374962, 2038.0965351562481, 2039.4104882812535, 0.0, -8793.6995175781194, 0.0, -4143.0923173828123, -18601.826035156249, -1232.7519765625038, -1233.8644023437519, -1233.9332617187465, 0.0, -2911.4417050781194, 0.0, 2056.8334638671877, 10416.076308593751, -1655.4472890625038, -1656.5831523437519, -1657.2066992187465, 0.0, 5965.3551699218806, 0.0, ...[there is a lot more]

I can tell that this is 8 channels repeated over and over again because of how my channels were reporting so I counted them off and found a pattern


1452.2558359374962, 1452.7449726562481, 1454.0901757812535, 0.0, -9975.9495175781194, 0.0, -4723.5024736328123, -16336.904160156249

-1455.3066640625038, -1456.5128398437519, -1456.7613867187465, 0.0, 927.26923242188059, 0.0, 5319.7162763671877, 16736.189589843751

-1512.9472890625038, -1514.0440898437519, -1514.3551367187465, 0.0, 3492.0661074218806, 0.0, 2102.7436201171877, 14433.892714843751‚


So this tells me that it is cycling through my 8 channels over and over again.   And this is GREAT because I can loop over that data and pick it apart.

There are a few other bits of data to note on the tail end of this package.

  • ProdId: 1 - I am guessing this is just an indication of which product this is going through.
  • chmask: "111111111" - My guess?  Channel Mask.  In programming a mask is ment to define a limitation so a numerical mask of "99.9999" means more more than 2 integers before the decimal, no more than 4 decimals deep.  In this example though I think that "11111111" is meant to indicate that there are 8 channels and so, I need to loop over all those channel values 8 times before I start over at channel 1 for the ninth value in the list.  If I turned on only 4 channels I would expect the chmask to be "1111" which would tell me that now the fifth number in the list is actually the first of the next four channels.
  • units: "uV"  - which means microvolts or 1/1,000,000 of a volt and indicates the unit of measurement the "chs" data represents

Where are we really going with this?

As I mentioned at the top of this post, I want to visualize this over the full length of time, and I found a Great blog with some custom software that takes a formated EEG data and turns it into a spectral graph.  (http://eeghacker.blogspot.com/2014/)

File1_detection.png

When you look at data like THIS, you can review the data over the full length of the experiment and when it is in a format similar to sound, it adds an additional level of data that pops out patterns.

To do that, I need to:

1) Get the data!
2) Convert the data into a friendly format
3) Feed that formatted data into an application that turns it into spectrograph. 

One down, two to go.


Nextup, converting the data into a freindly format.

 

Tank Project - Part 7 - All The Maths!

Wade Cantley

After a few hours of playing around I came up with a chunk of code that :

  1. Creates arrays to manage brightness (and eventually color) settings.
  2. Evaluates time between midnight and sunrise.
  3. Evaluates the time between Sunrise and Sunset.
  4. Evaluates the time between Sunset and Midnight.
  5. Outputs the correct brightness to print but later to the IR LED

 

What is important about the output is that the last iteration has some overlap.  So the last iteration (iteration 20) for the daytime overlaps with the first iteration of the evening.  I could be more precise but this is fine for my purposes and it will only happen under the circumstance where we are moving into a different time span.

I had hoped to just do two time periods... night and day.  But it turned out easier to divide the day into three segments of code for evaluation; morning, daytime, night.

So here is the code.

from urllib2 import Request, urlopen, URLError
import xml.etree.ElementTree as ET
import datetime
import time

#So we have to prep this URL with the day, month and whether to use daylight savings time.
#AND it has to be a string so that it is one big url string.
requestURL = "http://www.earthtools.org/sun/36.0286645/-84.2211902/" + str(datetime.datetime.today().day)  + "/" + str(datetime.datetime.today().month) + "/-5/" + str(time.localtime().tm_isdst)
request = Request(requestURL)

#Setup the variables that will be used and default values to start with.
sunrise = ""
sunset = ""
sunriseMinute = ""
sunsetMinute = ""
currentTimeMinutes = datetime.datetime.now().hour * 60 + datetime.datetime.now().minute
isError = False
incrementBy = 20
incrementalPeriod = ""
totalMinutesInDay = 60*24

print "current time minute : " + str(currentTimeMinutes)

#So we fetch the time stamp
try:
    response = urlopen(request)
    timestuff = response.read()
    #print timestuff[1:100000]
except URLError, e:
    print 'UUUHHHGGGGG. Got an error code:', e
    isError = True

# and we parse the data if there is no error
if isError == False:

    #get to the root of the XML
    root = ET.fromstring(timestuff)

    #pick out the sunrise and sunset from the XML, replace the colons with commas
    #then split it into a list with multiple objects. So from 07:10:25 into ['07','10','25']
    sunrise = root[3][0].text.replace(":",",").split(',')
    sunset = root[4][0].text.replace(":",",").split(',')

    #now we calculate the minutes into the day for each. These will be our base numbers.
    sunriseMinute = int(sunrise[0]) * 60 + int(sunrise[1])
    sunsetMinute = int(sunset[0]) * 60 + int(sunset[1])

    print "Sunrise Minute : " + str(sunriseMinute)
    print "Sunset Minute : " + str(sunsetMinute)



    # *********************  Day Time Calculations ************************

    #I need to reound this so that it is a whole number.  Just easier to deal with.
    incrementalPeriodDay = round((sunsetMinute - sunriseMinute) / incrementBy)
    print "Increment by Minutes Daytime : " + str(incrementalPeriodDay)

    #put the daytime brightness settings in an array
    brightness = [5,5,6,6,7,7,8,9,10,10,10,10,9,8,7,7,6,6,5,5]

    #NOTE : Add a color array here when we figure out what the color settings are.

    thisItteration = 1
    while thisItteration <= incrementBy:
        #from sunrise to sunset
        if (sunriseMinute + (incrementalPeriodDay * thisItteration)) > currentTimeMinutes:
            print "Daytime Brightness " + str(brightness[thisItteration - 1])
            print "Itteration " + str(thisItteration)
            break

        thisItteration = thisItteration + 1





    #reset increment to 10 since we are going to be handling two quarters of the day seperately.
    # so 10 increments after sunset to midnight, and 10 increments from midnight to sunrise.
    incrementBy = 10

    # *********************  Morning Time Calculations ************************

    #I need to reound this so that it is a whole number.  Just easier to deal with.
    incrementalPeriodMorning = round(sunriseMinute / incrementBy)
    print "Increment by Minutes Morning : " + str(incrementalPeriodMorning)

    #put the daytime brightness settings in an array
    brightness = [1,1,2,2,2,3,3,4,4,5]

    #NOTE : Add a color array here when we figure out what the color settings are.

    thisItteration = 1
    while thisItteration <= incrementBy:
        #from midnight to sunrise
        if (0 + (incrementalPeriodMorning * thisItteration)) > currentTimeMinutes:
            print "Morning Brightness " + str(brightness[thisItteration - 1])
            print "Itteration " + str(thisItteration)
            # color and brightness commands will go here.
            break

        thisItteration = thisItteration + 1




    # ********************* Evening Time Calculations ************************

    #Increments if we take the time between sunset and midnight and divide by 10
    incrementalPeriodDay = round((totalMinutesInDay - sunsetMinute) / incrementBy)
    print "Increment by Minutes Daytime : " + str(incrementalPeriodDay)

    #put the Evening brightness settings in an array
    brightness = [5,4,4,3,3,2,2,2,1,1]

    #NOTE : Add a color array here when we figure out what the color settings are.

    thisItteration = 1
    while thisItteration <= incrementBy:
        #From Sunset to midnight
        if (sunsetMinute + (incrementalPeriodDay * thisItteration)) > currentTimeMinutes:
            print "Evening Brightness " + str(brightness[thisItteration - 1])
            print "Itteration " + str(thisItteration)
            break


        thisItteration = thisItteration + 1

And the results after running it along with the overlap.

Again, as you can see, iteration 20 triggers the day time code as well as iteration 1 for the evening.  But I have the brightness setting the same so, no big deal.  I can refine this later.

Now that I have the logic nailed down, I need to figure out how to setup a python executable.

Tank Project - Part 6 - Parsing the XML

Wade Cantley

I left off scratching my head as to how I was going to parse this chunk of XML.  Turns out that is pretty easy to do in python. 

I am really growing fond of this language.  It is easy to follow, there is lots of resources online for finding answers to questions, and the language makes good sense.  I even like the tabbing behavior that while initially odd, makes great sense after thinking about how it saves a few keystrokes by not having to use braces {} to create closures and enforcing good code formatting at the same time.

So, I spent a little time figuring things out in my field notes book.

It goes like this.

  1. Fetch the sunrise and sunset time based on my location and some additional parameters (covered in the code below).
  2. Figure out what minute each is on.  (6:06 pm is minute 1086)
  3. Divide the number of minutes between the Sunrise and Sunset by 20 (round number to start with).

So we will have a Sunrise minute, Sunset minute, Current minute., and incremental period in minutes.

from urllib2 import Request, urlopen, URLError
import xml.etree.ElementTree as ET
import datetime
import time

#So we have to prep this URL with the day, month and whether to use daylight savings time.
#AND it has to be a string so that it is one big url string.
requestURL = "http://www.earthtools.org/sun/36.0286645/-84.2211902/" + str(datetime.datetime.today().day)  + "/" + str(datetime.datetime.today().month) + "/-5/" + str(time.localtime().tm_isdst)
request = Request(requestURL)

#Setup the variables that will be used and default values to start with.
sunrise = ""
sunset = ""
sunriseMinute = ""
sunsetMinute = ""
currentTimeMinutes = datetime.datetime.now().hour * 60 + datetime.datetime.now().minute
isError = False
incrementBy = 20
incrementalPeriod = ""

print "current time minute : " + str(currentTimeMinutes)

#So we fetch the time stamp
try:
    response = urlopen(request)
    timestuff = response.read()
    #print timestuff[1:100000]
except URLError, e:
    print 'UUUHHHGGGGG. Got an error code:', e
    isError = True

# and we parse the data if there is no error
if isError == False:

    #get to the root of the XML
    root = ET.fromstring(timestuff)

    #pick out the sunrise and sunset from the XML, replace the colons with commas
    #then split it into a list with multiple objects. So from 07:10:25 into ['07','10','25']
    sunrise = root[3][0].text.replace(":",",").split(',')
    sunset = root[4][0].text.replace(":",",").split(',')

    #now we calculate the minutes into the day for each. These will be our base numbers.
    sunriseMinute = int(sunrise[0]) * 60 + int(sunrise[1])
    sunsetMinute = int(sunset[0]) * 60 + int(sunset[1])

    print "Sunrise Minute : " + str(sunriseMinute)
    print "Sunset Minute : " + str(sunsetMinute)

    #I need to reound this so that it is a whole number.  Just easier to deal with.

    incrementalPeriod = round((sunsetMinute - sunriseMinute) / incrementBy)
    print "Increment by Minutes : " + str(incrementalPeriod)

And when we run it......

BAM!

So the point behind getting these numbers is that the next step is to do 20 loops and increment by 44 minutes each time.  Each loop I will add 44 minutes to the sunrise minute and I will check to see if my current minutes is less than my incremented number.  If I passed my current time, then do an IF statement check against the current loop count to see what light setting to use.

But why would we need to go through all that effort of looping and checking.  Couldn't we just look at the time and say "at 1pm make it yellow and bright"?

Yes we could do that but it wouldn't be true to the sunrise and sunset times.  Middle of winter has only 10 hours of day light where middle of summer is about 12 hours.  So I want the calculations to fluctuate so that the lighting in my tank is true to the lighting outside.  I will do all this again when calculating the night time lighting since that span is going to be different.

More later though.

Tank Project - Part 5.... getting my py on.

Wade Cantley

The burning of the OS image worked great.  At first I loaded the Kano version but that was way too much for kids and less for programming.  That and I think it is geared for the Pi2-B which is a step above my little Pi.

With Raspbian burned to disk, I gave it a whirl and BAM!  Works like a charm.

But going into the application I realize now that Python3 or Python2 is a very stripped down command prompt interface and while I am sure there is a better programming interface for the Raspberry Pi, I think I am going to first learn up on the code on my PC.

Now to get on with my python learning.

To start with, I don't know first thing about python but it is a programming language which means there is some sort of interpretive engine or a compiler, and an IDE of some sort.

Sure enough!

Interpreter : https://www.python.org/downloads/
IDE : https://www.jetbrains.com/pycharm/?fromMenu

In installed Python 3 only to realize that most of the tutorials out there are for Python 2 which has some differences in coding syntax so, I installed Python 2 and off we go.

So baby steps, the next thing I need to is figure out how to call on an API.

CodeAcademy seems to be helpful with this.  
http://www.codecademy.com/courses/python-intermediate-en-6zbLp/0/1?curriculum_id=50ecbb00306689057a000188

SUCCESS!!!!!

Granted, that is in New York but getting my latitude and longitude is just a quick trip to Google maps.

Here is the code for fetching this XML.

from urllib2 import Request, urlopen, URLError

request = Request('http://www.earthtools.org/sun/40.71417/-74.00639/4/12/-5/0')

try:
    response = urlopen(request)
    timestuff = response.read()
    print timestuff[1:100000]
except URLError, e:
    print 'UUUHHHGGGGG. Got an error code:', e

Next up, I will  need to figure out how to parse out the dates so that I can figure out how to time the intervals.  I may also need to figure out how to create an executable so that it runs continuously.   But one step at a time.

Fishtank Daylight Timed LED : Part 3 - Creating the Disk

Wade Cantley

I received the power supply and the diodes in the mail.

YAY!!!!

Tried to boot up from the disk.

BOOOO!!!

Still same error so I looked further and I think that I didn't burn the OS to the disk properly.  I figured I could just open up the .img file, and copy the files over.  But I was wrong.  I have to burn them to the card.  So I decided to go with the KANO burner for my MAC which has a nice copy of all the applications I think i will need as well as some games for the kids to learn on down the road.

http://www.kano.me/downloads

But just in case I needed to do something different down the road I read about a different loader that may help me get the OS burned in easy.

http://ivanx.com/raspberrypi/

 

Crossing my fingers.

Fishtank Daylight Timed LED : Part 2 - PANIC!

Wade Cantley

Ok, I couldn't find my power source for the Pi so I harvested one for recharging one of my phones.  And then I ran into this.

PANIC: VFS Unable to mount root fs on unknown-block (179,2)

The keyboard didn't seem to light up, and of course and the mouse was useless at this point.  So I went looking around and found this help forum.

https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=12245

" I found a reference that low voltage on the supply or feeds from the USB ports can cause unexpected writes to the SD card (I cant currently find the reference)."

This was really less important in finding the problem but it pointed to something I vaguely remembered when ordering which was that it needed a 2.5 amp power supply to fully power all the ports.  On checking my power supplies I didn't have anything that came close.  So, I cancelled my first power supply order and ordered the proper 2.5 amp power supply.

In the mean time I am going to see if  can tackle the software aspect by finding an emulator.  First stop is here.

http://sourceforge.net/projects/rpiqemuwindows/?source=typ_redirect

Fishtank Daylight Timed LED - Part 2

Wade Cantley

With a little help from the Pi4J project site, I setup for a simple LED to flash following these plans 

http://pi4j.com/example/control.html

 

So this should help with the software logic of making the LED flash.  Right now I only have a red LED but I will replace it with the IR LED as soon as it comes in the mail.


Also, I realized I lost my power supply so that is coming as well.  So the stuff ordered includes a power supply and the IR Diode LED light and sensor which thankfully there was a small kit that included both and didn't send quantities of 50.

Very simple circuit.

p18 = > 180 ohm resistor -> LED - > Ground

Fishtank Daylight Timed LED - Research

Wade Cantley

So here is the pitch.

I have a fish tank that I use an LED strip for lighting but it is one of those sylvania light strips that have a remote so you can change the brightness, the color, etc..

I also have my computer lit up with the same sort setup and being that my office, the tank, etc, is in my basement, I have no windows to really act as a night or day indicator.  So what I want to do is this.

  1. Get my RaspberryPi online and connect to an API that has the time as well as time to sun up and sun down.
  2. Hook up a IR LED
  3. Write some software that calls on the API occasionally to get that data and sends the IR code to the light's sensors and changes the color and brightness based on the time of day.

 

This way, if sunset is at 7:35, the light will be about mid red and mid brightness, morning will progressively get more yellow, until it is white and full at mid day, and at night it will be various shades of blue with the brightness lowered the later it gets.

What have I got?

  • RapberryPi
  • LED lighting for the tank.
  • various electronic stuff, breadboard, etc.

What do I need?

  • IR LED
  • Photodiodes

Here are some research link/s

http://www.stavros.io/posts/how-turn-your-raspberry-pi-infrared-remote-control/

Let's get started!