|
1 | 1 | ---
|
2 | 2 | title: GIGA R1 Camera Guide
|
3 |
| -description: Learn about GIGA R1 and camera compatibility, and find examples that work out of the box with the GIGA R1. |
4 |
| -tags: [ArduCAM, Camera, AI, OpenMV] |
| 3 | +description: Learn about the GIGA R1 & GIGA R1 WiFi's camera connector, and how to use existing examples. |
| 4 | +tags: [ArduCAM, Camera, Processing] |
5 | 5 | author: Karl Söderby
|
6 | 6 | ---
|
7 | 7 |
|
8 | 8 | The GIGA R1 has a dedicated camera connector that allows certain camera modules to mount directly on the board. This makes it possible to add machine vision to your GIGA R1 board without much effort at all.
|
9 | 9 |
|
10 |
| -In this guide, we will explore the GIGA R1's camera support a bit more in-depth: |
| 10 | +In this guide, we will explore the following: |
11 | 11 |
|
12 | 12 | - Where the camera connector is located.
|
13 | 13 | - What cameras are compatible.
|
14 |
| -- What library/examples are available. |
15 |
| -- How to get started with machine vision using the OpenMV platform. |
| 14 | +- What library to use. |
| 15 | +- How to setup a camera stream to a processing application. |
16 | 16 |
|
17 |
| -## Hardware Requirements |
| 17 | +## Hardware & Software Needed |
18 | 18 |
|
19 | 19 | To follow and use the examples provided in this guide, you will need one of the following boards:
|
20 | 20 |
|
21 |
| -- [GIGA R1]() |
22 |
| -- [GIGA R1 WiFi]() |
| 21 | +- [GIGA R1](/hardware/giga-r1) |
| 22 | +- [GIGA R1 WiFi](/hardware/giga-r1-wifi) |
| 23 | + |
| 24 | +You will also need the following software: |
| 25 | +- [Arduino IDE](https://www.arduino.cc/en/software) (any version). |
| 26 | +- [Processing](https://processing.org/download) (for displaying camera feed). |
23 | 27 |
|
24 | 28 | ## Supported Cameras
|
25 | 29 |
|
@@ -57,19 +61,19 @@ The complete pin map can be found below:
|
57 | 61 |
|
58 | 62 | 
|
59 | 63 |
|
60 |
| -## OpenMV |
| 64 | +You can also view the schematic for this connector in more detail just below. This is useful to understand exactly which pins on the STM32H747XI microcontroller is used. |
61 | 65 |
|
62 |
| -[OpenMV](https://openmv.io/) is a platform for machine vision projects, and can be programmed with MicroPython, more specifically, [OpenMV's branch of MicroPython](https://github.com/openmv/micropython). |
| 66 | + |
63 | 67 |
|
64 | 68 | ## Raw Bytes Over Serial (Processing)
|
65 | 69 |
|
66 | 70 | 
|
67 | 71 |
|
68 |
| -This example allows you to stream the sensor data from your camera to a Processing application, using serial over USB. This will allow you to see the image directly in your computer. |
| 72 | +This example allows you to stream the sensor data from your camera to a Processing application, using serial over USB. This will allow you to see the image directly in your computer. |
69 | 73 |
|
70 | 74 | ***This example requires a version of [Processing](https://processing.org/download) on your machine.***
|
71 | 75 |
|
72 |
| -**Step 1: Arduino** |
| 76 | +### Step 1: Arduino |
73 | 77 |
|
74 | 78 | Upload the following sketch to your board.
|
75 | 79 |
|
@@ -151,13 +155,13 @@ void loop() {
|
151 | 155 |
|
152 | 156 | ```
|
153 | 157 |
|
154 |
| -**Step 2: Processing** |
| 158 | +### Step 2: Processing |
155 | 159 |
|
156 |
| -The following processing sketch will launch a Java app that allows you to view the camera. As data is streamed via serial, make sure you close the Serial Monitor during this process, else it won't work. |
| 160 | +The following Processing sketch will launch a Java app that allows you to view the camera feed. As data is streamed via serial, make sure you close the Serial Monitor during this process, else it will not work. |
157 | 161 |
|
158 | 162 | ***Important! Make sure to replace the following line in the code below: `/dev/cu.usbmodem14301`, with the name of your port.***
|
159 | 163 |
|
160 |
| -Click on the big "PLAY" button to initialize the app. |
| 164 | +Click on the **"PLAY"** button to initialize the app. |
161 | 165 |
|
162 | 166 | ```cpp
|
163 | 167 | /*
|
@@ -283,184 +287,6 @@ void serialEvent(Serial myPort) {
|
283 | 287 |
|
284 | 288 | If all goes well, you should now be able to see the camera feed.
|
285 | 289 |
|
286 |
| -### JPEG Webserver |
287 |
| -
|
288 |
| -The **JPEG Webserver** allows you to take an image every X amount of seconds and upload it to a webserver that can be accessed remotely. This setup can be used for asset monitoring, security systems, smart doorbells and many more applications. |
289 |
| -
|
290 |
| -This setup also comes with a Golang script that you will need to launch via a terminal, which is required to make this setup work. |
291 |
| -
|
292 |
| -**Step 1: Launch Golang Script** |
293 |
| -
|
294 |
| -First, create a file in a directory of your choice, and name it `main.go`. Paste the following code into it: |
295 |
| -
|
296 |
| -```go |
297 |
| -package main |
298 |
| -
|
299 |
| -import ( |
300 |
| - "fmt" |
301 |
| - "io/ioutil" |
302 |
| - "net/http" |
303 |
| - "strconv" |
304 |
| - "time" |
305 |
| -) |
306 |
| -
|
307 |
| -func uploadFile(w http.ResponseWriter, r *http.Request) { |
308 |
| - fmt.Println("File Upload Endpoint Hit") |
309 |
| -
|
310 |
| - // Parse our multipart form, 10 << 20 specifies a maximum |
311 |
| - // upload of 10 MB files. |
312 |
| - r.ParseMultipartForm(10 << 20) |
313 |
| - // FormFile returns the first file for the given key `myFile` |
314 |
| - // it also returns the FileHeader so we can get the Filename, |
315 |
| - // the Header and the size of the file |
316 |
| - file, handler, err := r.FormFile("image1") |
317 |
| - if err != nil { |
318 |
| - fmt.Println("Error Retrieving the File") |
319 |
| - fmt.Println(err) |
320 |
| - return |
321 |
| - } |
322 |
| - defer file.Close() |
323 |
| - fmt.Printf("Uploaded File: %+v\n", handler.Filename) |
324 |
| - fmt.Printf("File Size: %+v\n", handler.Size) |
325 |
| - fmt.Printf("MIME Header: %+v\n", handler.Header) |
326 |
| -
|
327 |
| - // Create a temporary file within our temp-images directory that follows |
328 |
| - // a particular naming pattern |
329 |
| - name := "upload-" + strconv.Itoa(int(time.Now().Unix())) + "*.jpg" |
330 |
| - tempFile, err := ioutil.TempFile("", name) |
331 |
| - if err != nil { |
332 |
| - fmt.Println(err) |
333 |
| - } |
334 |
| - defer tempFile.Close() |
335 |
| - fmt.Println("File ", tempFile.Name()) |
336 |
| -
|
337 |
| - // read all of the contents of our uploaded file into a |
338 |
| - // byte array |
339 |
| - fileBytes, err := ioutil.ReadAll(file) |
340 |
| - if err != nil { |
341 |
| - fmt.Println(err) |
342 |
| - } |
343 |
| - // write this byte array to our temporary file |
344 |
| - tempFile.Write(fileBytes) |
345 |
| - // return that we have successfully uploaded our file! |
346 |
| - fmt.Println("Successfully Uploaded File\n") |
347 |
| -} |
348 |
| -
|
349 |
| -func setupRoutes() { |
350 |
| - http.HandleFunc("/upload", uploadFile) |
351 |
| - http.ListenAndServe(":8088", nil) |
352 |
| -} |
353 |
| -
|
354 |
| -func main() { |
355 |
| - fmt.Println("Hello World") |
356 |
| - fmt.Println("Serving on :8088") |
357 |
| - setupRoutes() |
358 |
| -} |
359 |
| -``` |
360 |
| - |
361 |
| -Then, to launch the script, open a terminal on the directory and use the following command: |
362 |
| - |
363 |
| -``` |
364 |
| -go run main.go |
365 |
| -``` |
366 |
| - |
367 |
| -Which, on success will return `Serving on :8088`. |
368 |
| - |
369 |
| -**Step 2: OpenMV Script** |
370 |
| - |
371 |
| -Next step is to launch the OpenMV editor. If you are not yet familiar with OpenMV, visit the [Getting Started with OpenMV]() section. |
372 |
| - |
373 |
| -Once the editor is open, connect your board. Then, copy and paste the script below into the editor, and click on the green "PLAY" button. |
374 |
| - |
375 |
| -***Please note that the `WIFI_SSID = "yournetwork"` and `WIFI_PASS = "yourpassword"` strings will need to be replaced with your credentials to your Wi-Fi network.*** |
376 |
| - |
377 |
| -```python |
378 |
| -import time |
379 |
| -import network |
380 |
| -import sensor |
381 |
| -import urequests |
382 |
| -import os |
383 |
| - |
384 |
| -WIFI_SSID = "yournetwork" |
385 |
| -WIFI_PASS = "yourpassword" |
386 |
| - |
387 |
| -url = 'http://10.130.22.213:8088/upload' |
388 |
| - |
389 |
| -headers = { |
390 |
| - 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:55.0) Gecko/20100101 Firefox/55.0', |
391 |
| - # Add more headers if needed |
392 |
| -} |
393 |
| - |
394 |
| -class RAMBlockDev: |
395 |
| - def __init__(self, block_size, num_blocks): |
396 |
| - self.block_size = block_size |
397 |
| - self.data = bytearray(block_size * num_blocks) |
398 |
| - |
399 |
| - def readblocks(self, block_num, buf, offset=0): |
400 |
| - addr = block_num * self.block_size + offset |
401 |
| - for i in range(len(buf)): |
402 |
| - buf[i] = self.data[addr + i] |
403 |
| - |
404 |
| - def writeblocks(self, block_num, buf, offset=None): |
405 |
| - if offset is None: |
406 |
| - # do erase, then write |
407 |
| - for i in range(len(buf) // self.block_size): |
408 |
| - self.ioctl(6, block_num + i) |
409 |
| - offset = 0 |
410 |
| - addr = block_num * self.block_size + offset |
411 |
| - for i in range(len(buf)): |
412 |
| - self.data[addr + i] = buf[i] |
413 |
| - |
414 |
| - def ioctl(self, op, arg): |
415 |
| - if op == 4: # block count |
416 |
| - return len(self.data) // self.block_size |
417 |
| - if op == 5: # block size |
418 |
| - return self.block_size |
419 |
| - if op == 6: # block erase |
420 |
| - return 0 |
421 |
| - |
422 |
| -def sensor_init(): |
423 |
| - sensor.reset() |
424 |
| - sensor.set_pixformat(sensor.RGB565) |
425 |
| - sensor.set_framesize(sensor.QVGA) |
426 |
| - sensor.skip_frames(time = 1000) |
427 |
| - |
428 |
| -def wifi_connect(): |
429 |
| - if not WIFI_SSID or not WIFI_PASS: |
430 |
| - raise (Exception("Network is not configured")) |
431 |
| - wlan = network.WLAN(network.STA_IF) |
432 |
| - wlan.active(True) |
433 |
| - wlan.connect(WIFI_SSID, WIFI_PASS) |
434 |
| - while not wlan.isconnected(): |
435 |
| - #raise (Exception("Network is not configured, add SSID and pass to secrets.py")) |
436 |
| - time.sleep_ms(500) |
437 |
| - print("WiFi Connected ", wlan.ifconfig()) |
438 |
| - |
439 |
| - |
440 |
| - |
441 |
| -if __name__ == "__main__": |
442 |
| - sensor_init() |
443 |
| - wifi_connect() |
444 |
| - bdev = RAMBlockDev(512, 100) |
445 |
| - os.VfsFat.mkfs(bdev) |
446 |
| - os.mount(bdev, '/ramdisk') |
447 |
| - while (True): |
448 |
| - img = sensor.snapshot() |
449 |
| - jpg = img.compress() |
450 |
| - with open('/ramdisk/img.jpg', 'w') as f: |
451 |
| - f.write(jpg) |
452 |
| - f.close() |
453 |
| - files = { |
454 |
| - 'image1': ('img.jpg', open('/ramdisk/img.jpg', 'rb')) |
455 |
| - } |
456 |
| - r = urequests.post(url, files=files, headers=headers) |
457 |
| - print(f"sending {jpg}") |
458 |
| - time.sleep(20.0) |
459 |
| -``` |
460 |
| - |
461 |
| -Once you run the script, the board will attempt to connect to the local Wi-Fi, and on success, it will capture an image and upload it. |
462 |
| - |
463 |
| -This can now be accessed if your device is on the same local network. |
464 |
| - |
465 |
| -### Motion Detection |
| 290 | +## Summary |
466 | 291 |
|
| 292 | +In this article, we learned a bit more about the camera connector on board the GIGA R1 board, how it is connected to the STM32H747XI microcontroller, and a simple example on how to connect an inexpensive OV7675 camera module to a Processing application. |
0 commit comments