Python 2.7 Tkinter GUI Example Code

February 28, 2015
Tags:

Some example code for future reference.


# This accepts preformatted text from textedit and formats it

from bs4 import BeautifulSoup
import collections
import Tkinter as tk
import sys


class MyWindow(tk.Frame):

    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.parent = parent
        self.grid()
        self.article_url = tk.StringVar()
        self.article_title = tk.StringVar()
        self.current_status = tk.StringVar()
        self.choice = tk.IntVar()
        self.article_total = 0
        for items in links.items():
            self.article_total += 1
        self.article_count = 0
        self.label = tk.Label(root, text="Welcome! Where does this article belong?", relief='raised')
        self.label.grid(column=0, row=0, pady=5)

        self.article_title.set(links.items()[0][0])
        self.article_url.set(links.items()[0][1])
        self.article_title_label = tk.Label(root, textvariable=self.article_title, wraplength=500, width=70, height=5, font=('TkDefaultFont', 16), background='lightgrey')
        self.article_title_label.grid(column=0, row=1, padx=0)

        self.article_url_label = tk.Label(root, textvariable=self.article_url, wraplength=550, relief='raised', width=70, height=10)
        self.article_url_label.grid(column=0, row=2)

        #Radio Buttons
        self.radbutton1 = tk.Radiobutton(root, text="Government", variable=self.choice, value=1, background='lightgrey')
        self.radbutton1.grid(column=0, row=3, sticky='w', padx=275)

        self.radbutton2 = tk.Radiobutton(root, text="Private", variable=self.choice, value=2, background='lightgrey')
        self.radbutton2.grid(column=0, row=4, sticky='w', padx=275)

        self.radbutton3 = tk.Radiobutton(root, text="Other", variable=self.choice, value=3, background='lightgrey')
        self.radbutton3.grid(column=0, row=5, sticky='w', padx=275)

        self.radbutton4 = tk.Radiobutton(root, text="Discard", variable=self.choice, value=4, background='lightgrey')
        self.radbutton4.grid(column=0, row=6, sticky='w', padx=275)

        #Submit button
        self.button = tk.Button(root, text="Submit", command=self.looper, background='lightgrey')
        self.button.grid(column=0, row=7)

        #Status label
        self.status_label = tk.Label(root, textvariable=self.current_status, background='lightgrey')
        self.status_label.grid(column=0, row=8)
        self.current_status.set("Start")

        #Zombatar
        self.zombatar_label = tk.Label(image=photo, background='lightgrey')
        self.zombatar_label.grid(column=0, row=8, sticky='w', padx=220)

        #set the default radio button to selected
        self.choice.set(1)

    def looper(self):
        #refresh view to display different article titles and urls

        html_link = '<p><a href="' + links.items()[self.article_count][1] + '" target="blank">' + links.items()[int(self.article_count)][0] + '</a></p>'

        self.article_total -= 1

        if self.article_total < 1:
            self.current_status.set("Done!!!")
            self.button.configure(text='Quit', command=self.quit)

        self.current_status.set(str(self.choice.get()) + ' | ' + str(self.article_count) + ' | ' + str(self.article_total))
        if self.choice.get() == 1:
            #print 'gov ' + html_link
            ordered_dict_final['1'][str(self.article_count)] = html_link

        elif self.choice.get() == 2:
            #print 'priv ' + html_link
            ordered_dict_final['2'][str(self.article_count)] = html_link

        elif self.choice.get() == 3:
            #print 'other ' + html_link
            ordered_dict_final['3'][str(self.article_count)] = html_link

        self.article_count += 1
        try:
            self.article_title.set((links.items()[self.article_count][0]))
            self.article_url.set((links.items()[self.article_count][1]))
        except IndexError:
            self.article_title.set("All Done!")
            self.article_url.set('')

        self.choice.set(1)

    def quit(self):
        #write the output file
        for key in ordered_dict_final.keys():
            if key == '1':
                 outputfile.write(gov_text)
            elif key == '2':
                 outputfile.write(priv_text)
            elif key == '3':
                 outputfile.write(other_text)
            for item in ordered_dict_final[key]:
                 #print ordered_dict_final[key][item].encode('ascii', 'ignore')
                 outputfile.write(ordered_dict_final[key][item].encode('ascii', 'ignore') + '\n')

        outputfile.write('</div>')
        #print 'done!'
        sys.exit()


if __name__ == "__main__":

    root = tk.Tk()
    links = collections.OrderedDict()
    ordered_dict_final = collections.OrderedDict()
    ordered_dict_final['1'] = {}
    ordered_dict_final['2'] = {}
    ordered_dict_final['3'] = {}

    gov_text = '''<!--------------------------------------------------------------------------------------------------------------------------------------------->
<p>&nbsp;</p>
<!--Government News-->
<p>&nbsp;</p>
<!--------------------------------------------------------------------------------------------------------------------------------------------->
<div class="sechead"><img class="article-img" alt="" src="/images/news/article-img/gov.png" />\n'''

    priv_text = '''</div>
<!--------------------------------------------------------------------------------------------------------------------------------------------->
<p>&nbsp;</p>
<!--Private Sector News-->
<p>&nbsp;</p>
<!--------------------------------------------------------------------------------------------------------------------------------------------->
<div class="sechead"><img class="article-img" alt="" src="/images/news/article-img/pri.png" />\n'''

    other_text = '''</div>
<!--------------------------------------------------------------------------------------------------------------------------------------------->
<p>&nbsp;</p>
<!--Other Security News-->
<p>&nbsp;</p>
<!--------------------------------------------------------------------------------------------------------------------------------------------->
<div class="sechead"><img class="article-img" alt="" src="/images/news/article-img/sec.png" />\n'''

    outputfile = open('articles_output.txt', 'w')
    f = open('cyberarticles.html', 'r')
    s = f.read()
    soup = BeautifulSoup(''.join(s))

    for a in soup.find_all('a', href=True):
        links[a.text] = a['href']

    #zombatar ico
    icon = """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"""
    photo = tk.PhotoImage(format='gif', data=icon)
    root.tk.call('wm', 'iconphoto', root._w, photo)
    root.geometry("650x460+250+250")
    root.configure(background='lightgrey')
    root.resizable(False, False)
    root.title("Article Sorter")
    root.lift()
    MyWindow(root)
    root.mainloop()
0

Rogue System Detection with Splunk

November 7, 2014

This Splunk search allows you to be alerted when a new IP is seen by Bro. The requirements for this alert to work are the bro_known_hosts log and a CSV with all allowed IP addresses. Setup the CSV as an automatic lookup table. The automatic lookup table is setup based on the host (securityonion) and contains this mapping (assuming your lookup table is named lan_lookup), lan_lookup ip AS id_orig_h OUTPUTNEW name AS hostname. The below image shows the setup of the CSV file. A Splunk app called Lookup Editor is very helpful in adding new hostnames.

lan_lookup

 

 

 

 

With the automatic lookup setup, a new field called hostname will appear in search results for data coming from the host securityonion. The hostname field will be populated with whatever is put in the name column of the CSV. Once this is setup, use the following search to find new IPs that are not in the CSV.

sourcetype=bro_known_hosts src_ip=”192.168.*” |fillnull value=0| search hostname=0| stats count by src_ip

This search will only have results when an IP shows up in the bro_known_hosts log that starts with 192.168. and does not have a name in the CSV file you created. This methodology works fine for very small LANs, but will not easily scale up. For larger environments, a DNS query could be used to ensure the IP is a known host.

 

0

Splunk free Configuration

March 14, 2014
Tags: ,

Splunk Free

This is the second post in how to setup pfSense, Squid, and Splunk. Here is a link to the first post, pfSense, Squid, and Splunk free

Sometime around 2013 Splunk switched to a paid and free version. The free version does not allow for emailed alerts or user authentication. For this post, I will be configuring Splunk for a daily digest email sent through a local postfix installation. This post starts after Ubuntu and Splunk are installed and Splunk is already being populated with events from pfSense (or another source)  via syslog. I am using Splunk version 6.0 and Ubuntu 12.04 for this setup. The main purpose for setting up Splunk was to get notifications of events. To gain that functionality back let’s use Python. This post assumes the reader already has a grasp on Python.  I am using Python 2.7.3 for these examples. To get started, install the Splunk SDK for Python. This is a Python module that allows you to interact with Splunk. Once the module is installed attempt to connect to your Splunk instance. Here is my code:

#!/usr/bin/python


#imports
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.MIMEImage import MIMEImage
import splunklib.client as client
import splunklib.results as results
import sys
from time import sleep
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np
import datetime as DT
from matplotlib.dates import date2num

#variables
HOST = "localhost"
PORT = 8089
USERNAME = "admin"
PASSWORD = ""
strFrom= 'admin@admin.com'
strTo= 'youremail@gmail.com'

##smtp init
##Create the root message and fill in the from, to, and subject headers
msgRoot = MIMEMultipart('related')
msgRoot['Subject'] = 'Message From Splunk'
msgRoot['From'] = strFrom
msgRoot['To'] = strTo
msgRoot.preamble = 'This is a multi-part message in MIME format.'

#SPLUNK
#get Top 20 Block FW ports
service = client.connect(host=HOST,port=PORT,username=USERNAME,password=PASSWORD)
#set the search from 7 days ago midnight to yesterday midnight. 
kwargs = {"earliest_time": "-8d@d", "latest_time": "@d"}

#function to wait the script for the search to finish
def polling():
     while True:
          job.refresh()
          #print job.is_done()
          if job.is_done():
                  break
          else:
                 sleep(5)

#message body
msgAlternative = MIMEMultipart('alternative')
msgRoot.attach(msgAlternative)

msgText = MIMEText('This is the alternative plain text message.')
msgAlternative.attach(msgText)

###############
#
#First query
#
###############
searchquery_normal = "search block in on em0 | chart count by dest_port | sort count desc | head 20"
#kwargs = {"earliest_time": "-7d@h"}
job = service.jobs.create(searchquery_normal, **kwargs)

polling()
splunk_text += """<h3>Top 20 Blocked Ports & URLS Last 7 Days</h3></b><table border ="0" cellpadding="3"><tr><td valign="top"><table border="1" cellpadding="3"><tr><td><b>Port</b></td><td><b>Count</b></td></tr>\n"""
#add in the splunk text too
for result in results.ResultsReader(job.results(segmentation='none')):
splunk_text += "<tr><td>" + str(result['dest_port'])+ "</td><td>" + str(result['count']) + "</td></tr>\n"

#close first table
splunk_text += """</table></td>"""

########end of table##########
splunk_text += """</table><br>"""

msgText = MIMEText(splunk_text, 'html')
msgAlternative.attach(msgText)

smtpObj = smtplib.SMTP('localhost')
smtpObj.sendmail(strFrom, strTo, msgRoot.as_string())
smtpObj.quit()

I have omitted some of this code for the sake of brevity. The code is setup to be formatted as a table for an email. The machine that is running Splunk is also running postfix which is configured to send email out. The code that I removed is additional queries to Splunk and uses matplotlib to create an image file to graphically represent my data. If anyone is interested please leave a comment and I can post the full code.

The next step would be to setup a daily cron job that would run this python code and you would then have a daily digest email with data about your network!

0

pfSense, Squid, and Splunk free

March 14, 2014

pfSense and Squid

I am continuously impressed with the amount and quality of free software that is available on the internet. pfSense is an open source firewall based on FreeBSD with a web based interface and easy to add packages. It has most standard firewall features, but also includes advanced features such as VPN, captive portal, and proxy filter. For this post I used version 2.1-RELEASE. After installing pfSense and configuring it for my network, I wanted to setup a way to analyze the firewall block logs and the proxy access traffic.

pfsense squid and splunk

To do this I first setup Squid. Squid is a proxy for caching web content. I am using the 2.7.9 pkg v.4.3.3 version for this post. For steps to configure squid in pfSense follow this guide. https://doc.pfsense.org/index.php/Setup_Squid_as_a_Transparent_Proxy. Once Squid is setup, it needs to be configured to forward its logs to Splunk. If you try to modify squid via the command line, any updates will overwrite your changes. To avoid this, add in the custom changes to the Custom Options text box within the squid package in pfSense.

pfsense and squid

Add this line to view the access log in Splunk.

access_log syslog:local7.info;

This will forward the access_log to syslog local7. I choose local7 because pfSense was already using this syslog for the DHCP log. By using local7, the squid access logs are mixed in with the DHCP logs, but this doesn’t matter because Splunk can filter the two. To forward the logs to Splunk, configure the remote logging options in pfSense.

pfsense syslog edit

Be sure to enable remote logging and input the IP of the remote Splunk server. pfSense will be sending the syslog via UDP over port 514. Be sure to allow that port through the firewall on the Splunk server. You have to check the box next to DHCP service events to forward the Squid access logs. I also like to see the Firewall events in Splunk so I checked it as well.

Splunk free

Let’s verify that we are seeing UDP traffic on port 514 from the Splunk server. I have already installed Splunk on Ubuntu 12.04 server edition. To test the UDP traffic run this command.

sudo tcpdump -i eth0 udp port 514

This will start tcpdump on interface eth0 and filter for UDP port 514 traffic. If you see information on the screen, then the syslog forward is working. Now let’s configure Splunk.

For this post I am using Splunk free version 6.0. Because I have already setup a data input over UDP these instructions may be different than an initial setup. Click on Settings -> Data inputs, then Add Data.  Choose Syslog as the data type. Click on Next under the Consume syslog over UDP. Fill out the text field for UDP port with 514 and the source name override as pfSense. Finally, click Save. Give Splunk a minute to begin collecting data then go to the Search and Reporting App to see if you have any events indexed. If you are not seeing any events you can leave a comment below for help troubleshooting the issue. If you can see events then you are ready to further configure Splunk!

 

0

SparkFun Robotic Arm Clock with Ethernet Shield

July 17, 2013
Tags: ,

After I learned how to code the Arduino and work with the SparkFun claw, I wanted to build something that could be useful, stay out of the way, and always be running. I settled on a clock. To incorporate the robotic arm in to the clock I set the arm up to move like a minute hand. I can roughly tell what minute it is based on the location of the arm. In addition to the motion, the clock also plays a chime every hour. To find out what the temperature is I added a temperature sensor and LCD to display the temperature, time, and date. The date and time is loaded by the ethernet shield over NTP (Network Time Protocol). The ethernet shield also makes it possible to run a web page. The web page that is running allows the robotic arm to be controlled over the internet. The current setup allows me to fully utilize the functionality of the robotic arm and ethernet shield.

Full Clock

 Arm Mounting

To mount the robot arm to the wooden box I used erector set parts.

Inside the Box

With all the electrical parts inside the wooden box it can warm up. I do not trust the temperature sensor that is mounted on the breadboard.  I have plans of purchasing a better temperature sensor and mounting it on the outside of the box to get a better reading.

 

SparkFun Robotic Arm Clock_bb

The LCD required so many pins I had to add in a shift register. Obviously, the speaker was needed to play the chime. The pot is used as a dimmer for the LCD. The three servos are used in the arm. I found an old wall charger to get the needed 6v 2.0A for the servos. The arduino is powered with a 5v wall charger. So the clock requires two wall chargers. For the NTP and ethernet shield an ethernet wire is required.

Code

This was written on Windows 7 with the Arduino 1.0.3 IDE. In order for the code to work you have to install extra libraries such as Time and LiquidCrystal_SR. Due to the html in the code, I don’t have it as part of the post. You can download it here:

download_button

The clock has two modes, clock mode and web mode. When the clock is in clock mode it acts like a clock with the arm moving every minute and a chime every hour. When the clock is in web mode the arm moves based on what links on the web site are clicked. The LCD is updated to show web mode. If no links are clicked on the web site after 30 seconds, the clock returns to clock mode.

  Video

Parts List

From Sparkfun.com:

Arduino Uno R3 – $30

Arduino Ethernet Shield – $46

Sparkfun Robotic Claw – $12

Sparkfun Robotic Claw Pan/Tilt Bracket – $30

Miscellaneous Erector Set pieces

Breadboard – $5

2 Medium/Standard Servos – $12/ each

Small Speaker – $4

Temperature Sensor – $2

Potentiometer – $1

Shift Register IC 74HC595 – $1.50

From Amazon:

LCD Module for Arduino 20 x 4, White on Blue – $12

From the junk pile:

6V 2A power for servos

0

Even More Example Code SparkFun Robotic Arm

March 3, 2013
Tags: ,

This code allows you to control the arm with serial commands.  The keys 1-6 are used to control the servos.


/*
Robot console

This code will control the arm via serial commands

*/

#include Servo.h

Servo servo1; //base-pan
Servo servo2; //arm-tilt
Servo servo3; //claw

void setup()
{
  Serial.begin(9600);
  servo1.attach(9);  //pan range is 20 to 140
  servo2.attach(10); //tilt range is 0 to 179
  servo3.attach(11); //claw range is 70 to 130
}

void loop()
{

  int incomingData = 0;
  
  //listen for serial input
  Serial.flush();
  while(Serial.available() > 0) {
    incomingData = Serial.read();
    if(incomingData == 49 && servo1.read() > 20) {
      int pos;
      int pos2;
      pos = servo1.read();
      pos2 = servo1.read() - 5;
      for(pos; pos > pos2; pos -= 1)
      {
        servo1.write(pos);
        Serial.print("PanNum: ");
        Serial.println(pos);
      
        delay(25);
      }      
    }
    else if (incomingData == 50 && servo1.read() < 140) {
      int pos;
      int pos2;
      pos = servo1.read();
      pos2 = servo1.read() + 5;
      for(pos; pos < pos2; pos += 1)
      {
        servo1.write(pos);
        Serial.print("PanNum: ");
        Serial.println(pos);
        delay(25);
      }
    }
    else if (incomingData == 51 && servo2.read() > 6) {
      int pos;
      int pos2;
      pos = servo2.read();
      pos2 = servo2.read() - 5;
      for(pos; pos > pos2; pos -= 1)
      {
        servo2.write(pos);
        Serial.print("TiltNum: ");
        Serial.println(pos);
        delay(25);
      }
    }
    else if (incomingData == 52 && servo2.read() < 174) {
      int pos;
      int pos2;
      pos = servo2.read();
      pos2 = servo2.read() + 5;
      for(pos; pos < pos2; pos += 1)
      {
        servo2.write(pos);
        Serial.print("TiltNum: ");
        Serial.println(pos);
        delay(25);
      }
    }
    else if (incomingData == 53 && servo3.read() > 76) {
      int pos;
      int pos2;
      pos = servo3.read();
      pos2 = servo3.read() - 5;
      for(pos; pos > pos2; pos -= 1)
      {
        servo3.write(pos);
        Serial.print("ClawNum: ");
        Serial.println(pos);
        delay(25);
      }
    }
    else if (incomingData == 54 && servo3.read() < 124) {
      int pos;
      int pos2;
      pos = servo3.read();
      pos2 = servo3.read() + 5;
      for(pos; pos < pos2; pos += 1)
      {
        servo3.write(pos);
        Serial.print("ClawNum: ");
        Serial.println(pos);
        delay(25);
      }
    }
  }
}

 

 

0

More Example Code SparkFun Robotic Arm

February 23, 2013
Tags: ,

I have continued to tweak the code for the robot demo. I call this code Robot Instructions. It allows me to call two different functions. The first function moves the arm very quickly and the second function moves the arm slowly. This is for the Arudino Uno with a three servo robotic arm sold from SparkFun.com.

/*
Robot instructions
Brad Poulton
*/

#include <servo.h>

Servo servo1; //base-pan
Servo servo2; //arm-tilt
Servo servo3; //claw

void setup()
{
  Serial.begin(9600);
  servo1.attach(9);  //pan range is 20 to 140
  servo2.attach(10); //tilt range is 0 to 179
  servo3.attach(11); //claw range is 70 to 130
}

