Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

problem with keypad and frequency measurement in pic18f4580

Status
Not open for further replies.

mustafahasan

Newbie
Joined
Jul 26, 2018
Messages
4
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
91
hello everybody,
Iam doing a project (keypad for enter the direction then to chose the speed of dc motor and measure the frequency with pic18f4580) and am using the mikroc PRO and the proteus to simulate my project,
the project is running successfully in simulation, BUT when I try to implement it in real work at the first the lcd gave me the message press 1 for cw and 3 for ccw then the lcd display random number .
is there are any mistake in my code? why its work in simulation perfect while it is not in real implementation?

anyone faced such a problem? how can I resolve? what things can cause such a problem?


my code and proteus in the attachments



any more explanation can be made upon request,
I will be thankfull for any help.
Regards.
 

Attachments

  • keypad+speed+direction.zip
    183.5 KB · Views: 89

what things can cause such a problem?

First of all, making a loop with the goto statement from within any evaluation routines is not a suited approach, actually, adding these shortcuts is considered a bad programming style; think of using the while statement instead. Another odd thing in your code is that at the function get_direction(), you are returning nothing (see lines 203/206) whereas it would be expected a char there. This is what could be seen at a glance.

Side note: Next time consider posting the code at the message body, instead of attaching it.
 

thank you for replay and this is my code


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
// LCD module connections
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;
 
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD module connections
 // start ketpad
 char Keypadport at portd;
 int i; char speed[6];
 int j; char direction[2];
 int dir=0;
 int maxspeed=1500;
 float b;
 int duty;
 int input;
 char srtofinput[6];
 //end keypad
  
  //start capture
 
unsigned int timer1_register;  //stores timer1 register value
char timer1_register_text[20];  //stores timer1 register value to string
unsigned int capture_register;  //stores capture register value
char capture_register_text[20];  //stores capture register value to string
 float period;                  //stores the periodic time
 char period_text[20];           // stores the periodic time converted to string
 unsigned short cnt=0;          // edge counter ,will be used to determine frst&second rising edge of pulse
  float output;
  int overflow=0;
bit flag;  //capture interrupt occured
 
    unsigned long t;    unsigned long t1;
 
 void CONFIGURE_CAPTURE()
{
  //Capture mode, every rising edge
  CCP1M3_bit = 0;
  CCP1M2_bit = 1;
  CCP1M1_bit = 0;
  CCP1M0_bit = 1;
 
  trisc.b2 = 1; //C2 as input
 
  //prescaler 1:8
  T1CKPS1_bit = 0;
  T1CKPS0_bit = 0;
  TMR1IE_bit=1;  TMR1IF_bit=0;      TMR1IP_bit=1;
  CCP1IE_bit = 1;  //enable capture interrupt
 
  //enable all interrupts
  PEIE_bit = 1;
  GIE_bit = 1;
 
  //reset high & low bytes of timer1 & capture registers
  TMR1H = 0; TMR1L = 0;
  CCPR1H = 0; CCPR1L = 0;
 
  TMR1ON_bit = 0; //start timer1
}
 
 
 //end capture configuration
   void get_print_timer1_capture()
{
  //get high & low bytes of timer1 & capture registers
  timer1_register = (TMR1H<<8) + TMR1L;
 
  capture_register = (CCPR1H<<8) + CCPR1L;
   t=(overflow*65536)-overflow;
 
 
   //calculate period
   t1=t+timer1_register;
   period=(float)(t1);
    period=(float)period* (4);
   period=(float)period* 1/32000000;
   period=(float)period*1;
 
      output=(float)(1/period);
 
 
  floatTOStr(output,period_text);
 
  lcd_out(2,1,"F: ");lcd_out(2,5, period_text);  lcd_out_cp("hz");
 
  //reset timer1 & capture
  TMR1H = 0; TMR1L = 0;      overflow=0;
  CCPR1H = 0; CCPR1L = 0;
}
 
  
  void interrupt()
{
  if(CCP1IF_bit == 1) //if capture interrupt occured (rising edge detected)
  {
    CCP1IF_bit = 0; //reset capture interrupt flag
    TMR1ON_bit = 0; //stop timer1
    cnt++;
    if(cnt==1){TMR1ON_bit = 1;}
    if(cnt==2){TMR1ON_bit = 0;   flag=1;}
  }
  if(tmr1if_bit==1)
  {tmr1if_bit=0; overflow++;  }
}
 
 
   char get_speed()
   {
    line:
    Lcd_Cmd(_LCD_CLEAR);
    Lcd_Out(1,1,"enter speed");
                  speed[0]=0;
                  speed[1]=0;
                  speed[2]=0;
                  speed[3]=0;
 
            for(i=0;i<4;i++)
            {
                 while(speed[i]==0)
                 {speed[i]=Keypad_Key_Click(); }
 
            if(speed[i]==1)     speed[i]='1';
            if(speed[i]==2)     speed[i]='4';
            if(speed[i]==10)    speed[i]='6';
            if(speed[i]==6)     speed[i]='5';
            if(speed[i]==5)     speed[i]='2';
            if(speed[i]==11)    speed[i]='9';
            if(speed[i]==7)     speed[i]='8';
            if(speed[i]==3)     speed[i]='7';
            if(speed[i]==9)     speed[i]='3';
            if(speed[i]==12)    speed[i]='#';
            if(speed[i]==8)     speed[i]='0';
            if(speed[i]==4)     speed[i]='*';
 
            Lcd_chr(2,i+1,speed[i]);
 
            }
                delay_ms(500);
 
                input= (1000*(speed[0]-48))+(100*(speed[1]-48))+(10*(speed[2]-48))+((speed[3]-48)) ;
                inttostr(input,srtofinput);
                if(input>maxspeed)
                  {
                  DELAY_ms(500);
                  Lcd_Cmd(_LCD_CLEAR);  Lcd_Cmd(_LCD_CURSOR_OFF);
                  Lcd_out(1,1,"out of range ");   delay_ms(1000);
                  goto line;
                  }
 
                    else
                   {
 
 
                   Lcd_Cmd(_LCD_CLEAR);  Lcd_Cmd(_LCD_CURSOR_OFF);
                   Lcd_out(1,1,"Des_S");     lcd_out(1,7,srtofinput); 
 
                   return;
                   }
 
    }
 
 
   char get_direction()
    {
    line1:
    Lcd_Cmd(_LCD_CLEAR);
    lcd_out(1,1,"1 for cw 3 ccw");
            for(j=0;j<1;j++)
            {
                 while(direction[j]==0)
                 {
                 direction[j]=Keypad_Key_Click();
                 }
 
            if(direction[j]==1)     direction[j]='1';
            if(direction[j]==2)     direction[j]='4';
            if(direction[j]==10)    direction[j]='6';
            if(direction[j]==6)     direction[j]='5';
            if(direction[j]==5)     direction[j]='2';
            if(direction[j]==11)    direction[j]='9';
            if(direction[j]==7)     direction[j]='8';
            if(direction[j]==3)     direction[j]='7';
            if(direction[j]==9)     direction[j]='3';
            if(direction[j]==12)    direction[j]='#';
            if(direction[j]==8)     direction[j]='0';
            if(direction[j]==4)     direction[j]='*';
 
            Lcd_chr(2,1,direction[j]);
            }
 
            if(strcmp(direction,"1")==0)
             {  DELAY_ms(500);   dir=1;   get_speed();   return;}
 
            if(strcmp(direction,"3")==0)
             {  DELAY_ms(500);  dir=3;   get_speed();    return; }
 
                   else
                  {
                  direction[0]=0;
                  direction[1]=0;
                  goto line1;
                  }
    }
 
 
 check_flag()
 {
  if(flag == 1) //if this flag is set
    {
      get_print_timer1_capture();
      cnt=0;    // rest rising edge counter
      flag = 0; //reset this flag
 
     }
 }
 
 
 
