Skip to main content

Arduino + ILI9486 觸控螢幕 code


#include <TouchScreen.h> //touch library
#include <LCDWIKI_GUI.h> //Core graphics library
#include <LCDWIKI_KBV.h> //Hardware-specific library

LCDWIKI_KBV my_lcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset

/* r g b */
#define BLACK 0x0000 /* 0, 0, 0 */
#define BLUE 0x001F /* 0, 0, 255 */
#define RED 0xF800 /* 255, 0, 0 */
#define GREEN 0x07E0 /* 0, 255, 0 */
#define CYAN 0x07FF /* 0, 255, 255 */
#define MAGENTA 0xF81F /* 255, 0, 255 */
#define YELLOW 0xFFE0 /* 255, 255, 0 */
#define WHITE 0xFFFF /* 255, 255, 255 */
#define NAVY 0x000F /* 0, 0, 128 */
#define DARKGREEN 0x03E0 /* 0, 128, 0 */
#define DARKCYAN 0x03EF /* 0, 128, 128 */
#define MAROON 0x7800 /* 128, 0, 0 */
#define PURPLE 0x780F /* 128, 0, 128 */
#define OLIVE 0x7BE0 /* 128, 128, 0 */
#define LIGHTGREY 0xC618 /* 192, 192, 192 */
#define DARKGREY 0x7BEF /* 128, 128, 128 */
#define ORANGE 0xFD20 /* 255, 165, 0 */
#define GREENYELLOW 0xAFE5 /* 173, 255, 47 */
#define PINK 0xF81F /* 255, 0, 255 */

/******************* UI details */
#define BUTTON_R 35 //the radius of button
#define BUTTON_SPACING_X 35 //the horizontal distance between button
#define BUTTON_SPACING_Y 10 //the vertical distance between button
#define EDG_Y 10 //lower edge distance
#define EDG_X 20 //left and right distance

#define YP A3 // must be an analog pin, use "An" notation!
#define XM A2 // must be an analog pin, use "An" notation!
#define YM 9 // can be a digital pin
#define XP 8 // can be a digital pin

//touch sensitivity for X
#define TS_MINX 906
#define TS_MAXX 116

//touch sensitivity for Y
#define TS_MINY 92
#define TS_MAXY 952

// We have a status line for like, is FONA working
#define STATUS_X 10
#define STATUS_Y 65

//touch sensitivity for press
#define MINPRESSURE 10
#define MAXPRESSURE 1000

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

int light_state[4] = {0, 0, 0, 0};
bool is_shooting = false;
unsigned long shooting_start = 10e6;
int prev_second = -3000;
const int light_pins[4] = {35, 37, 39, 41};
const int N_BUTTONS = 7;
const int N_LIGHTS = 4;

typedef struct _button_info
{
String button_name;
uint8_t button_name_size;
uint16_t font_color;
uint16_t button_color;
uint16_t button_x;
uint16_t button_y;
}button_info;

button_info buttons[7] = {
"A", 4, RED, WHITE, 25, 40,
"B", 4, RED, WHITE, 145, 40,
"C", 4, RED, WHITE, 265, 40,
"D", 4, RED, WHITE, 385, 40,

"OP", 4, RED, GREEN, 25, 180,
"CL", 4, RED, GREEN, 145, 180,

"S", 4, WHITE, RED, 265, 180,
};

void draw_button(String str, uint16_t x, uint16_t y, uint16_t font_color, uint16_t background_color, bool active){
if(active){
my_lcd.Set_Draw_color(YELLOW);
my_lcd.Fill_Rect(x, y, 80, 80, YELLOW);
}else{
my_lcd.Set_Draw_color(WHITE);
my_lcd.Fill_Rect(x, y, 80, 80, background_color);
}

my_lcd.Set_Text_Mode(1);
my_lcd.Set_Text_Size(5);
my_lcd.Set_Text_colour(font_color);
my_lcd.Print_String(str, x+15, y+15);
}

int detect_press(uint16_t x, uint16_t y){
for(int i=0; i<N_BUTTONS; i++){
if(
(x >= (buttons[i].button_x-5) && x <= (buttons[i].button_x + 85)) &&
(y >= (buttons[i].button_y-5) && y <= (buttons[i].button_y + 85))
){
return i;
}
}
return -1;
}

void set_light_state(int i, int state){
digitalWrite(light_pins[i], state);

if(light_state[i] != state){
draw_button(buttons[i].button_name, buttons[i].button_x, buttons[i].button_y, buttons[i].font_color, buttons[i].button_color, state);
}
light_state[i] = state;
}

