[?]: Move DB data from one to other in SCL

SIMATIC S7-200/300/400, Step7, PCS7, CFC, SFC, PDM, PLCSIM,
SCL, Graph, SPS-VISU S5/S7, IBHsoftec, LOGO ...
cabrca
Posts: 7
Joined: Thu Jul 01, 2010 6:01 am

[?]: Move DB data from one to other in SCL

Post by cabrca »

Hi all,

In PCS7 project I need to move indexed db data from one to other, but with different lenght....
For example I will need to define a start address like db10.dbx2.5 and a bit lenght like 30 (...so it will last 'till db10.dbx6.2) to a destination address like db20.dbw4 with the same lenght.

What I would like to have on my scl code is as Input parameters the "dbnn.dbxn.n" and "bit lenght" and the destination "dbnn.dbwnn" as output.

Anyone can give me a clue how to make it... or maybe someone have a code that makes it ??

Best regards,
dehell
Posts: 104
Joined: Sat Jun 13, 2009 12:25 pm
Location: Europe

Re: [?]: Move DB data from one to other in SCL

Post by dehell »

Hi,
Search for SFC20 BLKMOV in Siemens Step7 help.
An other solution : use google and search for oscat.de : you could find a SCL block library for free.
Best regards.
cabrca
Posts: 7
Joined: Thu Jul 01, 2010 6:01 am

Re: [?]: Move DB data from one to other in SCL

Post by cabrca »

dehell wrote:Hi,
Search for SFC20 BLKMOV in Siemens Step7 help.
An other solution : use google and search for oscat.de : you could find a SCL block library for free.
Best regards.
Thanks for the answer...

I will try and inform.

Best regards
Janosch07
Posts: 19
Joined: Sun Oct 22, 2006 9:12 am

Re: [?]: Move DB data from one to other in SCL

Post by Janosch07 »

This code is proven working
Show

Code: Select all

FUNCTION_Block "CopyDB"

AUTHOR : Someone
FAMILY : MoveDB
NAME : CopyDB
VERSION : '1.0'
KNOW_HOW_PROTECT

VAR_INPUT
    Source : INT;    // Source DB
    Destination : INT;    //Distination DB
END_VAR
VAR_OUTPUT
    Error : WORD;
END_VAR
VAR_IN_OUT
    Execute : BOOL  ;    //Execute Copy 
END_VAR

VAR_TEMP
    tiX : INT;
    RETVAL : INT;
    tiSourceDBLength : WORD;
    tiDestinationDB1Length : WORD;
    tbWriteProtected : BOOL;
END_VAR

BEGIN
    IF Execute THEN
        Error := 0;
        // Get information of source DB
        RETVAL := TEST_DB(DB_NUMBER := INT_TO_WORD(Source), DB_LENGTH := tiSourceDBLength, WRITE_PROT:=tbWriteProtected);
        // If TEST_DB for source DB function was executed error free, the continue, otherwise indicate the error
        IF RETVAL = 0 THEN
            RETVAL := TEST_DB(DB_NUMBER := INT_TO_WORD(Destination), DB_LENGTH := tiDestinationDB1Length, WRITE_PROT:=tbWriteProtected);
            // If TEST_DB for destination DB function was executed error free, the continue, otherwise indicate the error
            IF RETVAL = 0 THEN
                // Check if destination DB write protected
                IF tbWriteProtected THEN
                    Error := W#16#000A; // Write protection error W#16#A
                ELSE    
                    IF tiSourceDBLength = tiDestinationDB1Length THEN // Check if both DBs have the same length
                        // both DBs have the same length. copy source to destination
                        FOR tiX := 0 TO (WORD_TO_INT(tiSourceDBLength) - 2) BY 2 DO
                            // word by word copy
                            WORD_TO_BLOCK_DB(INT_TO_WORD(Destination)).DW[tiX] := WORD_TO_BLOCK_DB(INT_TO_WORD(Source)).DW[tiX];
                        END_FOR;
                    ELSE // If length differs then output error W#16#B (Length Error)
                        Error := W#16#000B;
                    END_IF;
                END_IF;    
            ELSE // destination DB error
                Error := INT_TO_WORD(RETVAL);
            END_IF;
        ELSE // Source DB error.
            Error := INT_TO_WORD(RETVAL);
        END_IF;
        Execute := False;
    END_IF;
 
Enjoy
cabrca
Posts: 7
Joined: Thu Jul 01, 2010 6:01 am

Re: [?]: Move DB data from one to other in SCL

Post by cabrca »

Janosch07 wrote:This code is proven working :

Enjoy
Hi Janosch07,

Tested and working. Your code copies a complete DB to another one exacty equal, but it does not makes exactly what I need.

I need to copy parts from one DB to another , but de source data may not start in DWn.0 and with a lenght different than 16 or 32 bits.
The source data I need to move is for example 30 bits starting in address db20.dbx2.4 and move them to another DB starting for example in the address db21.dbx0.0 . :roll:

How can I point to bits instead of words using an instruction like the one you've used:

Code: Select all

WORD_TO_BLOCK_DB(INT_TO_WORD(Destination)).DW[tiX] := WORD_TO_BLOCK_DB(INT_TO_WORD(Source)).DW[tiX]; 
Best regards,
dehell
Posts: 104
Joined: Sat Jun 13, 2009 12:25 pm
Location: Europe

Re: [?]: Move DB data from one to other in SCL

Post by dehell »

Hi,
Try this code
Show

Code: Select all

FUNCTION_BLOCK FB505

TITLE = 'Bit_DB_AREA_to_Word_DB_AREA'
//Take care, this block don't check if DB exist or enough long...
// Instruction
//
VERSION : '1.0'
AUTHOR  : Dehell
NAME    : BTW
FAMILY  : BTW

VAR_INPUT
    DB_IN: INT;// INPUT DB number
    IN_BYTE:INT;// INPUT Byte number
    IN_BIT:INT;// INPUT bit number
    DB_OUT:INT;// OUTPUT DB number
    DEST_WORD:INT;// OUTPUT Word number
    LENGH:INT;// Number of bit to copy
END_VAR
VAR_OUTPUT
    DONE:BOOL;
    
END_VAR
VAR
    NUM_DB_IN: WORD;
    NUM_DB_OUT:WORD;
    NUMBER_BYTE:INT;
    NUMBER_BYTE2:INT;
    INDEX1:INT;
    INDEX2:int;
    INDEX3:INT;
    INDEX4:INT;
    INDEX5:INT;
    MASK:BYTE;
    NBR_BIT_MASK:INT;
    BYTEARRAY: ARRAY[0..31]OF BYTE;// maximum 256 bits : you can increase this value
    BITARRAY2:ARRAY[0..255]OF BOOL;
    BYTEARRAY2 AT BITARRAY2:ARRAY[0..31]OF BYTE;
    BITARRAY1 AT BYTEARRAY :ARRAY[0..255]OF BOOL;
   
END_VAR

 BEGIN
 NUM_DB_IN:=INT_TO_WORD(DB_IN);
 NUM_DB_OUT:=INT_TO_WORD(DB_OUT);
 DONE:=FALSE;
 IF LENGH < 8 THEN
   RETURN;// if LENGH<8 this function is aborted
   ELSE 
 // Number of byte calculation
 NUMBER_BYTE:=(LENGH/8)+1;
 NUMBER_BYTE2:=(LENGH/8);
 END_IF;
 // Copy DB_IN into BYTE ARRAY
 FOR INDEX1:=0 TO NUMBER_BYTE DO
 BYTEARRAY[INDEX1]:=WORD_TO_BLOCK_DB(NUM_DB_IN).DB[IN_BYTE+INDEX1];   
END_FOR;
// Copy ARRAYBIT1 into ARRAYBIT2 with offset
FOR INDEX2:=0 TO LENGH DO
    BITARRAY2[INDEX2]:=BITARRAY1[INDEX2+IN_BIT];
END_FOR;
//Copy ARRAYBIT2 into WORDARRAY
FOR INDEX3:=0 TO (NUMBER_BYTE2-1) DO
WORD_TO_BLOCK_DB(NUM_DB_OUT).DB[DEST_WORD+INDEX3]:= BYTEARRAY2[INDEX3];
END_FOR;  
// For last BYTE, create Mask 
NBR_BIT_MASK:=((LENGH-(NUMBER_BYTE2*8))-1);
INDEX5:=DEST_WORD+(NUMBER_BYTE2);
FOR INDEX4:= 0 TO 7 BY 1 DO
    IF INDEX4 >=0 AND INDEX4 <= NBR_BIT_MASK THEN
    WORD_TO_BLOCK_DB(NUM_DB_OUT).DX[INDEX5,INDEX4]:= BITARRAY2[((NUMBER_BYTE2*8)+1)+INDEX4];
  END_IF;
 END_FOR;
DONE:=TRUE; 
 
 
    END_FUNCTION_BLOCK
I test on PLCSIM and it seem OK
Best regard
cabrca
Posts: 7
Joined: Thu Jul 01, 2010 6:01 am

Re: [?]: Move DB data from one to other in SCL

Post by cabrca »

Excellent answer dehell... This is exactly what I needed !!!!!

Thanks a lot !!

(clap) (clap) (clap) (pgood) (pgood) (pgood)
(suc) (suc) (suc) (tyou) (tyou)
Last edited by cabrca on Tue Oct 25, 2011 3:29 pm, edited 2 times in total.
Janosch07
Posts: 19
Joined: Sun Oct 22, 2006 9:12 am

Re: [?]: Move DB data from one to other in SCL

Post by Janosch07 »

Hi Cabrca,

Try this code for copying bits
Try this code for copying bits
Show

Code: Select all


FUNCTION_Block "CopyDBBits"

AUTHOR : abcd
FAMILY : efgh
NAME : CopyDBbx
VERSION : '1.0'
KNOW_HOW_PROTECT

VAR_INPUT
    Source : INT;    // Source DB
    Destination : INT;    //Distination DB
    SourceBitOffset : INT; // Offset to start bit of source DB. (if DBx.DBX8.7 then Offset  = 7)
    DestinationBitOffset : INT; // Offset to start bit of destination DB. (if DBx.DBX1.0 then Offset  = 0)
    SourceByteOffset : INT; // Offset to start byte of source DB. (if DBx.DBXB8.7 then Offset  = 8)
    DestinationByteOffset : INT; // Offset to start byte of destination DB. (if DBx.DBX1.0 then Offset  = 1)
    // Offset must be between 0 and 7
    BitsToMove : INT; // Number of bits to copy
END_VAR
VAR_OUTPUT
    Error : WORD;
END_VAR
VAR_IN_OUT
    Execute : BOOL  ;    //Execute Copy 
END_VAR

VAR_TEMP
    tiX : INT;
    RETVAL : INT;
    tiSourceBit : INT;
    tiDestinationBit : INT;
    tiSourceByte : INT;
    tiDestinationByte : INT;
    twSourceDBLength : WORD;
    twDestinationDBLength : WORD;
    tbWriteProtected : BOOL;
END_VAR

BEGIN
    IF Execute THEN
        Error := 0;
        // Get information of source DB
        RETVAL := TEST_DB(DB_NUMBER := INT_TO_WORD(Source), DB_LENGTH := twSourceDBLength, WRITE_PROT:=tbWriteProtected);
        // If TEST_DB for source DB function was executed error free, the continue, otherwise indicate the error
        IF RETVAL = 0 THEN
            RETVAL := TEST_DB(DB_NUMBER := INT_TO_WORD(Destination), DB_LENGTH := twDestinationDBLength, WRITE_PROT:=tbWriteProtected);
            // If TEST_DB for destination DB function was executed error free, the continue, otherwise indicate the error
            IF RETVAL = 0 THEN
                // Check if destination DB write protected
                IF tbWriteProtected THEN
                    Error := W#16#000A; // Write protection error W#16#A
                ELSE    
                    // No errors when evaluating DBs information. copy source to destination
                    // Check for Parameter errors
                    IF ((INT_TO_WORD(SourceBitOffset) OR 16#7) <> 7) THEN
                        Error := W#16#000C; // Source bit offset out of range
                    END_IF;    
                    IF ((INT_TO_WORD(DestinationBitOffset) OR 16#7) <> 7) THEN
                        Error := W#16#000D; // Source bit offset out of range
                    END_IF;    
                    tiSourceBit := SourceBitOffset; // Initialise the source bit pointer
                    tiDestinationBit := DestinationBitOffset; // Initialise the destination bit counter
                    tiSourceByte := SourceByteOffset; // Initialise the source byte counter
                    tiDestinationByte := DestinationByteOffset; // Initialise the destination byte counter
                    // First, check for length errors
                    // Note : the length of a DB is always an even number. If for example the last entry in a DB is DBX6.7, this function will allow writing up to 
                    // DBX7.7 and beyond that an error is returned
                    FOR tiX := 0 TO (BitsToMove - 1) DO // loop through the number of required bits to copy
                        IF ((tiDestinationByte + 1) > WORD_TO_INT(twDestinationDBLength)) THEN // Check if destination byte pointer exceeds the length of the destination DB
                            Error := W#16#000E; // Copy of bits interrupted due to possible write error on destination DB
                        END_IF;        
                        IF ((tiSourceByte + 1) > WORD_TO_INT(twSourceDBLength)) THEN // Check if destination byte pointer exceeds the length of the source DB
                            Error := W#16#000F; // Copy of bits interrupted due to possible read error from source DB
                        END_IF;
                        IF Error <> 0 THEN
                            EXIT;
                        END_IF;    
                        // word by word copy
                        WORD_TO_BLOCK_DB(INT_TO_WORD(Destination)).DX[tiDestinationByte,tiDestinationBit] := WORD_TO_BLOCK_DB(INT_TO_WORD(Source)).DX[tiSourceByte,tiSourceBit];
                        tiDestinationBit := tiDestinationBit + 1; // increment source bit pointer by 1
                        tiSourceBit := tiSourceBit + 1; // increment destination bit pointer by 1
                        
                        IF tiDestinationBit > 7 THEN // If bit higher than 7 then
                            tiDestinationByte := tiDestinationByte + 1; // increment byte pointer by 1 
                            tiDestinationBit := 0; // reset bit pointer to 0
                        END_IF;    
                        IF tiSourceBit > 7 THEN // If bit higher than 7 then
                            tiSourceByte := tiSourceByte + 1; // increment byte pointer by 1
                            tiSourceBit := 0; // reset bit pointer to 0
                        END_IF;    
                    END_FOR;
                END_IF;    
            ELSE // destination DB error
                Error := INT_TO_WORD(RETVAL);
            END_IF;
        ELSE // Source DB error.
            Error := INT_TO_WORD(RETVAL);
        END_IF;
        Execute := False;
    END_IF;
END_FUNCTION_BLOCK
test and see if it's good for you

Regards