by Ryan Summers
Over the course of winter break, I finally got a chance to work a bit on our beer-pong robot. Our parts finally came in and I figured there was nothing better to work on with my newfound free time. Our mechanical engineers created a small mock set-up for the electrical team to work on and I decided to hook our motors up to it!
This gave me an excellent platform to start working on. I hooked up our H bridge motor driver and started looking through some documentation on the controller. I quickly realized that my original plan of using a PIC microcontroller would no longer work effectively in the short term, as they supply 3.3V logic and the controller works off 5V logic. Instead, I decided to switch over to an AVR microcontroller to make use of the 5V logic before I could create a board to level shift the signals off the PIC board. This would come to have much larger implications than I originally expected, but I’ll get to that later. To program the microcontroller, I used the SUBLIBinal library that James Irwin and I developed for the Robosub club. Originally this code was developed for PIC microcontrollers, but we intended to port it over to AVR. This project forced me to finish the port that I was conducting, and the library allowed me to extremely quickly implement the microcontroller functionality without many hang-ups.
I quickly wired together the microcontroller to the motor driver on a breadboard and began writing some code. I got the initial microcontroller code to get the motors spinning, but the set up was far from perfect. I really needed a method to control the motor speeds. This meant that the microcontroller needed to communicate with the computer in some way, so I decided to implement a UART interface. After buying a UART-serial converter and writing up some serial programming code on the computer side, I got an efficient line of communication going so that the computer and the microcontroller could exchange information. However, this set up had quite a few issues with it: 1) The serial interface was through the command line and was extremely difficult to use effectively. 2) It would often hang when attempting to read due to blocking calls, and 3) the motors often became stuck on set-up due to changes in friction and would stop rotating – even when operating at the same PWM duty cycle. Additionally, there was no logical way to specify motor speeds besides duty cycle percentages. To combat the issue of friction and to create an effective way to communicate, I decided to implement a PID feedback control system.
We had ordered some small magnets and some hall-effect sensors for just this purpose, but I had never really worked with PID controllers before. I set up the hall-effect sensors close to the wheels and taped on the magnets to generate an interrupt to the microcontroller whenever they passed by. This allowed me to do some simple math on the data to provide an RPM value to the microcontroller. Now, I could send the microcontroller a desired RPM and it would have a value for its current RPMs as well. The next step was to implement some form of control system so that the microcontroller could dynamically adjust it’s PWM duty cycle to achieve it’s desired RPMs. After doing a small amount of research, I realized that implementing a PID controller within a microcontroller was actually quite a simple task! By storing just a bit of previous state information, the microcontroller can periodically generate an update to the PWM duty cycle through the feedback from the hall-effect sensors. After tinkering around with the parameters on the PID controller, I managed to find some rough values that were giving me back consistently held RPMs.
Now that the issue of logical communication and a control system had been solved, I knew that I needed to fix the computer-side interface. I had done some previous work with Qt for GUIs with the Robosub club, so I decided that creating some form of GUI would be the easiest way to interface with the microcontroller. This way, I could update the current RPMs of the microcontroller and set goal values all in real-time. However, this didn’t quite address the issue of the serial port holding application execution. After some thought, I realized I could use a thread for reading and writing to the serial port, and then run the GUI through a separate application. Through the course of a day, I wrote up a small GUI to display information on the screen so that anyone can set the goals easily. Below is the GUI after a number of improvements and iterations!
(Note: ‘RPM Setting’ should be ‘Duty Cycle Setting’ above – it’s still quite rough!)
Now, we have set up an interface for the computer science team to develop a computer-side application to control the motors. This allows us to move to our next step of the project to create an application that can start using visual feedback to adjust the shots that it takes. It’s going to be exciting to see where this project goes in the next few weeks!
Update: Due to some immense errors with the ATMega chip causing shutdowns and periodic reboots, I decided to switch over hardware to the PIC32MX250F128B. The library we are using is much more rigorously tested on this chip and we have more available debugging tools for correcting code errors. Below is a 3D model of the new board that has been ordered for interfacing with the motor controller!