TL;DR — Build a stand-alone, mobile, motion-capture apparatus for your vehicle or other remote location! Copy and paste the code at the end of this project into an Arduino Sketch, collect the associated components, adjust the sensitivity to your preference, and you're ready to catch any bad actors before they fly away!
Please use responsibly.
BackstoryA convertible with a panoramic sunroof! The ideal target for engorged avians, jealous vandals, and that one neighbor kid.
Thankfully only the victim of bird droppings so far, my precious vehicle has spent a lot of time outdoors in the parking lots of various grocery stores, theaters, etc., always at the mercy of its surroundings — The anxiety of such impending mishap was impeding my work, my errands, and generally ruining my movie-going experience.
Cars are designed for utility, fun, and beauty — not to be vandalized, struck by a shopping cart, or stained by pigeons — that’s why I created the Secured by SONY Vehicle Security System (VSS) using the SONY Spresense!
https://www.hackster.io/contests/sony/hardware_applications/9703
How-ToStep 1: Obtain a SONY Spresense Board and Other Components.
Incredibly fortunate, I happened upon my SONY Spresense by participating in the Make it Better with SONY Hackster.io Contest. If you’re not already a Hackster.io member, please sign up to today and keep an eye out for interesting projects and contests like this one in the future!
If you’re ready to equip, follow the links in the parts list above.
Step 2: Follow SONY's guide to install the Spresense Arduino IDE
SONY have done an excellent job of preparing the Spresense for Arduino compatibility. Having never used an Arduino system before, this was an easy process to complete and might be the only time-consuming task ahead of you!
Step 3: Download the SecuredBySONY_0.7.ino Sketch from this article.
Open the file in your Arduino installation, connect your SONY Spresense by USB and Upload the sketch.
Review the Sketch and notice the variable, “motion_tolerance.” Adjust this higher to make the camera less sensitive to motion; lower for greater sensitivity.
// Tolerance for Motion Detection
float motion_tolerance = 0.50;
Step 4: Connect to a Power Supply to Secure your Property with SONY!
For this purpose, I made use of my computer as the power supply.
The board can accept power from either micro-USB port — or both!
Remember to use the micro-USB port on the Main Board to upload code.
Example Installation — Video!After writing the Secured By SONY Sketch, I tried it out in my car!
In this video, I arm the Secured by SONY VSS just to see what it will detect!
The Secured By SONY Spresense Vehicle Security System was successful in detecting nearby vandals and correctly ignoring passing vehicles!
The egg-thing was very sticky; I kept out the rest of the bad throws. ¯\_(ツ)_/¯
Ideally, the VSS would detect the egg or droppings alone without my background presense, but keeping the visor open let in too much daylight and the view through the windscreen was washed out.
Making "Secured By SONY"This was my first time programming — anything!
And it really was quite a bit of fun and very interesting to learn. Please, if you’re interested in learning to program at all, the SONY Spresense is a great way to get started.
SONY have provided many examples to learn from; here’s how they helped me.
Referring back to my original challenge for the project, my goal for a Vehicle Security System (VSS) is one that surveils, alarms, and alerts. With this goal in mind I reviewed each of the different examples related to these topics.
SONY's camera.ino is the example I most heavily incorporated into my project.
/*
* camera.ino - One minute interval time-lapse Camera
* Copyright 2018 Sony Semiconductor Solutions Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* This is a test app for the camera library.
* This library can only be used on the Spresense with the FCBGA chip package.
*/
#include <SDHCI.h>
#include <stdio.h> /* for sprintf */
#include <Camera.h>
#define BAUDRATE (115200)
SDClass theSD;
int take_picture_count = 0;
/**
* Callback from Camera library when video frame is captured.
*/
void CamCB(CamImage img)
{
/* Check the img instance is available or not. */
if (img.isAvailable())
{
/* If you want RGB565 data, convert image data format to RGB565 */
img.convertPixFormat(CAM_IMAGE_PIX_FMT_RGB565);
/* You can use image data directly by using getImgSize() and getImgBuff().
* for displaying image to a display, etc. */
Serial.print("Image data size = ");
Serial.print(img.getImgSize(), DEC);
Serial.print(" , ");
Serial.print("buff addr = ");
Serial.print((unsigned long)img.getImgBuff(), HEX);
Serial.println("");
}
else
{
Serial.print("Failed to get video stream image\n");
}
}
/**
* @brief Initialize camera
*/
void setup()
{
/* Open serial communications and wait for port to open */
Serial.begin(BAUDRATE);
while (!Serial)
{
; /* wait for serial port to connect. Needed for native USB port only */
}
/* begin() without parameters means that
* number of buffers = 1, 30FPS, QVGA, YUV 4:2:2 format */
Serial.println("Prepare camera");
theCamera.begin();
/* Start video stream.
* If received video stream data from camera device,
* camera library call CamCB.
*/
Serial.println("Start streaming");
theCamera.startStreaming(true, CamCB);
/* Auto white balance configuration */
Serial.println("Set Auto white balance parameter");
theCamera.setAutoWhiteBalanceMode(CAM_WHITE_BALANCE_DAYLIGHT);
/* Set parameters about still picture.
* In the following case, QUADVGA and JPEG.
*/
Serial.println("Start streaming");
theCamera.setStillPictureImageFormat(
CAM_IMGSIZE_QUADVGA_H,
CAM_IMGSIZE_QUADVGA_V,
CAM_IMAGE_PIX_FMT_JPG);
}
/**
* @brief Take picture with format JPEG per second
*/
void loop()
{
sleep(1); /* wait for one second to take still picture. */
/* You can change the format of still picture at here also, if you want. */
/* theCamera.setStillPictureImageFormat(
* CAM_IMGSIZE_HD_H,
* CAM_IMGSIZE_HD_V,
* CAM_IMAGE_PIX_FMT_JPG);
*/
/* This sample code can take 100 pictures in every one second from starting. */
if (take_picture_count < 100)
{
/* Take still picture.
* Unlike video stream(startStreaming) , this API wait to receive image data
* from camera device.
*/
Serial.println("call takePicture()");
CamImage img = theCamera.takePicture();
/* Check availability of the img instance. */
/* If any error was occured, the img is not available. */
if (img.isAvailable())
{
/* Create file name */
char filename[16] = {0};
sprintf(filename, "PICT%03d.JPG", take_picture_count);
Serial.print("Save taken picture as ");
Serial.print(filename);
Serial.println("");
/* Save to SD card as the finename */
File myFile = theSD.open(filename, FILE_WRITE);
myFile.write(img.getImgBuff(), img.getImgSize());
myFile.close();
}
take_picture_count++;
}
}
This sketch creates a stop-motion camera. Upload this script to take 100 images in sequence. I adjusted this sketch in several ways to accommodate my motion-sensing algorithm.
Without using an electronic motion detector, I tried to program an equation based on the percent difference between two images shot immediately following each other.
// If this is the first image captured, record its size in image0_size.
if (image_count == 0) {
image0_size = img.getImgSize();
Serial.print("First Image Size is ");
Serial.print(img.getImgSize());
Serial.print(". ");
Serial.print("Recorded Image 1. Image Count = ");
Serial.print(image_count);
Serial.println(". ");
}
// If this is the second image captured, record its size in image1_size.
if (image_count == 1) {
image1_size = img.getImgSize();
Serial.print("Second Image Size is ");
Serial.print(img.getImgSize());
Serial.print(". ");
Serial.print("Recorded Image 2. Image Count = ");
Serial.print(image_count);
Serial.println(". ");
}
}
image_count++;
Serial.print("Finished Image Collection. Image Count = ");
Serial.print(image_count);
Serial.println(". ");
}
// If the two still photos are different, find percent difference.
// If percent difference exceeds tolerance, Instigate Motion Capture.
// Else, take two more photos (Main Loop Repetition).
if (image0_size != image1_size) {
// Find the larger of the two images to keep Percent Difference Positive.
if (image0_size > image1_size) {
image_diff = (image0_size - image1_size);
Serial.print("The two images are different by ");
Serial.print(image_diff);
Serial.println(" bytes.");
// Calculate Percent Difference.
image_perdiff = (image_diff / image0_size);
image_perdiff *= 100;
Serial.print("The two images are different by ");
Serial.print(image_perdiff);
Serial.println(" percent.");
}
if (image1_size > image0_size) {
image_diff = (image1_size - image0_size);
Serial.print("The two images are different by ");
Serial.print(image_diff);
Serial.println(" bytes.");
// Calculate Percent Difference.
image_perdiff = (image_diff / image1_size);
image_perdiff *= 100;
Serial.print("The two images are different by ");
Serial.print(image_perdiff);
Serial.println(" percent.");
}
// Now, Knowing Percent Difference, Compare to Motion Tolerance.
// Print out the current Motion Tolerance.
Serial.print("The current Motion Tolerance is ");
Serial.print(motion_tolerance);
Serial.println(" percent.");
// If the Percent Difference is greater than the motion tolerance,
// Instigate Surveillance.
if (image_perdiff >= motion_tolerance) {
// Record Cycle Count of Incident; Step back prior incidents.
// Incident-Count Relationship records in which cycle an incident occurred.
// Tracking past incidents for potential calibration mechanism.
incident_before_last = last_incident;
last_incident = this_incident;
this_incident = cycle_count;
incident_count = incident_before_last + last_incident + this_incident;
Serial.print("This incident belongs to cycle number ");
Serial.print(this_incident);
Serial.println(".");
This version worked fairly well, apart from the program sometimes failing to write the entire picture to disk. On many of my trial runs, the images captured were missing data for 50-90% of the image. At first I thought this was due to the camera shutter speed; however, I found that adjusting the camera settings did not improve the outcome.
//Prepare Camera for Photography; Initialization Requied.
Serial.println("Preparing Camera.");
theCamera.begin();
Somehow, this worked itself out; I believe by my relocating the photo capture function outside of the percent difference test function.
// If instigated, begin surveillance.
// Because 0 = 0, Surveillance will always run the first Cycle, Cycle 0.
if (this_incident == cycle_count) {
// Begin Capturing Photographs — EVIDENCE!
while (motion < next_motion) {
Serial.print("Motion Count = ");
Serial.print(motion);
Serial.println(". ");
// The following section based on camera.ino by SONY.
Serial.println("Save current image to file.");
CamImage img = theCamera.takePicture();
char filename[16] = {0};
sprintf(filename, "MOTION%03d.JPG", motion);
Serial.print("Save taken picture as ");
Serial.print(filename);
Serial.println("");
/* Save to SD card as the finename */
File myFile = theSD.open(filename, FILE_WRITE);
myFile.write(img.getImgBuff(), img.getImgSize());
myFile.close();
// End camera.ino excerpt.
motion++;
// Close While for Motion Capture.
}
Despite reviewing each of SONY's example sketches (Especially camera.ino, beep.ino, player.ino, and gnss.ino) and many attempts, I was unable to incorporate additional portions of the above sketches into "Secured By SONY."
#include <SDHCI.h>
#include <stdio.h>
#include <Camera.h>
I failed to find the right sequence that would allow all functions to operate within the same program. Even simply adding "#include <audio.h>" to the header would prevent the program from running the percent difference comparison. I believe this came about because the program either ran out of local variable space following the audio initialization or my variables escaped their own scope.
During trial runs, the Serial Monitor would indicate the program failed to capture images from the camera after the first pass through the main loop.
This prevented the inclusion of beep.ino, player.ino, or gnss.ino and therefore waylaid alarming and alerting as current features of the vehicle security system.
ConclusionsThis project has taught me a lot.
Starting from nothing and piecemealing this project together from example sketches and the Arduino Reference was an incredibly creative experience.
My projected benefitted greatly from the experiences provided by the examples on the SONY, Hackster.io, and Arduino platforms. Hopefully, this project, which took me over 100 hours to create brings you a similar leap forward!
As I continue to develop this project, my intention is to learn how to control memory resources better in order to make the system function with all features the controller is capable of — including the addition of cellular reporting when hardware enabled (Requiring additional components).
Perhaps this is capable in C with the Arduino SDK, if the community could point me in the right direction, that would be amazing; else, it may be necessary to program closer to the Nuttx operating system embedded in the SONY Spresense.
Next StepsOnce I am able to further my programming skills and I have determined how to manipulate the memory/storage allocation within my sketch, I would like to complete the creative vision set out in my backstory — a Vehicle Security System that not only reports on potential hazards, but also sets off a deterrent alarm (such as a high-pitched noise of some sort to keep away birds, as seen in beep.ino), and alerts me in real time to activity nearby the vehicle.
Thanks!Thank you so much to SONY and Hackster.io for presenting this competition; without this opportunity, I may never have been compelled to learn to code as much as I have and so inspired to continue learning — Thank you!
Thank you for reading!
Comments