Share it

Follow me

Twitter

Google+

LinkedIn

MovingRaspi - Part 02: iPhone -> Raspberry Pi communication

MovingRaspi is a project I had some times ago, and I've just decided to start. Project's goal is to motorize a Raspberry Pi and control it with an iPhone (or iPad, or iPod Touch). This second part is about the communication between the iPhone and the Raspberry Pi.

 

Technical basis

In order to keep the code easy to understand, communication protocol between iPhone and Raspberry Pi will be simple. Commands are sent as full text to the Raspberry Pi, and are listed below:

  • forward : the two wheels of the robot rotate in order to make it going forward, until “stop” command is received.
  • reverse : the two wheels of the robot rotate in order to make it going backward, until “stop” command is received.
  • left : left wheel makes the robot going backward, right one make it going forward : the robot rotates to the left, until “stop” command is received.
  • right : left wheel makes the robot going forward, right one make it going backward : the robot rotates to the left, until “stop” command is received.
  • stop : the two wheels are stopped .

Pushing a button off the iPhone send the related command (commands are just sent once), and releasing the button send “stop” command. Leaving the finger on a button allow to play the command without stopping.

Raspberry Pi side

Server side is based on Twisted library for Python. Twisted brings you all you need to create a simple TCP server.

Server basis is below :

# Protocol for managing MovingRaspiRemote commands
class MovingRaspi(Protocol):
  # When a client connects
  def connectionMade(self):
    print("A client connected")

  # When a command is received
  def dataReceived(self, data):
    if data == "forward":
      # Left wheel forward
      ... insert related code ...
      # Right wheel forward
      ... insert related code ...

    elif data == "reverse":
      # Left wheel reverse
      ... insert related code ...
      # Right wheel reverse
      ... insert related code ...

    elif data == "left":
      # Left wheel reverse
      ... insert related code ...
      # Right wheel forward
      ... insert related code ...

    elif data == "right":
      # Left wheel forward
      ... insert related code ...
      # Right wheel reverse
      ... insert related code ...

    else:
      # All wheels stop
      ... insert related code ...


# Twisted initialization
factory = Factory()

# Assign to Twisted the protocol managing commands
factory.protocol = MovingRaspi

# Set the server to listen on all network interfaces port 8000
reactor.listenTCP(8000, factory, 50, '0.0.0.0')

# Starts TCP server, which will wait for connections to serve
reactor.run()
          

Full code for the server is available on GitHub. To test it, you'll have to build the assembly below :

Temporary assembly
Temporary schematics

LEDs #1 to #4 are equivalents to the transistors driving right motor, LEDs #5 to #8 are equivalents to the transistors driving left motor.

  • Forward : LED #1, #2, #5 and #6 turned on.
  • Reverse : LED #3, #4, #7 and #8 turned on.
  • Right : LED #3, #4, #5 and #6 turned on.
  • Left : LED #1, #2, #7 and #8 turned on.

Explanations on transistors use will be given in third part.

iPhone side

Awaited GUI should looks like below:

MovingRaspi Remote

View controller must implements “NSStreamDelegate” protocol to manage communications with the server.

Connection button must call the following function on « TouchUpInside » event

- (IBAction)doConnect:(id)sender {
    // Set TCP connection to open with the server
    CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;
    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)CFBridgingRetain(@"hostname"), [@"port" intValue], &readStream, &writeStream);
    _outputStream = (NSOutputStream *)CFBridgingRelease(writeStream);

    [_outputStream setDelegate:self];

    [_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

    // Open TCP connection
    [_outputStream open];
}
          

Disconnection button must call the following function on « TouchUpInside » event

- (IBAction)doDisconnect:(id)sender {
    // Close TCP connection

    [_outputStream close];
}
          

“Forward” button must call the following function on « TouchDown » event (adapt code for “Reverse”, “Left” and “Right” to send the related commands).

- (IBAction)goForward:(id)sender {
    // Send "forward" command when “Forward” button is pushed

    NSString *response  = @"forward";
    NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
    [_outputStream write:[data bytes] maxLength:[data length]];
}
          

“Forward”, “Reverse”, “Left” and “Right” buttons must call the following function on « TouchUpInside » event

// Send "stop" command when button is released

NSString *response  = @"stop";
NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
[_outputStream write:[data bytes] maxLength:[data length]];
          

Full code of MovingRaspiRemote is available on GitHub. To test it, you have to install it on your iDevice (iPhone / iPad / iPod Touch). If you don't have an iOS Developer account, you may run it on iOS Simulator.

To finish

All code for this part is available on GitHub.

A video showing the code working is visible below:



comments powered by Disqus