Monday, December 30, 2013

RPi - Controlling a Servo Motor

Today I set up the Raspberry Pi to control a servo motor.

For the hardware setup, I referred to chapter 10 from the Raspberry Pi Cookbook. Aside from the Pi, I only used the Pi Cobbler, a 1k resistor, and a 4AA battery pack. I didn't use any other special components. In the future, I'll consider getting a specialized breakout board for controlling servos.

For the software, I started with the code from this blog post:  http://www.doctormonk.com/2012/07/raspberry-pi-gpio-driving-servo.html
Note that in Simon Monk's post, he uses a transistor in his circuit that I didn't use based on the circuit in the book.

My first attempt didn't work well. The servo would turn very slowly, arriving at the 180 degree position, and stay there. I could feel the motor working but there was little to no movement.

After further research, I made some modifications to the starting code including changing the order of the True and False statements and playing with the timing. Things started to work. I was reading that servos needed between a .001 and .002 second pulse to move between 0 and 180 degrees respectively. I was finding those to be too long. For my servo, the range was between .00055 and .002. I don't know if that is a servo thing or if that helps to compensate for a delay from the RPi itself.

Finally, I added some code to accept an angle 0-180 as input and convert that angle into the appropriate timing of the pulses. I also had that input affect the number of loops because for shorter angle changes, a greater number of loop iterations would result in the motor jumping around slightly after reaching the desired angle. Now I can probably convert this to a function and use with other programs.

I had been reading about others experiencing a jittery movement when only using GPIO to control the servo but once I figured out the appropriate timing and loops, I found that it moved very smoothly. I don't know if there are other factors that I'm not experiencing that could affect the performance.

The Code:

import RPi.GPIO as GPIO
import time
import math

pin = 18
refresh_period = 0.02

prev_angle = 90           #initiate previous angle

GPIO.setmode(GPIO.BCM)

GPIO.setup(pin, GPIO.OUT)
GPIO.output(pin, False)

while True:
    angle = int(input('Angle: '))

    # convert degrees (0-180) to the servo pulse (.00055 to .002ms)
    pulse = (angle * .00000805555) + .00055

    # determine the number of loops based on degrees needed to travel, a shorter distance (degrees) to travel = fewer loops
    loops = math.ceil(math.fabs(prev_angle - angle) * .135) + 2
    prev_angle = angle

    # move the servo arm
    for i in range(1, loops):
        time.sleep(refresh_period)
        GPIO.output(pin, True)
        time.sleep(pulse)
        GPIO.output(pin, False)


The circuit:

The servo I used:

The servo specs:

Years ago, I created a very simple robotic arm that waves and was able to revive it once again with the RPi!





Saturday, December 28, 2013

FitBit Data to Google Spreasheet

I received a FitBit for Christmas and while the website provides access to a lot of data a graphs, I wanted a way to access the data in a format to process with R (statistics).

I found the following blog post which points to the use of a Google script that accesses the data via the developer API and populates a Google spreadsheet.

http://citizen-statistician.org/2012/09/30/getting-data-from-fitbit/

It was pretty straight forward since I've worked a bit with Google scripts before.

It provides daily summary data across a dozen or so categories. What would be nice is more granular data.

Freezing Temp Alert

I created an alert on my phone to tell me when the temperature outside drops below freezing. Since I don't have my own network accessible thermometer, I am using the wunderground api to query the closest weather station, a couple of miles away. It should be close enough.

I used this blog post as a guide for accessing the wunderground api:  http://www.pocketables.com/2012/07/tasker-task-that-speaks-the-weather-forecast-download.html

I set up a wunderground developer account here: http://www.wunderground.com/weather/api/

In Tasker:

The profile runs every hour.

The task is as follows:

A1: HTTP Get [ Server:Port:api.wunderground.com Path:/api/[mykey]/conditions/q/[my state abbrev]/[the town or neigborhood with the station I wanted to query].xml Attributes: Cookies: Timeout:10 Mime Type:text/plain Output File: ]

A2: Variable Set [ Name:%wunderresults To:%HTTPD Do Maths:Off Append:Off ]

A3: Variable Search Replace [ Variable:%wunderresults Search:\<temp\_f\>\d\d.\d\<\/temp\_f\> Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In:%matchedtemp Replace Matches:Off Replace With:a ]

A4: Variable Search Replace [ Variable:%matchedtemp1 Search:\d\d.\d Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In:%matchedtemptwo Replace Matches:Off Replace With: ]

