Calculadora con funciones

Se asigna una tecla para calcular el valor de una función, en éste caso se sustituye la tecla ‘*’ por una función factorial como ejemplo:

Al presionar la tecla «!» se obtiene el valor del factorial del número.

5 !
120.000

El archivo de intrucciones modificado a partir de calculadora básica y la función de la tecla escrita al final se muestra a continuación:

// blog.espol.edu.ec/edelros
// edelros@espol.edu.ec 
// Calculadora Básica 2018.06.24

#include <LiquidCrystal_I2C.h> // LCD por I2C
#include <Wire.h> //comunicación I2C
#include <Keypad.h> //Teclado

// Pantalla LCD. npxmp
const byte mp = 20;
const byte np = 4;
LiquidCrystal_I2C lcd(0x27,mp,np); 

// Teclado ntxmt
const byte nt = 4;
const byte mt = 4;
char tabla[nt][mt]={ 
    {'1', '2', '3', '+'},
    {'4', '5', '6', '-'},
    {'7', '8', '9', '!'},
    {'C', '0', '.', '='}};  
byte PinF[nt]={7,6,5,4}; 
byte PinC[mt]={3,2,1,0}; 
Keypad teclado = Keypad(makeKeymap(tabla),PinF,PinC,nt,mt); 

float numA = 0;
float numB = 0;
float resultado = 0; 
String num1, num2;
char operador  = ' ';
int tamano = 0;
byte cualnum = 0;
boolean haypunto = 0;


void setup(){
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Calculadora-Basica");
  lcd.setCursor(0,1);
  lcd.print("FCNM-ESPOL");
  lcd.setCursor(0,2);
  lcd.print("blog.espol.edu.ec");
  lcd.setCursor(0,3);
  lcd.print("/matg1013");
  delay (2000);
  lcd.clear();
}

void loop(){
  char tecla = teclado.getKey(); 
  // tecla presionada
  if (tecla != NO_KEY){
    // tecla numero
    if (tecla=='1' || tecla=='2' || tecla=='3' || 
    tecla=='4' || tecla=='5' || tecla=='6' || 
    tecla=='7' || tecla=='8' || tecla=='9' || 
    tecla=='0'){
        if (cualnum <=1){
            num1 = num1 + tecla;
            cualnum = 1; 
            }
        if (cualnum ==2){
            num2 = num2 + tecla;
            }
    }
    // tecla punto decimal
    if (tecla=='.' and haypunto==0){
        if (cualnum ==1 or cualnum ==0){
            tamano = num1.length();
            if (tamano==0)
            {num1= "0.";}
            else
            {num1 = num1 + tecla;}
        }
        if (cualnum ==2){
            tamano = num2.length();
            if (tamano==0)
            {num2= "0.";}
            else
            {num2 = num2 + tecla;}
        }
        haypunto = 1;
    }
    //tecla de Operacion
    if (cualnum >= 1 && (tecla == '+' || 
    tecla == '-' || tecla == '!' || 
    tecla == '/')){   
        operador = tecla; 
        cualnum = 2;
        haypunto = 0; 
        }
    // obtener resultado
    if (tecla == '=' && cualnum == 2){
        if (operador == '+') 
        {resultado = numA + numB;}
        if (operador == '-')
        {resultado = numA - numB;}
        if (operador == '*')
        {resultado = numA * numB;}
        if (operador == '/')
        {resultado = numA / numB;}
        num1 = String(resultado);
        num2 = "";
        cualnum = 2;
        haypunto = 0;
        }
    // tecla factorial
    if (tecla == '!'){
        resultado = factorial(numA);
        num1 = String(resultado);
        num2 = "";
        cualnum = 2;
        haypunto = 0;
        }

    //tecla C Clear
    if (tecla == 'C'){
        cualnum = 0;
        num1 = "";
        num2 = "";
        operador = ' ';
        resultado = 0;
        haypunto = 0;
        }
    numA = num1.toFloat();
    numB = num2.toFloat();

    // SALIDA A PANTALLA LCD
    lcd.clear();
    lcd.setCursor(0,0);
    // muestra decimales = 3
    lcd.print(numA,3);
    if (numB!=0){
        lcd.setCursor(0,1);
        lcd.print(numB,3);    
    }
    lcd.setCursor(mp-2,0);
    lcd.print (operador);
    }
}

