Touching breadboard affects IO pin performance

Discussion in 'Embedded Systems and Microcontrollers' started by aeroguy, Jan 24, 2012.

  1. aeroguy

    Thread Starter Member

    Sep 16, 2009
    40
    2
    Howdy,

    I've encountered something interesting, which is sure to be educational for me.

    My PIC18F45K22 is breadboarded with pin RE0 set as a digital input with an external 10k pullup, and a simple push button.

    The pic is programed to blink an LED when I push the button.

    When I energize the circuit, I can generally push the button once and the light will blink. Further attempts at pushing the button yield no response.

    However, if I touch the metal part of the breadboard, or even the top of the pic chip surface, the light blinks every time I push the button.

    I jumpered my meter to the IO pin to see how the voltage with the button depressed changed when I touch the board. The voltage was reduced from essentially zero, to -2 mV or so. When the button is not depressed, the pin voltage is ~4.7 V, as expected.

    Any idea what is happening here?

    Kind regards,
    Eric
     
    Last edited: Jan 25, 2012
  2. adrenalina

    Active Member

    Jan 4, 2011
    78
    3
    you should post a schematic
     
  3. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    And the code might also be a good idea ;)
     
  4. aeroguy

    Thread Starter Member

    Sep 16, 2009
    40
    2
    "Adrenalina" - I can't upload an image from work here. However, I'm sure you know what a pullup/switch arrangement looks like on an I/O pin.

    See code below:

    _______

    Code ( (Unknown Language)):
    1.  
    2.  
    3. /*
    4. INCLUDES
    5. */
    6. #include <p18f45k22.h>
    7. #include <stdio.h>
    8. #include <timers.h>
    9. #include <delays.h>
    10. #include <usart.h>
    11. /*
    12. CONFIGURATION
    13. */
    14. #pragma config FOSC = INTIO7
    15. #pragma config PLLCFG = OFF
    16. #pragma config PRICLKEN = ON
    17. #pragma config FCMEN = OFF
    18. #pragma config IESO = OFF
    19. #pragma config PWRTEN = OFF
    20. #pragma config BOREN = ON
    21. #pragma config BORV = 285
    22. #pragma config WDTEN = OFF
    23. #pragma config CCP2MX = PORTB3
    24. #pragma config PBADEN = OFF
    25. #pragma config CCP3MX = PORTB5
    26. #pragma config HFOFST = OFF
    27. #pragma config T3CMX = PORTC0
    28. #pragma config P2BMX = PORTD2
    29. #pragma config MCLRE = INTMCLR
    30. #pragma config STVREN = OFF
    31. #pragma config LVP = OFF
    32. #pragma config XINST = OFF
    33. #pragma config DEBUG = OFF
    34. #pragma config CP0 = OFF
    35. #pragma config CP1 = OFF
    36. #pragma config CP2 = OFF
    37. #pragma config CP3 = OFF
    38. #pragma config CPB = OFF
    39. #pragma config CPD = OFF
    40. #pragma config WRT0 = OFF
    41. #pragma config WRT1 = OFF
    42. #pragma config WRT2 = OFF
    43. #pragma config WRT3 = OFF
    44. #pragma config WRTC = OFF
    45. #pragma config WRTB = OFF
    46. #pragma config WRTD = OFF
    47. #pragma config EBTR0 = OFF
    48. #pragma config EBTR1 = OFF
    49. #pragma config EBTR2 = OFF
    50. #pragma config EBTR3 = OFF
    51. #pragma config EBTRB = OFF
    52. /*
    53. DEFINES
    54. */
    55. #define ON 1
    56. #define OFF 0
    57. #define TRUE 1
    58. #define FALSE 0
    59.  
    60.  
    61. //void timer_isr (void);
    62.  
    63. void main (void);
    64. void int01_isr (void);
    65. void Blinkra0 (void);
    66. void strobera0 (void);
    67. void Button1pressed (void);
    68. void Button2pressed (void);
    69. void Button3pressed (void);
    70. void Button4pressed (void);
    71.  
    72. //static unsigned char s_count = 0;
    73.  
    74. union
    75. {
    76. struct
    77. {
    78. unsigned Int0:1; //flag to indicate a RB0 (int0) interrupt
    79. unsigned None:7;
    80. } Bit;
    81. unsigned char Byte;
    82. } Intxflags;
    83.  
    84. union
    85. {
    86. struct
    87. {
    88. unsigned But1:1; //flag to indicate a RE0 button push
    89. unsigned But2:1; //flag to indicate a RE1 button push
    90. unsigned But3:1; //flag to indicate a RE2 button push
    91. unsigned But4:1; //flag to indicate a RE3 button push
    92. unsigned Push:1; //flag to indicate a button has been pushed
    93. unsigned False:1; //flag to indicate a button has not been pushed
    94. unsigned Disable:1; //flag to indicate a pause before listening to button again
    95. unsigned None:1;
    96. } Bit;
    97. unsigned char Byte;
    98. } Butxflags;
    99.  
    100. //Declare variables
    101. unsigned int butcount;
    102. unsigned int nbounce;
    103. unsigned int ioloopcount;
    104. unsigned int nioloop;
    105. unsigned int noinputportvalue;
    106. unsigned int maskporte;
    107.  
    108. void main (void)
    109. {
    110. // Disable global interrupts for initialization
    111. INTCONbits.GIE = OFF;
    112. // Initialize internal oscillator speed to 4Mhz
    113. OSCCONbits.IRCF0 = 1;
    114. OSCCONbits.IRCF1 = 0;
    115. OSCCONbits.IRCF2 = 1;
    116.  
    117. // Initialize the special function registers TRISA and PORTA.
    118. PORTA = 0x00; //Clear PORTA pins
    119. TRISA = 0x00; //All of PORTA is output
    120. // Initialize the special function registers TRISB and PORTB.
    121. // RB0 is input (INT0)
    122. PORTB = 0x00;
    123. TRISB = 0x01;
    124. WPUBbits.WPUB0 = 1; // Configure RB0 (INT0) with weak pullup
    125. // Initialize the special function registers TRISE and PORTE.
    126. // all 4 PORTE pins will be inputs (for buttons)
    127. ANSELEbits.ANSE0 = 0;
    128. PORTE = 0x01;
    129. TRISE = 0x01;//set just RE0 as input during debugging. Note, pullup required on RE0 to RE2
    130. // Interrupt configuration
    131. RCONbits.IPEN = 0; // Disable interrupt priority
    132. INTCON2bits.RBPU = 0; // Enable weak pullups
    133. INTCON2bits.INTEDG0 = 0;// INT0 (RB0) triggers on falling edge
    134. //INTCON2bits.RBIP = 0; // Interrupt on change is low priority
    135. INTCONbits.TMR0IE = OFF;// Disable Timer0 overflow interrupt
    136. INTCONbits.RBIE = OFF; // Disable PORTB interrupt on change
    137. INTCONbits.PEIE = ON; // Enable peripheral interrupts
    138. INTCONbits.INT0E = ON; // Enable INT0 interrupt
    139. INTCONbits.INT0F = 0; // Clear external INT0 interrupt flag
    140. INTCONbits.RBIF = 0; // Clear PORTB IOC interrupt flag
    141. INTCONbits.GIE = ON; // Enable interrupts
    142. //INTCONbits.GIEL = ON; // Disable Lo-priority interrupts
    143. //INTCONbits.GIEH = ON; // Enable High-priority interrupts
    144.  
    145. // configure USART. This is baud 9600 for Fosc 4MhzS
    146. Open1USART( USART_TX_INT_OFF &
    147. USART_RX_INT_OFF &
    148. USART_ASYNCH_MODE &
    149. USART_EIGHT_BIT &
    150. USART_CONT_RX &
    151. USART_BRGH_HIGH,
    152. 25 );
    153.  
    154.  
    155.  
    156. //Initialize variables and flags
    157. Intxflags.Byte = 0; // Clear user interrupt flags
    158. Butxflags.Byte = 0; // Clear button IO flags
    159. butcount = 0; // counter to time how long a button is pressed for
    160. nbounce = 3; // this is arbitrary at the moment..
    161. ioloopcount = 0; // this counter will help decide when to resume responding to buttons
    162. nioloop = 10; // this many loops must be made between button pushes. Arbitrary for now..
    163. noinputportvalue = 1; //true for only one porte pin configured for input;
    164. maskporte = 0;
    165. // Begin Infinite Loop
    166. while (TRUE)
    167. {
    168. //blinkra0();
    169.  
    170. // Poll input buttons
    171. // All 4 inputs high should equal 0x0F I think.
    172.  
    173. if(!Butxflags.Bit.Disable) {
    174. if(PORTEbits.RE0!=noinputportvalue) {
    175. if(butcount<<nbounce) {
    176. butcount ++;
    177. } else {
    178.  
    179. maskporte = 0x0F & PORTE; // mask pertinent PORTE bits for peace of mind
    180. switch (maskporte)
    181. {
    182. case 0x00: //Button 1 pushed
    183. Butxflags.Bit.But1 = 1;
    184. break;
    185. /* case 0x0D: //Button 2 pushed
    186. Butxflags.Bit.But2 = 1;
    187. break;
    188. case 0x0B: //Button 3 pushed
    189. Butxflags.Bit.But3 = 1;
    190. break;
    191. case 0x07: //Button 4 pushed
    192. Butxflags.Bit.But4 = 1;
    193. break;*/
    194. default: //No button still pushed
    195. Butxflags.Bit.False = 1;
    196. break;
    197. }
    198. butcount = 0;
    199. if(!Butxflags.Bit.False) {
    200. Butxflags.Bit.Push = 1; //A button has really been pushed
    201.  
    202. } else {
    203. Butxflags.Byte = 0;
    204. }
    205.  
    206. }
    207. }
    208. } else {
    209. ioloopcount ++;
    210. }// close if Disable loop
    211.  
    212. if(ioloopcount>=nioloop) {
    213. Butxflags.Bit.Disable = 0;
    214. ioloopcount = 0;
    215. }
    216.  
    217.  
    218. // CHECK ALL FLAGS AND DO STUFF AS REQUIRED
    219.  
    220. if(Intxflags.Bit.Int0) {
    221. // DO INTERUPT STUFF HERE IF DESIRED
    222. //Delay10KTCYx(0);
    223. Intxflags.Bit.Int0 = 0; // clear interupt flag
    224. //while (Busy1USART()); // Makes sure the usart isn't busy
    225. //putc1USART('a');
    226. //Delay10KTCYx(0);
    227. }
    228.  
    229. if(Butxflags.Bit.Push) {
    230. switch (Butxflags.Byte)
    231. {
    232. case 0x11: //Button 1 pushed
    233. Button1pressed();
    234. break;
    235. case 0x12: //Button 2 pushed
    236. Button2pressed();
    237. break;
    238. case 0x14: //Button 3 pushed
    239. Button3pressed();
    240. break;
    241. case 0x18: //Button 4 pushed
    242. Button4pressed();
    243. break;
    244. default: //No button still pushed
    245. //clear out the counters/flags
    246. Butxflags.Byte = 0;
    247. break;
    248. }
    249. Butxflags.Byte = 0x00;
    250. Butxflags.Bit.Disable = 1; // Don't respond to another for a while
    251. }
    252.  
    253. } // big while loop
    254. }
    255.  
    256. #pragma code high_vector=0x08
    257. void high_vector (void)
    258. {
    259. if(INTCONbits.INT0IF) {
    260. _asm GOTO int01_isr _endasm
    261. }
    262. }
    263.  
    264. /*
    265. * Returns the compiler to the default code section.
    266. */
    267. #pragma code
    268.  
    269. #pragma interrupt int01_isr
    270. void int01_isr (void)
    271. {
    272. INTCONbits.INT0IF = 0; //Clear the INT0 interrupt flag
    273. Intxflags.Bit.Int0 = TRUE;
    274. }
    275.  
    276. void Button1pressed (void)
    277. {
    278. Blinkra0();
    279.  
    280. }
    281. void Button2pressed (void)
    282. {
    283.  
    284. }
    285. void Button3pressed (void)
    286. {
    287.  
    288. }
    289. void Button4pressed (void)
    290. {
    291.  
    292. }
    293.  
    294. void Blinkra0 (void)
    295. {
    296. PORTAbits.RA0 = ON;
    297. Delay1KTCYx(0); // delay 256000 cycles (0.064 seconds?)
    298. PORTAbits.RA0 = OFF;
    299. // Delay1KTCYx(0); // delay 256000 cycles (0.064 seconds?)
    300. }
    301. void strobera0 (void)
    302. {
    303. PORTAbits.RA0 = ON;
    304. Delay1KTCYx(100); // delay 100000 cycles
    305. PORTAbits.RA0 = OFF;
    306. Delay1KTCYx(100); // delay 100000 cycles
    307.  
    308.  
     
    Last edited by a moderator: Jan 25, 2012
  5. aeroguy

    Thread Starter Member

    Sep 16, 2009
    40
    2
    It'a almost like the threshold for the schmitt trigger is a perfect 0V, and that the pin is regarded as having value=1 (logic high) when the voltage at the pin is a few millivolts above zero.

    Somehow my touching the ground plane of the circuit creates that tiny voltage reduction that causes the schmitt trigger to switch to logic low when the button is pressed.

    Seems very strange to me.
     
  6. aeroguy

    Thread Starter Member

    Sep 16, 2009
    40
    2
    Okay, I've narrowed down my issue and can take it from here.

    The problem wasn't the logic level at my RE0 pin. I was testing for the value of all 4 PORTE pins. Apparently, my touching the breadboard is affecting a floating pin state on PORTE (on a pin other than RE0). I'll figure out what it is specifically tonight and report back for reference.

    Please disregard my request for help.

    thanks
     
  7. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    It's best to set any unconnected pins as outputs, or inputs and ground them. Floating inputs can cause resets.
     
  8. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    <chuckling> There are posts going on for dozens of pages on the Microchip Forums trying to determine the "best" way to do this.

    One of the worst ways is to leave them as floating inputs. Simon sez don't do that.
     
  9. MrChips

    Moderator

    Oct 2, 2009
    12,429
    3,360
    Many times in hindsight we learn not to assume anything.

    Couple of things to watch for, one already mentioned. Make sure all unused inputs are tied to GND or something similar.

    Sometimes those solderless breadboards do not make proper contact with IC pins. Pushing down on chips will sometimes fix this problem.
     
    Eric007 likes this.
  10. aeroguy

    Thread Starter Member

    Sep 16, 2009
    40
    2
    Thanks for the comments, guys. I've definitely learned something I can take away from the experience. The memory will be reinforced by having pulled my hair out for 12 hours on this.. :)

    Floating inputs bad.
     
    Last edited: Jan 25, 2012
  11. atferrari

    AAC Fanatic!

    Jan 6, 2004
    2,647
    759
    Good you solved it! In your way of knowledge you could even loose some hair as well.

    I am a long time user of breadboard (bought some 15++ years ago) where I developed everything with micros even something now, running at 20 MHz.

    I stopped having surprises like that when I became definitely thorough with wiring and the configuration of the micro prior turning the power on.

    Otherwise, buy it, ready made. :D
     
  12. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    Soon you may have the day when you notice either power or ground is unconnected on a chip (or six) on your board, but the board is still working great so no one else on your team will even look at your findings.
     
Loading...