Arduino command protocol

Arduino,C/C++ — Dillon @ 11:40 am

UPDATE: Use CmdMessenger instead of Messenger.

Here’s my IRC Arduino Bot. It uses a regular Arduino 328 and an Ethernet Shield both from sparkfun. As for software, I’m using the Ethernet2 library (see my previous post about this), the WString library and a homerolled IRC protocol parser. The breadboard’s power is connected to arbitrary pin 5 and some resistors to keep the LED from burning out.

arduino_irc_light

Basically, my bot joins an IRC channel and then listens for PRIVMSG commands starting with a password. It takes those commands and controls an LED. For example, I’d send this privately to the Arduino:
command password LEDON

And then the red LED comes on. I tell it “LEDOFF” and it turns off. Ok, it’s not a new RFC spec worthy of IEEE recognition and international adoption. But it got the job done in a human-readable manner. Previously on my facebook status light project, I had done much of the processing on my laptop and only send hex codes to the Arduino to light up LEDs. The difference now is that the Arduino is doing the processing and no computer is needed.

While I was working on this little project, I had the bot join the channel and announce itself.
irc_log

At one point, I was working on code and then my bot would disconnect. I checked the serial monitor and the server seemed to drop me after a few minutes. The channel would say that I timed out. I realized that I wasn’t responding to the PING from the server. So I threw in some code that checks for anything from the server that starts with “PING :”. I then respond with “PONG”. I remember seeing PING?/PONG! messages in mIRC back in the day. Now it makes sense why mIRC was doing that in the console window.

It works great and I was excited about how much this little board could do in 14KB. And then I kept testing it. After about 7 or 8 “turn on” and “turn off” commands, the Arduino wouldn’t do anything anymore. It’s like it just froze. If I typed 5 commands, it’d stay connected for a long time. But every time I’d send it 7 to 8 commands, it would lock up. And by lock up, I mean the commands wouldn’t work anymore and it would time out from the server. WTF. So close!

So I figure that it’s something to do with pointers and memory. I really don’t have a solid grasp on pointers and C. I got a lot of this working by iterative experimentation over many days. So I was looking for a better way to send human readable commands to my bot. By human readable I mean something that works like a unix command “command arg1 arg2″. Of course this human readable bit introduces strings which is tricky enough in C (for me) and even worse on the Arduino. I figured this was a problem that someone smarter than me had solved.

I found a library called Messenger. It’s pretty simple to install, just throw it in your ~/Documents/Arduino/libraries folder on Mac and um … the equivalent on Windows? There are examples in the Messenger folder that you can checkout. HOWEVER the whole point of me posting this big long thing is the following.

The example checkString really threw me for a loop. It did exactly what I need it do to in a much cleaner way. I uploaded to the Arduino and then broke out to a shell.

$ screen /dev/tty.usbserial-A9005bCr 115200

Substitute your virtual usb device for the /dev/tty path. Note that the sketch uses 115k serial speed. You won’t see anything when you type but if you hit “enter” (to clear the buffer) “on[enter]” in screen LED 13 will turn on. Type “off[enter]” ([enter] means the enter key) and it will turn off. Great! Exactly what I need. But then I tried typing “on” then “off” then “muffins” then “on” and the light stayed off. Any garbage gets the Arduino stuck like my sketch. Ok, is what I’m trying to do impossible or is this just coincidence?

I modified the checkString example to look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// This example demonstrates Messenger's checkString method
// It turns on the LED attached to pin 13 if it receives "on"
// It turns it off if it receives "off"
 
 
#include <messenger .h>
 
 
// Instantiate Messenger object with the message function and the default separator 
// (the space character)
Messenger message = Messenger(); 
 
 
// Define messenger function
void messageCompleted() {
  // This loop will echo each element of the message separately
  while ( message.available() ) {
    if ( message.checkString("on") ) {
      digitalWrite(13,HIGH);
    } else if ( message.checkString("off") ) {
      digitalWrite(13,LOW);
    } else {       // ADD THIS
      break;     // ADD THIS
    }                // ADD THIS
  }
 
 
}
 
void setup() {
  // Initiate Serial Communication
  Serial.begin(115200); 
  message.attach(messageCompleted);
 
  pinMode(13,OUTPUT);
 
}
 
void loop() {
 
  // The following line is the most effective way of 
  // feeding the serial data to Messenger
  while ( Serial.available() ) message.process( Serial.read() );
 
 
}
</messenger>

I added the break and it’s able to deal with garbage. I tested more than 20 commands with banging on the keyboard in between and it seems pretty solid. Now I just need to integrate this with my IRC bot and I might have something that can stay online for a while.

By the way, after you use screen to connect to a serial port, hit “Ctrl+A, k” to kill the window and break out of screen.

Update: People have asked for the code. It’s posted after the break.
(more…)

Growl Network Notifications Not Working

Mac — Dillon @ 9:13 pm

Growl’s network notifications weren’t working. Either sending or receiving. I had two machines that had growl cleanly installed and my main machine that’s had many versions installed over the years. It was my main box with a dirty growl history that was having problems.

I found a post on cocoaforge that helped a lot. First, I ran the uninstall applescript (I always keep uninstallers in ~/Uninstallers but you can find it in the Growl.dmg). That didn’t really work, it gave me an Apple Script time out. So I removed everything manually. I deleted the pref pane from SysPrefs by right-clicking on Growl and selecting remove.

growl_remove

After that was done I removed the preferences file from ~/Library/Preferences and also a folder under ~/Library/Application Support called Growl (has two subfolders called Tickets and Plugins). I emptied trash. Reinstalled Growl 1.2 (latest). I didn’t restart. I re-setup the network bit of Growl on this page:

growl_network

Notifications started working. Now all my boxes are notified when something cool happens. Weee!

Basic 555 timer Arduino project

Arduino — Dillon @ 4:27 pm

I put together the arduino protoshield from sparkfun. Excellent instructions at atomicsalad. Even though it’s a standard through-hole kit, atomicsalad’s instructions were nice to follow along.

After it was put together I had a few built-in LED lights to play with. I had seen this 555 timer in a piece kit I bought and I wondered what it does. I found a ton of examples and apparently you can do a zillion things with it. I wanted to start with the basics so I set out to make a light blink using only hardware. I’m only using the arduino for power in this one.

jump_breadboard_at_30
I found a great tutorial on youtube and modified it to work on a larger breadboard. I had some trouble because it turns out that this breadboard has its power rails split down the middle. I was confused and stuck on this for a day. Eventually I found a video that hinted at this fact and connected the two sides like so. After that, the power rails on each side will work like I expected. This is by design on these boards so that you can have two different voltages but I found it annoying.

So here’s the schematic that I followed for the configuration on the big breadboard.
555_bb

I transferred this layout onto a mini breadboard and it works like a champ. The protoshield has room for a mini self-adhesive breadboard. Here’s the actual wiring shot. This uses a light on the protoshield vs the light on the breadboard schematic. The concept is the same though. Pin3 on the 555 is the output which makes the light blink rapidly. You could use this chip as a cpu clock for example.
555_timer_wiring

You don’t have to use the breadboard switch (the black thing on the left), it’s just more convenient to flip a switch rather than plug in/out of the 3v. Oh yeah it’s powered by 3v on the arduino. The cap is 100uf. You can use 2x orange,orange,maroon (gold) resistors or one of those and a blue,gray,maroon one (sorry I don’t have the resistance values). Play with the resistor values to change the blink rate.

SCP vs RSync vs SMB vs FTP

Blog — Dillon @ 11:55 pm

Update: as many have commented, my testing with /dev/zero might be skewing the results. I’ll be adding a random DVD iso test soon. I have a newborn so give me a sec. I’ll even add the NFS test. :)

@fearthepenguin made an rsync comment that made me curious. He said that rsync in cygwin is faster than native SMB in Windows. Ok I haven’t done this test in a while, let’s get a reminder about how fat SMB is.

