-
-
Save Woolfy025/652717bd57e0b2262ac8604836455a0e to your computer and use it in GitHub Desktop.
Facilitates communication with extradimensional entites via a raspberry pi and sensehat (for entertainment purposes only)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment