Hướng dẫn toàn tập là LED ma trận giá tiền ảo và đồng bộ dữ liệu Internet - Học STEM IoT

Mô tả dự án: 

Bất cứ chúng ta đều cần cập nhập thông tin, nào là tin tức đời sống, lượt xem youtube hay là tỉ giá ngoại tệ, tiền ảo,... Doanh nghiệp cũng cần cập nhật giá cho các sản phẩm tại các shop của họ. Các bạn không cần bỏ ra một núi tiền để nghiên cứu nữa. Hãy cùng làm theo bài viết này, và nó sẽ truyền cảm hứng cho bạn. Bài viết này, khác ở chỗ, nó không hoạt động độc lập một mỉnh lẻ loi mà nó có thể scale-out ra hàng ngàn thiết bị ngay tức khắc mà bạn không cần lo lắng gì về server cả!

Tại sao bạn lại cần đọc bài này?

Đây là một bài viết toàn văn, đầy đủ các bước thực hiện, giải thích source code. Bạn không biết gì về lập trình mạng, IoT, cũng đừng lo lắng, bạn chỉ việc kéo thả các khối lệnh rất đơn giản mà thôi! Nói đơn giản là thế nhưng thực sự nó rất thú vị, bất cứ ai dù không biết gì về lập trình thì vẫn có thể làm được và làm tốt. Quan trọng hơn hết, chỉ cần bạn làm một thiết bị thì bạn có thể scale-out ra 10000 thiết bị ngay lập tức mà không cần tính toán gì ngoài việc tính toán tiền phần cứng! Điều mà một doanh nghiệp, công ty thực sự cần trong mọi dự án.

Nào, chúng ta cùng bắt đầu thôi!

Bạn cần chuẩn bị những gì để bắt đầu

Phần mềm

  • Trên điện thoại di động:
    • iNut - Công tắc wifi (các bạn search trong apple store hoặc google play từ khóa inut là ra). Tải về trên Apple Store, tải về ở Google Play.
  • Trên máy tính:

Phần cứng

Nếu các bạn muốn mua trọn bộ có thể liên lạc với mình Mr.Khánh 097 276 8491.

Kết nối IoT cho thiết bị iNut Cảm biến

Bạn sử dụng dây sạch Micro USB của Android hoặc xuống bước dưới nối dây như hình rồi thực hiện kết nối như video sau:

Cài đặt cho mạng (iNut_<con số>) (Password: inut12345)

Cách nối dây

Đối với board mạch Arduino Nano và Mega, các bạn cứ tìm cái ụ SPI tương tự như hình nhé! Cách nối chân tương tự. Đối với Arduino Nano, các bạn nối D1 của iNut cảm biến vào A4, D2 nối A5.

Arduino Uno iNut Cảm biến LED ma trận
GND GND GND
5V VIN VCC
SDA (A4) SDA (D1)  
SCL (A5) SCL (D2)  
SCK   CLK
MOSI   DIN
10   CS

 

Chương trình

#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
#include <Wire.h>
#include <ArduinoJson.h>
#include <EEPROM.h>

#define N_SENSOR  6
float sensors[N_SENSOR]; //biến lưu trữ danh sách cảm biến

int pinCS = 10; // Chọn chân SPI, các bạn có thể thay đổi số này trừ 11, 12, 13 (đối với Arduino Uno và Nano


byte numberOfHorizontalDisplays = 1; //số trong Hiển thị theo chiều ngang
byte numberOfVerticalDisplays = 4; // Số trong hiển thị theo chiều dọc. Bạn mua nhiều module hơn chỉ việc ghép nối tiếp lại và sửa số ở đây :D

Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays); // cấu hình matrix

String tape = "<3 iNut xLED <3";
String newTape = "";


byte wait = 30; // thời gian chạy chữ.

byte spacer = 1; // khoảng cách cách chữ
byte width = 5 + spacer; // độ rộng của font là 5 fixel
byte intensity = 15;


//Tạo vùng nhớ lưu trữ các biến tiền tệ để dễ dàng truy xuất.
//Ví dụ: list["BTC=>USD"] = 6000 list["BTC=>EUR"] = 4999 
// Khi bạn muốn sửa giá trị của BTC=>USD chỉ cần làm phép gán list["BTC=>USD"] = 6666 (giá trị mới chẳng hạn...)
//Đây chỉ là một cách dùng, các bạn có thể thay thế BTC=>USD = giá tiền bằng một cặp key => value mà bạn thích.
// Ví dụ: Temp = 33.3 (nhiệt độ nhà nấm là 33.3 độ C), Humi = 69.6% (Độ ẩm hiện tại là 69.6%,...)
StaticJsonBuffer<234> jsonBuffer; //Đối với các bạn muốn lưu và hiển thị nhiều số hơn thì sửa số 234 này cho lớn hơn là được. Các bạn dùng Arduino Mega thì vô tư còn các bạn dùng Arduino thì như vầy là đủ rồi!
static JsonObject& list = jsonBuffer.createObject();
void setup()
{
    //Bật Serial ở baudrate 9600 cho thoải mái
    Serial.begin(9600);
    
    
    //Khởi tạo EEPROM để dùng lưu trữ các biến khi mất điện
    EEPROM.begin();
    
    //Để sử dụng iNut Cảm biến - bạn cần chạy lệnh này
    //... để Arduino của bạn ở thành một thiết bị I2C Slave với địa chỉ là 10 :D (hơi học thuật một xíu bạn có thể bỏ qua)
    Wire.begin(10);
    
    
    ////Đọc các giá trị lưu ở "ổ cứng epprom". Bản chất epprom không phải là ổ cứng, nó là một vùng nhớ sẽ không bị mất đi khi cúp điện (ROM)
    wait = EEPROM.read(0); // thời gian chạy chữ.
    Serial.print(F("Wait: "));
    Serial.println(wait);
    if (wait > 200)
        wait = 50;
    Serial.println(wait);
    spacer = EEPROM.read(1); // khoảng cách cách chữ
    Serial.print(F("spacer: "));
    Serial.println(spacer);
    if (spacer > 10)
        spacer = 1;
    Serial.println(spacer);
    width = EEPROM.read(2); // độ rộng của font là 5 fixel
    Serial.print(F("width: "));
    Serial.println(width);
    if (width > 20)
        width = spacer + 5;
    Serial.println(width);
    intensity = EEPROM.read(3);
    Serial.print(F("intensity: "));
    Serial.println(intensity);
    if (intensity == 0 || intensity > 15)
        intensity = 15;
    Serial.println(intensity);
    Wire.onReceive(receiveEvent);
    Wire.onRequest(i2cRequestEvent);
    matrix.setIntensity(intensity); // cài đặt giá trị độ tương phản từ 0 đến 15.

    //Cứ để nguyên các giá trị mặc định, và chạy :D, sau đó bạn thử thay thế thuộc tính để xem hiệu ứng nhé!
    // điều chỉnh hiển thị theo nhu câu của người dùng.
    //  matrix.setPosition(0, 1, 3);  // The first display is at <0, 0>
    //   matrix.setPosition(1, 1, 0);  // The second display is at <1, 0>
    //   matrix.setPosition(2, 2, 0);  // The third display is at <2, 0>
    //  matrix.setPosition(3, 3, 0);  // And the last display is at <3, 0>
    //  ...
    // matrix.setRotation(0, 2);    // Màn hình hiển thị đầu tiên là vị trí đảo ngược
    matrix.setRotation(3); // The same hold for the last display
}


//Gửi dữ liệu lên Internet - Các bạn chỉ cần thêm đoạn này vào chương trình và không cần hiểu sâu về nó
void i2cRequestEvent()
{
    //Buộc phải có nếu bạn muốn gửi dữ liệu
    char *data = (byte*)&sensors;
    Wire.write(data, sizeof(sensors));
    Serial.println(F("."));
}
//Bắt dữ liệu từ Internet trả về - Các bạn chỉ cần thêm đoạn này vào chương trình và không cần hiểu sâu về nó
volatile char buffer[33];
volatile boolean receiveFlag = false;
bool firstTimeInit = false;
void receiveEvent(int howMany)
{
    Wire.readBytes((byte *)buffer, howMany);
    buffer[howMany] = 0;
    receiveFlag = true;
    Serial.println(F("!"));
}

