Lập trình giao diện và giao tiếp với vi điều khiển nếu mới bắt đầu quả là rất khó khăn, nhưng với processing thì việc đấy trở nên đơn giản hơn bao giờ hết. Như các bài trước chúng ta đã điều khiển LED qua nút nhấn, ADC và Serial với Tiva rồi, giờ chuyển sang lập trình giao diện và điều khiển qua lại giữa TIVA và Processing thôi.

Bạn có thể tải Processing bản mới nhất tại Processing Download

Dimer LED với Processing

Trong ví dụ này mình sẽ thực hiện điều khiển dimmer LED (hay còn gọi là điều khiển độ sáng LED) thông qua một giao diện đơn giản từ processing và con trỏ chuột

Code Energia

/*
  Dimmer LED
  
  Chương trình giao tiếp với processing, tạo ra giao diện, đưa chuột lên
  giao diện để tăng độ sáng tối cho LED
  Mạch điện:
  LED xanh lam nối với chân 40.
  created 2006
  by David A. Mellis
  modified 30 Aug 2011
  by Tom Igoe and Scott Fitzgerald
  Modified 15 April 2013
  By Sean Alvarado
  Hardware Required:
  * TIVA C LaunchPad
  * LED xanh
  
  This example code is in the public domain.
*/

const int ledPin = 40; // chân 40 nối với LED xanh

void setup()
{
  // Cấu hình giao tiếp baud 9600
  Serial.begin(9600);
  // cấu hình LED output
  pinMode(ledPin, OUTPUT);
}

void loop() {
  byte brightness;

  // Kiểm tra nếu có dữ liệu gửi từ máy tính:
  if (Serial.available()) {
    // Đọc giá trị hiện tại lưu vào biến brightness
    brightness = Serial.read();
    // Điều khiển độ sáng led bằng PWM
    analogWrite(ledPin, brightness);
  }
}

Code Processing

// Processing code
// Dimmer - gửi byte thông qua cổng serial
// by David A. Mellis
// Modified 16 April 2013
// by Sean Alvarado
// This example code is in the public domain.

import processing.serial.*;
Serial port;

void setup() {
  size(256, 150);

  println("Available serial ports:");
  println(Serial.list());

  // Khai báo cổng kết nối, thông số và tốc độ baud tương ứng với
  // thông số trong chương trình của Energia
  // Lệnh này sẽ tự tìm serial TIVA và kết nối
  port = new Serial(this, Serial.list()[0], 9600); 

  // Nếu bạn biết được port của kit TIVA là COM mấy thì có thể
  // cấu hình trực tiếp bằng lệnh sau
  //port = new Serial(this, "COM1", 9600);
}

void draw() {
  // Vẽ gradient màu đen sang trắng
  for (int i = 0; i < 256; i++) {
    stroke(i);
    line(i, 0, i, 150);
  }

  // Lấy vị trí tọa độ X hiện tại của chuột máy tính
  // sau đó gửi byte này qua cổng COM
  port.write(mouseX);
}

Kết quả khi ta đưa chuột như hình thì độ sáng của đèn sẽ thay đổi

Biến trở và Processing hiển thị màu

Ở ví dụ này ta sẽ sử dụng 3 biến trở cấp nguồn 3v3, chân còn lại nối với chân A0 A1 A2 của kit TIVA, yêu cầu là khi xoay biến trở thì giao diện được tạo từ processing sẽ đổi màu sắc dựa theo các giá trị từ biến trở.

/*
  This example reads three analog sensors (potentiometers are easiest)
  and sends their values serially. The Processing code at the bottom
  take those three values and use them to change the background color of the screen.
  Mạch điện:
  * 3 Biến trở nối với 3v3
  * Các chân out của biến trở nối lần lượt với chân A0 A1 A2 của kit TIVA
  created 2 Dec 2006
  by David A. Mellis
  modified 30 Aug 2011
  by Tom Igoe and Scott Fitzgerald
  modified 16 April 2013
  by Sean Alvarado
  
  Yêu cầu phần cứng:
  * TIVA C LaunchPad
  * (3) biến trở
  * breadboard
  * dây nối
  This example code is in the public domain.
*/

const int redPin = A0;  // Biến trở điều khiển màu đỏ
const int greenPin = A1; // Biến trở điều khiển màu xanh lá
const int bluePin = A2; // Biến trở điều khiển màu xanh lam

