#include "U8glib.h"
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <RTClib.h>
#include <NewPing.h>
#define TRIG_PIN 6 // Define the trigger pin for the ultrasonic sensor
#define ECHO_PIN 7 // Define the echo pin for the ultrasonic sensor
#define MAX_DISTANCE 200 // Define maximum distance for the ultrasonic sensor
#define BUTTON_UP_PIN 12 // Pin for UP button
#define BUTTON_DOWN_PIN 4 // Pin for DOWN button
#define BUTTON_LEFT_PIN 8 // Pin for LEFT button
#define BUTTON_SELECT_PIN 2 // Pin for SELECT button
#define CHIP_SELECT_PIN 10 // Pin for SD card chip select
#define RTC_SDA_PIN A4 // Pin for RTC SDA
#define RTC_SCL_PIN A5 // Pin for RTC SCL
RTC_DS1307 rtc; // Create an RTC object
NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE); // Create a NewPing object
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST); // Fast I2C / TWI
const int NUM_ITEMS = 10; // Number of items in the menu including the ultrasonic sensor option
const int MAX_ITEM_LENGTH = 20; // Maximum characters for the item name
const int ITEMS_DISPLAYED = 5; // Number of menu items displayed on the screen at a time
const int DATA_DISPLAYED = 2; // Number of lines displayed for saved data
char menu_items[NUM_ITEMS][MAX_ITEM_LENGTH] = {
{ "3D Cube" },
{ "Battery" },
{ "Dashboard" },
{ "Fireworks" },
{ "GPS Speed" },
{ "Big Knob" },
{ "Park Sensor" },
{ "Turbo Gauge" },
{ "View Saved Data" }, // New menu item to view saved data
{ "Ultrasonic Sensor" } // New menu item for the ultrasonic sensor
};
int current_item = 0; // Variable to track the current selected menu item
bool ultrasonic_selected = false; // Flag to indicate if ultrasonic sensor option is selected
bool view_data_selected = false; // Flag to indicate if view saved data option is selected
File dataFile; // File object for SD card data
int current_line_index = 0; // Variable to track the current line index for viewing saved data
void setup() {
Serial.begin(9600); // Initialize serial communication
Wire.begin(); // Initialize I2C communication for RTC
rtc.begin(); // Initialize RTC
if (!rtc.isrunning()) {
Serial.println("RTC is not running!");
}
if (!SD.begin(CHIP_SELECT_PIN)) { // Initialize SD card
Serial.println("SD card initialization failed!");
return;
}
Serial.println("SD card initialized.");
// Configure button pins as inputs with pull-up resistors
pinMode(BUTTON_UP_PIN, INPUT_PULLUP);
pinMode(BUTTON_DOWN_PIN, INPUT_PULLUP);
pinMode(BUTTON_LEFT_PIN, INPUT_PULLUP);
pinMode(BUTTON_SELECT_PIN, INPUT_PULLUP);
}
void loop() {
if (!ultrasonic_selected && !view_data_selected) {
// Read button states and update current item accordingly
if (digitalRead(BUTTON_UP_PIN) == LOW) {
current_item = (current_item + NUM_ITEMS - 1) % NUM_ITEMS; // Move to previous item
delay(250); // Debounce delay
}
if (digitalRead(BUTTON_DOWN_PIN) == LOW) {
current_item = (current_item + 1) % NUM_ITEMS; // Move to next item
delay(250); // Debounce delay
}
// Display menu options on the LCD screen
u8g.firstPage();
do {
u8g.setFont(u8g_font_7x14);
for (int i = 0; i < ITEMS_DISPLAYED; ++i) {
int index = (current_item + i - ITEMS_DISPLAYED / 2 + NUM_ITEMS) % NUM_ITEMS;
if (i == ITEMS_DISPLAYED / 2) {
u8g.drawStr(0, (i + 1) * 10, "-> "); // Indicator for current selected item
}
u8g.drawStr(20, (i + 1) * 10, menu_items[index]);
}
} while (u8g.nextPage());
// Check if SELECT button is pressed to select the item
if (digitalRead(BUTTON_SELECT_PIN) == LOW) {
if (current_item == NUM_ITEMS - 1) { // If "Ultrasonic Sensor" option is selected
ultrasonic_selected = true; // Enable ultrasonic sensor mode
} else if (current_item == NUM_ITEMS - 2) { // If "View Saved Data" option is selected
view_data_selected = true; // Enable view saved data mode
current_line_index = 0; // Reset the line index when entering view saved data mode
}
delay(250); // Debounce delay
}
} else if (view_data_selected) { // View saved data mode
viewSavedData(); // View saved data from SD card
} else { // Ultrasonic sensor mode
// Read distance from ultrasonic sensor
unsigned int duration = sonar.ping_median(5); // Measure distance in microseconds
unsigned int distance = duration / US_ROUNDTRIP_CM; // Convert to centimeters
// Print distance to serial monitor
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" cm");
// Save data to SD card
saveDataToSDCard(distance);
// Display distance on the OLED screen
displayUltrasonicDistance(distance);
// Check if LEFT button is pressed to exit ultrasonic sensor mode
if (digitalRead(BUTTON_LEFT_PIN) == LOW) {
ultrasonic_selected = false; // Disable ultrasonic sensor mode
delay(250); // Debounce delay
}
}
}
void viewSavedData() {
u8g.firstPage();
do {
u8g.setFont(u8g_font_7x14);
dataFile = SD.open("data.txt");
if (dataFile) {
int lineIndex = 0;
while (dataFile.available()) {
if (lineIndex >= current_line_index && lineIndex < current_line_index + DATA_DISPLAYED) {
String line = dataFile.readStringUntil('\n');
// Parse the line to extract date/time and distance
int commaIndex = line.indexOf(',');
if (commaIndex != -1) {
String dateTime = line.substring(0, commaIndex);
String distanceStr = line.substring(commaIndex + 1);
// Display date/time and distance
u8g.drawStr(0, (lineIndex - current_line_index + 1) * 20, dateTime.c_str());
u8g.drawStr(0, (lineIndex - current_line_index + 2) * 20, distanceStr.c_str());
}
} else {
dataFile.readStringUntil('\n'); // Read and discard lines outside the current view
}
lineIndex++;
}
dataFile.close();
} else {
Serial.println("Error opening data file!");
}
} while (u8g.nextPage());
// Read button states for scrolling through data
if (digitalRead(BUTTON_UP_PIN) == LOW && current_line_index > 0) {
current_line_index--; // Scroll up if not at the beginning
delay(250); // Debounce delay
}
if (digitalRead(BUTTON_DOWN_PIN) == LOW) {
current_line_index++; // Scroll down
delay(250); // Debounce delay
}
// Check if LEFT button is pressed to exit view saved data mode
if (digitalRead(BUTTON_LEFT_PIN) == LOW) {
view_data_selected = false; // Disable view saved data mode
delay(250); // Debounce delay
}
}
void saveDataToSDCard(unsigned int distance) {
dataFile = SD.open("data.txt", FILE_WRITE);
if (dataFile) {
DateTime now = rtc.now();
dataFile.print(now.year(), DEC);
dataFile.print('/');
dataFile.print(now.month(), DEC);
dataFile.print('/');
dataFile.print(now.day(), DEC);
dataFile.print(" ");
dataFile.print(now.hour(), DEC);
dataFile.print(':');
dataFile.print(now.minute(), DEC);
dataFile.print(':');
dataFile.print(now.second(), DEC);
dataFile.print(',');
dataFile.println(distance);
dataFile.close();
Serial.println("Data saved to SD card.");
} else {
Serial.println("Error opening data file!");
}
}
void displayUltrasonicDistance(unsigned int distance) {
u8g.firstPage();
do {
u8g.setFont(u8g_font_7x14);
u8g.drawStr(0, 20, "Ultrasonic Sensor:");
u8g.drawStr(0, 40, String(distance).c_str()); // Convert distance to string and draw on the screen
} while (u8g.nextPage());
}