A5: Variable Set [ Name:%oakbrookTemp To:%matchedtemptwo1 Do Maths:Off Append:Off ]

A6: Flash [ Text:%myTemp Long:Off ]

A7: If [ %myTemp < 33 ]

A8: Notify [ Title:Temperature Warning Text:%myTemp Icon:hd_alerts_and_states_warning Number:0 Permanent:Off Priority:3 ]



I had to do some parsing gymnastics to get the temperature out of the xml returned from wunderground (actions 3 and 4).

I also have the temp display on a MimialistText widget so I can see the temp anytime, not just when it's freezing.

RPi - Python and Blinking LED

I successfully created a python script to blink an LED attached to the RPi/Pi Cobbler.

The circuit attaches to the 3.3V output, routes through the LED, a 470R, and back to GPIO pin 18.

I wrote it using IDLE on the RPi GUI.

I used this blog post as my guide: http://www.thirdeyevis.com/pi-page-2.php
I also referred to this one and even started to set up the WebIDE: http://www.akeric.com/blog/?tag=pi-cobbler

The code:

import RPi.GPIO as GPIO
import time

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

def Blink(numTimes,speed):
    for i in range(0,numTimes):
        print "Iteration " + str(i+1)
        GPIO.output(18,True)
        time.sleep(speed)
        GPIO.output(18,False)
        time.sleep(speed)
    print "Done"
    GPIO.cleanup()

iterations = raw_input("Enter total number of times to blink: ")
speed = raw_input("Enter length of each blink(seconds): ")

Blink(int(iterations),float(speed))


Tuesday, December 24, 2013

Simple LED Circuit

My Pi Cobbler arrived the other day and finally got around to playing. Created a simple LED circuit using the 3.3 V and ground pins on the cobbler. No Pi functionality was used other than as a source of power.

I used this blog post as a guide.
https://projects.drogon.net/raspberry-pi/gpio-examples/tux-crossing/gpio-examples-1-a-single-led/

Next, I'll control the LED via gpio on the pi.


Circuit:

Google Location Data

Using this blog post as my guide, I downloaded the location data that Google stores about me and plotted it via R: http://seasci.wordpress.com/2013/12/20/it-knows-where-i-live/

The json file downloaded from Google Takeout was 123 MBs, over 780k location records. It takes several minutes for the script to parse all those records.

The blog author is from UK so I needed to adjust map parameters to my relevant locations.

This script uses get_map() a lot. Here's the documentation for get_map(): http://www.inside-r.org/packages/cran/ggmap/docs/get_map

I also tried to convert the json file to a csv prior to importing into R using this py script: https://github.com/Scarygami/location-history-json-converter/blob/master/location_history_json_converter.py
I modified the csv output format a bit to include accuracy data and to add a comma between lat and lon. I think because there were some records without accuracy, I was getting errors so applied a Catch KeyError function to the accuracy line. This helped me: http://stackoverflow.com/questions/16154032/catch-keyerror-in-python

Next I need to modify my R script to read in csv instead of json.




Tuesday, December 17, 2013

R - POSIXct vs. POSIXlt



As I continue to learn about managing date and time data, I'm working to understand the difference between

POSIXct and POSIXlt

POSIXct is a date-time data object that stores the number of seconds since a certain point in time in the past.

POSIXlt stores a list of day, month, year, hour, minute, second, etc.

I'm still learning when best to use each type in different contexts. More to come on that.

R - strftime() vs. strptime()

I'm learning how to handle date and time data in R.

There are two functions that are similar when converting date/time related data.

strptime() takes a character vector (string) and converts to a POSIXlt or POSIXct data object.

strftime() takes a a POSIXlt or POSIXct data object and converts to a character vector (string).

Here is documentation on use including formatting characters: http://www.inside-r.org/r-doc/base/strftime

Sunday, December 15, 2013

R - Comment Lines in Data File


Today I learned that you can have comments lines in data files. You need to include comment.char="#" as an argument to read.csv() and use whatever symbol you want, though a # (octothorpe) would be consistent with commenting in Rscript.

Example:
data <- read.csv("../datasets/heatmaps_in_r.csv", comment.char="#")

Saturday, December 14, 2013

R - Lubridate - Reading Date/Time Data

I'm reading in date and time data from my sleep project using the parse_date_time() function from the lubridate package.

sleep$StartDateTime <- parse_date_time(paste(sleep$Date, sleep$StartTime), "%m-%d-%Y %H.%M", truncate = 2)

The date and time data were in two separate columns so I needed to use the paste()function. The minutes data is in the format HH.MM.

