DS18B20 and PIC16F690

Discussion in 'Embedded Systems and Microcontrollers' started by Litch, Mar 20, 2013.

  1. Litch

    Thread Starter Member

    Jan 25, 2013
    86
    7
    So, my first day of PIC programming.

    I've found it is very much write and pray for the small footprint chips, no real-time debugging like I'm used to on a PC (at least not on the small PICs without more ICD hardware).

    Anyway, PIC asm can get stuffed, I don't have time to learn a whole new set of opcodes so I installed the HI-TECH C Compiler, MPLAB IDE etc...

    I have a "Pickit2 Low Pin Count Demo" board and a Pickit2 ISCP USB programmer.

    Project: Use a PIC16F690 to gather temperatures from multiple DS18B20 digital thermometers and output to RS232 to be logged by a server.

    So my idea was to output to RS232 and log temps, but before I went throwing MAX232s around I wanted to make sure the FIRST part was working (temp I/O) so the PICkit2 board has 4 LEDs on it, connected to RC0-RC3. I thought, well I'd just display nibble by nibble with a delay so I could scribble down the temp and verify it's accuracy (and just be sure that part's working before I go adding more 1-wire devices).

    BUT. I get nothing, no lights.

    The nibble([0-15]) function works fine, the delay_ms() works fine, and I have no idea where to go from here to debug this thing...

    Help?

    Schematic and code attached, power is drawn from the ICSP (USB 5v).
     
  2. JohnInTX

    Moderator

    Jun 26, 2012
    2,338
    1,018
    Is the common LED wire at ground? That would keep them from lighting.
    Can you step the code with the PicKit 2/MPLAB?
     
  3. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    The good news is the PICKIT2 allows you to do in circuit debugging just like on a PC... in fact you use your PC to view the PIC.

    The bad news is the PICKIT2 doesn't come with lessons in C.

    I'm not sure if the HI-TECH compiler works as seamlessly as the XC8 (free donload) compiler does.
     
  4. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    I also noted your I/O pins have analog functions... make sure you turn them OFF, they are on by default.

    Post the code. Use code tags please.
     
  5. Litch

    Thread Starter Member

    Jan 25, 2013
    86
    7
    The LEDs work fine, the function I wrote (nibble()) completely works as expected. This is purely an issue between the DS18B20 and the PIC - the code I've got detects the 1-wire presence, but does not communicate with the DS18B20.

    The source code and schematic it attached to my first post but if you want it pasted in here:

    Code ( (Unknown Language)):
    1. #include <htc.h>            //include hitech C header file
    2.  
    3. #define _XTAL_FREQ          8000000
    4.  
    5. // This configuration bits are for PIC16F690 using internal crystal
    6. __CONFIG(FOSC_INTRCIO &     // Clock pins are I/O
    7.          WDTE_OFF &         // Disable Watchdog Timer.
    8.          PWRTE_ON &         // Enable Power Up Timer.
    9.          BOREN_OFF);        // Disable Brown Out Reset.
    10.  
    11. #define SCS_BIT             0x01
    12. #define INT_OSC_8MHZ        (0b01110000 | SCS_BIT)
    13. #define INT_OSC_4MHZ        (0b01100000 | SCS_BIT)
    14. #define INT_OSC_2MHZ        (0b01010000 | SCS_BIT)
    15. #define INT_OSC_1MHZ        (0b01000000 | SCS_BIT)
    16. #define INT_OSC_500KHZ      (0b00110000 | SCS_BIT)
    17. #define INT_OSC_250KHZ      (0b00100000 | SCS_BIT)
    18. #define INT_OSC_125KHZ      (0b00010000 | SCS_BIT)
    19. #define INT_OSC_31KHZ       (0b00000000 | SCS_BIT)
    20.  
    21. #define Skip_ROM            0xCC
    22. #define Convert_T           0x44
    23. #define Read_scratchpad     0xBE
    24.  
    25. #define Port_18B20          RB4
    26. #define Tx_18B20            TRISB4 = 0
    27. #define Rx_18B20            TRISB4 = 1
    28.  
    29. #define WAIT1               1000
    30. #define WAIT2               500
    31.  
    32. #define DS18B20_CONV_TIME   750
    33. #define DS18B20_RESET_PULSE 480
    34. #define DS18B20_WAIT_TIME   60
    35. #define DS18B20_PULLUP_TIME 2
    36.  
    37. #define ONEWIRE_PRESENT     0
    38. #define ONEWIRE_ABSENT      1
    39.  
    40. void init();
    41. void delay_ms(unsigned int ui_value);
    42. void beep(unsigned char uc_count);
    43. unsigned char reset();
    44. void write(char WRT);
    45. unsigned char read();
    46. void nibble(unsigned byte);
    47.  
    48. /*******************************************************************************
    49. * MAIN FUNCTION                                                                *
    50. *******************************************************************************/
    51. int main(void)
    52. {
    53.     unsigned temp, val;
    54.     unsigned short tempL, tempH, fraction;
    55.     unsigned int i = 0; // declare a variable to store  
    56.  
    57.     init();
    58.  
    59.     while(1)    // create an infinite loop
    60.     {      
    61.         if (reset() == ONEWIRE_PRESENT)
    62.         {
    63.             write(Skip_ROM);
    64.             write(Convert_T);      
    65.             delay_ms(DS18B20_CONV_TIME);
    66.            
    67.             reset();
    68.             write(Skip_ROM);       
    69.             write(Read_scratchpad);
    70.            
    71.             tempL = read();         //read low temp value
    72.             tempH = read();         //read high temp value
    73.            
    74.             //put both value in one variable
    75.             nibble(tempH);
    76.             delay_ms(WAIT1);
    77.             nibble(0);
    78.             delay_ms(WAIT2);
    79.            
    80.             temp = tempH >> 4;
    81.             nibble(temp);
    82.             delay_ms(WAIT1);
    83.             nibble(0);
    84.             delay_ms(WAIT2);
    85.  
    86.             nibble(tempL);
    87.             delay_ms(WAIT1);
    88.             nibble(0);
    89.             delay_ms(WAIT2);
    90.  
    91.             temp = tempL >> 4;
    92.             nibble(temp);
    93.             delay_ms(WAIT1);
    94.             nibble(0);
    95.             delay_ms(WAIT2);
    96.         } else {
    97.             break;
    98.         }
    99.     }
    100.  
    101.     // Solid LED pattern to indicate we're somewhere we shouldn't be.
    102.     RC0 = 1;
    103.     RC1 = 0;
    104.     RC2 = 1;
    105.     RC3 = 0;
    106.  
    107.     while (1) continue;
    108. }
    109.  
    110. void init()
    111. {
    112.     ANSEL = 0;      //Initialize A/D ports off
    113.     ANSELH = 0;     //Initialize A/D ports off
    114.     CM1CON0 = 0;    //Initialize comp 1 off
    115.     CM2CON0 = 0;    //Initialize comp 2 off
    116.     PORTA = 0x00;   // Clears PORTA
    117.     PORTB = 0x00;   // Clears PORTB
    118.     PORTC = 0x00;   // Clears PORTC
    119.     TRISA = 0x00;   // Sets PORTA to all output
    120.     TRISB = 0x00;   // Sets PORTB to all output
    121.     TRISC = 0x00;   // sets PORTC to all output.
    122.  
    123.     // We want 8MHz
    124.     OSCCON = INT_OSC_8MHZ;
    125.  
    126.     // Wait for clock to stabilise.
    127.     delay_ms(10);
    128. }
    129.  
    130. void nibble(unsigned byte)
    131. {
    132.     PORTC = (unsigned)(byte & 0x0f);
    133.     return;
    134. }
    135.  
    136. void delay_ms(unsigned int ui_value)
    137. {
    138.     while (ui_value-- != 0) {
    139.         __delay_ms(1);                  // macro from HI-TECH compiler which will generate 1ms delay base on value of _XTAL_FREQ in system.h
    140.     }  
    141. }
    142.  
    143. unsigned char reset()
    144. {
    145.     Tx_18B20;                           // Tris = 0 (output)
    146.     Port_18B20 = 0;                     // set pin# to low (0)
    147.     __delay_us(DS18B20_RESET_PULSE);    // 1 wire require time delay
    148.     Rx_18B20;                           // Tris = 1 (input)
    149.     __delay_us(DS18B20_WAIT_TIME);      // 1 wire require time delay
    150.  
    151.     if (Port_18B20 == 0)                // if there is a presence pluse
    152.     {
    153.         __delay_us(DS18B20_RESET_PULSE);// Reset and return
    154.         return ONEWIRE_PRESENT;         // return 0 ( 1-wire is presence)
    155.     }
    156.  
    157.     __delay_us(DS18B20_RESET_PULSE);    // Reset and return
    158.     return ONEWIRE_ABSENT;              // return 1 ( 1-wire is NOT presence)
    159. }
    160.  
    161. void write(char WRT)
    162. {
    163.     char i,Cmd;
    164.     Cmd = WRT;
    165.     Rx_18B20; // set pin# to input (1)
    166.     for(i = 0; i < 8; i++)
    167.     {
    168.         if((Cmd & (1<<i))!= 0)
    169.         {
    170.             // write 1
    171.             Tx_18B20; // set pin# to output (0)
    172.             Port_18B20 = 0; // set pin# to low (0)
    173.             __delay_us(DS18B20_PULLUP_TIME); // 1 wire require time delay
    174.             Rx_18B20; // set pin# to input (release the bus)
    175.             __delay_us(DS18B20_WAIT_TIME); // 1 wire require time delay
    176.         } else  {
    177.             //write 0
    178.             Tx_18B20; // set pin# to output (0)
    179.             Port_18B20 = 0; // set pin# to low (0)
    180.             __delay_us(DS18B20_WAIT_TIME); // 1 wire require time delay
    181.             Rx_18B20; // set pin# to input (release the bus)
    182.         }
    183.     }
    184. }
    185.  
    186. unsigned char read()
    187. {
    188.     char i,result = 0;
    189.     Rx_18B20; // TRIS is input(1)
    190.     for(i = 0; i < 8; i++)
    191.     {
    192.         Tx_18B20; // TRIS is output(0)
    193.         Port_18B20 = 0; // genarate low pluse for 2us
    194.         __delay_us(DS18B20_PULLUP_TIME);
    195.         Rx_18B20; // TRIS is input(1) release the bus
    196.         if(Port_18B20 != 0) {
    197.             result |= 1<<i;
    198.         }
    199.         __delay_us(DS18B20_WAIT_TIME); // wait for recovery time
    200.     }
    201.     return result;
    202. }
    203.  
     
  6. Litch

    Thread Starter Member

    Jan 25, 2013
    86
    7
    I suspect the delay_us and delay_ms may be off, as this would explain the lack of communication between the DS18 and the PIC, it would also explain why it's still seeing the response from the DS18 as the timing on that is large and less specific compared to the read/write timing.

    But if I blink an LED at 1000ms it definitely seems like 1 second.../sigh...what I would do for a decent oscilloscope...
     
  7. Litch

    Thread Starter Member

    Jan 25, 2013
    86
    7
    Q: This PIC has an internal timer. How would I go about verifying the delay_ms() time using the LEDs?

    Something like:
    TMR0 = (Whatever equates to 500ms)
    delay_ms(500);
    RC0 = 1


    (When the Timer interrupt triggers RC1 = 1)

    Then I could see which turns on first, or if they're about right.

    Sound feasible?
     
  8. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    Nah, too much work and too much room for error. Besides, if the line:

    Code ( (Unknown Language)):
    1. #define    _XTAL_FREQ            8000000
    accurately reflects the crystal in the hardware then the delays will be correct.

    If you flashed the led for a second and it looks good by your watch then you nailed it.
     
  9. Litch

    Thread Starter Member

    Jan 25, 2013
    86
    7
    OMFG

    It was a dud breadboard.

    The +Ve strip up the side didn't continue past just over 1/3 of the length and the DQ pull up and Vcc for the DS18B20 wasn't even powered.

    Just because I made the assumption that the 1-wire was detecting within the PIC code that the temp IC was fine and it was an I/O issue...

    Works now, and the LEDS flash:
    1000
    0000
    0110
    0101

    Which is b'0000 0001 0101 0110'
    Which is decimal 378
    ...23.625 C

    I put my finger on it for a few seconds...

    1000
    0000
    1010
    0011

    Which is b'0000 0001 1100 0101'
    ...28.3125 C

    Which is about right.
     
Loading...