[wpfp-link] 

Projeyi yapan arkadaş bunu ST4000 autoplot cihazını uzaktan kumanda edebilmek için yapmış.  Sistem transmitter-sinyal verici ve receiver-sinyal alıcı kullanılıyor. Alıcı ve verici 433 Mhz radyo sinyaliyle haberleşiyor.

Aşağıdaki resimde transmitter kısmı (tuş takımı) sol taraftadır. PIC16f628 mikrodenetleyicisi ile kontrol ediliyor. Kutunun içinde Parallax 433Mhz transmitter modülü var. 9V pille çalışıyor. Sürekli çalışmada pil aylarca dayanıyor. Açma kapama düğmesi yok. Sağ tarafta ise receiver (alıcı ) kısmı var. Kutunun içinde Parallax 433Mhz transmitter modülü var.

alici- verici

Aşağıda devre şemalarını paylaştık:

transmitter devresi
transmitter devresi
receiver devresi
receiver devresi

Program dosyaları:

Transmitter pic programı:

/****************************************************************************

seatalk_wireless_remote_tx_1.c

This program is a remote control transmitter that sends a RxCx
number in an eight−byte message sentence with checksum.

Message protocol to the wireless receiver
* Each 9600 baud message contains a command and checksum:
   0xff    // wake up the transmitter and receiver
   0xff    // wake up the transmitter and receiver
   0xff    // wake up the transmitter and receiver
   'J'     // character
   'S'     // character
   'F'     // character
   cMsgCode   // which key was pressed
   'J' + 'S' + 'F' + cMsgCode   // equals checksum

                    +5
                    |
                    14
                
      R4 −6−| B0    A0 |−17 out to Parallax 433MHz transmitter
      R3 −7−| B1    A1 |−18 out to LED
      R2 −8−| B2       |
      R1 −9−| B3       |
      C3 −13−| B7       |
      C2 −12−| B6       |
      C1 −11−| B5       |
               |          |
 10MHz XTAL−15−|  16F628  |
       XTAL−16−|          |
                
                     5
                     |
                    Gnd

          KEYBOARD ASSIGNMENTS
            C1      C2      C3
        +−+
    R1  |      (cable here)      |
        |                        |
    R2  |                        |
        |                        |
    R3  |                        |
        |                        |
    R4  |                        |
        +−+

***************************************************************************/

#include <16F628.h>
#include 

#fuses HS, NOPROTECT, PUT, BROWNOUT, NOMCLR, NOLVP, WDT, NOCPD

#use fast_io ( A )
#use fast_io ( B )
#use delay ( clock = 10MHZ, restart_wdt )
#use rs232 ( baud = 9600, xmit = PIN_A0 )

#byte PORT_A   = 5
#byte PORT_B   = 6
#bit  LED      = PORT_A.1
#bit  TX_PWR   = PORT_A.2

#define KEY_NONE       0
#define KEY_C1_R1      1
#define KEY_C1_R2      2
#define KEY_C1_R3      3
#define KEY_C1_R4      4
#define KEY_C2_R1      5
#define KEY_C2_R2      6
#define KEY_C2_R3      7
#define KEY_C2_R4      8
#define KEY_C3_R1      9
#define KEY_C3_R2      10
#define KEY_C3_R3      11
#define KEY_C3_R4      12

void SendMsg ( char cMsgCode );
char GetKey ( void );
void DelayMs ( int cCount );

void main ( void )
        {
        char cKey, cCnt, cX;

        set_tris_a ( 0b11111000 );          // A0, A1, A2 are outputs
        set_tris_b ( 0b00011111 );          // Columns are outputs, rows are inputs, RB4 is input (LVP)
        TX_PWR = OFF;
        setup_counters ( RTCC_INTERNAL, WDT_36MS );   // 256 * 4uS = 1.024mS timer wrap
        port_b_pullups ( TRUE );
        disable_interrupts ( GLOBAL );
        cCnt = 0;                         // preset LED flash

        for ( cX = 0; cX < 20; cX++ )       // 2 second power up flash
            {
            LED = HIGH;
            DelayMs ( 50 );
            LED=LOW;
            DelayMs ( 50 );
            }

        while ( TRUE )      // do forever
            {
            sleep();                   // stop here, wait for WDT every 36mS
            if ( cCnt++ >= 138 )       // flash LED once every 5 seconds @ 36mS WDT
                {
                LED = HIGH;
                DelayMs ( 10 );
                LED = LOW;
                cCnt = 0;
                }
            cKey = GetKey();
            if ( cKey != KEY_NONE )
                {
                switch ( cKey )
                    {
                    case KEY_C1_R1:
                        {
                        SendMsg ( KEY_C1_R1 );
                        break;
                        }
                    case KEY_C1_R2:
                        {
                        SendMsg ( KEY_C1_R2 );
                        break;
                        }
                    case KEY_C1_R3:
                        {
                        SendMsg ( KEY_C1_R3 );
                        break;
                        }
                    case KEY_C1_R4:
                        {
                        SendMsg ( KEY_C1_R4 );
                        break;
                        }
                    case KEY_C2_R1:
                        {
                        SendMsg ( KEY_C2_R1 );
                        break;
                        }
                    case KEY_C2_R2:
                        {
                        SendMsg ( KEY_C2_R2 );
                        break;
                        }
                    case KEY_C2_R3:
                        {
                        SendMsg ( KEY_C2_R3 );
                        break;
                        }
                    case KEY_C2_R4:
                        {
                        SendMsg ( KEY_C2_R4 );
                        break;
                        }
                    case KEY_C3_R1:
                        {
                        SendMsg ( KEY_C3_R1 );
                        break;
                        }
                    case KEY_C3_R2:
                        {
                        SendMsg ( KEY_C3_R2 );
                        break;
                        }
                    case KEY_C3_R3:
                        {
                        SendMsg ( KEY_C3_R3 );
                        break;
                        }
                    case KEY_C3_R4:
                        {
                        SendMsg ( KEY_C3_R4 );
                        break;
                        }
                    }
                }
            }
        }

GetKey ( void )
    {
    char cKey, cPortBIn;

    restart_wdt();
    cKey = KEY_NONE;                            // default is invalidated key
    PORT_B = 0b00011111;                        // make all three columns low
    delay_us ( 500 );                           // wait for row lines to settle (was 5mS, lowered to consume less avg pwr)
    if ( ( PORT_B & 0x0F ) != 0x0F )            // if any row line is low
        {
        DelayMs ( 5 );                         // debounce
        PORT_B = 0b01111111;                    // make C3 low
        delay_us ( 10 );                        // wait 10uS to settle
        cPortBIn = PORT_B;                      // get port B contents
        if ( ( cPortBIn & 0x0F ) == 0b00001110 )  // check rows
            {
            cKey = KEY_C3_R4;
            }
        if ( ( cPortBIn & 0x0F ) == 0b00001101 )
            {
            cKey = KEY_C3_R3;
            }
        if ( ( cPortBIn & 0x0F ) == 0b00001011 )
            {
            cKey = KEY_C3_R2;
            }
        if ( ( cPortBIn & 0x0F ) == 0b00000111 )
            {
            cKey = KEY_C3_R1;
            }
        PORT_B = 0b10111111;                    // make C2 low
        delay_us ( 10 );                        // wait 10uS to settle
        cPortBIn = PORT_B;                      // get port B contents
        if ( ( cPortBIn & 0x0F ) == 0b00001110 )  // check rows
            {
            cKey = KEY_C2_R4;
            }
        if ( ( cPortBIn & 0x0F ) == 0b00001101 )
            {
            cKey = KEY_C2_R3;
            }
        if ( ( cPortBIn & 0x0F ) == 0b00001011 )
            {
            cKey = KEY_C2_R2;
            }
        if ( ( cPortBIn & 0x0F ) == 0b00000111 )
            {
            cKey = KEY_C2_R1;
            }
        PORT_B = 0b11011111;                    // make C1 low
        delay_us ( 10 );                        // wait 10uS to settle
        cPortBIn = PORT_B;                      // get port B contents
        if ( ( cPortBIn & 0x0F ) == 0b00001110 )  // check rows
            {
            cKey = KEY_C1_R4;
            }
        if ( ( cPortBIn & 0x0F ) == 0b00001101 )
            {
            cKey = KEY_C1_R3;
            }
        if ( ( cPortBIn & 0x0F ) == 0b00001011 )
            {
            cKey = KEY_C1_R2;
            }
        if ( ( cPortBIn & 0x0F ) == 0b00000111 )
            {
            cKey = KEY_C1_R1;
            }
        DelayMs ( 5 );
        PORT_B = 0b00011111;                    // make all three columns low
        delay_us ( 10 );                        // wait 10uS to settle
        while ( ( PORT_B & 0x0F ) != 0x0F )     // wait until all rows are high (no keys pressed )
           {
           DelayMs ( 5 );
           }
        }
    PORT_B = 0b11111111;                       // make all three columns high
    return ( cKey );
    }

