Go Down

### Topic: Making a calculator using an Arduino (Read 19139 times)previous topic - next topic

#15
##### Apr 01, 2012, 09:01 am
I think one reason you have a bug is that there is just too much going on in the one function. As Nis\$hant inferred you should compartmentalise things.

Also I don't think you need all the array shuffling and IMO read_keypad() should return a human-readable value, ie 0-9 and + etc.

For example here's is a simpler way (I think)

Code: [Select]
`long num1;long num2;long result;long *curr_num = num1;byte key;loop () { key = read_keypad(); // this should return an int == to the numeric key entered or obvious values for '=' etc switch (key) { case '+':     if (curr_num == num1) { // if first number just start accululating into second number curr_num = num2; } else { addNumbers(); // if the second number add them } break; case '=': addNumbers(); break; default: accumulateNumber(); display_number(curr_num); }}void addNumbers () { result = num1 + num2; display_number(result); curr_num = num1; num1 = 0; num2 = 0;}void accumulateNumber () { *curr_num *= 10; *curr_num += key;}void display_number(long * num){ for (int x = 0; x < 8, x++) { shiftNum (num % 10); // send digit out num /= 10; }}`

This is little more than psuedo code and there's no error checking etc but I think it's easy to follow and if there's a bug it should be easy to isolate.

______
Rob

Rob Gray aka the GRAYnomad www.robgray.com

#### Nishant_Sood

#16
##### Apr 01, 2012, 09:30 am
Yes Sir ROB i used to do similar coding while i programmed addition/subtraction/division/multiplication calculator back 2 years from now in VB.
The approach is pretty simple and easy to grasp while Mr. Serje  may not have any fault in his programme but due to increased cluttering he might not be able to stay on the correct logical path.
"Real Men can Accomplish  Anything"

- skype : nishants5
ਫ਼ਤੇਹ ਕਰੁਂ!
www.winacro.com

#### Techone

#17
##### Apr 02, 2012, 01:39 am

Thanks for your idea. I may change my code if I have issues. Oh yes... I still do... will change the code later.

@NI\$HANT

I agree with you. I may have to change my code for a modular method of coding. I have to many if()'s. I will have to do that later.

Updated :

I did re-code the add section, no modular method yet. Still have an issues with the keypad. I have : Double entry and  wrong entry. All intermittents problems. I may have to re-design the keypad circuit. Right now, it is not reliable.

As for the code, after the Add section change, still some bugs... But I like the new methode of adding.  Just like :

Carry : 1111
1234 <-- Array call : digit_number[]
+  9876 <-- Array call : add_number[]
-------
Last Digit ->11110   The last digit is the OverFlow.  So I add two array + the carry.  That is the logic behind the Add routine.

The section that work : entry routine, the clear routine, keypad routine, convert routine and the display routine.
I will use the Serial Monitor to see what is going on.

The updated code is the next post.

Thank for the idea. I will apreaciated that you guys check my code.

#### Techone

#18
##### Apr 02, 2012, 01:41 am
Here my updated code :

Code: [Select]
`/*   size : 2648 bytes      Calculator Version 1.5      Just add a number enter by the keypad and display it.   With 2 function : Add / Equal ===> * button                      Clear ==>  # button   It will use a MAX7219 for display the data ( for the shiftOut() ).   and a 4021 for the keypad input data with the use of    an NOT gate 74HC14. ( for the shiftin() )   See the keypad example in the tread for details.     The interrupt use a 72LS20 from the row pins, any LOW signal will   produce a HIGH pulse to be use has an interrupt signal.   By Serge J Desjardins   aka techone / tech37   Toronto, Ontario, Canada   Compile and Tested.   */// Keypad Serial pinsconst byte latchkeypin = 10;const byte datakeypin = 12;const byte clockkeypin = 11;// Display Serial pinsconst byte datadisplaypin = 9;const byte clockdisplaypin = 8;const byte latchdisplaypin = 7;// Anykey and interrupt pinconst byte anykeypin = 2;// MAX7419 init dataword initdata[5] = { 0x0C01, 0x0F00, 0x0A0B, 0x0B07, 0x09FF };// Fill the Display array with a blank codeword display_data[8] = { 0x0100, 0x020F, 0x030F, 0x040F, 0x050F, 0x060F, 0x070F, 0x080F };  // The digit arraybyte digit_number[8] = {0,0,0,0,0,0,0,0};// The second array - The total numberbyte add_number[9] = {0,0,0,0,0,0,0,0,0};// Key press keypad flag volatile boolean keystate;// Overflow flagboolean over_flow;// add button flagboolean add_flag;// Clear button flagboolean clear_flag;// The keypad data byte keydata;byte keynumber;void setup() {  //start serial  //Serial.begin(9600);  //define the pins modes  pinMode(latchkeypin, OUTPUT);  pinMode(clockkeypin, OUTPUT);   pinMode(datakeypin, INPUT);  pinMode(datadisplaypin, OUTPUT);  pinMode(clockdisplaypin, OUTPUT);  pinMode(latchdisplaypin, OUTPUT);  pinMode(anykeypin, INPUT);  // setup the interrupt pin  attachInterrupt(0,anykeypress,RISING);    /* Init the MAX7419 : Normal Mode                        Normal Operation                        Setting the Intensity                        Numbers of Digits being display                        Set to Decode Mode  */   for (int i=0;i<5;i++)  {       digitalWrite(latchdisplaypin, LOW);     shiftOut(datadisplaypin, clockdisplaypin, MSBFIRST, highByte(initdata[i]));     shiftOut(datadisplaypin, clockdisplaypin, MSBFIRST, lowByte(initdata[i]) );     digitalWrite(latchdisplaypin, HIGH);     delay(5);  }  // Blank the display  display_the_numbers();  // init the flags and the calculation variable  keystate = 0;    add_flag = 1;  over_flow = 0;  clear_flag = 1;  }  void loop(){    while ( keystate == 0)   {      // wait for a key press   }  read_keypad();  convert_the_keypad_data();  // Enter the numbers routine    if ( ( keynumber < 0x0A ) && ( over_flow == 0 ) )  {       if ( ( add_flag == 1) && ( clear_flag = 1 ) )     {       for (int i=0;i<8;i++)       {         digit_number[i] = 0;               display_data[i] = word ( ( i+1 ), 0x0F );       }           }         // Enter the key number and move the arrays data.          for (int i=7;i>0;i--)     {       digit_number[i] = digit_number[i-1];       display_data[i]=display_data[i-1];       display_data[i] = word ( (i+1) , lowByte( display_data[i] ) );     }     digit_number[0] = keynumber;          display_data[0] = word ( 1, keynumber );          display_the_numbers();     add_flag = 0;     clear_flag = 0;     keystate = 0;      }  else  {    // Check for the "Add / Equal" button    if ( ( keynumber == 0x0B ) && ( over_flow == 0) )    {            for (int i=0;i<8;i++)      {         add_number[i] = add_number[i+1] + add_number[i] + digit_number[i];         if (add_number[i] > 0x09 )         {           add_number[i+1] = 1;           display_data[i] = word ( ( i + 1 ), ( add_number[i] - 10 ));          }         else          {            display_data[i] = word ( ( i + 1 ) , add_number[i]);         }              }              // check for over flow      if ( add_number[8] > 0)      {              over_flow = 1;        digit_number[0] = 0;                display_data[0] = 0x010B;        for ( int i=1;i<8;i++)        {           digit_number[i] = 0;           display_data[i] = word( (i+1), 0x0F );                       }              keystate = 0;        over_flow = 1;        add_flag = 1;              display_the_numbers();                 }      else       {        keystate = 0;        over_flow = 0;        add_flag = 1;        display_the_numbers();      }          }        // Check for the "Clear" button     if ( keynumber == 0x0E )    {      digit_number[0] = 0;      add_number[0] = 0;      display_data[0] = 0x0100;      for ( int i=1;i<8;i++)      {        digit_number[i] = 0;        add_number[i] = 0;        display_data[i] = word( (i+1), 0x0F );                     }      add_number[8] = 0;      keystate = 0;      over_flow = 0;      add_flag = 1;      clear_flag = 1;      display_the_numbers();         }      }     //For troubleshooting the program using Serial Monitor /*      Serial.print(keydata, BIN);    Serial.print("  ");    Serial.print(keydata, HEX);    Serial.print("  ");    Serial.print(keynumber, HEX);    Serial.print("  ");    Serial.println(keydata, DEC);    delay(1000);*/}// Read keypad data via a 74HC14 - Inverter from the 4021void read_keypad(){  digitalWrite(latchkeypin,HIGH);  delayMicroseconds(20);  digitalWrite(latchkeypin,LOW);  keydata = shiftIn(datakeypin, clockkeypin,LSBFIRST);  } // Convert the keypad data into BCD// And a code for *, 0, # buttonvoid convert_the_keypad_data(){  byte what_row;    what_row = ( keydata >> 3) & 0x0F;  switch ( what_row)  {    case 1:           keynumber = ( ( keydata >> 1 ) & 0x03 ) + 1;           break;    case 2:           keynumber = (( keydata >> 1 ) & 0x03 ) + 4;           break;    case 4:           keynumber = (( keydata >> 1 ) & 0x03 ) + 7;           break;    case 8:           special_key();           break;      }    }  // the display the data routine to the MAX7219 void display_the_numbers(){   for (int i=0;i<8;i++)   {     digitalWrite(latchdisplaypin, LOW);     shiftOut(datadisplaypin, clockdisplaypin, MSBFIRST, highByte(display_data[i]) );     shiftOut(datadisplaypin, clockdisplaypin, MSBFIRST, lowByte(display_data[i]) );     digitalWrite(latchdisplaypin, HIGH);     delay(5);   }  }// A special code for 0, *, # buttonvoid special_key(){   byte special_case;      special_case = ( ( keydata >> 1) & 0x03 ) + 1;   switch ( special_case )   {     case 1:            keynumber = 0x0E;            break;     case 2:            keynumber = 0x00;            break;     case 3:            keynumber = 0x0B;            break;   }        }// Interrupt Routibevoid anykeypress(){  keystate = 1; }  `

#### Techone

#19
##### Apr 02, 2012, 03:24 am
Updated :

I did place the sections into a routine way. I re-modify my code. Almost the same code, except a bit more "modular"

Issue : The Add section still give me some problems. Sometime, it work, and then it is not, I even see the Over Flow ==> E the Numbers are lock and the add button is lock <== That is expected, that mean it did go through the Add Section. The clear work just great.  Still have double entry, and I got the feeling my keypad circuit need to be change.  The cause is : When I press a key, the voltage level is not approaching a LOW level for the input of the 74HC14. It is in the "If Zone" <-- "Can Not Make Up It Mind Level". So I will re-design the keypad circuit with LM339, and add a 555 circuit in a monostable mode to take care of the interrupt signal <-- possible cause of the "double" entry. The interrupt signal came from a 74LS20. The 555 is the "deboucing" circuit. And also, I may add a latch chip between the 74LS14 ( that is the buffer after the LM339 output )  and the 4021. Maybe the 555 output ? , or another digital out pin to take care of that ?   555 is a more reliable.

As for my code, I will keep it and test it with the new keypad circuit. Well I may change a bit the Add section... I press Add, and it display : 0000012 . That is just cosmetic bug, I will fix that in the Add section. Just replace the 0 before the 1 with 0x0F <-- code for Display Blank to be send at the MAX7219.

I know, it is sound overkill, I need reliability, that is why I overkill in my circuits and code. I am trying to remove Murphay's Law of the equation.    Input + Murphay's Law = Garbage Output

Next post is the updated code.

#### Techone

#20
##### Apr 02, 2012, 03:27 am
Here the updated code. I will appreaciated that you guys look at it and tell me what you think.

Code: [Select]
`/*   size : 2734 bytes      Calculator Version 1.5      Just add a number enter by the keypad and display it.   With 2 function : Add / Equal ===> * button                      Clear ==>  # button   It will use a MAX7219 for display the data ( for the shiftOut() ).   and a 4021 for the keypad input data with the use of    an NOT gate 74HC14. ( for the shiftin() )   See the keypad example in the tread for details.     The interrupt use a 72LS20 from the row pins, any LOW signal will   produce a HIGH pulse to be use has an interrupt signal.   By Serge J Desjardins   aka techone / tech37   Toronto, Ontario, Canada   Compile and Tested. Still Issues. Maybe it it the Keypad circuit. Not so clean   */// Keypad Serial pinsconst byte latchkeypin = 10;const byte datakeypin = 12;const byte clockkeypin = 11;// Display Serial pinsconst byte datadisplaypin = 9;const byte clockdisplaypin = 8;const byte latchdisplaypin = 7;// Anykey and interrupt pinconst byte anykeypin = 2;// MAX7419 init dataword initdata[5] = { 0x0C01, 0x0F00, 0x0A0B, 0x0B07, 0x09FF };// Fill the Display array with a blank codeword display_data[8] = { 0x0100, 0x020F, 0x030F, 0x040F, 0x050F, 0x060F, 0x070F, 0x080F };  // The digit arraybyte digit_number[8] = {0,0,0,0,0,0,0,0};// The second array - The total numberbyte add_number[9] = {0,0,0,0,0,0,0,0,0};// Key press keypad flag volatile boolean keystate;// Overflow flagboolean over_flow;// add button flagboolean add_flag;// Clear button flagboolean clear_flag;// The keypad data byte keydata;byte keynumber;// The choicebyte choise;void setup() {  //start serial  //Serial.begin(9600);  //define the pins modes  pinMode(latchkeypin, OUTPUT);  pinMode(clockkeypin, OUTPUT);   pinMode(datakeypin, INPUT);  pinMode(datadisplaypin, OUTPUT);  pinMode(clockdisplaypin, OUTPUT);  pinMode(latchdisplaypin, OUTPUT);  pinMode(anykeypin, INPUT);  // setup the interrupt pin  attachInterrupt(0,anykeypress,RISING);    /* Init the MAX7419 : Normal Mode                        Normal Operation                        Setting the Intensity                        Numbers of Digits being display                        Set to Decode Mode  */   for (int i=0;i<5;i++)  {       digitalWrite(latchdisplaypin, LOW);     shiftOut(datadisplaypin, clockdisplaypin, MSBFIRST, highByte(initdata[i]));     shiftOut(datadisplaypin, clockdisplaypin, MSBFIRST, lowByte(initdata[i]) );     digitalWrite(latchdisplaypin, HIGH);     delay(5);  }  // Blank the display  display_the_numbers();  // init the flags and the calculation variable  keystate = 0;    add_flag = 1;  over_flow = 0;  clear_flag = 1;  }  void loop(){    while ( keystate == 0)   {      // wait for a key press   }  read_keypad();  convert_the_keypad_data();  // The choise 1 = numbers , 2 = add , 3 = clear  switch (choise)  {     case 1 :             entry_of_numbers();             break;     case 2 :             add_section();             break;     case 3 :             clear_section();             break;       }  }// Choise 1void entry_of_numbers(){    // Enter the numbers routine    if ( over_flow == 0 )  {       if ( ( add_flag == 1) && ( clear_flag = 1 ) )     {       for (int i=0;i<8;i++)       {         digit_number[i] = 0;               display_data[i] = word ( ( i+1 ), 0x0F );       }           }         // Enter the key number and move the arrays data.          for (int i=7;i>0;i--)     {       digit_number[i] = digit_number[i-1];       display_data[i]=display_data[i-1];       display_data[i] = word ( (i+1) , lowByte( display_data[i] ) );     }     digit_number[0] = keynumber;          display_data[0] = word ( 1, keynumber );          display_the_numbers();     add_flag = 0;     clear_flag = 0;     keystate = 0;      }}// Choise 2 - the add sectionvoid add_section(){    // Check for the "Add / Equal" button    if ( over_flow == 0 )    {            for (int i=0;i<8;i++)      {         add_number[i] = add_number[i+1] + add_number[i] + digit_number[i];         if ((add_number[i] > 0x09) && (add_number[i] < 0x14) )         {           add_number[i+1] = 1;           display_data[i] = word ( ( i + 1 ), ( add_number[i] - 10 ));          }         else          {            display_data[i] = word ( ( i + 1 ) , add_number[i]);         }              }              // check for over flow      if ( add_number[8] != 0)      {              over_flow = 1;        digit_number[0] = 0;                display_data[0] = 0x010B;        for ( int i=1;i<8;i++)        {           digit_number[i] = 0;           display_data[i] = word( (i+1), 0x0F );                       }              keystate = 0;        over_flow = 1;        add_flag = 1;              display_the_numbers();                 }      else       {        keystate = 0;        over_flow = 0;        add_flag = 1;        display_the_numbers();      }          }}// Choise 3 - The clear sectionvoid clear_section(){    // Check for the "Clear" button       digit_number[0] = 0;      add_number[0] = 0;      display_data[0] = 0x0100;      for ( int i=1;i<8;i++)      {        digit_number[i] = 0;        add_number[i] = 0;        display_data[i] = word( (i+1), 0x0F );                     }      add_number[8] = 0;      keystate = 0;      over_flow = 0;      add_flag = 1;      clear_flag = 1;      display_the_numbers();           }     //For troubleshooting the program using Serial Monitor /*      Serial.print(keydata, BIN);    Serial.print("  ");    Serial.print(keydata, HEX);    Serial.print("  ");    Serial.print(keynumber, HEX);    Serial.print("  ");    Serial.println(keydata, DEC);    delay(1000);*/// Read keypad data via a 74HC14 - Inverter from the 4021void read_keypad(){  digitalWrite(latchkeypin,HIGH);  delayMicroseconds(20);  digitalWrite(latchkeypin,LOW);  keydata = shiftIn(datakeypin, clockkeypin,LSBFIRST);  } // Convert the keypad data into BCD// And a code for *, 0, # buttonvoid convert_the_keypad_data(){  byte what_row;    what_row = ( keydata >> 3) & 0x0F;  switch ( what_row)  {    case 1:           keynumber = ( ( keydata >> 1 ) & 0x03 ) + 1;           choise = 1;           break;    case 2:           keynumber = (( keydata >> 1 ) & 0x03 ) + 4;           choise = 1;           break;    case 4:           keynumber = (( keydata >> 1 ) & 0x03 ) + 7;           choise = 1;           break;    case 8:           special_key();           break;      }    }  // the display the data routine to the MAX7219 void display_the_numbers(){   for (int i=0;i<8;i++)   {     digitalWrite(latchdisplaypin, LOW);     shiftOut(datadisplaypin, clockdisplaypin, MSBFIRST, highByte(display_data[i]) );     shiftOut(datadisplaypin, clockdisplaypin, MSBFIRST, lowByte(display_data[i]) );     digitalWrite(latchdisplaypin, HIGH);     delay(5);   }  }// A special code for 0, *, # buttonvoid special_key(){   byte special_case;      special_case = ( ( keydata >> 1) & 0x03 ) + 1;   switch ( special_case )   {     case 1:            keynumber = 0x0E;            choise = 3;            break;     case 2:            keynumber = 0x00;            choise = 1;            break;     case 3:            keynumber = 0x0B;            choise = 2;            break;   }        }// Interrupt Routibevoid anykeypress(){  keystate = 1; }  `

#### Nishant_Sood

#21
##### Apr 02, 2012, 07:38 am
Hi Mr.Serje , had a look on the code,

What about the KeyPad , is it working fine with amp now? i recall you had a problem with that! , May be its having debouncing effect?
"Real Men can Accomplish  Anything"

- skype : nishants5
ਫ਼ਤੇਹ ਕਰੁਂ!
www.winacro.com

#22
##### Apr 02, 2012, 09:33 am
One thing  notice is that there's no debouncing with the keypad reading. That may cause unreliable input.

______
Rob
Rob Gray aka the GRAYnomad www.robgray.com

#### Techone

#23
##### Apr 02, 2012, 04:16 pm
I agree with both of you. I may add a debounce, but I wonder how and where to place the tiny delay ? The key data came from the 4021, after a shiftIn() read. And the interrupt signal came from a 4 input NAND gate - 74LS20.  So any bouncing by a key, also created a double pulse at the interrupt pin, activate the interrupt request. A 555 in monostable mode will take care of that. I will re-design the keypad circuit and is not done yet. I may add a latch in between the inverters and the 4021.  And beside the bouncing problem, the close contact is not a close contact after all, more than intermittent, due to a non - proper LOW level at the input gates. The LM339 comparator will take care of that. I will set the comparator V ref at 2.5 V <-- mid point. Still two state.

I will keep you guys posted.

I happen to have a PS/2 keypad - see picture. I will re-code using the PS/2 library and re-do a circuit to use the PS/2 keypad and using the same 7 segments display. I will do that later. I will keep you posted on that one too. Still keep the same tread anyway.

#### Nishant_Sood

#24
##### Apr 02, 2012, 06:53 pm
Hi Mr.Serje i hope things are fine and the code is hopefully getting done ,following i add my suggestions:

Quote
also created a double pulse at the interrupt pin, activate the interrupt request.

I think what here can be done is that as the interrupt is being fired by the NAND gate You can set a counter in here to note the number of times the interrupt routine is being fired and put in a debugging statements on the Serial (I debugged my code in the same way when I was working with interrupts that however came from a mechanical part that is a Reed Switch) this way the real culprit can be traced back, if and only if the debouncing may be happening.

also. Mr.Serje you told once that amplifying(if i recall it right from my memory) the keypad buttons may make then susceptible to ultra sensitivity and thus the same can result in debounce.

"Real Men can Accomplish  Anything"

- skype : nishants5
ਫ਼ਤੇਹ ਕਰੁਂ!
www.winacro.com

#25
##### Apr 02, 2012, 07:58 pm

I have a keypad/LCD screen that I put both debounce code into it for the usual reasons. I also put a millis count so that I could not double enter the same button.

Pseudo code:

Code: [Select]
`Check for button press twice for debounce          if good button press, use it,  if a new button press check millis if (millis - last button press) ==  long enough time  record new button press`

The downside is you can push a button too quickly and have it ignored depending how you set the "long enough time variable.
General Arduion tutorials = http://tronixstuff.wordpress.com
http://www.gammon.com.au/forum/bbshowpost.php?bbtopic_id=123

#### Techone

#26
##### Apr 03, 2012, 01:06 am

Thank for you tips. Using the millis - time  to check if a double press is being done... OK I think I get you. To impliment in my code, that I will figure this out. It look like it is a good idea. I will impliment something like that.

Let see :Loop 1 :  read key    Loop 1 ---> I mean : void loop()
measured time

measured time
check the time difference
if to small - don't take the key
if big enough - take the key

Something like that.  But with a 555 in monostable - output of the 555 going to the interrupt pin will solve the debouncing problem.
And I will do a digitalWrite( latchkeypin, HIGH ) in the interrupt routine to latch the keypad data.

@NI\$HANT

To monitor the interrupt routine using Serial Monitor is a good idea.

Quote
also. Mr.Serje you told once that amplifying(if i recall it right from my memory) the keypad buttons may make then susceptible to ultra sensitivity and thus the same can result in debounce

I agree. That the 555 in monostable come in. I just set the output of the 555 about .. let say 10 mS to 20 mS. The input can multi pulse for 1 ms to 8 mS until it is stable, and the 555 chip won't even care about it. It is after the 555 finish it's pulse that the 555 chip care. ( the mono stable circuit, that is )

#### Techone

#27
##### Apr 03, 2012, 01:25 am
Updated :

The new keypad circuit is still no done.  Today, when I was finish my afternoon run, going home, and in the kitchen, I was thinking about my code, and it occur to me that I made a executable bug in the ADD routine. I was installing the carry into the next array box, that may explain some garbage data in my display. No add right , screw up numbers, etc. Instead to place the carry into the add_number[] array, I just simply use a "temp" variable. Use the / and % to isolate the unit number.

Example :  temp = add_number / 10;   <-- the carry calculation
temp = 12 / 10 --> 1  or 8 / 10 --> 0
add_number = 12 % 10 --- > 2  or 8 % 10 ---> 8 <-- the unit to be display.

Add also, I fix the "cosmetic" bug. Was display : 00001234  Now :        1234

I change the interrupt routine : I just add : digitalWrite(latchkeypin, HIGH);  And remove that line from the read_keypad routine.

Next post is the new and final code. <-- I think

Here the old code :

Code: [Select]
`if ( over_flow == 0)    {            for (int i=0;i<8;i++)      {         add_number[i] = add_number[i+1] + add_number[i] + digit_number[i];         if (add_number[i] > 0x09 )         {           add_number[i+1] = 1;           display_data[i] = word ( ( i + 1 ), ( add_number[i] - 10 ));          }         else          {            display_data[i] = word ( ( i + 1 ) , add_number[i]);         }              }              // check for over flow      if ( add_number[8] > 0)      {              over_flow = 1;        digit_number[0] = 0;                display_data[0] = 0x010B;        for ( int i=1;i<8;i++)        {           digit_number[i] = 0;           display_data[i] = word( (i+1), 0x0F );                       }              keystate = 0;        over_flow = 1;        add_flag = 1;              display_the_numbers();                 }      else       {        keystate = 0;        over_flow = 0;        add_flag = 1;        display_the_numbers();      }          }`

Code: [Select]
`// Choise 2 - the add sectionvoid add_section(){    byte temp;      if ( over_flow == 0 )    {       // The Add logic         temp = 0; // the carry variable       for (int i=0;i<8;i++)      {         add_number[i] = temp + add_number[i] + digit_number[i];         temp = add_number[i] / 10;         add_number[i] = add_number[i] % 10;         display_data[i] = word ( ( i + 1 ) , add_number[i] );      }              // check for over flow      if ( temp != 0)      {              over_flow = 1;        digit_number[0] = 0;                display_data[0] = 0x010B;        for ( int i=1;i<8;i++)        {           digit_number[i] = 0;           display_data[i] = word( (i+1), 0x0F );                       }              keystate = 0;        over_flow = 1;        add_flag = 1;              display_the_numbers();                 }      else       {        /*        For a cleaner display by removing        the zero's on the left side of the number        */        for (int i=7;i>0;i--)        {          if (add_number[i] == 0)          {            display_data[i] = word ( ( i + 1 ) , 0x0F );          }          else           {            break;          }                  }                  keystate = 0;        over_flow = 0;        add_flag = 1;        display_the_numbers();      }          }}`

#### Techone

#28
##### Apr 03, 2012, 01:27 am
Here is the updated and maybe the final code. It is working nice, except the issue with the keypad - double entry and miss key.

Code: [Select]
`/*   size : 2794 bytes      Calculator Version 2.0      Just add a number enter by the keypad and display it.   With 2 function : Add / Equal ===> * button                      Clear ==>  # button   It will use a MAX7219 for display the data ( for the shiftOut() ).   and a 4021 for the keypad input data with the use of    an NOT gate 74HC14. ( for the shiftin() )   See the keypad example in the tread for details.     The interrupt use a 72LS20 from the row pins, any LOW signal will   produce a HIGH pulse to be use has an interrupt signal.   By Serge J Desjardins   aka techone / tech37   Toronto, Ontario, Canada   Compile and Tested.   */// Keypad Serial pinsconst byte latchkeypin = 10;const byte datakeypin = 12;const byte clockkeypin = 11;// Display Serial pinsconst byte datadisplaypin = 9;const byte clockdisplaypin = 8;const byte latchdisplaypin = 7;// Anykey and interrupt pinconst byte anykeypin = 2;// MAX7419 init dataword initdata[5] = { 0x0C01, 0x0F00, 0x0A0B, 0x0B07, 0x09FF };// Fill the Display array with a blank codeword display_data[8] = { 0x0100, 0x020F, 0x030F, 0x040F, 0x050F, 0x060F, 0x070F, 0x080F };  // The digit arraybyte digit_number[8] = {0,0,0,0,0,0,0,0};// The second array - The total numberbyte add_number[8] = {0,0,0,0,0,0,0,0};// Key press keypad flag volatile boolean keystate;// Overflow flagboolean over_flow;// add button flagboolean add_flag;// Clear button flagboolean clear_flag;// The keypad data byte keydata;byte keynumber;// The choicebyte choise;void setup() {  //define the pins modes  pinMode(latchkeypin, OUTPUT);  pinMode(clockkeypin, OUTPUT);   pinMode(datakeypin, INPUT);  pinMode(datadisplaypin, OUTPUT);  pinMode(clockdisplaypin, OUTPUT);  pinMode(latchdisplaypin, OUTPUT);  pinMode(anykeypin, INPUT);  // setup the interrupt pin  attachInterrupt(0,anykeypress,RISING);    /* Init the MAX7419 : Normal Mode                        Normal Operation                        Setting the Intensity                        Numbers of Digits being display                        Set to Decode Mode  */   for (int i=0;i<5;i++)  {       digitalWrite(latchdisplaypin, LOW);     shiftOut(datadisplaypin, clockdisplaypin, MSBFIRST, highByte(initdata[i]));     shiftOut(datadisplaypin, clockdisplaypin, MSBFIRST, lowByte(initdata[i]) );     digitalWrite(latchdisplaypin, HIGH);     delay(5);  }  // Blank the display  display_the_numbers();    // Set the latch key LOW  digitalWrite(latchkeypin, LOW);  // init the flags and the calculation variable  keystate = 0;    add_flag = 1;  over_flow = 0;  clear_flag = 1;   }  void loop(){    while ( keystate == 0)   {      // wait for a key press   }  read_keypad();  convert_the_keypad_data();  // The choise 1 = numbers , 2 = add , 3 = clear  switch (choise)  {     case 1 :             entry_of_numbers();             break;     case 2 :             add_section();             break;     case 3 :             clear_section();             break;       }  }// Choise 1void entry_of_numbers(){    // Enter the numbers routine    if ( over_flow == 0 )  {       if ( ( add_flag == 1) && ( clear_flag = 1 ) )     {       for (int i=0;i<8;i++)       {         digit_number[i] = 0;               display_data[i] = word ( ( i+1 ), 0x0F );       }           }         // Enter the key number and move the arrays data.          for (int i=7;i>0;i--)     {       digit_number[i] = digit_number[i-1];       display_data[i]=display_data[i-1];       display_data[i] = word ( (i+1) , lowByte( display_data[i] ) );     }     digit_number[0] = keynumber;          display_data[0] = word ( 1, keynumber );          display_the_numbers();     add_flag = 0;     clear_flag = 0;     keystate = 0;      }}// Choise 2 - the add sectionvoid add_section(){    byte temp;      if ( over_flow == 0 )    {       // The Add logic         temp = 0; // the carry variable       for (int i=0;i<8;i++)      {         add_number[i] = temp + add_number[i] + digit_number[i];         temp = add_number[i] / 10;         add_number[i] = add_number[i] % 10;         display_data[i] = word ( ( i + 1 ) , add_number[i] );      }              // check for over flow      if ( temp != 0)      {              over_flow = 1;        digit_number[0] = 0;                display_data[0] = 0x010B;        for ( int i=1;i<8;i++)        {           digit_number[i] = 0;           display_data[i] = word( (i+1), 0x0F );                       }              keystate = 0;        over_flow = 1;        add_flag = 1;              display_the_numbers();                 }      else       {        /*        For a cleaner display by removing        the zero's on the left side of the number        */        for (int i=7;i>0;i--)        {          if (add_number[i] == 0)          {            display_data[i] = word ( ( i + 1 ) , 0x0F );          }          else           {            break;          }                  }                  keystate = 0;        over_flow = 0;        add_flag = 1;        display_the_numbers();      }          }}// Choise 3 - The clear sectionvoid clear_section(){    // Check for the "Clear" button       digit_number[0] = 0;      add_number[0] = 0;      display_data[0] = 0x0100;      for ( int i=1;i<8;i++)      {        digit_number[i] = 0;        add_number[i] = 0;        display_data[i] = word( (i+1), 0x0F );                     }            keystate = 0;      over_flow = 0;      add_flag = 1;      clear_flag = 1;      display_the_numbers();           }   // Read keypad data via a 74HC14 - Inverter from the 4021void read_keypad(){   delayMicroseconds(10);  digitalWrite(latchkeypin,LOW);  keydata = shiftIn(datakeypin, clockkeypin,LSBFIRST);  } // Convert the keypad data into BCD// And a code for *, 0, # buttonvoid convert_the_keypad_data(){  byte what_row;    what_row = ( keydata >> 3) & 0x0F;  switch ( what_row)  {    case 1:           keynumber = ( ( keydata >> 1 ) & 0x03 ) + 1;           choise = 1;           break;    case 2:           keynumber = (( keydata >> 1 ) & 0x03 ) + 4;           choise = 1;           break;    case 4:           keynumber = (( keydata >> 1 ) & 0x03 ) + 7;           choise = 1;           break;    case 8:           special_key();           break;      }    }  // the display the data routine to the MAX7219 void display_the_numbers(){   for (int i=0;i<8;i++)   {     digitalWrite(latchdisplaypin, LOW);     shiftOut(datadisplaypin, clockdisplaypin, MSBFIRST, highByte(display_data[i]) );     shiftOut(datadisplaypin, clockdisplaypin, MSBFIRST, lowByte(display_data[i]) );     digitalWrite(latchdisplaypin, HIGH);     delay(5);   }  }// A special code for 0, *, # buttonvoid special_key(){   byte special_case;      special_case = ( ( keydata >> 1) & 0x03 ) + 1;   switch ( special_case )   {     case 1:            keynumber = 0x0E;            choise = 3;            break;     case 2:            keynumber = 0x00;            choise = 1;            break;     case 3:            keynumber = 0x0B;            choise = 2;            break;   }        }// Interrupt Routibevoid anykeypress(){  digitalWrite(latchkeypin, HIGH);  keystate = 1; }  `

#### Nishant_Sood

#29
##### Apr 03, 2012, 07:33 am
Quote
double entry and miss key

okay so it seems Mr.Serje that everything now is fine , i think we guys are done and the code is good the problem arising if any is because of that keypad that is getting beyond our control.
"Real Men can Accomplish  Anything"

- skype : nishants5
ਫ਼ਤੇਹ ਕਰੁਂ!
www.winacro.com

Go Up