Find distance between two zipcodes, dump the result in an excel file

I recently wrote a piece of software for a friend working on a project, you can find it on github here. The following is from the README.md:


zipcode-distance-excel

This is a command line utility to automatically calculate the distance between two zipcodes and then put the results in an excel (.xlsx) file. It works for US postal codes only.

It was developed to help a colleague and is very application-specific.

Prerequisites

Downloading is easy git, which is already on most systems, on ubuntu use:

sudo apt-get install git

For everyone else:

Installing

A step by step series of examples that tell you have to get a development env running

Say what the step will be

git clone https://github.com/esologic/zipcode-distance-excel
cd zipcode-distance-excel
python3 setup.py install

Usage

in a directory with the .xlsx file that you want to modify, run:

python3 zde.py

The program skips the first row in the spreadsheet to avoid headers.

Example Usage

Before:

Before

Terminal output:

Which file would you like to modify?
[0] - International Addresses.xlsx
[1] - testbook.xlsx
File Number: 1
You've selected [testbook.xlsx] to edit.
Which sheet would you like to modify?
[0] - Sheet1
[1] - Sheet2
[2] - Sheet3
Sheet Number: 0
You've selected [Sheet1] to edit.
Which column to read? (ie. A, B, AA): A
Which column to write result? (ie. A, B, AA): B
Point A Zipcode? 02114
Job Complete. 10 modifications made.

After:

After

Authors

  • Devon Braysite
  • Miranda Lawellsite

License

This project is licensed under the MIT License

Soft-latching toggle switch with active reset circuit

This circuit aims to replace a traditional toggle switch for switching large amounts of current. Instead of the bulky and expensive traditional toggle switch, this circuit allows for a cheap pushbutton, and a few transistors and resistors to be used and have the same effect.

For my application, I wanted a way to have the circuit draw very little curren
t when in the off state, be able to be powered on with a pushbutton, and then turned off through software on the Arduino.
Here is the circuit diagram:

Here’s a video of the circuit in operation:

The code running on the Arduino is very simple:

int button = 3;
int led = 2;

void setup() {
  pinMode(button, INPUT);
  pinMode(led, OUTPUT);

  digitalWrite(led, LOW);
}

void loop() {
  if (digitalRead(button)) {
    digitalWrite(led, HIGH);
  }
}

Comparing blank string definition in Python3

In python3 using

string = ""

or

string = str()

Produces the same result for the programmer. Which one is faster? Using the python module timeit, it’s really easy to find out!

Using string="" is WAY faster.

Here’s the source code for my tests:

from timeit import timeit

durations = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000]
definition_techniques = ['s=""', 's=str()']

for definition_technique in definition_techniques:
    print(definition_technique + ' durations')
    for duration in durations:
        print(timeit(definition_technique, number=duration))

StripPi – Software Demo, Roadkill Electronics

I’m constantly loosing the remote for my RGB LED strip lights, and I have a few days for spring break, time to get hacking. Here’s a demo and explanation video:

I don’t mention it in the video, but the cool part of this project is how the different processes communicate with each other. Rather than interacting with the different processes through pipes, or something like stdin, I’ve decided to use a TCP websocket server:

StripPi High Level Diagram

Processes on the device send RGB values to the Strip Server via a TCP packet. This very very easy to implement, and almost all of the hard work is taken care of via the socketserver  module included in python3. This also allows for interactions with that main process (the StripPi Server process) to take place off of the Raspberry Pi as well. I plan on writing an Alexa integration for this project moving forward, and this should make that a lot easier.

The analog to digital conversion is handled by an MCP3008, exactly the same way as I did it here.

Thanks for reading, more soon.

Multiplexing Composite NTSC Video

This was one of those rare times where I had a hunch, followed it, and had a great result.

So for a project I’m working on for school, we have a robot with multiple composite video cameras onboard. We will be using those cameras seen on DIY drones or in simple security systems. We will be transmitting this video feed via a 5.8GHz video transmitter meant for a drone. We want the operator to be able to switch which feed they’re viewing at a given time, but we don’t want to have to use 3 transmitters and receivers. So to get around this, I thought we might just connect video feeds to a simple analog multiplexer I had laying around from a previous project and see if you could switch the feed that way. Turns out, you totally can. Here’s the eventual block diagram of this part of our project if you’re interested:

The following is the code running on the arduino. Remember, this isn’t doing anything special other than driving the mux:

#define NUMSELECTS 4

