PIC ile PLC ModBus RTU Haberleşme

emaxx

Üye
Katılım
8 Mar 2010
Mesajlar
10
Puanları
1
Yaş
39
Merhaba,

Fırat Bey'in kütüphanesi olan PetitModbus kullanarak pic ile plc'yi haberleştirmeye çalıştım.

Öncesinde devreyi isis'te çizip modbus poll ve modbus tester programları ile test ettim. Modbus poll ile hem veri gönderip hem de veri okuyabildim. Bu simülasyonda tam istediğim gibi çalıştı. Fakat modbus tester'da işler biraz ters gitti. İlgili adrese data gönderebiliyorum fakat adresteki datayı okuyamıyorum. Programda "Read Status: Illegal Response" diye bir uyarı çıkıyor. Modbus poll'da bu sorunu yaşamadım.

Gelelim PLC tarafına;
Fatek plc ile pic'i max485 ile bağladım. PLC'den veri göndermek için DE ve RE pinlerini 0'a çekiyorum ve ilgili adrese data gönderebiliyorum. Görsel olarak Ledlerimi yakabiliyorum ama DE ve RE pinlerini 1'e çekip pic üzerindeki bilgiyi okumaya çalıştığımda hiçbir hareketlilik yok.

Örneğin:
Pic slave adresim 1
Kullandığım reg 0
Plc'den 400001. adrese yazma işlemiyle 1 değerini girdiğimde ilgili ledim yanıyor.

Yine pic slave adresim 1
Kullandığım reg 1
Pic'de o adresimde 1 değeri mevcut. Plc'den 400002. adrese okuma işlemini seçtiğimde bilgi gelmiyor.

Kod:
ProcessPetitModbus();

// PLC'DEN GÖNDERDİĞİM BİLGİYLE BU PORTLARI AKTİF EDEBİLİYORUM
output_bit(B0,bit_test(PetitRegisters[0].ActValue,0));
output_bit(B1,bit_test(PetitRegisters[0].ActValue,1));
output_bit(B2,bit_test(PetitRegisters[0].ActValue,2));
output_bit(B3,bit_test(PetitRegisters[0].ActValue,3));
output_bit(B4,bit_test(PetitRegisters[0].ActValue,4));
output_bit(B5,bit_test(PetitRegisters[0].ActValue,5));
output_bit(B6,bit_test(PetitRegisters[0].ActValue,6));
output_bit(B7,bit_test(PetitRegisters[0].ActValue,7));

// PIC ÜZERİNDEKİ BU BİLGİYİ PLC'DEN GÖREMİYORUM
PetitRegisters[1].ActValue = 1;

Sorunum kodlarımda mı sizce yoksa plc tarafında mı?
Simülasyonda da birinde tam çalışırken diğerinde hataya düşüyor.

Yardımlarınızı bekliyorum teşekkürler.



Düzenleme:

Kod:
#include "PetitModbusCcs.h"
#include "PetitModbusPortCcs.h"

/*******************************ModBus Functions*******************************/
#define PETITMODBUS_READ_COILS                  1
#define PETITMODBUS_READ_DISCRETE_INPUTS        2
#define PETITMODBUS_READ_HOLDING_REGISTERS      3
#define PETITMODBUS_READ_INPUT_REGISTERS        4
#define PETITMODBUS_WRITE_SINGLE_COIL           5
#define PETITMODBUS_WRITE_SINGLE_REGISTER       6
#define PETITMODBUS_WRITE_MULTIPLE_COILS        15
#define PETITMODBUS_WRITE_MULTIPLE_REGISTERS    16
/****************************End of ModBus Functions***************************/

#define PETIT_FALSE_FUNCTION                    0
#define PETIT_FALSE_SLAVE_ADDRESS               1
#define PETIT_DATA_NOT_READY                    2
#define PETIT_DATA_READY                        3

#define PETIT_ERROR_CODE_01                     0x01                            // Function code is not supported
#define PETIT_ERROR_CODE_02                     0x02                            // Register address is not allowed or write-protected
#define PETIT_ERROR_CODE_03                     0x03                            // Some data values are out of range, invalid number of register

unsigned int8 PETITMODBUS_SLAVE_ADDRESS         =1;

typedef enum
{
    PETIT_RXTX_IDLE,
    PETIT_RXTX_START,
    PETIT_RXTX_DATABUF,
    PETIT_RXTX_WAIT_ANSWER,
    PETIT_RXTX_TIMEOUT
}PETIT_RXTX_STATE;

