⬆Support this channel using the "Thanks" button⬆ or by making a donation through PayPal → www.paypal.com/donate/?hosted_button_id=7FBED5B26KT7S, or by becoming a Patron → www.patreon.com/sagatowski
The problems you see at the end about not writing a line is an actual bug. The fbPutFile gets stuck if it's only called one time with a false excecute. You can fix it by adding following state in the beginning, or end. Then the code will write every time to the logfile. CLEAR_FILE_FB: fbFileOpen(bExecute := FALSE); fbFilePuts(bExecute := FALSE); fbFileClose(bExecute := FALSE); eWriteState := FILE_OPEN_TRIGGER;
Regarding this, where is the stuff about bExecute explained in detail? Not just regarding file access, but in general. Among other things, I'd like to know: -Can I call e.g. fbFilePuts several times during one cycle? For example, first with bExecute := TRUE and then FALSE. -What if I try to write new stuff during the same cycle? Does the new just overwrite the old? -Do I have to call it every cycle to keep it doing whatever it should do, or does the system take care of that after I've called it once? -I'm guessing the outputs, including the busy state don't update if I don't call it?
Respect for the fact, that instead of cutting off from the video the part when an error has appeared, you showed how to handle with that. And hands up for using ENUM instead of INT. It's much more readable and I do keep forcing that since couple of years in my projects.
Добрый день, хочу поинтересоваться: насколько сильно на практике KRL отличается от ST? Насколько я понял, основной момент в программирование роботов, это то что робот работает не в постоянном цикле (как ПЛК), а просто однократно выполняет вызванную программу/подпрограмму. И в KRL вроде нет всех этих ООПшных плюшек?
You're an absolute hero. The videos are so well done. I hope you continue with PLC programming tips/tricks/guides or other PLC/programming oriented videos, even after this series ends. I'm a new software engineer in the field, your way of thinking and structure is just down my alley, keep it going! You're awesome! PS: Notice that every video has subtitles that even adds upon what he is saying. ALSO every video has timestamps and is structured. An absolute legend!
Wow thanks for the very kind words! I think it's a very good idea what you suggested. I will really try to upload videos even after the tutorial is finished, as it's really fun to do this. The only limitation is time, as it takes a lot of time to do the videos but thanks to feedback like you gave me I feel much more motivated. Thank you for becoming a member and supporting this channel!
@@JakobSagatowski If it were not for the titles, I would not be able to correctly perceive the material by ear, because I do not speak English properly. The credits are my salvation! Thanks!
Thank you for yet another great video. Having been through them all last couple of weeks, I feel this one is getting to the heart of what it needs to make the transition to "thinking in PLC". State machines, executes, enables, waiting for things to happen. That's how I feel at the moment
You got this! If you like this content (and would want to have early access to new videos), please consider becoming a Patron! ( www.patreon.com/sagatowski ). Thanks!
@@JakobSagatowski of course I will consider and I applaud your promotion. I have been doing this learning to see whether it's realistic to move into this tech from conventional s/w engineering, without prior experience. I have an actual opportunity to do that - but is it too high a mountain to climb? This is what I'm exploring. If it looks like a goer, then supporting your site looks like a great step :)
This is one of the greatest lessens i have ever seen ! Very good staff great tips and explanations i hope you will show how to create the buffer issue .... Thank you for this amaizing tutorial!!!!!!!!
Welcome back from a holiday Mr.Jakob!Coincidently,I was doing assignment on CSV file currently. I just sign up as your channel's member to support you. This really helps me a lot!❤️ Thanks :)
Hi Jakob. First of all thank you very much for your time and knowledge sharing. Some of my observations are: [REDITED] 1. We should start at WAIT_FOR_EVENT and once we get the event we will open the file, write to it and close. It is probably better as we just use the file when we need it and not keep it busy all the time. 2. I've been investigatitng a little more the topic of bExecute. Whe just need to put it at the end of each case rather of the begining and everything will work as expected. Maybe it will help someone. Here is my code: FUNCTION_BLOCK FB_CsvPersistentEventStorage IMPLEMENTS I_PersistentEventStorage VAR fbFileOpen : FB_FileOpen := (sPathName := 'C:\Events.log', nMode := FOPEN_MODEAPPEND OR FOPEN_MODETEXT); fbFilePuts : FB_FilePuts; fbFileClose : FB_FileClose; eWriteState : (WAIT_FOR_EVENT, FILE_OPEN_TRIGGER, FILE_OPEN, WRITE_EVENT_TRIGGER, WRITE_EVENT, FILE_CLOSE_TRIGGER, FILE_CLOSE, ERROR); stEventWrittenToFile : ST_Event; CsvString : T_MaxString; END_VAR ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- CASE eWriteState OF WAIT_FOR_EVENT : //Do Anything FILE_OPEN_TRIGGER : fbFileOpen(bExecute := TRUE); eWriteState := FILE_OPEN; FILE_OPEN : IF fbFileOpen.bError THEN eWriteState := ERROR; ELSIF NOT fbFileOpen.bBusy AND fbFileOpen.hFile 0 THEN eWriteState := WRITE_EVENT_TRIGGER; END_IF fbFileOpen(bExecute := FALSE); WRITE_EVENT_TRIGGER : eWriteState := FILE_OPEN_TRIGGER; CsvString := CreateCsvString(stEvent := stEventWrittenToFile); fbFilePuts(bExecute := TRUE, sLine := CsvString, hFile := fbFileOpen.hFile); eWriteState := WRITE_EVENT; WRITE_EVENT : IF fbFilePuts.bError THEN eWriteState := ERROR; ELSIF NOT fbFilePuts.bBusy THEN eWriteState := FILE_CLOSE_TRIGGER; END_IF fbFilePuts(bExecute := FALSE); FILE_CLOSE_TRIGGER : fbFileClose(bExecute := TRUE, hFile := fbFileOpen.hFile); eWriteState := FILE_CLOSE; FILE_CLOSE : IF fbFileClose.bError THEN eWriteState := ERROR; ELSIF NOT fbFileClose.bBusy THEN eWriteState := WAIT_FOR_EVENT; END_IF fbFileClose(bExecute := FALSE); ERROR : //Do Nothing END_CASE
Thank you! It took me at least an hour to review the whole code then I realized Jakob also had to trigger twice to append. With your modification the code works as intended.
Physically the methods are actually resided in the same file as the function block. Thanks for becoming a member and supporting creation of new content of this channel!
Thanks MauTau! You will get more and I will also play with hardware when we get to the episode about I/O (this will be part 10) 😊 Thanks for becoming a member!
@@JakobSagatowski Piggybacking off this reply to ask, could you do a video/series/(upload example of) on the general structure of your projects? I'm churning out TwinCat projects and i just wanted to compare how I structure mine to others to see if I could streamline it somehow.
Hey, thank you for this series of video guide ! I have a question however. When you defined the private methode CreateCSVString, you passed the ST_Event as a reference and defined an output. Considering the methode belongs to the FB, shouldn't it have access to the stevent and any variables declared there ? So, couldn't we just create the function without any calls nor return, kind of like a void function in C? Or am I mistaking things ?
Hi Jakob, I have a question: When I go to rebuild the project I have the following alert: "My project" build for platform 'TWINCAT RT (x64)' failed". How I can solve it? Thanks
Hi Jakob, i´ve been following along with your twincat series and your tutorial here. I encountered a problem with my state machine, which I dont understand: I start at CASE TRIGGER_FILE_OPEN, then after setting the trigger I go to FILE_OPEN and then i´m stuck cause, FB_FileOpen.bBusy stays true. Any idea what I did wrong? CASE eWriteState OF TRIGGER_FILE_OPEN : FileOpen(bExecute := TRUE); eWriteState := FILE_OPEN; FILE_OPEN : FileOpen(bExecute := FALSE); IF FileOpen.bError THEN eWriteState := ERROR; ELSIF NOT FileOpen.bBusy AND FileOpen.hFile 0 THEN eWriteState := WAIT_FOR_EVENT; END_IF
With a globally declared Enumeration DUT type, I often create a small state history log so that I can verify the state changes with timestamps. It seems that with the use of local enumerations, you cannot declare a "lastState" variable of that local enumeration type. Is this a small drawback to be aware of when using local enumerations, or do you have a workaround for this minor inconvenience? Thanks for the content @JakobSagatowski!
I think this will not work on every execute Jakob with a simulation it seems that it skips one line after second execute and then writes another line after third execute. Can it be a probelm with task if a task is slow then twincat can handle filewrite better.
The problems you see at the end about not writing a line is an actual bug. The fbPutFile gets stuck if it's only called one time with a false excecute. You can fix it by adding following state in the beginning, or end. Then the code will write every time to the logfile. CLEAR_FILE_FB: fbFileOpen(bExecute := FALSE); fbFilePuts(bExecute := FALSE); fbFileClose(bExecute := FALSE); eWriteState := FILE_OPEN_TRIGGER;
@@pdigeonknight yeah i did figure out the problem so instead of creating a seperate case to clear all FBs i cleared the Fbs every case. but this is also a nice way to program
for example it should work and will not skip the line eWriteState.FileOpen_TRIGGER://open file fbFileOpen(sNetId:='',nMode:=FOPEN_MODEAPPEND OR FOPEN_MODETEXT, sPathName:=sPathName,ePath:=PATH_GENERIC,bExecute:=TRUE); IF NOT fbFileOpen.bBusy THEN IF fbFileOpen.bError THEN eLogWriteState:=eWriteState.ERROR; ELSE fbFileOpen(sNetId:='',bExecute:=FALSE); eLogWriteState:=eWriteState.WAIT_FOR_EVENT; END_IF END_IF
Nice tutorial as always 👍👍👍 I didn't know you could create enums like that. @ 38:00 You could have put this in an string array and concatenated it using a FOR loop.
My guess for why you need to close the file before being able to see it would be that you are only adding the line to the file but you are not actually saving it (or releasing it to be more precise). In the FB_FileClose function block documentation we have the line : "The function block closes the file, thereby putting it in a defined state for further processing by other programs". So you can't open the file in notepad (or otherwise) before the FB_FileClose. What I would love to know is : does TwinCAT saves the file each time or wait until you close it before doing so? If it saves it but doesn't release it, it's good because in case of a potential powerloss we wouldn't lose the log, but we could still keep the file open and go back directly to the "wait for event" if we are not necessarily interessested to get the log of error while the PLC is running. On the other end if it wait for FB_FileClose before doing so, it would be best to close it between each event. I'm not entirely sure of how we could test this however. Thank for the great tutorial, I'm starting a master degree project on a parallel robot that was built with Beckhoff component and your tutorial are perfect for someone like me who doesn't know a lot about this ecosystem. Keep up the good work!
Hey Jakob. Thanks for the great tutorial. At the time 51.15 I'm getting a 'Page Fault' exception. What is this and why I'm getting it? After the error message the line "_PersistentEventStorage.StoreEvent(stEvent := EventBuffer[CurrentEventBufferIndex]);" is highlighted in the editor.
@JakobSagatowski: I got the same issue twice on the same Dell Laptop starting with a fresh Windows system inbetween. Error message: 15.07.2024 23:56:15 245 ms | 'Port_851' (851): Exception (Exception Code: 0xc0000005, Page Fault) in PLC Application HelloWorldPLC Instance, Task PlcTask (RBP: 0xffff838072e6ebb0, RIP: 0xffffb387f518123e, RSP: 0xffff838072e6e960), Area 0, Offset 0x711b6 I checked the EventBuffer and CurrentEventBufferIndex and both are fine and filled with the right arguments. "Error code 0xc0000005 is a common Windows error primarily related to memory access violation" Do you have any idea why referencing the stEvent fails here? best regards and thanks for helping, Jan PS: "A Core Dump created ... is available on the device" is also a message appering but I dont know if it helps? PPS: Do you share your project files somewhere? Then I could check if I missed something in your tutorial (twice).
Hey Jakob! I have problem with TwinCAT DEMO. I can't activate license. When I go to licence manager in field System-Id I have only that number: 00000000 0000 0000 0000 000000000000. I ca'nt start simulation, because log in button is gray. Could you help me, please?
Good course, but it was a really really bad idea to work still at the same code which we used at lecture 2-7. For me who is new to plc programming its starts to blow my mind because this project is so big I don't have any overlook so many files and Functionblock etc.
Hi, I encountered the same problem, I believe it’s something related to the FB_FileClose. UPDATE I fixed by introducing a move to next state only if busy is false in every fb trigger. Hope my explanation was clear enough
Hello Jakob, your lessons are just awesome, I cant describe how it is helpful to me. I've got one question. I did everything what's in the video, but text in the file is missing, all other works. In the method CreateCsvString is this part of the line : STR2 := stEvent.sEventText, which doesn't work. But when I use STR2 := 'stEvent.sEventText' - text stEvent.sEventText is in the file. Do you have any ideas or anybody? Thanks a lot for tutorial and future advice.
Thanks for the great videos! It helped me a lot. When I'm using an actual PLC and not just a simulation in twincat, he con't find the file. Do you have any idea of how I can fix that?
Hello, Can you please help me in this case I have a task in my studies I am completely new in Twincat. My task is CompA runs a TCP server using TwinCAT. CompB runs a TCP Server using Python. Both exchange 32-bit binary data over TCP connection. How to send and receive data packets for every 100ms ?
thank you so much Jakob for this good tutorial, perfect work. Could you kindly add the examples (codes) here or in your blog as Twincat3 file, if no problem.
Thank you! The problem is that I don't have the example code anymore as I've only worked on one VM all the time. I'll upload all the code examples from episode 7 and onward on my GitHub!
Hello Jakob! It's great you've uploaded this because I need it for one of my first projects :) One Question to this: I will use a similar version to this, but will close the file every time I am done writing. I will use several files ("channels") to log different stuff. A new file is supposed to be created on every new day (which I know how to do). I've had this running and all of a sudden I've broken something and can't fix it. My Pathname for FileOpen is 'D:\Events5.log' and using nMode := FOPEN_MODEAPPEND OR FOPEN_MODEPLUS I think I should be able to do this perfectly fine, but my FileOpen gives me Error Code 1804 / 0x70C which means invalid file name / file path. Am I just a little bit too tired to oversee anything obvious? Thanks in advance :)
Hi Felix! First, thanks for becoming a member, highly appreciated. Is the D: drive an actual physical hard-drive that is connected to the PLC? I'm not sure it's possible to write to for example external or USB-drives using TwinCAT. Can you just try to replace the D: with C:?
@@JakobSagatowski thanks for your reply. I'm using a C6920, so C: is my CFast Card and D: is a regular HDD, but it doesn't matter what Drive I am using. I've had it to the point that I could write about 800-1500 log entries before my fbFileOpen would throw an error. I've attempted several different things to debug, but it seems that I've only made it worse. I've tried using different filenames too, but my fbFileOpen still throws the same error code. I've pasted my source code (pastebin.com/kedBbYu4 ) - if you can take the time to take a look at it I'd be more than thankful.
Ok so it had been working, and then just stopped working, without you changing any of the code? Could you please upload the whole project to say a GitHub repo? Then I can take a look at it. Another suggestion is to also publish a question on StackOverflow... then there will be many more people than just me looking at it!
@@JakobSagatowski I've added you to the repo. Please don't be too harsh, I'm still learning! :D You can find the fb under POUs/Utilities/fbFileLog. Stackoverflow is a good point, I'll make sure and create my question on there tomorrow!
I tested your code and it worked perfectly fine. I did no changes. Running it with 3.1.4024.17. Yes, you should always post to StackOverflow as there are many more people there than just me that can answer your questions.
Hi, Jacob. Excellent course. Thank you very much for the work done. I program in Codesys and I've always wondered how different TwinCAT is. In 99% of cases, this is the same thing. The only difference is in the manufacturer's libraries. I have one question for you: What advantages of TwinCAT do you see over CDS, given that Beckhoff Embedde-PC is used against PLC (for example, Festo or Berghof Automotion). And one more suggestion about the course: is it possible to get links to the projects analyzed in the course.
Hi Alexander! Thank you very much for feedback (and for membership support). I fully agree, in 99% it's the same thing. I honestly don't think one is "better" or "worse" than the other. They have both advantages and disadvantages, depending on what you want to achieve and your perspective on things. I for instance prefer to use Visual Studio (TwinCAT) rather than the "Codesys vanilla" IDE. I also like the fact that Beckhoff PLCs are just ordinary PC's, so I can use my "normal" software on them as well without any issues. For other people, I know the tight EtherCAT integration is of big importance, but for me this doesn't matter as much (and nowadays I think the EtherCAT integration in Codesys vanilla is just as good). I unfortunately don't have the source code anymore for the projects as I've been developing on only one machine, but I will make sure to upload the projects on my GitHub from now on (including episode 7 and forward).
Thank you for your answer. EtherCAT works really well on CDS PLC. I used EtherCAT VFD (Schneider Electric) and ADC load cells in my projects. Everything is convenient and comfortable. Did I understand correctly that the OS is installed on the Beckhoff PLC. And do you have access to this OS, for example, to install a database? Also in one of the first videos, you talked about visualization. I understood correctly that on the Beckhoff PLC, you can make an HMI using HTML+CSS, Javascript/Python and link all this, for example, through OPC UA with the PLC program?
Yes you can install whatever you want to the operating system, it's just more or less "standard" Windows (or BSD in case of the TCBSD). I've been running a PLC with a standard PostgreSQL database installed (using TF6420 from Beckhoff to "talk" to it). That is completely correct understood. You can either develop the HMI yourself or use a product such as TE2000 from Beckhoff. Their own HMI can do OPC-UA (though I think you need to pay an additional license for it), but natively it talks Beckhoffs proprietary protocol that is called ADS (that I will talk more about in an upcoming episode of this course).
Hi Ddulek! Thanks for supporting this channel. The code doesn't exist in any repository yet. I did the mistake of never saving any of the code from when I was coding. My plan is to at some point go through all the tutorials myself and then upload all the code to GitHub. Hopefully I will find time for this soon. Cheers.
Thanks so much for all this super helpful content! One question I have is: does code calling a method care if the method takes longer than a single cycle to execute? Outside of OOP I am used to the way that a FB would have to be called every cycle whilst a state machine inside it completed its task. It would seem from this example that a method call doesn't have this same restriction as bBoolean is only true for one cycle?
Hello Jakob as a software developer and a plc developer I wanted to ask you if you think plc programming is future proof. It seems like a lot of code writing can be automated today to a point where the human hand is no longer necessary . What are your opinions on that matter?
I think some of the aspects of software development will be automated (and some already are, look at s/w build automation for example), but for all the other stuff I don't see it happen anytime soon. The stuff that is tedious and doesn't involve learning and that's repetitive I think it makes total sense to automate it.
Hi, Thanks for the Best videos, I can not open file for writing Error is : 0x70C File not found. Invalid file name or file path. I have created file also in the same directory still same error. fbFileOpen: FB_FileOpen:=(sPathName := 'C:\Event.Log',nMode:= FOPEN_MODEAPPEND OR FOPEN_MODETEXT);
⬆Support this channel using the "Thanks" button⬆ or by making a donation through PayPal → www.paypal.com/donate/?hosted_button_id=7FBED5B26KT7S, or by becoming a Patron → www.patreon.com/sagatowski
The problems you see at the end about not writing a line is an actual bug. The fbPutFile gets stuck if it's only called one time with a false excecute.
You can fix it by adding following state in the beginning, or end. Then the code will write every time to the logfile.
CLEAR_FILE_FB:
fbFileOpen(bExecute := FALSE);
fbFilePuts(bExecute := FALSE);
fbFileClose(bExecute := FALSE);
eWriteState := FILE_OPEN_TRIGGER;
Regarding this, where is the stuff about bExecute explained in detail? Not just regarding file access, but in general. Among other things, I'd like to know:
-Can I call e.g. fbFilePuts several times during one cycle? For example, first with bExecute := TRUE and then FALSE.
-What if I try to write new stuff during the same cycle? Does the new just overwrite the old?
-Do I have to call it every cycle to keep it doing whatever it should do, or does the system take care of that after I've called it once?
-I'm guessing the outputs, including the busy state don't update if I don't call it?
Respect for the fact, that instead of cutting off from the video the part when an error has appeared, you showed how to handle with that. And hands up for using ENUM instead of INT. It's much more readable and I do keep forcing that since couple of years in my projects.
Thanks Piotr, and good that you are applying good standards in your projects!
I am surprised to know that we can declare local enum's in Twincat,,,,it's very helpful. Thanks for this tutorial!!
Yes it's a very neat feature!
That is one of my favorite new features!
I highly admire this series and how you actively try to learn beginners how to program the right way. Thank you!
Урок, как всегда на высоте! Спасибо!
The lesson, as always, is on top! Thanks!
Добрый день, хочу поинтересоваться: насколько сильно на практике KRL отличается от ST? Насколько я понял, основной момент в программирование роботов, это то что робот работает не в постоянном цикле (как ПЛК), а просто однократно выполняет вызванную программу/подпрограмму. И в KRL вроде нет всех этих ООПшных плюшек?
You're an absolute hero. The videos are so well done. I hope you continue with PLC programming tips/tricks/guides or other PLC/programming oriented videos, even after this series ends. I'm a new software engineer in the field, your way of thinking and structure is just down my alley, keep it going! You're awesome!
PS: Notice that every video has subtitles that even adds upon what he is saying. ALSO every video has timestamps and is structured. An absolute legend!
Wow thanks for the very kind words! I think it's a very good idea what you suggested. I will really try to upload videos even after the tutorial is finished, as it's really fun to do this. The only limitation is time, as it takes a lot of time to do the videos but thanks to feedback like you gave me I feel much more motivated. Thank you for becoming a member and supporting this channel!
@@JakobSagatowski If it were not for the titles, I would not be able to correctly perceive the material by ear, because I do not speak English properly. The credits are my salvation! Thanks!
Happy to hear that my effort is not in vain 🙃
Thank you for yet another great video. Having been through them all last couple of weeks, I feel this one is getting to the heart of what it needs to make the transition to "thinking in PLC". State machines, executes, enables, waiting for things to happen. That's how I feel at the moment
You got this! If you like this content (and would want to have early access to new videos), please consider becoming a Patron! ( www.patreon.com/sagatowski ). Thanks!
@@JakobSagatowski of course I will consider and I applaud your promotion. I have been doing this learning to see whether it's realistic to move into this tech from conventional s/w engineering, without prior experience. I have an actual opportunity to do that - but is it too high a mountain to climb? This is what I'm exploring. If it looks like a goer, then supporting your site looks like a great step :)
That's exactly my background (started with traditional s/w dev), so I'm 100% certain it's do-able!
million likes for this video. Thank you for this tutorial!
Glad it helped!
This is one of the greatest lessens i have ever seen ! Very good staff great tips and explanations i hope you will show how to create the buffer issue ....
Thank you for this amaizing tutorial!!!!!!!!
Welcome back from a holiday Mr.Jakob!Coincidently,I was doing assignment on CSV file currently. I just sign up as your channel's member to support you. This really helps me a lot!❤️ Thanks :)
Thank you very much for the membership, I'm happy that you could use the CSV logger. And I'm also very happy that you like to use the cat-emojis!
Another great installment. Love the live coding.
Thanks Mark! Yes I too like to watch other people code live... 😊
Hi Jakob. First of all thank you very much for your time and knowledge sharing. Some of my observations are:
[REDITED]
1. We should start at WAIT_FOR_EVENT and once we get the event we will open the file, write to it and close. It is probably better as we just use the file when we need it and not keep it busy all the time.
2. I've been investigatitng a little more the topic of bExecute. Whe just need to put it at the end of each case rather of the begining and everything will work as expected.
Maybe it will help someone. Here is my code:
FUNCTION_BLOCK FB_CsvPersistentEventStorage IMPLEMENTS I_PersistentEventStorage
VAR
fbFileOpen : FB_FileOpen := (sPathName := 'C:\Events.log',
nMode := FOPEN_MODEAPPEND OR FOPEN_MODETEXT);
fbFilePuts : FB_FilePuts;
fbFileClose : FB_FileClose;
eWriteState : (WAIT_FOR_EVENT, FILE_OPEN_TRIGGER, FILE_OPEN, WRITE_EVENT_TRIGGER, WRITE_EVENT, FILE_CLOSE_TRIGGER, FILE_CLOSE, ERROR);
stEventWrittenToFile : ST_Event;
CsvString : T_MaxString;
END_VAR
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CASE eWriteState OF
WAIT_FOR_EVENT :
//Do Anything
FILE_OPEN_TRIGGER :
fbFileOpen(bExecute := TRUE);
eWriteState := FILE_OPEN;
FILE_OPEN :
IF fbFileOpen.bError THEN
eWriteState := ERROR;
ELSIF NOT fbFileOpen.bBusy AND fbFileOpen.hFile 0 THEN
eWriteState := WRITE_EVENT_TRIGGER;
END_IF
fbFileOpen(bExecute := FALSE);
WRITE_EVENT_TRIGGER :
eWriteState := FILE_OPEN_TRIGGER;
CsvString := CreateCsvString(stEvent := stEventWrittenToFile);
fbFilePuts(bExecute := TRUE,
sLine := CsvString,
hFile := fbFileOpen.hFile);
eWriteState := WRITE_EVENT;
WRITE_EVENT :
IF fbFilePuts.bError THEN
eWriteState := ERROR;
ELSIF NOT fbFilePuts.bBusy THEN
eWriteState := FILE_CLOSE_TRIGGER;
END_IF
fbFilePuts(bExecute := FALSE);
FILE_CLOSE_TRIGGER :
fbFileClose(bExecute := TRUE,
hFile := fbFileOpen.hFile);
eWriteState := FILE_CLOSE;
FILE_CLOSE :
IF fbFileClose.bError THEN
eWriteState := ERROR;
ELSIF NOT fbFileClose.bBusy THEN
eWriteState := WAIT_FOR_EVENT;
END_IF
fbFileClose(bExecute := FALSE);
ERROR :
//Do Nothing
END_CASE
Thank you. That was helpful.
Thank you! It took me at least an hour to review the whole code then I realized Jakob also had to trigger twice to append. With your modification the code works as intended.
Thank you for creating this series, I hope you continue with it! Looking forward to the episode about I/O
I'm not going to stop until the series is finished!
Having methods separated into different files within a function block is going to take time to get used to. So far so good!
Physically the methods are actually resided in the same file as the function block. Thanks for becoming a member and supporting creation of new content of this channel!
Please go forward !
Your video is very great!
As always, great video, keep it going. Always awaiting for next video 👍
Thanks Akshay!
Great as always!! we should get Beckhoff to pay that man!!
Amazing material and production of the video, thanks a lot for doing this
We want more!!!! It would be great if you could also play with some hardware eventually.
Thanks MauTau! You will get more and I will also play with hardware when we get to the episode about I/O (this will be part 10) 😊 Thanks for becoming a member!
Local ENums is massivly useful, thanks. I hope they add some way to manage namespaces for structures, etc too..
Yes it's a really great and unfortunately not very well-documented feature!
@@JakobSagatowski Piggybacking off this reply to ask, could you do a video/series/(upload example of) on the general structure of your projects? I'm churning out TwinCat projects and i just wanted to compare how I structure mine to others to see if I could streamline it somehow.
I amazed your programing style!
Great video, thank you for this series!
Thanks Jordan!
Hey, thank you for this series of video guide ! I have a question however. When you defined the private methode CreateCSVString, you passed the ST_Event as a reference and defined an output. Considering the methode belongs to the FB, shouldn't it have access to the stevent and any variables declared there ? So, couldn't we just create the function without any calls nor return, kind of like a void function in C? Or am I mistaking things ?
Hi!
When the next part comes out?
alltwincat.com/2021/06/24/making-of-a-youtube-video/
Hi Jakob,
I have a question:
When I go to rebuild the project I have the following alert: "My project" build for platform 'TWINCAT RT (x64)' failed".
How I can solve it?
Thanks
Hi Jakob, i´ve been following along with your twincat series and your tutorial here. I encountered a problem with my state machine, which I dont understand: I start at CASE TRIGGER_FILE_OPEN, then after setting the trigger I go to FILE_OPEN and then i´m stuck cause, FB_FileOpen.bBusy stays true. Any idea what I did wrong?
CASE eWriteState OF
TRIGGER_FILE_OPEN :
FileOpen(bExecute := TRUE);
eWriteState := FILE_OPEN;
FILE_OPEN :
FileOpen(bExecute := FALSE);
IF FileOpen.bError THEN
eWriteState := ERROR;
ELSIF NOT FileOpen.bBusy AND FileOpen.hFile 0 THEN
eWriteState := WAIT_FOR_EVENT;
END_IF
With a globally declared Enumeration DUT type, I often create a small state history log so that I can verify the state changes with timestamps. It seems that with the use of local enumerations, you cannot declare a "lastState" variable of that local enumeration type. Is this a small drawback to be aware of when using local enumerations, or do you have a workaround for this minor inconvenience? Thanks for the content @JakobSagatowski!
I think this will not work on every execute Jakob with a simulation it seems that it skips one line after second execute and then writes another line after third execute. Can it be a probelm with task if a task is slow then twincat can handle filewrite better.
The problems you see at the end about not writing a line is an actual bug. The fbPutFile gets stuck if it's only called one time with a false excecute.
You can fix it by adding following state in the beginning, or end. Then the code will write every time to the logfile.
CLEAR_FILE_FB:
fbFileOpen(bExecute := FALSE);
fbFilePuts(bExecute := FALSE);
fbFileClose(bExecute := FALSE);
eWriteState := FILE_OPEN_TRIGGER;
@@pdigeonknight, thanks
@@pdigeonknight yeah i did figure out the problem so instead of creating a seperate case to clear all FBs i cleared the Fbs every case. but this is also a nice way to program
for example
it should work and will not skip the line
eWriteState.FileOpen_TRIGGER://open file
fbFileOpen(sNetId:='',nMode:=FOPEN_MODEAPPEND OR FOPEN_MODETEXT,
sPathName:=sPathName,ePath:=PATH_GENERIC,bExecute:=TRUE);
IF NOT fbFileOpen.bBusy THEN
IF fbFileOpen.bError THEN
eLogWriteState:=eWriteState.ERROR;
ELSE
fbFileOpen(sNetId:='',bExecute:=FALSE);
eLogWriteState:=eWriteState.WAIT_FOR_EVENT;
END_IF
END_IF
Nice tutorial as always 👍👍👍
I didn't know you could create enums like that.
@ 38:00 You could have put this in an string array and concatenated it using a FOR loop.
My guess for why you need to close the file before being able to see it would be that you are only adding the line to the file but you are not actually saving it (or releasing it to be more precise). In the FB_FileClose function block documentation we have the line : "The function block closes the file, thereby putting it in a defined state for further processing by other programs". So you can't open the file in notepad (or otherwise) before the FB_FileClose. What I would love to know is : does TwinCAT saves the file each time or wait until you close it before doing so? If it saves it but doesn't release it, it's good because in case of a potential powerloss we wouldn't lose the log, but we could still keep the file open and go back directly to the "wait for event" if we are not necessarily interessested to get the log of error while the PLC is running. On the other end if it wait for FB_FileClose before doing so, it would be best to close it between each event. I'm not entirely sure of how we could test this however.
Thank for the great tutorial, I'm starting a master degree project on a parallel robot that was built with Beckhoff component and your tutorial are perfect for someone like me who doesn't know a lot about this ecosystem. Keep up the good work!
Hey Jakob. Thanks for the great tutorial.
At the time 51.15 I'm getting a 'Page Fault' exception. What is this and why I'm getting it?
After the error message the line "_PersistentEventStorage.StoreEvent(stEvent := EventBuffer[CurrentEventBufferIndex]);" is highlighted in the editor.
@JakobSagatowski:
I got the same issue twice on the same Dell Laptop starting with a fresh Windows system inbetween.
Error message:
15.07.2024 23:56:15 245 ms | 'Port_851' (851): Exception (Exception Code: 0xc0000005, Page Fault) in PLC Application HelloWorldPLC Instance, Task PlcTask (RBP: 0xffff838072e6ebb0, RIP: 0xffffb387f518123e, RSP: 0xffff838072e6e960), Area 0, Offset 0x711b6
I checked the EventBuffer and CurrentEventBufferIndex and both are fine and filled with the right arguments.
"Error code 0xc0000005 is a common Windows error primarily related to memory access violation"
Do you have any idea why referencing the stEvent fails here?
best regards and thanks for helping, Jan
PS: "A Core Dump created ... is available on the device" is also a message appering but I dont know if it helps?
PPS: Do you share your project files somewhere? Then I could check if I missed something in your tutorial (twice).
Hi!
I'm doing the video exercise and at the end the event type is saved as 0, not as an alarm ** Thinking **
Hey Jakob! I have problem with TwinCAT DEMO. I can't activate license. When I go to licence manager in field System-Id I have only that number: 00000000 0000 0000 0000 000000000000. I ca'nt start simulation, because log in button is gray. Could you help me, please?
You can activate test licenses. It's demonstrated in the 2nd or 3rd part of this tutorial.
Good course, but it was a really really bad idea to work still at the same code which we used at lecture 2-7. For me who is new to plc programming its starts to blow my mind because this project is so big I don't have any overlook so many files and Functionblock etc.
Your code is not working properly. Only one in two events is logged. So for eight events, only four are saved.
I wonder why this is so.
Hi, I encountered the same problem, I believe it’s something related to the FB_FileClose.
UPDATE
I fixed by introducing a move to next state only if busy is false in every fb trigger. Hope my explanation was clear enough
Beautiful tutorial👏🏻👏🏻💪 ! Will there be anything in the next regarding the buffer functions topic and FB_FileWrite for event loggers?
Not in the next but possible in a future episode!
@@JakobSagatowski 👍
I think it's also very good to try to write your own buffer as it's a good exercise to develop your skills!
Hello Jakob, your lessons are just awesome, I cant describe how it is helpful to me. I've got one question. I did everything what's in the video, but text in the file is missing, all other works. In the method CreateCsvString is this part of the line : STR2 := stEvent.sEventText, which doesn't work. But when I use STR2 := 'stEvent.sEventText' - text stEvent.sEventText is in the file. Do you have any ideas or anybody? Thanks a lot for tutorial and future advice.
Thanks for the great videos! It helped me a lot. When I'm using an actual PLC and not just a simulation in twincat, he con't find the file. Do you have any idea of how I can fix that?
Hello, Can you please help me in this case I have a task in my studies I am completely new in Twincat.
My task is CompA runs a TCP server using TwinCAT.
CompB runs a TCP Server using Python.
Both exchange 32-bit binary data over TCP connection.
How to send and receive data packets for every 100ms ?
You can use TF6310 for this.
I thought I reported a bug and its fix. I guess I'm imagining things again 😁
thank you so much Jakob for this good tutorial, perfect work. Could you kindly add the examples (codes) here or in your blog as Twincat3 file, if no problem.
Thank you! The problem is that I don't have the example code anymore as I've only worked on one VM all the time. I'll upload all the code examples from episode 7 and onward on my GitHub!
@@JakobSagatowski thanks, it will be very useful. 👍
may I ask for tutorial of library creation in twincat3 please?
Hi! This will be covered in part 11.
Hello Jakob! It's great you've uploaded this because I need it for one of my first projects :)
One Question to this:
I will use a similar version to this, but will close the file every time I am done writing.
I will use several files ("channels") to log different stuff. A new file is supposed to be created on every new day (which I know how to do).
I've had this running and all of a sudden I've broken something and can't fix it.
My Pathname for FileOpen is 'D:\Events5.log' and using nMode := FOPEN_MODEAPPEND OR FOPEN_MODEPLUS I think I should be able to do this perfectly fine, but my FileOpen gives me Error Code 1804 / 0x70C which means invalid file name / file path.
Am I just a little bit too tired to oversee anything obvious? Thanks in advance :)
Hi Felix! First, thanks for becoming a member, highly appreciated. Is the D: drive an actual physical hard-drive that is connected to the PLC? I'm not sure it's possible to write to for example external or USB-drives using TwinCAT. Can you just try to replace the D: with C:?
@@JakobSagatowski thanks for your reply. I'm using a C6920, so C: is my CFast Card and D: is a regular HDD, but it doesn't matter what Drive I am using. I've had it to the point that I could write about 800-1500 log entries before my fbFileOpen would throw an error. I've attempted several different things to debug, but it seems that I've only made it worse. I've tried using different filenames too, but my fbFileOpen still throws the same error code.
I've pasted my source code (pastebin.com/kedBbYu4 ) - if you can take the time to take a look at it I'd be more than thankful.
Ok so it had been working, and then just stopped working, without you changing any of the code? Could you please upload the whole project to say a GitHub repo? Then I can take a look at it. Another suggestion is to also publish a question on StackOverflow... then there will be many more people than just me looking at it!
@@JakobSagatowski I've added you to the repo. Please don't be too harsh, I'm still learning! :D You can find the fb under POUs/Utilities/fbFileLog.
Stackoverflow is a good point, I'll make sure and create my question on there tomorrow!
I tested your code and it worked perfectly fine. I did no changes. Running it with 3.1.4024.17. Yes, you should always post to StackOverflow as there are many more people there than just me that can answer your questions.
Hi, Jacob. Excellent course. Thank you very much for the work done. I program in Codesys and I've always wondered how different TwinCAT is. In 99% of cases, this is the same thing. The only difference is in the manufacturer's libraries. I have one question for you: What advantages of TwinCAT do you see over CDS, given that Beckhoff Embedde-PC is used against PLC (for example, Festo or Berghof Automotion). And one more suggestion about the course: is it possible to get links to the projects analyzed in the course.
Hi Alexander! Thank you very much for feedback (and for membership support). I fully agree, in 99% it's the same thing. I honestly don't think one is "better" or "worse" than the other. They have both advantages and disadvantages, depending on what you want to achieve and your perspective on things. I for instance prefer to use Visual Studio (TwinCAT) rather than the "Codesys vanilla" IDE. I also like the fact that Beckhoff PLCs are just ordinary PC's, so I can use my "normal" software on them as well without any issues. For other people, I know the tight EtherCAT integration is of big importance, but for me this doesn't matter as much (and nowadays I think the EtherCAT integration in Codesys vanilla is just as good).
I unfortunately don't have the source code anymore for the projects as I've been developing on only one machine, but I will make sure to upload the projects on my GitHub from now on (including episode 7 and forward).
Thank you for your answer. EtherCAT works really well on CDS PLC. I used EtherCAT VFD (Schneider Electric) and ADC load cells in my projects. Everything is convenient and comfortable. Did I understand correctly that the OS is installed on the Beckhoff PLC. And do you have access to this OS, for example, to install a database? Also in one of the first videos, you talked about visualization. I understood correctly that on the Beckhoff PLC, you can make an HMI using HTML+CSS, Javascript/Python and link all this, for example, through OPC UA with the PLC program?
Yes you can install whatever you want to the operating system, it's just more or less "standard" Windows (or BSD in case of the TCBSD). I've been running a PLC with a standard PostgreSQL database installed (using TF6420 from Beckhoff to "talk" to it). That is completely correct understood. You can either develop the HMI yourself or use a product such as TE2000 from Beckhoff. Their own HMI can do OPC-UA (though I think you need to pay an additional license for it), but natively it talks Beckhoffs proprietary protocol that is called ADS (that I will talk more about in an upcoming episode of this course).
@@JakobSagatowski Great, I'll be waiting for new videos. Thank you again for your time and experience.
this PLC family program same as high language on PC, they don't use ladder to program ?
You can use ladder too
@@JakobSagatowski this Programing is easy to upgrade with IOT
Hi, it is a really great series! Thank You a lot! Is the code from videos avaible in any repository? If not, would you consider to share it?
Hi Ddulek! Thanks for supporting this channel. The code doesn't exist in any repository yet. I did the mistake of never saving any of the code from when I was coding. My plan is to at some point go through all the tutorials myself and then upload all the code to GitHub. Hopefully I will find time for this soon. Cheers.
Thanks so much for all this super helpful content! One question I have is: does code calling a method care if the method takes longer than a single cycle to execute? Outside of OOP I am used to the way that a FB would have to be called every cycle whilst a state machine inside it completed its task. It would seem from this example that a method call doesn't have this same restriction as bBoolean is only true for one cycle?
Sorry! Answered my own question listening better to your excellent teaching! 45:46. Thanks again for the great content!
Hello Jakob as a software developer and a plc developer I wanted to ask you if you think plc programming is future proof.
It seems like a lot of code writing can be automated today to a point where the human hand is no longer necessary
. What are your opinions on that matter?
I think some of the aspects of software development will be automated (and some already are, look at s/w build automation for example), but for all the other stuff I don't see it happen anytime soon. The stuff that is tedious and doesn't involve learning and that's repetitive I think it makes total sense to automate it.
Hi, Thanks for the Best videos, I can not open file for writing Error is : 0x70C File not found. Invalid file name or file path. I have created file also in the same directory still same error.
fbFileOpen: FB_FileOpen:=(sPathName := 'C:\Event.Log',nMode:= FOPEN_MODEAPPEND OR FOPEN_MODETEXT);
Hi Muhammed! Could you please post your question to StackOverflow? Then others will see it too that might have the same problem.
Where can I get source code from ? Great content!
Hi! I'm working on releasing all the source code to all my Patrons: www.patreon.com/sagatowski
Great videos! will you cover how to implement API's with twincat 3, for read/write?
Hi Theodor! The whole tutorial content is here: alltwincat.com/twincat-3-tutorial/
@@JakobSagatowski just learned that ADS is what I am looking for as far as API's are concerned, and that video is coming up! Can't wait
oop please
What more specifically in OOP do you want me to talk about?
@@JakobSagatowski implementation of oop concepts in twincat with complex examples
@@ahmedatef5563 I'm covering OOP concepts in part 6A and 6B 😃 Enjoy!
@@JakobSagatowski also programming with c++
I'm a little but greedy 😂