W artykule zostanie przedstawione menu do wyświetlacza dotykowego za pomocą którego jest możliwość odczytywania aktualnych wartości z wagi (belki tensometrycznej). Na wyświetlaczu również można ustawić wartość do jakiej ma zostać obciążona waga (np. jakimś płynem w połączeniu z pompą).


Spis treści
- Wykorzystane komponenty
- Wstęp
- Zaprogramowanie
- Pliki do pobrania
Wykorzystane komponenty
- Arduino Mega
- Dotykowy Wyświetlacz LCD TFT przekątna 3.2″
Wstęp
Program jak i wyświetlacz można wykorzystać w różnych projektach z wagą, posiada on 3 funkcje: pierwsza to pokazywanie aktualnego obciążenia na wadze, druga to możliwość ustawienia gramów do którego momentu ma zostać obciążona, a trzecia to tarowanie. Po naciśnięciu wyświetlacza w miejscu ustaw wagę, wyświetli się klawiatura na której będziemy mogli wpisać interesującą nas wartość. Program posiada również zabezpieczenie i więcej niż 4 liczby nie wpiszemy. Wszystkie te funkcje można zmodyfikować pod swój projekt albo dodać własne. Niezbędna do zaprogramowania wyświetlacza będzie tutaj wiedza z tego artykułu https://ajmaker.pl/2022/01/20/dotykowe-ekran-lcd-3-2-wykorzystanie-w-praktyce/.
Zaprogramowanie
Na początku deklarujemy wszystkie potrzebne zmienne, definicje, biblioteki oraz najważniejsze ustawienia w funkcji setup.
#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>
#include <TouchScreen.h>
MCUFRIEND_kbv tft; // Stworzenie obiektu pełniącego rolę wyświetlacza
/* Zmienne do obsługi ekranu dotykowego */
uint8_t YP = A1;
uint8_t XM = A2;
uint8_t YM = 7;
uint8_t XP = 6;
/* --------------------------------- */
int16_t BOXSIZE; // zainicjowanie zmiennej służącej nam do tworzenia przycisków
/* Definicja poszczególnym boków ekranu */
uint16_t TS_LEFT = 880;
uint16_t TS_RT = 170;
uint16_t TS_TOP = 950;
uint16_t TS_BOT = 180;
/* --------------------------------- */
#define MINPRESSURE 20 // Minimalna wartość jaką może odczytać program aby uznać, że dotknęliśmy ekranu
#define MAXPRESSURE 500 // Maksymalna wartość jaką może odczytać program aby uznać, że dotknęliśmy ekranu
#define PWM 3
#define IN1 2
#define IN2 5
/* --------------------------------- */
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 250); // Stworzenie obiektu pełniącego rolę ekranu dotykowego
TSPoint tp; // Stworzenie obiektu do ustalania aktualnego punktu na ekranie
/* przypisanie do nazw kolorów odpowiadających im wartości w systemie szesnastkowym*/
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
bool mieszanie = true; //zmienna do silnika
bool pompa = true; //zmienna do pomy
int obroty = 100; //obroty silnika
int value = 255; //wartosc obrotow
bool menu_mierzenie = false; //menu do wazenia
int num_count_A = 0; //liczba wpisanych liczb w menu wagi A
int num_count_B = 0; //liczba wpisanych liczb w menu wagi B
bool wazenie = true; //zadeklarowanie zmiennej wazenie
int once = 0; //zadeklarowanie zmiennej oncet
unsigned long ustawgramy_A = 0; //ustawione gramy wagi A
unsigned long last_number_A = 0; //poprzedni numer wpisany w funkcji ustawGramy()
bool ustaw_wage_A = false; //menu do ustawiania wagi A
unsigned long ustawgramy_B = 0; //ustawione gramy wagi B
unsigned long last_number_B = 0; //poprzedni numer wpisany w funkcji ustawGramy()
bool ustaw_wage_B = false; //menu do ustawiania wagi B
void setup() {
Serial.begin(9600); // Rozpoczęcie transmisji szeregowej
pinMode(PWM, OUTPUT); //ustawienie PWM jako wyjście
pinMode(IN1, OUTPUT); //ustawienie IN1 jako wyjście
pinMode(IN2, OUTPUT); //ustawienie IN2 jako wyjście
analogWrite(PWM, 0); //ustawienie prędkości obrotów
digitalWrite(IN1, LOW); //ustawienie stanu niskiego na IN1
digitalWrite(IN2, LOW); //ustawienie stanu niskiego na IN2
tft.begin(0x9327); // Rozpoczęcie pracy ekranu o id 0x9327 ( odpowiada naszemu modelowi ekranu)
tft.fillScreen(BLACK); // Wypełnienie ekranu kolorem czarnym
tft.setRotation(1); // ustawienie rotacji ekranu na poziomą
tft.setTextColor(WHITE); // Ustawienie koloru tekstu na czarny
BOXSIZE = tft.height() / 3;
menuWazenie(); // wyświetl menu ważenie
}Teraz zajmiemy się główną funkcją loop, na początek standardowe ustawienia wyświetlacza oraz niezbędny if.
void loop() {
uint16_t xpos, ypos; // inicjacja zmiennych służących do ustalenia składowych x i y pozycji kursora
tp = ts.getPoint(); // przypisanie do zmiennej tp aktualnego punktu na ekranie
/*ustawienie na wyjście pinów służących do obsługi ekranu dotykowego*/
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
pinMode(XP, OUTPUT);
pinMode(YM, OUTPUT);
/* --------------------------------- */
if (tp.z > MINPRESSURE && tp.z < MAXPRESSURE) { // sprawdzanie czy punkt znajduje się w granicach ustalonych na początku programu
xpos = map(tp.x, TS_LEFT, TS_RT, 0, tft.width()); // rozdzielenie zmiennej tp na składową x poprzez funkcję mapowania
ypos = map(tp.y, TS_TOP, TS_BOT, 0, tft.height()); // rozdzielenie zmiennej tp na składową y poprzez funkcję mapowania
Teraz pozostałe instrukcje warunkowe, które określą gdzie aktualnie dotykamy ekran i przypisujemy do nich odpowiednie działanie.
if (xpos > 240) // jeżeli składowa x punktu jest większa od 240, czyli znajdujemy się w pierwszym wierszu
{
if (ypos > 144 && ypos < 192) // jeżeli składowa y punktu jest większa od 144 i mniejsza od 188, czyli znajdujemy się w obszarze przycisku mieszanie
{
once = 0; //wyzerowanie zmiennej once
ustaw_wage_A = true; //ustaw zmienną ustaw_wage_A na true
while (ustaw_wage_A) // do póki ustaw_wage_A prawda, wykonuj pentle
{
if (once < 1) // jeżeli zmienna once mniejsza od 1 wykonaj poniższe instrukcje
{
klawiatura(ustawgramy_A); //wywołanie funkcji klawiatury
once++; //dodaj 1 do zmiennej once
}
tp = ts.getPoint(); // przypisanie do zmiennej tp aktualnego punktu na ekranie
/*ustawienie na wyjście pinów służących do obsługi ekranu dotykowego*/
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
pinMode(XP, OUTPUT);
pinMode(YM, OUTPUT);
/* --------------------------------- */
if (tp.z > MINPRESSURE && tp.z < MAXPRESSURE) { // sprawdzanie czy punkt znajduje się w granicach ustalonych na początku programu
xpos = map(tp.x, TS_LEFT, TS_RT, 0, tft.width()); // rozdzielenie zmiennej tp na składową x poprzez funkcję mapowania
ypos = map(tp.y, TS_TOP, TS_BOT, 0, tft.height()); // rozdzielenie zmiennej tp na składową y poprzez funkcję mapowania
if (num_count_A < 1) // jeżeli zmienna once mniejsza od 1 wykonaj poniższe instrukcje
{
tft.setCursor(22, 30); //ustawienie kursora
tft.setTextColor(WHITE, BLACK); //zmiana koloru tekstu
}
wpiszGramy(xpos, ypos); //wyświetl menu z ważeniem
}
}
menuWazenie(); //wyświetl menu z ważeniem
}
else if (ypos > 192 && ypos < 240)
{
Serial.println("taruj wage A");
//tutaj będzie tarowanie wagi A
}
}
else if (xpos > 120 && xpos < 240)
{
if (ypos > 144 && ypos < 192) // jeżeli składowa y punktu jest większa od 144 i mniejsza od 188, czyli znajdujemy się w obszarze przycisku mieszanie
{
once = 0; //wyzerowanie zmiennej once
ustaw_wage_B = true; //ustaw zmienną ustaw_wage_B na true
while (ustaw_wage_B) // do póki ustaw_wage_B prawda, wykonuj pentle
{
if (once < 1) // jeżeli zmienna once mniejsza od 1 wykonaj poniższe instrukcje
{
klawiatura(ustawgramy_B); //wywołanie funkcji klawiatury
once++; //dodaj 1 do zmiennej once
}
tp = ts.getPoint(); // przypisanie do zmiennej tp aktualnego punktu na ekranie
/*ustawienie na wyjście pinów służących do obsługi ekranu dotykowego*/
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
pinMode(XP, OUTPUT);
pinMode(YM, OUTPUT);
/* --------------------------------- */
if (tp.z > MINPRESSURE && tp.z < MAXPRESSURE) { // sprawdzanie czy punkt znajduje się w granicach ustalonych na początku programu
xpos = map(tp.x, TS_LEFT, TS_RT, 0, tft.width()); // rozdzielenie zmiennej tp na składową x poprzez funkcję mapowania
ypos = map(tp.y, TS_TOP, TS_BOT, 0, tft.height()); // rozdzielenie zmiennej tp na składową y poprzez funkcję mapowania
if (num_count_B < 1)
{
tft.setCursor(22, 30); //ustawienie kursora
tft.setTextColor(WHITE, BLACK); //zmiana koloru tekstu
}
wpiszGramy(xpos, ypos); //wywołanie funkcji wpiszGramy
}
}
menuWazenie(); //wyświetl menu z ważeniem
}
else if (ypos > 192 && ypos < 240)
{
Serial.println("taruj wage B");
//tutaj będzie tarowanie wagi B
}
}
}
}Z głównego programu byłoby na tyle, ale zostały jeszcze wykorzystane w nim funkcje. Pierwsza z nich ustawGramy() odpowiada za łączenie wpisywanych liczb z wyświetlacza, wyświetlanie liczby i wysyłanie jej do odpowiedniej zmiennej. Zależy to od tego czy korzystamy z menu A czy B. Funkcja posiada jeden argument w którym przyjmowana jest aktualnie wciskana liczba na wyświetlaczu.
void ustawGramy(int l)
{
if (ustaw_wage_A)
{
if (num_count_A > 0 && num_count_A < 4) //jeżeli ilość liczb jest większa od zera i mniejsza od 4 wykonaj poniższe instrukcje
{
ustawgramy_A = last_number_A * 10 + l; //pomnożenie ostatniej liczby przez 10 i dodanie liczby, która została wybrana
last_number_A = ustawgramy_A; //przypisanie gramów jako ostatnia liczba
}
else if (num_count_A < 1) //jeżeli ilość liczb jest mniejszy od 1 wykonaj poniższe instrukcje
{
ustawgramy_A = l; //ustawienie gramów wagi A
last_number_A = ustawgramy_A; //przypisanie gramów jako ostatnia liczba
}
num_count_A++; //zwiększenie ilości numerów
tft.setCursor(22, 30); //ustawienie pozycji kursora
tft.print(ustawgramy_A); //wyświetlenie tekstu
}
else
{
if (num_count_B > 0 && num_count_B < 4) //jeżeli ilość liczb jest większa od zera i mniejsza od 4 wykonaj poniższe instrukcje
{
ustawgramy_B = last_number_B * 10 + l; //pomnożenie ostatniej liczby przez 10 i dodanie liczby, która została wybrana
last_number_B = ustawgramy_B; //przypisanie gramów jako ostatnia liczba
}
else if (num_count_B < 1) //jeżeli ilość liczb jest mniejszy od 1 wykonaj poniższe instrukcje
{
ustawgramy_B = l; //ustawienie gramów wagi B
last_number_B = ustawgramy_B; //przypisanie gramów jako ostatnia liczba
}
num_count_B++; //zwiększenie ilości numerów
tft.setCursor(22, 30); //ustawienie pozycji kursora
tft.print(ustawgramy_B); //wyświetlenie tekstu
}
}Kolejna funkcja menuWazenie wyświetla całe menu.
void menuWazenie()
{
tft.fillScreen(BLACK); //wypełnij wyświetlacz czarnym kolorem
tft.setTextColor(WHITE); //ustaw kolor tekstu na biały
//pierwsza kolumna
tft.setTextSize(1); //ustawienie rozmiaru tekstu
tft.setCursor(10, 35); //ustawienie pozycji kursora
tft.print("WAGA A"); //wyświetlenie tekstu
tft.setCursor(10, 115); //ustawienie pozycji kursora
tft.print("WAGA B"); //wyświetlenie tekstu
tft.setCursor(10, 195); //ustawienie pozycji kursora
//pierwszy wiersz
tft.setCursor(345, 55); //ustawienie pozycji kursora
tft.print("TARUJ"); //wyświetlenie tekstu
tft.setCursor(250, 55); //ustawienie pozycji kursora
tft.print("USTAW WAGE"); //wyświetlenie tekstu
tft.setTextColor(WHITE); //ustawienie koloru tekstu
tft.setCursor(159, 55); //ustawienie pozycji kursora
tft.print("AKT. WAGA"); //wyświetlenie tekstu
tft.setTextSize(2); //ustawienie rozmiaru tekstu
tft.setCursor(355, 25); //ustawienie pozycji kursora
tft.print("X"); //wyświetlenie tekstu
tft.setCursor(255, 25); //ustawienie pozycji kursora
tft.print(ustawgramy_A); //wyświetlenie tekstu
tft.print("g"); //wyświetlenie tekstu
tft.setCursor(180, 25); //ustawienie pozycji kursora
tft.print("0"); //wyświetlenie tekstu
//drugi wiersz
tft.setTextSize(1); //ustawienie rozmiaru tekstu
tft.setCursor(345, 130); //ustawienie pozycji kursora
tft.print("TARUJ"); //wyświetlenie tekstu
tft.setCursor(250, 130); //ustawienie pozycji kursora
tft.print("USTAW WAGE"); //wyświetlenie tekstu
tft.setTextColor(WHITE); //ustawienie koloru tekstu
tft.setCursor(159, 130); //ustawienie pozycji kursora
tft.print("AKT. WAGA"); //wyświetlenie tekstu
tft.setTextSize(2); //ustawienie rozmiaru tekstu
tft.setCursor(355, 100); //ustawienie pozycji kursora
tft.print("X"); //wyświetlenie tekstu
tft.setCursor(255, 100); //ustawienie pozycji kursora
tft.print(ustawgramy_B); //wyświetlenie tekstu
tft.print("g"); //wyświetlenie tekstu
tft.setCursor(180, 100); //ustawienie pozycji kursora
tft.print("0"); //wyświetlenie tekstu
}Funkcja klawiatura, wyświetla całą klawiaturę wraz z ustawionymi gramami. Przyjmuje ona jeden argument i wyświetla aktualnie ustawione gramy.
void klawiatura(int g)
{
tft.fillScreen(BLACK); //wypełnij wyświetlacz czarnym kolorem
tft.setTextColor(WHITE); //ustaw kolor tekstu na biały
tft.setTextSize(3); //ustawienie rozmiaru tekstu
tft.setCursor(22, 30); //ustawienie pozycji kursora
tft.print(g); //wyświetlenie tekstu
tft.setCursor(112, 30); //ustawienie pozycji kursora
tft.print("g"); //wyświetlenie tekstu
tft.setCursor(192, 30); //ustawienie pozycji kursora
tft.print("1"); //wyświetlenie tekstu
tft.setCursor(272, 30); //ustawienie pozycji kursora
tft.print("2"); //wyświetlenie tekstu
tft.setCursor(352, 30); //ustawienie pozycji kursora
tft.print("3"); //wyświetlenie tekstu
tft.setCursor(22, 110); //ustawienie pozycji kursora
tft.print("GOTOWE"); //wyświetlenie tekstu
tft.setCursor(192, 110); //ustawienie pozycji kursora
tft.print("4"); //wyświetlenie tekstu
tft.setCursor(272, 110); //ustawienie pozycji kursora
tft.print("5"); //wyświetlenie tekstu
tft.setCursor(352, 110); //ustawienie pozycji kursora
tft.print("6"); //wyświetlenie tekstu
tft.setCursor(112, 190); //ustawienie pozycji kursora
tft.print("0"); //wyświetlenie tekstu
tft.setCursor(32, 190); //ustawienie pozycji kursora
tft.print("C"); //wyświetlenie tekstu
tft.setCursor(192, 190); //ustawienie pozycji kursora
tft.print("7"); //wyświetlenie tekstu
tft.setCursor(272, 190); //ustawienie pozycji kursora
tft.print("8"); //wyświetlenie tekstu
tft.setCursor(352, 190); //ustawienie pozycji kursora
tft.print("9"); //wyświetlenie tekstu
tft.drawFastHLine(0, 0, 400, WHITE); //narysowanie linii poziomej
tft.drawFastHLine(0, 80, 400, WHITE); //narysowanie linii poziomej
tft.drawFastHLine(0, 160, 400, WHITE); //narysowanie linii poziomej
tft.drawFastHLine(0, 239, 400, WHITE); //narysowanie linii poziomej
tft.drawFastVLine(0, 0, 400, WHITE); //narysowanie linii pionowej
tft.drawFastVLine(80, 160, 400, WHITE); //narysowanie linii pionowej
tft.drawFastVLine(160, 0, 400, WHITE); //narysowanie linii pionowej
tft.drawFastVLine(240, 0, 400, WHITE); //narysowanie linii pionowej
tft.drawFastVLine(320, 0, 400, WHITE); //narysowanie linii pionowej
tft.drawFastVLine(399, 0, 400, WHITE); //narysowanie linii pionowej
}Ostatnią i największą funkcją będzie wpiszGramy, odbiera ona wciśnięte przez użytkownika liczby i wysyła do funkcji ustawGramy. Funkcja posiada dwa argumenty, gdzie przyjmuje pozycje ekranu, aby mogła poprawnie działać.
void wpiszGramy(int xpos, int ypos)
{
if (xpos > 240) // jeżeli składowa x punktu jest większa od 240, czyli znajdujemy się w pierwszym wierszu
{
if (ypos > 106 && ypos < 154)
{
Serial.println("1"); //wyświetl w monitorze portu szeregowego
ustawGramy(1); //wywołanie funkcji ustawGramy
delay(500); //opoźnienie
}
else if (ypos > 154 && ypos <= 202)
{
Serial.println("2"); //wyświetl w monitorze portu szeregowego
ustawGramy(2); //wywołanie funkcji ustawGramy
delay(500); //opoźnienie
}
else if (ypos > 202 && ypos <= 250)
{
Serial.println("3"); //wyświetl w monitorze portu szeregowego
ustawGramy(3); //wywołanie funkcji ustawGramy
delay(500); //opoźnienie
}
}
else if (xpos > 120 && xpos <= 240) // jeżeli składowa x punktu jest większa od 120 i mniejsza od 240, czyli znajdujemy się w drugim wierszu
{
if (ypos > 0 && ypos < 106)
{
Serial.println("GOTOWE"); //wyświetl w monitorze portu szeregowego
ustaw_wage_A = false;
ustaw_wage_B = false;
delay(500); //opoźnienie
}
else if (ypos > 106 && ypos < 154)
{
Serial.println("4"); //wyświetl w monitorze portu szeregowego
ustawGramy(4); //wywołanie funkcji ustawGramy
delay(500); //opoźnienie
}
else if (ypos > 154 && ypos < 202)
{
Serial.println("5"); //wyświetl w monitorze portu szeregowego
ustawGramy(5); //wywołanie funkcji ustawGramy
delay(500); //opoźnienie
}
else if (ypos > 202 && ypos < 250)
{
Serial.println("6"); //wyświetl w monitorze portu szeregowego
ustawGramy(6); //wywołanie funkcji ustawGramy
delay(500); //opoźnienie
}
}
else if (xpos < 120) //jeżeli składowa x punktu jest mniejsza od 120, czyli znajdujemy się w trzecim wierszu
{
if (ypos > 0 && ypos < 48)
{
Serial.println("C");
tft.setCursor(22, 30);
tft.setTextColor(WHITE, BLACK); //ustawienie koloru tekstu i tła, pierwszy parametr kolor tekstu, drugi tła
tft.print("0 "); //wyświetlenie 0 ze spacjami, żeby wyczyścić ekran w miejscu wpisywanych liczb
if (ustaw_wage_A) //jeżeli jesteśmy w menu wagi A zerujemy wartości
{
last_number_A = 0; //zerujemy zmienną
ustawgramy_A = 0; //zerujemy zmienną
num_count_A = 0; //zerujemy zmienną
}
else if (ustaw_wage_B) //jeżeli jesteśmy w menu wagi B zerujemy wartości
{
last_number_B = 0; //zerujemy zmienną
ustawgramy_B = 0; //zerujemy zmienną
num_count_B = 0; //zerujemy zmienną
}
delay(500);
}
else if (ypos > 48 && ypos < 106) //zakres zera na wyświetlaczu
{
Serial.println("0"); //wyświetl w monitorze portu szeregowego
ustawGramy(0); //wywołanie funkcji ustawGramy
delay(500); //opoźnienie
}
else if (ypos > 106 && ypos < 154) //zakres siódemki na wyświetlaczu
{
Serial.println("7"); //wyświetl w monitorze portu szeregowego
ustawGramy(7); //wywołanie funkcji ustawGramy
delay(500); //opoźnienie
}
else if (ypos > 154 && ypos < 202) //zakres ósemki na wyświetlaczu
{
Serial.println("8"); //wyświetl w monitorze portu szeregowego
ustawGramy(8); //wywołanie funkcji ustawGramy
delay(500); //opoźnienie
}
else if (ypos > 202 && ypos < 250) //zakres dziewiątki na wyświetlaczu
{
Serial.println("9"); //wyświetl w monitorze portu szeregowego
ustawGramy(9); //wywołanie funkcji ustawGramy
delay(500); //opoźnienie
}
}
}




