Mitt första program - miniräknare. Kommentarer ?

Jag är ny på allt, har inte skrivit en programrad sedan jag höll på med ABC800 och assembler på Motorola 6800 i gymnasiet på 80-talet. Nu ville gubben lära sig igen. Detta är mitt första egna program utöver startkit-boken. Det fungerar och jag är nöjd själv.

Men jag vill gärna få kommentarer från er som är mer erfarna. Finns det andra sätt att göra detta som skulle vara effektivare och bättre?

/*
Calculator using remote control for keys
note: Calculation with float has 6-7 figures accuracy. But Serial.print and lcd.print only prints two deciamals

Jonteman
Linköping, Sweden
2015-04-12

*/

int receiver = 13; //PIN for remote reciever
int siffra; //single digit, numbers 0-9, values obove 10 for other functions
int decimal; // single digit after decimal dot
int numDeci = -1; //counter for number of decimals, starts with -1 for first decimal (as in 10 raised to -1)
int type; //type of calculation: 1=addition, 2=subtraction, 3=multiplication, 4=division
int deci; //marker for decimal dot
int fini; //marker finished
int row; //row in display
int pos; //position in display
float value; // aggregated value with all digits
float prevValue;
float firstValue; //First value in calculation
float answer;

// LCD-library
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //PIN: 12=RS, 11=EN , 2-5 = D4-D7)

//Library for remote control
#include "IRremote.h"
IRrecv irrecv(receiver); // create instance of 'irrecv'
decode_results results; // create instance of 'decode_results'

void setup() {
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
lcd.begin(16, 2); //Declare size of LCD (16 digits, 2 rows)
lcd.print ("Jonas Arduino ");
lcd.setCursor (pos, row + 1);
lcd.print ("Calculator");
}

void loop() {
if (irrecv.decode(&results)) { // have we received an IR signal?
// Serial.println(results.value, HEX); //UN Comment to see raw values
translateIR();
irrecv.resume(); // receive the next value
if (siffra < 10 ) { // digit
if (value == 0) { //first digit
if (prevValue == 0) {
lcd.clear ();
}
value = siffra;
prevValue = siffra;
lcd.setCursor (pos, row);
lcd.print (siffra);
pos ++;
}
else { //following digits
if (deci == 0) { //integer
value = prevValue * 10 + siffra; //tenfold last digit and add new digit
prevValue = value;
lcd.setCursor (pos, row);
lcd.print (siffra);
pos ++;
}
else { //decimal number
decimal = siffra; //convert from int to float
value = prevValue + decimal * pow(10, numDeci); //10 raised to negtive numbers of decimals gives a tenfold lower for each decimal
prevValue = value;
numDeci --;
lcd.setCursor (pos, row);
lcd.print (siffra);
pos ++;
}
}
}
else { //non digit button pushed
switch (siffra) {
case 11: plus(); break ;
case 12: minus(); break ;
case 13: multiplication(); break ;
case 14: division(); break ;
case 15: equal(); break ;
case 20: dot(); break;
case 100: reset(); break ;
}
}
Serial.println (" ");
Serial.print ("Siffra ");
Serial.println (siffra);
Serial.print ("PrevValue ");
Serial.println (prevValue);
Serial.print ("Value ");
Serial.println (value);
Serial.print ("firstValue ");
Serial.println (firstValue);
Serial.print ("Answer ");
Serial.println (answer);
Serial.print ("Deci ");
Serial.println (deci);
}
if (irrecv.decode(&results) && fini != 0) { // reset from next button after equal
reset();
irrecv.resume();
}
}

void plus() {
firstValue = value;
value = 0;
deci = 0;
numDeci = -1;
type = 1;
lcd.setCursor (pos, row);
lcd.print ("+");
pos ++;
}

void minus() {
firstValue = value;
value = 0;
deci = 0;
numDeci = -1;
type = 2;
lcd.setCursor (pos, row);
lcd.print ("-");
pos ++;
}