float factorial(float n){
    float resultado = 1;
    int i = 2;
    for (i = 2; i<=n; i++){
        resultado = resultado*i;
    }
    return resultado;
}

Calculadora Básica-LCD y Teclado4x4

Como proyecto base se usa una calculadora básica para números reales (float) usando un teclado 4×4 y un LCD 20×4 (tenía disponible) y tiene integrado un módulo I2C. El módulo I2C facilita la conexión mediante las señales SDA (Serial Data) y SCL (Serial Clock).

El prototipo puede ser adaptado a otros modelos de pantallas, teclados y arduinos, debe cambiar las variables que controlan el display, el teclado o las entradas en los arduinos.

// blog.espol.edu.ec/edelros
// edelros@espol.edu.ec 
// Calculadora Básica 2018.06.24

#include <LiquidCrystal_I2C.h> // LCD por I2C 
#include <Wire.h> //comunicación I2C 
#include <Keypad.h> //Teclado

// Pantalla LCD. npxmp
const byte mp = 20;
const byte np = 4;
LiquidCrystal_I2C lcd(0x27,mp,np); 

// Teclado ntxmt
const byte nt = 4;
const byte mt = 4;
char tabla[nt][mt]={ 
    {'1', '2', '3', '+'},
    {'4', '5', '6', '-'},
    {'7', '8', '9', '*'},
    {'C', '0', '.', '='}};  
byte PinF[nt]={7,6,5,4}; 
byte PinC[mt]={3,2,1,0}; 
Keypad teclado = Keypad(makeKeymap(tabla),PinF,PinC,nt,mt); 

float numA = 0;
float numB = 0;
float resultado = 0; 
String num1, num2;
char operador  = ' ';
int tamano = 0;
byte cualnum = 0;
boolean haypunto = 0;


void setup(){
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Calculadora-Basica");
  lcd.setCursor(0,1);
  lcd.print("FCNM-ESPOL");
  lcd.setCursor(0,2);
  lcd.print("blog.espol.edu.ec");
  lcd.setCursor(0,3);
  lcd.print("/matg1013");
  delay (2000);
  lcd.clear();
}

void loop(){
  char tecla = teclado.getKey(); 
  // tecla presionada
  if (tecla != NO_KEY){
    // tecla numero
    if (tecla=='1' || tecla=='2' || tecla=='3' || 
    tecla=='4' || tecla=='5' || tecla=='6' || 
    tecla=='7' || tecla=='8' || tecla=='9' || 
    tecla=='0'){
        if (cualnum <=1){
            num1 = num1 + tecla;
            cualnum = 1; 
            }
        if (cualnum ==2){
            num2 = num2 + tecla;
            }
    }
    // tecla punto decimal
    if (tecla=='.' and haypunto==0){
        if (cualnum ==1 or cualnum ==0){
            tamano = num1.length();
            if (tamano==0)
            {num1= "0.";}
            else
            {num1 = num1 + tecla;}
        }
        if (cualnum ==2){
            tamano = num2.length();
            if (tamano==0)
            {num2= "0.";}
            else
            {num2 = num2 + tecla;}
        }
        haypunto = 1;
    }
    //tecla de Operacion
    if (cualnum >= 1 && (tecla == '+' || 
    tecla == '-' || tecla == '*' || 
    tecla == '/')){   
        operador = tecla; 
        cualnum = 2;
        haypunto = 0; 
        }
    // obtener resultado
    if (tecla == '=' && cualnum == 2){
        if (operador == '+') 
        {resultado = numA + numB;}
        if (operador == '-')
        {resultado = numA - numB;}
        if (operador == '*')
        {resultado = numA * numB;}
        if (operador == '/')
        {resultado = numA / numB;}
        num1 = String(resultado);
        num2 = "";
        cualnum = 2;
        haypunto = 0;
        }
    //tecla C Clear
    if (tecla == 'C'){
        cualnum = 0;
        num1 = "";
        num2 = "";
        operador = ' ';
        resultado = 0;
        haypunto = 0;
        }
    numA = num1.toFloat();
    numB = num2.toFloat();

    // SALIDA A PANTALLA LCD
    lcd.clear();
    lcd.setCursor(0,0);
    // muestra decimales = 3
    lcd.print(numA,3);
    if (numB!=0){
        lcd.setCursor(0,1);
        lcd.print(numB,3);    
    }
    lcd.setCursor(mp-2,0);
    lcd.print (operador);
    }
}

