#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Keypad.h>
// Configuración de la pantalla OLED (ejemplo: SSD1306 128x64)
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1 // -1 para reset por software
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Configuración del teclado matricial en pines GPIO 32 a 13 (de mayor a menor)
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {32, 33, 25, 26}; // Ajusta a tus conexiones físicas
byte colPins[COLS] = {27, 14, 12, 13}; // Ajusta a tus conexiones físicas
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
const int MAX_ECUACIONES = 5;
float matriz[MAX_ECUACIONES][MAX_ECUACIONES + 1];
float soluciones[MAX_ECUACIONES];
int numEcuaciones = 0;
// Funciones auxiliares para OLED (letra grande)
void oledClear() {
display.clearDisplay();
display.setTextSize(2); // LETRA GRANDE
display.setCursor(0, 0);
}
void oledPrint(const char* txt, int line=0) {
display.setCursor(0, line*16); // 16px por línea (size 2)
display.print(txt);
display.display();
}
void oledPrint(String txt, int line=0) {
display.setCursor(0, line*16);
display.print(txt);
display.display();
}
void setup() {
Serial.begin(115200);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
while (true);
}
// Pantalla de bienvenida distribuida en 4 líneas tamaño 1
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 5); // Línea 1, centrado
display.print("CALCULADORA DE");
display.setCursor(5, 20); // Línea 2, centrado
display.print("SISTEMAS LINEALES");
display.setCursor(35, 40); // Línea 3, centrado
display.print("AUTOR:");
display.setCursor(25, 53); // Línea 4, centrado
display.print("MERINO ROJAS");
display.display();
delay(3000);
// Regresa a letra grande para el flujo normal
display.setTextSize(2);
oledClear();
}
void loop() {
oledClear();
oledPrint("Num ecuac:", 0);
numEcuaciones = leerNumeroOLED();
if (numEcuaciones <= 0 || numEcuaciones > MAX_ECUACIONES) {
oledPrint("Valor inval.", 1);
delay(1500);
return;
}
// Solicitar coeficientes
for (int i = 0; i < numEcuaciones; i++) {
for (int j = 0; j <= numEcuaciones; j++) {
oledClear();
if (j < numEcuaciones)
oledPrint("x" + String(j+1) + " ec" + String(i+1), 0);
else
oledPrint("Indep ec" + String(i+1), 0);
oledPrint("Valor:", 1);
matriz[i][j] = leerNumeroOLED();
}
}
if (resolverSistema(numEcuaciones)) {
mostrarResultados();
} else {
oledClear();
oledPrint("Sin solucion", 0);
}
delay(3000);
}
void mostrarResultados() {
oledClear();
display.setTextSize(1); // Cambia a letra pequeña para resultados
display.setCursor(0, 0);
display.print("Soluciones:");
display.display();
int i = 0;
while (i < numEcuaciones) {
display.clearDisplay();
display.setTextSize(1);
// Hasta 6 resultados por pantalla (con tamaño 1)
for (int j = 0; j < 6 && i < numEcuaciones; j++, i++) {
display.setCursor(0, j*10); // 10px por línea en size 1
display.print("x");
display.print(i+1);
display.print(" = ");
display.print(soluciones[i], 10); // Muestra hasta 10 decimales
}
display.display();
// Esperar a 'D' para siguiente tanda, o 'A' para reset
while (true) {
char tecla = keypad.getKey();
if (tecla) {
if (tecla == 'D') break;
else if (tecla == 'A') {
display.setTextSize(2); // Restaurar letra grande
reiniciarCalculadora();
return;
}
}
}
}
display.setTextSize(2); // Restaurar letra grande para el resto del flujo
}
float leerNumeroOLED() {
String input = "";
char tecla;
display.fillRect(0, 2*16, SCREEN_WIDTH, 16, SSD1306_BLACK); // Borra línea antes de imprimir input
oledPrint(input, 2);
while (true) {
tecla = keypad.getKey();
if (tecla) {
if (tecla == 'A') reiniciarCalculadora();
else if (tecla == 'D') {
if (input.length() > 0) break;
} else if (tecla == '*') { // Borrar todo el número
input = "";
} else if (tecla == '#' && input.indexOf('.') == -1) {
input += ".";
} else if (tecla == 'B' && input.length() == 0) {
input += '-';
} else if (tecla >= '0' && tecla <= '9') {
input += tecla;
}
// Siempre borrar línea y volver a imprimir el input actualizado
display.fillRect(0, 2*16, SCREEN_WIDTH, 16, SSD1306_BLACK);
oledPrint(input, 2);
}
}
return input.toFloat();
}
bool resolverSistema(int n) {
for (int i = 0; i < n; i++) {
int maxFila = i;
for (int k = i + 1; k < n; k++)
if (fabs(matriz[k][i]) > fabs(matriz[maxFila][i])) maxFila = k;
for (int k = i; k <= n; k++) {
float temp = matriz[maxFila][k];
matriz[maxFila][k] = matriz[i][k];
matriz[i][k] = temp;
}
if (fabs(matriz[i][i]) < 1e-6) return false;
for (int k = i + 1; k < n; k++) {
float factor = matriz[k][i] / matriz[i][i];
for (int j = i; j <= n; j++) matriz[k][j] -= factor * matriz[i][j];
}
}
for (int i = n - 1; i >= 0; i--) {
soluciones[i] = matriz[i][n] / matriz[i][i];
for (int j = i - 1; j >= 0; j--) matriz[j][n] -= matriz[j][i] * soluciones[i];
}
return true;
}
void reiniciarCalculadora() {
oledClear();
oledPrint("Reset...", 0);
delay(1200);
numEcuaciones = 0;
for (int i = 0; i < MAX_ECUACIONES; i++)
for (int j = 0; j <= MAX_ECUACIONES; j++)
matriz[i][j] = 0;
oledClear();
loop();
}