Tôi yêu Arduino gửi vào
- 59140 lượt xem
Giới thiệu
Yeah, cộng đồng Arduino Việt Nam chúng ta đã có một bài viết về sóng vô tuyến rất hay của NTP_PRO phải không nào! Tuy nhiên, mình thấy một số ý kiến về sự đụng độ thư viện VirtualWire và Servo (của Arduino). Vì vậy, qua cách tiếp cận này của mình sẽ giúp các bạn giải quyết vấn đề trên nhé. Ngoài ra, qua bài viết, mình muốn chia sẻ cho các bạn cách "hack" những thiết bị vô tuyến hiện có như xe độ, hay cửa sắt tự động,.... Từ đó, tự các bạn chế ra những bộ remote của riêng mình.
Phần cứng
- Arduino UNO / Mini,...
- Một mạch phát 315 (hoặc 433) Mhz nếu có mạch thu nữa thì càng tốt! Bất kỳ mạch thu có IC nào trong danh sách sau: SC5262 / SC5272, HX2262 / HX2272, PT2262 / PT2272 (SC2272), EV1527, RT1527, FP1527 hoặc HS1527
- ... hình như là đủ òi :D... nhưng nếu bạn có một chiếc remote 315 (hoặc 433) Mhz nữa thì thật là tuyệt vời .
Đặt vấn đề
Oki, như chúng ta đã biết về sóng vô tuyến, để truyền / thu tín hiệu vẫn nhau thì chúng phải nằm ở cùng tấn số. Nghĩa là, một bộ phát 315Mhz chỉ có thể phát tín hiệu đến những mạch thu nào có thạch anh rung động ở tần số 315Mhz mà thôi (tất nhiên là nó chỉ thu được nếu khoảng cách giữa 2 mạch không quá xa, tùy chất lượng bố thu và bộ phát). Như vậy, nếu bạn đang sở hữu những thiết bị được điều khiển thông qua sóng vô tuyến ở các tần số 315 / 433 Mhz thì bạn có thể "hack" chúng để chúng thông minh hơn (chẳng hạn).
Lấy một ví dụ hơi "phá một tí" , bạn có một mạch Arduino, một bố phát 315Mhz. Bạn biết rằng (giả định thôi nhé), cửa kéo nhà hàng xóm của bạn có một cửa kéo điều khiển từ xa ở tần số 315Mhz và bạn muốn "mở" nó một cách bất hợp pháp . Như vậy, theo lý thuyết ở trên, bạn có thể làm được. Vấn đề ở đây là tín hiệu bạn gửi đi là gì? Một cách dễ nhất bạn có thể làm, đó là ... cho quét toàn bộ những đoạn mã số tín hiệu vô tuyến mà bạn có thể gửi đi! Không chỉ cửa nhà hàng xóm, mà nếu có xe máy sử dụng đề từ xa hoặc báo động từ xa, nó sẽ kêu ủm tòi cho mà toi. KHÔNG tin ư, hãy thử đọc bài này và bạn vọc thử xem... tuy nhiên, tôi không khuyến khích bạn thương mại hóa hay ứng dụng nó để làm việc xấu nhé.
Tóm lại, bài viết chúng ta chỉ có 2 vấn đề đơn giản sau:
- Tín hiệu của sóng 315Mhz được mã hóa rồi gửi đi như thế nào?
- Làm thế nào để gửi, nhận và hiểu những tín hiệu đó?
1. Tín hiệu của sóng 315Mhz được gửi đi như thế nào trong thế giới Arduino RC Switch?
Lưu ý, trong phần mô tả quy trình dưới đây chỉ áp dụng được cho các mach thu 315Mhz có IC. Với các lại mạch thu không IC sẽ được ghi chú ở mỗi phần.
Yeah, nó là một quy trình đơn giản như hình sau:
Giải thích quy trình:
- Dữ liệu của các biến trong Arduino được lưu trong RAM (các bạn có thể tìm đọc bài viết này trên arduino.vn). Như vậy, tùy kiểu dữ liệu mà nó sẽ chiếm hữu một số byte xác định cụ thể!
- Và cứ mỗi lần gửi dữ liệu chúng ta sẽ gửi từng byte (8 bit) như vậy. Mỗi cặp 2 bit sẽ mã hóa dữ liệu cho 1 chân, nếu nó là 11 thì chân đó sẽ có tín hiệu là HIGH (output 5V), còn lại là LOW (output GND).
- Mỗi bộ thu có một địa chỉ nhà (nếu những bộ thu khác nhau nhưng chung địa chỉ nhà thì khi bạn gửi cả 2 bộ thu sẽ cùng nhận được tín hiệu => lỗi đúng đẵn của dữ liệu), mỗi địa chỉ là một word (nôm na là 2 byte = 16 bit). Mỗi lần gửi dữ liệu ngoài từng byte lưu trữ dữ liệu ta phải gửi thèm theo địa chỉ này.
- Như vậy ta phải gửi tổng cộng 8 + 16 = 24 bit cho mỗi lần gửi dữ liệu, bao gồm địa chỉ bộ thu và byte dữ liệu.
Như vậy nếu một kiểu int hay một chuỗi kiểu char, thì làm thế nào để chúng ta gửi được dữ liệu, vì khi gửi chúng ta chỉ có thể gửi từng byte?
Yeah, lúc này chúng ta phải xây dựng một thư viện đặc biệt để xử lý nhiệm vụ này, các bạn có thể tham khảo thư viện VirtualWire đã được trình bày cụ thể rõ ràng ở bài viết này. Còn nếu muốn xây dựng một thư viện của riêng mình thì tốt nhất bạn không nên làm vì nó hơi thừa và nếu bạn muốn tự làm lại để học hỏi vì nên tham khảo phương pháp của Virtual Wire, chúng ta sẽ không đi sâu vào vấn đề này,... vì mình thấy nó không cần thiết với những gì mình định nói.
2. Vậy với ý tưởng truyền sóng như trên, làm thế nào để xây dựng một mô hình truyền gửi to lớn với mạch Arduino?
Chúng ta biết rằng, mỗi địa chỉ của bộ thu được mã hóa bằng 16 bit tương đương 216 cảm biến, tuy nhiên để biết kiệm chân nhằm giảm kích thước mạch thu 315Mhz có IC, người ta chỉ dùng 8 chân để mã hóa 16 bit theo cách sau: cứ mỗi cặp 2 bit trong 16 bit sẽ được quy về 1 pin. Nếu pin này không được mắc với cực âm hay cực dương (không nối) thì nó sẽ quy định 2 bit 01, nếu nó được mắc vào cực dương (VCC) thì nó sẽ quy định 2 bit 11, còn nối vào cực âm (GND) thì nó quy định 2 bit 00. Như vậy chúng ta sẽ có thể xây dựng được tối đa một hệ thống có 38 cảm biến với khả năng mỗi cảm biến nhận được 24 = 16 giá trị. (Nôm na là cứ mỗi địa chỉ là một mạch thu 4 kênh).
Tuy nhiên, nếu dùng với hệ thống VirtualWire và IC thu không IC giải mã thì bạn có thể xây dựng một hệ thống bá đạo hơn nhưng đồng thời nó cũng nặng hơn về dung lượng chương trình đấy nhé. Vì sao? Vì ngay từ bước 1 "làm thế nào" thì nó đã rộng hơn rồi! Bạn chọn bao nhiêu bit để mã hóa địa chỉ hay dữ liệu cũng được... Nếu so sánh VirtualWire với Rc-Switch trong Arduino, thì bạn chỉ cần xem VirtualWire là một con trỏ chuỗi và RC-Switch là một ký tự. Rõ ràng, bạn thấy thằng nào đơn giản hơn rồi đấy. Con trỏ thì luôn mang chiều hướng phức tạp còn những byte cố định thì luôn là một lựa chọn tối ưu trong một hệ thống tối ưu. Vì sao? Bạn hãy đọc bài viết cách lưu trữ biến trong Arduino trên cộng đồng của chúng ta.
Ngoài ra, với việc sử dụng RC-switch cho các loại IC thu không IC bạn cũng có thể tự mình điều chỉnh lại độ dài bit lưu trữ địa chỉ hay giá trị. Vì lúc này, chính con Arduino đảm nhiệm như vai trò giải mã, chứ không phải con IC giải mã có sẵn trên mạch thu 315Mhz có IC.
3. Thực hành
Chúng ta sẽ thống nhất với nhau sử dụng mạch thu có IC 2272 (L4) trong bài viết này nhé, sau đây là hình ảnh của em nó.
Mỗi loại mạch thu hầu hết đều có các chân sau: VCC, GND, D0 (10), D1 (11), D2 (12), D3 (13), VT(17), ANT và 8 chân mã hóa địa chỉ. Hình sau mô tả chi tiết các chân quan trọng của mạch thu của chúng ta.
Như hình trên thì theo lý thuyết địa chỉ của em này là 0101010101010101 (8 cặp 01). Để sửa địa chỉ, bạn chỉ việc lấy mối hàn và một mảnh đồng nhỏ để hàn các chân trong 8 chân địa chỉ nhằm thiết lập địa chỉ cho một mạch thu (node). Ví dụ như mạch sau, địa chỉ của hắn là 0101010101010000.
À, có một câu hỏi đặt ra là, nhiệm vụ của các chân D0, D1, D2, D3 và VT là gì? Nếu bạn chưa biết về mạch này nhưng qua quá trình đọc có thể đoán được rằng chân D0, D1, D2, D3 sẽ là 4 chân output của mạch thu này. Vâng, thật vậy ! Còn chân VT là chân debug, nghĩa là khi mạch này nhận được tín hiệu vào không cần biết địa chỉ là gì, miễn đúng địa chỉ thì nó nhận và nó sẽ sáng (HIGH) đến khi nào còn nhận dữ liệu và tắt thì không nhận dữ liệu. Ngoài ra, điểm đặc biệt của dòng mạch SC2272 là nó sẽ lưu giữ tín hiệu cuối cùng mà nó nhận được. Nghĩa là khi mạch này còn hoạt động (được cấp 5V vào VCC) thì nó còn lưu giữ tín hiệu mà nó nhận được trước đó (nếu chưa nhận được gì thì nó sẽ xuất ra 4 chân mã LOW). Nôm na, nếu bạn làm một chiếc xe điều khiển với mạch này thì khi xe đang chạy thẳng, mặc dù khi nó chạy ra khỏi vùng phủ sóng thì nó vẫn chạy tiếp.
Lắp mạch
Mạch thu, các chân D0 -> D3 và chân VT sẽ nối với một con LED. Còn chân VCC sẽ mắc vào một bộ nguồn 5V (4 cục pin tiểu hay cục ắc quy 6Vol vẫn ok), chân GND sẽ nối với cực âm của nguồn. Ở mạch này chúng ta sẽ không mắc bất cứ thứ gì với mạch Arduino. Vì mạch thu này hoạt động độc lập. Chúng ta sẽ không hàn các chân địa chỉ hoặc hàn thành bất cứ kiểu gì bạn muốn.
Mạch phát, các bạn mắc như hình
Hình mẫu trên mạng, Din (hoặc DATA hoăc ATAD).
Lập trình
Các bạn xin download thư viện rc-switch tại địa chỉ này (dự phòng).
Chúng ta sẽ bắt đầu với bài đơn giản là link với led D3. Mình có nhờ ksp làm một video với con bò sữa khá đẹp, các bạn xem demo bên dưới nhé.
#include <RCSwitch.h> RCSwitch mySwitch = RCSwitch(); void setup() { //Chân phát là chân số 10. mySwitch.enableTransmit(10); } void loop() { unsigned long address = 0b0101010101010101; /* Chúng ta phải để address là unsigned long vì: + address sẽ là biến nhận 24 bit dữ liệu má hóa nên kích thước của nó phải đủ lớn để chứa 16 bit địa chỉ và 8 bit dữ liệu + nó dương (unsigned) để chúng ta chuyển nó sang thập phân cho dễ (khỏi quân tâm đến số âm) */ /* Code blink D3 */ mySwitch.send((address << 8) | 0b00000011, 24); delay(1000); mySwitch.send((address << 8) | 0b00000000, 24); delay(1000); }
Lập trình cho 4 đèn LED sáng đuổi nhau.
#include <RCSwitch.h> RCSwitch mySwitch = RCSwitch(); void setup() { //Chân phát là chân số 10. mySwitch.enableTransmit(10); } void loop() { unsigned long address = 0b0101010101010101; //chưa hàn bất kì chân tín hiệu nào => địa chỉ là 8 cặp 01 /* Chúng ta phải để address là unsigned long vì: + address sẽ là biến nhận 24 bit dữ liệu má hóa nên kích thước của nó phải đủ lớn để chứa 16 bit địa chỉ và 8 bit dữ liệu + nó dương (unsigned) để chúng ta chuyển nó sang thập phân cho dễ (khỏi quân tâm đến số âm) */ unsigned int data = 0; for (int i = 0; i <= 4; i++) { mySwitch.send((address << 8) | data, 24); // tham số đầu là 24 bit mã hóa, phía sau là độ dài chuỗi mã hóa (max = 24). Nếu bé hơn 24 thì nó sẽ tự động thêm vào các bit 0 ở phía trước data <<= 2;// đẩy trái 2 bit data |= 3;//3 = 0b00000011 delay(100); } }
4. Mở rộng
Như mình đã nói ở mục một, chúng ta hoàn toàn có thể hack được một mạch thu phát sóng, bây giờ mình sẽ mô hình hóa quá trình đó để các bạn có thể tự thử nghiệm ở nhà
Bây giờ, theo mình nghĩ, chúng ta có 2 cách đơn giản nhất để hack một hệ thống thu / phát 315. Đó là:
- Đặt một máy thu 315MHz tại nhà nạn nhân và ngồi ở quán cafe 1 ngày để thu được tín hiệu mã hóa gồm 16 bit địa chỉ và 8 bit dữ liệu. Vì phần lớn mấy cái cửa sắt toàn của bọn Trung Quốc nên chúng làm ăn "mèo" lắm.
- "Dò trâu" từng địa chỉ với việc bật cả 4 kênh lên mức HIGH. Cái này dễ hơn, giống như trong phim người ta dò số để mở cửa vậy. Nhưng sẽ hơi tốn thời gian một tí. Nhưng điều đó chấp nhận được.
Chúng ta sẽ tìm hiểu cách 2 cho dễ, không cần đòi hỏi gì nhiều, chỉ cần một bé arduino hoặc promini và một module phát giá 25k là có thể hack một cái cửa hay một cái xe máy òi. .
Lưu ý: Bài viết này không cổ vũ cho các bạn đi phá nhà người khác, mà chỉnh mong muốn các bạn thông minh hơn để tự phòng vệ cho chính bản thân mình. Hãy loại bỏ những chiếc cửa mà có thể bị hack bởi bài viết này, vì nó không an toàn. Nếu bạn không bỏ nó thì sẽ có ngày nhà của bạn sẽ bị viến thăm bởi các tên trộm công nghệ cao.
Có thể chúng ta sẽ mất đến khoảng 30 phút (tối đa) để dò được địa chỉ mạch thu của nạn nhân, nhưng thông thường quá trình đó chỉ mất khoảng vài phút. Tuy nhiên, trong trường hợp thử nghiệm của bạn ksp, thì chỉ mất vài giây để mò ra địa chỉ và bật sáng con bò sữa... Như vậy lý thuyết đã được kiểm chứng, các bạn có thể "mò" sâu hơn nếu "cần".
Đây là phần code dò mã của chúng ta.
#include <RCSwitch.h> RCSwitch mySwitch = RCSwitch(); const byte block[3] = {1, 0, 3}; //01, 00, 11 void setup() { //Chân phát là chân số 10. mySwitch.enableTransmit(10); } void tryhack(int i, unsigned long address) { if (i == 8) mySwitch.send((address << 8) | 255, 24); else for (int j = 0; j < 3; j++) tryhack(i + 1, (address << 2) | block[j]); } void loop() { tryhack(0, 0); }
Trong đoạn code trên, chúng ta dùng một thuật toán đệ quy đơn giản nhằm sinh ra các địa chỉ có thể có sau đó phát lệnh bật toàn bộ 4 kênh ở bên mạch thu.
Video
Kết luận
Như vậy, qua cách tiếp cận như thế này, chúng ta có thể hack bất cứ thứ gì. Vâng, ở trên mình vẫn chưa nói về cách hack 1, cách này được dùng thường xuyên để lắng nghe rồi từ đó điều khiển một thiết bị bằng chính "đồ nghề" của mình. Các bạn có thể tham khảo bài viết của một anh Tây nhằm tự mình tìm tòi thêm nhé.
Với cách tiếp cận này, các bạn chỉ cần một mạch Arduino và từ đó "hack" và "control" mọi thứ. Chúc các bạn thành công.