void setup()
{
  // Cấu hình Serial baud 9600
  Serial.begin(9600);
}

void loop()
{
  //Gửi các giá trị lên processing
  Serial.print(analogRead(redPin));
  Serial.print(",");
  Serial.print(analogRead(greenPin));
  Serial.print(",");
  Serial.println(analogRead(bluePin));
}
// Processing code for this example

// This example code is in the public domain.

import processing.serial.*;

float redValue = 0; // Giá trị LED đỏ
float greenValue = 0; // Giá trị LED xanh lá
float blueValue = 0; // Giá trị LED xanh lam

Serial myPort;

void setup() {
  size(200, 200);

  // Liệt kê danh sách các cổng COM kết nối
  println(Serial.list());

  // Mở COM của TIVA LaunchPad
  myPort = new Serial(this, Serial.list()[0], 9600);

  // Nếu không có Enter(chọn newline) từ người dùng thì không nhận dữ liệu
  myPort.bufferUntil('\n');
}

void draw() {
  // Tạo background với các màu sắc:
  background(redValue, greenValue, blueValue);
}

void serialEvent(Serial myPort) { 
  // Nhận chuỗi mã:
  String inString = myPort.readStringUntil('\n');

  if (inString != null) {
    // Cắt bỏ các khoảng trắng:
    inString = trim(inString);
    // Cắt chuỗi bởi các dấu phẩy và chuyển sang mảng integer
  float[] colors = float(split(inString, ","));
  // Nếu mảng có ít nhất 3 phần tử thì đã nhận được hết dữ liệu sau đó
  // đưa các số nhận được vào các biến màu sắc:
  if (colors.length >=3) {
    // map các giá trị với ngưỡng 0-255:
    redValue = map(colors[0], 0, 4096, 0, 255);
    greenValue = map(colors[1], 0, 4096, 0, 255);
    blueValue = map(colors[2], 0, 4096, 0, 255);
    }
  }
}

Kết quả ta sẽ thấy màu sắc thay đổi khi xoay các biến trở

Nút nhấn, biến trở và Processing

Tận dụng số biến trở ở bài ví dụ trước, chúng ta sẽ tạo ra một số chuyển động đơn giản với hình tròn, như xoay biến trở thì hình tròn dịch chuyển sang trái, sang phải, đi lên, đi xuống, ngoài ra còn có thể thay đổi màu sắc của hình tròn bằng 1 biến trở khác.

Về nguyên tắc hoạt động mình xin tóm tắt như sau:

  • TIVA sẽ gửi 1 request tới Processing là kí tự A
  • Processing nhận được yêu cầu sẽ gửi ngược lại TIVA kí tự A, đây gọi là quá trình bắt tay
  • TIVA nhận được kí tự A từ Processing gửi thì kết thúc quá trình bắt tay, sau đó gửi dữ liệu lên có dạng [x,y,color] tương ứng với 3 giá trị đọc được từ biến trở. Dữ liệu này sẽ được lưu trong mảng 3 phần tử.
  • Processing nhận dữ liệu và show hình ảnh và chuyển động cho chúng ta quan sát.
/*
  Gửi và nhận dữ liệu qua Serial
  Chương trình sẽ gửi kí tự A liên tục cho đến khi nhận được phản hồi
  sau đó sẽ thực nhiện nhận dữ liệu, kiểm tra nếu có đủ 3 dữ liệu từ 
  biến trở thì dừng lại.
  
  Thanks to Greg Shakar and Scott Fitzgerald for the improvements
  Mạch điện:
  * 3 biến trở nối với chân A0 A1 A2
  * Biến trở nối nguồn 3v3
  Created 26 Sept. 2005
  by Tom Igoe
  modified 24 April 2012
  by Tom Igoe and Scott Fitzgerald
  Modified 19 April 2013
  By Sean Alvarado
  
  Hardware Required:
  * TIVA C LaunchPad
  * (3) biến trở
  * breadboard
  * dây nối
  This example code is in the public domain.
*/
int firstSensor = 0; // giá trị biến trở 1
int secondSensor = 0; // giá trị biến trở 2
int thirdSensor = 0; // giá trị biến trở 3
int inByte = 0; // biến lưu byte dữ liệu

void setup()
{
  // Cấu hình serial baud 9600
  Serial.begin(9600);
  establishContact(); // Gửi dữ liệu bắt tay và chờ phản hồi.
}

