查看: 2571|回复: 35

[项目] 基于红外接收器与1602的简化科学计算器

[复制链接]

该用户从未签到

发表于 2018-5-16 01:39 | 显示全部楼层 |阅读模式
本帖最后由 52hpfans 于 2018-6-15 01:43 编辑

上图展示效果
IMG_4565.PNG

硬件:
arduino uno r3
红外接收器和遥控器
1602显示屏
面包板
杜邦线
滑动变阻器
接线方式:
缺图待补,可参考红外接收器与1602显示屏接线教程
实现功能:
光标移动、屏幕显示表达式的删除与更改,最多可输入29个字符
视频待补
目前存在bug:
目前受限于uno的double,无法将较大的数转为double,小数点后只能精确到两位, (计算错误问题已debug解决)
遗憾之处:未加入ans功能

正文:
本计算器采用类似下图遥控器
QQ20180516-013531@2x.png


程序如下:

kittenblock中小学创客名师推荐的图形化编程软件

#include <IRremote.h>
#include <IRremoteInt.h>
#include <LiquidCrystal.h>

const int RECV_PIN = 9;    
short int data = 0;   
short int gloc = 0; 
char screen[30];
short int ifoperator[30];
byte minus[8] = {
        B00000,
        B00000,
        B00000,
        B01110,
        B00000,
        B00000,
        B00000,
};                
IRrecv irrecv(RECV_PIN);   
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(13, 12, 5, 4, 3, 2);
decode_results irresults;

double calculation(double num[], short int operator_typ[], short int operator_num){
        //change nifix expression to postfix expression
        short int total_length = (sizeof(num) / sizeof(num[0])) + operator_num;
        short int *stack = new short int[operator_num]{};
        short int *store = new short int[total_length]{};
        *store = 0;
        short int compare = -1;
        int location_store = 1;
        int location_stack = 0;
        for(short int i=0; i<operator_num; i++){        
                if(i == 0){
                   *(stack + location_stack) = operator_typ;
                        compare = operator_typ;
                        location_stack++; 
                }
                else{
                        if(compare < 3 && operator_typ > 3){
                                *(stack + location_stack) = operator_typ;
                                compare = operator_typ;
                                location_stack++;        
                        }
                        else if(operator_typ < 3){
                                for(int j=location_stack-1; j>=0; j--){
                                        *(store + location_store + (location_stack -1 - j)) = *(stack + j); 
                                }
                                location_store = location_store + location_stack;
                                location_stack = 0;
                                *(stack + location_stack) = operator_typ;
                                location_stack++;
                        }
                        else{
                                while(*(stack + location_stack -1) > 3){
                                *(store + location_store) = *(stack + location_stack -1); 
                                location_store = location_store + 1; 
                                location_stack --;
                                }
                                *(stack + location_stack) = operator_typ;
                                compare = operator_typ;
                                location_stack++;
                        }
                }
                *(store + location_store) = 0;
                if(i == operator_num-1){
                        for(int j=location_stack-1; j>=0; j--){
                                *(store + location_store + (location_stack - j)) = *(stack + j); 
                        }
                        location_store = location_store + location_stack;
                }
                location_store++;
        }
        delete stack;
        char fin_store[29];
        for(int i=0; i<location_store; i++){ 
                fin_store = char(*(store + i)); 
        }
        fin_store[location_store] = '\0';
        //start calculation
        double *num_stack = new double[operator_num]{};
        short int numstack_loc = 0;
        short int numloc = 0;
        for(int i=0; i<location_store; i++){
                switch (fin_store) {
                        case 0x00:
                        *(num_stack + numstack_loc) = num[numloc];
                        numloc++;
                        numstack_loc++;
                        break;
                        case 0x01:
                        *(num_stack + (numstack_loc - 2)) = *(num_stack + (numstack_loc - 2)) - *(num_stack + (numstack_loc - 1));
                        numstack_loc--;
                        break;
                        case 0x02:
                        *(num_stack + (numstack_loc - 2)) = *(num_stack + (numstack_loc - 2)) + *(num_stack + (numstack_loc - 1));
                        numstack_loc--;
                        break;
                        case 0x04:
                        *(num_stack + (numstack_loc - 2)) = *(num_stack + (numstack_loc - 2)) / *(num_stack + (numstack_loc - 1));
                        numstack_loc--;
                        break;
                        case 0x05:
                        *(num_stack + (numstack_loc - 2)) = *(num_stack + (numstack_loc - 2)) * *(num_stack + (numstack_loc - 1));
                        numstack_loc--;
                        break;
                }
        }
        double result = *(num_stack);
        return result;
        delete store;
        delete num_stack;
        store = NULL;
        stack = NULL;
        num_stack = NULL;
}

