element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Summer of FPGA
  • Challenges & Projects
  • Design Challenges
  • Summer of FPGA
  • More
  • Cancel
Summer of FPGA
Blog Security Camera #5: Adding Peripheral Sensors
  • Blog
  • Forum
  • Documents
  • Files
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: angelo76
  • Date Created: 30 Jan 2022 3:44 AM Date Created
  • Views 1857 views
  • Likes 9 likes
  • Comments 0 comments
  • Security Camera
  • fpga
  • summer of fpga
  • cmod s7
Related
Recommended

Security Camera #5: Adding Peripheral Sensors

angelo76
angelo76
30 Jan 2022

Blog 5: Adding Peripheral Sensors

We successfully connected the OV7670 camera to the SD card driver for storage of images. Now its time to make our camera smarter by adding sensors! The goal of this fifth blog is to interface sensors in our Security Camera.

Sensors make machines smarter. Machines become "smarter" when it has data to process and this data mostly comes from sensors. It "sense" the world and encode that data into binary which can be understood by any digital system. In fact, we had already used a sensor in my previous blog: the OV7670 camera. It converts the light information into pixel data of 16 bits. However, enough of the OV7670. Let us now talk of other kinds of sensors that we will add to our Security Camera.

PIR Sensor

I'm sure many of you had already used this sensor for your theft detection projects. If you had not yet play with this thing, this is your time. A passive infrared sensor (PIR sensor) is an electronic sensor that measures infrared (IR) light radiating from objects in its field of view. PIR sensors use a pair of pyroelectric sensors to detect heat energy in the surrounding environment. The PIR sensor I bought is the very common HC-SR501. It only has three pins and some trimmers for sensitivity:

image

When PIR sensor detects movement or heat energy, the digital OUT will go high.

Sound Sensor

As the name itself, it detects sound. The sound sensor has a thin piece of material called a diaphragm that vibrates when hit by sound waves which is akin to how our eardrum vibrates when hearing sound. This diaphragm alerts the system when a significant sound vibration is felt. The sound sensor I bought is similar to this:

image

When the sensor detects sound past its set threshold(can be adjusted by the trimmers), the digital OUT will go low (active low).

Temperature Sensor

Now for the tricky part, we will also interface with a temperature sensor. The output of a temperature sensor is analog.I used the all very common LM35 temperature sensor:

image

As you can see on the pin 2 description, Analog Out is 10mV/Celsius. It means that analog output voltage will increase by 10mV every time the temperature increase by 1 Celsius. For example. if the temperature is 30 Celsius, you will have an analog output voltage of 300mV (30Celsius*10mV/Celsius). Enough of how it works, the question is how can a digital device like the FPGA interface with an analog device like this temperature sensor? The answer is that we use Analog to Digital Converters (ADC).

XADC in CMOD S7

Fortunately, the Spartan 7 FPGA chip in the CMOD S7 has an analog to digital converter and is called XADC. The inputs for this XADC is multiplexed between the external and internal analog inputs. The internal analog input can be the internal temperature sensor of the chip. If you had tried programming the bitstream to the FPGA, you will likely see the XADC System Monitor which displays the current temperature of the chip. We can use this internal temperature sensor for this project but I decided not to since for the demonstration I will be using a real fire(from a lighter only) and I do not want to keep that near to the main chip of the FPGA. Thus, we will be using the external analog input.

The XADC interface is this:

