Assignment 12: Interface and Applications Programming

Because I spent most of the week of town for Thanksgiving, I tried to keep it simple for this week (well, simple given I've never done anything like this before). My goal was to create a very simple user interface to run a servo. I used Python with Tkinter and PySerial, and the Arduino IDE.

PySerial and Arduino

I found this simple tutorial on getting started with interfacing PySerial with an Arduino, and built off of that to write my own Arduino and Python code to control a servo. Even before worrying about the user interface, I tried debugging this first. The servo did move when I ran the Python program, but somewhat intermittently and unexpectedly, and usually only if I hit Reset first. I'm not entirely sure what was happening, but I decided to throw in the user interface anyway and see if I could debug the whole thing.

Tkinter

I found this tutorial to be a great place to start with using Tkinter. I added in a very basic user interface, just something to start the servo and quit the program. It didn't work - in fact, nothing showed up in the Serial Monitor. Amir, the TA, helped me debug the program. The problem seemed to be mainly how it was interfacing with the serial. The code that worked for me is below.

Arduino

            
#include 

Servo servo1;
int in;

void setup(){
  servo1.attach(5); 
  Serial.begin(115200);
}

void loop(){
  if(Serial.available()>0){
    in = Serial.read();
    Serial.print("Received: ");
    Serial.println(in, DEC);
    
    if (in == 1){
      Serial.println("communicating with servo...");
    servo1.write(30);
    delay(300);
    servo1.write(0);
    delay(300);
    servo1.write(60);
    delay(300);
    servo1.write(90);
    delay(300);
    Serial.println('done');
  }
}
}
    
            

Python

            import serial
from Tkinter import *

ser = serial.Serial("/dev/tty.usbserial-A501VM6Y", 115200)

class App:
    def __init__(self, master):
        frame = Frame(master)
        frame.pack()

        self.start = Button(
            frame, text="Start Servo", fg="green", command=self.run_servo
            )
        self.start.pack(side=LEFT)

        self.end = Button(
            frame, text="Quit", command=frame.quit)
        self.end.pack(side=LEFT)

    def run_servo(self):
        ser.write(b'1')



root = Tk()

app = App(root)

root.mainloop()

I tested this with Amir and it worked great! Unfortunately, I wish I'd thought to film it at the time for the reasons explained below.

Trying to burn the bootloader

When Amir saw me using the FabISP with the Fabduino, he told me that it's actually possible to burn the bootloader, and then I wouldn't have to use the ISP anymore. It sounded great, so we tried it! However, what I forgot was that on my original board, as mentioned in last week's assignment, I'd forgotten to connect the CS/CTS pins to anything. So burning the bootloader didn't work. I decided I'd do that for the next iteration of my board for the final project.

Later that evening, I tried hooking up everything again so I could film my successful servo interface. And it didn't work. I got this error from the Arduino IDE:

avrdude: initialization failed, rc=-1
Double check connections and try again, or use -F to override
this check.

The computer recognized that the board and the ISP were attached, but there was some other problem anyway. I also tried using another classmate's ISP and had the same problem. The only thing I could conclude is that the failed attempt to burn the bootloader somehow messed up the Fabduino. Unfortunately at this point I don't have enough time to make another Fabduino to show the video of the working program for this week, but the TA, Amir Lazarovich, can vouch for me that it worked. Meanwhile, I need to try to work out why burning the bootloader would have messed up the Fabduino.