double str2double(char mat[], short int size){        //transfer str into double
        char *temp = new char[size]{};
        char *temp_p;
        temp_p = temp;
        for(short int i=0; i<size; i++){
                *(temp + i) = mat; 
                if(i != 0 && mat == '-'){
                  synError();
                  irrecv.resume();
                  irrecv.decode(&irresults);
                  while(irresults.value != 0xFFC23D && irresults.value != 0xFFA25D && irresults.value != 0xFFE21D){
                            delay(100);
                            irrecv.resume();
                            delay(100);
                            irrecv.decode(&irresults);
                        }
                        lcd.noBlink();
                        lcd.noCursor();
                        lcd.setCursor(0,0);
                        gloc = 0;
                }
        }
        *(temp + size) = '\0';
        double dtemp = strtod (temp_p, NULL);
        delete [] (temp);
        temp = NULL;
        return dtemp;
}

void synError() {
        lcd.clear(); 
        lcd.noCursor();
        lcd.noBlink();
        lcd.home();
        lcd.print("Syntax ERROR");
        lcd.setCursor(0,1);
        lcd.print("Press AC or DIR");
}

void setup() {
        Serial.begin(9600);
  irrecv.enableIRIn(); // enable ir receiver  
  // set up the LCD's number of columns and rows: 
  lcd.createChar(5, minus);
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.clear(); 
  lcd.cursor();
  lcd.blink();
  lcd.home();
}

