Shop OBEX P1 Docs P2 Docs Learn Events
towards a P2 PLC - Page 6 — Parallax Forums

towards a P2 PLC

12346

Comments

  • evanhevanh Posts: 16,103

    @refaQtor said:
    ... there are plenty of enhancements to displaying live the status of the system. and assist in debugging. all well beyond those languages.

    That's no longer a language discussion at all. That's tools.

  • evanhevanh Posts: 16,103
    edited 2025-01-12 03:42

    @refaQtor said:
    and, from the current miserable experience I'm having of trying to decipher and modify Ladder Logic code for these fancy mass-flow controllers that require stepping through strings of characters and doing math digit by digit, which I find on industrial control forums, not uncommon.... I see that there is an official language that covers the full spectrum of digital/analog discrete/continuous. so, that is why I look to making that more useful and easier to see visually live what is going on in the system.

    There is an extension to Ladder in modern PLCs that I only know as Function Block. Not the IEC's FBD.

    Function blocks allow incorporating of other languages as subordinate to the Ladder. In the Ladder, such blocks look not dissimilar to a timer but can be placed in the middle of a rung - Some PLCs have timers in mid-rung too. The number of inputs and outputs are definable. For the code author, they are conceptually a little tricky because the blocks are not processed sequentially within the Ladder execution order but rather in their own time. Presumably still synchronised with the I/O scan though.

    EDIT: Replaced "Ladder sequence" with "Ladder execution order".
    PS: It might not be so new an idea either. I suspect Siemens PLCs (from the S5's at least) might have always provided this extension.

  • refaQtorrefaQtor Posts: 95
    edited 2025-01-12 03:59

    @evanh said:
    There is an extension to Ladder in modern PLCs that I only know as Function Block. Not the IEC's FBD.

    I see the OpenPLC does have those, and you can add your own in other languages. It doesn't enforce Ladder at the top level, though. But, their examples show well when they do. Each rung has a functional block in the middle with a different language.

    Well, that'll teach me to step into fixing/finishing another person's project started, apparently, on an inadequate PLC with only one limited language IDE option.

  • evanhevanh Posts: 16,103

    Yep, knowing what the options are helps. You'll strike this same problem in every profession. Only select polytechs will teach the speciality and you only get to find out what that is after beginning an apprenticeship in the field.

  • refaQtorrefaQtor Posts: 95
    edited 2025-01-12 05:04

    @evanh said:
    and you only get to find out what that is after beginning an apprenticeship in the field.

    well, as I might've mentioned before, I began Ladder Logic in the '80s, it was actual Relay Logic on 45KW LORAN transmitters - water-colled vacuum tubes from the '50s. :) I liked it. you could hear/feel/see the execution of the ladder down the relay panel, and standby with the the wooden safety cane to rap on sticky relays, if your internal timer felt it was taking too long on startup. ah, the days when you could commit the entire schematic & identifier of every cap and tube and resistor and triac to memory :) . Debugging often started with turning off the lights and turning on your nose. the smell of each type of overhot component was different, and may have been glowing as well.

    then computer engineeing in college spoiled me with math and string libraries. just learning how they've been combined thanks to good people sharing.

  • evanhevanh Posts: 16,103

    You're a lot older than I expected. :embarrassed:

  • RossHRossH Posts: 5,508

    @Rayman said:
    Alternatively, could use the c file that ldmicro can make. But, this way allows for eventual on chip editing of the ladder…

    Catalina can compile and run it. I demonstrated this with OpenPLC, which is the part of LDmicro that generates C code. You may need to write some runtime library functions.

  • RaymanRayman Posts: 14,825

    Need to see how I/o pins are handled…
    Only read before the ladder and written after?
    Or, can they change within the loop?

  • @Rayman said:
    Need to see how I/o pins are handled…
    Only read before the ladder and written after?
    Or, can they change within the loop?

    I believe that the I/O mustn't change within the loop. I think you want to read them all into registers that shadow the state of them all at the beginning, then work only from those registers, while the actual I/O may be shifting.

    on the other side of things... be writing results to these interim register, then only copy them out to the output pins at the end of the logic processing stage.

  • refaQtorrefaQtor Posts: 95
    edited 2025-01-12 15:32

    @evanh said:
    You're a lot older than I expected. :embarrassed:

    I sound a lot younger than I am. :embarrassed:

    While I have come to respect the-way-things-are-done, from electrronics to databases to protocols, and why. I also haven't had my dreams of how I want a machine to work completely beaten out of me. After a long percolation, the designs are coming together in my head and getting out on designs and hardware. difficult to convey except in terms of similar things. In fact- I called this project "platypus" for a long time, because it was so hard to describe. it is more af a cephalopod, now.

    The unique features of the Propeller have gone a long way to soliidifying designs. so, I pester you all around here. I apologise that I communicate better with machines than humans.

  • RaymanRayman Posts: 14,825

    Thanks @refaQtor
    Same for registers? (i.e., "internal relays")

    These seem to be bits, but might be easier to handle as bytes or longs...
    Can't imagine there would ever enough of them to be a memory problem...

  • @Rayman said:
    Thanks @refaQtor
    Same for registers? (i.e., "internal relays")

    I think the internal registers are accessed and changed as necessary in the strict sequence of the rungs.
    some are binary, and when doing math, they will be stored in bytes/words/longs. there is some definition of standard datatypes. I can't look up now. but, the process can be put in place with just longs, to start.

  • JonnyMacJonnyMac Posts: 9,191
    edited 2025-01-12 18:54

    I've only casually looked at ladder logic. Am I wrong to think that the synchronized loop in the Propeller (using waitcnt() and waitct()) lend themselves to converting ladder to Spin? Structurally, something like...

      t := cnt
      repeat
        inputs := ina
        run_rung1
        run_rung2
        run_rung3
        waitcnt(t += LOOP_TICKS)
        update_timers 
        update_outputs
    

    Or am I being far too simplistic?

  • RaymanRayman Posts: 14,825

    Think it could be done in Spin, especially with the new structures.
    Thought about doing it that for a moment...

    What is happening in this code is that the program is turned into a null terminated list of structures...
    Then, that list is used for drawing by going through the list one element at a time.

    What does help a lot is typecasting the structures. Assume can do that in new Spin2, but don't really know...

    Thinking that executing the program will also be just going through the list...

  • refaQtorrefaQtor Posts: 95
    edited 2025-01-12 18:42

    @JonnyMac said:
    Or am I being far too simplistic?

    a simple as possible is good.
    there is to be a timer update section after the rung processing, where the state of all the timers/counters are updated by adding the time that transpired since last time 'round.

    next processing loop will read and act based on the updated timer values. similar thing happens with the counters, I believe.

  • JonnyMacJonnyMac Posts: 9,191

    ...where the state of all the timers/counters are updated by adding the time that transpired since last time 'round.

    In my simple world view, this becomes easy by creating a variable for each timer, syncing it to the system clock, and then adding/subtracting the loop ticks value -- unless elements of the runs are able to gate them, which does make sense.

  • RaymanRayman Posts: 14,825
    edited 2025-01-12 19:47

    Going to test with a simple motor Start/Stop button controller...

    But, ldmicro won't let me use an I/O pin as both output and input....
    Removes pin from the list of pins when one is selected...
    Did not expect that...

    So, to do a Start/Stop operation with pins as input and another pin as output, guess on needs to use an internal relay?

    Want XStart and XStop to be controlled by I/O pins and also have an LED on YMotorOn that lights when "motor" is running...

    786 x 593 - 26K
  • RaymanRayman Posts: 14,825
    edited 2025-01-12 20:03

    Well, guess this is how it is done in the Wikipedia Start/Stop example too, so guess that's how it is...
    https://en.wikipedia.org/wiki/Ladder_logic

  • RaymanRayman Posts: 14,825

    Pull up situation is another question...

    The ldmicro .ld file now has a section like this:

    PULL-UP LIST
        PA: 0xFFFFFFFF 
        PB: 0xFFFFFFFF 
        PC: 0xFFFFFFFF 
        PD: 0xFFFFFFFF 
        PE: 0xFFFFFFFF 
        PF: 0xFFFFFFFF 
        PG: 0xFFFFFFFF 
        PH: 0xFFFFFFFF 
        PJ: 0xFFFFFFFF 
        PK: 0xFFFFFFFF 
        PL: 0xFFFFFFFF 
    END
    

    Think can hack ldmicro to just have PA and PB.
    But, should all the I/O really have pullups turned on?

  • RaymanRayman Posts: 14,825

    Ok, found this window where you can set pullup bits.
    But, they are only 8-bits...

    Might have to pretend there are eight 8-bit I/O ports...

    856 x 432 - 18K
  • evanhevanh Posts: 16,103

    @JonnyMac said:
    I've only casually looked at ladder logic. Am I wrong to think that the synchronized loop in the Propeller (using waitcnt() and waitct()) lend themselves to converting ladder to Spin? Structurally, something like...

      t := cnt
      repeat
        inputs := ina
        run_rung1
        run_rung2
        run_rung3
        waitcnt(t += LOOP_TICKS)
        update_timers 
        update_outputs
    

    Or am I being far too simplistic?

    Looks good to me. Although the rungs, being dynamic length, would be processed by a loop and end up existing as a DAT section or even loaded from a separate file in the end.

  • evanhevanh Posts: 16,103
    edited 2025-01-12 23:08

    @JonnyMac said:

    ...where the state of all the timers/counters are updated by adding the time that transpired since last time 'round.

    In my simple world view, this becomes easy by creating a variable for each timer, syncing it to the system clock, and then adding/subtracting the loop ticks value -- unless elements of the runs are able to gate them, which does make sense.

    You've got free rein on how complex a timer you want. PLCs all vary on this front. You can have several variants if you like. Multiple control inputs is an option. Same for counters. There is often even a small number of special timers/counters that can operate faster than the rest. Tying them to dedicated hardware is also up for grabs.

  • evanhevanh Posts: 16,103

    @Rayman said:
    Going to test with a simple motor Start/Stop button controller...

    But, ldmicro won't let me use an I/O pin as both output and input....
    Removes pin from the list of pins when one is selected...
    Did not expect that...

    So, to do a Start/Stop operation with pins as input and another pin as output, guess on needs to use an internal relay?

    Want XStart and XStop to be controlled by I/O pins and also have an LED on YMotorOn that lights when "motor" is running...

    Outputs used as inputs is quite normal. Don't know why you had any issue there.

  • RaymanRayman Posts: 14,825

    Ok, I get it now... ldmicro will let you use an "output" as both an output and an input...

    786 x 669 - 28K
  • RaymanRayman Posts: 14,825

    Got the motor stop/start example going now in "simulation mode" with fake input.
    Liking the idea of simulation mode along with single stepping, like ldmicro does...

    Guess need to add mouse support next, so can control simulation.

  • jmgjmg Posts: 15,183
    edited 2025-01-13 20:48

    I found a Chinese PLC on MCU effort here
    https://www.stcaimcu.com/forum.php?mod=viewthread&tid=7796

    and some speed claims here
    https://www.stcaimcu.com/forum.php?mod=viewthread&tid=7945

    and also this speed claim
    The data operation instruction efficiency of Mitsubishi PLC is too low. For example, 1000 single-word registers are squared and the result is 32 bits, which is equivalent to 1000 multiplication and addition operations. The program is implemented with loop instructions. The actual time taken by Delta ES2 series PLC (CPU is 72MHz STM32F103) is 27.9ms, while the actual time taken by this program on 32MHz STC32G12K128 is 10ms.

    Here is an SPI call example, as an image :

    That suggests live pin access is certainly supported, here doing the SPI chip select and send within the blocks.

    Below is a larger i2c library, I copied and AI translated.
    Syntax is similar but not quite identical :
    Ladder in-line uses =, +, etc , whilst code block uses MOV and AND etc
    Sometimes it uses assembler level lines like
    MOV Temp1,H00A2
    and also supported is more HLL lines
    DM0[RtcAddr]=Temp1+DM0[ValAddr]

    It does not look like formal IEC61131, but somewhere between HLL and Assembler.
    It seems the compiler/parser can accept any mix of the Ladder conditionals, and the text code ?
    The examples I've seen so far have at most 1-2 lines of text language within any ladder rung, maybe convention is to call a function when code gets larger to keep the 'Ladder look' ?

    RdSec: FUN I, Void As D0 
    ; Function: Read the seconds of the real-time clock. 
    | Function: Read the seconds information in the real-time clock module as the return value of the function. 
    | Void: meaningless, should be 0. 
    | Return value: The seconds in the real-time clock module (binary number). 
    | For example: DM300=RdSec(0)
        IICSTART
        MOV %D0,H00A2
        IICW %D0
        MOV %D0,H0002
        IICW %D0
        IICSTART
        MOV %D0,H00A3
        IICW %D0
        IICRNAK %D0
        IICSTOP
        RST %D0.7
        BIN %D0
        RETURN %D0
        EndFun
    
    ;================================================== ================================================== ================================================== ================================================== = ================================================== ================================================== ================================================== ================================================== ==
    RdRTC: FUN I,RTC_DM As D0 
    ;Function: Read the real-time clock function. 
    | Function: Read the year, week, month, day, hour, and minute information in the real-time clock module and store them in the specified data block (integer array). 
    | RTC_DM: The first address of the array that stores the real-time clock information (all expressed in BCD code). The meanings of each element in the array are as follows: 
    | [0]: Stores the year and week. The thousands and hundreds of the BCD number are the year, and the tens and ones are the week, such as: H0401 represents Monday, 2004. 
    | [1]: Stores the month and day. The thousands and hundreds of the BCD number are the month, and the tens and ones are the day, such as: H1205 represents December 5. 
    | [2]: Stores the hours and minutes. The thousands and hundreds of the BCD number are the hours, and the tens and ones are the minutes, such as: H2031 represents 20:31.
        LOCAL Temp1,Temp2 AS D1
        IICSTART
        MOV Temp1,H00A2
        IICW Temp1
        MOV Temp1,H0003
        IICW Temp1
        IICSTART
        MOV Temp1,H00A3
        IICW Temp1
        IICRACK Temp1 ;min
        SWAP Temp1
        IICRACK Temp1 ; hours
        AND Temp1,0X7F3F
        SWAP Temp1
        DM2[RTC_DM]=Temp1
        IICRACK Temp1 ; Day
        IICRACK Temp2 ; Week
        SWAP Temp1
        IICRACK Temp1 ;Month
        AND Temp1,0X3F1F
        SWAP Temp1
        DM1[RTC_DM]=Temp1
        SWAP Temp2
        IICRNAK Temp2 ;year
        IICSTOP
        AND Temp2,0X07FF
        SWAP Temp2
        DM0[RTC_DM]=Temp2
        EndFun
    
    ;================================================== ================================================== ================================================== ================================================== = ================================================== ================================================== ================================================== ================================================== ==
    WrRTC: FUN I, year As D0, day As D1, time As D2
    ; Write real-time clock function 
    | Function: Write the specified time information (week, year, month, day, hour, minute) into the real-time clock. 
    | year: year and week, BCD number. The thousands and hundreds of the BCD number are the year, and the tens and ones are the week, such as: H0401 means Monday, 2004. 
    | day: month and day, BCD number. The thousands and hundreds of the BCD number are the month, and the tens and ones are the day, such as: H1205 means December 5. 
    | time: hours and minutes, BCD number. The thousands and hundreds of the BCD number are the hours, and the tens and ones are the minutes, such as: H2031 means 20:31.
        LOCAL Temp1 AS D3
        IICSTART
        MOV Temp1,H00A2
        IICW Temp1
        MOV Temp1,H0000
        IICW Temp1
        IICW Temp1
        IICW Temp1
        IICW Temp1 ; seconds
        IICW time; minutes
        SWAP time
        IICW time;
        IICW day; day
        IICW year; week
        SWAP day
        IICW day; month
        SWAP year
        IICW year;
        IICSTOP
        EndFun
    
    ;================================================== ================================================== ================================= ================================================== ================================================== =================================
    RtcToVal: FUN I, RtcAddr As D0, ValAddr As D1
    ; ​​Convert the real-time clock format to a numerical format 
    | Function: Convert the compressed BCD format of the real-time clock to a single integer numerical format. 
    | Input parameters: 
    | RtcAddr: The first address of the data block (in DM) storing the compressed BCD format of the real-time clock. 
    | It occupies 3 words, 
      [0] is the year and week (high byte is year, low byte is week), 
      [1] is the month and day (high byte is month, low byte is day), 
      [2] is the hour and minute (high byte is hour, low byte is minute). 
    | ValAddr: The first address of the data block (in DM) storing the integer numerical format of the converted real-time clock. 
    | It occupies 6 words, [0]: week, [1]: year, [2]: month, [3]: day, [4]: ​​hour, [5]: minute. 
    | For example: RtcToVal(#DM300,#DM400)
        LOCAL Temp As D2
        Temp=DM0[RtcAddr]&H0FF00
        SWAP Temp
        BIN Temp
        DM1[ValAddr]=Temp+2000
        DM0[ValAddr]=DM0[RtcAddr]&H00FF
        Temp=DM1[RtcAddr]&H0FF00
        SWAP Temp
        BIN Temp
        DM2[ValAddr]=Temp
        Temp=DM1[RtcAddr]&H00FF
        BIN Temp
        DM3[ValAddr]=Temp
        Temp=DM2[RtcAddr]&H0FF00
        SWAP Temp
        BIN Temp
        DM4[ValAddr]=Temp
        Temp=DM2[RtcAddr]&H00FF
        BIN Temp
        DM5[ValAddr]=Temp
        EndFun
    
    ;================================================== ================================================== ================================= ================================================== ================================================== =================================
    ValToRtc: FUN I, ValAddr As D0, RtcAddr As D1
    ; ​​Convert the real-time clock value format to the compressed BCD format 
    | Function: Convert the single integer value format of the real-time clock to the compressed BCD format. 
    | Input parameters: 
    | ValAddr: The first address of the data block (in DM) storing the integer value format of the real-time clock. 
    Occupies 6 words, [0]: week, [1]: year, [2]: month, [3]: day, [4]: ​​hour, [5]: minute. 
    | RtcAddr: The first address of the data block (in DM) storing the compressed BCD format of the converted real-time clock. 
    Occupies 3 words, [0] is the year and week (high byte is year, low byte is week), [1] is the month and day (high byte is month, low byte is day), [2] is the hour and minute (high byte is hour, low byte is minute). 
    | For example: ValToRtc(#DM400,#DM300)
        LOCAL Temp1,Temp2 As D2
        Temp1=DM1[ValAddr]-2000
        BCD Temp1
        SWAP Temp1
        DM0[RtcAddr]=Temp1+DM0[ValAddr]
        Temp1=DM2[ValAddr]
        BCD Temp1
        SWAP Temp1
        Temp2=DM3[ValAddr]
        BCD Temp2
        DM1[RtcAddr]=Temp1+Temp2
        Temp1=DM4[ValAddr]
        BCD Temp1
        SWAP Temp1
        Temp2=DM5[ValAddr]
        BCD Temp2
        DM2[RtcAddr]=Temp1+Temp2
        EndFun
    

    This also needs live pin access to work.

    and here is an example of a file include, and some direct SFR access, looking very assembler like, but giving MCU register level access here.

  • evanhevanh Posts: 16,103
    edited 2025-01-13 21:47

    It's not so much the ladder is doing the live I/O, it's those Sxxx blocks are specially made to do it. Each one is a purpose built function that is designed to be used in execution sequence to produce I2C packets. I'd hazard a guess they're working with a hardware I2C module in the MCU.

    I'd also say a little unusual to have such fine grain support at the ladder level but it does give an example of how one PLC maker has chosen to add extensions.

    PS: It also demonstrates ordered execution. It's an example of where it's handy to have the function completed within the Ladder execution. Normally, this is reserved for maths on internal memory/logic only.

  • RaymanRayman Posts: 14,825
    edited 2025-01-13 22:04

    Got simulation mode working with mouse input on the Motor Start/Stop example.
    If you want to try it, connect VGA adapter on basepin 16 and USB host on basepin 24.

    Believe it is behaving similar to the ldmicro simulation mode....

    There is no timing yet, there's enough serial diagnostic output right now to slow it down enough...

  • RaymanRayman Posts: 14,825
    edited 2025-01-13 22:21

    Added Emergency Stop contact and seems to work in simulation.
    Note that the cursor is a magenta block and you single click on a contact to toggle it's fake i/o pin value...

    ldmicro changes color scheme in simulation mode so that active lines are red.
    Maybe will get to that eventually, but that seems like icing at this point...

  • RaymanRayman Posts: 14,825

    Just noticed something in ldmicro that don't fully understand...

    Contacts have an option for "Set High Level before simulation" that is only enabled for I/O pins that are INPUTS.
    This puts a caret character in front of the symbol.

    Why can't this apply to "Internal Relay" or OUTPUTS too? Not really getting that.
    Also, doesn't seem like super important to implement right away...

Sign In or Register to comment.