Test Setup

SOHO gigabit switch. Ubuntu 9.10 and octo-core 2008 Mac Pro running 10.6. Both pretty fast boxes. Regular SATA drives in each, not very fast I/O. Whatever, network should be the bottleneck.

Get my test file generated.
$ dd if=/dev/zero of=1gb_file.zeros bs=1G count=1
1073741824 bytes (1.1 GB) copied, 133.577 s, 8.0 MB/s

Ignore that 8.0 MB/s. You can do a blocksize trick to make it output a file faster, I just didn’t feel like looking up the switches. Now you can see Mr. 1GB Zero File in all it’s empty and big glory.

$ ls -lh
total 1.2G
-rw-r--r-- 1 dude herd 1.0G 2010-02-11 12:29 1gb_file.zeros

The Tests

RSync
Copy from ubuntu box to Mac Pro:
$ time rsync -t /tmp/1gb_file.zeros dude@mac:~/tmp
real 0m17.694s
user 0m11.577s
sys 0m3.056s

SMB
Mount Mac share from Ubuntu box. Copy same file from ubuntu box to Mac Pro over SMB mount. I never do this. It’s stupid, slow, strips permissions and requires a mount. In the name of science!
# time cp /tmp/1gb_file.zeros /mnt/tmp
real 0m32.649s
user 0m0.008s
sys 0m0.568s

FTP
Ok let’s goddamn turn on OSX FTP and test that too. FTP is stupid.
The remote file "1gb_file.zeros" already exists.
Local: 1073741824 bytes, dated Thu 11 Feb 2010 12:29:06 PM EST.
(Files are identical, skipped)

Hey at least FTP is showing some smarts about it. Or maybe ncftp just rules. I dunno. Deleted it and got FTP time.

$ time ncftpput -u dude -p whoa mac /dest/tmp /tmp/1gb_file.zeros
/tmp/1gb_file.zeros: 1.00 GB 39.09 MB/s
real 0m26.507s
user 0m0.036s
sys 0m0.828s

SCP
Is SCP any different than rsync?
$ time scp /tmp/1gb_file.zeros dude@mac:~/tmp
1gb_file.zeros 100% 1024MB 42.7MB/s 00:24
real 0m24.303s
user 0m9.641s
sys 0m2.212s

Weird. It is. I wonder if rsync has compression flags whereas ssh does not without the -C magic switches. You can get SCP to be pretty quick with blowfish or arcfour:

$ time scp -c arcfour /tmp/1gb_file.zeros dude@mac:~/tmp
1gb_file.zeros 100% 1024MB 46.6MB/s 00:22
real 0m21.653s
user 0m5.452s
sys 0m2.032s

Conclusion

rsync SMB FTP SCP SCP arcfour
time 17.694 32.649 26.507 24.303 21.653
MB/sec 57.87 31.36 38.63 42.13 47.29

So RSync is pretty quick and SMB is pretty slow. @fearthepenguin was right.

Subversion Aptitude Error

Unix — Dillon @ 5:24 pm

I used to have an SVN repository up and running. Then my server crashed. Nothing was really important so I never rebuilt it. However my server backup files referenced the SVN modules in apache. I suppose during the crazy rebuild time, I restored an old conf file that referenced dav_svn and I disabled the module by deleting the file.

So now I want to get SVN back because Git (while great) lacks a nice GUI. I’m not converting to SVN. I’m just going to put stuff in both places for a while and then merge them after playing with Versions.

Anyway, why you are here. You’re getting a ERROR: Module dav_svn does not exist! when trying to install subversion with aptitude install libapache2-svn? That’s what I was getting. I strace’d and googled it for a bit and nothing was working. Eventually I found the original files and put them in their place and that seemed to resolve the package installation however aptitude still thinks the conf files are there even after removing. So this method will get you past the aptitude install and let you install/uninstall as you like (I tested install/uninstall about fives times). And then it will remove your existing svn configs. So please don’t have anything regarding mod_svn that you want to keep.