int s0 = 2;
int s1 = 3;
int s2 = 4;
int s3 = 5;

int selects[NUMSELECTS] = {s0, s1, s2, s3};
int select_state[NUMSELECTS] = {0, 0, 0, 0};

void setup()
{
  Serial.begin(9600);
  for (int index = 0; index < NUMSELECTS; index++)
  {
    pinMode(selects[index], OUTPUT);
    digitalWrite(selects[index], select_state[index]);
  }
}

void loop() 
{
  if (Serial.available() > 0)
  {
    char inchar = Serial.read(); //assigns one byte (as serial.read()'s only input one byte at a time
    switch(inchar)
    {
      case '0':
        Serial.println("Switching to video signal 0");
        select_state[0] = 0;
        select_state[1] = 0;
        select_state[2] = 0;
        select_state[3] = 0;
        write_selects();
        break;
      case '1':
        Serial.println("Switching to video signal 1");
        select_state[0] = 1;
        select_state[1] = 0;
        select_state[2] = 0;
        select_state[3] = 0;
        write_selects();
        break;
       default:
        Serial.println("Bad input");
        break;
    }
  }
}

void write_selects()
{
  for (int index = 0; index < NUMSELECTS; index++)
  {
    digitalWrite(selects[index], select_state[index]);
  }
}

Raspberry Pi Digital Hourglass

Trying to get the most out of a day has been big theme of my life lately, as I’m sure it is for many people. I’ve found that I always manage my time better when things are urgent; I’m considerably more productive when I have to be.

I want an ascetically pleasing way to be able to represent how much time is left in the day at a granular scale, like an hourglass. Watching individual seconds disappear will look cool and (hopefully) create that sense of urgency that I want to induce.

Technically, this is a really simple thing to accomplish thanks to python and pygame. Here’s a video of a proof of concept running on my laptop:

At the start of each day, the display is filled with squares at random locations, with a random color. As each second elapses, a square will vanish.

To make it easier to see for the video, I’ve made the squares much bigger than they will actually be for the final build. This is what the display looks like with the squares at their actual size:

The code really really simple, like less than 100 lines simple. Here’s how it works:

Here’s the version of the code running on my computer in the video:

import pygame
from random import randint
from apscheduler.schedulers.blocking import BlockingScheduler
import datetime

class random_square(object):
    def __init__(self, max_x_location, max_y_location):

        self.x_loc = randint(0, max_x_location)
        self.y_loc = randint(0, max_y_location)

        max_color_value = 255

        red = randint(0, max_color_value)
        green = randint(0, max_color_value)
        blue = randint(0, max_color_value)

        self.color = [red, green, blue]


class clock(object):
    def __init__(self, initial_count, max_count, screen_w, screen_h):

        self.max_count = max_count
        self.screen_w = screen_w
        self.screen_h = screen_h

        # create the screen object, force pygame fullscreen mode
        self.screen = pygame.display.set_mode([screen_w, screen_h], pygame.FULLSCREEN)

        # the screen's width in pixels is stored in the 0th element of the array
        self.square_size = screen_w / 200

        # create the list of squares, initially as empty
        self.squares = []

        # fill the squares with the inital seconds until midnight
        for second in range(initial_count):
            self.squares.append(random_square(screen_w, screen_h))


    # starts ticking the clock
    def start(self):
        scheduler = BlockingScheduler()
        scheduler.add_job(self.tick, 'interval', seconds=1)
        try:
            scheduler.start()
        except (KeyboardInterrupt, SystemExit):
            pass

    # this occurs once every time a unit of time elapses
    def tick(self):
        # this will happen once per "day"
        if len(self.squares) == 0:

            # fill the list of squares to be drawn
            for second in range(self.max_count):
                self.squares.append(random_square(self.screen_w, self.screen_h))

        # draw a blank screen
        self.screen.fill([0, 0, 0])

        # draw the squares
        for square in self.squares:
            rect = (square.x_loc, square.y_loc, self.square_size, self.square_size)
            pygame.draw.rect(self.screen, square.color, rect, 0)

        pygame.display.update()

        # remove a single square from the list as one tick has elapsed
        self.squares.pop()

# initialize pygame
pygame.init()

# figure out the parameters of the display we're connected to
screen_width = pygame.display.Info().current_w
screen_height = pygame.display.Info().current_h
screen_size = screen_width, screen_height

# determine the number of seconds until midnight
seconds_in_a_day = 86400
now = datetime.datetime.now()
midnight = now.replace(hour=0, minute=0, second=0, microsecond=0)
seconds_until_midnight = seconds_in_a_day - (now - midnight).seconds

# create and start the clock!
cl = clock(seconds_until_midnight, seconds_in_a_day, screen_width, screen_height)
cl.start()

Let’s walk through some of the design decisions of this code. The first thing that’s worth talking about is how the data for the squares is handled:

class random_square(object):
    def __init__(self, max_x_location, max_y_location):

        self.x_loc = randint(0, max_x_location)
        self.y_loc = randint(0, max_y_location)

        max_color_value = 255

        red = randint(0, max_color_value)
        green = randint(0, max_color_value)
        blue = randint(0, max_color_value)

        self.color = [red, green, blue]

It’s just an object with no methods, and on initialization, all the parameters of the square (location and color) are generated randomly as opposed to just floating the raw numbers in arrays around (even though that’s basically what is happening). This let’s us fill the squares array very easily later on in the file here:

# fill the squares with the inital seconds until midnight
for second in range(initial_count):
    self.squares.append(random_square(screen_w, screen_h))

and here:

# this will happen once per "day"
if len(self.squares) == 0:

    # fill the list of squares to be drawn
    for second in range(self.max_count):
        self.squares.append(random_square(self.screen_w, self.screen_h))

When it comes time to draw these squares, it also makes that pretty intuitive:

# draw the squares
for square in self.squares:
    rect = (square.x_loc, square.y_loc, self.square_size, self.square_size)
    pygame.draw.rect(self.screen, square.color, rect, 0)

Again, very simple stuff, but worth it to talk about.

I’ll be back at my place that has the Raspberry Pi and display I would like to use for this project, so more on this then.

Thanks for reading!

Blink out IP address for Raspberry Pi using Python

So in the final chapter of the long saga that has been connecting my Raspberry Pi to my Campus’s WiFi network, I needed a way to obtain the IP address of the Pi without using a display or a serial cable.

I’m actually pretty proud of this and I think it’s an elegant solution to a fairly annoying problem. Here’s a video of the system in action:

The program starts with three blinks. After that, the pattern goes as follows:

Blink Blink Blink Pause = 3
Blink Blink Pause = 2

So

Blink Blink Blink Pause Blink Blink Blink Blink Pause Blink = 341

Etc. Four short blinks indicate a 0 and six short blinks indicate a “.”

Once the address is fully read out, three long blinks will occur.

Here’s the code:

import RPi.GPIO as GPIO ## Import GPIO library

import time
GPIO.setmode(GPIO.BCM) ## Use board pin numbering

led = 20
button = 21

GPIO.setup(led, GPIO.OUT) ## Setup GPIO Pin 7 to OUT
GPIO.setup(button, GPIO.IN)

from subprocess import *

while 1:
	if (GPIO.input(button)):
	
		ip = Popen("ip addr show wlan0 | grep inet | awk '{print $2}' | cut -d/ -f1", shell=True, stdout=PIPE).communicate()[0]
			
		for x in range(3): #three rapid blinks to indicate procedure is starting
			
			GPIO.output(led,True)
			time.sleep(.2)
			GPIO.output(led,False)
			time.sleep(.2)
		
		time.sleep(3) # followed by a delay
		
		for x in list(ip):
		
			time.sleep(4) #a long delay between characters
			
			if x.isdigit():
				if (int(x) == 0):
					for x in range(4): #four rapid blinks indicate a 0
						
						GPIO.output(led,True)
						time.sleep(.2)
						GPIO.output(led,False)
						time.sleep(.2)
					
									
				elif (int(x) != 0):
					for y in range(int(x)):
						
						GPIO.output(led,True)
						time.sleep(.5)
						GPIO.output(led,False)
						time.sleep(.5)

			elif (x == '.'):
				for x in range(6): #six rapid blinks indicate a .
					
					GPIO.output(led,True)
					time.sleep(.1)
					GPIO.output(led,False)
					time.sleep(.1)
		
				time.sleep(5)
			
			elif (x == '\n'):
				for x in range(3): #six rapid blinks indicate a '.'
					
					GPIO.output(led,True)
					time.sleep(2)
					GPIO.output(led,False)
					time.sleep(2)
		

You can make it run every time the Pi boots with:

crontab -e

Add the following line:

@reboot screen -d -m sudo python /path/to/script/Blink_IP.py

And your good to go! You can now press the button any time the pi boots to get the IP address without connecting anything!

Parsing Serial Data Sent To Arduino

I use this code constantly. It basically packages serial data for strtok_r to split into pieces paced on predefined deliminators. Each bit of data is separated by a “,” and the end of the set of data is a “.”

If you send in a string like:

10,50,100.

You can split it into three varaibles that equate to those different values. In this case:

int x = atoi(subStr(serialbuf, ",", 1))

The Variable x would equate to 10.

Here’s the code:

const char EOPmarker = '.'; //This is the end of packet marker
char serialbuf[32]; //This gives the incoming serial some room. Change it if you want a longer incoming.

#include <SoftwareSerial.h>
#include <string.h> // we'll need this for subString
#define MAX_STRING_LEN 20 // like 3 lines above, change as needed.

SoftwareSerial SoftSer(11, 10); // RX, TX

void setup(){
  Serial.begin(9600);
  SoftSer.begin(9600);
}

void loop() {
    if (SoftSer.available() > 0) { //makes sure something is ready to be read
      static int bufpos = 0; //starts the buffer back at the first position in the incoming serial.read
      char inchar = SoftSer.read(); //assigns one byte (as serial.read()'s only input one byte at a time
      if (inchar != EOPmarker) { //if the incoming character is not the byte that is the incoming package ender
        serialbuf[bufpos] = inchar; //the buffer position in the array get assigned to the current read
        bufpos++; //once that has happend the buffer advances, doing this over and over again until the end of package marker is read.
      }
      else { //once the end of package marker has been read
        serialbuf[bufpos] = 0; //restart the buff
        bufpos = 0; //restart the position of the buff

        /*

          THIS IS WHERE THE CODE HAPPENS

        */

      }
    }
}

char* subStr (char* input_string, char *separator, int segment_number) {
  char *act, *sub, *ptr;
  static char copy[MAX_STRING_LEN];
  int i;
  strcpy(copy, input_string);
  for (i = 1, act = copy; i <= segment_number; i++, act = NULL) {
    sub = strtok_r(act, separator, &ptr);
    if (sub == NULL) break;
  }
 return sub;
}

Here’s an example.

Say you have a serial device hooked up to your softserial port and in inputs “10,50,100.” to the arduino to be split up. If you want to set each of these numbers to separate integers and then print them to the serial console, you’d do it like this.

const char EOPmarker = '.'; //This is the end of packet marker
char serialbuf[32]; //This gives the incoming serial some room. Change it if you want a longer incoming.

#include <SoftwareSerial.h>
#include <string.h> // we'll need this for subString
#define MAX_STRING_LEN 20 // like 3 lines above, change as needed.

SoftwareSerial SoftSer(11, 10); // RX, TX

void setup(){
  Serial.begin(9600);
  SoftSer.begin(9600);
}

void loop() {
    if (SoftSer.available() > 0) { //makes sure something is ready to be read
      static int bufpos = 0; //starts the buffer back at the first position in the incoming serial.read
      char inchar = SoftSer.read(); //assigns one byte (as serial.read()'s only input one byte at a time
      if (inchar != EOPmarker) { //if the incoming character is not the byte that is the incoming package ender
        serialbuf[bufpos] = inchar; //the buffer position in the array get assigned to the current read
        bufpos++; //once that has happend the buffer advances, doing this over and over again until the end of package marker is read.
      }
      else { //once the end of package marker has been read
        serialbuf[bufpos] = 0; //restart the buff
        bufpos = 0; //restart the position of the buff

        int x = atoi(subStr(serialbuf, ",", 1));
        int y = atoi(subStr(serialbuf, ",", 2));
        int z = atoi(subStr(serialbuf, ",", 3));

        Serial.print("The first number, x is: ");
        Serial.print(x);
        Serial.print(" - The second number, y is: ");
        Serial.print(y);
        Serial.print(" - The third number, z is: ");
        Serial.print(z);
        Serial.println();

      }
    }
}

char* subStr (char* input_string, char *separator, int segment_number) {
  char *act, *sub, *ptr;
  static char copy[MAX_STRING_LEN];
  int i;
  strcpy(copy, input_string);
  for (i = 1, act = copy; i <= segment_number; i++, act = NULL) {
    sub = strtok_r(act, separator, &ptr);
    if (sub == NULL) break;
  }
 return sub;
}

Getting a Raspberry Pi on Worcester Polytechnic Institute (WPI) WiFi (WPA-EAP)

