BeeLab: Raspberry Pi
Showing posts with label Raspberry Pi. Show all posts
Showing posts with label Raspberry Pi. Show all posts

Tuesday, January 15, 2019

[Raspberry Pi] Cảnh báo trộm bằng RasPi | Raspberry Pi Motion Detector with Photo Capture

8:18:00 AM
[Raspberry Pi] Cảnh báo trộm bằng RasPi | Raspberry Pi Motion Detector with Photo Capture
This project shows how to take photos with a Raspberry Pi when motion is detected. It can be used as a burglar detector, to take wildlife photos or in other applications. We’ll be using a Raspberry Pi V2 camera and the code will be written in Python programming language.
Prerequisites
Project Overview
The circuit for this project consists of a PIR motion sensor, a pushbutton, and a camera module you’ll connect to your Pi. The pushbutton is an extra component that allows you to stop the Python script.
To program the Raspberry Pi we’ll be using a Python script and the built-in picameralibrary, which makes it very simple to control the camera. To control the GPIOs we’ll be using the gpiozero library that contains classes for most popular components like pushbuttons, LEDs, motion sensor, etc.

Enable the Camera

You need to enable your Raspberry Pi’s camera software before you can use the camera module. In the desktop environment, go to the main menu and select Preferences > Raspberry Pi Configuration. Select the Interfaces tab and a window as shown below should open.
Alternatively, in the Terminal window, type the following command:
pi@raspberry:~ $ sudo raspi-config
You should see the Raspberry Pi software configuration tool. Select the Interfacing Options:
Enable the camera and reboot your Pi:

Connect the Camera

With the camera software enabled, shut down your Pi and then connect the camera to the CSI port. Make sure the camera is connected with the blue letters facing up and oriented as shown in the following figure. Then start up your Pi again.

Build the Circuit

With the camera connected, follow the next schematic diagram to wire the rest of the circuit.
  • Pushbutton: GPIO 2
  • PIR motion sensor: GPIO 4
Note: the PIR motion sensor we’re using in this project should be powered using the 5V pin. Other sensors required 3.3V to operate. Read your sensor’s specifications before wiring the circuit.

Writing the Script

To control the camera, you’ll use the built-in picamera library. Here’s an overview of what the code should do:
  1. Initialize the camera.
  2. Take a photo when the PIR motion sensor detects movement.
  3. Save the photos in your Desktop folder.
  4. Name the photos incrementally so you know what order they were taken in—for example, image_1.jpg, image_2.jpg, and so on.
  5. Stop the camera when the pushbutton is pressed. If you don’t include this feature, you won’t be able to exit the camera preview that pops up on your screen.

Entering the script

Create a new file using Python 3 (IDLE) and copy the following code. Then, save the code in the Desktop folder with the following name: burglar_detector.py.
#Project 13 - Burglar Detector With Photo Capture
#latest code updates available at: https://github.com/RuiSantosdotme/RaspberryPiProject
#project updates at: https://nostarch.com/RaspberryPiProject
#import the necessary packages
from gpiozero import Button, MotionSensor
from picamera import PiCamera
from time import sleepfrom signal import pause
#create objects that refer to a button,
#a motion sensor and the PiCamera
button = Button(2)
pir = MotionSensor(4)
camera = PiCamera()
#start the camera
camera.rotation = 180
camera.start_preview()
#image image names
i = 0
#stop the camera when the pushbutton is pressed
def stop_camera():
    camera.stop_preview()
    #exit the program
    exit()
#take photo when motion is detected
def take_photo():
    global i
    i = i + 1
    camera.capture('/home/pi/Desktop/image_%s.jpg' % i)
    print('A photo has been taken')
    sleep(10)
#assign a function that runs when the button is pressed
button.when_pressed = stop_camera#assign a function that runs when motion is detected
pir.when_motion = take_photo

pause()

How the code works

First you import the necessary libraries; as we’ve said, the program uses the picameralibrary to control the camera. The gpiozero library contains classes to control the pushbutton and the motion sensor: Button and MotionSensor. The sleep method allows us to deal with delays, and the pause method is used to handle interrupts.
from gpiozero import Button, MotionSensor
from picamera import PiCamera
from time import sleep
from signal import pause
Then, you create objects to refer to the pushbutton, the PIR motion sensor, and the camera. The pushbutton is on GPIO 2 and the motion sensor on GPIO 4.
button = Button(2)
pir = MotionSensor(4)
camera = PiCamera()
Then, initialize the camera with camera.start_preview().
camera.start_preview()
Depending on how your camera is oriented, you might also need to rotate it 180 degrees so that it doesn’t take the photos upside down.
camera.rotation = 180
Next, you initialize an i variable that starts at 0.
i = 0
Then, we create the stop_camera() and the take_photo() functions that will be called later in the code.
The take_photo() function, will use the i variable to count and number the images, incrementing the number in the filename by one with each picture taken.
def take_photo():
  global i
  i = i + 1
  camera.capture('/home/pi/Desktop/image_%s.jpg' % i)
  print('A photo has been taken')
  sleep(10)
To take and save a photo you use the camera.capture() method, specifying the directory you want to save the image to inside the parentheses. In this case, we’re saving the images in the Desktop folder and naming the images image_%s.jpg, where %s is replaced with the number we incremented earlier in i.
If you want to save your files to a different folder, replace this directory with the path to your chosen folder. You then impose a 10-second delay, meaning the camera takes photos at 10-second intervals for as long as the PIR sensor detects movement. Feel free to increase or decrease the delay time, but be careful to not overload the Pi with tons of images by making the delay time too small.
The stop_camera() function stops the camera with the camera.stop_preview() method.
def stop_camera():
  camera.stop_preview()
  #exit the program
  exit()
This function stops the camera preview and exits the program. The exit() function pops up a window asking if you want to close the program; to close it, just click OK.
Finally, you define that when the pushbutton is pressed, the cameras stops.
button.when_pressed = stop_camera
Finally, you tell the camera to take a photo by triggering the take_photo() function when motion is detected.
pir.when_motion = take_photo
The pause() at the end of the code keeps your program running so that interrupts can be detected.

Demonstration

If your’re using Python IDLE to write your code, press F5 or go to Run > Run Module to run the script. While the script is running, you should see a preview of what the camera sees on your screen. To shut down the camera preview, press the pushbutton and click OK in the window that pops up.
Alternatively, in the Terminal window you can type:
pi@raspberrypi:~ $ python3 burglar_detector.py
Congratulations, you project is ready to detect motion and take some photos. You can place this project in a strategic place and come back later to check any saved photos. The following figure shows a photo taken by this project.

Wrapping Up

Using cameras with the Raspberry Pi is an easy task and can be applied to a wide variety of projects. The picamera and gpiozero libraries give you an easy way to control the camera and GPIOs with the Raspberry Pi.
Thank you for reading!
Follow randomnerdtutorials.com

Tuesday, August 15, 2017

[Raspberry Pi] - Bài 6: Lập trình và điều khiển Raspberry Pi không cần màng hình (Remove Desktop)

11:07:00 PM
[Raspberry Pi] - Bài 6: Lập trình và điều khiển Raspberry Pi không cần màng hình (Remove  Desktop)
Qua quá trình làm việc với Raspberry Pi, nhận thấy có 1 vấn đề khá lớn của bo mạch này đó là mặc dù chi phí rất rẻ, nhưng phụ kiện kèm theo không hề rẻ, đặc biệt là thiết bị hiển thị (hầu hết người mới lập trình sẽ muốn lập trình qua giao diện, do đó sẽ cần màn hình hiển thị).
  • Màn hình có HDMI thì có thể kết nối ngay với Rasp Pi bằng 1 dây HDMI, nhưng không phải ai cũng có màn hình, và chi phí rất cao.
  • Màn hình VGA có thể có sẵn và chi phí rẻ hơn, nhưng cũng sẽ phải mua thêm 1 bộ chuyển đổi HDMI-VGA vào khoảng 300k
Xin giới thiệu với các bạn 1 cách khác để lập trình Rasp Pi với giao diện Raspbian mà không cần màn hình, đó là sử dụng XRDP, một chương trình Remote Desktop. Không tốn chút chi phí nào.

Chuẩn bị:

Raspberry Pi khởi chạy vào chế độ đồ họa
Kết nối internet
Máy chạy win có trình remote desktop connection
Remote desktop connection: là chương trình dùng Remote Desktop Protocol cho phép kết nối đến một máy tính từ một máy tính khác, cụ thể ta có thể kết nối từ laptop đến Raspberry để đăng nhập vào và sử dụng Pi như một user với đầy đủ tính năng chuột, bàn phím, đồ họa.
Gói xrdp: Gói mã nguồn mở hỗ trợ Remote desktop protocol server.

Bước 1: Cài gói xrdp cho Pi

Mở terminal chạy lệnh:
Sudo apt-get update
Sudo apt-get install xrdp
Sau khi cài đặt xong, XRDP sẽ tự động chạy khi Raspberry Pi chạy trong chế độ giao diện
Ta có thể bật tắt XRDP bằng lệnh:
sudo service xrdp stop
sudo service xrdp restart

Bước 2:

Kiểm tra IP của Raspberry Pi
Lệnh:
ifconfig
Ở chuỗi inet addr:192.168.1.144 ta có địa chỉ IP của Pi.

Bước 3:

Kết nối Chương trình Remote desktop đến Pi
-Mở trình Remote desktop trên Window lên
-Điền vào IP của Pi ta đã lấy và nhấn connect
-Nhập usename và password để đăng nhập vào Pi như thường
Vậy là ta đã kết nối vào màn hình làm việc của Pi và có thể thao tác bình thường
Chúc các bạn thành công!

Monday, June 12, 2017

[Raspberry Pi] Bài 5: Cài đặt và lập trình giao tiếp IIC

11:04:00 PM
[Raspberry Pi] Bài 5: Cài đặt và lập trình giao tiếp IIC
Bài viết này hướng dẫn sử dụng I2C trên Rasp Pi, các cách cài đặt và lập trình giao tiếp I2C

Sơ đồ vị trí chân I2C trên GPIO của Raspberry Pi

1. Cài đặt cho phép sử dụng I2C.

  • Trước khi lập trình I2C trên Raspberry pi bạn cần thực hiện việc cài đặt để có thể sử dụng I2C.
  • Bạn cần Enable việc sử dụng I2C.
Gõ lệnh trên terminal:
sudo nano /etc/modprobe.d/raspi-blacklist.conf
Comment lại dòng “blacklist i2c-bcm2708” trong file raspi-blacklist.conf bằng việc đánh dấu # ở đầu dòng. Thì dòng đó sẽ như sau:
blacklist i2c-bcm2708
  • Sau khi thực hiện xong nhấn Ctrl + X để lưu và thực hiện reboot lại hệ thống.
 sudo reboot 
  • Sau khi reboot xong bạn vào terminal và chạy lệnh ở dưới để kích hoạt chân I2C hoạt động.
sudo modprobe i2c-dev 
  • Sau đó bạn list các cổng I2C có trên thư mục /dev/ của bạn:
ls /dev/i2c* 
  • Tiếp theo thực hiện việc chmod cho các người dùng khác nhau có thể truy nhập.
sudo chmod o+rw /dev/i2c* 
  • Cuối cùng bạn vào /etc/modules để thêm dòng “i2c-dev” vào cuối file và bạn đã có thể sử dụng i2c để phát triển.
sudo nano /etc/modules
Và bạn thêm:
i2c-dev 
  • Quá trình cài đặt sử dụng I2C đã hoàn tất bây giờ ta thực hiện việc lập trình.

2. Lập trình