void main()
 { OSCCON = 0b11110111;
    OSCTUNE = 0b01000000;
 
 
 
  trisc.b3=0;            portc.b3=0;  trisc.b4=0;            portc.b4=0;
  CMCON = 7;            ECCP1CON=0;   ADCON1=0x0f;
  lcd_init();           keypad_init();
 
  Lcd_Cmd(_LCD_CLEAR);  Lcd_Cmd(_LCD_CURSOR_OFF);
     get_direction();      CONFIGURE_CAPTURE();
 
 
         while(1)
         {
 
                    
                    switch(dir)
                     {
                    case(1):           {      portc.b4=1;  portc.b3=0;  check_flag();      break;  }
 
 
 
 
 
                     case(3):          {     portc.b4=0;    portc.b3=1; check_flag();     break;  }
 
                     }
 
          }
}

 
Last edited by a moderator:

i still facing the same problem any one can help me? it is work with proteus but its is not work in real implementation!!
 

Hi,

Basic error: (discussed very often here)
* the ISR need to be as short as possible in time.
Don't do havy calculations in an ISR. In the ISR: just safe important data and set a flag.
* Do most of the processing in main loop.
Your main loop dies almost nothing.
Here check the flag and process the data. Do the calculations, transmit the data to the display.

Basic error:
* To me it seems you completely misunderstood the "capture" function. (But I have to admit, that I don't understand your code at all)
Timer setup: select the timer frequency that the time from one overfow to the next overflow is bigger than the period time of the lowest expectable input frequency.
No need to clear or reset the timer registers. Never for this application.
The capture gives you a timestamp.
In ISR:
Check flaags to decide what to do.
Safe the capture information at the first rising edge as "start_timestamp". Set a "start_captured_flag"
Safe the capture information at the next rising edge as "stop_timestamp". Set a "stop_captured_flag"


In main:
If stop_captured_flag is set:
Now you have the: period_time_information = stop_timestamp - start_timestamp
Signal_Frequency = timer_tick_frequency / period_time_information.
Process data and do display update:
(Here you may include a "wait" for delayed next display update)
Then clear both flags to enable new measurement.

Klaus
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top