Observaciones: Se peude cambiar el número de decimales a mostrar en «Salida a pantalla LCD»

Funciones personalizadas, Entrada/salida serie

Componentes: Arduino, cable USB.

Una forma de usar funciones personalizadas para cálculo en arduino, consiste en serparar las instrucciones de cálculo como una función separada del bloque/lazo principal.

Por ejemplo, se puede usar la forma polinómica de la serie de Taylor para una función no disponible de cálculos con la precisión deseada.

La operatividad se muestra usando como ejemplo la función factorial(),   enviando y recibiendo los valores por medio de la conexión por USB y el «monitor serie». Ejemplo:

Observe que se encuentra habilitado el uso de «nueva línea» y «cambio de línea» (NL & CR) , para que al presionar «ENTER» se considera ingresado todos los dígitos del número.

Funciones para cálculos

Para el ejemplo, se realiza el cálculo del factorial:

n! = 1 x 2 x 3 x … x n

float factorial(float n){
    float resultado = 1;
    int i = 2;
    for (i = 2; i<=n; i++){
        resultado = resultado*i;
    }
    return resultado;
}

En el resultado, la cantidad de dígitos  se extiende usando el tipo real (float). Como práctica,  cambie la variable resultado a tipo entero (int), actualice el programa en el arduino, y calcule para números mayores  a 7; observe y explique el resultado.

Envío y recepción de datos con «monitor Serie»

La prueba de la función se simplifica enviando y recibiendo datos por la conexión USB. La variable mensaje almacena un caracter enviado al arduino, validando que sea un dígito entre 0 y 9. Al presionar «ENTER» se cierra el mensaje, se cambia el valor a número a entero y se procede a usar la función factorial para mostrar el resultado.

// funciones personalizadas para cálculo
// ingreso y salida por 'monitor serial'
// el mensaje se procesa por dígitos número hasta presional ENTER
//    y se convierte a número, para usar la función

String mensaje = "";
void setup() {
    Serial.begin(9600);
    while (!Serial) {
        // espera por conexion serial, usar solo con USB
        }
    Serial.println("\n calcula un factorial(): \n");
}
void loop() {
    int uncaracter = 0;
    int numero = 0;
    float resultado = 0.0;
    while (Serial.available() > 0) {
        uncaracter = Serial.read();
        if (isDigit(uncaracter)) {
            mensaje = mensaje + (char)uncaracter;
            }
        if (uncaracter == '\n') {
            numero = mensaje.toInt();
            Serial.print("mensaje: ");
            Serial.println(mensaje);
            Serial.print("numero es: ");
            Serial.println(numero);


            resultado = factorial(numero);
            Serial.print("factorial(numero): ");
            Serial.println(resultado);
            
            mensaje = "";
            }
    }
}

float factorial(float n){
    float resultado = 1;
    int i = 2;
    for (i = 2; i<=n; i++){
        resultado = resultado*i;
    }
    return resultado;
}

Para probar otras funciones, modifique los mensajes siguiendo el contexto del problema a resolver.

Referencias:

Arduino Serial read , Arduino lista de funciones básicas .