void loop()
{
    
    
    //Để đồng bộ các giá trị, ta chỉ việc gán các giá trị sensors[0] => sensors[5] là các giá trị thuộc tính của đèn led
    //iNut Cảm biến cho ta 8 thanh ghi để đồng bộ, tuy nhiên trong dự án này, ta chỉ cần 6 mà thôi.
    //Việc gán các giá trị rất đơn giản như sau 
    sensors[0] = wait;
    sensors[1] = spacer;
    sensors[2] = width;
    sensors[3] = intensity;
    sensors[4] = numberOfHorizontalDisplays;
    sensors[5] = numberOfVerticalDisplays;

    static unsigned long timer = 0;
    static unsigned long i = 0;
    
    //đoạn chương trình hiển thị led ma trận với hiệu ứng chữ chạy ngang
    //Thú thực với các bạn là mình cũng không quan tâm nó code gì trong này, chỉ cần biết là tốc độ nó hiển thị ra rất ổn
    //  và việc của chúng ta là thay đổi giá trị của biến chuỗi tape là xong!
    if (millis() - timer > (unsigned long)wait) {
        if (i < width * tape.length() + matrix.width() - 1 - spacer) {

            matrix.fillScreen(LOW);

            int letter = i / width;
            int x = (matrix.width() - 1) - i % width;
            int y = (matrix.height() - 8) / 2; // center the text vertically

            while (x + width - spacer >= 0 && letter >= 0) {
                if (letter < tape.length()) {
                    matrix.drawChar(x, y, tape[letter], HIGH, LOW, 1);
                }

                letter--;
                x -= width;
            }

            matrix.write(); // Send bitmap to display
            i++;
            timer = millis();
        } else {
            i = 0;
            if (newTape != "")
                tape = newTape;
        }

    }

    
    if (receiveFlag) { //khi có tín hiệu là đã nhận được lệnh và cần phải xử lý lệnh từ Internet

        String command = buffer; //chép lệnh vào biến String cho dễ xử lý


        Serial.print(command);// in ra lệnh
        Serial.print(' ');
        Serial.println(millis());//in ra thời gian theo millis tính từ lúc arduino chạy để debug
    
    
    //Các bạn xem quy ước lệnh ở phần tiếp theo trong bài viết
        StaticJsonBuffer<100> jsonBuffer;

        JsonObject& root = jsonBuffer.parseObject(command.c_str());

        if (root.containsKey("c")) {
            byte command_code = root.get<byte>(F("c"));
            byte value = root.get<byte>(F("v"));
            Serial.print(F("COMMAND CODE: "));
            Serial.println(command_code);
            switch (command_code) {
                case 0: //setup wait
                    Serial.println(F("Cap nhap wait"));
                    wait = value;
                    EEPROM.write(0, wait);
                    break;
                case 1: //setup spacer
                    Serial.println(F("Cap nhap spacer"));

                    spacer = value;
                    EEPROM.update(1, spacer);
                    break;
                case 2: //setup width
                    Serial.println(F("Cap nhap width"));

                    width = value;
                    EEPROM.update(2, width);
                    break;
                case 3: //setup intensity
                    Serial.println(F("Cap nhap intensity"));

                    intensity = value;
                    EEPROM.update(3, intensity);
                    matrix.setIntensity(intensity);
                    break;
            }
        } else if (root.containsKey("k")) {
            Serial.print(F("add key "));
            Serial.println(getMemoryFree());
            const char * key = root.get<const char *>(F("k"));

            const char * value = root.get<const char *>(F("v"));
            Serial.println(key);
            Serial.println(value);
            if (strlen(key) > 1 && strlen(value) > 1) {
                
                list.set(String(key),  String(value));
                newTape = "";
                // using C++11 syntax (preferred):
                int idx = 0;
                for (auto kv : list) {
                    idx++;


                    //Serial.println(kv.key);
                    //Serial.println(kv.value.as<char*>());
                    newTape += idx;
                    newTape += ".";
                    newTape += String(kv.key);
                    newTape += " ";
                    newTape += String(kv.value.as<const char*>());
                    newTape += ", ";
                    
                }

                if (!firstTimeInit) {
                    tape = newTape;
                    firstTimeInit = true;
                    i = 0;
                }
                tape = newTape;


                Serial.println(newTape);
            }
        }

        receiveFlag = false; //đánh dấu đã xử lý xong lệnh, không cần đọc nữa
    }
    
    //Cứ mỗi 1s là in ra số RAM còn dư của Arduino :D
    static unsigned long timer3 = 0;
    if (millis() - timer3 > 1000UL) {
        timer3 = millis();
        Serial.print(F("RAM: "));
        Serial.println(getMemoryFree());
    }
}

//Bạn xem bài viết này nếu muốn hiểu rõ hơn: http://arduino.vn/bai-viet/356-tiet-kiem-ram-trong-arduino
int getMemoryFree() {
    // Trong trường hợp này, ta có thể hiểu extern sẽ khai báo một biến toàn cục trong chương trình (nếu chưa có) hoặc include một biến toàn cục đã được extern trước đó
    extern int __heap_start;
    extern int *__brkval; 
    
    //Dấu & phía trước tên biến / tên con trỏ sẽ cho ta biết vị trí ô nhớ mà nó đang đứng
    //Lưu ý: bài viết này không dành cho beginner và bạn cần tưởng tượng một chút để có thể mườn tượng vấn đề
    return (int) SP - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

Các bạn chỉ việc nạp chương trình vào Arduino là xong! Nếu bạn chưa biết cách nạp chương trình, thì xem hướng dẫn nạp chương trình cho Arduino nhé.

Để biên dịch chương trình trên thành công, bạn cần 3 thư viện sau: Adafruit_GFX, ArduinoJson, Max72xxPanel. Các bạn có thể tải ngay 3 thư viện này tại đây.

Chương trình đồng bộ quản lý dữ liệu trên máy tính

Để cài đặt chương trình điều khiển bảng LED:

Các bạn mở Windows command line lên bằng cách nhấn tổ hợp phím Windows + R (phím Windows là phím giữa Alt và Ctrl á). Sau đó gõ lệnh cmd và nhấn OK.

Trong bản lệnh hiện ra, bạn lần lượt chạy các lệnh sau (chép và dán vào từng lệnh một cho chắc nhé)

Clone code về

git clone https://github.com/ngohuynhngockhanh/iNut-Node-RED-Kickstarter

cd iNut-Node-RED-Kickstarter

git checkout ledmatrix

Cài đặt

npm install

Chạy chương trình

npm start

Sau khi cài đặt xong, bạn sẽ có một thông báo như thế này:

Và các bạn truy cập vào http://127.0.0.1:1880/... nhé! Đây là giao diện của chúng ta.

Các bạn truy cập vào địa chỉ http://localhost:1880/ui/... để xem giao diện đồ họa nhé.

Okay, cài đặt xong rồi, bước tiếp theo là cập nhập các mã thông tin trong ví dụ mẫu cho phù hợp với các thiết bị iNut của bạn. 

Cách chép mã Node-Red topic từ phần mềm iNut

Bạn sửa topic trong khối lệnh trên bằng mã iNut cảm biến của bạn nhé. Để lấy mã mqtt topic của bạn, làm ơn xem video dưới dây.

Cách chép mã REST API từ phần mềm iNut

Bạn sửa URL trong khối lệnh trên bằng mã iNut cảm biến của bạn nhé. Để lấy mã REST API của bạn, làm ơn xem video dưới dây.

Hãy thử trải nghiệm thành quả của mình một cái đã rồi đọc tiếp nhé :D

Hiểu sâu hơn!

Tại sao nên sử dụng iNut Platform?

Trước tiên, chúng ta phải liệt kê ra một số bạn bè, anh chị đồng nghiệp trên thị trường để thấy rõ những điểm hay sáng tạo và những vấn đề cố hữu xung quanh nó.

Những anh chị nối tiếng ở thị trường Việt Nam (về marketing)

BKAV SMARTHOME, LUMI là hai thương hiệu về thiết bị nhà thông minh nổi tiếng nhất Việt Nam. Giải pháp của BKAV và LUMI hướng đến đối tượng toàn bộ một toàn nhà, văn phòng, căn hộ với giải pháp trọn gói. Bên cạnh đó, họ cũng phát triển hệ thống bán lẻ, bán buôn khắp các tỉnh thành Việt Nam.

Phân khúc khách hàng của nhóm đối tượng này rất rõ ràng: người dùng có nhu cầu sống trong nhà thông minh với thu nhập cao. Tuy nhiên lại không tùy biến cao vì chi phí một bộ thường khá đắt và chi phí lắp đặt cao. Ngoài ra, bị giới hạn bởi sự sáng tạo của công ty BKAV và LUMI. Người dùng chỉ được dùng những sản phẩm dịch vụ cho một bên đối tác BKAV LUMI cung cấp.

Sản phẩm rất đẹp và thể hiện được nhu cầu thể hiện bản thân của gia chủ.

Những công ty cung cấp giải pháp IoT cho các đối tượng công nghiệp

Spente là công ty thành công trong việc cung cấp giải pháp monitoring cho các ứng dụng máy chủ và server. Họ làm tốt trong việc tập trung đến các khách hàng trong ngành công nghiệp máy chủ.

Tuy nhiên, cũng như BKAV hay Limi, các công ty chỉ cho người dùng được dùng phần mềm của họ và từ họ. Không có cơ chế để cho bên thứ 3 vào và phát triển chung.

Trên thế giới, chuyện này đã có

Xively, Koor.io, Blynk,… có rất nhiều platform làm việc trực tiếp với nhà phát triển. Họ cung cấp giải pháp có phí và miễn phí để chạy dự án… Tuy nhiên, có những điều gọi là “gót chân asin” của những nền tảng này, đó là việc người lập trình phải chịu mọi rủi ro tại dự án của họ.

Các ví dụ kể đến:

  • Khách hàng đổi tên mạng wifi, đổi mật khẩu wifi. Và lập trình viên phải ngồi nạp code lại hết cho toàn bộ thiết bị. Nếu có cơ chế OTA và cơ chế đó bị lộ ra ngoài thì hacker có thể sử dụng để tạo thành một mạng ddos mạnh nhất.
  • Mỗi thiết bị có một key và key này phải gắn cứng khi cài đặt. Người dùng có thể tự lập trình cơ chế này (khó và mỗi người lại tự làm một kiểu khác nhau – thật khó để thống nhất).
  • Mỗi node thường bị hạn chế bởi thư viện. Phù hợp với những dự án nhỏ và không quá phức tạp. Chương trình người dùng bị hạn chế bởi khả năng lập trình mạng và lập trình ứng dụng sử dụng thư viện mạng. Nếu chương trình ứng dụng bị deadlock có thể gây lỗi cho chương trình IoT vì 2 chương trình này chạy song song trong cùng một vi điều khiển.

Vậy iNut có gì để chơi trong ngành công nghiệp hàng trăm tỉ đô la Trump này?

iNut tập trung vào một bộ công cụ, một IoT Platform để kết nối mọi thiết bị lại với nhau. Ở đó, người dùng ngoài việc sử dụng những sản phẩm của iNut team như BKAV, LUMI. Họ còn có thể lập trình được. Người dùng không phải là sử dụng thư viện của iNut để lập trình truyền thống, họ sử dụng một bo phát triển, gọi là iNut – Cảm biến, board này sẽ giao tiếp với Arduino qua chuẩn I2C. Người dùng sẽ lập trình ứng dụng của họ trên nền tảng quen thuộc là Arduino mà không cần phải tối ưu hóa chương trình của họ[1]. Arduino có thể làm mọi thứ[2], vì vậy iNut platform tích hợp được với Arduino thì có thể làm được tất cả mọi thứ. Với mô hình này, iNut không cần phải lo lắng và phát triển thư viện tổng quát như Blynk, Koor.io, Xively,… iNut có thể đóng lại để có cái gọi là tập trung gọi và ra các API để cho các lập trình viên ở Internet Side và Arduino Side phát triển ứng dụng.

Như vậy, iNut không tranh giành thị trường của các anh lớn và cạnh tranh với người khổng lồ open source, open service, iNut bản thân nó là đóng vai trò như một công cụ để phát triển ứng dụng thương mại và công nghiệp. Nền kinh tế chia sẻ là hệ thống tinh thần của iNut. Nơi mà các nhà phát triển, người dùng đều được hưởng lợi theo cơ chế tập trung và dân chủ. iNut Platform không đơn thuần bị bó hẹp trong một công ty như BKAV, LUMI hay Spenta, nó còn là một sản phẩm mang hình thái chủ nghĩa xã hội vạn vật. Nơi mọi vật có 2 quyền cơ bản: quyền được làm việc (gọi lệnh) và quyền được gửi dữ liệu về cho chủ nhân (trả về dữ liệu) như Koor,IO, Xively, Blynk. Với cơ chế này, iNut có thể được phát triển bởi rất nhiều bên và không bị hạn chế bởi một bên bất kỳ. Nơi đó, những nhà phát triển platform được xem là người đại diện cho người dùng để phát triển những tính năng cốt lõi mới. Còn người dùng và nhà phát triển ứng dụng là những người tương hỗ và đem lại lợi ích lẫn nhau.

 

[1] Tha hồ để delay (dừng hẳn chương trình – điều tối kị khi lập trình với Blynk, Koor.IO

[2] Arduino làm được mọi thứ: từ cái xe điều khiển đến vệ tinh đều làm được bởi những nhà phát triển trên toàn thế giới.

Cấu trúc giao tiếp với Internet của iNut Cảm biến như thế nào?

Nếu bạn nào đã biết đến truyền thông Bluetooth qua board mạch HC-06 thì có thể hiểu ngay đó là một board mạch Serial to Bluetooth và rất dễ sử dụng. Vậy thì iNut cảm biến cũng thế, bạn có thể hiểu đơn giản đây là một board mạch I2C to Internet! Và với hệ thống hỗ trợ viết app kéo thả bằng Node-RED nhưng vẫn đảm bảo sự bảo mật tuyệt đối thông qua các key mà bạn thấy như trong bài viết, các bạn có thể yên tâm về chủ quyền app của mình trên Internet.

 

Khẩu quyết truyền và nhận dữ liệu như sau:

  • Truyền dữ liệu (lập trình viên => Arduino):
    •  Bạn sẽ gửi được 32 ký tự (tối đa) xuống iNut Cảm biến. 
    • Để có thể gửi được đến iNut Cảm biến bạn phải có một key và bạn lấy key đó thông qua phần mềm iNut trên điện thoại của bạn. Bạn có thể thu hồi key này bất cứ lúc nào!
    • iNut cảm biến sẽ chuyển đúng 32 ký tự này cho Arduino.
    • Dựa vào cơ cấu truyền lệnh của bạn mà chương trình sẽ có độ phức tạp ít hay nhiều. Ví dụ bạn gửi lệnh BAT_DEN => bật đèn. Nhưng có thể chương trình của bạn quản lý 1000 bóng đèn thì sẽ có một cơ cấu khác ví dụ: BAT_DEN 1000 (bật bóng đèn số 1000)...

.

  • Nhận dữ liệu (Arduino => lập trình viên):
    • iNut cảm biến hỗ trợ 8 luồn float hồi tiếp về cho người sử dụng. Nôm na sẽ có tối đa 8 biến để bạn gán giá trị như trong đoạn code ở trên.
    • Dữ liệu sẽ được iNut lấy từ Arduino rồi gửi lên Internet sau mỗi 3s (có thể tùy chỉnh trong app iNut).
    • Lập trình viên nào có key và đang lắng nghe dữ liệu sẽ có thể nghe được qua hai phương thức chủ động là Socket.io và MQTT.

Rất đơn giản như thế thôi.

Chi tiết phương pháp truyền dẫn dữ liệu trong iNut xLED và lập trình viên

Vâng, như đã nói ở trên. Lập trình viên có 32 ký tự để gửi xuống Arduino và Arduino có 8 đường dữ liệu để gửi feedback cho người dùng.

Như đã mô tả trong code, chúng ta có 6 thuộc tính sẽ trả về cho người dùng:

Trong phạm vi bài viết, mình chỉ quan tâm đến hai thông số là waitintensity. Trong đó:

  • wait: là tốc độ chạy chữ. Mình để giới hạn từ 0 - 200. wait càng lớn thì tốc độ chạy càng chậm
  • intensity: đọ sáng màn hình, nó càng lớn thì càng sáng!

Ở nhu cầu của mình, mình muốn cập nhật giá trị của waitintensity. và thêm được càng nhiều càng tốt các thông tin về giá. Vậy mình sẽ có 3 lệnh cần gửi xuống cho Arduino:

  • Thay đổi wait
  • Thay đổi intensity
  • Thêm loại tiền mình muốn quan tâm

Để tiết kiệm thời gian code ở arduino, mình dùng chuẩn JSON để gửi dữ liệu. Ưu điểm của chuẩn JSON là phần bóc tách dữ liệu đã làm khá tốt và thư viện cũng sẵn có. Ngoài ra mình cũng dùng thư viện JSON để lưu trữ cho các loại tiền mình quan tâm nữa nên mình phải dùng JSON. Tuy nhiên, nhược điểm của nó là cấu trúc khá tốn ký tự, ví dụ như bạn phải có "" và {}, nhiêu đây là hết 4 ký tự rồi :D. Nhưng mà, yêu cầu của mình cũng không quá khó nên dùng JSON sẽ tiết kiệm thời gian code nhiều hơn.

Dựa vào yêu cầu đó, mình chia ra cấu trúc lệnh như sau:

{
    "c": <function code>,
    "v": <giá trị>,
}
hoặc
{
    "k": <tên tiền hoặc tham số>,
    "v": <giá trị>,
}

Trong đó, nếu dùng loại lệnh 1 thì sẽ gồm các function code sau:

  • 0:
    • cập nhập wait (giá trị được cập nhập là v)
  • 1
    • cập nhập spacer (giá trị được cập nhập là v)
  • 2
    • cập nhập width (giá trị được cập nhập là v)
  • 3
    • cập nhập intensity (giá trị được cập nhập là v)

Đối với loại lệnh thứ 2, chỉ đơn giản gửi một cặp lệnh để điều chỉnh giá mà thôi!

{"k":"BTC->USD","v":6969.696}

Như thế là đã thêm mới hoặc cập nhật (nếu đã có) cho giá trị đồng tiền BTC=>USD rồi! Các bạn nào muốn thử nghiệm lệnh và tập lập trình, xin hãy đọc thêm bài viết Kiểm thử iNut cảm biến này nhé (test các lệnh truyền thông trước khi làm project thật sự)

Vâng, đơn giản vậy thôi! Các code Arduino và code kéo thả trong chương trình node-red đã nói ở trên là minh chứng cho những gì chúng ta đã nói và thử nghiệm.

Chúc các bạn thành công!

lên
10 thành viên đã đánh giá bài viết này hữu ích.
Các dự án được truyền cảm hứng

Select any filter and click on Apply to see results

Các bài viết cùng tác giả

false

Trái lại với true, false là một hằng logic có giá trị là phủ định của true (và ngược lại), tức là (!true) = false. Bạn cũng có thể HIỂU false là một hằng số nguyên mang giá trị là 0. Trong các biểu thức logic, một hằng số hay giá trị của một biểu thức bằng 0 được xem như là bằng false.

lên
2 thành viên đã đánh giá bài viết này hữu ích.