void multiplication() {
firstValue = value;
value = 0;
deci = 0;
numDeci = -1;
type = 3;
lcd.setCursor (pos, row);
lcd.print ("*");
pos ++;
}

void division() {
firstValue = value;
value = 0;
deci = 0;
numDeci = -1;
type = 4;
lcd.setCursor (pos, row);
lcd.print ("/");
pos ++;
}

void dot() {
deci = 1;
lcd.setCursor (pos, row);
lcd.print (",");
pos ++;
}

void equal() {
switch (type) {
case 1: answer = firstValue + value; break ;
case 2: answer = firstValue - value; break ;
case 3: answer = firstValue * value; break ;
case 4: answer = firstValue / value; break ;
}
lcd.setCursor (0, row + 1);
lcd.print ("= ");
lcd.print (answer);
fini++;
}

void reset() {
siffra = 0;
value = 0;
prevValue = 0;
firstValue = 0;
answer = 0;
decimal = 0;
deci = 0;
numDeci = -1;
type = 0;
fini = 0;
pos = 0;
row = 0;
lcd.clear ();
lcd.print ("Jonas Arduino ");
lcd.setCursor (pos, row + 1);
lcd.print ("Calculator");
}

void translateIR() {
switch (results.value) {
case 0xFF4AB5: siffra = 0 ; break;
case 0xFF6897: siffra = 1 ; break;
case 0xFF9867: siffra = 2 ; break;
case 0xFFB04F: siffra = 3 ; break;
case 0xFF30CF: siffra = 4 ; break;
case 0xFF18E7: siffra = 5 ; break;
case 0xFF7A85: siffra = 6 ; break;
case 0xFF10EF: siffra = 7 ; break;
case 0xFF38C7: siffra = 8 ; break;
case 0xFF5AA5: siffra = 9 ; break;
case 0xFF629D: siffra = 11 ; break; //Button FORWARD = plus
case 0xFFA857: siffra = 12 ; break; //Button REVERSE = minus
case 0xFF22DD: siffra = 13 ; break; //Button LEFT = multiplication
case 0xFFC23D: siffra = 14 ; break; //Button RIGHT = division
case 0xFF02FD: siffra = 15 ; break; //Button OK = equal
case 0xFF52AD: siffra = 20 ; break; //Button # = dot
case 0xFF42BD: siffra = 100 ; break; //Button * = reset
case 0xFFFFFFFF: siffra = 100 ; break; //"REPEAT", not used
default:
Serial.println(" other button ");
}
delay(500); // Do not get immediate repeat
}

/* ( THE END ) */

Hej,

fungerar det? Så är det bra nog.

Det ensta jag tycker som "fel" är

value = prevValue + decimal * pow(10, numDeci);

Om du kollar så är pow() en float funktion, så du riskerar at du får afrundingsproblem. Tar också tid (som inte spelar nån roll här, men i andre program kunne vara ett problem)

Kolla mit nnnC bibliotek som också konverterer från ciffror til et tal - här gør jeg et stort heltal, og dividerer ned antal decimaler når talet är afslutet.

I print (som är samme print til både Serial og lcd) så kan man ange antallet decimaler Serial.println(1.23456, 4) gives "1.2346"Reference

OCH - när du cut-n-paster ind et program så tryk på "code" knappen - så ligger det i en seperat box där kantparanteser ikke forvandlas

Tack !
Jag tittade på ditt bibliotek men det är nog lite för avancerat för mig just nu. Jag tyckte faktiskt min lösning med negativa exponenter för att skapa decimaler var lite kreativ. Tog ett tag att komma på i alla fall :slight_smile:
Tipset om decimaler var värdefullt. Jag letade också länge efter "felet" som gjorde att jag bara fick två decimaler innan jag hittade att det satt i print. Nu har jag lösningen också.