typedef struct
{
  unsigned int8     Address;
  unsigned int8     Function;
  unsigned int8     DataBuf[PETITMODBUS_RXTX_BUFFER_SIZE];
  unsigned int16    DataLen;
}PETIT_RXTX_DATA;

/**********************Slave Transmit and Receive Variables********************/
PETIT_RXTX_DATA     Petit_Tx_Data;
unsigned int16      Petit_Tx_Current              = 0;
unsigned int16      Petit_Tx_CRC16                = 0xFFFF;
PETIT_RXTX_STATE    Petit_Tx_State                = PETIT_RXTX_IDLE;
unsigned int8       Petit_Tx_Buf[PETITMODBUS_TRANSMIT_BUFFER_SIZE];
unsigned int16      Petit_Tx_Buf_Size             = 0;

PETIT_RXTX_DATA     Petit_Rx_Data;
unsigned int16      Petit_Rx_CRC16                = 0xFFFF;
PETIT_RXTX_STATE    Petit_Rx_State                = PETIT_RXTX_IDLE;
unsigned int8       Petit_Rx_Data_Available       = FALSE;

unsigned int16 PetitModbusTimerValue         = 0;





//volatile unsigned int16 PetitModbusTimerValue         = 0;
/****************End of Slave Transmit and Receive Variables*******************/

/*
 * Function Name        : CRC16
 * @param[in]           : Data  - Data to Calculate CRC
 * @param[in/out]       : CRC   - Anlik CRC degeri
 * @How to use          : First initial data has to be 0xFFFF.
 */
void Petit_CRC16(unsigned int8 Data, unsigned int16* CRC)
{
    unsigned int8 i;

    *CRC = *CRC ^(unsigned int8) Data;
    for (i = 8; i > 0; i--)
    {
        if (*CRC & 0x0001)
            *CRC = (*CRC >> 1) ^ 0xA001;
        else
            *CRC >>= 1;
    }
}

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

/*
 * Function Name        : DoTx
 * @param[out]          : TRUE
 * @How to use          : It is used for send data package over physical layer
 */
unsigned int8 Petit_DoSlaveTX(void){ 
    
    PetitModBus_UART_String(Petit_Tx_Buf,Petit_Tx_Buf_Size);

    Petit_Tx_Buf_Size = 0;   
  
    return TRUE;
}

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

/*
 * Function Name        : SendMessage
 * @param[out]          : TRUE/FALSE
 * @How to use          : This function start to sending messages
 */
unsigned int8 PetitSendMessage(void)
{   
    if (Petit_Tx_State != PETIT_RXTX_IDLE)
        return FALSE;

    Petit_Tx_Current  =0;
    Petit_Tx_State    =PETIT_RXTX_START;   
    
    return TRUE;
}

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

/*
 * Function Name        : HandleModbusError
 * @How to use          : This function generated errors to Modbus Master
 */
void HandlePetitModbusError(unsigned int8 ErrorCode)
{
    // Initialise the output buffer. The first byte in the buffer says how many registers we have read   
    
    Petit_Tx_Data.Function    = ErrorCode | 0x80;
    Petit_Tx_Data.Address     = PETITMODBUS_SLAVE_ADDRESS;
    Petit_Tx_Data.DataLen     = 0;
    PetitSendMessage();
    
}

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

/*
 * Function Name        : HandleModbusReadHoldingRegisters
 * @How to use          : Modbus function 03 - Read holding registers
 */
#if PETITMODBUS_READ_HOLDING_REGISTERS_ENABLED > 0
void HandlePetitModbusReadHoldingRegisters(void)
{
    // Holding registers are effectively numerical outputs that can be written to by the host.
    // They can be control registers or analogue outputs.
    // We potientially have one - the pwm output value
    unsigned int16    Petit_StartAddress        = 0;
    unsigned int16    Petit_NumberOfRegisters   = 0;
    unsigned int16    Petit_i                   = 0;

    // The message contains the requested start address and number of registers
    Petit_StartAddress        = ((unsigned int16) (Petit_Rx_Data.DataBuf[0]) << 8) + (unsigned int16) (Petit_Rx_Data.DataBuf[1]);
    Petit_NumberOfRegisters   = ((unsigned int16) (Petit_Rx_Data.DataBuf[2]) << 8) + (unsigned int16) (Petit_Rx_Data.DataBuf[3]);
    
    
    // If it is bigger than RegisterNumber return error to Modbus Master
    if((Petit_StartAddress+Petit_NumberOfRegisters)>NUMBER_OF_OUTPUT_PETITREGISTERS)
        HandlePetitModbusError(PETIT_ERROR_CODE_02);
    else
    {
        // Initialise the output buffer. The first byte in the buffer says how many registers we have read
        Petit_Tx_Data.Function    = PETITMODBUS_READ_HOLDING_REGISTERS;
        Petit_Tx_Data.Address     = PETITMODBUS_SLAVE_ADDRESS;
        Petit_Tx_Data.DataLen     = 1;
        Petit_Tx_Data.DataBuf[0]  = 0;

        for (Petit_i = 0; Petit_i < Petit_NumberOfRegisters; Petit_i++)
        {
            unsigned int16 Petit_CurrentData = PetitRegisters[Petit_StartAddress+Petit_i].ActValue;

            Petit_Tx_Data.DataBuf[Petit_Tx_Data.DataLen]        = (unsigned int8) ((Petit_CurrentData & 0xFF00) >> 8);
            Petit_Tx_Data.DataBuf[Petit_Tx_Data.DataLen + 1]    = (unsigned int8) (Petit_CurrentData & 0xFF);
            Petit_Tx_Data.DataLen                        += 2;
            Petit_Tx_Data.DataBuf[0]                      = Petit_Tx_Data.DataLen - 1;
        }

        PetitSendMessage();
    }
}
#endif

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

/*
 * Function Name        : HandleModbusReadInputRegisters
 * @How to use          : Modbus function 06 - Write single register
 */
#if PETITMODBUSWRITE_SINGLE_REGISTER_ENABLED > 0
void HandlePetitModbusWriteSingleRegister(void)
{
    // Write single numerical output
    unsigned int16    Petit_Address   = 0;
    unsigned int16    Petit_Value     = 0;
    unsigned int8   Petit_i         = 0;

    // The message contains the requested start address and number of registers
    Petit_Address   = ((unsigned int16) (Petit_Rx_Data.DataBuf[0]) << 8) + (unsigned int16) (Petit_Rx_Data.DataBuf[1]);
    Petit_Value     = ((unsigned int16) (Petit_Rx_Data.DataBuf[2]) << 8) + (unsigned int16) (Petit_Rx_Data.DataBuf[3]);

    // Initialise the output buffer. The first byte in the buffer says how many registers we have read
    Petit_Tx_Data.Function    = PETITMODBUS_WRITE_SINGLE_REGISTER;
    Petit_Tx_Data.Address     = PETITMODBUS_SLAVE_ADDRESS;
    Petit_Tx_Data.DataLen     = 4;

    if(Petit_Address>=NUMBER_OF_OUTPUT_PETITREGISTERS)
        HandlePetitModbusError(PETIT_ERROR_CODE_03);
    else
    {
        PetitRegisters[Petit_Address].ActValue=Petit_Value;
        // Output data buffer is exact copy of input buffer
        for (Petit_i = 0; Petit_i < 4; ++Petit_i)
            Petit_Tx_Data.DataBuf[Petit_i] = Petit_Rx_Data.DataBuf[Petit_i];
    }

    PetitSendMessage();
}
#endif

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

/*
 * Function Name        : HandleModbusWriteMultipleRegisters
 * @How to use          : Modbus function 16 - Write multiple registers
 */