Also, I was getting NA data at first when the minutes data was 00 (at the top of the hour). I added the truncate argument so that it would ignore incomplete data in seconds and minutes.

Here is a good summary of the parse_date_time() function: http://www.inside-r.org/packages/cran/lubridate/docs/parse_date_time

Monday, December 9, 2013

Sleep Segments

First graph of the number of sleep segments per night. This, combined with the duration of sleep would be the two most significant measurements of the quality of sleep. So far, it appears I am improving in my sleep by waking less during the night.

(click to view)

R - Converting Column to Date

In my sleep data, I have a date column that was originally a character type. When plotted in ggplot(), it was listing every date in the x axis, making the labels very crowded.

Then I added the following code

dailytotals$EndDate <- as.Date(dailytotals$EndDate , "%m-%d-%Y")

which converted it to a date type. Then ggplot automatically created tick marks and labels every 15 days (for data that spans two months.

Note that the %Y (capitalized) recognizes a four digit year where %y (lower case) recognizes a two digit year.

Saturday, December 7, 2013

Initial Sleep Analysis

This is my first post sharing my initial analysis of my sleep data. I've collected data for two months now using Tasker on my Android phone. It collects the start and end date/time of each sleep period as well as why I woke up.

I've just started using R and love it. Here is the first graph showing the total number of hours slept each night. Weekends are colored red because I wanted to know if I slept better on the weekends (it doesn't seem to matter).

Here is the graph:
(click to view)
I had a few days in November where my tasker action didn't save all the sleep intervals. On those days, I added estimate data. I may remove those dates altogether. There may be other dates that are incomplete. I have a could of days with less than four hours and I can't remember if that is correct or not. That probably has an impact on the dip in sleep duration in November.

Generally, I am getting more sleep that I expected, averaging around 6.5 to 7 hours per night.

Next I need to factor in the number of sleep segments to come up with a measurement of sleep quality (greater duration and fewer segments represents better sleep). I also need to consider why I woke up. If I was interrupted by an alarm, for example, and that cut my sleep shorter than it would have been naturally, it's not necessarily fair to treat that as a dependent variable when considering factors that affect sleep quality.

Here is the R Script I used (via RStudio):
library(methods) 
library(lubridate)

sleep <- read.csv("C:/Users/xxxxxxx/Documents/R/Sleep/sleepdata.csv", header=T)

sleep["EndDate"] <- NA

sleep$EndDate <- ifelse(sleep$EndTime > 12, format(mdy(as.character(sleep$Date)) + days(1), format="%m-%d-%Y"), format(mdy(as.character(sleep$Date)), format="%m-%d-%Y"))  #fill column with date of the morning of each sleep period

sleep["Weekday"] <- NA

sleep$Weekday <- weekdays(mdy(sleep$EndDate))  #fill column with weekday of the sleep period

sleep  #display data in case I want to review

dailytotals <-unique(within(sleep, {
  Duration <- ave(Duration, EndDate, FUN=sum)rm(Date,StartTime,EndTime,Status)
}))  #create frame, one record per day with total number of hours slept

dailytotals  #display in case I want to review

ggplot(dailytotals, aes(x=EndDate, y=Duration, group=1, colour=Weekday)) +
  geom_point() +  #plot points on graph
  stat_smooth(level=.99) + #regression/curve line with 99% certainty range
  theme(axis.text.x = element_text(angle = 90), axis.title.x = element_text(angle = 0), axis.title.y = element_text(angle = 0)) +  #labels, turn x axis vertically
  scale_color_manual(values=c(Saturday="red", Sunday="red", Monday="blue", Tuesday="blue", Wednesday="blue", Thursday="blue", Friday="blue"))  #color code weekend days

Friday, November 29, 2013

AutoRemote and Linux

I successfully paired Raspberry Pi with two android devices via AutoRemote.

I used the instructions here http://joaoapps.com/autoremote/linux/ but was getting an invalid key error. This is because I was trying to use the personal url rather than the personal key. The difference is explained here: http://joaoapps.com/autoremote/personal/ .

I set these connections up using the internal IP but will try to add registrations using a public IP so I can control from anywhere. I'll need to set up port fowarding in my router. I'll also need to come up with the best way to always know my home public IP.

I also successfully sent commands from my phone to the RPi.
  • sudo halt
  • aplay [filepath]

Wednesday, November 27, 2013

Playing Audio on Rasperry Pi

I successfully played an audio file (.wav) out the headphone jack using the command:

aplay [name of file]

