Skip to content

Instantly share code, notes, and snippets.

@RedRoosterKey
Created February 19, 2017 00:04
Show Gist options
  • Save RedRoosterKey/54c8e237ac0a13d026621c9903191b7e to your computer and use it in GitHub Desktop.
Save RedRoosterKey/54c8e237ac0a13d026621c9903191b7e to your computer and use it in GitHub Desktop.
Facilitates communication with extradimensional entites via a raspberry pi and sensehat (for entertainment purposes only)
#!/usr/bin/python
from sense_hat import SenseHat
from datetime import datetime
import math,os,random,subprocess,time
#
# Background:
#
# I have seen various electronic devices on paranormal TV shows (most popular
# being the Ovilus by Digital Dousing) that claim to convert "ghost energy" into
# actual English words. From the digital dousing website, they claim that their
# ghost box simply "converts environmental readings into words."
# - https://www.digitaldowsing.com/shop/ovilus-v/
# The algorithm for how this is done is not open source and could be as simple
# as this example, which uses a raspberry pi and sensehat to pick up
# "environmental readings" and using changes in that data to seed a random
# number generator later randomly choosing a word from the provided dictionary.
# To get this to work, you will need:
# * A raspberry pi
# * A sensehat
# * The python sensehat library installed
# sudo apt-get install sense-hat
# * A word list - set the "filename" variable (Results vary depending on the
# quality of your word list)
# * (optional) The espeak library installed (if you wish to HEAR the ghosts)
# sudo apt-get install espeak
# Comment out the calls to espeak() if you don't need this.
# You can have this program start up when the raspberry pi is powered by adding
# something akin to the following into /etc/rc.local before the exit 0
#
# # Ghost Box
# cd /home/pi
# su pi -c "python ghostBox.py" &
# This code is very sensitive to physical movement, it works best when set in a
# stationary position and read (or listened to) from about 3 or so meters away.
# VARIABLES
sense = SenseHat()
sense.low_light = True # It's more fun at night :-)
red = (255, 0, 0)
white = (255, 255, 255)
black = (0, 0, 0)
# Put the location of your word list file here.
# The one that Digital Dousing uses is available on their website.
# https://www.digitaldowsing.com/product-guides/ovilus-v/word-list/
filename="ovilus.txt"
# The minimum percent change required to trigger a word.
# A higher number will cause the ghost box to produce fewer words.
# A lower number will cause the ghost box to produce more words.
# 2.5 percent seems to be the magic number based on experimentation.
percent_change_min=2.5
# The number of seconds between readings.
# A higher number will cause the ghost box to produce fewer words.
# A lower number will cause the ghost box to produce more words.
# 5 seconds feels like a good cadence.
rest_period_between_readings=5
# FUNCTIONS
# Displays the message given, in the color given,
# right side up based on the detected acceleration of gravity.
def show_right_side_up_message(sense, message, color):
acc = sense.get_accelerometer_raw()
x = acc["x"]
y = acc["y"]
orientation = 90
if y > 0.75 :
orientation = 0
elif y < -0.75 :
orientation = 180
elif x > 0.75 :
orientation = 270
elif x < -0.75 :
orientation = 90
sense.set_rotation(orientation)
sense.show_message(message, text_colour=color)
# Get a random line from the file with the name provided
# and seed the rng with the given seed.
def get_random_line(seed, filename):
my_file = open(filename,'r')
line = next(my_file)
random.seed(seed)
for num, aline in enumerate(my_file):
if random.randrange(num + 2): continue
line = aline
return line
# Get a heuristic aggregating all sensor data allowing general change detection.
def aggregate_sense_data():
hum = sense.get_humidity()
temp = sense.get_temperature()
temp_from_hum = sense.get_temperature_from_humidity()
temp_from_press = sense.get_temperature_from_pressure()
press = sense.get_pressure()
o = sense.get_orientation()
yaw = o["yaw"]
pitch = o["pitch"]
roll = o["roll"]
mag = sense.get_compass_raw()
mag_x = mag["x"]
mag_y = mag["y"]
mag_z = mag["z"]
acc = sense.get_accelerometer_raw()
x = acc["x"]
y = acc["y"]
z = acc["z"]
gyro = sense.get_gyroscope_raw()
gyro_x = gyro["x"]
gyro_y = gyro["y"]
gyro_z = gyro["z"]
return hum + temp + temp_from_hum + temp_from_press + press + pitch + yaw \
+ roll + mag_x + mag_y + mag_z + x + y + z + gyro_x + gyro_y + gyro_z
# Speak the words verbally through the headphone jack.
# You must have espeak installed for this to work.
def espeak(message):
espeak = 'espeak -s100 "%s" 2>>/dev/null' % message
subprocess.Popen(espeak, shell=True)
# Display a basic animation to get us to look
# at the box before the message is displayed.
# Keeps you from missing words if audio is disabled.
def alert(sense):
spiral_sequence = [
[4, 4],
[3, 4],
[3, 3],
[4, 3],
[3, 3],
[5, 3],
[5, 4],
[5, 5],
[4, 5],
[3, 5],
[2, 5],
[2, 4],
[2, 3],
[2, 2],
[3, 2],
[4, 2],
[5, 2],
[6, 2],
[6, 3],
[6, 4],
[6, 5],
[6, 6],
[5, 6],
[4, 6],
[3, 6],
[2, 6],
[1, 6],
[1, 5],
[1, 4],
[1, 3],
[1, 2],
[1, 1],
[2, 1],
[3, 1],
[4, 1],
[5, 1],
[6, 1],
[7, 1],
[7, 2],
[7, 3],
[7, 4],
[7, 5],
[7, 6],
[7, 7],
[6, 7],
[5, 7],
[4, 7],
[3, 7],
[2, 7],
[1, 7],
[0, 7],
[0, 6],
[0, 5],
[0, 4],
[0, 3],
[0, 2],
[0, 1],
[0, 0],
[1, 0],
[2, 0],
[3, 0],
[4, 0],
[5, 0],
[6, 0],
[7, 0]
]
# set them all white
for x, y in spiral_sequence:
sense.set_pixel(x, y, white)
time.sleep(0.02)
# set them all black
for x, y in spiral_sequence:
sense.set_pixel(x, y, black)
time.sleep(0.02)
# MAIN LOOP
previous=aggregate_sense_data()
alert(sense)
espeak("Ghost Box Starting up!")
show_right_side_up_message(sense, "Ghost Box!", red)
while True:
current=aggregate_sense_data()
change=abs( (current / previous) - 1.0)
if ( (percent_change_min / 100.0) < change ) :
ghost_message = get_random_line(change, filename)
# Logging output
now = datetime.now() # this will not be accurate
# unless you have either a RTC or ntp with internet
print str(now)
print ghost_message
alert(sense)
espeak(ghost_message)
show_right_side_up_message(sense, ghost_message, red)
# it takes time to display the message so no sleep is required
else:
time.sleep(rest_period_between_readings)
previous=current
@Tornnnuts
Copy link

Is there any way someone could let me know how to get the ghostbox.py to pull from the ovilus.txt library or where to put the library?

@RedRoosterKey
Copy link
Author

Copy from here https://www.digitaldowsing.com/product-guides/ovilus-v/word-list/
put it in a text file

change the filename variable to use the text file you saved.

# Put the location of your word list file here.
# The one that Digital Dousing uses is available on their website.
# https://www.digitaldowsing.com/product-guides/ovilus-v/word-list/
filename="ovilus.txt"

@Tornnnuts
Copy link

thanks for the response i am still very new at this. Do i save the ovilus.txt into documents on the raspbian? I am just confused on where to put the list of words and how i can make the program grab from that list

@Tornnnuts
Copy link

do i change filename to ovilus.txt?

@Tornnnuts
Copy link

where should i put the file once i name it? i am super new to this

@RedRoosterKey
Copy link
Author

I would just modify the script to include the full file path. You can get that by running
readlink -f ovilus.txt

Also make sure that the file is readable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment