Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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.

Christopher Pitt

May 04, 2017
Tweet

More Decks by Christopher Pitt

Other Decks in Programming

Transcript

  1. MAKING ROBOTS

    View Slide

  2. GONNA TALK ABOUT
    ▸ hardware
    ▸ software
    ▸ creativity

    View Slide

  3. HARDWARE
    ▸ Arduino
    ▸ Tessel

    View Slide

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

    View Slide

  5. View Slide

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

    View Slide

  7. MANY WAYS TO PROGRAM
    ▸ Compiled
    ▸ Firmata

    View Slide

  8. TIME TO
    MAKE IT WORK!

    View Slide

  9. View Slide

  10. SIMPLE
    AND EFFECTIVE!

    View Slide

  11. SOMETIMES CIRCUITS
    GET COMPLEX

    View Slide

  12. LIMITS
    (LIKE CURRENT)

    View Slide

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

    View Slide

  14. RESISTOR

    View Slide

  15. DIODE

    View Slide

  16. TRANSISTOR

    View Slide

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

    View Slide

  18. WHAT CAN WE
    DO WITH THIS?

    View Slide

  19. View Slide

  20. USEFUL WITH AERYS

    View Slide

  21. WHAT ELSE?

    View Slide

  22. View Slide

  23. interface Service
    {
    public function name();
    public function colors();
    public function query();
    public function dismiss();
    }

    View Slide

  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
    );
    }
    }

    View Slide

  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;
    }

    View Slide

  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];
    }

    View Slide

  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;
    }
    }

    View Slide

  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;
    }
    // ...

    View Slide

  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;
    }

    View Slide

  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];
    }

    View Slide

  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();

    View Slide

  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;

    View Slide

  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
    ]);

    View Slide

  34. $loop->setInterval(function () use (&$services) {
    $remaining = count($services);
    while ($remaining--) {
    $next = $services->dequeue();
    $next[1] = $next[0]->query();
    $services->enqueue($next);
    }
    }, 1000 * 5);

    View Slide

  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;
    // ...

    View Slide

  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);

    View Slide

  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);

    View Slide

  38. bit.ly/sitepoint-arduino-notifications

    View Slide

  39. QUESTIONS?
    twitter.com/assertchris

    View Slide