void SendMsg ( char cMsgCode )
   {
   TX_PWR = ON;
   LED = HIGH;
   DelayMs ( 10 );  // power on time for transmitter (at least 4mS)
   putc ( 0x00 );    // wake up the receiver
   putc ( 0x00 );    // wake up the receiver
   putc ( 0x00 );    // wake up the receiver
   putc ( 'J' );
   putc ( 'S' );
   putc ( 'F' );
   putc ( cMsgCode );
   putc ( 'J' + 'S' + 'F' + cMsgCode );   // checksum
   restart_wdt();
   LED = LOW;
   TX_PWR = OFF;
   }

void DelayMs ( int cCount )
    {
    int cX;

    for ( cX = 0; cX < cCount; cX++ )
        {
        delay_ms ( 1 );
        restart_wdt();
        }
    }

Receiver alıcı kodları:

/****************************************************************************

seatalk_wireless_remote_rx_1.c

USE AT YOUR OWN RISK!

This program is a remote control receiver for Raytheon's Autohelm ST4000 autopilot using the
Seatalk(tm) network protocol.  It also switches the Raytheon instrument lamps on
and off.

The following Seatalk protocol is extracted from Thomas Knauf's web site:
www.thomasknauf.de/seatalk.htm

Message protocol FROM wireless transmitter
* The command simply tells what key (row/col) was pressed.  Key−to−Seatalk associations are done in the receiver.
* Each 9600 baud message contains a command and checksum:
   0xff    // wake up the receiver
   0xff    // wake up the receiver
   0xff    // wake up the receiver
   'J'
   'S'
   'F'
   cMsgCode   // which key was pressed
   'J' + 'S' + 'F' + cMsgCode   // checksum

Message protocol TO Seatalk bus
* Each 4800 baud message contains between 3 and 18 characters:
* COMMAND byte (the only byte with the command−bit set)
  ATTRIBUTE byte, specifying the total length of the message in the least significant nibble:
      Most  significant 4 bits: 0 or part of a data value
      Least significant 4 bits: Number of additional bytes beyond the mandatory data byte
  DATA byte (mandatory, meaning than the smallest message is 3 bytes)
  DATA bytes (optional, up to 15 additional data bytes, meaning that longest messages is 18 bytes)

Serial Data Transmission
11 bits are transmitted for each byte:
  * 1  Start bit (0V)
  * 8  Data Bits (least significant bit transmitted first, bit ON = +12V)
  * 1  Command/Data bit (+12V if command byte, 0V if other)
  * 1  Stop bit (+12V)

Collision Management
Bus should be idle for at least 2mS (+12V for at least 10/4800 seconds).
Transmitter listens to it's own transmission and recognizes when its message
has been corrupted by a another talker. In this case it abandons the remaining
bytes in the message, waits for the bus to become free again, and then
retransmits the whole message after a delay.

LAMP INTENSITY CODES

30 00 00          Lamp off
30 00 0C          Lamp full on

KEYSTROKE CODES

86 11 01 FE     AUTO
86 11 02 FD     STANDBY
86 11 03 FC     TRACK
86 11 05 FA     −1
86 11 06 F9    −10
86 11 07 F8      +1
86 11 08 F7    +10
86 11 04 FB    DISP?

                 +5   +5
                  |    |
                  14   4
                
               | B0    A0 |−17 out to Seatalk (transistor driver)
               |       A1 |−18 in from Seatalk (transistor buffer)
               | B2    A2 |−1 LED
               | B3       |
               |       B1 |−7 input from Parallax 433MHz receiver
               | B5    B2 |−8 debug serial output
               | B6    B4 |−10 GND (LVP)
               |          |
  6MHz XTAL−15−|  16F628  |
       XTAL−16−|          |
                
                     5
                     |
                    Gnd

          KEYBOARD ASSIGNMENTS
            C1      C2      C3
        +−+
    R1  |  −1      Track    +1   |
        |                        |
    R2  |  −5      Auto     +5   |
        |                        |
    R3  |  −10    Standby   +10  |
        |                        |
    R4  |  Lamp      x     DISP  |
        +−+

***************************************************************************/

/* The following include should contain 16F84 or 16F628. */
#include <16F628.h>
#include 

#fuses HS, NOPROTECT, PUT, BROWNOUT, NOMCLR, NOLVP, NOCPD, NOWDT

#use fast_io ( A )
#use delay ( clock = 6000000 )
#use rs232 ( baud = 9600, rcv = PIN_B1, xmit = PIN_B2, ERRORS )

#byte PORT_A   = 5
#bit SEATALK_TX_OUT    = PORT_A.0
#bit SEATALK_RX_IN     = PORT_A.1
#bit LED               = PORT_A.2

#define LAMP_OFF       0x00
#define LAMP_ON        0x0C
#define PLUS_ONE       0x07
#define MINUS_ONE      0x05
#define PLUS_TEN       0x08
#define MINUS_TEN      0x06
#define STANDBY        0x02
#define AUTO           0x01
#define TRACK          0x03
#define DISP           0x04
#define KEY_NONE       0
#define KEY_C1_R1      1
#define KEY_C1_R2      2
#define KEY_C1_R3      3
#define KEY_C1_R4      4
#define KEY_C2_R1      5
#define KEY_C2_R2      6
#define KEY_C2_R3      7
#define KEY_C2_R4      8
#define KEY_C3_R1      9
#define KEY_C3_R2      10
#define KEY_C3_R3      11
#define KEY_C3_R4      12

void SendKeystrokeMsg ( char cData );
void SendLampMsg ( char cX );
char SendByte ( char cError, char cCommand, char cData );
char SendBit ( char cError, char cBit );
void CheckBus ( void );
char ParseMsg ( void );
char GetNextChar ( void );

static char cLampState, cKey, cBuffer [ 15 ], cWritePointer, cReadPointer;

void main ( void )
        {
        char cKey, cX;

        delay_ms ( 100 );                   // programming delay
        SEATALK_TX_OUT = LOW;               // allow output to float
        set_tris_a ( 0b11111010 );          // A0, A2 are outputs, A1 is input
        setup_counters ( RTCC_INTERNAL, WDT_18MS );   // 256 * 4uS = 1.024mS timer wrap
        port_b_pullups ( TRUE );
        cLampState = LAMP_OFF;              // preset toggle

        for ( cX = 0; cX < 10; cX++ )       // power−on flash LED
            {
            LED = HIGH;
            delay_ms ( 50 );
            LED=LOW;
            delay_ms ( 50 );
            }

        //printf ( "READY\n\r" );
        cWritePointer = 0;
        cReadPointer = 0;
        for ( cX = 0; cX < 15; cX++ )    // clear buffer
            {
            cBuffer [ cX ] = 0;
            }
        enable_interrupts ( INT_RDA );
        enable_interrupts ( GLOBAL );

    //while(1){SendBit ( NO, HIGH );SendBit ( NO, LOW );}

        while ( TRUE )      // do forever
            {
            cKey = ParseMsg();   // wait for valid message to come in
            switch ( cKey )
                {
                case KEY_C1_R1:
                    {
                    SendKeystrokeMsg ( MINUS_ONE );
                    break;
                    }
                case KEY_C1_R2:
                    {
                    SendKeystrokeMsg ( MINUS_ONE );
                    SendKeystrokeMsg ( MINUS_ONE );
                    SendKeystrokeMsg ( MINUS_ONE );
                    SendKeystrokeMsg ( MINUS_ONE );
                    SendKeystrokeMsg ( MINUS_ONE );
                    break;
                    }
                case KEY_C1_R3:
                    {
                    SendKeystrokeMsg ( MINUS_TEN );
                    break;
                    }
                case KEY_C1_R4:
                    {
                    if ( cLampState == LAMP_OFF )
                        {
                        cLampState = LAMP_ON;
                        }
                    else
                        {
                        cLampState = LAMP_OFF;
                        }
                    SendLampMsg ( cLampState );      // send DISP keystroke
                    break;
                    }
                case KEY_C2_R1:
                    {
                    SendKeystrokeMsg ( TRACK );
                    break;
                    }
                case KEY_C2_R2:
                    {
                    SendKeystrokeMsg ( AUTO );
                    break;
                    }
                case KEY_C2_R3:
                    {
                    SendKeystrokeMsg ( STANDBY );
                    break;
                    }
                case KEY_C2_R4:
                    {
                    // not assigned
                    break;
                    }
                case KEY_C3_R1:
                    {
                    SendKeystrokeMsg ( PLUS_ONE );
                    break;
                    }
                case KEY_C3_R2:
                    {
                    SendKeystrokeMsg ( PLUS_ONE );
                    SendKeystrokeMsg ( PLUS_ONE );
                    SendKeystrokeMsg ( PLUS_ONE );
                    SendKeystrokeMsg ( PLUS_ONE );
                    SendKeystrokeMsg ( PLUS_ONE );
                    break;
                    }
                case KEY_C3_R3:
                    {
                    SendKeystrokeMsg ( PLUS_TEN );
                    break;
                    }
                case KEY_C3_R4:
                    {
                    SendKeystrokeMsg ( DISP );
                    break;
                    }
                }
            delay_ms ( 50 );
            }
        }

