Making Robots (PHP Unicorn Conf)

Making Robots (PHP Unicorn Conf)

I bet you're the kind of person who's too busy working to build robots, with PHP. Well, you're missing out!

Over the last few years, I've built all sorts of useful robots (Internet of Things machines); to connect to virtual environments, automate my surroundings, or generally make my life easier.

And I found all of these could be built using little more than the familiar PHP code I was using in my 9-to-5. Join me as I show you some of the cool things you can do, with an Arduino, some useful PHP libraries, and a lot of imagination.

061e3bae4ce4234a2194d20a382e5d19?s=128

Christopher Pitt

May 04, 2017
Tweet

Transcript

  1. MAKING ROBOTS

  2. GONNA TALK ABOUT ▸ hardware ▸ software ▸ creativity

  3. HARDWARE ▸ Arduino ▸ Tessel

  4. THEY UNDERSTAND ▸ Javascript ▸ C/C++

  5. None
  6. INPUT, OUTPUTS, SERIAL... (OH MY!)

  7. MANY WAYS TO PROGRAM ▸ Compiled ▸ Firmata

  8. TIME TO MAKE IT WORK!

  9. None
  10. SIMPLE AND EFFECTIVE!

  11. SOMETIMES CIRCUITS GET COMPLEX

  12. LIMITS (LIKE CURRENT)

  13. LET'S MAKE A NEW CIRCUIT, AND LEARN SOME NEW COMPONENTS...

  14. RESISTOR

  15. DIODE

  16. TRANSISTOR

  17. http://bit.ly/arduino-motors

  18. WHAT CAN WE DO WITH THIS?

  19. None
  20. USEFUL WITH AERYS

  21. WHAT ELSE?

  22. None
  23. interface Service { public function name(); public function colors(); public

    function query(); public function dismiss(); }
  24. namespace Notifier\Service; use Notifier\Service; use Endroid\Twitter\Twitter as Client; class Twitter

    implements Service { private $client; private $new = false; private $since = null; public function __construct($consumerKey, $consumerSecret, $accessToken, $accessTokenSecret) { $this->client = new Client( $consumerKey, $consumerSecret, $accessToken, $accessTokenSecret ); } }
  25. public function query() { if ($this->new) return true; $parameters =

    ["count" => 1]; if ($this->since) { $parameters["since_id"] = $this->since; } $response = $this->client->query( "statuses/mentions_timeline", "GET", "json", $parameters ); $tweets = json_decode($response->getContent()); if (count($tweets) > 0) { $this->new = true; $this->since = (int) $tweets[0]->id; } return $this->new; }
  26. public function dismiss() { $this->new = false; } public function

    name() { return "twitter"; } public function colors() { return [1 - 0.11, 1 - 0.62, 1 - 0.94]; }
  27. namespace Notifier\Service; use Notifier\Service; class Gmail implements Service { private

    $new = false; private $emails = []; private $username; private $password; public function __construct($username, $password) { $this->username = $username; $this->password = $password; } }
  28. public function query() { if ($this->new) return true; $inbox =

    imap_open( "{imap.gmail.com:993/imap/ssl}INBOX", $this->username, $this->password ); if (!inbox) { return false; } // ...
  29. $emails = imap_search($inbox, "ALL", SE_UID); if ($emails) { foreach ($emails

    as $email) { if (!in_array($email, $this->emails)) { $this->new = true; break; } } $this->emails = array_values($emails); } return $this->new; }
  30. public function dismiss() { $this->new = false; } public function

    name() { return "gmail"; } public function colors() { return [1 - 0.89, 1 - 0.15, 1 - 0.15]; }
  31. use Carica\Io; use Carica\Firmata; $loop = Io\Event\Loop\Factory::get(); $board = new

    Firmata\Board( Io\Stream\Serial\Factory::create( "/dev/cu.usbmodem14111", 57600 ) ); $board ->activate() ->done(function () use ($loop, $board) { // ...connect to services }); $loop->run();
  32. // diode pins $board->pins[10]->mode = Firmata\Pin::MODE_PWM; $board->pins[10]->analog = 1; $board->pins[11]->mode

    = Firmata\Pin::MODE_PWM; $board->pins[11]->analog = 1; $board->pins[9]->mode = Firmata\Pin::MODE_PWM; $board->pins[9]->analog = 1; // sensor pins $board->pins[12]->mode = Firmata\Pin::MODE_OUTPUT; $board->pins[12]->digital = 1; $board->pins[14]->mode = Firmata\Pin::MODE_ANALOG;
  33. $services = new SplQueue(); $services->enqueue([ new Notifier\Service\Twitter( getenv("SERVICE_TWITTER_CONSUMER_KEY"), getenv("SERVICE_TWITTER_CONSUMER_SECRET"), getenv("SERVICE_TWITTER_ACCESS_TOKEN"),

    getenv("SERVICE_TWITTER_ACCESS_TOKEN_SECRET") ), false ]); $services->enqueue([ new Notifier\Service\Gmail( getenv("SERVICE_GMAIL_USERNAME"), getenv("SERVICE_GMAIL_PASSWORD") ), false ]);
  34. $loop->setInterval(function () use (&$services) { $remaining = count($services); while ($remaining--)

    { $next = $services->dequeue(); $next[1] = $next[0]->query(); $services->enqueue($next); } }, 1000 * 5);
  35. $service = null; $next = function () use ($loop, $board,

    &$next, &$services, &$service) { $remaining = count($services); while ($remaining--) { $next = $services->dequeue(); $services->enqueue($next); if ($next[1]) { $service = $next; break; } } // ...no notifications if (!$service) return; // ...
  36. $colors = $service[0]->colors(); $board->pins[10]->analog = $colors[0]; $board->pins[11]->analog = $colors[1]; $board->pins[9]->analog

    = $colors[2]; $loop->setTimeout(function () use ($board, &$service) { $board->pins[10]->analog = 1; $board->pins[11]->analog = 1; $board->pins[9]->analog = 1; $service = null; }, 1000 * 1.5); }; $loop->setInterval($next, 1000 * 4);
  37. $loop->setInterval(function() use ($board, &$services, &$service) { if ($service !== null

    && $board->pins[14]->analog < 0.1) { $remaining = count($services); while ($remaining--) { $next = $services->dequeue(); // dismissing notification... if ($next[0]->name() === $service[0]->name()) { $service = null; $next[0]->dismiss(); $next[1] = false; } $services->enqueue($next); } } }, 50);
  38. bit.ly/sitepoint-arduino-notifications

  39. QUESTIONS? twitter.com/assertchris