I found the originals from sysinf0.klabs.be.

Create or edit /etc/apache2/mods-available/dav_svn.conf
# dav_svn.conf - Example Subversion/Apache configuration
#
# For details and further options see the Apache user manual and
# the Subversion book.
#
# NOTE: for a setup with multiple vhosts, you will want to do this
# configuration in /etc/apache2/sites-available/*, not here.

# ...
# URL controls how the repository appears to the outside world.
# In this example clients access the repository as http://hostname/svn/
# Note, a literal /svn should NOT exist in your document root.
#

# Uncomment this to enable the repository
#DAV svn

# Set this to the path to your repository
#SVNPath /var/lib/svn
# Alternatively, use SVNParentPath if you have multiple repositories under
# under a single directory (/var/lib/svn/repo1, /var/lib/svn/repo2, ...).
# You need either SVNPath and SVNParentPath, but not both.
#SVNParentPath /var/lib/svn

# Access control is done at 3 levels: (1) Apache authentication, via
# any of several methods. A "Basic Auth" section is commented out
# below. (2) Apache and , also commented out
# below. (3) mod_authz_svn is a svn-specific authorization module
# which offers fine-grained read/write access control for paths
# within a repository. (The first two layers are coarse-grained; you
# can only enable/disable access to an entire repository.) Note that
# mod_authz_svn is noticeably slower than the other two layers, so if
# you don't need the fine-grained control, don't configure it.

# Basic Authentication is repository-wide. It is not secure unless
# you are using https. See the 'htpasswd' command to create and
# manage the password file - and the documentation for the
# 'auth_basic' and 'authn_file' modules, which you will need for this
# (enable them with 'a2enmod').
#AuthType Basic
#AuthName "Subversion Repository"
#AuthUserFile /etc/apache2/dav_svn.passwd

# To enable authorization via mod_authz_svn
#AuthzSVNAccessFile /etc/apache2/dav_svn.authz

# The following three lines allow anonymous read, but make
# committers authenticate themselves. It requires the 'authz_user'
# module (enable it with 'a2enmod').
#
#Require valid-user
#

#

Create or edit /etc/apache2/mods-available/dav_svn.load

# Depends: dav
LoadModule dav_svn_module /usr/lib/apache2/modules/mod_dav_svn.so
LoadModule authz_svn_module /usr/lib/apache2/modules/mod_authz_svn.so

After putting those in:
sudo aptitude uninstall libapache2-svn
sudo aptitude install libapache2-svn
/etc/init.d/apache2 restart

Now when you do:
sudo aptitude search libapache2-svn
c libapache2-svn - Subversion server modules for Apache

You’ll see that annoying little ‘c’ from aptitude. That means that it’s not installed but the config files are still hanging around. Purge the config files with:
sudo aptitude purge libapache2-svn

And you’ll see:
aptitude search libapache2-svn
p libapache2-svn - Subversion server modules for Apache

Ethernet2 Arduino Library Fix on 0017

Arduino — Dillon @ 10:58 pm

arduino_0017
Ethernet2 lib. It’s a lighterweight and better Ethernet class. Head into your ~/Documents/Arduino/libraries (or Windows equivalent) and checkout the SVN project:

$ svn co http://tinkerit.googlecode.com/svn/trunk/Ethernet2%20library/Ethernet2

Now change your sketch to use Ethernet2.h instead of Ethernet.h. Wondeful? No. You’ll get this error in 0017.

'EthernetClass' has not been declared

Ok, the forums have a fix. But it didn’t work for the longest time because I didn’t know what they meant by Server.cpp. There’s two of them! The original or the new one?! If you edit the old one you’ll get this:

Print.cpp:129: first defined here

So:
1. Edit Server.cpp in Ethernet2 to include Ethernet2.h and not Ethernet.h.
2. Delete the Print.cpp and Print.h files from Ethernet2.
3. Compile.
4. Have some yay.

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License.
(c) 2012 SQUARISM | powered by WordPress with Barecity