From bbcd0f4ecc9225a82d31a46f26b7838a70705d46 Mon Sep 17 00:00:00 2001
From: marqdevx
Date: Fri, 19 Aug 2022 11:35:19 +0200
Subject: [PATCH 01/11] Update sketch and alignt content to it
Co-authored-by: sebromero
---
.../camera-to-bitmap-sd-card/content.md | 359 ++++++++++--------
1 file changed, 196 insertions(+), 163 deletions(-)
diff --git a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
index 3d095cc035..8d7b75e6af 100644
--- a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
+++ b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
@@ -48,8 +48,8 @@ You will be using the **Himax HM-01B0 camera module** which has a resolution of
Inside the sketch, you can use these libraries to access the camera APIs, also compatible with the [Arduino Nicla Vision](hardware/nicla-vision)
```cpp
-#include "camera.h" // Arduino Mbed Core Camera APIs
-#include "himax.h" // Exclusive Camera library for the Portenta Vision Shield //Only for the Vision Shield
+#include "camera.h" // Multi Media Card APIs
+#include "himax.h" // Mbed API for portable and embedded systems
```
#### Bitmap File Format
@@ -76,8 +76,8 @@ You can find the sketch on the latest version of the [Arduino_Pro_Tutorials](htt
First you need to include the needed libraries
```cpp
-#include "SDMMCBlockDevice.h" // Multi Media Card APIs
-#include "FATFileSystem.h" // Mbed API for portable and embedded systems
+#include "SDMMCBlockDevice.h" // Multi Media Card APIs
+#include "FATFileSystem.h" // Mbed API for portable and embedded systems
#include "camera.h" // Arduino Mbed Core Camera APIs
#include "himax.h" // Exclusive Camera library for the Portenta Vision Shield
@@ -86,8 +86,8 @@ First you need to include the needed libraries
Then we define the following objects with their respective constructor (`blockDevice` and `fileSystem` objects), needed for getting access to the SD Card and the file system.
```cpp
-#include "SDMMCBlockDevice.h" // Multi Media Card APIs
-#include "FATFileSystem.h" // Mbed API for portable and embedded systems
+#include "SDMMCBlockDevice.h" // Multi Media Card APIs
+#include "FATFileSystem.h" // Mbed API for portable and embedded systems
SDMMCBlockDevice blockDevice;
mbed::FATFileSystem fileSystem("fs");
@@ -95,76 +95,71 @@ mbed::FATFileSystem fileSystem("fs");
#include "himax.h" // Exclusive Camera library for the Portenta Vision Shield
HM01B0 himax;
Camera cam(himax);
-FrameBuffer fb; // Buffer to save the capture
+
+FrameBuffer frameBuffer; // Buffer to save the capture
```
For the bitmap headers binary file you will need some information like the resolution of the image, the bits per pixel and more; so you can define your settings as shown:
```cpp
// Settings for our setup
-#define RES_H (unsigned int)240
-#define RES_W (unsigned int)320
+#define IMAGE_HEIGHT (unsigned int)240
+#define IMAGE_WIDTH (unsigned int)320
#define IMAGE_MODE CAMERA_GRAYSCALE
-#define IMAGE_BPP (unsigned int)8
+#define BITS_PER_PIXEL (unsigned int)8
+#define PALETTE_COLORS_AMOUNT (unsigned int)(pow(2, BITS_PER_PIXEL))
+#define PALETTE_SIZE (unsigned int)(PALETTE_COLORS_AMOUNT * 4) // 4 bytes = 32bit per color (3 bytes RGB and 1 byte 0x00)
+#define IMAGE_PATH "/fs/image.bmp"
+
// Headers info
-#define HEADER_FILE_HEADER (unsigned int)14
-#define HEADER_DIB_SIZE (unsigned int)40
-#define HEADER_FULL_SIZE (HEADER_FILE_HEADER + HEADER_DIB_SIZE)
-#define PALETTE_SIZE (2 ^ IMAGE_BPP) * 4 // 4 bytes per color
+#define BITMAP_FILE_HEADER_SIZE (unsigned int)14 // For storing general information about the bitmap image file
+#define DIB_HEADER_SIZE (unsigned int)40 // For storing information about the image and define the pixel format
+#define HEADER_SIZE (BITMAP_FILE_HEADER_SIZE + DIB_HEADER_SIZE)
```
-To mount the SD Card, you can use the following function in the sketch:
+The program has the following functions declared:
+* `void mountSDCard()`
+* `unsigned char * captureImage()`
+* `void setFileHeaders(bitmapFileHeaders, bitmapDIBHeader, fileSize)`
+* `void setColorMap(colorMap)`
+* `saveImage(imageData, imagePath)`
+
+To mount the SD Card you will use the following function in the sketch:
```cpp
// Mount File system block
-void mountSD()
-{
- Serial.println("Mounting SD Card...");
-
+void mountSDCard(){
int error = fileSystem.mount(&blockDevice);
- if (error)
- {
- Serial.println("No SD Card found");
- while (1)
- ;
+ if (error){
+ Serial.println("Trying to reformat...");
+ int formattingError = fileSystem.reformat(&blockDevice);
+ if (formattingError) {
+ Serial.println("No SD Card found");
+ while (1);
+ }
}
}
```
-Another function that the sketch contains is the one to generate the `.bmp` file called `parseData()`.
-This function will create the needed headers that you will need later to encode our bitmap into a file.
-
-***Take a look at the section [Bitmap File Format](#bitmap-file-format) to better understand the file headers that are created with this function***
-
+The function to capture the frame from the camera:
```cpp
-void parseData()
-{
- unsigned char *imgData = NULL;
- int fileSize = HEADER_FILE_HEADER + RES_W * RES_H;
-
- FILE *file = fopen("/fs/image.bmp", "w+");
-
- // Get a Frame
- if (cam.grabFrame(fb, 3000) == 0)
- {
- // Save the raw image data (8bpp grayscale)
- imgData = fb.getBuffer();
- }
- else
- {
+// Get the raw image data (8bpp grayscale)
+unsigned char * captureImage(){
+ if (cam.grabFrame(frameBuffer, 3000) == 0){
+ return frameBuffer.getBuffer();
+ } else {
Serial.println("could not grab the frame");
- while (1)
- ;
+ while (1);
}
- // Bitmap structure (Head + DIB Head + ColorMap + binary image)
- unsigned char bitmapFileHeader[HEADER_FILE_HEADER];
- unsigned char bitmapDIBHeader[HEADER_DIB_SIZE];
- unsigned char colorMap[PALETTE_SIZE]; // Needed for <=8bpp grayscale bitmaps
+}
+```
- // Set the file headers to 0
- memset(bitmapFileHeader, (unsigned char)(0), HEADER_FILE_HEADER);
- memset(bitmapDIBHeader, (unsigned char)(0), HEADER_DIB_SIZE);
- memset(colorMap, (unsigned char)(0), PALETTE_SIZE);
+To manipulate the file you will need to set the headers on the binary information as follows:
+```cpp
+// Set the headers data
+void setFileHeaders(unsigned char *bitmapFileHeader, unsigned char *bitmapDIBHeader, int fileSize){
+ // Set the headers to 0
+ memset(bitmapFileHeader, (unsigned char)(0), BITMAP_FILE_HEADER_SIZE);
+ memset(bitmapDIBHeader, (unsigned char)(0), DIB_HEADER_SIZE);
- // Write the headers info
// File header
bitmapFileHeader[0] = 'B';
bitmapFileHeader[1] = 'M';
@@ -172,59 +167,89 @@ void parseData()
bitmapFileHeader[3] = (unsigned char)(fileSize >> 8);
bitmapFileHeader[4] = (unsigned char)(fileSize >> 16);
bitmapFileHeader[5] = (unsigned char)(fileSize >> 24);
- bitmapFileHeader[10] = (unsigned char)HEADER_FULL_SIZE + PALETTE_SIZE;
+ bitmapFileHeader[10] = (unsigned char)HEADER_SIZE + PALETTE_SIZE;
// Info header
- bitmapDIBHeader[0] = (unsigned char)(HEADER_DIB_SIZE);
- bitmapDIBHeader[4] = (unsigned char)(RES_W);
- bitmapDIBHeader[5] = (unsigned char)(RES_W >> 8);
- bitmapDIBHeader[8] = (unsigned char)(RES_H);
- bitmapDIBHeader[8] = (unsigned char)(RES_H >> 8);
- bitmapDIBHeader[14] = (unsigned char)(IMAGE_BPP);
-
- // Color palette for grayscale Bitmaps (8bpp)
- for (int i = 0; i < (2 ^ IMAGE_BPP); i++)
- {
+ bitmapDIBHeader[0] = (unsigned char)(DIB_HEADER_SIZE);
+ bitmapDIBHeader[4] = (unsigned char)(IMAGE_WIDTH);
+ bitmapDIBHeader[5] = (unsigned char)(IMAGE_WIDTH >> 8);
+ bitmapDIBHeader[8] = (unsigned char)(IMAGE_HEIGHT);
+ bitmapDIBHeader[9] = (unsigned char)(IMAGE_HEIGHT >> 8);
+ bitmapDIBHeader[14] = (unsigned char)(BITS_PER_PIXEL);
+}
+```
+
+***Take a look at the section [Bitmap File Format](#bitmap-file-format) to better understand the file headers that are created with this function***
+
+In this case that our image (320x240) is 8bits per pixel and grayscale on the bitmap rules we need to define the color table (color map) to assign an specific RGB color for our 8 bit color.
+On the follwing function it sets the color map as a grayscale of RGB colors from [R:0x00 G:0x00 B:0x00] to [R:0xFF G:0xFF B:0xFF]
+```cpp
+void setColorMap(unsigned char *colorMap){
+ //Init the palette with zeroes
+ memset(colorMap, (unsigned char)(0), PALETTE_SIZE);
+
+ // Gray scale color palette, 4 bytes per color (R, G, B, 0x00)
+ for (int i = 0; i < PALETTE_COLORS_AMOUNT; i++) {
colorMap[i * 4] = i;
colorMap[i * 4 + 1] = i;
colorMap[i * 4 + 2] = i;
}
+}
+```
+
+The function in charge to save the image will use the previous functions to set the headers and write the buffers into the file `image.bmp`
+```cpp
+
+// Save the headers and the image data into the .bmp file
+void saveImage(unsigned char *imageData, const char* imagePath){
+ int fileSize = BITMAP_FILE_HEADER_SIZE + DIB_HEADER_SIZE + IMAGE_WIDTH * IMAGE_HEIGHT;
+ FILE *file = fopen(imagePath, "w");
+
+ // Bitmap structure (Head + DIB Head + ColorMap + binary image)
+ unsigned char bitmapFileHeader[BITMAP_FILE_HEADER_SIZE];
+ unsigned char bitmapDIBHeader[DIB_HEADER_SIZE];
+ unsigned char colorMap[PALETTE_SIZE]; // Needed for <= 8bpp grayscale bitmaps
- // Write theh bitmap file
- fwrite(bitmapFileHeader, 1, HEADER_FILE_HEADER, file);
- fwrite(bitmapDIBHeader, 1, HEADER_DIB_SIZE, file);
- fwrite(colorMap, 1, PALETTE_SIZE, file); // Color map
- fwrite(imgData, 1, RES_H * RES_W, file);
+ setFileHeaders(bitmapFileHeader, bitmapDIBHeader, fileSize);
+ setColorMap(colorMap);
- // Close the stream (bitmap file)
+ // Write the bitmap file
+ fwrite(bitmapFileHeader, 1, BITMAP_FILE_HEADER_SIZE, file);
+ fwrite(bitmapDIBHeader, 1, DIB_HEADER_SIZE, file);
+ fwrite(colorMap, 1, PALETTE_SIZE, file);
+ fwrite(imageData, 1, IMAGE_HEIGHT * IMAGE_WIDTH, file);
+
+ // Close the file stream
fclose(file);
}
```
-The `setup()` will Initialize the Serial Monitor, mount the SD Card, initialize the camera module and parse the image data into the bitmap with its needed headers.
-
+Now that you have all the functions to be used, inside the `setup()` its call them only once after the board restarts.
```cpp
-void setup()
-{
+void setup(){
Serial.begin(115200);
- while (!Serial)
- ;
-
- // Mount SD Card
- mountSD();
+ while (!Serial && millis() < 5000);
+
+ Serial.println("Mounting SD Card...");
+ mountSDCard();
+ Serial.println("SD Card mounted.");
// Init the cam QVGA, 30FPS, Grayscale
- if (!cam.begin(CAMERA_R320x240, IMAGE_MODE, 30))
- {
+ if (!cam.begin(CAMERA_R320x240, IMAGE_MODE, 30)){
Serial.println("Unable to find the camera");
}
- // Save the headers and the image data into the .bmp file
- parseData();
+ Serial.println("Fetching camera image...");
+ unsigned char *imageData = captureImage();
+
+ Serial.println("Saving image to SD card...");
+ saveImage(imageData, IMAGE_PATH);
+
+ fileSystem.unmount();
+ Serial.println("Done. You can now remove the SD card.");
}
```
-
-The `loop()` is empty, as it only does one shot when the Serial Monitor is open.
+The `loop()` is empty, as it only does one shot when the Serial Monitor is open or after 5 seconds passed after boot.
### 3. Upload the Sketch
@@ -236,7 +261,7 @@ Insert a micro SD Card into the Portenta Vision Shield.
Connect the Portenta Vision shield to the Portenta H7.
-Once the sketch is uploaded, open the Serial Monitor: you should see that everything is fine and the capture has been taken.
+Once the sketch is uploaded, open the Serial Monitor or wait 5 seconds: you should see that everything is fine and the capture has been taken.
Once the capture is saved, remove the SD Card and plug it into a computer/phone with an SD Card reader, open the storage unit, look for a bitmap called `image.bmp` and open it to check the result. You will be able to see a grayscale image on your device's image viewer.
@@ -255,88 +280,78 @@ mbed::FATFileSystem fileSystem("fs");
HM01B0 himax;
Camera cam(himax);
-FrameBuffer fb; // Buffer to save the capture
+FrameBuffer frameBuffer; // Buffer to save the capture
// Settings for our setup
-#define RES_H (unsigned int)240
-#define RES_W (unsigned int)320
+#define IMAGE_HEIGHT (unsigned int)240
+#define IMAGE_WIDTH (unsigned int)320
#define IMAGE_MODE CAMERA_GRAYSCALE
-#define IMAGE_BPP (unsigned int)8
+#define BITS_PER_PIXEL (unsigned int)8
+#define PALETTE_COLORS_AMOUNT (unsigned int)(pow(2, BITS_PER_PIXEL))
+#define PALETTE_SIZE (unsigned int)(PALETTE_COLORS_AMOUNT * 4) // 4 bytes = 32bit per color (3 bytes RGB and 1 byte 0x00)
+#define IMAGE_PATH "/fs/image.bmp"
+
// Headers info
-#define HEADER_FILE_HEADER (unsigned int)14
-#define HEADER_DIB_SIZE (unsigned int)40
-#define HEADER_FULL_SIZE (HEADER_FILE_HEADER + HEADER_DIB_SIZE)
-#define PALETTE_SIZE (2 ^ IMAGE_BPP) * 4 // 4 bytes per color
+#define BITMAP_FILE_HEADER_SIZE (unsigned int)14 // For storing general information about the bitmap image file
+#define DIB_HEADER_SIZE (unsigned int)40 // For storing information about the image and define the pixel format
+#define HEADER_SIZE (BITMAP_FILE_HEADER_SIZE + DIB_HEADER_SIZE)
-void setup()
-{
- Serial.begin(115200);
- while (!Serial)
- ;
- // Mount SD Card
- mountSD();
+void setup(){
+ Serial.begin(115200);
+ while (!Serial && millis() < 5000);
+
+ Serial.println("Mounting SD Card...");
+ mountSDCard();
+ Serial.println("SD Card mounted.");
// Init the cam QVGA, 30FPS, Grayscale
- if (!cam.begin(CAMERA_R320x240, IMAGE_MODE, 30))
- {
+ if (!cam.begin(CAMERA_R320x240, IMAGE_MODE, 30)){
Serial.println("Unable to find the camera");
}
- // Save the headers and the image data into the .bmp file
- parseData();
+ Serial.println("Fetching camera image...");
+ unsigned char *imageData = captureImage();
+
+ Serial.println("Saving image to SD card...");
+ saveImage(imageData, IMAGE_PATH);
+
+ fileSystem.unmount();
+ Serial.println("Done. You can now remove the SD card.");
}
-void loop()
-{
- while (1)
- ;
+void loop(){
}
// Mount File system block
-void mountSD()
-{
- Serial.println("Mounting SD Card...");
-
+void mountSDCard(){
int error = fileSystem.mount(&blockDevice);
- if (error)
- {
- Serial.println("No SD Card found");
- while (1)
- ;
+ if (error){
+ Serial.println("Trying to reformat...");
+ int formattingError = fileSystem.reformat(&blockDevice);
+ if (formattingError) {
+ Serial.println("No SD Card found");
+ while (1);
+ }
}
}
-void parseData()
-{
- unsigned char *imgData = NULL;
- int fileSize = HEADER_FILE_HEADER + RES_W * RES_H;
-
- FILE *file = fopen("/fs/image.bmp", "w+");
-
- // Get a Frame
- if (cam.grabFrame(fb, 3000) == 0)
- {
- // Save the raw image data (8bpp grayscale)
- imgData = fb.getBuffer();
- }
- else
- {
+// Get the raw image data (8bpp grayscale)
+unsigned char * captureImage(){
+ if (cam.grabFrame(frameBuffer, 3000) == 0){
+ return frameBuffer.getBuffer();
+ } else {
Serial.println("could not grab the frame");
- while (1)
- ;
+ while (1);
}
- // Bitmap structure (Head + DIB Head + ColorMap + binary image)
- unsigned char bitmapFileHeader[HEADER_FILE_HEADER];
- unsigned char bitmapDIBHeader[HEADER_DIB_SIZE];
- unsigned char colorMap[PALETTE_SIZE]; // Needed for <=8bpp grayscale bitmaps
+}
- // Set the file headers to 0
- memset(bitmapFileHeader, (unsigned char)(0), HEADER_FILE_HEADER);
- memset(bitmapDIBHeader, (unsigned char)(0), HEADER_DIB_SIZE);
- memset(colorMap, (unsigned char)(0), PALETTE_SIZE);
+// Set the headers data
+void setFileHeaders(unsigned char *bitmapFileHeader, unsigned char *bitmapDIBHeader, int fileSize){
+ // Set the headers to 0
+ memset(bitmapFileHeader, (unsigned char)(0), BITMAP_FILE_HEADER_SIZE);
+ memset(bitmapDIBHeader, (unsigned char)(0), DIB_HEADER_SIZE);
- // Write the headers info
// File header
bitmapFileHeader[0] = 'B';
bitmapFileHeader[1] = 'M';
@@ -344,31 +359,49 @@ void parseData()
bitmapFileHeader[3] = (unsigned char)(fileSize >> 8);
bitmapFileHeader[4] = (unsigned char)(fileSize >> 16);
bitmapFileHeader[5] = (unsigned char)(fileSize >> 24);
- bitmapFileHeader[10] = (unsigned char)HEADER_FULL_SIZE + PALETTE_SIZE;
+ bitmapFileHeader[10] = (unsigned char)HEADER_SIZE + PALETTE_SIZE;
// Info header
- bitmapDIBHeader[0] = (unsigned char)(HEADER_DIB_SIZE);
- bitmapDIBHeader[4] = (unsigned char)(RES_W);
- bitmapDIBHeader[5] = (unsigned char)(RES_W >> 8);
- bitmapDIBHeader[8] = (unsigned char)(RES_H);
- bitmapDIBHeader[8] = (unsigned char)(RES_H >> 8);
- bitmapDIBHeader[14] = (unsigned char)(IMAGE_BPP);
-
- // Color palette for grayscale Bitmaps (8bpp)
- for (int i = 0; i < (2 ^ IMAGE_BPP); i++)
- {
+ bitmapDIBHeader[0] = (unsigned char)(DIB_HEADER_SIZE);
+ bitmapDIBHeader[4] = (unsigned char)(IMAGE_WIDTH);
+ bitmapDIBHeader[5] = (unsigned char)(IMAGE_WIDTH >> 8);
+ bitmapDIBHeader[8] = (unsigned char)(IMAGE_HEIGHT);
+ bitmapDIBHeader[9] = (unsigned char)(IMAGE_HEIGHT >> 8);
+ bitmapDIBHeader[14] = (unsigned char)(BITS_PER_PIXEL);
+}
+
+void setColorMap(unsigned char *colorMap){
+ //Init the palette with zeroes
+ memset(colorMap, (unsigned char)(0), PALETTE_SIZE);
+
+ // Gray scale color palette, 4 bytes per color (R, G, B, 0x00)
+ for (int i = 0; i < PALETTE_COLORS_AMOUNT; i++) {
colorMap[i * 4] = i;
colorMap[i * 4 + 1] = i;
colorMap[i * 4 + 2] = i;
}
+}
+
+// Save the headers and the image data into the .bmp file
+void saveImage(unsigned char *imageData, const char* imagePath){
+ int fileSize = BITMAP_FILE_HEADER_SIZE + DIB_HEADER_SIZE + IMAGE_WIDTH * IMAGE_HEIGHT;
+ FILE *file = fopen(imagePath, "w");
+
+ // Bitmap structure (Head + DIB Head + ColorMap + binary image)
+ unsigned char bitmapFileHeader[BITMAP_FILE_HEADER_SIZE];
+ unsigned char bitmapDIBHeader[DIB_HEADER_SIZE];
+ unsigned char colorMap[PALETTE_SIZE]; // Needed for <= 8bpp grayscale bitmaps
+
+ setFileHeaders(bitmapFileHeader, bitmapDIBHeader, fileSize);
+ setColorMap(colorMap);
- // Write theh bitmap file
- fwrite(bitmapFileHeader, 1, HEADER_FILE_HEADER, file);
- fwrite(bitmapDIBHeader, 1, HEADER_DIB_SIZE, file);
- fwrite(colorMap, 1, PALETTE_SIZE, file); // Color map
- fwrite(imgData, 1, RES_H * RES_W, file);
+ // Write the bitmap file
+ fwrite(bitmapFileHeader, 1, BITMAP_FILE_HEADER_SIZE, file);
+ fwrite(bitmapDIBHeader, 1, DIB_HEADER_SIZE, file);
+ fwrite(colorMap, 1, PALETTE_SIZE, file);
+ fwrite(imageData, 1, IMAGE_HEIGHT * IMAGE_WIDTH, file);
- // Close the stream (bitmap file)
+ // Close the file stream
fclose(file);
}
```
From a850ad05e0f969358f25e637297811e3ad50234d Mon Sep 17 00:00:00 2001
From: marqdevx
Date: Fri, 19 Aug 2022 11:46:34 +0200
Subject: [PATCH 02/11] Fix typo
---
.../tutorials/camera-to-bitmap-sd-card/content.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
index 8d7b75e6af..8e350a7148 100644
--- a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
+++ b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
@@ -182,7 +182,7 @@ void setFileHeaders(unsigned char *bitmapFileHeader, unsigned char *bitmapDIBHea
***Take a look at the section [Bitmap File Format](#bitmap-file-format) to better understand the file headers that are created with this function***
In this case that our image (320x240) is 8bits per pixel and grayscale on the bitmap rules we need to define the color table (color map) to assign an specific RGB color for our 8 bit color.
-On the follwing function it sets the color map as a grayscale of RGB colors from [R:0x00 G:0x00 B:0x00] to [R:0xFF G:0xFF B:0xFF]
+On the following function it sets the color map as a grayscale of RGB colors from [R:0x00 G:0x00 B:0x00] to [R:0xFF G:0xFF B:0xFF]
```cpp
void setColorMap(unsigned char *colorMap){
//Init the palette with zeroes
From 6e0ddec0af8b5f7f42278e88af650d4413438d52 Mon Sep 17 00:00:00 2001
From: marqdevx
Date: Fri, 19 Aug 2022 12:04:14 +0200
Subject: [PATCH 03/11] Add blink function
---
.../tutorials/camera-to-bitmap-sd-card/content.md | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
index 8e350a7148..3d2fe62245 100644
--- a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
+++ b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
@@ -224,6 +224,17 @@ void saveImage(unsigned char *imageData, const char* imagePath){
}
```
+Then to have visual feedback lets add a blink function to make 3 blinks after the photo is taken, once the blue LED is ON it means the picture was taken.
+```cpp
+void countDownBlink(){
+ for (int i = 0; i < 6; i++){
+ digitalWrite(LEDG, i % 2);
+ delay(500);
+ }
+ digitalWrite(LEDG, HIGH);
+ digitalWrite(LEDB, LOW);
+}
+```
Now that you have all the functions to be used, inside the `setup()` its call them only once after the board restarts.
```cpp
void setup(){
@@ -239,6 +250,7 @@ void setup(){
Serial.println("Unable to find the camera");
}
+ countDownBlink();
Serial.println("Fetching camera image...");
unsigned char *imageData = captureImage();
From b5486f35fa035ef74c653cebe4ded9e387236519 Mon Sep 17 00:00:00 2001
From: Sebastian Romero
Date: Fri, 19 Aug 2022 15:12:17 +0200
Subject: [PATCH 04/11] Update
content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
---
.../tutorials/camera-to-bitmap-sd-card/content.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
index 3d2fe62245..00d6e42b69 100644
--- a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
+++ b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
@@ -49,7 +49,7 @@ You will be using the **Himax HM-01B0 camera module** which has a resolution of
Inside the sketch, you can use these libraries to access the camera APIs, also compatible with the [Arduino Nicla Vision](hardware/nicla-vision)
```cpp
#include "camera.h" // Multi Media Card APIs
-#include "himax.h" // Mbed API for portable and embedded systems
+#include "himax.h" // API to read from the Himax camera found on the Portenta Vision Shield
```
#### Bitmap File Format
From d0f81876596a57a8a77c7c38ce51acc4bf05da74 Mon Sep 17 00:00:00 2001
From: Sebastian Romero
Date: Fri, 19 Aug 2022 15:12:22 +0200
Subject: [PATCH 05/11] Update
content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
---
.../tutorials/camera-to-bitmap-sd-card/content.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
index 00d6e42b69..44873427ce 100644
--- a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
+++ b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
@@ -87,7 +87,7 @@ Then we define the following objects with their respective constructor (`blockDe
```cpp
#include "SDMMCBlockDevice.h" // Multi Media Card APIs
-#include "FATFileSystem.h" // Mbed API for portable and embedded systems
+#include "FATFileSystem.h" // API to run operations on a FAT file system
SDMMCBlockDevice blockDevice;
mbed::FATFileSystem fileSystem("fs");
From 37c7bda4fa17b0ef8c601c1551d77326784c1e53 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Marqu=C3=ADnez=20Ferr=C3=A1ndiz?=
Date: Fri, 19 Aug 2022 15:52:27 +0200
Subject: [PATCH 06/11] Update
content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
Co-authored-by: Sebastian Romero
---
.../tutorials/camera-to-bitmap-sd-card/content.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
index 44873427ce..d6bcefe201 100644
--- a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
+++ b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
@@ -96,7 +96,7 @@ mbed::FATFileSystem fileSystem("fs");
HM01B0 himax;
Camera cam(himax);
-FrameBuffer frameBuffer; // Buffer to save the capture
+FrameBuffer frameBuffer; // Buffer to save the camera stream
```
For the bitmap headers binary file you will need some information like the resolution of the image, the bits per pixel and more; so you can define your settings as shown:
From 7f32d41a1b6e6c85de81c51ae291f522fab1ef99 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Marqu=C3=ADnez=20Ferr=C3=A1ndiz?=
Date: Fri, 19 Aug 2022 15:54:53 +0200
Subject: [PATCH 07/11] Update full sketch
---
.../tutorials/camera-to-bitmap-sd-card/content.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
index d6bcefe201..f568e1137d 100644
--- a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
+++ b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
@@ -283,7 +283,7 @@ Once the capture is saved, remove the SD Card and plug it into a computer/phone
```cpp
#include "SDMMCBlockDevice.h" // Multi Media Card APIs
-#include "FATFileSystem.h" // Mbed API for portable and embedded systems
+#include "FATFileSystem.h" // API to run operations on a FAT file system
SDMMCBlockDevice blockDevice;
mbed::FATFileSystem fileSystem("fs");
@@ -292,7 +292,7 @@ mbed::FATFileSystem fileSystem("fs");
HM01B0 himax;
Camera cam(himax);
-FrameBuffer frameBuffer; // Buffer to save the capture
+FrameBuffer frameBuffer; // Buffer to save the camera stream
// Settings for our setup
#define IMAGE_HEIGHT (unsigned int)240
From 3ccd21655323d99e598b409ec551b6605d93efa9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Marqu=C3=ADnez=20Ferr=C3=A1ndiz?=
Date: Fri, 19 Aug 2022 15:56:45 +0200
Subject: [PATCH 08/11] Update full sketch
---
.../tutorials/camera-to-bitmap-sd-card/content.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
index f568e1137d..980488ed6d 100644
--- a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
+++ b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
@@ -80,7 +80,7 @@ First you need to include the needed libraries
#include "FATFileSystem.h" // Mbed API for portable and embedded systems
#include "camera.h" // Arduino Mbed Core Camera APIs
-#include "himax.h" // Exclusive Camera library for the Portenta Vision Shield
+#include "himax.h" // API to read from the Himax camera found on the Portenta Vision Shield
```
Then we define the following objects with their respective constructor (`blockDevice` and `fileSystem` objects), needed for getting access to the SD Card and the file system.
@@ -92,7 +92,7 @@ SDMMCBlockDevice blockDevice;
mbed::FATFileSystem fileSystem("fs");
#include "camera.h" // Arduino Mbed Core Camera APIs
-#include "himax.h" // Exclusive Camera library for the Portenta Vision Shield
+#include "himax.h" // API to read from the Himax camera found on the Portenta Vision Shield
HM01B0 himax;
Camera cam(himax);
@@ -288,7 +288,7 @@ SDMMCBlockDevice blockDevice;
mbed::FATFileSystem fileSystem("fs");
#include "camera.h" // Arduino Mbed Core Camera APIs
-#include "himax.h" // Exclusive Camera library for the Portenta Vision Shield
+#include "himax.h" // API to read from the Himax camera found on the Portenta Vision Shield
HM01B0 himax;
Camera cam(himax);
From d4cf34866c7114aa6f1e0e1fda8cff36d30b11c5 Mon Sep 17 00:00:00 2001
From: marqdevx
Date: Mon, 22 Aug 2022 14:22:19 +0200
Subject: [PATCH 09/11] First person plural removal
---
.../tutorials/camera-to-bitmap-sd-card/content.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
index 980488ed6d..5b0b93f507 100644
--- a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
+++ b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
@@ -56,7 +56,7 @@ Inside the sketch, you can use these libraries to access the camera APIs, also c
The bitmap binary file needs to contain some information in order to tell the computer for example the resolution of the picture and the bit-depth (bpp). Bit depth refers to the color information stored in the image. The higher the bit depth of an image, the more colors it can store. As the bit depth increases, the file size of the image also increases, because more color information has to be stored for each pixel in the image.
-The following table shows all the headers, the size of its buffer, offsets, the settings that we used with their details:
+The following table shows all the headers, the size of its buffer, offsets, the settings that are being used with their details:
| Name | Size | Details |
| ------------------- | ----------- | ------------------------------------------------------------ |
@@ -83,7 +83,7 @@ First you need to include the needed libraries
#include "himax.h" // API to read from the Himax camera found on the Portenta Vision Shield
```
-Then we define the following objects with their respective constructor (`blockDevice` and `fileSystem` objects), needed for getting access to the SD Card and the file system.
+Then define the following objects with their respective constructor (`blockDevice` and `fileSystem` objects), needed for getting access to the SD Card and the file system.
```cpp
#include "SDMMCBlockDevice.h" // Multi Media Card APIs
@@ -181,7 +181,7 @@ void setFileHeaders(unsigned char *bitmapFileHeader, unsigned char *bitmapDIBHea
***Take a look at the section [Bitmap File Format](#bitmap-file-format) to better understand the file headers that are created with this function***
-In this case that our image (320x240) is 8bits per pixel and grayscale on the bitmap rules we need to define the color table (color map) to assign an specific RGB color for our 8 bit color.
+In this case that our image (320x240) is 8bits per pixel and grayscale on the bitmap rules you need to define the color table (color map) to assign an specific RGB color for our 8 bit color.
On the following function it sets the color map as a grayscale of RGB colors from [R:0x00 G:0x00 B:0x00] to [R:0xFF G:0xFF B:0xFF]
```cpp
void setColorMap(unsigned char *colorMap){
From f682e46a6882391b0f62b9bcdd4fd55e4e44ba7a Mon Sep 17 00:00:00 2001
From: marqdevx
Date: Tue, 23 Aug 2022 10:11:13 +0200
Subject: [PATCH 10/11] Update full sketch
---
.../tutorials/camera-to-bitmap-sd-card/content.md | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
index 5b0b93f507..c53d96a233 100644
--- a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
+++ b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
@@ -321,9 +321,10 @@ void setup(){
if (!cam.begin(CAMERA_R320x240, IMAGE_MODE, 30)){
Serial.println("Unable to find the camera");
}
-
+ countDownBlink();
Serial.println("Fetching camera image...");
unsigned char *imageData = captureImage();
+ digitalWrite(LEDB, HIGH);
Serial.println("Saving image to SD card...");
saveImage(imageData, IMAGE_PATH);
@@ -416,6 +417,15 @@ void saveImage(unsigned char *imageData, const char* imagePath){
// Close the file stream
fclose(file);
}
+
+void countDownBlink(){
+ for (int i = 0; i < 6; i++){
+ digitalWrite(LEDG, i % 2);
+ delay(500);
+ }
+ digitalWrite(LEDG, HIGH);
+ digitalWrite(LEDB, LOW);
+}
```
## Conclusion
From ad6bc888b879ab2e94027b2e26545c46d6fc09ed Mon Sep 17 00:00:00 2001
From: marqdevx
Date: Tue, 23 Aug 2022 10:17:33 +0200
Subject: [PATCH 11/11] Change title and fix typo
---
.../tutorials/camera-to-bitmap-sd-card/content.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
index c53d96a233..d86efc3286 100644
--- a/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
+++ b/content/hardware/04.pro/shields/portenta-vision-shield/tutorials/camera-to-bitmap-sd-card/content.md
@@ -1,5 +1,5 @@
---
-title: "Saving Images as Bitmaps Into the SD Card"
+title: "Saving Bitmap Camera Images to the SD Card"
difficulty: easy
tags: [Camera, Bitmap, SD Card]
description: This tutorial shows you how to capture a frame from the Portenta Vision Shield Camera module and save the output as a bitmap image.
@@ -18,7 +18,7 @@ software:
---
## Overview
-This tutorial shows you how to capture a frame from the Portenta Vision Shield Camera module and save the output as a bitmap image. It will allow you to see the output directly on your computer without using any third party tool.
+This tutorial shows you how to capture a frame from the Portenta Vision Shield Camera module and save the output as a bitmap image. It will allow you to see the output directly on your computer without using any third party tool.
## Goals
@@ -181,7 +181,7 @@ void setFileHeaders(unsigned char *bitmapFileHeader, unsigned char *bitmapDIBHea
***Take a look at the section [Bitmap File Format](#bitmap-file-format) to better understand the file headers that are created with this function***
-In this case that our image (320x240) is 8bits per pixel and grayscale on the bitmap rules you need to define the color table (color map) to assign an specific RGB color for our 8 bit color.
+In this case that our image (320x240) is 8 bits per pixel and grayscale on the bitmap rules you need to define the color table (color map) to assign an specific RGB color for our 8 bit color.
On the following function it sets the color map as a grayscale of RGB colors from [R:0x00 G:0x00 B:0x00] to [R:0xFF G:0xFF B:0xFF]
```cpp
void setColorMap(unsigned char *colorMap){