void loop()
{
  //Put your instructions here
  //DANCE Moves
  //robotInst(100,20,120,10);
  //robotInst(80,65,100,10);
  //robotInst(140,160,70,10);

  //move a BLOCK
  robotInst(130,65,70,25);
  robotMove(130,165,70);
  robotInst(130,165,120,25);
  robotMove(50,165,120);
  robotMove(50,130,70);

}

void robotMove(int a, int b, int c)
{
  //move the servos fast!
  servo1.write(a);
  delay(25);
  servo2.write(b);
  delay(25);
  servo3.write(c);
  delay(25);

}

void robotInst(int a, int b, int c, int d)
{
  int pos;
  ////////
  //
  //PAN
  //
  ///////
  if (a < servo1.read()){     
    for(pos = servo1.read(); pos > a; pos -= 1)
    {
      servo1.write(pos);
      Serial.print("PanNum: ");
      Serial.println(pos);

      delay(d);
    }

  } else if (a > servo1.read()){
    for(pos = servo1.read(); pos < a; pos += 1)
    {
      servo1.write(pos);
      Serial.print("PanNum: ");
      Serial.println(pos);

      delay(d);
    }

  } else {

    Serial.println("equals");
  }

  ////////
  //
  //TILT
  //
  ///////
  if (b < servo2.read()){     
    for(pos = servo2.read(); pos > b; pos -= 1)
    {
      servo2.write(pos);
      Serial.print("TiltNum: ");
      Serial.println(pos);

      delay(d);
    }

  } else if (b > servo2.read()){
    for(pos = servo2.read(); pos < b; pos += 1)
    {
      servo2.write(pos);
      Serial.print("TiltNum: ");
      Serial.println(pos);

      delay(d);
    }

  } else {

    Serial.println("equals");
  }

  ////////
  //
  //Claw
  //
  ///////
  if (c < servo3.read()){     
    for(pos = servo3.read(); pos > c; pos -= 1)
    {
      servo3.write(pos);
      Serial.print("ClawNum: ");
      Serial.println(pos);

      delay(d);
    }

  } else if (c > servo3.read()){
    for(pos = servo3.read(); pos < c; pos += 1)
    {
      servo3.write(pos);
      Serial.print("ClawNum: ");
      Serial.println(pos);

      delay(d);
    }

  } else {

    Serial.println("equals");
  }

  Serial.print("ClawNum Final: ");
  Serial.println(pos);

  Serial.print("Servos: ");
  Serial.print(servo1.read());
  Serial.print(" ");
  Serial.print(servo2.read());
  Serial.print(" ");
  Serial.println(servo3.read());
}

 

1

Example Code SparkFun Robotic Arm

February 23, 2013
Tags: ,

Here is some more example code for a 3 servo arm. I call this the robot demo. It simply moves the robot around slowly.


/*
Robot demo

*/

#include   // servo library

Servo servo1; //base-pan
Servo servo2; //arm-tilt
Servo servo3; //claw

int posf1 = 140; //pan
int posf2 = 90;
int posf3 = 90;

void setup()
{
  Serial.begin(9600);
  servo1.attach(9);  //pan range is 10 to 170
  servo2.attach(10); //tilt
  servo3.attach(11); //claw range is 50 to 120
}

void loop()
{
  //pan
  for(posf1 = 140; posf1 > 20; posf1 -= 1)
  {
    servo1.write(posf1);
    Serial.print("PanNum: ");
    Serial.println(posf1);

    delay(25);
  }

  //pan
  for(posf1 = 20; posf1 < 140; posf1 += 1)
  {
    servo1.write(posf1);
    Serial.print("PanNum: ");
    Serial.println(posf1);

    delay(25);
  }

    //tilt
  for(posf2 = 179; posf2 > 1; posf2 -= 1)
  {
    servo2.write(posf2);
    Serial.print("TiltNum: ");
    Serial.println(posf2);
    delay(25);
  }

  //tilt
  for(posf2 = 1; posf2 < 179; posf2 += 1)
  {
    servo2.write(posf2);
    delay(25);
  }

  //claw
  for(posf3 = 130; posf3 > 70; posf3 -= 1)
  {
    servo3.write(posf3);
    delay(25);
  }

  //claw
  for(posf3 = 70; posf3 < 130; posf3 += 1)
  {
    servo3.write(posf3);
    delay(25);
  }

}
0

How To Assemble and Code the SparkFun Robotic Claw with Pan and Tilt for Beginners

February 22, 2013
Tags: ,

For Christmas 2012 I got the SparkFun Robotic Arm. I was unable to find any beginners guides that encompassed the full assembly and code. Here is my attempt. As a warning, I have no background experience in Arduino or electronics. Be sure to read the SparkFun product guides to know what additional equipment needs to be purchased. My build was delayed because I neglected to purchase the additional servos that do NOT come with the claw and pan/tilt hardware. I purchased the first generation of the claw. SparkFun now has a newer version of the claw (MKII) with a spring loaded clutch to protect the servo.

Claw Assembly