module xadc_interface( //reads ADC output and store to register
    input wire clk, rst,
    input wire vaux5_p, vaux5_n, //pin 32 
    input wire vaux12_p, vaux12_n,
    output reg[11:0] adc_0,adc_1,adc_2 //ADC CODE: adc_0(die temp) , adc_1(pin 32) , adc_2(pin33)
    );
    
    wire [4 : 0] channel_out;
    wire eoc_out;
    wire drdy_out;
    wire [15 : 0] do_out;
    //reg[11:0] adc_0,adc_1,adc_2; //ADC CODE: adc_0(die temp) , adc_1(pin 32) , adc_2(pin33)
    
   
    //register operation
    always @(posedge clk,posedge rst) begin
        if(rst) begin
            adc_0<=0;
            adc_1<=0;
            adc_2<=0;
        end
        else if(drdy_out)begin //read operation successful and data is now available at do_out
            if(channel_out==5'h00) adc_0<=do_out[15:4]; //die temp sensor (info at datasheet)
            if(channel_out==5'h15) adc_1<=do_out[15:4]; //pin 32  (info at datasheet)
            if(channel_out==5'h1c) adc_2<=do_out[15:4]; //pin 35  (info at datasheet)
        end 
    end

    
    //XADC IP instantiation
    xadc_wiz_0 m0 (
      .di_in(),              // no write operation is needed
      .daddr_in({2'b00,channel_out}), // instantly read the channel(5bits) after conversion (daddr_in is 7bits)
      .den_in(eoc_out),            // start read operation at end-of-conversion
      .dwe_in(1'b0),            // always do read operation
      .drdy_out(drdy_out),        // ticks when do_out is available for reading
      .do_out(do_out),            // 12MSB is the ADC code (0-to-4095)
      .dclk_in(clk),          // input clk (12MHz for CMOD-S7)
      .reset_in(rst),        // input wire reset_in
      .vp_in(vp_in),              // NOT USED 
      .vn_in(vn_in),              // NOT USED
      .vauxp5(vaux5_p),            // pin 32
      .vauxn5(vaux5_n),            // grounded for unipolar input
      .vauxp12(vaux12_p),          // pin 33
      .vauxn12(vaux12_n),          // grounded for unipolar input
      .channel_out(channel_out),  // channel converted by eoc_out
      .eoc_out(eoc_out),          // end-of-conversion 
      .alarm_out(alarm_out),      // NOUT USED
      .eos_out(eos_out),          // NOT USED
      .busy_out(busy_out)        // NOT USED
);

   
endmodule

Note that this code is just an interface to the main IP used in XADC. So make sure you first instantiate the XADC IP. You can use the IP instantiation template added on my code to get an idea on what parameters you will use for instantiating the XADC IP. The possible inputs for this interface are the analog external input pins (pin 32 and 33) and the internal temperature sensor. I want to make the XADC interface as general as possible so that I can re-use this code in my future projects.

Connecting the Sensors to the Camera

Now that all three sensors are ready, how can we add it to the camera interface we did last time? The snippet of code to make the sensors work is this (this is already included in the camera driver code on blog 4),

rest: if(key_tick || pir_sensor || !sound_sensor || temp_sensor) begin
     lines_d=0;
     state_d=vsync_fedge;
 end

The logic is simple, the camera will start saving data to SD card if key_tick is pressed(de-bounced output of btn1) OR PIR sensor is high OR sound sensor is low(active-low) OR temperature sensor is active (reached the threshold). Very simple logic but will definitely make the Security Camera smarter.

Before we Proceed to the Final Blog

Did you remember on my third blog, when we tried storing ASCII letters to the SD card to test if the driver code is working. I did not implemented a file system that is why the computer was not able to view the real binary data we saved to it. We instead used the dd command to extract the data from sectors of the SD card.

That means when the camera sends pixel data to the SD card, we will not also be able to view the image normally when we open the directory of the SD card. That is pretty bad. Why store it to SD card if we cannot access it? The thing we can do is to use the dd command again to extract all sectors with the data of the image: sudo dd bs=512 count=1200 skip=2050 if=/dev/sdd of=sdcard.bin

Take note of the value of 1200 for count , this is not just some magic number. 1200 counts of 512 bytes is in fact the size of a whole frame:

1200 counts * 512 bytes/count = 614400 bytes

2 bytes/pixel  *  640 pixels/line * 480 lines/frame= 614400 bytes/frame

And there you go, so if you want to retrieved 1 frame from your SD card use count=1200. Obviously, if you would want to retrieve 10 frames, the count should be 1200*10=12000. Let me remind again that skip=2050 is just the number of counts or 512 bytes skipped before retrieving the data. It is set to 2050 since that is what I set at the SD card driver (2050 seems to be always a safe sector). After extracting data from sectors of the SD card, the binary output must then be converted to an image. That might seem tedious so I made an MATLAB script for that,

function f = ov7670(MAX_IMAGES)
fid=fopen('sdcard.bin');
file=fread(fid);
k=1;
rgb_index=1;
while k<=(614400*MAX_IMAGES)
  pixel=file(k)*2^8 + file(k+1);
  k=k+2;
  r(rgb_index)=uint8((bitand(pixel,63488)/2^11)*2^3);
  g(rgb_index)=uint8((bitand(pixel,2016)/2^5)*2^2);
  b(rgb_index)=uint8((bitand(pixel,31))*2^3);
  rgb_index=rgb_index+1;
end

rgb_index=1;
foldername='OV7670_images';
mkdir(foldername);
for img_saved=1:MAX_IMAGES
  for width=1:480
      for length=1:640
         img(width,length,1)=r(rgb_index);
         img(width,length,2)=g(rgb_index);
         img(width,length,3)=b(rgb_index);
         rgb_index=rgb_index+1;
      endfor
  endfor
  imshow(img)
  num=num2str(img_saved);
  filename=strcat(foldername,'/','img',num,'.bmp')
  imwrite(img,filename);
endfor

end

This can run on Octave so you might opt for that since Octave is free and lighter compared to MATLAB. What this code do is simple, it reads the sdcard.bin that were extracted when we used the dd command. It will extract the red, green, and blue pixels by bit manipulation (magic numbers 63488, 2016, 31). This red, green, and blue pixels will be combined to make the original 640x480 image. To use this code just type ov7670(arg) on the command line. The arg is a number that pertains to how many frames you want to retrieve. Keep the number low(less than 10) since it will take a lot of time to process each of those images.

Preview for Next Blog

Now that everything is ready, we can now proceed to my final blog. Next stop: project demonstration and some final words.

6-Part Blog Series

  • Security Camera #1: Project Proposal
  • Security Camera #2: SD Card Interfacing
  • Security Camera #3: Testing the SD Card Driver
  • Security Camera #4: Interfacing with OV7670 Camera
  • Security Camera #5: Adding Peripheral Sensors
  • Security Camera #6: Project Demonstration and Final Words

To see more of my FPGA projects, visit my GitHub account: https://github.com/AngeloJacobo

References:

https://en.wikipedia.org/wiki/Passive_infrared_sensor

https://www.componentsinfo.com/hc-sr501-module-pinout-datasheet/

https://www.engineersgarage.com/lm35-description-and-working-principal/

  • Sign in to reply
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube