Trong bài này, tôi sẽ giới thiệu cơ bản về ngôn ngữ Python, cách cài đặt thư viện dùng lập trình cho cho Raspberry Pi2 (RPi2) và bài vỡ lòng đầu tiên là lập trình đèn led nhấp nháy cho đến khi nhấn CTRL+C thì thoát chương trình.
Python là một ngôn ngữ tuyệt vời và mạnh mẽ đó là dễ dàng để sử dụng (dễ đọc và viết) và với Raspberry Pi cho phép bạn kết nối với dự án của bạn với thế giới thực.
Cú pháp Python rất sạch sẽ, nó nhấn mạnh về khả năng đọc và sử dụng từ khóa tiếng Anh chuẩn. Bắt đầu bằng cách mở IDLE (công cụ hỗ trợ lập trình Python) từ máy tính để bàn hoặc trong hệ điều hành Raspbian.
Python có 2 phiên bản là 2 và 3, lúc này chúng ta chưa quan tâm nhiều về sự khác biệt của 2 phiên bản, chúng ta mở phiên bản nào cũng được. Chúng ta sẽ nói về sự khác biệt của 2 phiên bản trong phần sau.
IDLE
Đơn giản nhất để lập trình Python là dùng IDLE, một môi trường phát triển Python. Mở IDLE từ màn hình Desktop hoặc ứng dụng menu:
IDLE cung cấp cho bạn một REPL (Read-Evaluate-Print-Loop) , trong đó có dấu nhắc cho bạn nhập lệnh Python vào. Vì nó là một REPL bạn có thể lấy kết quả ngay tức thì mà không cần lệnh print.
Bạn có thể sử dụng biến ngay bên trong IDLE, và bạn cũng có thể sử dụng như một máy tính cầm tay. Xem ví dụ:
>>> 1 + 2
3
>>> name = "Sarah"
>>> "Hello " + name
'Hello Sarah'
IDLE cũng có chức năng làm nổi bật cú pháp và một số chức năng hỗ trợ tự động điền trong khi gõ. Bạn có thể tìm lại các lệnh mà bạn đã nhập trong REPL với Alt + P (trước đó) và Alt + N (tiếp theo).
SỬ DỤNG PYTHON CƠ BẢN
In ra dòng chữ bất hủ trong giới lập trình "Hello Word" với câu lệnh sau (sử dụng trong Python 3), lưu ý, ngôn ngữ Python không sử dụng dấu (;) để kết thúc câu lệnh
print("Hello world")
THỤT ĐẦU DÒNG TRONG PYTHON
Một số ngôn ngữ sử dụng dấu ngoặc nhọn {và} để bọc mã nguồn bên trong các dòng code đều thụt đầu dòng để hiển thị lồng trực quan. Tuy nhiên, Python không sử dụng dấu ngoặc nhọn nhưng đòi hỏi phải thụt đầu dòng vào trong. Ví dụ như một vòng lặp for trong Python:
for i in range(10):
print("Hello")
khi dùng lệnh thứ 2 thụt vào thì nó sẽ thuộc trong vòng lập for, như vậy nó sẽ in ra 10 dòng chữ Hello. Đối với nhiều dòng lệnh hơn thì chúng ta cũng làm tương tự như thế, ví dụ:for i in range(2):
print("A")
print("B")
Kết quả in ra là:A
B
A
B
Một ví dụ khácfor i in range(2):
print("A")
print("B")
Kết quả làA
A
B
SỬ DỤNG BIẾN
Để lưu giá trị vào biến bạn làm như sau:
name = "Bob"
age = 15
Việc khai báo biến trong Python không cần quan tâm đến kiểu dữ liệu, Python sẽ xử lý tự động để thay đổi kiểu dữ liệu trong quá trình hoạt động.age = 15
age += 1 # increment age by 1
print(age)
GHI CHÚ MÃ NGUỒN (COMMENT)
Trong Python, chúng ta sử dụng dấu (#) để tạo ghi chú như dòng lệnh phía trê
DANH SÁCH (LIST)
LIST hoặc mảng trong các ngôn ngữ khác là tập hợp các giá trị có kiểu bất kỳ, các giá trị được đặt trong dấu móc vuông ([ và ]):
numbers = [1, 2, 3]
ITERATION
Một số kiểu dữ liệu là iterable, có nghĩa là bạn có thể lặp qua các giá trị mà họ có. Ví dụ: một danh sách:
numbers = [1, 2, 3]
for number in numbers:
print(number)
Câu lệnh trên sẽ in ra từng giá trị trong mảng numbers1
2
3
Tôi sử dụng từ number (bạn có thể sử dụng từ nào tùy ý) để chỉ đến từng phần tử trong mảng numbers,
Ví dụ khác, in ra từng ký tự trong 1 chuỗi
dog_name = "BINGO"
for char in dog_name:
print(char)
Kết quả nhận được
B
I
N
G
O
RANGE
Kiểu số nguyên thì không thể duyệt qua từng phần tử nếu không chúng sẽ sinh lỗi. Ví dụ:
for i in 3:
print(i)
Nó sẽ sinh lỗi
TypeError: 'int' object is not iterable
Và chúng ta sẽ sử dụng hàm range() để khắc phục
for i in range(3):
print(i)
Hàm range(5) chứac các số 0, 1, 2, 3 và 4 (5 số là tổng). Để lấy từ 1 đến 5 sử dụng range(1, 6).
TÌM CHIỀU DÀI GIÁ TRỊ
Bạn dùng hàm len():
ame = "Jamie"
print(len(name)) # 5
names = ["Bob", "Jane", "James", "Alice"]
print(len(names)) # 4
CÂU LỆNH IF
Có cấu trúc như ví dụ sau:
name = "Joe"
if len(name) > 3:
print("Nice name,")
print(name)
else:
print("That's a short name,")
print(name)
CÁC TẬP TIN PYTHON TRONG IDLE
Bạn chọn File > New File để mở file mới, trong đó bạn có thể nhập các câu lênh Python, lưu lại và chạy nó, kết quả sẽ hiển thị trong 1 cửa sổ khác. Ví dụ:
n = 0
for i in range(1, 101):
n += i
print("The sum of the numbers 1 to 100 is:")
print(n)
Lưu file File > Save hoặc Ctrl + S, chạy file (Run > Run Module) hoặc nhấn F5 và xem kết quả ở cửa sổ khác
THỰC THI FILE PYTHON TỪ DÒNG LỆNH
Bạn sử dụng lệnh cd, ls và python để chạy file python có đuôi mở rộng là py, ví dụ: python hello.py
Hết phần 1
Nguồn raspberrypi.org
Trong nhiều trường hợp, chúng ta phải thiết lập địa chỉ IP của Raspberry Pi thành IP tĩnh, ví dụ khi bạn làm web server, file server, printer server, …Bài viết này sẽ hướng dẫn các bạn cách thiết lập địa chỉ IP tĩnh cho Raspberry Pi chạy hệ điều hành Raspbian.
Để thực hiện điều đó, các bạn chỉ cần sửa file config tại /etc/network/interfaces
Mặc định eth0 (ethernet) đang để config nhận IP từ DHCP (iface eth0 inet dhcp)
Công việc của chúng ta là chuyển nó về dạng static (ip tĩnh) với các config như sau: static, ipadress, broadcast, gateway, network, netmask,..
Mở file /etc/network/interfaces bằng lệnh:
sudo nano /etc/network/interfaces
Khi mở file /etc/network/interfaces bạn sẽ thấy nội dung kiểu như sau:
auto lo
iface lo inet loopback
iface eth0 inet dhcp
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp
Đầu tiên, cần đổi phương thức nhận địa chỉ IP từ động (thông qua DHCP) sang tĩnh
Sửa dòng
iface eth0 inet dhcp
thành
iface eth0 inet static
Sau đó, tiến hành thêm các dòng sau vào phía dưới
address 192.168.1.127
netmask 255.255.255.0
network 192.168.1.0
broadcast 192.168.1.255
gateway 192.168.1.1
Lưu ý, tùy thuộc theo mạng LAN của các bạn mà địa chỉ IP Address, Netmask, Gateway của các bạn sẽ khác nhau, trong bài viết này mạng của mình có IP là 192.168.1.x.
Sau đó, các bạn lưu lại file interfaces bằng cách bấm Ctrl + X, bấm Y và Enter.
Cuối cùng, các bạn chỉ cần khởi động lại dịch vụ network để việc thay đổi có hiệu lực
/etc/init.d/network restart
Chúc các bạn thành công
Souce: raspberrypi.vn
1. Cài đặt một số thư viện mjpg-streamer cần sử dụng :
sudo apt-get install libv4l-dev libjpeg8-dev subversion imagemagick
2. Sửa lỗi thiếu thư viện videodev.h :
Để mjpg-stream build không bị lỗi thiếu thư viện, bạn cần tạo symbolic link videodev.h từ file videodev2.h trong đường dẫn /usr/include/linux/videodev2.h
sudo ln -s /usr/include/linux/videodev2.h /usr/include/linux/videodev.h
3. Download source mjpg-streamer từ sourceforge.net :
wget http://sourceforge.net/code-snapshots/svn/m/mj/mjpg-streamer/code/mjpg-streamer-code-182.zip
Giải nén : unzip mjpg-streamer-code-182.zip
4. Build mjpeg-streamer
$ cd mjpg-streamer-code-182/mjpg-streamer
$ make mjpg_streamer input_file.so output_http.so
5. Cài đặt mjpg-streamer
$ sudo cp mjpg_streamer /usr/local/bin
$ sudo cp output_http.so input_file.so /usr/local/lib/
$ sudo cp -R www /usr/local/www
6. Test :
mjpg_streamer -i “/usr/lib/input_uvc.so -d /dev/video0 -y -r 640×480 -q 95 -f 4 -l auto” -o “/usr/lib/output_http.so -p 8080 -w /usr/local/www”
Giải thích các thông số để bạn có thể tùy chỉnh theo ý muốn :
- mjpg streamer sử dụng port 8080
- Độ phân giải yêu cầu là 640×840 có thể giảm xuống 320×240 để tốc độ nhanh hơn
- Chất lượng hình ảnh là 95% và số frame truyền mỗi giây là 4 frame
Nếu muốn đặt mật khẩu để bảo vệ thì bạn có thể tham khảo command sau :
mjpg_streamer -i “/usr/lib/input_uvc.so -d /dev/video0 -y -r 640×480 -q 95 -f 4 -l auto” -o “/usr/lib/output_http.so -p 8080 -w /usr/local/www -c user:id”
Bài viết này giới thiệu cách làm thế nào để truy xuất GPIO bằng C++ trên kit RPI . Có 2 cách để thực hiện điều này :
- Cách thứ nhất là tác động trực tiếp tới các thanh ghi GPIO trên RPI giống như phương pháp lập trình vi điều khiển thông thường mà không có hệ điều hành (OS) . Ưu điểm của phương pháp này là hoàn toàn bỏ qua hệ điều hành, các chân GPIO sẽ được truy xuất rất nhanh. Tuy nhiên cách này không an toàn và có thể gây ra xung đột bởi sự truy xuất cùng lúc của nhiều quá trình đến các thanh ghi vật lý trên RPI.- Cách thứ hai : Sử dụng cách truy xuất GPIO an toàn thông qua driver đã được xây dựng sẵn trên Linux OS. Về cơ bản nó xem mỗi thuộc tính của mỗi chân GPIO như là 1 tập tin. Công việc của ta là thao tác với các tập tin này để điều khiển GPIO. Đây là phương pháp được ưu tiên để truy xuất GPIO .
Bài viết này sẽ trình bày theo cách thứ hai. Mô hình kết nối như sau :
Mục đích của lớp GPIOClass là cho phép điều khiển từng chân GPIO. Lớp này được thiết kế sao cho GPIO pin number được xác định thông qua hàm khởi tạo của lớp GPIOClass. file header “GPIOClass.h” được cung cấp bên dưới :
#ifndef GPIO_CLASS_H
#define GPIO_CLASS_H
#include <string>
using namespace std;
/* GPIO Class
* Purpose: Each object instantiated from this class will control a GPIO pin
* The GPIO pin number must be passed to the overloaded class constructor
*/
class GPIOClass
{
public:
GPIOClass(); // tạo 1 GPIO object để điều khiển GPIO4 (mặc định)
GPIOClass(string x); // tạo 1 GPIO object để điều khiển GPIOx, x được truyền vào thông qua hàm khởi tạo
int export_gpio(); // exports GPIO
int unexport_gpio(); // unexport GPIO
int setdir_gpio(string dir); // Set GPIO Direction
int setval_gpio(string val); // Set GPIO Value (putput pins)
int getval_gpio(string& val); // Get GPIO Value (input/ output pins)
string get_gpionum(); // trả về chỉ số GPIO tương ứng với 1 object
private:
string gpionum; // GPIO number : lưu trữ chỉ số của gpio
};
#endif
Mỗi object GPIOClass có các hàm thành viên cho phép ta export hoặc unexport GPIO pins, set direction của GPIO pins cũng như get value của GPIO pins. object GPIOClass có 1 biến private để lưu chỉ số GPIO pin.
Dưới đây là nội dung file “GPIOClass.cpp” :
Dưới đây là nội dung file “GPIOClass.cpp” :
#include <fstream>
#include <string>
#include <iostream>
#include <sstream>
#include "GPIOClass.h"
using namespace std;
GPIOClass::GPIOClass()
{
this->gpionum = "4"; //GPIO4 is giá trị mặc định cho hàm khởi tạo không có tham số truyền vào
}
GPIOClass::GPIOClass(string gnum)
{
this->gpionum = gnum; // hàm khởi tạo có thông số truyền vào cho gpionum là gnum
}
int GPIOClass::export_gpio()
{
string export_str = "/sys/class/gpio/export";
ofstream exportgpio(export_str.c_str()); // Thực hiện mở file "export" . Convert C++ string to C string. Required for all Linux pathnames
if (exportgpio < 0){
cout << " OPERATION FAILED: Unable to export GPIO"<< this->gpionum <<" ."<< endl;
return -1;
}
exportgpio << this->gpionum ; //write GPIO number to export
exportgpio.close(); //close export file
return 0;
}
int GPIOClass::unexport_gpio()
{
string unexport_str = "/sys/class/gpio/unexport";
ofstream unexportgpio(unexport_str.c_str()); //Open unexport file
if (unexportgpio < 0){
cout << " OPERATION FAILED: Unable to unexport GPIO"<< this->gpionum <<" ."<< endl;
return -1;
}
unexportgpio << this->gpionum ; //write GPIO number to unexport
unexportgpio.close(); //close unexport file
return 0;
}
int GPIOClass::setdir_gpio(string dir)
{
string setdir_str ="/sys/class/gpio/gpio" + this->gpionum + "/direction";
ofstream setdirgpio(setdir_str.c_str()); // open direction file for gpio
if (setdirgpio < 0){
cout << " OPERATION FAILED: Unable to set direction of GPIO"<< this->gpionum <<" ."<< endl;
return -1;
}
setdirgpio << dir; //write giá trị direction đến direction file (là 'in' hoặc 'out')
setdirgpio.close(); // close direction file
return 0;
}
int GPIOClass::setval_gpio(string val)
{
string setval_str = "/sys/class/gpio/gpio" + this->gpionum + "/value";
ofstream setvalgpio(setval_str.c_str()); // open value file for gpio
if (setvalgpio < 0){
cout << " OPERATION FAILED: Unable to set the value of GPIO"<< this->gpionum <<" ."<< endl;
return -1;
}
setvalgpio << val ;//write value to value file
setvalgpio.close();// close value file
return 0;
}
int GPIOClass::getval_gpio(string& val){
string getval_str = "/sys/class/gpio/gpio" + this->gpionum + "/value";
ifstream getvalgpio(getval_str.c_str());// open value file for gpio
if (getvalgpio < 0){
cout << " OPERATION FAILED: Unable to get value of GPIO"<< this->gpionum <<" ."<< endl;
return -1;
}
getvalgpio >> val ; //read gpio value
if(val != "0")
val = "1";
else
val = "0";
getvalgpio.close(); //close the value file
return 0;
}
string GPIOClass::get_gpionum(){
return this->gpionum;
}
Để open hoặc close file trong C++ ta sử dụng các class ifstream/ofstream (ifstream cho nhập (đọc) từ một file, ofstream cho xuất (ghi) tới một file) và fstream cho nhập/xuất (đọc/ghi) tới một file).
Viết một class để test có tên là “GPIOtest1.cpp” như sau :
Viết một class để test có tên là “GPIOtest1.cpp” như sau :
#include <iostream>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "GPIOClass.h"
using namespace std;
int main (void)
{
string inputstate;
GPIOClass* gpio4 = new GPIOClass("4"); //create new GPIO object to be attached to GPIO4
GPIOClass* gpio17 = new GPIOClass("17"); //create new GPIO object to be attached to GPIO17
gpio4->export_gpio(); //export GPIO4
gpio17->export_gpio(); //export GPIO17
cout << " GPIO pins exported" << endl;
gpio17->setdir_gpio("in"); //GPIO4 set to output
gpio4->setdir_gpio("out"); // GPIO17 set to input
cout << " Set GPIO pin directions" << endl;
while(1)
{
usleep(500000); // wait for 0.5 seconds
gpio17->getval_gpio(inputstate); //read state of GPIO17 input pin
cout << "Current input pin state is " << inputstate <<endl;
if(inputstate == "0") // if input pin is at state "0" i.e. button pressed
{
cout << "input pin state is "Pressed ".n Will check input pin state again in 20ms "<<endl;
usleep(20000);
cout << "Checking again ....." << endl;
gpio17->getval_gpio(inputstate); // checking again to ensure that state "0" is due to button press and not noise
if(inputstate == "0")
{
cout << "input pin state is definitely "Pressed". Turning LED ON" <<endl;
gpio4->setval_gpio("1"); // turn LED ON
cout << " Waiting until pin is unpressed....." << endl;
while (inputstate == "0"){
gpio17->getval_gpio(inputstate);
};
cout << "pin is unpressed" << endl;
}
else
cout << "input pin state is definitely "UnPressed". That was just noise." <<endl;
}
gpio4->setval_gpio("0");
}
cout << "Exiting....." << endl;
return 0;
}
Chương trình GPIOtest1.cpp khá đơn giản. Đầu tiên nó khởi tạo hai đối tượng GPIOClass để truy xuất đến GPIO4 và GPIO17 (gpio4 và gpio17) trên header 26 chân .Chú ý tên object được đặt tượng trưng cho tên gpio nhưng ta vẫn có thể đặt tên khác.
Các chân GPIO sau đó được export, GPIO4 set thành output và GPIO17 set input. Vòng lặp vô hạn sẽ đọc trạng thái đầu vào tại chân GPIO17. Nếu trạng thái của chân này là ’0′ nghia là button có thể đã được nhấn. Trạng thái của chân GPIO17 được kiểm tra lại một lần nữa để chắc chắn rằng điều này là đúng và thực hiện set gpio4 lên mức ’1′ để bật LED. Một vòng lặp khác được thực hiện để kiểm tra rằng nếu GPIO17 vẫn còn đang nhấn thì LED trên GPIO4 vẫn tiếp tục sáng đến khi nào thả nút nhấn trên GPIO17.
Dòng đầu tiên mô tả tên của một biến cấu trúc kiểu sigaction có tên là sig_struct. Dòng thứ 2 gán tên của hàm xử lý mà khi có ngắt thì chương trình sẽ nhảy tới đó.Dòng thứ 3 với “sa_flags” mô tả tập hợp các cờ để set các trạng thái tín hiệu ngắt, ở đây mình không quan tâm, cứ set là 0. Dòng cuối cùng của đoạn code trên với sig_struct.sa_mask của cấu trúc sigaction sẽ được khởi tạo empty. sa_mask cho phép ta thiết lập thêm những tín hiệu nào sẽ bị chặn trong suốt quá trình xử lý ngắt.
Hàm sigaction sẽ được dùng để map “sig_struct” với tín hiệu SIGINT mỗi khi cấu trúc sig_struct được hoàn thành.
Các chân GPIO sau đó được export, GPIO4 set thành output và GPIO17 set input. Vòng lặp vô hạn sẽ đọc trạng thái đầu vào tại chân GPIO17. Nếu trạng thái của chân này là ’0′ nghia là button có thể đã được nhấn. Trạng thái của chân GPIO17 được kiểm tra lại một lần nữa để chắc chắn rằng điều này là đúng và thực hiện set gpio4 lên mức ’1′ để bật LED. Một vòng lặp khác được thực hiện để kiểm tra rằng nếu GPIO17 vẫn còn đang nhấn thì LED trên GPIO4 vẫn tiếp tục sáng đến khi nào thả nút nhấn trên GPIO17.
Phần 2-kết hợp ngắt
Có một lỗ hổng cơ bản trong chương GPIO ở bài trước.Thông thường khi chương trình đang chạy mà ta muốn thoát chương trình thì hay dùng thao tác đó là sử dụng tổ hợp phím Ctrl-C.Như zậy nếu với đoạn code trên thì chương trình sẽ thoát trực tiếp mà chưa hề được giải phóng bộ nhớ đã cấp cho 2 đối tượng gpio4 và gpio7. Có một cách để giải quyết vấn đề trến là viết hàm xử lý khi có tín hiệu đến (xử lý ngắt mềm) và gán nó đến sự kiện SIGINT (ctrl-C). Điều này cho phép chương trình sẽ nhảy đến signal handler này bất cứ khi nào ctrl-C được nhấn, thay vì thoát trực tiếp chương trình. Hàm xử lý ngắt sau đó có thể khởi tạo một phương pháp thoát chương trình tối ưu hơn ví dụ như giải phóng bộ nhớ và unexport các chân trước khi exit. Bắt đầu vào phân tích code, đầu tiên ta phải include :
#include <signal.h>
Bước tiếp theo là khai báo và thiết lập một biến cấu trúc là sig_struct như sau :
struct sigaction sig_struct;
sig_struct.sa_handler = sig_handler;
sig_struct.sa_flags = 0;
sigemptyset(&sig_struct.sa_mask);</code>
Dòng đầu tiên mô tả tên của một biến cấu trúc kiểu sigaction có tên là sig_struct. Dòng thứ 2 gán tên của hàm xử lý mà khi có ngắt thì chương trình sẽ nhảy tới đó.Dòng thứ 3 với “sa_flags” mô tả tập hợp các cờ để set các trạng thái tín hiệu ngắt, ở đây mình không quan tâm, cứ set là 0. Dòng cuối cùng của đoạn code trên với sig_struct.sa_mask của cấu trúc sigaction sẽ được khởi tạo empty. sa_mask cho phép ta thiết lập thêm những tín hiệu nào sẽ bị chặn trong suốt quá trình xử lý ngắt.
Hàm sigaction sẽ được dùng để map “sig_struct” với tín hiệu SIGINT mỗi khi cấu trúc sig_struct được hoàn thành.
if (sigaction(SIGINT, &sig_struct, NULL) == -1) {
cout << "Problem with sigaction" << endl;
return -1;
}
Ta cũng cần viết hàm xử lý ngắt “sig_handler”.Khi ctrl-C được nhấn, chương trình thực thi sẽ nhảy đến hàm xử lý ngắt và set cờ ctrl_c_pressed thành true. Một vòng lặp while trong hàm main sẽ kiểm tra cờ này.Nếu nó được set thành true bởi tín hiệu ngắt thì chương trình sẽ thực hiện các công việc cần thiết để giải phóng bộ nhớ và unexport các pin GPIO theo đúng các.
void sig_handler(int sig)
{
write(0,"nCtrl^C pressed in sig handlern",32);
ctrl_c_pressed = true;
}
//phần kiểm tra ctrl-C :
if(ctrl_c_pressed)
{
cout << "Ctrl^C Pressed" << endl;
cout << "unexporting pins" << endl;
gpio4->unexport_gpio();
gpio17->unexport_gpio();
cout << "deallocating GPIO Objects" << endl;
delete gpio4;
gpio4 = 0;
delete gpio17;
gpio17 =0;
break;
}
Còn đây là toàn bộ code chương trình “GPIOTest2.cpp” . Lưu ý là chương trình phải được chạy dưới quyền user root.
#include <iostream>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "GPIOClass.h"
using namespace std;
void sig_handler(int sig);
bool ctrl_c_pressed = false;
int main (void)
{
struct sigaction sig_struct;
sig_struct.sa_handler = sig_handler;
sig_struct.sa_flags = 0;
sigemptyset(&sig_struct.sa_mask);
if (sigaction(SIGINT, &sig_struct, NULL) == -1) {
cout << "Problem with sigaction" << endl;
exit(1);
}
string inputstate;
GPIOClass* gpio4 = new GPIOClass("4");
GPIOClass* gpio17 = new GPIOClass("17");
gpio4->export_gpio();
gpio17->export_gpio();
cout << " GPIO pins exported" << endl;
gpio17->setdir_gpio("in");
gpio4->setdir_gpio("out");
cout << " Set GPIO pin directions" << endl;
while(1)
{
usleep(500000);
gpio17->getval_gpio(inputstate);
cout << "Current input pin state is " << inputstate <<endl;
if(inputstate == "0")
{
cout << "input pin state is "Pressed ".n Will check input pin state again in 20ms "<<endl;
usleep(20000);
cout << "Checking again ....." << endl;
gpio17->getval_gpio(inputstate);
if(inputstate == "0")
{
cout << "input pin state is definitely "Pressed". Turning LED ON" <<endl;
gpio4->setval_gpio("1");
cout << " Waiting until pin is unpressed....." << endl;
while (inputstate == "0"){
gpio17->getval_gpio(inputstate);
};
cout << "pin is unpressed" << endl;
}
else
cout << "input pin state is definitely "UnPressed". That was just noise." <<endl;
}
gpio4->setval_gpio("0");
if(ctrl_c_pressed)
{
cout << "Ctrl^C Pressed" << endl;
cout << "unexporting pins" << endl;
gpio4->unexport_gpio();
gpio17->unexport_gpio();
cout << "deallocating GPIO Objects" << endl;
delete gpio4;
gpio4 = 0;
delete gpio17;
gpio17 =0;
break;
}
}
cout << "Exiting....." << endl;
return 0;
}
void sig_handler(int sig)
{
write(0,"nCtrl^C pressed in sig handlern",32);
ctrl_c_pressed = true;
}
Cách biên dịch chương trình sử dụng g++:
g++ -fpermissive -Wall GPIOClass.cpp GPIOTest2.cpp -o outBin (với outBin là file thực thi được tạo ra sau khi biên dịch.
set quyền thực thi : chmod +x outBin
Chạy chương trình : ./outBin
g++ -fpermissive -Wall GPIOClass.cpp GPIOTest2.cpp -o outBin (với outBin là file thực thi được tạo ra sau khi biên dịch.
set quyền thực thi : chmod +x outBin
Chạy chương trình : ./outBin