#if PETITMODBUS_WRITE_MULTIPLE_REGISTERS_ENABLED > 0
void HandleMPetitodbusWriteMultipleRegisters(void)
{
    // Write single numerical output
    unsigned int16   Petit_StartAddress            =0;
    unsigned int8    Petit_ByteCount               =0;
    unsigned int16   Petit_NumberOfRegisters       =0;
    unsigned int8    Petit_i                       =0;
    unsigned int16   Petit_Value                   =0;

    // The message contains the requested start address and number of registers
    Petit_StartAddress        = ((unsigned int16) (Petit_Rx_Data.DataBuf[0]) << 8) + (unsigned int16) (Petit_Rx_Data.DataBuf[1]);
    Petit_NumberOfRegisters   = ((unsigned int16) (Petit_Rx_Data.DataBuf[2]) << 8) + (unsigned int16) (Petit_Rx_Data.DataBuf[3]);
    Petit_ByteCount           = Petit_Rx_Data.DataBuf[4];

    // If it is bigger than RegisterNumber return error to Modbus Master
    if((Petit_StartAddress+Petit_NumberOfRegisters)>NUMBER_OF_OUTPUT_PETITREGISTERS)
        HandlePetitModbusError(PETIT_ERROR_CODE_03);
    else
    {
        // Initialise the output buffer. The first byte in the buffer says how many outputs we have set
        Petit_Tx_Data.Function    = PETITMODBUS_WRITE_MULTIPLE_REGISTERS;
        Petit_Tx_Data.Address     = PETITMODBUS_SLAVE_ADDRESS;
        Petit_Tx_Data.DataLen     = 4;
        Petit_Tx_Data.DataBuf[0]  = Petit_Rx_Data.DataBuf[0];
        Petit_Tx_Data.DataBuf[1]  = Petit_Rx_Data.DataBuf[1];
        Petit_Tx_Data.DataBuf[2]  = Petit_Rx_Data.DataBuf[2];
        Petit_Tx_Data.DataBuf[3]  = Petit_Rx_Data.DataBuf[3];

        // Output data buffer is exact copy of input buffer
        for (Petit_i = 0; Petit_i <Petit_NumberOfRegisters; Petit_i++)
        {
            Petit_Value=(Petit_Rx_Data.DataBuf[5+2*Petit_i]<<8)+(Petit_Rx_Data.DataBuf[6+2*Petit_i]);
            PetitRegisters[Petit_StartAddress+Petit_i].ActValue=Petit_Value;
        }

        PetitSendMessage();
    }
}
#endif

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

/*
 * Function Name        : RxDataAvailable
 * @return              : If Data is Ready, Return TRUE
 *                        If Data is not Ready, Return FALSE
 */
unsigned int8 Petit_RxDataAvailable(void)
{
    unsigned int8 Result    = Petit_Rx_Data_Available;
    
    Petit_Rx_Data_Available       = FALSE;

    return Result;
}

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

/*
 * Function Name        : CheckRxTimeout
 * @return              : If Time is out return TRUE
 *                        If Time is not out return FALSE
 */
unsigned int8 Petit_CheckRxTimeout(void)
{
    // A return value of true indicates there is a timeout   
    if (PetitModbusTimerValue>= PETITMODBUS_TIMEOUTTIMER)
    {
        PetitModbusTimerValue   =0;
        PetitReceiveCounter     =0;
        return TRUE;
    }

    return FALSE;
}

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

/*
 * Function Name        : CheckBufferComplete
 * @return              : If data is ready, return              DATA_READY
 *                        If slave address is wrong, return     FALSE_SLAVE_ADDRESS
 *                        If data is not ready, return          DATA_NOT_READY
 *                        If functions is wrong, return         FALSE_FUNCTION
 */
unsigned int8 CheckPetitModbusBufferComplete(void)
{
    int16 PetitExpectedReceiveCount=0;

    if(PetitReceiveCounter>4)
    {
        if(PetitReceiveBuffer[0]==PETITMODBUS_SLAVE_ADDRESS)
        {
            if(PetitReceiveBuffer[1]==0x01 || PetitReceiveBuffer[1]==0x02 || PetitReceiveBuffer[1]==0x03 || PetitReceiveBuffer[1]==0x04 || PetitReceiveBuffer[1]==0x05 || PetitReceiveBuffer[1]==0x06)  // RHR
            {
                PetitExpectedReceiveCount    =8;
            }
            else if(PetitReceiveBuffer[1]==0x0F || PetitReceiveBuffer[1]==0x10)
            {
                PetitExpectedReceiveCount=PetitReceiveBuffer[6]+9;
            }
            else
            {
                PetitReceiveCounter=0;
                return PETIT_FALSE_FUNCTION;
            }
        }
        else
        {
            PetitReceiveCounter=0;
            return PETIT_FALSE_SLAVE_ADDRESS;
        }
    }
    else
        return PETIT_DATA_NOT_READY;

    if(PetitReceiveCounter==PetitExpectedReceiveCount)
    {
        return PETIT_DATA_READY;
    }

    return PETIT_DATA_NOT_READY;
}

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

/*
 * Function Name        : RxRTU
 * @How to use          : Check for data ready, if it is good return answer
 */