The following is a very specific guide and like all guides of this nature written by me it is mostly for my benefit so I can come back to it later. It is a modification of this guide written by Campus IT.  If you have any suggestions to improve anything, PLEASE shoot me an email or leave me a comment below.


I will be connecting my Raspberry Pi Model B+ running the latest build of Raspbian using the Edimax EW-7811Un WiFi dongle to this kind of network (From Campus IT):

Specifically, WPI requires 802.1x EAP-TLS certificate based authentication. This is sometimes referred to as WPA Enterprise

Having an internet connection will make doing this much much easier. In fact, if all you need to do is share your laptops WiFi with the Pi over the Ethernet port on your laptop that is quite easy (For WPI people please note that this is a violation of the networks’ acceptable use policy). For windows 8.1:

First, we will have to enable sharing our Wi-Fi through the Ethernet ports of our computer.

Open the Network and Sharing center on your computer. It is found under Control Panel->Network and Internet->Network and Sharing Center.
Next, click on “change adapter settings.”
Right click on your Wi-Fi, and select “Properties.” You will most likely need to be an administrator for this step.
Click on the “Sharing” tab.
Check the “Allow other network users to connect through this computer’s Internet connection” checkbox.
Hit OK to close this window.
Next, we will connect to the raspberry Pi over our Ethernet cable.

Open up cmd. Type “ping raspberrypi.mshome.net” into the command line. Do not use any quotes when you type in this command.
Take note of this IP address. You can connect to the Pi through Putty using that IP address.

If you’re using a fresh install, make sure you set the Pi’s internal time to the proper time using raspi-config. It’s under internationalization options.

sudo raspi-config

You will then need to register the MAC address

Next we need to acquire the proper certificates.

Campus IT has already created a good tutorial for doing this found here. You’ll want two get two certificates seen here:

Move those two documents onto the Pi as well. I’m using

/home/pi/certs/

as the location for my certificates for the sake of this tutorial.

From there you’ll have to convert the ‘certificate.p12’ document to a .pem format with OpenSSL. OpenSSL is installed by default in Raspian. Do this with the following command:

openssl pkcs12 -in /home/pi/certs/certificate.p12 -out /home/pi/certs/certificate.pem -nodes

Enter the password for the NETWORK when prompted. We now have 3 certificate files. The CA-.pem, certificate.p12 and certificate.pem all located in the /home/pi/certs directory on the pi.

Next we have to disable all the default wifi settings that come with Raspian. Do this by changing your /etc/network/interfaces file to the following:

auto lo

iface lo inet loopback
iface eth0 inet dhcp

#allow-hotplug wlan0
#iface wlan0 inet manual
#wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
#iface default inet dhcp

Doing this stops the Pi from trying to use the wlan0 device at boot and will allow us to use it directly.

Now we must configure wpa_supplicants. It doesn’t really matter where you put the configuration file, but the raspberry pi places it by default here:

/etc/wpa_supplicant/wpa_supplicant.conf

Edit the file to look like the following. Note that things you WILL have to change are marked with []’s. Also note that this config places all 3 certs in that directory I’ve mentioned a few times.

#ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
#update_config=1

network={
 ssid="WPI-Wireless"
 key_mgmt=WPA-EAP
 proto=WPA2
 pairwise=CCMP
 group=CCMP
 eap=TLS

 identity="[YOUR_WPI_EMAIL]@wpi.edu"

 ca_cert="/home/pi/certs/CA-[A_BUNCH_OF_NUMBERS].pem"
 client_cert="/home/pi/certs/certificate.pem"
 private_key="/home/pi/certs/certificate.p12"
 private_key_passwd="[YOUR_WPI_EMAIL_PASSWORD]"

 priority=1
}

I found that in an example configuration of wpa_supplicant.conf specifically notes the need of a .pem file for the client cert, thus the conversion.

We’re pretty much done, all we need to do is add a few steps to the boot process to start the whole process each time the device boots. We can use crontab or /etc/rc.local (thanks Greg Tighe) to accomplish this.

With Crontab:

crontab -e

Add the two lines to the file:

@reboot sudo wpa_supplicant -c /etc/wpa_supplicant/wpa_supplicant.conf -i wlan0
@reboot sudo /sbin/dhclient wlan0

or edit /etc/rc.local to contain:

@reboot sudo wpa_supplicant -c /etc/wpa_supplicant/wpa_supplicant.conf -i wlan0

And reboot your pi! Everything should connect and work.