Notes From a Traveling Salesman
Sunday, April 5, 2015
Feed My Cat, World!
I just rolled out a new update to the cat feeder so that the world can feed my cat through the power of Twitter. Just tweet me @jerbearly with the hash tag #feedMeow!
Saturday, December 29, 2012
Automated Cat Feeder w/ Android App
Problem: My cat Ten-Ten was starving while waiting for me to come home from work to feed him.
Solution: An automated dry cat food and water dispensing system that dispenses food and water on a timer at different times during the day. In version 1.0 of the system, I used an Arduino microcontroller and added a web server module, an LCD module, and an Android mobile application to act as an user interface between my cat and myself. In version 2.0, I ported the entire system to a Raspberry Pi microcontroller and rewrote everything on the backend. As part of the port, I replaced the LCD module with a web application, as well as added other features.
*Version 1.0:
For the food dispensing component, I found a brilliant design here, which used a low RPM high torque motor to rotate a cereal dispenser knob to dispense dry food. Instead of reinventing the wheel, I decided to replicate it.
First, I stabilized the food container base and motor base.
![]() |
![]() |
Then, I opened up a hole for the food to fall out from the bottom of the container the dispenser is housed in and hooked up the ~$15 motor I bought online.
![]() |
![]() |
![]() |
For the water dispensing component, I couldn't find anything on the web that fit my taste, so I had to come up with something myself. During the design phase, I went through many iterations. At the end, I settled on using a cheap 350GPH water pump to pump water from a low pressure tubing to a high pressure tubing, which fed into Ten-Ten's dish:
![]() |
![]() |
With the mechanics done and enclosed in a plastic drawer container, I used a mosfet tutorial to wire up a mosfet circuit to the knob rotating motor/water pump and my Arduino microcontroller so I could turn the two motors on and off by sending a digital signal from my microcontroller to the circuit. At this point, I slapped some code onto the Arduino using a couple of their open source libraries and I had a working prototype that fed my cat at 9:30am, 2:30pm, and 6:30pm. Now I wanted a cool interface to go along with this project. So I added an ethernet shield to the Arduino and some code to allow the Arduino to serve HTTP requests. With this live on my local network, I built an Android mobile application that would make HTTP requests to ask the Arduino to dispense food and/or water. In addition to this, I also added an LCD module with buttons and some code behind that allowed me to navigate a virtual menu with the buttons, which allowed me to do the same as the mobile app. In hindsight, I realized that adding the LCD module with buttons was a very low return investment because I almost always resorted to the mobile application and never to the LCD module. Here's the system in action:
*Version 2.0:
After using this system for about 4 months on a daily basis, I decided I wanted to make some modifications to it. First, I wanted to get rid of the LCD module and replace it with a web application. Secondly, I wanted to collect logs of when Ten-Ten was given food/water and publish the same logs to Twitter so I can access them anywhere. Because of the amount of code I needed to add in order to make these modifications, I realized that I couldn't use the Arduino due to memory constraints, so I decided to go with a Raspberry Pi.
With a LAMP stack running Debian Linux installed on the Raspberry Pi, I rewrote all the backend code to work with the Pi then modified the Android app slightly so it would be compatible with both the Arduino and Raspberry Pi. Now, whenever Ten-Ten is given food and/or water through the cat feeder, that information is logged into a local MySQL database and published to Twitter. Here's the result of the modifications and hard work:
|
|
Next step: use Twitter as a control source to feed Ten-Ten.
References:
http://arduino.cc/en/Reference/HomePage
http://arduino.cc/en/Reference/Libraries
http://www.newtonnet.co.uk/catfeeder/
http://bildr.org/2012/03/rfp30n06le-arduino/
http://elinux.org/RPi_Beginners
https://projects.drogon.net/raspberry-pi/wiringpi/
https://dev.twitter.com/docs/twitter-libraries
http://developer.android.com/reference/packages.html
Sunday, October 23, 2011
Curve Rendering (part 2): Bezier Curves && the deCastelijau Algorithm
Here is a really great explanation on the de Castelijau algorithm, which is used to generate Beizer curves. And here's my implementation of the de Castelijau algorithm:
void deCastelijau(const Point* ctrlPoints, const int numCtrlPts,
const int resolutionOfLine, Point* bezierPoints) {
/* ctrlPoints — our control points for this curve
numCtrlPts — number of control points
resolutionOfLine — resolution/”number of lines drawn for the entire curve”
bezierPoints — our output, a collection of points we are to connect to attain our bezier curve*/
//// do some error checking here on input
for(int i = 0; i <= resolutionOfLine; i++) {
double u = (double) i / (double) resolutionOfLine;
Point Q[numCtrlPts];
for(int j = 0; j < numCtrlPts; j++) {
Q[j] = ctrlPoints[j];
}
for(int j = 1; j < numCtrlPts; j++) {
for(int k = 0; k < numCtrlPts - j; k++) {
Point temp((1.0 - u) * Q[k].x + u * Q[k + 1].x, (1.0 - u) * Q[k].y + u * Q[k + 1].y);
Q[k] = temp;
}
}
bezierPoints[i] = Q[0];
}
}
Check out the source code.
Wednesday, August 3, 2011
Curve Rendering (part 1): B-Spline Curves && de de Boor Algorithm
While taking a graphics class last fall, we touched upon curve rendering (one of the most interesting graphics topics IMO). We learned of two different types of curves - Bezier and B-Spline, and two algorithm to generate these curves - de Casteljau and de Boor. Because I'm not a mathematician, these algorithms were pretty difficult to understand. But after spending a long time studying them, I got a fairly good understanding of how each work. I don't want to bore you with an explanation of how the algorithm works because it can be found everywhere on the web. Instead, I want to share with you my implementation of the two algorithms. In this particular post, however, I will be sharing my implementation of the de Boor algorithm, which is used to generate B-Spline curves:
struct Point {
Point() : x(0.0), y(0.0) {}
Point(const double xIn, const double yIn) : x(xIn), y(yIn) {}
Point operator=(const Point rhs) {
x = rhs.x;
y = rhs.y;
return *this;
}
Point operator+(const Point rhs) const {
return Point(x + rhs.x, y + rhs.y);
}
Point operator*(const double m) const {
return Point(x * m, y * m);
}
Point operator/(const double m) const {
return Point(x / m, y / m);
}
double x, y;
};
void deBoor(const Point* ctrlPoints, const int numCtrlPts,
const float* knots, const int numKnots,
const int k, const int resolution,
Point* bsplinePoints) {
/*
ctrlPoints -- our control points for this curve
numCtrlPts -- number of control points
knots -- list of knots for this curve
numKnots -- number of knots we currently have, this is equal to (numCtrlPts - 1 + k)
k -- order of this spline curve
resolution -- number of spline points
*/
int initialX = k - 1, finalX = numCtrlPts, numIterations = 0;
float initial = knots[initialX], final = knots[finalX];
float du = (final - initial) / (double) resolution;
for(float u = initial; u < final; u += du) {
/* find where u lies */
int I = initialX;
for(; I <= finalX - 1; I++) {
if(u >= knots[I] && u < knots[I + 1]) {
break;
}
}
/* initialize set of points used in this layer of the calculation */
Point myD[k][numCtrlPts];
for(int i = 0; i < numCtrlPts; i++) {
myD[0][i] = ctrlPoints[i];
}
/* calculate spine points this "layer" */
for(int r = 1; r <= (k - 1); r++) {
for(int i = I - (k - 1); i <= (I - r); i++) {
float alpha = (knots[i + k] - u), alpha2 = (u - knots[i + r]);
float bottem = (knots[i + k] - knots[i + r]);
if(bottem == 0) {
alpha = alpha2 = 0;
bottem = 1;
}
myD[r][i] = myD[r - 1][i] * (alpha / bottem) + myD[r - 1][i + 1] * (alpha2 / bottem);
}
}
/* set output B-Spline point */
bsplinePoints[numIterations++] = myD[k - 1][I - (k - 1)];
}
}
Check out the source code.
Wednesday, June 8, 2011
Android ListActivity Arrows
While developing on the Android this week, I wanted to use a ListActivity. I used the ListActivity class quite a lot before, but this time I wanted to do something different with it. Instead of having a plain list, I wanted to have arrows on the right side of each list item, kind of like how the iOS UITableView has it. I made several attempts of doing this and I was finally able to come up with a good solution.
The trick is to build your own list adapter (derived from the BaseAdapter), define an xml layout for each row in the list, and use the list adapter to populate the list with the layout that you defined. To start, we define some local variables from our CustomListAdapter class and write the constructor to cache some local variables:
In my case, I chose to cache two things: a String array mListItemTxt, which holds the text for each row in the ListActivity, and an int mTextWidth, which is the width that the text in each row can occupy. We can calculate this width by getting the width of the arrow we have in our resources folder, and subtracting that value from the width of the display. Next we have to define the layout for each row of our ListActivity.
In our row layout, we have the following:
The trick is to build your own list adapter (derived from the BaseAdapter), define an xml layout for each row in the list, and use the list adapter to populate the list with the layout that you defined. To start, we define some local variables from our CustomListAdapter class and write the constructor to cache some local variables:
public class CustomListAdapter extends BaseAdapter {
private String[] mListItemTxt = null;
private LayoutInflater mLayoutInflater = null;
private int mTextWidth = 0;
private int mTextHeight = 60; // in dip
// holder struct for each row
public static class CustomHolder {
public TextView text;
public ImageView image;
}
public CustomListAdapter(Context context, String[] listItemTxt, int textWidth) {
// cache data locally
mListItemTxt = listItemTxt;
mLayoutInflater =
(LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mTextWidth = textWidth;
}
...more code...
In my case, I chose to cache two things: a String array mListItemTxt, which holds the text for each row in the ListActivity, and an int mTextWidth, which is the width that the text in each row can occupy. We can calculate this width by getting the width of the arrow we have in our resources folder, and subtracting that value from the width of the display. Next we have to define the layout for each row of our ListActivity.
In our row layout, we have the following:
<?xml version="1.0" encoding="utf-8"?>After this, we need to complete the CustomListAdapter class:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical" android:id="@+id/relativeLayout1">
<TextView android:id="@+id/custom_list_item_txt"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="" android:textSize="24dip" android:layout_weight="1"
android:gravity="center|left"></TextView>
<ImageView android:id="@+id/custom_list_item_image"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:src="@drawable/icon" android:layout_toRightOf="@+id/custom_list_item_txt"
android:layout_weight="0"></ImageView>
</RelativeLayout>
@OverrideAfter defining these functions, add an arrow icon to the resources folder and the list adapter should be ready to use. Check out the source code, and screenshot:
public int getCount() {
// return 0 if null
return (mListItemTxt == null ? 0 : mListItemTxt.length);
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
CustomHolder ch = null;
if(v == null) {
// create a new one if it doesnt exist
v = mLayoutInflater.inflate(R.layout.list_item, null);
ch = new CustomHolder();
ch.text = (TextView) v.findViewById(R.id.custom_list_item_txt);
ch.image = (ImageView) v.findViewById(R.id.custom_list_item_image);
v.setTag(ch);
}
else {
ch = (CustomHolder) v.getTag();
}
try {
// load the text and the arrow image
// also set width and height to make it look nice
ch.text.setText(mListItemTxt[position]);
ch.text.setWidth(mTextWidth);
ch.text.setHeight(mTextHeight);
ch.image.setTag(Integer.toString(position));
ch.image.setImageResource(R.drawable.arrow);
ch.image.setMinimumHeight(mTextHeight);
return v;
}
catch(Exception e) {
e.printStackTrace();
return null;
}
}

Subscribe to:
Posts (Atom)