0

How can I turn on or turn off a switch using Android and a Wi-Fi connection?

I have used SparkFuns IOIO to control relays. But how do I do it wirelessly?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Arjun
  • 73
  • 2
  • 8

4 Answers4

1

You could use an Arduino with an Ethernet Shield - or possibly a Netduino. Basically, any device with wireless internet capabilities, since that is the only wireless protocol Android uses - besides Bluetooth (or NFC). When the user presses a button, you could open a Socket or a BluetoothSocket to communicate to the second device that it needs to open the switch. Fairly simple - if you have a wireless home network, then your device could be plugged in to your router with a physical wire - as long as your Android device and your microprocessor are on the same network. There might be other wireless options you could use - these are just the simplest I could thing of. Hope this helps!

crocboy
  • 414
  • 1
  • 6
  • 14
  • +1 for good suggestion. This is essentially what I have done. Arduino connected to WRT-54G via built in serial connection, openWRT firmware and a custom build server app that receives data from an android UDP connection. – ZnArK Jul 06 '12 at 13:54
  • I forgot about the USB serial connection with the Arduino...anyways, good answer, I'll probably use it in some of my projects – crocboy Jul 06 '12 at 15:46
  • I guess netduino will serve my purpose. Thanks for the suggestion. – Arjun Jul 09 '12 at 08:56
1

That's why how I did it with my iPhone (should be the same on Android):

  • run a TCP server on a computer connected to the same network as your phone and by USB/serial to the Arduino.
  • This server should forward all incoming data coming through Wi-Fi from your Android phone through USB to the Arduino.
  • The phone should run a TCP client which sends a simple one-byte (maybe zero and non-zero) command
  • The Arduino shall be programmed so it listens for incoming serial data via interrupts; if a byte arrives it decides if it should switch the I/O pin on or off.
1

I have a project just like this. Mine is sending position data for a steering system, but the idea is the same. I'll finish uploading it to Google Code soon. You can check it out at PowerWheelino.

The basic structure is this:

  1. Touch event on Android sends data (over UDP) to the server.
  2. The UDP server (WRT54G router in this case) receives the data and forwards it over serial to the Arduino.
  3. The Arduino decides what to do with the data from the serial connection.

Keep in mind that the Arduino automatically resets when receiving data over serial (outside of the IDE Serial interface). See my post here on this topic and ways to get around it. Knowing this previously would have saved me a lot of troubleshooting.

Disclaimer:

This code requires some minor modification to accomplish what was requested by the OP. Since you've already made a working Android program with IOIO and an Arduino sketch, I assume this is within your abilities.

Here's the Android UDP client code:

Execute UdpClient::sendData() on touch event or button press.

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

import android.util.Log;

public class UdpClient {
    String messageStr;
    DatagramSocket s;;
    int server_port;
    InetAddress local;
    int msg_length;
    byte[] message;

    public UdpClient (String ipAddress, int port){
        server_port = port;
        try {
            local = InetAddress.getByName(ipAddress);
            s = new DatagramSocket();
        }
        catch (Exception e) {
            e.printStackTrace();
            Log.d("Powerwheelino",e.getStackTrace() + "error");
        }
    }

    public boolean sendData(byte drive, byte steering){
        byte drvByte = (byte) (drive & 0xFF);
        byte steerByte = (byte) (steering & 0xFF);
        message = new byte[2];
        message[0] = drvByte;
        message[1] = steerByte;
        msg_length = message.length;
        //message = messageStr.getBytes();
        try {
            DatagramPacket p = new DatagramPacket(message, msg_length,local,server_port);
            s.send(p);
        }
        catch (Exception e) {
            // TODO Auto-generated catch block
            Log.d("Powerwheelino", e.getStackTrace() +"ERROR ");
            e.printStackTrace();
            return false;
        }
        return true;
    }
}

Here's the listening UDP server (C++) code

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <SerialStream.h>

using namespace std;

class udp_server {
    int sock;
    int bytes_read;
    socklen_t addr_len;

    struct sockaddr_in server_addr , client_addr;

    public:
        udp_server(int portNum)
        {
            if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
                perror("Socket");
                exit(1);
            }

            server_addr.sin_family = AF_INET;
            server_addr.sin_port = htons(portNum);
            server_addr.sin_addr.s_addr = INADDR_ANY;
            bzero(&(server_addr.sin_zero),8);


            if (bind(sock,(struct sockaddr *)&server_addr,
                sizeof(struct sockaddr)) == -1)
            {
                perror("Bind");
                exit(1);
            }

            addr_len = sizeof(struct sockaddr);

            printf("\nUDPServer Waiting for client on port %d", portNum);
                fflush(stdout);
        }

        int listen(char recv_data[]) {
            while (1)
            {
                bytes_read = recvfrom(
                                 sock,
                                 recv_data,
                                 1024,
                                 0,
                                 (struct sockaddr *)&client_addr,
                                 &addr_len
                             );

                recv_data[bytes_read] = '\0';
                printf("\n(%s , %d) said : ",inet_ntoa(client_addr.sin_addr),
                                             ntohs(client_addr.sin_port));
                printf("%s", recv_data);
                string drive;
                string direction;
                int speed, angle;

                if ((recv_data[0] & 128) > 0) {
                    drive = "Fwd";
                }
                else {
                    drive = "Rev";
                }
                if ((recv_data[1] & 128) > 0) {
                    direction = "Left";
                }
                else {
                    direction = "Right";
                }
                speed = recv_data[0] & 127;
                angle = recv_data[1] & 127;
                printf("\t %s @ %d and %s @ %d",
                        drive.c_str(),
                        speed,
                        direction.c_str(),
                        angle);
                fflush(stdout);
            }
            return 0;
        }
};

Here's a snippet of the serial communication to the Arduino using LibSerial:

LibSerial::SerialStream myss;
SerialComm(int argc, char** argv) {
    myss = new LibSerial::SerialStream("/dev/ttyS0", ios_base::out);
    myss.SetBaudRate(LibSerial::SerialStreamBuf::BAUD_57600);
    myss.SetCharSize(LibSerial::SerialStreamBuf::CHAR_SIZE_8);
    myss.SetFlowControl(LibSerial::SerialStreamBuf::FLOW_CONTROL_NONE);
    myss.SetParity(LibSerial::SerialStreamBuf::PARITY_NONE);
    myss.SetNumOfStopBits(1);

    const int Dsize = 2;
    char buffer[1];
    buffer[0] = 125; //0b00000001;
    buffer[1] = '\0';
    bitset(buffer[0]);
    //myss << buffer;
    myss.write(buffer,1);
    //myss.Close();
}
Community
  • 1
  • 1
ZnArK
  • 1,533
  • 1
  • 12
  • 23
1

You can also use a Rugged Circuits Yellowjacket. It has a Wifi on board and can serve simple web pages and control inputs/outputs.

Jeff
  • 1,364
  • 1
  • 8
  • 17