I would recommend following this guide (http://www.sparkfun.com/tutorials/258) for the assembly of the arm. I did not read these instructions the first time and it caused problems later on. Basically, you are mounting the servo so it will connect with the servo horn and claw.

UPDATE (2/22/13): I burnt up my first servo! The first generation SparkFun Claw has an alignment problem that has the potential to burn up servos. I had to replace the first servo I bought and the second generation claw has addressed this issue. On my second attempt, I added some washers to help keep the servo aligned with the claw gears.

Arm Assembly

The hardest part of the arm assembly is mounting the pan servo. SparkFun does not provide a solution for this. I made my own out of wood and Erector Set pieces.

IMG_1122 IMG_1123

When you decide on your own solution for this problem, consider the fact that the tilt servo can only go down so far. You do not want a very tall mount or you will not be able to pick up smaller objects with the claw. Making the pan servo mount compatible with the Erector Set will allow me to  add this claw to an Erector Set project.

Final Assembly

Here is a picture of the fully assembled arm.

IMG_1117

 

Arduino Wiring

I wanted to control the arm with two potentiometers and two buttons. Here are pictures of the layout.

SparkFun Robotic Arm_bb

SparkFun Robotic Arm – Fritzing

IMG_1120 IMG_1121

 

Servo Battery Power

Having no prior electronics experience, I had no idea that the 5 volts from the Arduino Uno could not support the three servos. After a lot of googling, I discovered I needed an external battery to power the servos. I used 4 AA batteries. I bought the hardware to hold the batteries from Radio Shack.

After using the AA batteries I found that when I used all 3 servos at the same time it was not enough power. To fix this, a wall adapter was used that supplied 6 volts and 2.0 amps. With this much electricity the arm worked very well.

Wall Adapter

Arduino Code

Here is the final code I used:


/*
Brad Poulton
Robotic Arm
*/

#include   // servo library

Servo servo1; //base-pan
Servo servo2; //arm-tilt
Servo servo3; //claw
const int sensorPin1 = 0; // The potentiometer is connected to analog pin 0
const int sensorPin2 = 1;
int sensorValue1;
int sensorValue2;
const int button1Pin = 2;  // pushbutton 1 pin
const int button2Pin = 3;  // pushbutton 2 pin
int button1State;
int button2State;
const int ledPin =  13;   //onboard LED
int clawNum = 50; //init clawNum 

void setup()
{
  Serial.begin(9600);
  pinMode(button1Pin, INPUT);
  pinMode(button2Pin, INPUT);
  pinMode(ledPin, OUTPUT);
  servo1.attach(9);  //pan range is 10 to 170
  servo2.attach(10); //tilt
  servo3.attach(11); //claw range is 50 to 120
  servo3.write(clawNum);  //open claw 
}

void loop()
{
  button1State = digitalRead(button1Pin);
  button2State = digitalRead(button2Pin);
  if (button1State == LOW){
    //open claw
    digitalWrite(ledPin, HIGH);  // turn the LED on
    if (clawNum < 150){
       clawNum = clawNum + 10;
     }
   }
   else if (button2State == LOW) {
     //close claw
     digitalWrite(ledPin, HIGH);  // turn the LED on
     if (clawNum > 50) {
      clawNum = clawNum - 10;
    }

  }
  else {
    digitalWrite(ledPin, LOW);  // turn the LED off
  }

  Serial.print("ClawNum: ");
  Serial.println(clawNum);
  servo3.write(clawNum);
  delay(20);

  //read in pot values
  sensorValue1 = analogRead(sensorPin1);
  sensorValue2 = analogRead(sensorPin2);

  //map the values
  sensorValue1 = map(sensorValue1, 30, 1023, 0, 170);
  sensorValue2 = map(sensorValue2, 0, 1023, 0, 179);

  servo1.write(sensorValue1);
  //Serial.print("Servo1: ");
  //Serial.println(sensorValue1);
  //move servo2
  servo2.write(sensorValue2);
  //Serial.print("Servo2: ");
  //Serial.println(sensorValue2);
  //wait
  delay(15);
}

After doing some testing, I found the claw only had a range from about 20 to 150 before it was stopped. I ran into a problem where the servo for the claw was getting really hot and the claw was not closing. This was caused by the nuts and bolts on the claw being too tight. Another issue I ran into was the way I wired up the battery and servos. I had an extra wire connecting the battery wire and the servo wires on the breadboard. For some reason, this extra wire caused short outs and made the servos act very strange.

Check out my other code examples!

Example Code SparkFun Robotic Arm

 

More Example Code SparkFun Robotic Arm

 

Conclusion

In retrospect, I have concluded that this is an ambitious project for someone who has no experience with electronics. I had no idea how many AMPs the servos needed and that the Arduino was not able to supply enough electricity, but just like many of my other projects, as I overcome problems I learn a lot at the same time.

Videos

 

Part List

From Sparkfun.com:

Arduino Uno R3 – $30

Sparkfun Robotic Claw – $12

Sparkfun Robotic Claw Pan/Tilt Bracket – $30

2 Medium/Standard Servos – $12/ each

2 Potentiometer – $1

Breadboard – $5

2 10k ohm Resistors (Brown Black Orange) – $1 https://www.sparkfun.com/products/11508

2 Push Button Switch – $0.35

From the junk pile:

6V 2A power for servos

Miscellaneous Erector Set/ Wood pieces

Wiring

2

Python 3.2 Tkinter GUI Beginners Example Code

February 2, 2013
Tags:

UPDATED (2/2/2013)

This example is now working. I had to add a sequence to the bind statements.

Have you ever wanted to add a simple GUI to an excellent python script without installing any additional modules? Here is some basic example code to help you. When I started I wanted a GUI solution that would work natively with Python 3.2. This search brought me to Tkinter. Tkinter has been around for a long time so I had trouble finding example code specifically for Python 3.2. I have included examples of items that are explained in this “how to” on Pythonware.com. This was written on a Windows (XP/7) machine with ActivePython 3.2 in Notepad++. Enjoy!

I ran into problems when running this script from the command line. I was successful when I opened the code in IDLE and pressed F5 for Run Module.


#!/usr/bin/env python
#--------------------------
#Brad 
#
#Aug 4
#
#Gui testing
#--------------------------

from tkinter import *
import tkinter.messagebox as tkMessageBox
import tkinter.simpledialog as tkSimpleDialog
import tkinter.filedialog as tkFileDialog
import tkinter.simpledialog as tkSimpleDialog
import os

#########################
#
#Global vars
#
#########################

labeltext = "Status"

########################
#
#Simple Dialog Class (Not used)
#
########################
class MyDialog(tkSimpleDialog.Dialog):

    def body(self, master):

        Label(master, text="First:").grid(row=0)
        Label(master, text="Second:").grid(row=1)

        self.e1 = Entry(master)
        self.e2 = Entry(master)

        self.e1.grid(row=0, column=1)
        self.e2.grid(row=1, column=1)
        return self.e1 # initial focus

    def apply(self):
        first = string.atoi(self.e1.get())
        second = string.atoi(self.e2.get())
        print (first)

##########################
#
#Define Functions
#
###########################
def windowclose():
	if tkMessageBox.askokcancel("Quit", "Do you really wish to quit?"):
		root.destroy()		

def tempwindow2():
	tkMessageBox.showwarning("Hi","close me")

def middlemouseclick(event):
	if tkMessageBox.askokcancel("Quit", "Do you really wish to quit?"):
		root.destroy()

#####CAPTURE MOUSE MOTION AND UPDATE LABELS############
def mousemotion(event):
		sx.set(event.x)
		sy.set(event.y)

#####CAPTURE MOUSE CLICK AND UPDATE LABELS#############
def mouseclick(event):
		cx.set(event.x)
		cy.set(event.y)

########CHANGE THE BACKGROUND BASED ON SCALE VALUE######
def scaleupdate(sc):
		#print (scalevalue.get())
		if scalevalue.get() == 0:
			frame.config(bg="lightblue")
		elif scalevalue.get() == 1:
			frame.config(bg="blue")
		elif scalevalue.get() == 3:
			frame.config(bg="red")
		elif scalevalue.get() ==5:
			frame.config(bg="green")
		else:
			frame.config(bg="yellow")

########UPDATE THE LABELS IN THE STATUS BAR########
def labelupdate(newtext):
		l.set(newtext)
		if ckb.get():
			n.set(n.get()+5)
		else:
			n.set(n.get()+1)

###########INPUT DATA################
def inputdata():
	x = tkSimpleDialog.askinteger("Input","Multiplier")
	if x:
		tkMessageBox.showwarning("Yes",x)
		listbox.insert(END, x)
	else:
		tkMessageBox.showwarning("No","You did it wrong")

############SELECT FILE#################
def fileselect():
	filename = tkFileDialog.askopenfilename()
	if filename:
		tkMessageBox.showwarning("Yes", filename)
	else:
		tkMessageBox.showwarning("No", "You did it wrong")

#####################################
#
#MAIN
#
#####################################

root = Tk()

###########ROOT WINDOW PROPERTIES#####
root.resizable(False,False)
root.iconbitmap(default="")  ##input your own ico file here. this will replace the default red Tk icon
root.title("Test")
root.attributes("-alpha", 1.0)
root.protocol("WM_DELETE_WINDOW", windowclose)

###############main frame##############
frame = Frame(root,relief='raised', border=4, bg="lightblue", padx=12)
frame.bind("<a>", mousemotion)
frame.bind("<a>", middlemouseclick)
frame.grid(column =0,row=1, sticky='w')

#############CLICK HERE#################
label = Label(frame, text="Click Here", cursor="gumby")
label.bind("<Enter>", mouseclick)
label.grid(column=0,row=0)

############HELLO########################
message = Message(frame, text="Hello")
message.grid(column=1,row=0)

############SCALE##########################
scalevalue = DoubleVar()
scalevalue.set(0)
scale = Scale(frame, activebackground="blue", background="red", to="10", troughcolor="green", width="25", command= scaleupdate, variable=scalevalue )
scale.grid(column=0,row=1, columnspan=2)

###################STATUS BAR###############
l = StringVar()
l.set("Status")
status = Label(root, textvariable=l, bd=1, relief=SUNKEN, anchor='w')
status.grid(column=0, row=4, sticky='w')

n = IntVar()
n.set(0)
status2 = Label(root, textvariable=n, bd=1, relief=SUNKEN, anchor='w')
status2.grid(column=0, row=4, sticky='w', padx=40)

sx = IntVar()
sx.set(0)
statusx = Label(root, textvariable=sx, bd=1, relief=SUNKEN, anchor='w')
statusx.grid(column=0, row=4, sticky='w', padx=65)

sy = IntVar()
sy.set(0)
statusy = Label(root, textvariable=sy, bd=1, relief=SUNKEN, anchor='w')
statusy.grid(column=0, row=4, sticky='w', padx=95)

cx = IntVar()
cx.set(0)
statuscx = Label(root, textvariable=cx, bd=1, relief=SUNKEN, anchor='w')
statuscx.grid(column=0, row=4, sticky='w', padx=125)

cy = IntVar()
cy.set(0)
statuscy = Label(root, textvariable=cy, bd=1, relief=SUNKEN, anchor='w')
statuscy.grid(column=0,row=4,sticky='w', padx=140)

####################RADIO BUTTONS###########
v = IntVar()
radbutton = Radiobutton(frame, text = "Option 1", variable=v, value=1)
radbutton.grid(column = 2, row = 0, sticky = NW)

radbutton2 = Radiobutton(frame, text = "Option 2", variable=v, value=2)
radbutton2.grid(column = 2, row = 1, sticky = NW)

#################CHECK BUTTONS##############
ckb = IntVar()
ckbbutton = Checkbutton(frame, text = "Add 5", variable=ckb)
ckbbutton.grid(column = 2, row= 2, sticky=NW)

#################LIST BOX#####################

listbox = Listbox(frame, selectmode=MULTIPLE)
listbox.grid(column=2, row=3, sticky=NW)

listbox.insert(END, "zero")
listbox.insert(END, "one")
listbox.insert(END, "two")

###################IMAGES IN BASE64 ############
img00 = PhotoImage(format='gif', data="R0lGODlhKwAQAJEAACWgA/3bYYNOGgAAACwAAAAAKwAQAAACfIyPqcsrD2M0oAJqa8h29yAkITiG3HWmKWiUrdtpseZdtcfmJSyjvf2Z5Q671u0wA9I+RtLjZcwgfxglTTchjqS34JUrCUMQySOzih07Tb62eeneqSfU8vsmf65xZa8S/zI3dlLD5deRl1dlxdT4MYIA2TBJuSZ2iZkZVgAAOw==")
img01 = PhotoImage(format='gif', data="R0lGODlhDwAPAKECAAAAzMzM/////wAAACwAAAAADwAPAAACIISPeQHsrZ5ModrLlN48CXF8m2iQ3YmmKqVlRtW4MLwWACH+H09wdGltaXplZCBieSBVbGVhZCBTbWFydFNhdmVyIQAAOw==")
cat = PhotoImage(file="") ##place your own .gif file here
open = PhotoImage(format='gif', data="R0lGODlhEAAQAIcAADFKY0L/QplnAZpoApxqBJ5sBqBuCKJwCqNxC6RyDKVzDad1D6x6FLB+GLOBG7WCHbeEH7qHIr2KJcaaGcaaGsKPKsiVMMmWMcuYM8yZNMmgIc+iJte4QNq/bOKzQ+LBUP3VcP/bdfDkev/kf5SlvZylvbe3t5ytxqW11qm92r3GxrnK5P/XhP/rhP/viffwif/4k///mf//nP//pcTExMXFxc3NzdHR0cbW69jh8efv9+vz//r7/P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAMAAAEALAAAAAAQABAAAAiZAAMIHEiwoMGDBzNkwHDBAkKBGXpI5MGjAsKIMjJm7CEhAoQHDhoIxNBDo0mJEhncCHChB4yXMGPKWFBjgs2bOG1+aIGAxoQYJk3G6DCBhQGfQGPClPFiAogCNAL8dEG1KtUZGjwQiPpTxoivYEfM4LBhQFSpMUKoXatWBAUBNQROUECXboIDBgoQGGDCxkAbNAILHuz34cGAADs=")

imglabel = Label(frame, image=cat)
imglabel.grid(column=3, row=0, rowspan=4)

############TOOLBAR#####################
toolbar = Frame(root)
b = Button(toolbar, image=open, width=20, command=tempwindow2)
b.grid(column=0, row=0, sticky='w')
b2 = Button(toolbar, image=img00, width=50, command=lambda: labelupdate("status"))
b2.grid(column=1, row=0)
toolbar.grid(column=0, row=0, sticky='w')

#######################MENU#################
menu = Menu(root)
root.config(menu=menu)

filemenu = Menu(menu)
menu.add_cascade(label="File", menu=filemenu)
filemenu.add_command(label="Open", command=fileselect)
filemenu.add_command(label="Quit", command=windowclose)

editmenu = Menu(menu)
menu.add_cascade(label="Edit", menu=editmenu)
editmenu.add_command(label="Input", command=inputdata)

helpmenu = Menu(menu)
menu.add_cascade(label="Help", menu=helpmenu)
helpmenu.add_command(label = "About", command=tempwindow2)
#######ROOT MAIN###########################
root.mainloop()

 

6