It is alway fun to control something using your telephone.
Ofcouse it is possible to implement a small webserver on our processor board and use our telephone’s browser to access that page, but it is that browser that makes communicating with our device somewhat oversized.
It would be much nicer if we could just send messages to our device.
The underlying ethernet communication TCP/IP and UDP make this possible but the limiting factor here is the telephone…
We need to have a way to send these messages.
Since I’m a iPhone user, I thought: “there must be an app for that”…
And yes! Ardumote (no relation).
It is a simple app that lets you make an interface on your iPhone consisting of buttons, switches and sliders, and have these send UDP messages to your device.
Just what I was looking for.
There was only one catch, it did not support my enc28j60 based ethercard.
So, work to do…
As I was using the JeeLabs ethercard library, it turned out that the code to implement an UDP server was there, but not available.
After exporting the appropriate functions, writing a sketch was not too difficult.
// UDP server Demo
// Adapted from Guido Socher, tuxgraphics.org
// [http://tuxgraphics.org/electronics/200905/embedded-tcp-ip-stack.shtml]
// Theater4all, Frank van den Berg 8-sept-2011 [http://scenelight.nl]
// Using the EtherCard library by jcw [http://jeelabs.org]
#include <EtherCard.h>
static uint8_t mymac[6] = { 0x54,0x55,0x58,0x10,0x00,0x24};
static uint8_t myip[4] = { 192,168,0,222 };
static union {
uint16_t PortNr;
uint8_t PortByte[2];
} myport;
#define BUFFER_SIZE 250
static uint8_t buf[BUFFER_SIZE+1];
uint16_t plen;
uint8_t payloadlen=0;
char str[30];
EtherCard eth;
void setup () {
Serial.begin(57600);
Serial.print("\n\r[UDP server]\n\r");
// Set port for udp and init ethercard.
myport.PortNr = 7777;
eth.spiInit();
eth.initialize(mymac);
eth.initIp(mymac, myip, myport.PortNr);
}
void loop () {
// get the next new packet:
plen = enc28j60PacketReceive(BUFFER_SIZE, buf);
// plen will be unequal to zero if there is a valid
// packet (without crc error)
if (plen==0) {
return;
}
// arp is broadcast if unknown but a host may also
// verify the mac address by sending it to
// a unicast address.
if (eth_type_is_arp_and_my_ip(buf,plen)) {
make_arp_answer_from_request(buf);
return;
}
// check if ip packets (icmp or udp) are for us:
if (eth_type_is_ip_and_my_ip(buf,plen)==0){
return;
}
if (buf[IP_PROTO_P]==IP_PROTO_ICMP_V && buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V){
// a ping packet, let's send pong
make_echo_reply_from_request(buf,plen);
return;
}
// Check port nr
if (buf[IP_PROTO_P] == IP_PROTO_UDP_V
&& buf[UDP_DST_PORT_H_P] == myport.PortByte[1]
&& buf[UDP_DST_PORT_L_P] == myport.PortByte[0]) {
// Yes: this one is ours !
// handle the package
payloadlen = buf[UDP_LEN_L_P] - UDP_HEADER_LEN;
Serial.println((char *)&(buf[UDP_DATA_P]));
// If we need to send a reply, this is the place...
// strcpy(str, "Got your message");
// make_udp_reply_from_request(buf, str, strlen(str), myport.PortNr);
}
}
Et voila: a working iPhone remote control using UDP messaging.
The changed library with the code from the example can be downloaded here.