8 Bit Shift Register with PIC16F628A

Discussion in 'Embedded Systems and Microcontrollers' started by beeson76, Jul 30, 2012.

  1. beeson76

    Thread Starter Member

    Apr 19, 2010
    185
    1
    I know this is a long shot:)

    I have a TPIC6595 8 Bit Shift Register on a Board that is "connected" to a PIC16F628A Microchip.

    Please see the following pictures.

    Here are the connections from the Pic to the Shift Register

    RA1 goes to RCK
    RA0 goes to SRCLR
    RA2 goes to SRCK
    RA3 goes to G
    RA4 goes to SER IN

    In the pictures below, the shift register goes on U2 and the Microchip goes on U1.

    And then the the 8 Drain from the Shift Register are all connected to corresponding relays which in turn are connected to motors.

    You wont like it very much but I don't have a schematic of the circuit but I can certainly provide pictures, and maybe draw up a crude schematic in autocad or something.

    As far as the inputs I have 7 inputs (PORTB) on the Microchip that is connected to a controller that eventually controls the motors. For example, you hit Switch1, and the microchip recognizes the button press and sends a control to the shift register which in turns sends control to the relay for Motor1. (I am assuming that is how is works, because I don't really know anything about shift registers)

    So now to the problem. I don't have any code for the Microchip. I can program the code in C, and I already have the code written to recognize the button press and now I am stuck on how I send it to the shift register. I did some reading on the internet, and I am getting more confused, the more I read. I just need some help in being pointed in the right direction, such as how to write the code.

    Any help in getting pointed in the right direction would be greatly appreciated:)
     
    Last edited: Jul 30, 2012
  2. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    It sounds like you're looking for a function like this, maybe?

    Code ( (Unknown Language)):
    1.    #define dat porta.4          // RA4 = SER(in)
    2.    #define clk porta.2          // RA2 = SRCK
    3.    #define lat porta.1          // RA1 = RCK
    4.  
    5.    void shiftout(char work)
    6.    { unsigned char i;           //
    7.      for(i=8; i>0; i--)         // load TPIC6C595 shift register
    8.      { dat = 0; clk = 0;        // preset dat and clk pins
    9.        if(work.7) dat = 1;      // set dat to '1' for a '1' bit
    10.        clk = 1;                 // clock out the bit
    11.        work <<= 1;              // prep for next bit
    12.      }                          //
    13.      lat = 1; lat = 0;          // copy SR bits onto the outputs
    14.    }                            //
    15.  
    You could probably tie the clear pin to VCC and the output enable pin to ground, unless you have some other operations in mind for those pins.

    Regards, Mike
     
  3. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    If it matters what happens to the relays as the PIC is first powered up / reset, you can connect the output enable to 5V with a 10K resistor and then pull it low with a pin once valid data has been shifted in.
    Here's some assembler which is fairly well optimised for speed (assumes there are no other outputs on PORTA, and it's missing the storage register pulse).
    Code ( (Unknown Language)):
    1.     clrf PORTA
    2.     clrw
    3.     btfsc INDF, 7
    4.     movlw 2
    5.     movwf PORTA        ;set or clear PORTA, 1 (data)
    6.     andlw 1
    7.     movwf PORTA        ;set PORTA, 0 (clock)
    8.    
    9.     clrf PORTA
    10.     clrw
    11.     btfsc INDF, 6
    12.     movlw 2
    13.     movwf PORTA        ;set or clear PORTA, 1 (data)
    14.     andlw 1
    15.     movwf PORTA        ;set PORTA, 0 (clock)
    16.    
    17.     clrf PORTA
    18.     clrw
    19.     btfsc INDF, 5
    20.     movlw 2
    21.     movwf PORTA        ;set or clear PORTA, 1 (data)
    22.     andlw 1
    23.     movwf PORTA        ;set PORTA, 0 (clock)
    24.    
    25.     clrf PORTA
    26.     clrw
    27.     btfsc INDF, 4
    28.     movlw 2
    29.     movwf PORTA        ;set or clear PORTA, 1 (data)
    30.     andlw 1
    31.     movwf PORTA        ;set PORTA, 0 (clock)
    32.    
    33.     clrf PORTA
    34.     clrw
    35.     btfsc INDF, 3
    36.     movlw 2
    37.     movwf PORTA        ;set or clear PORTA, 1 (data)
    38.     andlw 1
    39.     movwf PORTA        ;set PORTA, 0 (clock)
    40.    
    41.     clrf PORTA
    42.     clrw
    43.     btfsc INDF, 2
    44.     movlw 2
    45.     movwf PORTA        ;set or clear PORTA, 1 (data)
    46.     andlw 1
    47.     movwf PORTA        ;set PORTA, 0 (clock)
    48.    
    49.     clrf PORTA
    50.     clrw
    51.     btfsc INDF, 1
    52.     movlw 2
    53.     movwf PORTA        ;set or clear PORTA, 1 (data)
    54.     andlw 1
    55.     movwf PORTA        ;set PORTA, 0 (clock)
    56.    
    57.     clrf PORTA
    58.     clrw
    59.     btfsc INDF, 0
    60.     movlw 2
    61.     movwf PORTA        ;set or clear PORTA, 1 (data)
    62.     andlw 1
    63.     movwf PORTA        ;set PORTA, 0 (clock)
     
  4. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    You could probably have some fun with this project. For example, if you're using the push button switches to emulate toggle switches (press to toggle a motor from on-to-off or from off-to-on), each pin can support both a switch and an LED, like this;

    [​IMG]

    There are some nice lighted push button switches available. I used some from Mouser in the past that looked like this;

    [​IMG]

    Software for debouncing and reading the switches, as well as driving the LEDs, is relatively simple. Here's a small (untested) example program using the free/lite version of BoostC;

    Cheerful regards, Mike

    Code ( (Unknown Language)):
    1. /********************************************************************
    2.  *                                                                  *
    3.  *  Project: Relay Demo                                             *
    4.  *   Source: Relay_Demo.c                                           *
    5.  *   Author: Mike McLaren, K8LH                                     *
    6.  *     Date: 30-Jul-12                                              *
    7.  *  Revised: 30-Jul-12                                              *
    8.  *                                                                  *
    9.  *  16F628A + TPIC6C595 Eight Channel Relay Demo                    *
    10.  *                                                                  *
    11.  *                                                                  *
    12.  *      IDE: MPLAB 8.84 (tabs = 4)                                  *
    13.  *     Lang: SourceBoost BoostC v7.05, Lite/Free version            *
    14.  *                                                                  *
    15.  ********************************************************************/
    16.  
    17.   #include <system.h>
    18.  
    19.   #pragma DATA _CONFIG, _LVP_OFF&_MCLRE_OFF&_WDT_OFF&_INTOSC_OSC_NOCLKOUT
    20.  
    21.   #pragma CLOCK_FREQ 4000000      // 4-MHz Internal Oscillator
    22.  
    23. //--< function prototypes >------------------------------------------
    24. //--< typedef and defines >------------------------------------------
    25.  
    26.   #define clk porta.2           // RA2 -> SCK (serial clock)
    27.   #define dat porta.4           // RA4 -> SER (data input)
    28.   #define lat porta.1           // RA1 -> RCK (data latch)
    29.  
    30. //--< variables >----------------------------------------------------
    31.  
    32.   char swnew = 0;               //
    33.   char swold = 0;               // switch state latch
    34.   char flags = 0;               // toggle state flags
    35.  
    36. //--< functions >----------------------------------------------------
    37.  
    38. /********************************************************************
    39.  *  main init                                                       *
    40.  ********************************************************************/
    41.  
    42.  void main()
    43.  {
    44.    cmcon = 0x07;                // comparator off for digital I/O
    45.    trisb = 0b11111111;          // set all pins to inputs
    46.    trisa = 0b00000000;          // set all pins to outputs
    47.    portb = 0b00000000;          // set all output latches to '0'
    48.    porta = 0b00000000;          // set all output latches to '0'
    49.  
    50. /********************************************************************
    51.  *  main loop                                                       *
    52.  ********************************************************************/
    53.  
    54.    while(1)
    55.    { delay_ms(25);              // 25-msec sample intervals
    56.  
    57.   /*                                                                *
    58.    *  Lighted Push Button Switches (emulated toggle switches)       *
    59.    *                                                                *
    60.    *  swnew  ____---____-----___   sample active lo switches        *
    61.    *  swold  _____---____-----__   switch state latch               *
    62.    *  swnew  ____-__-___-____-__   changes, press or release        *
    63.    *  swnew  ____-______-_______   filter out 'release' bits        *
    64.    *  flags  _____-------_____--   toggle flag bits for main        *
    65.    *  trisb  -----_______-----__   toggle tris bits for LEDs        *
    66.    *                                                                */
    67.      trisb = 0b11111111;        // set all portb to inputs
    68.      swnew = ~portb;            // sample active lo switches
    69.      swnew ^= swold;            // changes, press or release
    70.      swold ^= swnew;            // update switch state latch
    71.      swnew &= swold;            // filter out 'release' bits
    72.      flags ^= swnew;            // toggle flag bits for main
    73.      portb = 0b00000000;        // clear portb output latches
    74.      trisb ^= flags;            // light only active sw LEDs
    75.  
    76.   /*                                                                *
    77.    *  update TPIC6C595 outputs after any switch state change        *
    78.    *                                                                */
    79.      if(swnew)                  // if any "new press" bits
    80.      { char mask = 0b10000000;  //
    81.        while(mask)              // shift out 8 bits
    82.        { clk = 0; dat = 0;      //
    83.          if(flags & mask)       // if a '1' bit
    84.            dat = 1;             // set <dat> pin
    85.          clk = 1;               // clock out the <dat> bit
    86.          mask >>= 1;            // shift mask for next bit
    87.        }                        //
    88.        lat = 1; lat = 0;        // copy SR bits onto outputs
    89.      }                          //
    90.    }                            //
    91.  }                              //
    92.  
     
    Last edited: Jul 31, 2012
  5. beeson76

    Thread Starter Member

    Apr 19, 2010
    185
    1
    Wow:), thanks guys for the nice replies.

    My programming will be really basic, and after I get the concept I will put things in functions etc. Here is what I have right off. It will require a lot more work, but Im just wanting to get some of your opinions.

    Here is my code. It is not compiled yet, and therefore untested. I think it is pretty well commented out, so you should be able to figure out:):)

    Code ( (Unknown Language)):
    1.  
    2. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    3. //
    4. //This program controls a Matrix Switch.  The Switch consists of 2 columns and 5 rows.
    5. //Whenever a switch is pushed it simply turns on a motor.
    6. //The PIC16F628A Microcontroller from Microchip is being used.  
    7. //Also the TPIC6595N 8 Bit Shift Register is being used.  It will be controlled by the PIC16F628A chip.
    8. //
    9. //RA1 goes to RCK on TPIC6595N
    10. //RA0 goes to SRCLR ""
    11. //RA2 goes to SRCK ""
    12. //RA3 goes to G ""
    13. //RA4 goes to SER IN ""
    14. //
    15. //As I learn more about the TPIC6595N I will write more about it here:)
    16. //
    17. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    18. #define _LEGACY_HEADERS
    19.  
    20. #include <htc.h>
    21.  
    22.  
    23. #define dat             RA4         // RA4 = SER(in)
    24. #define clk             RA2         // RA2 = SRCK
    25. #define lat             RA1         // RA1 = RCK
    26.  
    27. #define COL_1           RB0
    28. #define COL_2           RB1
    29. #define ROW_1           RB3
    30. #define ROW_2           RB4
    31. #define ROW_3           RB5
    32. #define ROW_4           RB6
    33. #define ROW_5           RB7
    34.  
    35. #define  DelayS(T)      {unsigned char i; for (i = 0; i < T * 10; i++) __delay_ms(100);}    //Delay Macro
    36. #define  _XTAL_FREQ             4000000                             //Needs to be set for __delay_ms
    37.  
    38.  
    39. //Master Clear Reset enabled & Internal RC No Clock & Watchdog Timer Disable & Power Up Timer On & Brown Out Reset Disabled &
    40. // Low Voltage Porgramming Disabled & Code Unprotect
    41. __CONFIG (MCLREN & INTIO & WDTDIS & PWRTEN & BORDIS & LVPDIS & UNPROTECT);
    42.  
    43. main()
    44. {
    45.    
    46. PORTA = 0x00;                                       //PORTA is cleared and set low
    47. PORTB = 0xFF;                                       //(0b11111111 binary) (0xFF hex)--ROWS set to HIGH, COLUMNS set to HIGH  
    48.                                                     //PORTB7:B0 is set to high,high,high,high,high,high,high,high)
    49.                                                    
    50. TRISA = 0x00;                                       //Set PORTA to outputs for LCD--RA1, RA2, RA4 are Control lines for LCD
    51.  
    52. TRISB = 0x7C;                                       //(0b01111100 binary) (0x7C hex)--ROWS set to INPUT, COLUMNS set to OUTPUT
    53.                                                     //PORTB7:B0 is set to output,input,input,input,input,input,output,output,
    54.                                                     //ROWS set to INPUT
    55.  
    56. OPTION = 0b01010101;                                //OPTION REG
    57.                                                     //xbxxxxx101  1:64
    58.                                                     //xbxxxx0xxx  Prescaler set to Timer0
    59.                                                     //xbxxx1xxxx  (T0SE) set to Increment on high-to-low transition on T0CKI pin
    60.                                                     //xbxx0xxxxx  (T0CS) Internal instruction cycle clock
    61.                                                     //xbx1xxxxxx  (INTEDG) Interrupt on rising edge of INT pin
    62.                                                     //xb0xxxxxxx  (RBPU) PORTB pull-ups are enabled by individual PORT latch values
    63. RBPU = 0;                                           //Don't think I need this, but to be safe...PORTB Weak Internal Pullups enabled
    64. WPUB0 = 0;                                          //COL_1 Weak pullup is individually DISABLED--OUTPUT
    65. WPUB1 = 0;                                          //COL_2 Weak Pullup is inidivdually DISABLED--OUTPUT
    66. WPUB2 = 0;                                          //Not being used...Weak Pullup is individually DISABLED
    67. WPUB3 = 1;                                          //ROW_1 Weak Pullup is individually ENABLED--INPUT
    68. WPUB4 = 1;                                          //ROW_2 Weak Pullup is individually ENABLED--INPUT
    69. WPUB5 = 1;                                          //ROW_3 Weak Pullup is individually ENABLED--INPUT
    70. WPUB6 = 1;                                          //ROW_4 Weak Pullup is individually ENABLED--INPUT
    71. WPUB7 = 0;                                          //COL_3 Weak Pullup is individually DISABLED--INPUT
    72.  
    73.  
    74. char i;
    75.  
    76.  
    77. while (1)
    78.     {
    79.         COL_1 = 0;                                  //COLUMN 1 is set LOW
    80.         if (ROW_1 == 0)                             //and If ROW 1 is LOW...
    81.             {
    82.                 for (i = 8; i > 0; i--)             // load TPIC6C595 shift register
    83.                         {
    84.                             dat = 0;
    85.                             clk = 0;                // preset dat and clk pins
    86.                             if(work.7)
    87.                                 {
    88.                                     dat = 1;        // set dat to '1' for a '1' bit
    89.                                 }
    90.                             clk = 1;                // clock out the bit
    91.                             work <<= 1;             // prep for next bit
    92.                         }                           //
    93.                         lat = 1;
    94.                         lat = 0;                    // copy SR bits onto the outputs
    95.             }
    96.                
    97.         if (ROW_2 == 0)                             //if ROW 2 is LOW...
    98.             {
    99.                 for (i = 8; i > 0; i--)             // load TPIC6C595 shift register
    100.                         {
    101.                             dat = 0;
    102.                             clk = 0;                // preset dat and clk pins
    103.                             if(work.7)
    104.                                 {
    105.                                     dat = 1;        // set dat to '1' for a '1' bit
    106.                                 }
    107.                             clk = 1;                // clock out the bit
    108.                             work <<= 1;             // prep for next bit
    109.                         }                           //
    110.                         lat = 1;
    111.                         lat = 0;                    // copy SR bits onto the outputs                                       
    112.             }  
    113.         if (ROW_3 == 0)                             //If ROW 3 is LOW
    114.             {
    115.                 for (i = 8; i > 0; i--)             // load TPIC6C595 shift register
    116.                         {
    117.                             dat = 0;
    118.                             clk = 0;                // preset dat and clk pins
    119.                             if(work.7)
    120.                                 {
    121.                                     dat = 1;        // set dat to '1' for a '1' bit
    122.                                 }
    123.                             clk = 1;                // clock out the bit
    124.                             work <<= 1;             // prep for next bit
    125.                         }                           //
    126.                         lat = 1;
    127.                         lat = 0;                    // copy SR bits onto the outputs                                       
    128.             }
    129.         if (ROW_4 == 0)                             //If ROW 4 is LOW
    130.             {
    131.                 for (i = 8; i > 0; i--)             // load TPIC6C595 shift register
    132.                         {
    133.                             dat = 0;
    134.                             clk = 0;                // preset dat and clk pins
    135.                             if(work.7)
    136.                                 {
    137.                                     dat = 1;        // set dat to '1' for a '1' bit
    138.                                 }
    139.                             clk = 1;                // clock out the bit
    140.                             work <<= 1;             // prep for next bit
    141.                         }                           //
    142.                         lat = 1;
    143.                         lat = 0;                    // copy SR bits onto the outputs                                       
    144.             }
    145.         if (ROW_5 == 0)                             //If ROW 4 is LOW
    146.             {
    147.                 for (i = 8; i > 0; i--)             // load TPIC6C595 shift register
    148.                         {
    149.                             dat = 0;
    150.                             clk = 0;                // preset dat and clk pins
    151.                             if(work.7)
    152.                                 {
    153.                                     dat = 1;        // set dat to '1' for a '1' bit
    154.                                 }
    155.                             clk = 1;                // clock out the bit
    156.                             work <<= 1;             // prep for next bit
    157.                         }                           //
    158.                         lat = 1;
    159.                         lat = 0;                    // copy SR bits onto the outputs                                       
    160.             }
    161.            
    162.         COL_1 = 1;                                  //COLUMN 1 is set HIGH again
    163.         COL_2 = 0;                                  //COLUMN 2 is set LOW
    164.         if (ROW_1 == 0)                             //and If ROW 1 is LOW...
    165.             {
    166.                 for (i = 8; i > 0; i--)             // load TPIC6C595 shift register
    167.                         {
    168.                             dat = 0;
    169.                             clk = 0;                // preset dat and clk pins
    170.                             if(work.7)
    171.                                 {
    172.                                     dat = 1;        // set dat to '1' for a '1' bit
    173.                                 }
    174.                             clk = 1;                // clock out the bit
    175.                             work <<= 1;             // prep for next bit
    176.                         }                           //
    177.                         lat = 1;
    178.                         lat = 0;                    // copy SR bits onto the outputs                                       
    179.             }
    180.                
    181.         if (ROW_2 == 0)                             //if ROW 2 is LOW...
    182.             {
    183.                 for (i = 8; i > 0; i--)             // load TPIC6C595 shift register
    184.                         {
    185.                             dat = 0;
    186.                             clk = 0;                // preset dat and clk pins
    187.                             if(work.7)
    188.                                 {
    189.                                     dat = 1;        // set dat to '1' for a '1' bit
    190.                                 }
    191.                             clk = 1;                // clock out the bit
    192.                             work <<= 1;             // prep for next bit
    193.                         }                           //
    194.                         lat = 1;
    195.                         lat = 0;                    // copy SR bits onto the outputs                                       
    196.             }
    197.         if (ROW_3 == 0)                             //If ROW 3 is LOW
    198.             {
    199.                 for (i = 8; i > 0; i--)             // load TPIC6C595 shift register
    200.                         {
    201.                             dat = 0;
    202.                             clk = 0;                // preset dat and clk pins
    203.                             if(work.7)
    204.                                 {
    205.                                     dat = 1;        // set dat to '1' for a '1' bit
    206.                                 }
    207.                             clk = 1;                // clock out the bit
    208.                             work <<= 1;             // prep for next bit
    209.                         }                           //
    210.                         lat = 1;
    211.                         lat = 0;                    // copy SR bits onto the outputs                                       
    212.             }
    213.         if (ROW_4 == 0)                             //If ROW 4 is LOW
    214.             {
    215.                 for (i = 8; i > 0; i--)             // load TPIC6C595 shift register
    216.                         {
    217.                             dat = 0;
    218.                             clk = 0;                // preset dat and clk pins
    219.                             if(work.7)
    220.                                 {
    221.                                     dat = 1;        // set dat to '1' for a '1' bit
    222.                                 }
    223.                             clk = 1;                // clock out the bit
    224.                             work <<= 1;             // prep for next bit
    225.                         }                           //
    226.                         lat = 1;
    227.                         lat = 0;                    // copy SR bits onto the outputs                                       
    228.             }
    229.         if (ROW_5 == 0)                             //If ROW 4 is LOW
    230.             {
    231.                 for (i = 8; i > 0; i--)             // load TPIC6C595 shift register
    232.                         {
    233.                             dat = 0;
    234.                             clk = 0;                // preset dat and clk pins
    235.                             if(work.7)
    236.                                 {
    237.                                     dat = 1;        // set dat to '1' for a '1' bit
    238.                                 }
    239.                             clk = 1;                // clock out the bit
    240.                             work <<= 1;             // prep for next bit
    241.                         }                           //
    242.                         lat = 1;
    243.                         lat = 0;                                                           
    244.             }
    245.         COL_2 = 1;                                      }
    246. }
    247.  
    248.  
    249.  
    Any help is greatly appreciated very much. I certainly appreciate it.
     
  6. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    Code ( (Unknown Language)):
    1. dat = 0;
    2.                             clk = 0;                // preset dat and clk pins
    3.                             if(work.7)
    4.                                 {
    5.                                     dat = 1;        // set dat to '1' for a '1' bit
    6.                                 }
    7.                             clk = 1;                // clock out the bit
    8.                             work <<= 1;  
    Code ( (Unknown Language)):
    1. clk=0;work<<=1;dat=CARRY;clk=1;
     
  7. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    hi beeson76,

    A couple questions, please? How are you using ten switches with only eight outputs? How do you want the switches to operate the motors? Do you only want a motor to stay on as long as a switch is being held pressed?
     
  8. beeson76

    Thread Starter Member

    Apr 19, 2010
    185
    1
    Thanks for your replies. The controller has 10 buttons. It is in a matrix switch...2 rows and 5 columns. I would like the motors to stay when you press the button, and keep it held down, and then go off when the button is depressed.

    Here is how I am programming the matrix switch, there could probably be better code for it, but I want to keep it simple at first.

    I am bringing my pin low for my column first, then I am scanning for any of my rows to go low. When a pin goes low, the program is suppose to read it:) and then keep it held low until it is released.

    Then I am bringing my pin high on my column, and then it passes on to the pin for my second column.

    It keeps scanning like this until a button is pressed...or suppose to anyway:)

    I really do appreciate the help guys. I love this forum.
     
  9. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    I'm sorry but I don't quite understand. You want a motor to come on when it's switch is pressed and then go off when the switch is depressed (???). Did you mean to say the motor would go off when the switch was released?

    Also, you didn't say how you intend to use ten switches for eight outputs.
     
  10. beeson76

    Thread Starter Member

    Apr 19, 2010
    185
    1
    No thats fine:)

    I have 7 pins being used on my PORTB. 2 Pins on being used for my Columns on my matrix switch and 5 pins are being used for my Rows on my switch.

    Yes when a button is pressed and continued to be pressed, I would like the motor to come on and stay on. Then when the button is let go, I would like the motor to go off.

    As far as the chip controlling the 8 bit shift register, I have no idea how it "communicates" with the chip except for the pins that I traced down. They mentioned in the first post. I would like to know the sequence of the "communication" between the chip and shift register, such as do you have to bring something high, write the bits, and then bring it low to send it, and then clear the register, for the next set of bits.

    There are a total of 4 motors--each have a set of relays (2 relays per motor) for each motor. One relay controls the up function of the motor, and the other relay controls the down function of the motor. 2 buttons on the control, control 2 motors.

    I think I understand now how you were confused:) I wasnt making myself clear at all. I left out a lot of details:)

    I will try to clarify things a little bit. 4 sets of buttons on the control each control a motor...each set has an up and down button--thus you have 8 buttons. The 9th and 10 buttons control 2 motors in unison.

    I hope this helps. Please ask if you still need help with the layout. Sorry for the missed details:)
     
  11. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    That seems a bit more complicated. For example, will you need logic to prevent both the "up" and "down" relays for any particular motor from actuating at the same time?
     
  12. beeson76

    Thread Starter Member

    Apr 19, 2010
    185
    1
    Yes I will.

    I have a circuit board, with all components. I have the original code for the PIC but for some reason, it always locks up the relays after using it a little bit. The only way of getting it to shut down is unplug it, listen for the relay to unlatch and wait a few seconds even after that. After plugging it back in it will work normally until it happens again:)

    Something is causing the whole circuit to lock up with relays latched, and I am trying to check to see if it is the programming. The programming is using the CCS Compiler which Im really not familiar to. But I have an old version (2007) laying around. Here is the original code for it.
     
  13. beeson76

    Thread Starter Member

    Apr 19, 2010
    185
    1
    Code ( (Unknown Language)):
    1.  
    2.  
    3. /* Pre-processor **************************************************************/
    4. #include "16F628.h"     // Header file.
    5. #include <stdlib.h>
    6.  
    7.  
    8. #case                           // Makes CCS case sensative.
    9. #use standard_io(A)    
    10.  
    11. #define ON 1                // These are useful.
    12. #define OFF 0
    13. #define bool short int  // 'Boolean' and "short int" take too long to type!
    14.  
    15. #define SRCLR  PIN_A0   // Clears input shift register (active low).
    16. #define RCK    PIN_A1   // Sends shift register data to outputs of device.
    17. #define SRCK   PIN_A2   // Shift register clock (advances serial data on L-to-H).
    18. #define G      PIN_A3   // Enable outputs of shift register.
    19. #define SIN    PIN_A4   // Serial data input (I/O must have a pull-up resistor).
    20.  
    21. /* Global Variables and Setup**************************************************/
    22. struct pendant_map {        // Defines the pendant port.
    23.     bool col_1;          // Up
    24.     bool col_2;          // Down
    25.     bool unused_col_3;
    26.     int  keys : 5;       // Head, Foot, Bed, Seat, Trend, Chair.
    27. }pendant;
    28.  
    29. #byte pendant = 6          // To port B.
    30.  
    31. struct function {       // Maps the function to a port pin.
    32.     bool hu;
    33.     bool hd;
    34.     bool fu;
    35.     bool fd;
    36.     bool bu;
    37.     bool bd;
    38.     bool t;
    39.     bool tr;
    40.     bool su;
    41.     bool sd;
    42. };
    43.  
    44. struct scan {       // Holds the information grabbed from the port.
    45.     int in : 5;
    46.     int unused : 3;
    47. };
    48.  
    49. struct key {        // Used to decode the individual port pins.
    50.     bool h;
    51.     bool f;
    52.     bool b;
    53.     bool t;
    54.     bool s;
    55.    bool un1;
    56.    bool un2;
    57.    bool un3;
    58. };
    59.  
    60. union combine { // See above 2 blocks.
    61.     struct scan a;
    62.    struct key b;
    63. };
    64.  
    65. union mix{  // Used to convert up/down to one variable.
    66.     struct function data;
    67.    long ldata;
    68. };
    69.  
    70. int const PRESCALE = 13;    // Timer0 preset value. For perfect 4MHz (maybe).
    71. int go_thous = 0;               // For main process loop entry.
    72. int to_out = 0;            // Data that is sent to 6595 IC.
    73.  
    74. struct scan up;       // Holds pendant up data 'up.in'.
    75. struct scan dn;         // Holds pendant dn data 'dn.in'.
    76.  
    77. union mix info;         // This is 2 pendant data values converted to 1 long.
    78. long deb_info;              // Use as temp storage to debounce buttons in 'isr'.
    79. union mix use_info;     // Actual modified pendant data to use.
    80.  
    81. /* Function declarations ******************************************************/
    82. void setup_io(void);            // Sets up all I/O ports.
    83. void start_rtcc(void);      // Sets up the rtcc counter.
    84. void convert(void);         // Convert 2 pendant data values to 1 long.
    85. void check_input(void);     // Enforces buttons pressed follow rules.
    86. void motor_timers(void);    // Sets "change of direction" timers.
    87. void process_state(void);   // Determines outputs for running motors.
    88. void rtcc_isr(void);            // Interrupt service routine.
    89. void make_it_so(void);     // Output to motors.
    90.  
    91.  
    92.  
    93.  
    94.  
    95.  
    96. // Main ***********************************************************************
    97.  
    98. main() {
    99.     setup_io();
    100.     start_rtcc();
    101.  
    102.     while(TRUE) {
    103.         if(go_thous){           // This variable set in isr.
    104.             go_thous = 0;
    105.  
    106.             check_input();
    107.             motor_timers();
    108.             process_state();
    109.             make_it_so();
    110.         }
    111.     }
    112. return 0;
    113. }
    114.  
    115. // Function definitions ********************************************************
    116.  
    117. void setup_io(void) {
    118.    set_tris_b(248);             // 1-input, 0-output. All out.
    119.    port_b_pullups(TRUE);        // Use internal pullups.
    120.    output_high(G);         // Turns off outputs.
    121.    output_low(SRCLR);    // Clear input register.
    122.    output_high(SRCLR);     // Input register back on.
    123.    output_low(SRCK);     // Set clock input low.
    124.    output_low(RCK);      // Set sr clock low.
    125.    output_low(SIN);
    126. }
    127.  
    128. void start_rtcc(void) {
    129.     setup_counters(RTCC_INTERNAL, RTCC_DIV_4);
    130.     set_rtcc(PRESCALE);         // Tunes the actual time to overflow.
    131.     enable_interrupts(INT_RTCC);
    132.     enable_interrupts(GLOBAL);
    133. }
    134.  
    135. #int_rtcc       // RTCC interrupt subroutine.
    136. rtcc_isr(void) {
    137.  
    138.     static int debounce = 0;        // Debouncing flag.
    139.     int const DEBOUNCE_TIME = 5;    // Amount X state_mach(max n+1) = milliseconds.
    140.     static int debounce_ctr = 0;    // Duh!
    141.     static int state_mach = 0;      // Usefull for switch/case block.
    142.  
    143.     set_rtcc(PRESCALE);             // Restart with prescale value (~ 1mS).
    144.     go_thous = 1;                       // For section of "main loop" entry.
    145.  
    146.     switch(state_mach) {
    147.         case 0:
    148.             pendant.col_1 = 0;      // Set up column low to check pendant.
    149.             state_mach = 1;
    150.             break;
    151.         case 1:
    152.             up.in = ~pendant.keys;  // Pullups used so ~port to get a high value
    153.             state_mach = 2;         // on the button pressed.
    154.             break;
    155.         case 2:
    156.             pendant.col_1 = 1;      // Change to scan down column.
    157.             pendant.col_2 = 0;
    158.             state_mach = 3;
    159.             break;
    160.         case 3:
    161.             dn.in = ~pendant.keys;  // Same as above.
    162.             state_mach = 4;
    163.             break;
    164.         case 4:
    165.             pendant.col_2 = 1;      // Restore down column to 'high'.
    166.             state_mach = 5;
    167.             convert();                  // Convert the data to a single long.
    168.             break;
    169.         case 5:
    170.             if(debounce){
    171.                 if(--debounce_ctr == 0){    // Only do work if debounce completed.
    172.                     debounce = OFF;
    173.                     if(info.ldata == deb_info) {    // If button still pressed.
    174.                         use_info.ldata = deb_info;  // Keep good data.
    175.                }
    176.                 }
    177.             }
    178.             else {
    179.             // Or if key changed.
    180.                 if(info.ldata != use_info.ldata){
    181.                     deb_info =  info.ldata;             // Save, to test it later.
    182.                     debounce_ctr = DEBOUNCE_TIME;       // Reset debounce timer.
    183.                     debounce = ON;                          // Start the timer.
    184.                 }
    185.             }
    186.             state_mach = 0;
    187.             break;
    188.         default:
    189.             state_mach = 0;
    190.             break;
    191.     }
    192.  
    193. return 0;
    194. }
    195.  
    196. void convert() {
    197.    union combine work;  // Used to decode functions in the input data.
    198.  
    199.    info.ldata = 0;      // Start with no data in the holder.
    200.    work.a.in = up.in;   // Put in up data.
    201.    if(work.b.h)
    202.     info.data.hu = ON;
    203.    if(work.b.f)
    204.     info.data.fu = ON;
    205.    if(work.b.b)
    206.     info.data.bu = ON;
    207.    if(work.b.t)
    208.     info.data.t = ON;
    209.    if(work.b.s)
    210.     info.data.su = ON;
    211.  
    212.    work.a.in = dn.in;   // Repeat above for down side.
    213.    if(work.b.h)
    214.     info.data.hd = ON;
    215.    if(work.b.f)
    216.     info.data.fd = ON;
    217.    if(work.b.b)
    218.     info.data.bd = ON;
    219.    if(work.b.t)
    220.     info.data.tr = ON;
    221.    if(work.b.s)
    222.     info.data.sd = ON;
    223. }
    224.  
    225. void check_input(void) {
    226.     if(use_info.data.hu && use_info.data.hd)    // Up/dn can never run together.
    227.         use_info.data.hu = 0;
    228.     if(use_info.data.fu && use_info.data.fd)
    229.         use_info.data.fu = 0;
    230.     if(use_info.data.bu && use_info.data.bd)
    231.         use_info.data.bu = 0;
    232.     if(use_info.data.t && use_info.data.tr)
    233.         use_info.data.tr = 0;
    234.     if(use_info.data.su && use_info.data.sd)
    235.         use_info.data.su = 0;
    236.  
    237.     // Place these in the order of precedence. Trend is master.
    238.     if(use_info.data.t) {  
    239.     use_info.ldata = 0;
    240.         use_info.data.t = ON;
    241.     }
    242.     if(use_info.data.tr) {
    243.     use_info.ldata = 0;
    244.         use_info.data.tr = ON;
    245.     }
    246.     if(use_info.data.sd) {
    247.     use_info.ldata = 0;
    248.         use_info.data.sd = ON;
    249.     }
    250.     if(use_info.data.su) {
    251.     use_info.ldata = 0;
    252.         use_info.data.su = ON;
    253.     }
    254. }
    255.  
    256.  
     
  14. beeson76

    Thread Starter Member

    Apr 19, 2010
    185
    1
    Code ( (Unknown Language)):
    1.  
    2. void motor_timers(void) {
    3.  
    4.     static struct function delays;  // Delay flags.
    5.  
    6.     static long hd_ctr = 0;     // Counters for up/dn delays.
    7.     static long hu_ctr = 0;
    8.     static long fd_ctr = 0;
    9.     static long fu_ctr = 0;
    10.     static long bd_ctr = 0;
    11.     static long bu_ctr = 0;
    12.     static long t_ctr = 0;
    13.     static long tr_ctr = 0;
    14.     static long su_ctr = 0;
    15.     static long sd_ctr = 0;
    16.  
    17.     static union mix last;  // Save to compare to button for timers.
    18.  
    19.     // Start change of direction delay timers if needed.
    20.     // If dn is off but was on, start the delay for up. etc...
    21.     if(!use_info.data.bd && last.data.bd) {
    22.         delays.bd = ON;
    23.         bd_ctr = 750;
    24.     }
    25.     if(!use_info.data.bu && last.data.bu) {
    26.         delays.bu = ON;
    27.         bu_ctr = 750;
    28.     }
    29.     if(!use_info.data.fd && last.data.fd) {
    30.         delays.fd = ON;
    31.         fd_ctr = 750;
    32.     }
    33.     if(!use_info.data.fu && last.data.fu) {
    34.         delays.fu = ON;
    35.         fu_ctr = 750;
    36.     }
    37.     if(!use_info.data.hd && last.data.hd) {
    38.         delays.hd = ON;
    39.         hd_ctr = 750;
    40.     }
    41.     if(!use_info.data.hu && last.data.hu) {
    42.         delays.hu = ON;
    43.         hu_ctr = 750;
    44.     }
    45.     if(!use_info.data.t && last.data.t) {
    46.         delays.t = ON;
    47.         t_ctr = 750;
    48.     }
    49.     if(!use_info.data.tr && last.data.tr) {
    50.         delays.tr = ON;
    51.         tr_ctr = 750;
    52.     }
    53.     if(!use_info.data.su && last.data.su) {
    54.         delays.su = ON;
    55.         su_ctr = 750;
    56.     }
    57.     if(!use_info.data.sd && last.data.sd) {
    58.         delays.sd = ON;
    59.         sd_ctr = 750;
    60.     }
    61.  
    62.     // This section prevents a direction change on the motors too quickly.
    63.     // Count down until opposite function can be used.
    64.     if(delays.fd) {
    65.         if(--fd_ctr == 0)
    66.             delays.fd = OFF;
    67.         else {
    68.             use_info.data.fu = OFF;
    69.             use_info.data.su = OFF;
    70.         }
    71.     }
    72.     if(delays.fu) {
    73.         if(--fu_ctr == 0)
    74.             delays.fu = OFF;
    75.         else {
    76.             use_info.data.fd = OFF;
    77.             use_info.data.sd = OFF;
    78.         }
    79.     }
    80.     if(delays.hd) {
    81.         if(--hd_ctr == 0)
    82.             delays.hd = OFF;
    83.         else {
    84.             use_info.data.hu = OFF;
    85.             use_info.data.su = OFF;
    86.         }
    87.     }
    88.     if(delays.hu) {
    89.         if(--hu_ctr == 0)
    90.             delays.hu = OFF;
    91.         else {
    92.             use_info.data.hd = OFF;
    93.             use_info.data.sd = OFF;
    94.         }
    95.     }
    96.     if(delays.bd) {
    97.         if(--bd_ctr == 0)
    98.             delays.bd = OFF;
    99.         else {
    100.             use_info.data.bu = OFF;
    101.             use_info.data.t = OFF;
    102.             use_info.data.tr = OFF;
    103.             use_info.data.su = OFF;
    104.             use_info.data.sd = OFF;
    105.         }
    106.     }
    107.     if(delays.bu) {
    108.         if(--bu_ctr == 0)
    109.             delays.bu = OFF;
    110.         else {
    111.             use_info.data.bd = OFF;
    112.             use_info.data.t = OFF;
    113.             use_info.data.tr = OFF;
    114.             use_info.data.su = OFF;
    115.             use_info.data.sd = OFF;
    116.  
    117.         }
    118.     }
    119.     if(delays.t) {
    120.         if(--t_ctr == 0)
    121.             delays.t = OFF;
    122.         else {
    123.             use_info.data.tr = OFF;
    124.             use_info.data.bd = OFF;
    125.             use_info.data.bu = OFF;
    126.             use_info.data.su = OFF;
    127.             use_info.data.sd = OFF;
    128.         }
    129.     }
    130.     if(delays.tr) {
    131.         if(--tr_ctr == 0)
    132.             delays.tr = OFF;
    133.         else {
    134.             use_info.data.t = OFF;
    135.             use_info.data.bd = OFF;
    136.             use_info.data.bu = OFF;
    137.             use_info.data.sd = OFF;
    138.         }
    139.     }
    140.     if(delays.su) {
    141.         if(--su_ctr == 0)
    142.             delays.su = OFF;
    143.         else {
    144.             use_info.data.hd = OFF;
    145.             use_info.data.fd = OFF;
    146.             use_info.data.sd = OFF;
    147.             use_info.data.t = OFF;
    148.             use_info.data.bu = OFF;
    149.             use_info.data.bd = OFF;
    150.         }
    151.     }
    152.     if(delays.sd) {
    153.         if(--sd_ctr == 0)
    154.             delays.sd = OFF;
    155.         else {
    156.             use_info.data.hu = OFF;
    157.             use_info.data.fu = OFF;
    158.             use_info.data.su = OFF;
    159.             use_info.data.bu = OFF;
    160.             use_info.data.t = OFF;
    161.             use_info.data.tr = OFF;
    162.         }
    163.     }
    164.  
    165.    last.ldata = use_info.ldata;
    166.  
    167. }
    168.  
    169. void process_state(void) {
    170.     struct bits{    // This is how the port is laid out.
    171.         bool fbu;
    172.         bool fbd;
    173.         bool hbu;
    174.         bool hbd;
    175.         bool fd;
    176.         bool fu;
    177.         bool hd;
    178.         bool hu;
    179.     };
    180.  
    181.     union both{     // So the port doesn't need to be accessed pin by pin.
    182.         int output;
    183.         struct bits out;
    184.     }process;
    185.  
    186.     process.output = 0;
    187.  
    188.     if(use_info.data.hu) {
    189.         process.out.hu = ON;
    190.     }
    191.     if(use_info.data.hd) {
    192.         process.out.hd = ON;
    193.     }
    194.     if(use_info.data.fu) {
    195.         process.out.fu = ON;
    196.     }
    197.     if(use_info.data.fd) {
    198.         process.out.fd = ON;
    199.     }
    200.     if(use_info.data.bu) {
    201.         process.out.fbu = ON;
    202.         process.out.hbu = ON;
    203.     }
    204.     if(use_info.data.bd) {
    205.         process.out.fbd = ON;
    206.         process.out.hbd = ON;
    207.     }
    208.     if(use_info.data.t) {
    209.         process.out.fbu = ON;
    210.         process.out.hbd = ON;
    211.     }
    212.     if(use_info.data.tr) {
    213.         process.out.fbd = ON;
    214.         process.out.hbu = ON;
    215.     }
    216.     if(use_info.data.su) {
    217.         process.out.hu = ON;
    218.         process.out.fu = ON;
    219.         process.out.fbd = ON;
    220.         process.out.hbu = ON;
    221.     }
    222.     if(use_info.data.sd) {
    223.         process.out.hd = ON;
    224.         process.out.fd = ON;
    225.         process.out.fbd = ON;
    226.         process.out.hbd = ON;
    227.     }
    228.  
    229.     to_out = process.output;
    230. }
    231.  
    232. void make_it_so() {
    233.    static int last_to_out = 0;
    234.    int ctr;
    235.    if(to_out != last_to_out) {
    236.       output_high(G);   // Turns off outputs.
    237.       output_low(SRCLR);    // Clear input register.
    238.       output_high(SRCLR);     // Input register back on.
    239.      
    240.       // Shift data out to shift register.
    241.       for(ctr = 0; ctr < 8; ctr++) {
    242.          output_bit(SIN, bit_test(to_out, ctr));
    243.          output_high(SRCK);   // Data shifts on L-to-H.
    244.          output_low(SRCK);
    245.       }
    246.      
    247.       output_high(RCK);    // Send data to outputs of shift register.
    248.       output_low(RCK);
    249.      
    250.       output_low(G);     // Enable shift register outputs.
    251.      
    252.       last_to_out = to_out;   // Save the most recent change.
    253.    }
    254. }
    255.  
    256.  
    257.  
     
  15. beeson76

    Thread Starter Member

    Apr 19, 2010
    185
    1
    But this program is not only way beyond me, but written using the CCS Compiler.

    So I was just going to write a simple code, to see if it is the programming or some hardware malfunction that is causing the relays to lock up.

    The code I was going to write didnt include any logic or switch debouncing or anything to that extent. I thought it was going to be pretty easy but I ran into the 8 bit shift register that I didnt' notice was connected to the PIC. Now I am having to program code to control the shift register, and I think I got in over my head:) But Im am viewing it as a learning experience too, because I would like to learn how to program for other chips on my PIC.

    Hope this all makes sense:) Its pretty complicated.
     
  16. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    Yeah, that's a bit more complicated. I apologize that I don't have the time to dig into it for you.

    Cheerful regards, Mike
     
  17. atferrari

    AAC Fanatic!

    Jan 6, 2004
    2,648
    764
    To put some clarity into your own ideas you should draw a circuit, first of all, for yourself. And then, show it here.
     
  18. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    An excellent point. And also draw out as a flowchart the operation sequence of the code. By the time you have done those two things it gets MUCH easier to fill the rest of the code in. :)
     
  19. beeson76

    Thread Starter Member

    Apr 19, 2010
    185
    1
    Thanks for the replies:)

    I will get a circuit drawn out. I wont draw the whole circuit out, but I will start from the chip and draw all the way to the relays. I will then post it here. The other parts of the relay are just the power side of things, but I can draw it if you think I need to.

    For some reason, I just have an inkling that the problem lies in the last block of code I sent you in the make_it_so() function.

    Can anyone tell just by looking at that function, if there would be a conflict that would cause problems. I don't know why I think so, its just an inkling:):)
     
  20. beeson76

    Thread Starter Member

    Apr 19, 2010
    185
    1
    Here is the board in a PDF format.

    I hope this will help in finding a solution to the problem.

    I certainly appreciate any and all help provided.
     
Loading...