Creating a logfile with Karel?

  • Hi, I have no experience of Karel programing. I need to make a program that store values from a couple of registers and put them in logfile(txt) with date stamps. Would this even be possible to do in Karel? If so, do anyone have an example of something similar?


    Thanks in advance!

  • This is certainly possible with Karel and should not be too difficult to implement.


    You could write something that runs a simple WHILE loop (with an appropriate termination condition and DELAY statement), and periodically writes out the values of the registers you are interested in.


    Couple of pointers:


      • mark your logging program as not containing any motion: use the %NOLOCKGROUP directive for this. This would also allow you to keep your logging program running (in the background) in case of any (motion related) errors (see %NOPAUSE and %NOBUSYLAMP fi)

      • you can get the current time with the GET_TIME routine. Convert this to a string using CNV_TIME_STR. One issue is that GET_TIME returns a value with a resolution of 2 seconds. This might be an issue, depending on your requirements. If you need sub-second logging, GET_USEC_TIM might do the trick.

      • Accesing registers: GET_POS_REG, GET_REG, GET_STR_REG, etc.

      • Don't forget to terminate the lines you send to WRITE with a CR: not only does this lead to very long lines, but depending on configuration of your file descriptor, CR is actually used to signal to the interpreter that the buffer should be flushed to the device.

      • I'd install an ABORT handler, which delays aborting of your Karel program, so you can properly close your logfile. Depending on circumstances, not closing (and flushing) of FILE descriptors can lead to data loss. See Chapter 6 (Condition Handlers) of the Karel Reference Manual for this.

      • Be sure to build in some kind of limiting system: you don't want your logfile to eat up all the free space on your MD or RD device. I've noticed Fanuc controllers can suffer from memory fragmentation, where the total amount of free memory seems ok, but the largest free block is very small. This can lead to performance issues with other subsystems (such as motion).


    Hope this helps.

    Edited once, last by rf103 ().

  • Maybe it can help you. It is simple test program to create XML file. And after you can get this file from LAN into pc and parse it.


  • Hello,
    I know this is an old topic...but I was wondering why I am not getting the Seconds to output with the following code:


    GET_TIME(intTime)
    CNV_TIME_STR(intTime, time_str)
    WRITE ('Date: ' , SUB_STR(time_str, 1, 9), CR)
    WRITE ('Time: ' , SUB_STR(time_str,11,5), CR)
    WRITE('Full String: ',time_str, CR)


    My output reads:


    Date: 28-JUN-16
    Time: 11:26
    Full String: 28-JUN-16 11:26


    Any ideas?
    Thank you


  • from what i read, the routine does not convert the values for seconds

  • Skalactik, I read that too, and makes me think it is not possible. But if you read under the GET_TIME Built-In Procedure it states, "Use the CNV_TIME_STR built-in procedure to convert the INTEGER into the "DD-MMM-YYY-HH:MM:SS" STRING format. The manual is not really clear, but from testing I'm thinking I cannot get the seconds to output.

  • We're been doing this for a couple of months now, with good success.
    I've got a karel program that gets called while sending the robot home. It then stores the previous job number, timestamp, resin and glass weights, and if we're spraying the whole cart, or only a section of the cart.


    PROGRAM spray_log
    VAR
    file_var : FILE
    glass_weight : REAL
    resin_weight : REAL
    glass_status : INTEGER
    resin_status : INTEGER
    gtemp : INTEGER
    rtemp : INTEGER
    programname : STRING[5]
    now : INTEGER
    timestamp : STRING[20]
    wallside4 : STRING[2]
    wtemp : REAL
    wstatus : INTEGER
    wallreg : INTEGER
    BEGIN
    GET_TIME(now)
    CNV_TIME_STR(now,timestamp)
    GET_REG(1,TRUE,rtemp,resin_weight,resin_status)
    GET_REG(2,TRUE,gtemp,glass_weight,glass_status)
    GET_REG(20,FALSE,wallreg,wtemp,wstatus)
    CNV_INT_STR(wallreg,2,0,wallside4)
    IF NOT UNINIT(programname) THEN
    OPEN FILE file_var('AP', 'fr:spray_log.xml')
    WRITE file_var ('<part><ts>',timestamp,'</ts><job>',programname+wallside4,'</job><rw>', resin_weight::9::2 ,'</rw><gw>', glass_weight::9::2,'</gw></part>' ,CR)
    CLOSE FILE file_var
    ENDIF
    programname=$TP_DEFPROG
    END spray_log

  • Hello,


    I want to log different data during production. I know how to log the data now but does any body know how to check the size of the logfile?
    I want to delete the log file if size becomes to big to avoid that the memory becomes full.


    Thanks in advance,
    Regards,
    Fabrice

  • If you are using xml type, then you can previously make deseriallization of your data file and after that check how much records do you have. It should pretty much equal to your requirement. Also you need to check how much records satisfy your requirement for file size. And after you can decide do you want to delete the file or not. I mixed few sentences but I hope you understand.

  • Hi Scotty,


    Thanks for the information.
    Is it really needed to use xml file, what will you mean by deseriallization?


    If I follow you idea I can maybe use this instruction GET_FILE_POS to check the amount of records.


    Reagrds,
    Fabrice

  • Serialization is the process of converting an object into a stream of bytes in order to store the object or transmit it to memory, a database, or a file. Its main purpose is to save the state of an object in order to be able to recreate it when needed. The reverse process is called deserialization.


    If you want to have file with structured data type then I recommend to make xml structure and take a look to XML topic in KAREL Reference Manual. In opposite case you can use any other solution.


    Recommendation from Fanuc:
    GET_FILE_POS is only supported for files opened on the RAM Disk device. Do not use GET_FILE_POS on another device; otherwise, you could injure personnel and damage equipment.


    Regards,
    Scotty

    Edited once, last by scotty ().

  • To check the file size you can use the FILE_LIST built-In procedure:


    ----------------------------------------------------------
    --- Display a directory listing of files on the MC drive:
    file_spec = 'MC:\*.*' -- All files in MC drive
    n_skip = 0 -- First time do not skip any files
    format = 4 -- Return list in filename.filetype size date time - format
    WRITE ('Doing FILE list',CR)
    REPEAT -- UNTIL all files have been listed
    FILE_LIST(file_spec, n_skip, format, ary_nam, n_files, STATUS)
    IF (STATUS <>0 ) THEN -- Error occurred
    WRITE ('FILE_LIST builtin failed WITH STATUS = ',STATUS,CR)
    ELSE
    displ_list(n_files) -- Write the names to the TP USER menu
    n_skip = n_skip + n_files -- Skip the files we already got.
    ENDIF
    UNTIL (ARRAY_LEN(ary_nam) <> n_files) -- When n_files does not equal
    ----------------------------------------------------------------------------


    The file size is written in:
    ary_nam :ARRAY[100] OF STRING[40] -- Returned names format: filename.filetype size date time
    and always starts with char 21


    Date and time is only supported if the device supports timestamping. I guess this is related to a controller SW-version...

  • Thanks for you replies.


    I will use the following code and write in the ram memory.


    str_fn = 'rd:\CycleTime.txt'
    CLOSE FILE logfile
    OPEN FILE logfile('AP',str_fn) -- Appends data
    FileSize=GET_FILE_POS(logfile)
    IF FileSize>1000000 THEN
    CLOSE FILE logfile
    OPEN FILE logfile('RW',str_fn) -- Rewrites - Delete existing data
    ENDIF

  • Or you could use a PIP-file in case memory-management is an issue, it offers following functionality:
    -Read and write data at the same time. (a Karel program fills the buffer while another retrieves information of interest)
    -Rolling buffer


    The max buffer size is determined by the PERM cmos memory (menu>statu>memory) if 'cmos_flag=TRUE' is enabled. 700kb equals +- 20 000 lines of 40 char logging data.



    PROGRAM pip_write
    %NOLOCKGROUP
    %NOPAUSE= COMMAND + TPENABLE + ERROR


    VAR
    out_file:FILE
    console:FILE
    cmos_flag: BOOLEAN
    n_sectors: INTEGER
    record_size: INTEGER
    form_dict: STRING[32]
    form_ele: INTEGER
    STATUS:INTEGER
    i: INTEGER


    BEGIN
    FORCE_SPMENU(TP_PANEL,SPI_TPUSER,1)--activate user
    WRITE(CHR(128),CR)--clear user screen

    cmos_flag=TRUE -- CMOS_flag if set to TRUE will put the pipe data in CMOS. By default pipe data is in DRAM.
    -- If CMOS_FLG = False; n_sectors will stay default 8 ==> 8 * 1024 = 8192 characters
    -- Put CMOS_FLG = TRUE to change the n_sectors. (example 32 ===> 32 * 1024 = 32768 bytes of logfile)
    n_sectors = 700 --n_sectors number of 1024 byte sectors to allocate to the pipe. The default is 8
    record_size = 0 --record_size the size of a binary record in a pipe. If set to 0 the pipe is treated as ASCII
    form_dict = 'test'
    form_ele = 1
    PIPE_CONFIG( 'PIP:JT_1.dat', cmos_flag, n_sectors, record_size, form_dict, form_ele, STATUS) --need to be called before file is open


    OPEN FILE out_file ('rw', 'PIP:JT_1.dat')-- open file for write to device PIP:
    STATUS = IO_STATUS(out_file)
    WRITE TPDISPLAY('status open file for write',STATUS,CR)
    FOR i = 0 TO 20005 DO
    WRITE out_file ('nr', i , ' - Data that I am logging', CR)
    ENDFOR
    STATUS = IO_STATUS(out_file)
    WRITE TPDISPLAY('status after writing',STATUS,CR)
    CLOSE FILE out_file


    END pip_write

Advertising from our partners