UPDATED Section 4 on 20130301 to show Analog Pin Read (APR) code and updated Digital Pin Read (DPR) code.

I recently went Googling for examples of calculator programs (sketches) for my Arduino Nano.  I found a number of examples on how to interface an Arduino to the keyboard of an old calculator, but did not get any hits of pre-written sketches for turning an Arduino into a scientific calculator... you know, the ones with Sin, Cos, Tan, and etc. (Excepting one clever implementation of a full version of an HP 45 but it required a massive IBM PS/2 keyboard.)

Why would anyone want such a thing?  The answer to this question is probably why I could not find anything on the Internet!  But I had my reasons and so I was forced to write my own sketch.  I sat down with paper and pencil and wrote down (while looking at my old HP instruction manual from college) and came up with a list of things I wanted: the obvious +, -, *, and / (add, subtract, multiply, and divide) and the more involved ones: Sin, Cos, Tan, SQR, Log, and so on.  Then there were the nice to have power functions.  Then the arcSin, arcCos, and arcTan stuff.  The list got a bit long... too long to assign a single keyboard character to each operation.

Then there was the concern about how to get my input into the Arduino.  Generally, one types in something and presses the Enter Key to confirm that they are finished with that entry.  Then the next bit, and then the next bit... each followed with that Enter key.  I'm not particularly fond of the Enter key so I wanted to send everything to the Arduino at one time:  The operation to perform and one or two numbers as required.  All I wanted the Arduino software to do was spit back the answer!  After finishing the program, the bulk of the code is in the area of sending back things that I really did not want... for testing and such.  So, I created two ways to build the application, one with all the voluminous output and one with just the answer; I call this verbose mode and the obvious non-verbose mode.  Verbose mode is useful if you want the operator prompted for each value and for viewing settings such as Decimals and Degree-Radians.

Step 1: Arduino Scientific Calculator - Commands

I implemented a number of commands once I got the hang of it... single variable commands look mostly the same and double variable commands look nearly the same... so, cut&paste makes for easy expansion.

Commands are not case-sensitive; so, div and DIV and diV all mean the same thing.  All numeric input less than 1 MUST HAVE A LEADING ZERO:  So, div 3.4 0.45 is valid and div 3.4 .45 IS NOT VALID

Currently the commands are;

"DIV", divide
"MUL", multiply
"ADD", add
"SUB", subtract
"Y^X", raise Y to X power
"LOG", log x
"NLG", natural log x
"10X", 10 raised to X power
"1/X", reciprocal
"e^X", Euler's number raised to X power
"SQR", Square Root
"X^2", X squared
"SIN", sin of X
"COS", cos of X
"TAN", tan of X
"ASN", arcsin of X
"ACS", arccos of X
"ATN", arctan of X
"DEG", mode = degrees (default)
"RAD", mode = radians
"DEC", display decimal places
"RTT", hypotenuse with x and y legs
"DPR", 328P digital pin# read (experimental)
"APR", 328P analog pin# read (not implemented)
"LTX", Last value displayed, 0 initially
how many decimal of pi can you get it to calculate?
... In calculations, 355 DIV 113 comes in very close to Pi<br><br>Ray
Pi is a constant in the code: <br>float Pi = 3.141592654; <br> <br>Decimals default to 7 places. You can override this in script to execute: <br>(but remember that floats in Arduino are only 4-byte IEEE numbers, so 10 digits really does not make a lots of sense.) <br> <br>byte decimals = 7; <br>&lt;...&gt; <br>case 20: // DEC set decimal places <br> if (verbose) {Serial.print(F(&quot;Prompting for Decimal places 0-10: &quot;)); } <br> b = Serial.parseInt(); <br> if (b&gt;10) {b = 10; } <br> decimals = b; <br> if (verbose) {Serial.print(F(&quot; Decimal Places = &quot;)); <br> Serial.print(b); } <br> if (verbose) {Serial.println(); } <br> break; <br>
I love it Ray. I'm thinking about changing verbose to a boolean and set/clear it via VM+ VM- commands. Also maybe storing LastX into a circular array or 255 values and being able to use past values via an ANS -N (or could use a STO to store it at a location). You may want to include functions to set the pins I or O and to enable the pull up resistors. A matrix solver could also be useful as well as unit conversions... the list goes on and on :-) <br>Best Wishes
Writing this was an educational exercise for me since I wanted to play with the new Arduino 1.0+ streaming commands. The for-loop serial parser really needs a new architecture if many more commands are needed to minimize the loop delay. Also, I should have used a compiler directive instead of the 'verbose' implementation used.<br><br>But, all in fun. Another idea would be to use eeprom to implement numerous physical constants instead of inline code.<br><br>The IO extension may actually be the most productive use of this concept because it could allow some remote intelligence to be added via RF RS232 comm. In such an implementation, I would op to create a response channel so that the main uC actually knows that the remote did its bidding.<br><br>Evolve and repost! Also a thread is open in the Arduino forum:<br> Arduino Forum :: <br>Community :: <br>Exhibition / Gallery :: <br>Don't Cross The Streams (FP scientific calculator serial co-processor)<br><br>Thanks!

About This Instructable




Bio: Ray Burne is my pseudonym, I sometimes write on various Blogs and Sites. Effective 12 June 2013, Ray has decided to no longer participate as ... More »
More by RayBurne:Minty Magic Morse - Arduino Style PICAXE Pitcher Perfect Thermometer A PICAXE Infrared "logging" Thermometer 
Add instructable to: