4-Digit UP/Down Counter Using Rotary Encoder

Discussion in 'The Completed Projects Collection' started by MCU88, Mar 20, 2015.

Thread Status:
Not open for further replies.
  1. MCU88

    Thread Starter Member

    Mar 12, 2015
    360
    35
    4-Digit UP/Down Counter Using Rotary Encoder

    [​IMG]

    [​IMG]
    [​IMG]

    mikroC Source Code:
    Code (Text):
    1.  
    2. unsigned short i = 0;
    3. unsigned short j = 0;
    4. unsigned short scan = 0;
    5. unsigned short rLeft = 0;
    6. unsigned short rRight = 0;
    7. unsigned short rotating = 0;
    8. signed short ones = 0;
    9. signed short tens = 0;
    10. signed short hundreds = 0;
    11. signed short thousands = 0;
    12.  
    13. #define dslpD PORTA.F1
    14. #define dslpC PORTA.F0
    15. #define dslpB PORTA.F3
    16. #define dslpA PORTA.F2
    17.  
    18. #define segA PORTB.F7
    19. #define segB PORTB.F5
    20. #define segC PORTB.F3
    21. #define segD PORTB.F2
    22. #define segE PORTB.F1
    23. #define segF PORTB.F6
    24. #define segG PORTB.F4
    25.  
    26. #define rotary02 PORTB.F0
    27. #define rotary01 PORTA.F4
    28. #define rotary03 PORTB.F3
    29.  
    30. void num0()
    31. {
    32.   segA = 1;
    33.   segB = 1;
    34.   segC = 1;
    35.   segD = 1;
    36.   segE = 1;
    37.   segF = 1;
    38. }
    39.  
    40. void num1()
    41. {
    42.   segB = 1;
    43.   segC = 1;
    44. }
    45.  
    46. void num2()
    47. {
    48.   segA = 1;
    49.   segB = 1;
    50.   segG = 1;
    51.   segD = 1;
    52.   segE = 1;
    53. }
    54.  
    55. void num3()
    56. {
    57.   segA = 1;
    58.   segB = 1;
    59.   segC = 1;
    60.   segD = 1;
    61.   segG = 1;
    62. }
    63.  
    64. void num4()
    65. {
    66.   segF = 1;
    67.   segG = 1;
    68.   segB = 1;
    69.   segC = 1;
    70. }
    71.  
    72. void num5()
    73. {
    74.   segA = 1;
    75.   segF = 1;
    76.   segG = 1;
    77.   segC = 1;
    78.   segD = 1;
    79. }
    80.  
    81. void num6()
    82. {
    83.   segA = 1;
    84.   segC = 1;
    85.   segD = 1;
    86.   segE = 1;
    87.   segF = 1;
    88.   segG = 1;
    89. }
    90.  
    91. void num7()
    92. {
    93.   segA = 1;
    94.   segB = 1;
    95.   segC = 1;
    96. }
    97.  
    98. void num8()
    99. {
    100.   segA = 1;
    101.   segB = 1;
    102.   segC = 1;
    103.   segD = 1;
    104.   segE = 1;
    105.   segF = 1;
    106.   segG = 1;
    107. }
    108.  
    109. void num9()
    110. {
    111.   segA = 1;
    112.   segB = 1;
    113.   segC = 1;
    114.   segF = 1;
    115.   segG = 1;
    116. }
    117.  
    118. void blankDigit()
    119. {
    120.   segA = 0;
    121.   segB = 0;
    122.   segC = 0;
    123.   segD = 0;
    124.   segE = 0;
    125.   segF = 0;
    126.   segG = 0;
    127. }
    128.  
    129. void displayOff()
    130. {
    131.    dslpA = 0;
    132.    dslpB = 0;
    133.    dslpC = 0;
    134.    dslpD = 0;
    135. }
    136.  
    137. void decCount()
    138. {
    139.    if (ones != 0 || tens != 0 || hundreds != 0 || thousands != 0)
    140.    {
    141.       ones--;
    142.  
    143.       if (ones < 0)
    144.       {
    145.          if (tens > 0)
    146.          {
    147.             ones = 9;
    148.             tens --;
    149.          }
    150.          else if (hundreds > 0)
    151.          {
    152.             if (tens == 0)
    153.             {
    154.                tens = 9;
    155.                ones = 9;
    156.                hundreds --;
    157.             }
    158.          }
    159.          else if (thousands > 0)
    160.          {
    161.             if (hundreds == 0)
    162.             {
    163.                if (tens == 0)
    164.                {
    165.                   tens = 9;
    166.                   ones = 9;
    167.                   hundreds = 9;
    168.                   thousands --;
    169.                }
    170.             }
    171.          }
    172.       }
    173.    }
    174. }
    175.  
    176. void incCount()
    177. {
    178.    if (ones != 9 || tens != 9 || hundreds != 9 || thousands != 9)
    179.    {
    180.       ones++;
    181.  
    182.       if (ones > 9)
    183.       {
    184.          ones = 0;
    185.          tens ++;
    186.       }
    187.       if (tens > 9)
    188.       {
    189.          tens = 0;
    190.          hundreds ++;
    191.       }
    192.       if (hundreds > 9)
    193.       {
    194.          hundreds = 0;
    195.          thousands ++;
    196.       }
    197.    }
    198. }
    199.  
    200. void rstCount()
    201. {
    202.    ones = 0;
    203.    tens = 0;
    204.    hundreds = 0;
    205.    thousands = 0;
    206. }
    207.  
    208. void pollRotaryEncoder()
    209. {
    210.    TRISB = 0x09;
    211.    
    212.    if (rotary03 == 0)
    213.    {
    214.       rstCount();
    215.    }
    216.  
    217.    TRISB = 0x01;
    218.  
    219.    if (rotary01 == 0)
    220.    {
    221.       if (rotary02 == 0)
    222.       {
    223.          rotating = 1;
    224.       }
    225.    }
    226.  
    227.    if (rotating == 1)
    228.    {
    229.       if (rotary01 == 1)
    230.       {
    231.          rRight = 1;
    232.          rotating = 0;
    233.       }
    234.       if (rotary02 == 1)
    235.       {
    236.          rLeft = 1;
    237.          rotating = 0;
    238.       }
    239.    }
    240.  
    241.    if (rotary01 == 1)
    242.    {
    243.       if (rotary02 == 1)
    244.       {
    245.          if (rleft == 1)
    246.          {
    247.             incCount();
    248.             rLeft = 0;
    249.          }
    250.            
    251.          if (rRight == 1)
    252.          {
    253.             decCount();
    254.             rRight = 0;
    255.          }
    256.       }
    257.    }
    258. }
    259.  
    260. void setDigit(signed short digit)
    261. {
    262.    switch (digit)
    263.    {
    264.       case 0:
    265.          num0();
    266.          break;
    267.  
    268.       case 1:
    269.          num1();
    270.          break;
    271.  
    272.       case 2:
    273.          num2();
    274.          break;
    275.  
    276.       case 3:
    277.          num3();
    278.          break;
    279.  
    280.       case 4:
    281.          num4();
    282.          break;
    283.  
    284.       case 5:
    285.          num5();
    286.          break;
    287.  
    288.       case 6:
    289.          num6();
    290.          break;
    291.  
    292.       case 7:
    293.          num7();
    294.          break;
    295.  
    296.       case 8:
    297.          num8();
    298.          break;
    299.  
    300.       case 9:
    301.          num9();
    302.          break;
    303.          
    304.       case 10:
    305.          blankDigit();
    306.          break;
    307.  
    308.    }
    309. }
    310.  
    311. void multiplexDisplays()
    312. {
    313.   displayOff();
    314.   blankDigit();
    315.          
    316.    switch (scan)
    317.    {
    318.       case 0:
    319.          setDigit(ones);
    320.          dslpA = 1;
    321.          break;
    322.  
    323.       case 1:
    324.          setDigit(tens);
    325.          dslpB = 1;
    326.          break;
    327.  
    328.       case 2:
    329.          setDigit(hundreds);
    330.          dslpC = 1;
    331.          break;
    332.  
    333.       case 3:
    334.          setDigit(thousands);
    335.          dslpD = 1;
    336.          break;
    337.    }
    338.  
    339.    scan++;
    340.  
    341.    if (scan == 4)
    342.    {
    343.       scan = 0;
    344.    }
    345. }
    346.  
    347. void main()
    348. {
    349.   CMCON = 7;            
    350.   TRISA = 0x10;        
    351.   TRISB = 0x01;        
    352.   PORTA = 0x00;        
    353.   PORTB = 0x00;        
    354.  
    355.   while(1)
    356.   {
    357.      multiplexDisplays();
    358.      Delay_us(100);
    359.      pollRotaryEncoder();
    360.   }
    361. }[/SIZE]
    362.  

    N.B: See attached for PCB artwork in Adobe Acrobat and hex file for PIC.

     
    Last edited: Mar 21, 2015
    RRITESH KAKKAR, ScottWang and absf like this.
  2. R!f@@

    AAC Fanatic!

    Apr 2, 2009
    8,754
    760
    It's just a counter. Nothing else ?
     
  3. MCU88

    Thread Starter Member

    Mar 12, 2015
    360
    35
    Resistors

    • 11 x 470R
    • 4 x 100K
    • 1 x 1K

    Capacitors

    • 2 x 22pF Ceramic
    • 1 x 100nF Polyester
    • 1 x 10uF Electrolytic

    Semiconductors

    • IC1 Pre-Programmed 16F628a
    • IC2 LM78L05 Voltage Regulator
    • 4-Digit Common Cathode Red LED Display
    • Q1 – Q4 BC547 NPN Transistors
    • D1 SSR 1N4007

    Miscellaneous

    • IC1 Socket 18-Pin
    • Battery Connector
    • Wire Links
    • Rotary Encoder with Knob
    • XTAL 4MHz Crystal
     
  4. MCU88

    Thread Starter Member

    Mar 12, 2015
    360
    35
    I engineered it to understand and implement rotary encoders. What would you like it to do?
     
    AnwarHegazy and RRITESH KAKKAR like this.
  5. ScottWang

    Moderator

    Aug 23, 2012
    4,855
    767
    If you could offer the *.hex file then it can be write to the Pic directly, it will be more convenience.
     
  6. Wendy

    Moderator

    Mar 24, 2008
    20,766
    2,536
    There are times a simple counter is handy. Fast is good, then it could be the heart of a freq counter, for example. Or just count turns of a shaft, or whatever is needed.

    I have never programmed a pic, though I would like to learn how.
     
  7. WBahn

    Moderator

    Mar 31, 2012
    17,777
    4,805
    As a cute little project to get introduced to rotary encoders, it is just fine.

    Notice that your picture has a huge splash that proclaims "No Buttons". I hate to be the bearer of bad news, but when you press the knob to reset it, guess what? That's a button! Minor point.

    The bigger problem is that you don't document your code, which makes in almost impossible to read without a lot of reverse-engineering effort. This is particularly the case for the section where you are polling the rotary encoder. Just a handful of comments indicating what the signals mean and what task each subsection of the code accomplishes would make it very readable. Just put yourself in the place of someone that has never seen the schematic or the PCB and that can't see anything in the code beyond that section of it and then write the comments that you would need in order to understand what is happening.
     
  8. tracecom

    AAC Fanatic!

    Apr 16, 2010
    3,871
    1,394
    Then, do so! Or start easy with PICAXE.
     
  9. MCU88

    Thread Starter Member

    Mar 12, 2015
    360
    35
    Sir the hex file has been uploaded. rotaryEncoderCounterHex.hex

    It is in post #1 as well.
     
  10. MCU88

    Thread Starter Member

    Mar 12, 2015
    360
    35
    No buttons of the traditional fashion for such an counter. One button to increment the count UP and one button to decrement the count DOWN. I see where you are coming from though. I did sell a few kits on eBay. Satisfied customers in the end. One guy had BIG trouble with soldering the board though. All I could do was to offer to sell him an pre-build one. He bought it and quickly saw the error of his way.

    Yes I am getting old and lazy. I used to comment code years back. I'll fix it.
     
  11. MCU88

    Thread Starter Member

    Mar 12, 2015
    360
    35
    Nonsense. Go STRAIGHT to mikroC and use this forum for help. mikroC is no harder than BASIC. If I can do it, then any idiot can ;)
     
  12. MCU88

    Thread Starter Member

    Mar 12, 2015
    360
    35
    Very true Bill. There are spin-offs to this project and the code. I could quickly adapt and make the following:
    • Capacitance Meter
    • Frequency Meter
    • Door Opening Counter
    • Tachometer
    • Digital (n) Readout Display
    • 4-Digit Clock
    • Count Down Timer
    The code runs at a good clip. Could get away with it doing many of the aforementioned projects.

    Keen to learn C for programming PICs? Then I recommend doing an online Java course at RMIT University in Melbourne Australia. Cost you AUD 600 per unit. I did 3 units of Java. Worth the money!
     
    RRITESH KAKKAR likes this.
  13. ScottWang

    Moderator

    Aug 23, 2012
    4,855
    767
    Thank you.
    It's really convenience and anyone no need to write any program or install the compiler.
     
  14. MCU88

    Thread Starter Member

    Mar 12, 2015
    360
    35
    I agree. You just program the hex file to the chip. I have many PIC projects ...

    Perhaps someone can start and sell the pre-programmed chips here? $5 plus postage worldwide?
     
  15. MCU88

    Thread Starter Member

    Mar 12, 2015
    360
    35
    I hope all those pin numbers are correct. I designed the PCB on the Monday before drawing the schematic on the Tuesday. Well actually I drew the schematic last night and did the PCB about a year ago. I did an 245 LED moving message display for an forum back in 2007, the circuit was BIG and I got a couple of pin numbers wrong. The thread was an train-wreck with people accusing me of deliberately putting in mistakes. That's insane and makes me look like an idiot...
     
  16. R!f@@

    AAC Fanatic!

    Apr 2, 2009
    8,754
    760
    Everybody makes mistakes.
     
  17. MCU88

    Thread Starter Member

    Mar 12, 2015
    360
    35
    Some times I get it right the first time. But usually... 50 compiles for the C code... 3 goes at the PCB. I did this project presented here in about a day. So say 8-hours labor. 8 x $30 p/hr so... it owes me $240 + parts.
     
  18. MrChips

    Moderator

    Oct 2, 2009
    12,449
    3,365
    Yes, you made a mistake with the pin numbers in the drawing.
    The RESET switch should be connected to RB3 at pin-9, not pin-10.

    On the PCB layout, the 100nF capacitor should be placed as close as possible across pins 5 and 14 for it to be any use.
     
  19. MCU88

    Thread Starter Member

    Mar 12, 2015
    360
    35
    Arh yes I see it. Will make amendments and upload schematic to post #1. I agree that the closer the better for the 100nF decoupling cap. The board was manually routed. I could move things around a bit...
     
    absf likes this.
  20. MCU88

    Thread Starter Member

    Mar 12, 2015
    360
    35
    Alright done. Anymore errors can anyone see?
     
Loading...
Thread Status:
Not open for further replies.