void Petit_RxRTU(void)
{
    unsigned int8   Petit_i;
    unsigned int8   Petit_ReceiveBufferControl=0;

    Petit_ReceiveBufferControl    =CheckPetitModbusBufferComplete();

    if(Petit_ReceiveBufferControl==PETIT_DATA_READY)
    {
        Petit_Rx_Data.Address               =PetitReceiveBuffer[0];
        Petit_Rx_CRC16                      = 0xffff;
        Petit_CRC16(Petit_Rx_Data.Address, &Petit_Rx_CRC16);
        Petit_Rx_Data.Function              =PetitReceiveBuffer[1];
        Petit_CRC16(Petit_Rx_Data.Function, &Petit_Rx_CRC16);

        Petit_Rx_Data.DataLen=0;

        for(Petit_i=2;Petit_i<PetitReceiveCounter;Petit_i++)
            Petit_Rx_Data.DataBuf[Petit_Rx_Data.DataLen++]=PetitReceiveBuffer[Petit_i];

        Petit_Rx_State =PETIT_RXTX_DATABUF;

        PetitReceiveCounter=0;
    }

    Petit_CheckRxTimeout();

    if ((Petit_Rx_State == PETIT_RXTX_DATABUF) && (Petit_Rx_Data.DataLen >= 2))
    {
        // Finish off our CRC check
        Petit_Rx_Data.DataLen -= 2;
        for (Petit_i = 0; Petit_i < Petit_Rx_Data.DataLen; ++Petit_i)
        {
            Petit_CRC16(Petit_Rx_Data.DataBuf[Petit_i], &Petit_Rx_CRC16);
        }
        
        if (((unsigned int16) Petit_Rx_Data.DataBuf[Petit_Rx_Data.DataLen] + ((unsigned int16) Petit_Rx_Data.DataBuf[Petit_Rx_Data.DataLen + 1] << 8)) == Petit_Rx_CRC16)
        {
            // Valid message!
            Petit_Rx_Data_Available = TRUE;
        }

        Petit_Rx_State = PETIT_RXTX_IDLE;
    }
}

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

/*
 * Function Name        : TxRTU
 * @How to use          : If it is ready send answers!
 */
void Petit_TxRTU(void)
{
    Petit_Tx_CRC16                =0xFFFF;
    Petit_Tx_Buf_Size             =0;
    Petit_Tx_Buf[Petit_Tx_Buf_Size++]   =Petit_Tx_Data.Address;
    Petit_CRC16(Petit_Tx_Data.Address, &Petit_Tx_CRC16);
    Petit_Tx_Buf[Petit_Tx_Buf_Size++]   =Petit_Tx_Data.Function;
    Petit_CRC16(Petit_Tx_Data.Function, &Petit_Tx_CRC16);

    for(Petit_Tx_Current=0; Petit_Tx_Current < Petit_Tx_Data.DataLen; Petit_Tx_Current++)
    {
        Petit_Tx_Buf[Petit_Tx_Buf_Size++]=Petit_Tx_Data.DataBuf[Petit_Tx_Current];
        Petit_CRC16(Petit_Tx_Data.DataBuf[Petit_Tx_Current], &Petit_Tx_CRC16);
    }
    
    Petit_Tx_Buf[Petit_Tx_Buf_Size++] = Petit_Tx_CRC16 & 0x00FF;
    Petit_Tx_Buf[Petit_Tx_Buf_Size++] =(Petit_Tx_CRC16 & 0xFF00) >> 8;

    Petit_DoSlaveTX();

    Petit_Tx_State    =PETIT_RXTX_IDLE;
}

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

/*
 * Function Name        : ProcessModbus
 * @How to use          : ModBus main core! Call this function into main!
 */