void loop() {
        char ifequal = 0;
        char *screenchar;
        screenchar = screen;
        char input = 0;
        if(irrecv.decode(&irresults))   
        {
                switch (irresults.value) {
                        case 0xFF52AD:
                        lcd.blink();
                        lcd.cursor();
                        ifoperator[gloc] = 0;
                        screen[gloc]='9';
                        input = 1;
                        break;
                        case 0xFF4AB5:
                        lcd.blink();
                        lcd.cursor();
                        ifoperator[gloc] = 0;
                        screen[gloc]='8';
                        input = 1;
                        break;
                        case 0xFF42BD:
                        lcd.blink();
                        lcd.cursor();
                        ifoperator[gloc] = 0;
                        screen[gloc]='7';
                        input = 1;
                        break;
                        case 0xFF5AA5:
                        lcd.blink();
                        lcd.cursor();
                        ifoperator[gloc] = 0;
                        screen[gloc]='6';
                        input = 1;
                        break;
                        case 0xFF38C7:
                        lcd.blink();
                        lcd.cursor();
                        ifoperator[gloc] = 0;
                        screen[gloc]='5';
                        input = 1;
                        break;
                        case 0xFF10EF:
                        lcd.blink();
                        lcd.cursor();
                        ifoperator[gloc] = 0;
                        screen[gloc]='4';
                        input = 1;
                        break;
                        case 0xFF7A85:
                        lcd.blink();
                        lcd.cursor();
                        ifoperator[gloc] = 0;
                        screen[gloc]='3';
                        input = 1;
                        break;
                        case 0xFF18E7:
                        lcd.blink();
                        lcd.cursor();
                        ifoperator[gloc] = 0;
                        screen[gloc]='2';
                        input = 1;
                        break;
                        case 0xFF30CF:
                        lcd.blink();
                        lcd.cursor();
                        ifoperator[gloc] = 0;
                        screen[gloc]='1';
                        input = 1;
                        break;
                        
                        case 0xFFB04F:
                        lcd.blink();
                        lcd.cursor();
                        ifoperator[gloc] = 0;
                        screen[gloc]='-';        
                        input = 1;
                        break;

                        case 0xFF9867:
                        lcd.blink();
                        lcd.cursor();
                        ifoperator[gloc] = 0;
                        screen[gloc]='.';
                        input = 1;
                        break;

                        case 0xFF6897:
                        lcd.blink();
                        lcd.cursor();
                        ifoperator[gloc] = 0;
                        screen[gloc]='0';
                        input = 1;
                        break;
                        case 0xFF906F:
                        ifequal = 1;
                        break;
                        case 0xFFA857:
                        lcd.blink();
                        lcd.cursor();
                        ifoperator[gloc] = 2;
                        screen[gloc]='+';
                        input = 1;
                        break;
                        case 0xFFE01F:
                        lcd.blink();
                        lcd.cursor();
                        ifoperator[gloc] = 1;
                        screen[gloc]='-';
                        input = 1;
                        break;
                        case 0xFFC23D:                        //clear
                        lcd.blink();
                        lcd.cursor();
                        screen[30] = {};
                        for(short int i=0; i<30; i++){
                                ifoperator = 3; 
                        }
                        lcd.clear();
                        lcd.home();
                        gloc = 0;
                        data = 0;
                        break;
                        case 0xFF02FD:
                        lcd.blink();
                        lcd.cursor();
                        ifoperator[gloc] = 5;
                        screen[gloc]='*';
                        input = 1;
                        break;
                        case 0xFF22DD:
                        lcd.blink();
                        lcd.cursor();
                        ifoperator[gloc] = 4;
                        screen[gloc]='/';
                        input = 1;
                        break;
                        case 0xFFE21D:                        // cursor move right
                        lcd.blink();
                        lcd.cursor();
                        if(gloc == data){
                                break;    
                        }
                        else{
                                if(gloc >= 15){
                                        lcd.scrollDisplayLeft(); 
                                        lcd.setCursor(gloc+1,0);
                                        gloc = gloc + 1; 
                                }
                                else{
                                        lcd.setCursor(gloc+1,0);
                                        gloc = gloc + 1;
                                }
                                break;
                        }

                        case 0xFF629D:                //delete
                        lcd.blink();
                        lcd.cursor();
                        if(gloc > 0){
                                if(gloc == data){
                                        gloc = gloc - 1;
                                        data = data - 1;
                                        lcd.setCursor(gloc,0);
                                        lcd.write(byte(0x20));
                                        lcd.setCursor(gloc,0);
                                        if(gloc >= 15){
                                                lcd.scrollDisplayRight(); 
                                        }
                                }
                                else{
                                        for(int i = 0; i < data - gloc - 1; i++){
                                                screen[gloc + i] = *(screenchar + gloc + i + 1);
                                                ifoperator[gloc + i] = ifoperator[gloc + i + 1];
                                                if(*(screenchar + gloc + i) == '-' && ifoperator[gloc + i] == 0){
                                                        lcd.write(byte(5));
                                                }
                                                else{
                                                        lcd.print(*(screenchar + gloc + i )); 
                                                }
                                        }
                                        data =data - 1;
                                        lcd.write(byte(0x20));
                                        lcd.setCursor(gloc,0);
                                }
                        }
                        break;
                        case 0xFFA25D:                        //cursor move left
                        lcd.blink();
                        lcd.cursor();
                        if(gloc == 0){
                                break;    
                        }
                        else{
                                if(gloc > 15){
                                        lcd.scrollDisplayRight(); 
                                        lcd.setCursor(gloc-1,0);
                                        gloc = gloc - 1;
                                }   
                                else{
                                        lcd.setCursor(gloc-1,0);
                                        gloc = gloc - 1;
                                }
                                break;
                        }
                }
                /* switch finish */
                if(data < 29){
                        if(gloc == data){
                                if(input == 1){
                                        if(*(screenchar + gloc) == '-' && ifoperator[gloc] == 0){
                                                lcd.write(byte(5));
                                        }
                                        else{
                                                lcd.print(*(screenchar + gloc));
                                        }
                                        gloc = gloc + 1;
                                        data = data + 1;
                                        if(gloc > 15){ 
                                                lcd.scrollDisplayLeft(); 
                                        }
                                }
                        }

                        else{
                                if(input == 1){
                                        //Serial.println(*(screenchar + gloc));
                                        if(*(screenchar + gloc) == '-' && ifoperator[gloc] == 0){
                                                lcd.write(byte(5));
                                        }
                                        else{
                                                lcd.print(*(screenchar + gloc));
                                        }
                                        gloc = gloc + 1;
                                        if(gloc > 15){ 
                                                lcd.scrollDisplayLeft(); 
                                        }
                                }
                        }
                }
                irrecv.resume();
        }
        if(ifequal == 1){                                                //equal button is pressed        
                        if(gloc > 15){
                                lcd.home();
                        }        
                        short int operator_num = 0;                                        //the number of operator
                        for(short int i = 0; i < data; i++){
                                if(ifoperator != 0){
                                        operator_num++;                                //obtain the number of operator
                                }        
                        }
                        if(operator_num == 0){
                                lcd.setCursor(0,1);
                                lcd.print("=");
                                char numtemp1[data];
                                        for(short int i=0; i<data; i++){
                                                numtemp1= *(screenchar + i);
                                        }
                                        double num1 = str2double(numtemp1, data);
                                        if(num1 < 0){
                                            num1 = -1.0 * num1;
                                            lcd.write(byte(5));
                                            lcd.print(num1);
                                        }
                                        else{
                                                lcd.print(num1);
                                        }
                        }
                        else{
                                double num[operator_num + 1];
                                short int *operator_loc = new short int[operator_num + 2]; //array to store the location of the operator
                                short int *operator_typ = new short int[operator_num]; //array to store the type of the operator
                                operator_loc[0] = -1;
                                operator_loc[operator_num + 1] = data;
                                //store the location and the type of operator
                                short int count = 0;
                                for(short int i = 0; i < data; i++){
                                        if(ifoperator != 0){
                                                operator_loc[count + 1] = i;
                                                operator_typ[count] = ifoperator;
                                                count++;
                                        }        
                                }
                                //store the numbers between the operators
                                short int noERROR;
                                for(short int i=0; i<operator_num + 1; i++){
                                        short int temp = operator_loc[i + 1] - operator_loc -1;
                                        noERROR = temp;
                                        if(temp == 0){
                                                synError();
                                                irrecv.resume();
                                                irrecv.decode(&irresults);
                                                delay(100);
                                                while(irresults.value != 0xFFC23D && irresults.value != 0xFFA25D && irresults.value != 0xFFE21D){
                                                    delay(100);
                                                    irrecv.resume();
                                                    delay(100);
                                                    irrecv.decode(&irresults);
                                                    Serial.println(1);
                                                }
                                                break;
                                        }
                                        else{
                                                char numtemp[temp];
                                                for(short int j=0; j<temp; j++){
                                                        numtemp[j]= *(screenchar + operator_loc + 1 + j) ;
                                                }
                                                num = str2double(numtemp, temp);
                                        }

                                }
                                if(noERROR != 0){
                                        double result = calculation(num,operator_typ, operator_num);
                                        lcd.setCursor(0,1);
                                        lcd.print("=");
                                        if(result < 0){
                                            result = -1.0 * result;
                                            lcd.write(byte(5));
                                            lcd.print(result);
                                        }
                                        else{
                                                lcd.print(result);
                                        }
                                }
                        }
                        lcd.noBlink();
                        lcd.noCursor();
                        lcd.setCursor(0,0);
                        gloc = 0;                
                }
        }