void loop()
{
  // Nếu có dữ liệu yêu cầu thì bắt đầu đọc dữ liệu từ các biến trở:
  if (Serial.available() > 0) {
    // Nhận dữ liệu:
    inByte = Serial.read();
    // Đọc giá trị ADC(4096) và chia cho 16 để ra ngưỡng từ 0-255:
    firstSensor = analogRead(A0)/16;
    // delay 10ms để thực hiện chuyển đổi
    delay(10);
    // Đọc giá trị ADC(4096) và chia cho 16 để ra ngưỡng từ 0-255:
    secondSensor = analogRead(A1)/16;
    delay(10);
    // Đọc giá trị ADC(4096) và chia cho 16 để ra ngưỡng từ 0-255:
    thirdSensor = analogRead(A2)/16;
    delay(10); 
    // Gửi các giá trị cảm biến:
    Serial.write(firstSensor);
    Serial.write(secondSensor);
    Serial.write(thirdSensor); 
  }
}

void establishContact() {
  while (Serial.available() <= 0) {
    Serial.println('A'); // gửi kí tự A
    delay(300);
  }
}
// Chương trình Processing điều khiển chấm tròn dùng 3 biến trở 

// This example code is in the public domain.

import processing.serial.*;

int bgcolor; // Màu nền Background 
int fgcolor; // Màu cho hình tròn
Serial myPort; // Cổng serial
int[] serialInArray = new int[3]; // Mảng lưu các giá trị nhận được
int serialCount = 0; // Biến đếm bao nhiêu byte nhận
int xpos, ypos; // Tọa độ Vị trí của hình tròn
boolean firstContact = false; // Thiết lập ban đầu chưa có bắt tay với TIVA

void setup() {
  size(256, 256); // Khai báo kích thước
  noStroke(); // Không tạo biên trên hình vẽ kế tiếp

  // Đặt vị trí ban đầu của hình tròn là ở giữa
  xpos = width/2;
  ypos = height/2;

  // In ra cổng COM kết nối để debug:
  println(Serial.list());
  // Tự kết nối COM TIVA
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, 9600);
}

void draw() {
  background(bgcolor);
  fill(fgcolor);
  // Vẽ hình tròn
  ellipse(xpos, ypos, 20, 20);
}

void serialEvent(Serial myPort) {
  // Nhận byte gửi từ TIVA:
  int inByte = myPort.read();
  // Nếu byte đầu tiên nhận được là A thì xóa hết buffer
  // ngược lại thì nhận dữ liệu từ các biến trở.
  if (firstContact == false) {
    if (inByte == 'A') { 
      myPort.clear(); // Xóa buffer
      firstContact = true; // Set cờ kết nối, đã thực hiện bắt tay với TIVA
      myPort.write('A'); // Yêu cầu dữ liệu
    } 
  } 
  else {
    // Lưu các dữ liệu nhận được vào mảng:
    serialInArray[serialCount] = inByte;
    serialCount++;

    // Kiểm tra nếu có 3 bytes:
    if (serialCount > 2 ) {
      xpos = serialInArray[0];
      ypos = serialInArray[1];
      fgcolor = serialInArray[2];

      // In các giá trị này ra để debug:
      println(xpos + "\t" + ypos + "\t" + fgcolor);

      // Gửi A để yêu cầu dữ liệu mới:
      myPort.write('A');
     // Reset lại biến serialCount:
     serialCount = 0;
    }
  }
}

Kết quả sau khi vặn từng biến trở ta sẽ thấy hình tròn di chuyển theo trục x, trục y, và màu sắc thay đổi dần từ đen về trắng

Lưu ý: Độ phân giải ADC của TIVA là 12 bit tương ứng với giá trị là 4096
Các chương trình Energia và TIVA bạn chỉ cần copy và run chạy thử nghiệm luôn cho nóng, nhưng cố gắng hiểu và nắm được code để ứng dụng các bạn nhé.

Tạm kết

Chào mừng năm mới bằng bài hướng dẫn giao tiếp giữa TIVA và máy tính thông qua Energia và Processing, chưa bao giờ lập trình giao diện và giao tiếp máy tính lại đơn giản đến thế, hi vọng các bạn sẽ có nguồn tham khảo để ứng dụng vào trong các dự án cá nhân.

Mình sẽ cập nhật một số hướng dẫn các hàm vẽ vời thông dụng trong Processing cho các bạn sớm.