void ProcessPetitModbus(void)
{
    if (Petit_Tx_State != PETIT_RXTX_IDLE)                                      // If answer is ready, send it!
        Petit_TxRTU();

    Petit_RxRTU();                                                              // Call this function every cycle

    if (Petit_RxDataAvailable())                                                // If data is ready enter this!
    {
        if (Petit_Rx_Data.Address == PETITMODBUS_SLAVE_ADDRESS)                 // Is Data for us?
        {
            switch (Petit_Rx_Data.Function)                                     // Data is for us but which function?
            {
                #if PETITMODBUS_READ_HOLDING_REGISTERS_ENABLED > 0
                case PETITMODBUS_READ_HOLDING_REGISTERS:    {   HandlePetitModbusReadHoldingRegisters();        break;  }
                #endif
                #if PETITMODBUSWRITE_SINGLE_REGISTER_ENABLED > 0
                case PETITMODBUS_WRITE_SINGLE_REGISTER:     {   HandlePetitModbusWriteSingleRegister();         break;  }
                #endif
                #if PETITMODBUS_WRITE_MULTIPLE_REGISTERS_ENABLED > 0
                case PETITMODBUS_WRITE_MULTIPLE_REGISTERS:  {   HandleMPetitodbusWriteMultipleRegisters();      break;  }
                #endif
                default:                                    {   HandlePetitModbusError(PETIT_ERROR_CODE_01);    break;  }
            }
        }
    }
}

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

/*
 * Function Name        : InitPetitModbus
 * @How to use          : Petite ModBus slave initialize
 */
void InitPetitModbus(unsigned int8 PetitModbusSlaveAddress)
{
    PETITMODBUS_SLAVE_ADDRESS    =PetitModbusSlaveAddress;
    
    PetitModBus_UART_Initialise();
    PetitModBus_TIMER_Initialise();
}

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

Bu kısımda modbus ayarlarıyla ilgili kısım. Okuma ve yazma işlemlerinin olduğu program.
 

Ekli dosyalar

  • sim.png
    159.8 KB · Görüntüleme: 99
  • sim2.png
    163.8 KB · Görüntüleme: 90
Son düzenleme:
Pici ancak slave olarak kullanabilirsin. Petit modbus kütüphanesi slave için yazılmış. Master tarafını ücretli satıyor dye biliyorum.
 
Pici ancak slave olarak kullanabilirsin. Petit modbus kütüphanesi slave için yazılmış. Master tarafını ücretli satıyor dye biliyorum.

Slave olarak kullandığımda PLC'den pic'in registerlarını okuma işlemi yapamıyor muyum?
03 - 06 - 16 modbus fonksiyonlarını içeriyordu kütüphane. Okuma - Tekli ve çoklu yazma işlemleri değil mi bunlar? Tekli ve çoklu yazıyorum. Okumayı yapamıyor muyuz slave olunca?

Modbus poll üzerinden picteki veriyi okuyabiliyordum.
 
Bence başka bir hata yapıyorsunuz,birini master digerini slave yaptıgınızda her halukarda master tarafı slave tarafına data yazabilir veya icerisinde ne bilgi var diye sorgulayabilmesi gerekir.Ben modbus i plc ile hiç kullanmadım fakat hmi ile habelestirmistim,orda bir registere hagi kodla yazma hangi kodla okuma yapılacagı yazıyordu.
Pic in içindeki datayı okumak için,pic i slave,PLC yi master yaptıgınızdan emin olun,bu sekilde yaptıgınızda PLC surekli olarak pic deki veriyi cekmek için sorgulama datası gönderecek.simulatorde Break point kullanarak gelen datanın ne oldugunu ve ardından ne işlemler yaptıgını takip edin.hatayı bu sekilde bulabilirsiniz.
12:15:08.721 [ID: 00026] INIT: Read Coils (code $01)
12:15:08.721 [-------->] SEND: 01 01 00 00 00 08 3D CC
12:15:08.908 [<--------] RECV: 01 01 01 37 10 5E
12:15:08.908 [ID: 00026] DONE: Read Coils (code $01)
12:15:08.924 [ID: 00026] PASS: Normal response
12:15:08.940 8 coils were processed.
12:15:08.940 Coil 0 is ON.
12:15:08.955 Coil 1 is ON.
12:15:08.955 Coil 2 is ON.
12:15:08.971 Coil 3 is OFF.
12:15:08.971 Coil 4 is ON.
12:15:08.986 Coil 5 is ON.
12:15:08.986 Coil 6 is OFF.
12:15:09.002 Coil 7 is OFF.

12:16:09.936 [ID: 00027] INIT: Write Multiple Coils (code $0F)
12:16:09.936 [-------->] SEND: 01 0F 00 00 00 04 01 0F 7E 92
12:16:10.123 [<--------] RECV: 01 8F 01 85 F0

12:19:43.543 [ID: 00043] INIT: Read Holding Registers (code $03)
12:19:43.559 [-------->] SEND: 01 03 00 00 00 01 84 0A
12:19:43.730 [<--------] RECV: 01 03 02 00 00 B8 44

