// choose if digital font "7-segment" be used for the Timer
//#define DIGITAL_FONT
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EEPROM.h>
#ifdef DIGITAL_FONT
#include "Numbers.h"
//#include "digital24B.h"
#define font1 &DS_DIGIB24pt7b
#else
#include <Fonts/FreeSansBold18pt7b.h>
#define font1 &FreeSansBold18pt7b
#endif
//#include <Fonts/FreeSans9pt7b.h>
//#define font2 &FreeSans9pt7b
//#define font3 &FreeSans9pt7b
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3D ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define impactPin A0
#define SW1 7
#define RESET 3
#define elapsedTime (millis() - tNow)
#define buttonPressed !digitalRead(BTN_SELECT)
#define INTERNAL_REFERENCE_VOLTAGE 1.1
#define ONE_SECOND 1000 //1000
#define HALF_SECOND 500 //500
// Define the min and max voltage for your battery. Adjust these values.
// Example for a 9V battery:
#define BATTERY_MAX_VOLTAGE 3.3
#define BATTERY_MIN_VOLTAGE 2.5
// The VCC value in volts will be stored here.
float vccVoltage;
int batteryPercentage;
unsigned long tNow;
//************************************************************
//********************* SETUP ********************************
//************************************************************
void setup() {
pinMode(SW1, INPUT_PULLUP);
pinMode(RESET,OUTPUT);
initializeDisplay();
tNow = millis();
analogReference(INTERNAL);
//Wire.setClock(800000UL);
resetVoltage();
}
//************************************************************
//********************** LOOP *******************************
//************************************************************
float v = 0.5;
float vB=0;
int vd;
unsigned int batVoltage;
unsigned long tImpact;
unsigned int adcReading;
void loop() {
if(digitalRead(SW1) == 0){
processImpact();
}
if (millis() - tNow >= HALF_SECOND) {
tNow = millis();
//vd = analogRead(impactPin);
//v = vd * 1.1/1024;
//v = v + 0.1;
//if (v > 1.1) v = 0.0;
adcReading = readVcc();
vB = (INTERNAL_REFERENCE_VOLTAGE * 1024.0) / adcReading;
displayVB();
//displayFull();
}
}
void processImpact(){
resetVoltage();
for(int i = 0;i<40;i++){
adcReading = analogRead(impactPin);
v = adcReading * INTERNAL_REFERENCE_VOLTAGE /1024.0;
displayImpact();
if(digitalRead(SW1) == 0){
resetVoltage();
i = 0;
}
while(millis()-tImpact < HALF_SECOND){
if(digitalRead(SW1) == 0){
resetVoltage();
i = 0;
}
delay(10);
}
tImpact = millis();
}
}
void resetVoltage(){
displayReset();
digitalWrite(RESET,HIGH);
delay(ONE_SECOND);
digitalWrite(RESET,LOW);
displayReady();
delay(HALF_SECOND);
}
//************************************************************
//****************** Initialze DISPLAY ***********************
//************************************************************
void initializeDisplay() {
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
}
display.clearDisplay();
//display.setTextSize(1); // Draw 2X-scale text
display.setRotation(2);
display.setTextColor(SSD1306_INVERSE);
display.setFont(font1);
display.display();
}
void displayReset(){
display.clearDisplay();
display.setCursor(10,40);
display.println("Reset");
display.display();
}
void displayReady(){
display.clearDisplay();
display.setCursor(10,40);
display.println("Ready");
display.display();
}
//************************************************************
//************* Display Count Down Time **********************
//************************************************************
void displayVB() {
display.clearDisplay();
display.setFont(font1);
display.setCursor(30, 40);
//display.println(vd);
display.println(vB);
// Map the voltage to a percentage and constrain it
batteryPercentage = map(vB * 100, BATTERY_MIN_VOLTAGE * 100, BATTERY_MAX_VOLTAGE * 100, 0, 100);
batteryPercentage = constrain(batteryPercentage, 0, 100);
// Draw the battery icon with percentage fill in the top-right corner
drawBatteryIcon(batteryPercentage);
//delay(1000);
display.display();
}
void displayImpact(){
display.clearDisplay();
display.setFont(font1);
display.setCursor(30, 40);
display.println(v);
// Map the voltage to a percentage and constrain it
batteryPercentage = map(vB * 100, BATTERY_MIN_VOLTAGE * 100, BATTERY_MAX_VOLTAGE * 100, 0, 100);
batteryPercentage = constrain(batteryPercentage, 0, 100);
// Draw the battery icon with percentage fill in the top-right corner
drawBatteryIcon(batteryPercentage);
//delay(1000);
display.display();
}
void displayFull() {
display.fillScreen(0xFFFF);
display.display();
}
// Function to read the internal 1.1V reference voltage
long readVcc() {
// Set the ADC reference to VCC. This is the key step.
// We're measuring the internal reference against the supply voltage itself.
//#if defined(__AVR_ATmega328PB__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
// For Atmega328 and similar
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
//#endif
// A small delay is needed to allow the ADC to settle
delay(1);
// Start a conversion
ADCSRA |= _BV(ADSC);
// Wait for the conversion to complete
while (bit_is_set(ADCSRA, ADSC));
// Read the result
long result = ADCW;
return result;
}
// Function to draw a mobile phone-style battery icon in the top-right corner
void drawBatteryIcon(int percentage) {
// Coordinates and dimensions for the icon
int x = SCREEN_WIDTH - 25; // Top-left X position
int y = 2; // Top-left Y position
int width = 20, height = 12;
int radius = 2;
// Clear the area of the icon before drawing
// This prevents the previous frame's data from ghosting
display.fillRect(x, y, width + 2, height, SSD1306_BLACK);
// Draw the main battery body with rounded corners
display.drawRoundRect(x, y, width, height, radius, SSD1306_WHITE);
// Draw the positive terminal
display.fillRect(x + width, y + 4, 2, 4, SSD1306_WHITE);
// Calculate the filled width based on percentage
int filledWidth = map(percentage, 0, 100, 0, width - 4);
// Draw the filled portion of the battery
if (filledWidth > 0) {
display.fillRect(x + 2, y + 2, filledWidth, height - 4, SSD1306_WHITE);
}
}