void SendKeystrokeMsg ( char cData )
    {
    char cError;

    do {
        disable_interrupts ( INT_RDA );             // turn off interrupt to avoid jitter in bit time
        CheckBus();                                 // wait for bus to be idle
        LED = HIGH;                                 // LED on during message
        cError = SendByte ( NO, YES, 0x86 );        // command: keystroke
        cError = SendByte ( cError, NO, 0x11 );     // data: remote control, 1 extra byte (4 total)
        cError = SendByte ( cError, NO, cData );    // data: PlusOne key
        cError = SendByte ( cError, NO,~cData );    // data: inverted data
        enable_interrupts ( INT_RDA );              // turn interrupt back on
        delay_ms ( 10 );                            // LED visible delay
        LED = LOW;                                  // LED off
        } while ( cError == YES );                  // repeat if message was corrupted
    }

void SendLampMsg ( char cX )
    {
    char cError;

    do {
        disable_interrupts ( INT_RDA );             // turn off interrupt to avoid jitter in bit time
        CheckBus();    // wait for bus to be idle
        LED = HIGH;
        cError = LOW;                               // default no error
        cError = SendByte ( NO, YES, 0x30 );        // command: lamp
        cError = SendByte ( cError, NO, 0x00 );     // data: 00
        cError = SendByte ( cError, NO, cLampState );   // data: lamp state
        enable_interrupts ( INT_RDA );              // turn interrupt back on
        delay_ms ( 10 );                            // LED visible delay
        LED = LOW;                                  // LED off
        } while ( cError == YES );                  // repeat if message was corrupted
    }

char SendByte ( char cError, char cCommand, char cData )
    {
    char cX;
    if ( cError != YES )                // if no error from previous
        {
        cError = SendBit ( cError, HIGH );           // start bit (0V)
        for ( cX = 0; cX < 8; cX++ )
            {
            cError = SendBit ( cError, ~cData & 0x01 );  // LSB data bit
            cData >>= 1;                 // shift right
            }
        cError = SendBit ( cError, cCommand ? LOW : HIGH );    // set if command byte, clear if data byte
        cError = SendBit ( cError, LOW );           // stop bit (+12V)
        }
    return ( cError );
    }

char SendBit ( char cError, char cBit )
    {
    char cX;
    // this is bit−banged code, it must be adjusted to give 208uS bit times (4800 baud)

    if ( cError != YES )                // if no error from previous
        {
        SEATALK_TX_OUT = cBit;         // send bit to output
        for ( cX = 0; cX < 7; cX++ )   // check output bit periodically
            {
            delay_us ( 12 );        // 12 adjust
            if ( SEATALK_RX_IN == !cBit )  // check if output bit is corrupted by another talker
                {
                return ( HIGH );        // return collision error
                }
            }
        return ( LOW );                 // return no error, bit sucessfully sent
        }
    else
        {
        return ( HIGH );        // simply return collision error from before
        }
    }

void CheckBus ( void )
    {
    char cX;

    for ( cX = 0; cX < 255; cX++ )  // assumes output is floating to +12V for ~5mS
        {
        if ( SEATALK_RX_IN == HIGH )  // check if output bit is corrupted by another talker
            {
            cX = 0;                 // reset count to zero
            }
        delay_us ( 7 );
        }
    }

#int_rda
void int_handler ()
    {
    if ( kbhit() )
        {
        cBuffer [ cWritePointer ] = getch();
        cWritePointer++;
        if ( cWritePointer >= 15 )
            {
            cWritePointer = 0;
            }
        }
    }

char GetNextChar ( void )
    {
    char cX;

    while ( cWritePointer == cReadPointer );    // wait for character to come in via interrupt
    cX = cBuffer [ cReadPointer ];
    cReadPointer++;
    if ( cReadPointer >= 15 )
        {
        cReadPointer = 0;
        }
    //printf ( "     %c\n\r", cX );
    return ( cX );
    }

char ParseMsg ( void )
    {
    char cCmd, cChk, cKey;

    while ( TRUE )
        {
        while ( TRUE )
            {
            cKey = GetNextChar();
            if ( cKey != 'J' )
                {
                break;
                }
            cKey = GetNextChar();
            if ( cKey != 'S' )
                {
                break;
                }
            cKey = GetNextChar();
            if ( cKey != 'F' )
                {
                break;
                }
            cCmd = GetNextChar();        // command
            cChk = GetNextChar();        // checksum
            if ( ( 'J' + 'S' + 'F' + cCmd ) == cChk )
                {
                return ( cCmd );   //done
                }
            }
        }
    }

CEVAP VER

Lütfen yorumunuzu giriniz!
Lütfen isminizi buraya giriniz