arduino · Electronics · kids · lessons · magic · programming · Websites

ESP32 Cameras! Incredible power for teaching.

40508073-98f9-452b-88e3-951cb8adafcb

There is a new and fantastic cluster of ESP32 boards that have hit the market.  This is just one of them.  They are WifiCameras that just work.  I’ve been tinkering with cameras for a long time – using them for dog detection, facial recognition, even Nerf Battle Turrets.  Before now many of those projects were overly complicated and expensive.

The ESP32 Boards finally hit that sweet spot of ease and cost.

1b85a92b-9f71-497e-98ed-16a473f022e1

The boards are most easily found on BangGood.com the source code that just worked for me is found here:

https://github.com/LilyGO/ESP32-Camera

The library for the screen isn’t one of the ones you’ll find in the library manager but its easy to get going.  Its located here:

https://github.com/ThingPulse/esp8266-oled-ssd1306

And to install, you just download the git repo, then copy the whole directory into the “Libraries” of your Arduino install.

If you have trouble… let me know.

I forked the Repos at the point they worked….

The code…

The default program just worked out of the box… it was kind of amazing.

#include "OV2640.h"
#include <WiFi.h>
#include <WebServer.h>
#include <WiFiClient.h>

#define ENABLE_OLED 1 //if want use oled

#ifdef ENABLE_OLED
#include "SSD1306.h"
#define OLED_ADDRESS 0x3c
#define I2C_SDA 14
#define I2C_SCL 13
SSD1306Wire display(OLED_ADDRESS, I2C_SDA, I2C_SCL, GEOMETRY_128_32);
#endif

OV2640 cam;
WebServer server(80);

const char *ssid =     "<your wifi ssid>";         // Put your SSID here
const char *password = "<your wifi password>";     // Put your PASSWORD here

void handle_jpg_stream(void)
{
  WiFiClient client = server.client();
  String response = "HTTP/1.1 200 OK\r\n";
  response += "Content-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n";
  server.sendContent(response);

  while (1)
  {
    cam.run();
    if (!client.connected())
      break;
    response = "--frame\r\n";
    response += "Content-Type: image/jpeg\r\n\r\n";
    server.sendContent(response);

    client.write((char *)cam.getfb(), cam.getSize());
    server.sendContent("\r\n");
    if (!client.connected())
      break;
  }
}

void handle_jpg(void)
{
  WiFiClient client = server.client();

  cam.run();
  if (!client.connected())
  {
    Serial.println("fail ... \n");
    return;
  }
  String response = "HTTP/1.1 200 OK\r\n";
  response += "Content-disposition: inline; filename=capture.jpg\r\n";
  response += "Content-type: image/jpeg\r\n\r\n";
  server.sendContent(response);
  client.write((char *)cam.getfb(), cam.getSize());
}

void handleNotFound()
{
  String message = "Server is running!\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  server.send(200, "text/plain", message);
}

void setup()
{
  Serial.begin(115200);
  while (!Serial)
  {
    ;
  }

  camera_config_t camera_config;
  camera_config.ledc_channel = LEDC_CHANNEL_0;
  camera_config.ledc_timer = LEDC_TIMER_0;
  camera_config.pin_d0 = 17;
  camera_config.pin_d1 = 35;
  camera_config.pin_d2 = 34;
  camera_config.pin_d3 = 5;
  camera_config.pin_d4 = 39;
  camera_config.pin_d5 = 18;
  camera_config.pin_d6 = 36;
  camera_config.pin_d7 = 19;
  camera_config.pin_xclk = 27;
  camera_config.pin_pclk = 21;
  camera_config.pin_vsync = 22;
  camera_config.pin_href = 26;
  camera_config.pin_sscb_sda = 25;
  camera_config.pin_sscb_scl = 23;
  camera_config.pin_reset = 15;
  camera_config.xclk_freq_hz = 20000000;
  camera_config.pixel_format = CAMERA_PF_JPEG;
  camera_config.frame_size = CAMERA_FS_SVGA;

  cam.init(camera_config);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(F("."));
  }
  Serial.println(F("WiFi connected"));
  Serial.println("");
  Serial.println(WiFi.localIP());

#ifdef ENABLE_OLED
  display.init();
  display.flipScreenVertically();
  display.setFont(ArialMT_Plain_16);
  display.setTextAlignment(TEXT_ALIGN_CENTER);
  display.drawString(128 / 2, 32 / 2, WiFi.localIP().toString());
  display.display();
#endif

  server.on("/", HTTP_GET, handle_jpg_stream);
  server.on("/jpg", HTTP_GET, handle_jpg);
  server.onNotFound(handleNotFound);
  server.begin();
}

void loop()
{
  server.handleClient();
}

Note you’ll need to update your Wifi settings in there, but once it works, it shows you the Wifi IP to hit.  Then just load the base page and you’ll start getting images!

It just keeps working!

I’ve been running this little board for two weeks straight – and it just keeps working.  The pictures are probably VGA quality – though I haven’t tried for anything better.

Some ideas for teaching…

There are some basic things about human nature that limit us.  Our reach, our strength, our intellect, resources and training.  Easy entertainment is found anytime you can make us feel like we are super human or give us a new skill.

For instance – we love cars because they make us fast.  Comic book characters because they help us imagine the ability to fly or bend metal with our bare hands.  Harry Potter and his magical abilities to affect things without touching them.

Super Human Abilities…

Sight beyond sight:

Anything that makes us feel super human is fun.  This board then gives us two things we can capitalize on as teachers.  The first: x-ray vision or far-sight.  The ability to see into impossible places.  Like this:

Now, the way you show this.  Install one of these little boards in a place that is as far away as you can reach and preferably looking at something cool.

Show the kids the board, get them running the code for the camera.  Make it real.  Then show them where in the world you’ve placed it.  It could be looking at a birds nest, or a beautiful vista.  The load up the webpage and show them the view you’ve found.

They suddenly hold, in their hands, the ability to use “Sight beyond sight.” 😉

Affect things from afar…

The second ability is linked to the ability to affect things from far away.  Kids throw stones as they explore their ability to cause something to happen a far away as they can reach.  With the internet… their reach is now global.

Install one of these boards… again as far away as you can get.  Make sure it has an internet wifi.  Maybe even in your home backyard.  Then use the URL params to cause something to happen.

In my case I have something super cool to turn on, my Wizards Fire, but it’s simple enough to cause a servo to wag a finger, or a motor to spin a flag.

MVIMG_20190124_205647
Wizards fire light.

See my Nginx Tutorial for making it publicly available

NginX on a Raspberry PI

That’s it!  Have fun, and let me know if you need help…

I like to hear about people teaching their kids – so if you need help – please let me know.

Have fun!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.