-
Notifications
You must be signed in to change notification settings - Fork 41
Display Driver Enhancement (after credential rework) #142
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
marcelrru
wants to merge
2
commits into
Redback-Operations:main
Choose a base branch
from
marcelrru:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
79 changes: 79 additions & 0 deletions
79
IoT_Wearable/Codebase/Complete_Code/dev_display_driver/main.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| // This is used for: | ||
| // - Arduino Nano 33 IoT board, paired with | ||
| // - WaveShare ST7789v2 display module | ||
|
|
||
| #include <Adafruit_GFX.h> // Core graphics library | ||
| #include <Adafruit_ST7789.h> // Hardware-specific library for ST7789, used for initializing display object | ||
| #include <SPI.h> | ||
| #include <WiFiNINA.h> | ||
| #include <WiFiUdp.h> | ||
| #include <RTCZero.h> | ||
|
|
||
| //Include user defined header files | ||
| #include <template.h> | ||
| #include <wifi_time.h> | ||
|
|
||
| //Setting up the pins | ||
| #define TFT_CS 10 | ||
| #define TFT_RST 8 | ||
| #define TFT_DC 9 | ||
|
|
||
| // We are using the HARDWARE SPI pins for MOSI and SCLK, which are unique | ||
| // to each board and not reassignable. For Arduino Nano 33 IoT: MOSI = pin 11 and | ||
| // SCLK = pin 13. This is done to improve the performance of the display. | ||
|
|
||
| // Create a display object of the Adafruit_ST7789 class | ||
| Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST); | ||
|
|
||
| //Declare rtc object for real time clock | ||
| RTCZero rtc; | ||
|
|
||
|
|
||
| void drawTemplate() { | ||
| tft.fillScreen(ST77XX_BLACK); //Clear screen before redrawing | ||
|
|
||
| uint8_t padding = 10; // Padding for layout | ||
|
|
||
| // Top Section: Battery level with battery icon | ||
| drawBatteryIcon(tft, padding + 10, padding + 10, ST77XX_WHITE); // Draw battery icon with 85% charge | ||
|
|
||
| // First Section: Heart Rate and SpO2 | ||
| drawHeartIcon(tft, padding + 10, padding + 170, ST77XX_RED); // Heart icon | ||
| drawBubbleIcon(tft, padding + 10, padding + 240, ST77XX_CYAN); // Bubble icon with SpO2 percentage | ||
|
|
||
| drawCircularStepsGauge(tft, 170, 220, 2000, 10000, ST77XX_GREEN); | ||
|
|
||
| // Fourth Section: Body Temperature | ||
| drawThermometerIcon(tft, padding + 10, padding + 200); // Thermometer icon | ||
|
|
||
| // Use the new RTC-aware version of drawTime | ||
| drawTime(tft, rtc, 20, 85, ST77XX_WHITE); | ||
| drawDate(tft, rtc, 120, 25, ST77XX_WHITE); | ||
| } | ||
|
|
||
| void setup() { | ||
| // Initialize Serial Monitor | ||
| Serial.begin(9600); | ||
| Serial.println(F("Initializing ST7789 Display...")); | ||
|
|
||
| // Initialize WiFi | ||
| WiFi_Setup(WiFi, rtc); | ||
|
|
||
| // Initialize display (240x280 resolution) | ||
| tft.init(240, 280); | ||
| tft.setRotation(2); // Portrait orientation | ||
| tft.fillScreen(ST77XX_BLACK); | ||
|
|
||
| // Set default text size and color | ||
| tft.setTextSize(2); | ||
| tft.setTextColor(ST77XX_WHITE); | ||
|
|
||
| // Draw the template | ||
| drawTemplate(); | ||
| } | ||
|
|
||
| void loop() { | ||
| // Continuously update the time every second | ||
| delay(3000); // Wait for 3 seconds | ||
| drawTemplate(); // Redraw the template to update the time | ||
| } |
169 changes: 169 additions & 0 deletions
169
IoT_Wearable/Codebase/Complete_Code/dev_display_driver/template.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,169 @@ | ||
| #ifndef template_h | ||
| #define template_h | ||
|
|
||
| #include <Adafruit_GFX.h> // Core graphics library for displays | ||
| #include <Adafruit_ST7789.h> // Specific driver for the ST7789 display | ||
| #include <SPI.h> // SPI communication used for the display | ||
|
|
||
| /** | ||
| * Get the name of the weekday for a given date using Zeller's Congruence. | ||
| * | ||
| * @param day Day of the month | ||
| * @param month Month (1 = January, 12 = December) | ||
| * @param year Full year (e.g., 2024) | ||
| * @return Abbreviated weekday name (e.g., "Mon", "Tue", ...) | ||
| */ | ||
| const char* weekdayName(int day, int month, int year) { | ||
| if (month < 3) { | ||
| month += 12; | ||
| year -= 1; | ||
| } | ||
|
|
||
| int k = year % 100; | ||
| int j = year / 100; | ||
| int h = (day + (13 * (month + 1)) / 5 + k + k/4 + j/4 + 5*j) % 7; | ||
|
|
||
| const char* days[] = {"Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri"}; | ||
| return days[h]; | ||
| } | ||
|
|
||
| /** | ||
| * Draws a battery icon on the display, representing battery percentage visually. | ||
| */ | ||
| void drawBatteryIcon(Adafruit_ST7789 tft, int x, int y, uint16_t color) { | ||
| tft.drawRect(x, y, 50, 25, color); // Battery body outline | ||
| tft.fillRect(x + 52, y + 7, 5, 12, color); // Battery terminal | ||
| tft.fillRect(x + 2, y + 2, 46, 21, ST77XX_BLACK); // Battery "empty" interior | ||
|
|
||
| // Display the battery percentage as text | ||
| tft.setCursor(x + 8, y + 5); | ||
| tft.setTextColor(color); | ||
| tft.setTextSize(2); | ||
| tft.print("80%"); | ||
| } | ||
|
|
||
| /** | ||
| * Draws a heart icon and displays a heart rate value. | ||
| */ | ||
| void drawHeartIcon(Adafruit_ST7789 tft, int x, int y, uint16_t color) { | ||
| tft.fillCircle(x + 4, y + 4, 4, color); // Left part of the heart | ||
| tft.fillCircle(x + 12, y + 4, 4, color); // Right part of the heart | ||
| tft.fillTriangle(x, y + 4, x + 8, y + 16, x + 16, y + 4, color); // Bottom point | ||
|
|
||
| // Display heart rate | ||
| tft.setCursor(x + 25, y); | ||
| tft.setTextColor(ST77XX_WHITE); | ||
| tft.setTextSize(2); | ||
| tft.print("76"); | ||
| } | ||
|
|
||
| /** | ||
| * Draws a bubble (oxygen) icon and displays an SpO2 percentage value. | ||
| */ | ||
| void drawBubbleIcon(Adafruit_ST7789 tft, int x, int y, uint16_t color) { | ||
| tft.drawCircle(x + 8, y + 8, 8, color); // Outer bubble outline | ||
| tft.fillCircle(x + 6, y + 6, 2, color); // Highlight dot inside | ||
|
|
||
| // Display SpO2 percentage | ||
| tft.setCursor(x + 25, y); | ||
| tft.setTextColor(ST77XX_WHITE); | ||
| tft.setTextSize(2); | ||
| tft.print("98%"); | ||
| } | ||
|
|
||
| /** | ||
| * Draws a thermometer icon and displays a body temperature reading. | ||
| */ | ||
| void drawThermometerIcon(Adafruit_ST7789 tft, int x, int y) { | ||
| tft.fillRect(x + 4, y + 2, 4, 12, ST77XX_WHITE); // Thermometer stem | ||
| tft.fillCircle(x + 6, y + 16, 3, ST77XX_WHITE); // Thermometer bulb (outer) | ||
| tft.fillRect(x + 5, y + 7, 2, 12, ST77XX_RED); // Mercury (stem) | ||
| tft.fillCircle(x + 6, y + 16, 2, ST77XX_RED); // Mercury (bulb) | ||
|
|
||
| // Display body temperature | ||
| tft.setCursor(x + 25, y + 3); | ||
| tft.setTextColor(ST77XX_WHITE); | ||
| tft.setTextSize(2); | ||
| tft.print("36.4C"); | ||
| } | ||
|
|
||
| /** | ||
| * Displays the current time in HH:MM format using RTCZero. | ||
| */ | ||
| void drawTime(Adafruit_ST7789 tft, RTCZero& rtc, int x, int y, uint16_t color) { | ||
| int hours = rtc.getHours(); | ||
| int minutes = rtc.getMinutes(); | ||
|
|
||
| tft.setCursor(x, y); | ||
| tft.setTextColor(color); | ||
| tft.setTextSize(7); | ||
| if (hours < 10) tft.print("0"); | ||
| tft.print(hours); | ||
| tft.print(":"); | ||
| if (minutes < 10) tft.print("0"); | ||
| tft.print(minutes); | ||
| } | ||
|
|
||
| /** | ||
| * Displays the current date in format: Weekday DD/MM using RTCZero. | ||
| */ | ||
| void drawDate(Adafruit_ST7789 tft, RTCZero& rtc, int x, int y, uint16_t color) { | ||
| int day = rtc.getDay(); | ||
| int month = rtc.getMonth(); | ||
| int year = rtc.getYear() + 2000; | ||
|
|
||
| const char* weekday = weekdayName(day, month, year); | ||
|
|
||
| tft.setCursor(x, y); | ||
| tft.setTextColor(color); | ||
| tft.setTextSize(2); | ||
| tft.print(weekday); | ||
| tft.print(" "); | ||
|
|
||
| if (day < 10) tft.print("0"); | ||
| tft.print(day); | ||
| tft.print("/"); | ||
|
|
||
| if (month < 10) tft.print("0"); | ||
| tft.print(month); | ||
| } | ||
|
|
||
| /** | ||
| * Draws a circular step counter gauge showing progress toward a step goal. | ||
| */ | ||
| void drawCircularStepsGauge(Adafruit_ST7789 tft, int x, int y, int steps, int maxSteps, uint16_t color) { | ||
| // Draw outer circle for gauge | ||
| tft.fillCircle(x, y, 50, ST77XX_BLACK); // Background | ||
| tft.drawCircle(x, y, 50, ST77XX_WHITE); // Border | ||
|
|
||
| // Convert step count to angle (0° to 360°) | ||
| int angle = map(steps, 0, maxSteps, 0, 360); | ||
|
|
||
| // Draw each pixel along the arc | ||
| for (int i = 0; i < angle; i++) { | ||
| int x1 = x + 50 * cos(radians(i)); | ||
| int y1 = y - 50 * sin(radians(i)); | ||
| tft.drawPixel(x1, y1, color); | ||
| } | ||
|
|
||
| // Label: "Steps" above gauge | ||
| tft.setCursor(x - 15, y - 25); | ||
| tft.setTextColor(ST77XX_WHITE); | ||
| tft.setTextSize(1); | ||
| tft.print("Steps"); | ||
|
|
||
| // Display current step count in center | ||
| tft.setCursor(x - 22, y - 5); | ||
| tft.setTextColor(ST77XX_WHITE); | ||
| tft.setTextSize(2); | ||
| tft.print(steps); | ||
|
|
||
| // Display goal step count below | ||
| tft.setCursor(x - 15, y + 25); | ||
| tft.setTextColor(ST77XX_WHITE); | ||
| tft.setTextSize(1); | ||
| tft.print("/"); | ||
| tft.print(maxSteps); | ||
| } | ||
|
|
||
| #endif |
77 changes: 77 additions & 0 deletions
77
IoT_Wearable/Codebase/Complete_Code/dev_display_driver/wifi_time.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| #ifndef wifi_time_h | ||
| #define wifi_time_h | ||
|
|
||
| #include <WiFiNINA.h> // WiFi library for Arduino boards using NINA module | ||
| #include <WiFiUdp.h> // Required for time retrieval using NTP | ||
| #include <RTCZero.h> // Real-time clock library | ||
|
|
||
| // Debug toggle: Set to false to disable Serial prints | ||
| bool WIFI_DEBUG = true; | ||
|
|
||
| // WiFi credentials | ||
| #define SECRET_SSID "REPLACE_WITH_YOUR_SSID" | ||
| #define SECRET_PASS "REPLACE_WITH_YOUR_PASSWORD" | ||
|
|
||
| // WiFi connection status tracking variable | ||
| int status = WL_IDLE_STATUS; | ||
|
|
||
| /** | ||
| * Function to connect to WiFi and synchronize RTC with NTP time. | ||
| * | ||
| * @param wifi Reference to the WiFi module instance (usually `WiFi`) | ||
| * @param rtc Reference to RTCZero instance used for tracking real time | ||
| * | ||
| * @return true if setup was successful and time was synced, false otherwise | ||
| */ | ||
| bool WiFi_Setup(WiFiClass& wifi, RTCZero& rtc) { | ||
| // Check if WiFi module is present and working | ||
| if (wifi.status() == WL_NO_SHIELD) { | ||
| if (WIFI_DEBUG) Serial.println("WiFi adapter not ready"); | ||
| return false; // Exit early if WiFi hardware is not detected | ||
| } | ||
|
|
||
| // Attempt to connect to the WiFi network | ||
| while (status != WL_CONNECTED) { | ||
| if (WIFI_DEBUG) { | ||
| Serial.print("Connecting to SSID: "); | ||
| Serial.println(SECRET_SSID); | ||
| } | ||
| status = wifi.begin(SECRET_SSID, SECRET_PASS); // Start connection attempt | ||
| delay(3000); // Wait 3 seconds before retrying | ||
| } | ||
|
|
||
| if (WIFI_DEBUG) Serial.println("WiFi connected!"); | ||
|
|
||
|
|
||
| // Clock logic to be fixed, currently not accurate | ||
|
|
||
| // Initialize the real-time clock | ||
| rtc.begin(); | ||
|
|
||
| // Try to get the current time from an NTP server | ||
| unsigned long epoch; // Stores the retrieved epoch time | ||
| int tries = 0, maxTries = 6; // Retry up to 6 times | ||
|
|
||
| do { | ||
| epoch = wifi.getTime(); // Request time from NTP server | ||
| tries++; | ||
| delay(1000); // Wait 1 second between tries | ||
| } while ((epoch == 0) && (tries < maxTries)); | ||
|
|
||
| // If time could not be retrieved after maxTries, return false | ||
| if (tries == maxTries) { | ||
| if (WIFI_DEBUG) Serial.println("NTP unreachable!!"); | ||
| return false; | ||
| } | ||
|
|
||
| Serial.print("Epoch received: "); | ||
| Serial.println(epoch); | ||
|
|
||
| // Set RTC time using the retrieved epoch | ||
| rtc.setEpoch(epoch); | ||
| if (WIFI_DEBUG) Serial.println("Time synced."); | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| #endif |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way the WIFI credentials are setup here may lead to possible data breaches or unauthorised access to networks. While it is a placeholder and needs to be replaced by a user, it could possibly lead to someone having their information exposed once they add their credentials in.