#include <bcm2835.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define MODE_READ 0
#define MODE_WRITE 1
#define MAX_LEN 32
char wbuf[MAX_LEN];
typedef enum {
NO_ACTION,
I2C_BEGIN,
I2C_END
} i2c_init;
uint8_t init = NO_ACTION;
uint16_t clk_div = BCM2835_I2C_CLOCK_DIVIDER_148;
uint8_t slave_address = 0x00;
uint32_t len = 0;
uint8_t mode = MODE_READ;
//*******************************************************************************
// comparse: Parse the command line and return EXIT_SUCCESS or EXIT_FAILURE
// argc: number of command-line arguments
// argv: array of command-line argument strings
//*******************************************************************************
int comparse(int argc, char **argv) {
int argnum, i, xmitnum;
if (argc < 2) { // must have at least program name and len arguments
// or -ie (I2C_END) or -ib (I2C_BEGIN)
fprintf(stderr, "Insufficient command line arguments\n");
return EXIT_FAILURE;
}
argnum = 1;
while (argnum < argc && argv[argnum][0] == '-') {
switch (argv[argnum][1]) {
case 'i': // I2C init
switch (argv[argnum][2]) {
case 'b': init = I2C_BEGIN; break;
case 'e': init = I2C_END; break;
default:
fprintf(stderr, "%c is not a valid init option\n", argv[argnum][2]);
return EXIT_FAILURE;
}
break;
case 'd': // Read/Write Mode
switch (argv[argnum][2]) {
case 'r': mode = MODE_READ; break;
case 'w': mode = MODE_WRITE; break;
default:
fprintf(stderr, "%c is not a valid init option\n", argv[argnum][2]);
return EXIT_FAILURE;
}
break;
case 'c': // Clock divider
clk_div = atoi(argv[argnum]+2);
break;
case 's': // Slave address
slave_address = atoi(argv[argnum]+2);
break;
default:
fprintf(stderr, "%c is not a valid option\n", argv[argnum][1]);
return EXIT_FAILURE;
}
argnum++; // advance the argument number
}
// If command is used for I2C_END or I2C_BEGIN only
if (argnum == argc && init != NO_ACTION) // no further arguments are needed
return EXIT_SUCCESS;
// Get len
if (strspn(argv[argnum], "0123456789") != strlen(argv[argnum])) {
fprintf(stderr, "Invalid number of bytes specified\n");
return EXIT_FAILURE;
}
len = atoi(argv[argnum]);
if (len > MAX_LEN) {
fprintf(stderr, "Invalid number of bytes specified\n");
return EXIT_FAILURE;
}
argnum++; // advance the argument number
xmitnum = argc - argnum; // number of xmit bytes
memset(wbuf, 0, sizeof(wbuf));
for (i = 0; i < xmitnum; i++) {
if (strspn(argv[argnum + i], "0123456789abcdefABCDEFxX") != strlen(argv[argnum + i])) {
fprintf(stderr, "Invalid data: ");
fprintf(stderr, "%d \n", xmitnum);
return EXIT_FAILURE;
}
wbuf[i] = (char)strtoul(argv[argnum + i], NULL, 0);
}
return EXIT_SUCCESS;
}
//*******************************************************************************
// showusage: Print the usage statement and return errcode.
//*******************************************************************************
int showusage(int errcode) {
printf("i2c \n");
printf("Usage: \n");
printf("i2c [options] len [rcv/xmit bytes]\n");
printf("\n");
printf(" Invoking i2c results in an I2C transfer of a specified\n");
printf(" number of bytes. Additionally, it can be used to set the appropriate\n");
printf(" GPIO pins to their respective I2C configurations or return them\n");
printf(" to GPIO input configuration. Options include the I2C clock frequency,\n");
printf(" initialization option (i2c_begin and i2c_end). i2c must be invoked\n");
printf(" with root privileges.\n");
printf("\n");
printf(" The following are the options, which must be a single letter\n");
printf(" preceded by a '-' and followed by another character.\n");
printf(" -dx where x is 'w' for write and 'r' is for read.\n");
printf(" -ix where x is the I2C init option, b[egin] or e[nd]\n");
printf(" The begin option must be executed before any transfer can happen.\n");
printf(" It may be included with a transfer.\n");
printf(" The end option will return the I2C pins to GPIO inputs.\n");
printf(" It may be included with a transfer.\n");
printf(" -cx where x is the clock divider from 250MHz. Allowed values\n");
printf(" are 150 through 2500.\n");
printf(" Corresponding frequencies are specified in bcm2835.h.\n");
printf("\n");
printf(" len: The number of bytes to be transmitted or received.\n");
printf(" The maximum number of bytes allowed is %d\n", MAX_LEN);
printf("\n");
printf("\n");
printf("\n");
return errcode;
}
char buf[MAX_LEN];
int i;
uint8_t data;
int main(int argc, char **argv) {
printf("Running ... \n");
// parse the command line
if (comparse(argc, argv) == EXIT_FAILURE) return showusage (EXIT_FAILURE);
if (!bcm2835_init()) return 1;
// I2C begin if specified
if (init == I2C_BEGIN) bcm2835_i2c_begin();
// If len is 0, no need to continue, but do I2C end if specified
if (len == 0) {
if (init == I2C_END) bcm2835_i2c_end();
printf("... done!\n");
return EXIT_SUCCESS;
}
bcm2835_i2c_setSlaveAddress(slave_address);
bcm2835_i2c_setClockDivider(clk_div);
fprintf(stderr, "Clock divider set to: %d\n", clk_div);
fprintf(stderr, "len set to: %d\n", len);
fprintf(stderr, "Slave address set to: %d\n", slave_address);
if (mode == MODE_READ) {
for (i=0; i<MAX_LEN; i++) buf[i] = 'n';
data = bcm2835_i2c_read(buf, len);
printf("Read Result = %d\n", data);
for (i=0; i<MAX_LEN; i++) {
if(buf[i] != 'n') printf("Read Buf[%d] = %x\n", i, buf[i]);
}
}
if (mode == MODE_WRITE) {
data = bcm2835_i2c_write(wbuf, len);
printf("Write Result = %d\n", data);
}
// This I2C end is done after a transfer if specified
if (init == I2C_END) bcm2835_i2c_end();
bcm2835_close();
printf("... done!\n");
return 0;
}