void setup(void)
{
Serial.begin(9600);
my_lcd.Init_LCD();
Serial.println(my_lcd.Read_ID(), HEX);
my_lcd.Fill_Screen(BLACK);
my_lcd.Set_Rotation(1);

for(int i=0; i<N_LIGHTS; i++){
pinMode(light_pins[i], OUTPUT);
}

for(int i=0; i<N_BUTTONS; i++){
my_lcd.Set_Draw_color(BLUE);
my_lcd.Fill_Rect(buttons[i].button_x+2, buttons[i].button_y+2, 80, 80, BLUE);
draw_button(buttons[i].button_name, buttons[i].button_x, buttons[i].button_y, buttons[i].font_color, buttons[i].button_color, false);
}
}

void loop(void)
{
digitalWrite(13, HIGH);
TSPoint p = ts.getPoint();
digitalWrite(13, LOW);

pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
if (p.z > MINPRESSURE && p.z < MAXPRESSURE)
{

p.x = map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(),0) - 10;
p.y = int(1.05 * (310 - map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(),0)));

Serial.print(p.x);Serial.print(", ");Serial.print(p.y);Serial.print("\n");

int press = detect_press(p.x, p.y);
if (press >= 0){
Serial.println(press);
}

if (press == -1){
// do nothing
}else if((press >= 0 && press <= 3) && !is_shooting){
set_light_state(press, !light_state[press]);
}else if(press == 4){
// all open
for(int i=0; i<N_LIGHTS; i++){
set_light_state(i, HIGH);
}
is_shooting = false;
draw_button("", 385, 180, BLACK, BLACK, false);
}else if(press == 5){
// all close
for(int i=0; i<N_LIGHTS; i++){
set_light_state(i, LOW);
}
is_shooting = false;
draw_button("", 385, 180, BLACK, BLACK, false);
}else if(press == 6){
// shooting
is_shooting = true;
shooting_start = millis();
}
delay(300);
}


if(is_shooting){
unsigned long now = millis();

// counting
if (int((now-shooting_start)/1000)-3 != prev_second){
draw_button(String(int((now-shooting_start)/1000)-3), 385, 180, RED, BLACK, false);
prev_second = int((now-shooting_start)/1000)-3;
}

if(now - shooting_start < 3000){
for(int i=0; i<N_LIGHTS; i++){
set_light_state(i, LOW);
}
}else if(now - shooting_start < 6000){
set_light_state(0, HIGH);
}else if(now - shooting_start < 8000){
set_light_state(0, LOW);
}else if(now - shooting_start < 11000){
set_light_state(0, HIGH);
}else if(now - shooting_start < 13000){
set_light_state(0, LOW);
}else if(now - shooting_start < 16000){
set_light_state(0, HIGH);
}else if(now - shooting_start < 18000){
set_light_state(0, LOW);
}else if(now - shooting_start < 21000){
set_light_state(0, HIGH);
}else if(now - shooting_start < 23000){
set_light_state(0, LOW);
}else if(now - shooting_start < 26000){
set_light_state(0, HIGH);
}else if(now - shooting_start < 29000){
set_light_state(0, LOW);
}else{
is_shooting = false;
shooting_start = 10e6;
set_light_state(0, LOW);
set_light_state(1, HIGH);
set_light_state(2, HIGH);
set_light_state(3, HIGH);
draw_button(String(int((now-shooting_start)/1000)), 385, 180, BLACK, BLACK, false);
}
}
}

LCD 顯示

  • my_lcd.Fill_Screen(BLACK)
  • my_lcd.Set_Rotation(1)

畫按鈕

// 畫背景
my_lcd.Set_Draw_color(WHITE);
my_lcd.Fill_Rect(x, y, 80, 80, background_color);

// 寫字
my_lcd.Set_Text_Mode(1);
my_lcd.Set_Text_Size(5);
my_lcd.Set_Text_colour(font_color);
my_lcd.Print_String(str, x+15, y+15);

讀取觸控

TSPoint p = ts.getPoint();
digitalWrite(13, LOW);

pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
if (p.z > MINPRESSURE && p.z < MAXPRESSURE)
{

p.x = map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(),0) - 10;
p.y = int(1.05 * (310 - map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(),0)));

}

要先測試一下按的點和讀取到的 x,y 有沒有對應,要做一點縮放(在某個範例程式找到的 code)。

p.x = map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(),0) - 10;
p.y = int(1.05 * (310 - map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(),0)));

計時

Arduino loop():不能用 delay() 計時,delay的時候程式會暫停,要使用 millis() 讀取時間來做計時