GPIO Kernel

Để bắt đầu xây dựng thư viện cho ngoại vi này bạn cần hiểu về nó trước.

Đây là ngoại vi cơ bản trên mỗi tất cả MCU, chức năng của chúng là đọc/xuất tín hiệu múc cao/thấp, chỉ cơ bản như vậy thôi.

Với mỗi IO chúng ta sẽ tạo ra 1 biến để quản lý chúng:

typedef struct{

bool (*read)(void);

void (*write)(bool value);

//…add function that you want

}GPIO_Struct;

Vậy là chúng ta đã tạo ra một biến để quản lý tất cả các hoạt động của GPIO, mỗi IO sẽ được quản lý bởi một biến, truy xuất bằng con trỏ, như bạn đã thấy ở trên.

Nếu bạn đã từng làm việc trên các framework bạn sẽ biết rằng, các tổ chức hoặc công ty sẽ tạo ra các biến chung, các function chung, một số function được định nghĩa trước, một số bạn sẽ tự định nghĩa khi sử dụng.

Cùng tạo thư viện quản lý GPIO thôi. Trước tiên, bạn tạo file GPIO_Common.h – nơi chứa kiểu GPIO_Struct vừa tạo và các function khác.

Trong file này chúng ta tạo 1 function rỗng hay còn gọi là prototype để người dùng tự định nghĩa.

void createGPIOCommon(GPIO_Struct *pIO);

Đây sẽ là function chung dùng để khởi tạo GPIO.

Tiếp theo, bạn tạo 1 file source code (.c) và include “GPIO_Common.h

//Khởi tạo biến button

GPIO_Struct pButton;

//Viết source code định nghĩa

void createGPIOCommon(GPIO_Struct *pIO)

{

if(pIO==&pButton)

{

GPIO_InitTypeDef GPIO_InitStructure;

/*Config for button*/        BUTTON_1_CLK_CMD(BUTTON_1_RCC_PORT, ENABLE);        GPIO_InitStructure.GPIO_Mode = BUTTON_1_MODE;        GPIO_InitStructure.GPIO_Speed = BUTTON_1_SPEED;        GPIO_InitStructure.GPIO_Pin = BUTTON_1_PIN;    GPIO_Init(BUTTON_1_PORT,&GPIO_InitStructure);
/* Init pointer function */
pIO->read=&readButton;

}

}

Tiếp theo là định nghĩa cho function readButton.

bool readButton(void)

{

return(GPIO_ReadInputDataBit(BUTTON_1_PORT, BUTTON_1_PIN));

}

Việc tạo function output cho Led cũng tương tự.

Your Libraries For All MCU

Có bao giờ bạn tự hỏi:

Làm sao tái sử dụng code của mình khi chuyển qua lập trình trên một kiến trúc khác?

Đó cũng là câu hỏi không chỉ của mình bạn mà còn của rất nhiều lập trình viên hệ thống nhúng khác. Bạn đang lập trình trên ARM Cortex-M0, bỗng một ngày bạn cần nâng cấp vi xử lý của mình lên Cortex-M3, bạn phải code lại từ đầu sao? Thật phí công sức và thời gian phải không nào? Làm sao để giải quyết được điều này?

Như bạn đã biết hardware là thành phần cơ sở trong một hệ thống, tùy vào yêu cầu và giá thành mà hardware sử dụng những loại MCU cho phù hợp . Mỗi MCU lại được nhà sản xuất hỗ trợ những thư viện riêng để giúp người dùng có thể tiếp cận nhanh chóng và dễ dàng. Nhưng chính sự đa dạng MCU đó lại làm khó các lập trình viên khi họ chuyển sang một kiến trúc khác. Để dễ hình dung, bạn có thể tưởng tượng theo phân lớp sau đây:

  1. Hardware: tầng riêng của MCU, thư viện riêng,…
  2. Kernel: đây là phần dành cho OS, cầu nối giữa hardware và UI.
  3. UI-user interface: đây là tầng tương tác với người dùng, đọc tín hiện đầu vào, trả kết quả ra, chẳng hạn như đọc nút nhấn và xuất ra led.

Chúng ta sẽ làm việc ở giữa tầng 1 và tầng 2, chúng ta sẽ tạo ra những variable, function,… tập hợp chúng lại tạo thành 1 thư viện chung hay framework để dùng cho tất cả MCU. Các thành viên trong nhóm hay trong công ty của bạn sử dụng bộ framework này để lập trình. Việc này sẽ giúp nhóm bạn dễ dàng kiểm soát lỗi trong quá trình xây dựng, chuyển đổi kiến trúc MCU được dễ dàng và nhanh chóng, từ đó có thể tiết kiệm thời gian, công sức và tiền bạc.

Những nguyên tắc để xây dựng framework này:

  • Xây dựng trên ngôn ngữ C.
  • Hoạt động một cách độc lập, không phụ thuộc vào bất kì MCU nào.
  • Đương nhiên là có thể tái sử dụng
  • Dễ dàng nâng cấp và chỉnh sửa
  • Mang đến sự thuận tiện cho lập trình viên

Việc cần làm đầu tiên để xây dựng một framework, đó là định nghĩa kiểu dữ liệu chung. Các MCU được xây dựng sẵn các bộ thư viện riêng, chúng thường sử dụng các kiểu dữ liệu tùy biến từ các kiểu cơ bản. Việc làm này sẽ giúp project của bạn tránh bị lỗi khi chuyển qua một kiến trúc khác.

Ví dụ:

#ifndef __DataTypeOfProject_h__
#define __DataTypeOfProject_h__

#include <stdbool.h>
#include <stdint.h>

#ifndef true
#define true 1
#endif

#ifndef false
#define false 0
#endif

#ifndef Null
#define Null 0
#endif

#ifndef null
#define null 0
#endif

#ifndef NULL
#define NULL 0
#endif

#define bDISABLE 0
#define bENABLE 1

#define ui8 uint8_t
#define ui16 uint16_t
#define ui32 uint32_t

typedef enum{
bERROR=0,
bPASS=1,
bUNKNOWN=2,
}bInit;

#define typeclock ui16

#endif /*__DataTypeOfProject_h__*/

Bạn cũng có thể thêm các kiểu dữ liệu khác vào file này.

Trong phần tiếp theo, chúng ta sẽ xây dựng thư viện cho GPIO.

Hardware Sensor Android Phần 2

Trong phần này, bạn sẽ biết học cách giám sát cảm biến trên Android như thế nào.
Lest’s Go!
Để giám sát sensor, bạn cần implement lớp SensorEventListener. Trong lớp này có 2 method cần lưu ý:
onSensorChanged để giám sát giá trị cảm biến trả về
onAccuracyChanged phản ứng với sự thay đổi độ chính xác của cảm biến.

final SensorEventListener mySensorEventListener = new SensorEventListener() {
public void onSensorChanged(SensorEvent sensorEvent) {
// TODO Monitor Sensor changes.
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO React to a change in Sensor accuracy.
}
};

Tham số SensorEvent trong method onSensorChanged gồm 4 thuộc tính cho mỗi sự kiện:

  • sensor- loại cảm biến được lắng nghe trong event
  • accuracy- độ chính xác của cảm biến khi event xảy ra (low, medium, high, or unreliable)
  • values- một mảng dữ liệu kiểu float chứa giá trị của cảm biến
  • timestamp- thời gian event xảy ra (ns).

Bạn có thể thay đổi độ chính xác của cảm biến trong method onAccuracyChanged. Độ chính xác của cảm biến được định nghĩa bằng các hằng số:

  • SensorManager.SENSOR_STATUS_ACCURACY_LOW: nhìn mặt là được hình dong ngay, đây là cấp đọ chính xác thấp của cảm biến
  • SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM: mức độ chính xác trung bình
  • SensorManager.SENSOR_STATUS_ACCURACY_HIGH: đây là mức độ chính xác cao nhất
  • SensorManager.SENSOR_STATUS_UNRELIABLE: mức độ không đáng tin cậy, cần hiệu chuẩn và không thể đọc.

Để lắng nghe event từ cảm biến, bạn cần đăng ký với Sensor Manager, bạn cần chỉ ra, lắng nghe loại cảm biến nào, tỉ lệ mà bạn muốn update.

Note: Không phải cảm biến nào cũng có mặt trên trên thiết bị, bạn cần check xem nó thiết bị đó có trang bị loại cảm biến mà bạn muốn sử dụng hay không. Bạn cũng cần trao quyền sử dụng Sensor trong manifest.

Ví dụ bên dưới hướng dẫn cách register cảm biến PROXIMITY (tiệm cận-khoảng cách):

Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
sensorManager.registerListener(mySensorEventListener,
sensor,
SensorManager.SENSOR_DELAY_NORMAL);

Trong SensorManager chứa các hằng số tỉ lệ cập nhật khi event occurs:

  • SENSOR_DELAY_FASTEST: nhìn tên là biết nó nhanh nhất dòi
  • SENSOR_DELAY_GAME: tỉ lệ được sử dụng cho điều khiển trò chơi
  • SENSOR_DELAY_NORMAL: tỉ lệ mặc định
  • SENSOR_DELAY_UI: tỉ lệ phù hợp cho UI

Tỉ lệ bạn chọn sẽ không bị ràng buộc. Sensor Manager sẽ trả về cho bạn giá trị nhanh hay chậm tùy vào bạn yêu cầu, nhưng xu hướng là nhanh. Để giảm thiểu tài nguyên sử dụng cho ứng dụng, bạn nên chọn ở mức chấp nhận được.
Một việc cũng khá quan trọng, đó là khi không lắng nghe trong thời gian dài, bạn nên unregister việc lắng nghe để tiết kiệm pin và tài nguyên.

sensorManager.unregisterListener(mySensorEventListener);

Nhớ nhé: register trong onResume() và unregister trong onPause().

Giải thích giá trị cảm biến

Độ dài và giá trị các thành phần trả về trong method onSensorChanged tùy thuộc vào loại cảm biến mà bạn giám sát.

Bạn có thể tham khảo link này để xem hướng dẫn về document của các loại cảm biến SensorEvent

Giá trị trả về khi event xảy ra là 1 mảng số thực, độ dài của mảng và đơn vị tùy thuộc vào loại cảm biến được lắng nghe.

Sử Dụng Hardware SenSor Trên Ăn-Rồi Phần 1

Có bao giờ bạn hỏi:

Khi gọi điện, bạn để điện thoại áp sát tai thì màn hình tắt không?
Khi bạn xoay màn hình ngang để xem phim, tại sao điện thoại biết bạn đang xoay màn hình ngang?
Có những chiếc điện thoại còn biết bạn đang ở độ cao bao nhiêu so với mực nước biến, sao nó biết được?
Khi để điện thoại ở độ sáng tự động, bạn ra nắng, màn hình sáng hơn bình thường, bạn vào bóng tối, màn hình dịu lại, tại sao vậy?
Khi tra cứu bản đồ, sao ứng dụng đó biết bạn đang nhìn hướng nào?

Đó chỉ một trong số những chức năng mà các cảm biến trên thiết bị di động mang lại.

Trong bài này sẽ hướng dẫn cách làm việc với những cảm biến đó:

  • Sử dụng Sensor Manager
  • Giới thiệu về các loại cảm biến trên điện thoại
  • Tìm định hướng tự nhiên của điện thoại
  • Gắn khung tham chiếu lên thiết bị
  • Giám sát và giải thích giá trị cảm biến
  • Sử dụng cảm biến để theo dõi chuyển động và định hướng thiết bị
  • Sử dụng cảm biến theo dõi mồi trường của thiết bị

1. Sử dụng và Quản Lý Sensor

Sensor Manager được sử dụng để quản lý sensor có sẵn trên thiết bị Android.
SensorManager sensorManager=(SensorManager)getSystemService(Context.SENSOR_SERVICE);
Sensor là class bao gồm tập hợp hằng số những mô tả về những cảm biến có mặt trong lớp này. Hằng số này có dạng Sensor.TYPE_.
Các loại cảm biến mà Ăn-Rồi hỗ trợ:
Sensor.TYPE_AMBIENT_TEMPERATURE: là một cái nhiệt kế sẽ trả về kết quả nhiệt độ môi trường đơn vị độ C.
Sensor.TYPE_ACCELEROMETER: là một cảm biến gia tốc 3 trục đơn vị m/s2.
Sensor.TYPE_GRAVITY: đây là 1 loại cảm biến trọng lực 3 trục.
Sensor.TYPE_LINEAR_ACCELERATION: cảm biến gia tốc tuyến tính, để phát hiện tăng tốc.
Sensor.TYPE_GYROSCOPE: cảm biến con quay hồi chuyển, kết hợp với tóc độ quay để phát hiện hướng hiện tại của thiết bị.
Sensor.TYPE_ROTATION_VECTOR: một loại cảm biến trả về giá trị là hướng của thiết bị.
Sensor.TYPE_MAGNETIC_FIELD: cảm biến từ trường.
Sensor.TYPE_PRESSURE: cảm biến áp suất, sử dụng để xác định độ cao, đo áp suất khí quyển.
Sensor.TYPE_RELATIVE_HUMIDITY: cảm biến độ ẩm
Sensor.TYPE_PROXIMITY: cảm biến khoảng cách, dùng để xác định khoảng cách của thiết bị so với đối tượng.
Sensor.TYPE_LIGHT: cảm biến ánh sáng.
Thông thường, các loại cảm biến hoạt động 1 cách độc lập với nhau, chúng đều báo cáo kết quả thu được của mình về thiết bị. Trong 1 loại cảm biến còn có nhiều cảm biến, chỉ khác nhau về tên gọi, nhà sản xuất,… điều này để kết qua đo đạt được chính xác hơn thôi, hem có gì. Trong các cảm biến cùng loại, Android sẽ chọn cảm biến có kết quả tốt nhất để làm mặc định.

2. Finding Sensor

Lấy danh sách tất cả các loại cảm biến:
List allSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
Lấy danh sách của 1 loại cảm biến cụ thể, ví dụ:
List gyroscopes = sensorManager.getSensorList(Sensor.TYPE_GYROSCOPE);
Nếu có nhiều cảm biến trong cùng 1 loại, bạn có thể quyết định cảm biến nào được sử dụng. Mỗi loại cảm biến sẽ bao gồm: tên, năng lượng sử dụng, độ trễ tối thiểu, tầm đo tối đa, độ phân giải, nhà sản xuất.
Bạn có thể lấy cảm biến mặc định cho mỗi loại bằng cách:
Sensor defaultBarometer = sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);
Nếu kết quả trả về null, nghĩa là thiết bị không có hỗ trợ cảm biến này.
Ví dụ dưới đây chỉ bạn làm thế nào để chọn cảm biến ánh sáng có tầm đo lớn nhất và năng lượng tiêu thụ thấp nhất:
List lightSensors
= sensorManager.getSensorList(Sensor.TYPE_LIGHT);
List gyroscopes
= sensorManager.getSensorList(Sensor.TYPE_GYROSCOPE);
Sensor bestLightSensor
= sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
Sensor correctedGyro
= sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
if (bestLightSensor != null)
for (Sensor lightSensor : lightSensors) {
float range = lightSensor.getMaximumRange();
float power = lightSensor.getPower();
if (range >= bestLightSensor.getMaximumRange())
if (power < bestLightSensor.getPower() || range > bestLightSensor.getMaximumRange())
bestLightSensor = lightSensor;
}
if (gyroscopes != null && gyroscopes.size() > 1)
correctedGyro = gyroscopes.get(gyroscopes.size()-1);

Thông thường, bộ cảm biến không lọc sẽ trả về kết quả mặc định cho người dùng. Trong trường hợp sử dụng bộ lọc sẽ cho kết quả tốt hơn.
Trong phần tiếp theo, chúng ta sẽ học cách giám sát cảm biến.

Làm Quen Với Git

Bạn đã từng khổ sở khi phải ráp code của các thành viên vào 1 project?
Bạn có 1 source code hoặc 1 project rất hay, bạn muốn chia sẻ để mọi người cùng phát triển?
Bạn muốn quản lý project trong team của mình được hiệu quả?

Bạn sẽ tìm được nhiều công cụ hỗ trợ đắc lực cho việc đó, và trong đó có Git.

Để bắt đầu thì máy tính của bạn cần cài đặt Gitbash, https://git-scm.com/downloads. Đây là một công cụ để làm việc dạng command line. Bạn cũng cần tạo 1 tài khoản trên https://github.com/. Bạn nên làm quen với command line vì nó có mặt trên cả 3 hệ điều hành phổ biến trên máy tính hiện nay là MacOS, Window, Linux. Khi bạn đã quen rồi, bạn sẽ sử dụng các phần mềm khác dễ dàng hơn.

1. Trước tiên, bạn cần vào https://github.com/, để tạo 1 repository- đây được gọi là remote repository, nơi lưu trữ source code của bạn, bạn có thể chia sẻ để mợi người cùng làm việc. Nhấn vào New Repository để tạo mới, nhập tên project, ví dụ tên project là A, check vào Initialize this repository with a README nếu bạn muốn tạo file README.md, sau đó click Create repository. Bây giờ bạn đã có 1 remote repository để lưu trữ code và chia sẻ với mọi người rồi.

2. Tiếp theo, ta sẽ clone project từ remote repository về máy tính( tức là tạo mới quan hệ giữa máy tính của bạn và remote repository). Ở đây, ta phân ra 2 trường hợp: Trường hợp bạn đã có chưa có bất kỳ source code nào và trường hợp bạn đã tạo source code rồi.

Đối với trường hợp, bạn chưa có source code: Right Click vào thư mục B-nơi bạn muốn lưu trữ. Sau đó, chọn Git Bash Here. Một cửa sổ làm việc với git sẽ hiện ra. Bây giờ, ta tiến hành cấu hình trước, bằng lệnh:
git config --global user.name "ten_cua_ban"
git config --global user.email "email_cua_ban"
Tiếp đến, các bạn sẽ clone project về máy tính, bằng lệnh:
git clone dia_chi
lệnh này sẽ tạo ra 1 folder mới có tên là A (tên project trên remote). Hoặc sử dụng lệnh:
git clone dia_chi .
( chú ý có khoảng cách và dấu “.”) lệnh này sẽ nhân bản source code trong project A về thư muc B này.
Với địa chỉ repository được lấy bằng cách vào project mà bạn tạo trên github.com, click vào Clone or download sẽ xuất hiện phần địa chỉ repository, click vào hình tờ giấy để copy địa chỉ, dán vào màn hình git bằng cách phải chuột và chọn Paste. Như vậy là bạn đã clone về máy thành công.

Trường hợp 2- khi bạn đã có project rồi: Mở project của bạn lên, right click vùng trống và chọn Git Bash Here.
Sau đó sử dụng: git init, để khởi tạo .git

Tiếp theo, chúng ta sẽ tạo mối quan hệ giữa máy tính và remote repository. Trong cửa sổ git bash here, sử dụng lệnh:

git add remote origin dia_chi

với đia chỉ được lấy tương tự như trên.

Bạn tiến hành add source code và push lên remote repository.

git add .

để add tất cả các file có trong folder hiện tại, hoặc:

git add ten_file

để add file được chỉ định.

Tiếp theo bạn sẽ đẩy nhưng thay đổi này vào local, bằng lệnh:

git commit -m"Noi_dung_commit"

Hiện tại, source code của bạn vẫn còn nằm ở máy tính, chưa có trên repository. Bạn sẽ đẩy nó lên remote bằng lệnh:

git push

Bạn đợi một chút cho câu lệnh chạy xong, bạn quan sát trên remote repository sẽ thấy source code của bạn trên đấy.
Lưu ý: Lần đầu tiên sử dụng gitbash sẽ cần đăng nhập nhé!

Trong phần hướng dẫn sau, tôi sẽ hướng dẫn cách làm việc nhóm trên github.