代码注释确实有点少了,在最新的arduino上可编译成功,用sublime的deviot配上platformio也可编译上传。




该用户从未签到

 楼主| 发表于 2018-5-17 02:07 | 显示全部楼层
没人评论只能自己坐沙发了,已修改大量代码,除去了多个bug
  • TA的每日心情
    无聊
    2018-7-10 05:55
  • 签到天数: 4 天

    [LV.2]偶尔看看I

    发表于 2018-5-18 23:42 | 显示全部楼层
    应用想法很不错,感谢分享!

    该用户从未签到

    发表于 2018-6-3 11:15 | 显示全部楼层
    wxyyxr 发表于 2018-5-18 23:42
    应用想法很不错,感谢分享!

    不错,应该遥控器的写按键位标一下。

    该用户从未签到

    发表于 2018-6-4 17:47 来自手机 | 显示全部楼层
    楼主有视频图片吗

    该用户从未签到

     楼主| 发表于 2018-6-15 01:42 | 显示全部楼层
    shuidashen 发表于 2018-6-4 17:47
    楼主有视频图片吗

    有一小段视频,可惜貌似直接传不上来,也没上传过视频网站

    该用户从未签到

     楼主| 发表于 2018-6-15 01:45 | 显示全部楼层
    x534133715 发表于 2018-6-3 11:15
    不错,应该遥控器的写按键位标一下。

    上面那个表格和遥控器图片就是按键对应编码和对应功能,遥控器按键位置和表格中编码位置是一致的
  • TA的每日心情
    擦汗
    2018-8-23 10:16
  • 签到天数: 8 天

    [LV.3]偶尔看看II

    发表于 2018-8-15 10:09 | 显示全部楼层
    ouble calculation(double num[], short int operator_typ[], short int operator_num){         //change nifix expression to postfix expression         short int total_length = (sizeof(num) / sizeof(num[0])) + operator_num;         short int *stack = new short int[operator_num]{};         short int *store = new short int[total_length]{};         *store = 0;         short int compare = -1;         int location_store = 1;         int location_stack = 0;
  • TA的每日心情
    擦汗
    2018-8-23 10:16
  • 签到天数: 8 天

    [LV.3]偶尔看看II

    发表于 2018-8-15 10:10 | 显示全部楼层
    ouble calculation(double num[], short int operator_typ[], short int operator_num){
            //change nifix expression to postfix expression
            short int total_length = (sizeof(num) / sizeof(num[0])) + operator_num;
            short int *stack = new short int[operator_num]{};
            short int *store = new short int[total_length]{};
            *store = 0;
            short int compare = -1;
            int location_store = 1;
            int location_stack = 0;
    能解释一下这段的意思吗
    看不懂有些

    该用户从未签到

     楼主| 发表于 2018-8-20 17:17 | 显示全部楼层
    本帖最后由 52hpfans 于 2018-8-20 17:41 编辑
    ztw 发表于 2018-8-15 10:10
    ouble calculation(double num[], short int operator_typ[], short int operator_num){
            //change  ...

    https://www.cnblogs.com/chensongxian/p/7059802.html
    可以看下这个链接的文章,这个calculation这块主要实现了中缀表达式到后缀表达式的转换以及后缀表达式的计算。这个是通过两个堆栈来实现的,store这个堆栈中0代表数字,其他数字代表不同运算符
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    KittenBot杯第六届开源硬件开发大赛启动啦
    KittenBot杯第六届开源硬
    大赛简介: 第六届开源硬件开发大赛由Arduino中文社区发起 由KittenBot冠名赞助
    台灣兼職外約性感嬌嗲正妹line:802923
    台灣兼職外約性感嬌嗲正妹
    www.highbaby7788.com論壇看照約妹 LINE ID:pdlaa520 或者是802923 微信:ladyduola
    请问这个电机的编码电源和信号反馈是干嘛的
    请问这个电机的编码电源和
    25GA370直流减速电机带编码器,新手,求指导
    Arduino MEGA中文数据手册
    Arduino MEGA中文数据手册
    2018.9.23重新翻译整理 转载请注明来自Arduino中文社区,并附本帖链接 本帖地址:http
    原创 drawbot平面关节机械臂 教程直播贴
    原创 drawbot平面关节机械
    这个项目上个月就在做了,结构和代码反反复复改了多次,加上自己又太忙,一直没来得及
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表