12:19:49.065 [ID: 00044] INIT: Write Single Register (code $06)
12:19:49.065 [-------->] SEND: 01 06 00 00 00 00 89 CA
12:19:49.253 [<--------] RECV: 01 86 01 83 A0
 
Modbus tester'da Length : 100 ayarını 1'e çektim simülasyonda çalıştı. Yalnızca bir adres okuması yapacağım için o kısımda hata alıyormuşum. Şuan her iki simülasyonda da sorunum yok.

TX ve RX durumlarına baktığımda iki simülasyonda da aynı sonucu görüyorum.

01 03 00 00 00 01 84 0A
01 03 02 00 01 79 84

Slave numarası 1 olan picin 0.reg'ine 1 bilgisi kaydettim.
Simülasyonda 400001. adreste 1 bilgisini gördüm.
PLC'de 400001. adrese bu bilgi gelmiyor.


Fakat plc kısmında hala yazdırma yapabiliyorum ama okutma yaptıramıyorum. Fatek plc'de okuma işlemi için yaptırdığım durum ekran görüntüsü ektedir. Bu tarafta mı bir şeyleri yanlış yapıyorum acaba?

Ya da max485 modülü kullanıyorum. Yazarken DE RE pinlerini 0V'a bağlıyorum yazıyor.
Okuma yapmak için DE RE pinlerini 5V'a bağlıyorum ama plc'de bir şey göremiyorum. Bu kısımda mı sıkıntı var? Yardımlarınızı bekliyorum teşekkürler.
 

Ekli dosyalar

  • 1.png
    59 KB · Görüntüleme: 74
Haberleşme Fonksiyon Kodu
( H2, H3, H4, H5, H6, H0F, H10, H17)

H2 = Bir veya birden fazla bit adres okumak için kullanılır.

H3 = Bir veya birden fazla data (Word Adres) okumak için kullanılır.

H4 = Bir veya birden fazla input register okumak için

H5 = Tek bir bit adres yazmak için kullanılır.

H6 = Tek bir data (Word Adres) yazmak için kullanılır.

HF = Bir veya birden fazla bit adres yazmak için kullanılır.

H10 = Bir veya birden fazla data (Word Adres) yazmak için kullanılır.

H17 = Aynı komutla Word data okuma ve yazmak için kullanılır

Kaynak:
http://destek.delta-turkey.com/viewtopic.php?t=348
 
Merhaba, bilgi için teşekkür ederim. Kullandığım PLC Fatek marka.
Okuma yapmak için bir sıcaklık kontrol cihazı bağladım ve cihazın adres bilgisini girip RS485 ile üzerinde ki değeri okuyabiliyorum. Bu konuda da sorunum yok.

MAX485 modülünde sorun olduğunu düşünüyorum. Başka MAX485 modülleri de denedim sorunum devam ediyor. RE ve DE pinlerini 0V'a aldığımda bilgi yazıyorum ama 5V'a aldığımda picteki bilgiyi okuyamıyorum bir türlü

RE ve DE uçlarıyla ilgili mi bir sıkıntı var acaba? Pic'i rs232 ile bilgisayara bağlayıp simülasyondan deniyorum gayet iyi çalışıyor. Hem bilgi yazıyorum hem bilgi okuyabiliyorum. Tek fark rs485 modülünü takıp plc'ye bağladığımda sadece pic'e veri yazabiliyorum okuyamıyorum.
 
Son durum nedir çalıştı mı?
 
Son durum nedir çalıştı mı?
Çalıştı hocam. Sorun MAX485 devresinden kaynaklı. RE ve DE pinlerini rs232 ayarlarında Enable=PIN_C5 olarak yazıp otomatik kontrol etmeye çalışıyordum ama işe yaramadı bir türlü. Picler arası max485 ile haberleşirken işe yarıyordu ama plc ile bağlantıda bu işe yaramadı. Otomatik RE-DE ayarlayıcılı kart ile aşılabiliyor durum.
 
hocam merhaba bende delta plc ile uygulama yapacağım otomatik re-de aayarlayıcı kart ile ilgili bilgi verebilirmisin.
 
Bu siteyi kullanmak için çerezler gereklidir. Siteyi kullanmaya devam etmek için onları kabul etmelisiniz. Daha fazla bilgi edin…