P2 PLC: Foundation might be working...
Here's a very rough cut at the start of a P2 PLC.
There are three modes:
1. Edit (doesn't really work, just displays ladder, eventually would like onboard editing...)
2. Simulate: Interact with ladder using USB mouse
3. Run: Uses actual I/O
Can display ladder via VGA and/or USB serial.
Slowed down USB serial so can use regular FlexProp terminal to view ladder, but it's painfully slow to interact with mouse.
I'm using Visual Studio to edit and run.
But, you should be able to open up ladder.c in FlexProp and run that way as well.
Many of the settings like VGA pins and USB pins and baud are in Platform.h
For the moment, there are only contacts and coils.
Think have both I/O and internal relay version working.
The input file comes from ldmicro, the .ld file is embedded in "ldfile.spin2".
This code is very preliminary.
The menu doesn't work.
Nothing scrolls, etc.
Cycle time is now correct.
Simulation mode now runs in own cog so as to have correct cycle time.
Comments
Here's a version of ldmicro that was modified to include P2 as MCU option.
The files that were changed are attached.
The .ld file that is embedded in the above is also attached here.
Seems there are two PC side software routes to pursue...
ldmicro is one and is what is used here. This is relatively old and only has ladder logic.
But, simplicity can be a virtue. Also, the code is something that is easy for me to modify...
It can also generate Ansi C code that be adapted for P2 and compiled with Catalina and/or FlexProp.
Other one is OpenPLC. This one is newer and supports ladder logic plus 4 other coding methods.
This looks to be what Arduino adapted for use with their Opta PLC device.
This could probably also be adapted for P2, but would be more work, looks like...
OpenPLC is not off my table, but ldmicro seems to be easiest path to start with...
I should say thanks to @refaQtor and others for guidance as to what people would want from this thread:
https://forums.parallax.com/discussion/176074/towards-a-p2-plc#latest
Ok, run mode was completely broke.
Think fixed now with alpha0p002, now in top post...
On a different computer putty is not behaving... Must be more that rows and cols that made it work, have to investigate that...
super results! the "cycle time" sort of thing would be useful to watch on the side in one of the status info blocks.... along with usage of any other constrained/limited resources.
I think your efforts on pure ladder are going so well, I wouldn't mire it with trying to incorporate all the other of OpenPLC at the moment. But, that may be limitations in my understanding of what's involved on the compiler/translation sides of things. I suggest keep going whatever direction you can keep your momentum up. I think either of the Ladder only or a full suite of OpenPLC would be useful. Ladder might be simply done, and useful, standalone. OpenPLC seems like it might have more life for broader usage. Just a hunch, though.
Thanks @refaQtor
Think have cycle time working now in run mode.
Multimeter was saying 713 Hz when should be 666 Hz for 15 ms.
Have to get out scope to make sure...
Assuming cycle time doesn't need to be correct in simulation mode, but maybe?
Thought had Ansi serial output figured out by upping baud to 921600 and using putty with cols set to 128 and rows set to 50.
But, while this is working fine on one PC, doesn't work on another...
Thinking that updating then entire screen using ansi over serial might just not work...
I didn't look into your code to see, but I'll point out that screen updating CANNOT be in the execution loop. the slowest part by far is the serial writing, and that'll need to execute at its own refresh rate that is sensible, which will be impossibly slow for the actual ladder loop. this situation does present a likely probablility that you'll not see some of the execution reflected in the display - things will go on-off between screen refreshes... and that is the behavior I've seen of the few PLC "live-view" modes out there already.
In the past, I've been stymied by introducing an innocent print statement to see what was happeining, which introduced painful delay and bug masking in a process that normally took ms to execute.
@refaQtor Realized needed to do that this morning and fixed it...
The RunProgram() code now runs in it's own cog.
But, seems I've published this before getting run mode working correctly when in its own cog...
There is some logic to fix... Hopefully, all good tomorrow...
Think close to having run mode work right...
Just realized that coils can be of negated type. This is messing with my brain...
Got stuck so took peek at the Ansi C file that ldmicro generated...
Seeing that it updates and reads I/O during the program...
Right now, the idea was to read I/O at the start and write I/O at the end...
Guess need to allow both ways...
Think have the run mode logic sorted out...
But, this is with what guess would call "buffered" I/O so that I/O is only read and written to outside of the program code.
Guess need option to make it "unbuffered" as well to match what ldmicro does.
Now, need to update the simulation mode to match the run mode...
Late to the party as usual but this is all looking really interesting.
I've programmed a few PLCs over the years - Siemens, Opto22, Toshiba, Mitsubishi, Koyo, Telemechanique, Horner, Omron, AB, and my hazy memory is that it was the "buffered" operation that was by far the norm. You can get into race/fallthrough conditions if unbuffered - especially with things like state machines.
I'm not sure what the unbuffered option practically offers except its a bit more like regular computer programming. You really don't want to be switching relays/contactors on and off within a ~10ms cycle time
Across the PLC brands there was variation un support for special output coils such as Set & Reset (like a flip flop) and also edge triggered coils. It looks like maybe 61131-3 doesn't worry about the special output coils and just sticks to standard and negated, does that sound correct? I think the specialised output coils can be achieved other ways on the input side. Here's a reasonable summary of specialised coil types
https://tprojects.schneider-electric.com/GeoSCADAHelp/ClearSCADA%202017%20R2/Content/LogicGuide/LadderDiagramComponents.htm#:~:text=Set%20coil.,Off%20(by%20a%20reset).
The
--| P |--
rising and--| N |--
falling edge detects are great features.I've not seen the
--( P )--
and--( N )--
coil types before. Not sure I understand what they do. The blurb reads like it produces a pulse lasting for one rung of execution time.Yeah thats exactly it, a one-shot for one single cycle.
A cycle is typically a whole scan cycle of the Ladder + I/O. One rung is far shorter period.
Ah I see what you're saying, yes it does seem to say that its the shorter rung period, which surprises me. I'll see if I can fire something up to test what actually happens
This is not in ldmicro, right? Where do you see this? OpenPLC?
I came across this occasionally on PLCs years ago, but it didn't appear to be supported in LDmicro. I wasn't sure whether it was an IEC 61131 thing or not. Seems like it is,
https://cache.industry.siemens.com/dl/files/938//att_78450/v1/iec_61131_compliance_e.pdf
Having the set and reset coils is more useful than the edge triggered coils, so its good that these are included in LDmicro. The edge triggered coils can be achieved using edge triggered contacts (on the left side of the rung rather than right), so this really isn't a big issue. Getting anything working solidly with the P2 would be awesome
Schneider link above - https://tprojects.schneider-electric.com/GeoSCADAHelp/ClearSCADA 2017 R2/Content/LogicGuide/LadderDiagramComponents.htm
I have used single scan output pulse functions for effecting edge detect. They work. However, input edge detect is the more concise way. And certainly don't need both solutions.
Was pulling hair out today because this little test input board with 3 slide switches was making crazy things happen to the ladder.
Then, remembered that these switches momentarily short all three contacts together when slid from one side to the other.
This connects 3.3V to ground for a moment.
Like discussed here:
https://forums.adafruit.com/viewtopic.php?t=215763
Rewired and all good. But, lost a couple hours because forgot about this "feature".
Have to find some slide switches that don't do this for my test PCB being made...
Oh wow that's nasty. Well found...
Got the cycle time right now... Was overflowing...
Now dividing both us and clkfreq by 1000 before multiplying:
Rounding us to ms is maybe not ideal, so might look to improve that in the future...
Fixed up the code to almost be presentable now...
Posted alpha 0.003 to top post.
Fixed inverted contacts.
For now, living with slow serial terminal viewing of ladder and put baud back to 230400. Now works in regular terminal window, don't need putty.
Realized that you might actually want simulation mode to be in real time so that timers are correct.
So, now have simulation loop running in it's own cog, just like run mode does.
Read up on Spin2's
muldiv64()
.@evanh Great idea, thanks!
Implemented that using spin2 'cause not seeing it in C...
Oh, missed that. FlexC has
_muldiv64()
instead.