I also tried to adjust the volume using amixer but it didn't seem to make a difference. I'll need to play with that some more.

Transfer Files from Windows to Raspberry Pi

I wanted to transfer a .wav file from my windows machine to the raspberry pi.

I found this blog post and successfully used WinSCP.

http://www.neil-black.co.uk/transfer-files-across-your-network-from-windows-to-a-raspberry-pi#.Upaw-sTUBiI

Use the SCP protocol rather than FTP or SFTP.

Tuesday, November 26, 2013

Monday, November 25, 2013

Bootable USB Drive for Linux Install

Today I learned about and used the Universal USB Installer software to prepare a bootable USD thumb drive with an Ubuntu image. I then installed Ubuntu on an old Dell Mini Inspiron 910 netbook.

 http://www.pendrivelinux.com/universal-usb-installer-easy-as-1-2-3/

Linux installs are so much easier now. I remember installing linux 15 years ago and it was not for the faint-at-heart.

Sunday, November 24, 2013

EventGhost

Just installed EventGhost. I've been starting to investigate how to use EventGhost, AutoRemote, and Tasker to control the PC from an Android device.

More to come.



Resources:

Eject USB Drive - Error and Fix

Earlier today, I successfully used a USB drive in my raspberry pi but when I went to eject the drive by right clicking on the drive in the file manager (via the desktop), I got an error message: "Error starting job: Failed to execute child process "eject". No such file."

Found this thread: http://www.raspberrypi.org/phpBB3/viewtopic.php?t=18364

Installed "eject" using the command line:

sudo apt-get install eject

Works now.

Rasp Pi: USB Thumbdrive

First time trying a USB thumb drive in the raspberry pi. After plugging it in, I remoted in (RDP) and it was already mounted as a drive in the file system. I didn't need to do anything.

I need to test whether it would have been mounted if I only remoted in via terminal (SSH). Was it the x interface that mounted it or the plugging in of the drive at the OS level that mounted it?



Resources:

Wednesday, November 20, 2013

Shutting Down the Raspberry Pi

Two options for shutting down the raspberry pi from the command line:

sudo shutdown -h now

or

sudo halt

Tuesday, November 19, 2013

AutoRemote, AutoLocation, AutoVoice

I have purchased and started playing with three plug in apps for Tasker created by João Dias.
  • AutoVoice
  • AutoRemote
  • AutoLocation
Info on these plugins can be found here.

Sunday, November 17, 2013

Connect Digital Camera to Raspberry Pi

I tried to connect an older digital camera, the Cannon Powershot Elph SD1000, to the raspberry pi and use it to take pictures remotely.

I installed gphoto2.

After a number of attempts, I saw that while accessing files on the SD1000 is possible, taking photos is not.

We have a couple of other old digital cameras around, I'll try those when I get the chance.

startx

From the command line, use 

startx 

to launch the desktop GUI.


(Raspian Wheezy OS)

Friday, November 15, 2013

New Raspberry Pi



I received my new raspberry pi as a birthday present.

I ordered the Raspberry Pi Model B Board with 8GB O/S Card from MCM Electronics for just under $40.

I already had a 1 amp, 5 volt micro USB charger from an old cell phone. While the minimum is 700 milliamps, everyone recommends at least 1 amp.

I connected it to our home network via ethernet. A wireless adapter is on the wishlist.

I didn't have an HDMI tv close to a network drop so I used the analog port to connect to an old tv. At first, no video appeared but then I needed to press 4 at startup so that the pi would output to analog NTSC.

I borrowed a USB mouse and keyboard from another computer in order to get things setup.

Everything working great so far.



Friday, November 1, 2013

Sleep Data - Getting Started

Occasionally, I have trouble sleeping. The most common issue is waking up in the middle of the night, typically around 2am, and having trouble getting back to sleep.

There are lots of variables that could impact my sleep and rather than just guessing, I wanted to start collecting my actual sleep times and other events that could impact sleep. Then I can look for potential causal relationships.

I've been using Tasker on my Android phone to collect sleep data. When I turn the phone face down, it sets that time to a variable. Then when the phone is picked up (and it's been more than 1/2 hour), a dialog asked why I woke up. Then it records the date, time, duration, and reason to a new line in a csv file on the phone. That file is synced once a day to my Google Drive so I can work further with it.

I also have a Tasker dialog that allows me to collect events that could affect sleep such as caffine, stress, nap, etc. That records the date, time, and reason to another csv file.

I've started to learn how to use R, a statistics programming language/environment, to analyze the data but still very early in that process. Specifically, I've been using R Studio.