Learn how to incorporate specific functions such as ANDP into another function easily. Instead of using PLS(M8011, M0), you can streamline the process by embedding the function like this: RD3A(ANDP(TRUE, M8011), 0, 1, D100). By integrating the ANDP function into the code, you can simplify tasks like reading and writing analog signals. Give it a try on your FX3U controller by adapting the code to suit your setup, replacing analog read/write functions with appropriate alternatives if needed.
We are grateful for all the assistance received in this fantastic community!drbitboy mentioned that there is a swap between the use of D1 and D0 in the ladder and ST versions of the code. This change does not appear to affect the overall operation.
parky expressed some concerns regarding the use of IF statements. It is anticipated that additional code will be added within the IF blocks, including mathematical operations on the ADC values.
goghie shared a suggestion to check the start-up condition and made improvements based on the feedback provided. While trying to enhance the program, different registers were tested for better performance, but the program did not yield the desired results.
In response to drbitboy's inquiry about using LDP and LDF instead of PLS and PLSF, the original poster explained that the former options were initially considered but replaced with the latter when issues arose. Despite implementing suggested changes for edge detection, the program still did not function correctly.
The provided video demonstrates the challenges faced with the FX3U clone ST program. Despite efforts to update registers and optimize clock settings for monitoring, the program did not deliver the expected outcome.
The generated instruction list highlights the steps performed by the program, emphasizing the attempt to read analog input 0 and transmit the result to analog output 0. This detailed breakdown provides insight into the program's execution and potential areas for improvement.
By incorporating the instructions "LDI M8002" and "CJ P2051," the PLC application consistently transitions to line 22, specifically to address P2051, with the exception of the initial scan period.
Below is the code snippet I shared for a simple CJ jump, with instructions such as LD M80001, MOV H0FFF D06, LD M80027, WR3A K0 K0 D014, LD M800015, ANDP M017, OUT M767920, LD M767923, RD3A K0 K1 D130, LD M800031, ANDF M801133, OUT M767936, LD M767939, and WR3A K0 K1 D1.
In my initial attempt, I utilized LDP/LDF, although they were eventually commented out in my original post. However, when facing issues with them, I decided to try PLS/PLF instead. Despite exploring your recommendation for edge detection, the functionality still seems to be ineffective, with the monitor output appearing nonsensical. The video snippet provided illustrates that M1 remains stagnant, even after manually altering its value. Additionally, D0 does not reflect the analog input value while analog output 0 fails to be set (unlike analog output 1). Through the usage of the M8013 one-second clock for reliable monitoring, it is apparent that M1 fails to synchronize with M0's values.
I have a suspicion that the given code is not being executed, as the final instruction does not trigger a change in the value of M1 to match M0. To rectify this, include the statement "real_all := real_all + 1.0;" after "M1 := M0;". Subsequently, insert "real_rising := real_rising + 1.0;" within the "IF M1 AND NOT M0 THEN -END_IF" block, and include "real_falling := real_falling + 1.0;" inside the "IF M0 AND NOT M1 THEN -END_IF" clause. Ensure that all variables (real_all, real_rising, real_falling) are defined as REAL data types. Should my suspicion hold true, these REALs will exhibit no incrementation.
Why not read the analog signals on a timebase instead of every scan? Mitsi displays this feature but it is not necessary. Furthermore, the use of an 'iff' statement is not needed as it is essentially the same as using a pulse trigger in the mathematics section. This can save on resources and streamline the code. I have included a program below that utilizes a PI temperature control loop on a clone device. I have tested this program on a borrowed clone from a friend and it worked successfully. Please note that the only instance where a time-generated pulse is used is within the PI loop, not for the analog signals. Originally, I wrote this program in Function Block Diagram, but my friend preferred a simpler ladder logic layout with multiple instances of the same address instead of branching off one bit.
parky suggested re-evaluating the approach to reading analogs in a timebase and recommended reading them every scan instead. Mitsi displays this, but it is not necessary as the if statement and additional math code are redundant when using a pulse trigger in the math section. Attached is a program demonstrating a PI temperature control loop running on a clone. I borrowed a friend's clone to test it out, and it worked. The only instance where I used a time-generated pulse is in the PI loop, not the analog inputs. Initially, I wrote this in FBD, but my friend preferred a simple ladder on separate rungs, resulting in multiple instances of the same address rather than branching off one bit.
This serves as a proof of concept, and I have a functioning ladder example that I aim to replicate in ST. I want to avoid implementing workarounds without understanding why they are needed, as this could lead to issues when adding more code later on.
When analyzing the code, it appears that the section from line 6 to 15 should only execute once after startup. Surprisingly, this is the only segment of the code that behaves as intended.
Upon further investigation, it seems that the code is not executed properly due to the lack of updates to M1 to match M0. By inserting a statement that increments real_all after setting M1 to M0, and adding statements to increment real_rising and real_falling in their respective conditions, we can monitor the variable changes accurately.
After incorporating these changes, it is evident that the blocks following "IF M8002 THEN" are not being executed, even when manually toggling M1. While it is common to use integer types for debugging in C/C++, using REAL types for this purpose in PLC might be new to some. In my attempt to troubleshoot, placing the rising/falling edge code inside an ELSE block showed some progress.
By adjusting the code to read analog input into D0 and observing the increment in 'real_rise,' it becomes apparent that this occurs at the scan rate rather than a one-second period. Subsequently splitting the falling edge blocks into their ESLIF block and replicating the M1 := M0; statement for each led to a regression in functionality, with only the startup block operating correctly.
Considering these challenges, it might be time to replace the clone with a real PLC that fully supports ST, has analog inputs, and comes with free or affordable software. The plethora of options available in the market can be overwhelming, but finding a budget-friendly device with the required features is essential for seamless operations.
mikeromeo mentioned that the lines (* IF LDP(TRUE, M8011) THEN *) and (* IF LDF(TRUE, M8011) THEN *) are currently commented out in the FX3U PLCs. This could potentially explain why the code is not functioning as intended. Although I am not experienced with FX3U PLCs, it appears that these lines need to be uncommented for proper functionality.
During testing, it was discovered that the blocks following "IF M8002 THEN" were not being executed, even when manually toggling M1 through the watch window. Is there a specific reason for using the REAL type in debug code like this? In C/C++, integers are commonly used for debugging purposes, but I am still learning about PLCs.
The issue lies in the fact that the entire section of code is not being called or evaluated by the PLC in the main program. If these statements are not executed by the PLC, they will not have any impact on the logic. REALs were chosen to prevent overflow issues, as the counters will stop incrementing at approximately 16 million. This limit is acceptable for diagnostic purposes and avoids potential CPU faults that can occur when incrementing integers on certain PLCs.
While compiling, I encountered multiple errors. Real_xx variables could not compile due to "real" being a reserved word. It is recommended to use them as global variables instead of local. Additionally, there was a compiler error with the IF/Else statement as it was incorrect. Setting the output to full scale on the first scan may lead to issues if connected to an analogue sensor, resulting in it being overwritten. Consider whether it will ever reach overscale if not connected.
Levi G mentioned his lack of experience with FX3U Plc's, noting that certain lines of code were commented out in the original post. This could be the reason why the code is not functioning as intended. Levi commented out the lines because they were not yielding the desired results, and instead tried using PLS/PLF instructions, which also did not work as expected.
Responding to Levi's comment, drbitboy explained that he opted for REALs to avoid any potential issues with overflow. He pointed out that using REALs ensures that the counters will stop incrementing at around 16M (224), preventing any problems with overflow. This strategy helps prevent a CPU fault, which can occur when incrementing integers on certain PLCs. It's important to be aware of the possibility of overflow causing faults, so thanks for sharing this information.
Parky mentioned that during the compilation process, several errors were encountered. The variables named Real_xx could not compile due to the reserved word "real". It is recommended to use these variables as global rather than local. Additionally, there was a compiler error produced by the IF/Else statement, which was incorrect.
The question arises as to why the output is set to full scale on the first scan. This may cause issues if connected to an analog sensor, potentially overwriting data. Adjusting the output in this manner may prevent it from reaching overscale.
In this particular test, one of the analog outputs is set to full scale to serve as a 10V reference voltage source. While this may not be suitable for a real-world application, it allows for the simulation of a sensor using a potentiometer.
By setting the variables as globals with lowercase names, the compilation process proceeded without any warnings. It is interesting that this approach worked, prompting the inquiry about the version number of GX Works 2 being used. The decision to use this FX3 clone was influenced by access to a loaner laptop from work already equipped with GX Works 2.
While variable names may vary between versions, in my version (1.620), using a variable name that is the same as an instruction (first word) will not compile. However, if it is a subsequent word (text), it is allowed. In some early GXIEC versions, you could use the same name for input variables on function blocks as the variable passed to it. In GXWorks, this option can be set, especially when converting the GXIEC file. The issue with your code not working properly is not due to the GXW version. When I compiled the code, there were errors with IF statements. By removing the else statement and adding 'not M8002' in the call to read analog, the issue was resolved. Disabling other logic like reading or outputting analogs on the first scan may not make a noticeable difference due to the speed of the scan. However, it is a good practice for setting or controlling outputs. In a better version of the code, unnecessary code for creating rising and falling edges was removed as LDP and LDF functions can be used instead. Removing the else statement is also recommended as evaluating the falling edge does not require it and only adds unnecessary code. It is common to overlook such mistakes initially, but revisiting the code can help in identifying and eliminating unnecessary code.
Once more, I'll reiterate: the issue lies not in the code itself, but in the failure to execute the complete statements routine, resulting in a lack of evaluation. This discrepancy is clearly evident in the video provided. When it comes to variable naming conventions, consider using REEL_ instead of REAL_.
By making the changes above, the code functions smoothly, as evidenced by the increasing status. It has been demonstrated that simply adding a character before a real number allows for compilation. While there may be an option in GXW2 that permits the use of reserved words, I have not come across it. The software only seems to allow the same symbolic name to be used for local and inout variables in Function Blocks (FBs).
Based on the original poster's messages, it appears that they are utilizing global variables. However, if these globals have been allocated to specific D registers, it is important to note that each register is 16 bits. Therefore, assigning D100 to Real_rise and D101 to Real_Fall would overwrite the second register and potentially display "NAN" (not a number).
It is unnecessary to use IF/END_IF statements with jumps. Instead, create the necessary oneshots and utilize the built-in functions to enable calls to those functions. For example, instead of using an IF statement like IF xxxxx, create the required oneshot: M0 := LDP[TRUE,M8013] AND NOT M8002. Then, implement each function like WR3A[ M0,0,0,D0]. This streamlines the code and eliminates unnecessary complications like jump commands in the compiled code.
I successfully programmed my device on a clone without encountering any issues. Even though I used a different device, borrowed from a friend, I tested various functions and found that they work perfectly. It's worth noting that the clone my friend lent me has a transistor output instead of a relay. I was initially unsure if certain features would work as they do on a genuine device, but after testing the PLSY function (specific to transistor outputs), everything performed as expected. It's important to mention that the transistor output on the clone operates as NPN, meaning it acts as a sink rather than a source, with the common being at 0v.
Parky suggested changing the code as mentioned earlier. It seems to be functioning properly based on the incrementing status. However, this solution does not seem to work on my FX3 clone. The issue persists, with the IF blocks not being executed and the debug variables not increasing. It is puzzling how the ladder program can function correctly if the clone is running faulty firmware. If possible, could you share the compile output (instruction list) for the provided program? I have attached my output for reference.
mikeromeo suggested that the IF blocks are not executed and the debug variables remain unchanged. How do FX/Mitsubishi devices segregate tasks and routines? Could this code be integrated into the main continuous task to ensure execution? Have you verified that the PLC is operating in RUN mode?
I am certain that the PLC is in run mode as indicated by the illuminated RUN LED, and the ladder diagram functions properly in this state. Despite manually switching the PLC before and after programming and using GX Works to handle the run mode automatically, the outcome remains consistent. The initial IF block executes correctly as evidenced by the analog output being set to 10v. It's worth noting that in the ST compile output, I observe the expected conditional jumps associated with IF blocks. However, within the ladder project, the option to "View compile output" is not available. Instead, instructions can be exported as a CSV file (attached), revealing a lack of jumps. This discrepancy raises doubts about the completeness of the export feature, leaving room for potential issues in the code execution.
Consider moving the statement "W_all := W_all + 1.0;" to the beginning of the routine outside of any loops, and incorporating a few more updates such as "W_2 := W_2 + 1.0;" before the conditional statement "IF LDP...", "W_3 := W_3 + 1.0;" before "IF LDF...", and "W_4 := W_4 + 1.0;" after the last "END_IF". By ensuring that the initial IF-END_IF block executes as expected, we can troubleshoot potential issues with the other statements. While it is uncommon to suspect compiler or hardware bugs with simple code, it is essential to verify all possibilities.
In ladder programming, jumps to subroutines are not used. ST programming language uses jumps because of the presence of IF statements. Mitsubishi designed GXW2 compiler to be compatible with ladder/IL, which results in the use of conditional and unconditional calls to subroutines and the utilization of intermediate "Reserved" bits/words, typically in the M9000 range. It is important to ensure that floats are double words, assigned as globals and not overlapping. When using consecutive D registers for floats, such as My_Float and float1, it is crucial to allocate two 16-bit words per tag for proper functioning. For example, My_Float should be assigned as Single precision, occupying D20 (D20 + D21), while float1 should be assigned as Single precision, using D22 (D22 + D23).
I have borrowed a clone from a friend to test some code, and it seems that the original code designed for a true FX does not function properly on the clone. After thorough testing, I have found an alternative solution that works on the clone. However, there are some issues to be mindful of. The IF statements seem to not work correctly, possibly due to differences in how the clone handles conditional jumps. To address this, I have eliminated the IF statements in the code.
Additionally, the analogue output on the clone may be unreliable, as it does not output a full 10v. Even when powered by a 22v PSU, the maximum output is only 9.68v. If values exceed HFFF (4095 Dec) or 10v, the output drops to zero. Therefore, testing for overrange may not be accurate.
I have integrated the logic for rising and falling edge triggers directly into the function calls to address this issue. While Mitsubishi suggests using one scan triggers for read/write operations, it is not essential for other logic or comparing values. I recommend avoiding the use of ST with IF statements (CJ) on the clones.
Please refer to the included running screen capture and the actual file for more details.
When connecting online with a cloned PLC and accessing PLC Diagnostics, it is important to check the CPU version information. I recently encountered a situation where a customer unknowingly purchased a fake Mitsubishi FX2N PLC from eBay with a CPU version of V2 (or V2.1), which did not support many standard instructions. It is crucial to be aware of the authenticity of the PLC to avoid compatibility issues and malfunctioning.
Parky mentioned that after borrowing a friend's clone, he discovered that the original code designed for a true FX did not function properly on the clone. After thorough testing, he found an alternative solution that eliminated the need for IF statements, which were not working correctly due to possible issues with the clone's support for conditional jumps. Additionally, he noted that the analogue output was not stable, maxing out at 9.68v instead of 10v. Overreaching 4095 Dec or 10v caused it to drop to zero. To address these issues, he integrated logic directly into function calls for rising and falling triggers. He emphasized that for normal programming tasks, there is no need for these triggers, except for specific speed requirements. He recommended avoiding ST with IF statements (CJ) on clones.
Goghie, on the other hand, shared his experience with a fake Mitsubishi FX2N PLC that lacked support for standard instructions due to a lower CPU version. He advised checking the CPU version in PLC Diagnostics when using a clone. In his case, the CPU version displayed as 0.0, indicating potential limitations in instruction support. There were no reported errors during program execution, suggesting that the clone may be silently ignoring unsupported instructions.
As Parky considers trying OpenPLC to address the issues with the clone, he acknowledges the learning experience gained from troubleshooting the lower level operations of these devices. Despite encountering challenges with the clone's analog outputs, such as a full-scale voltage of around 10.26v, he remains determined to find a solution.
I have a suspicion that the power supply unit (PSU) I borrowed may have been intended for charging small electronics or devices. Although I did not measure the exact voltage, it was labeled as 22v, which likely decreases under load. I found it interesting that the analog output reached a maximum count of 4095, equivalent to 9.68v in my case. However, when the count reached 4096, the voltage dropped to around 14mv, indicating a potential negative number in terms of conversion. This is due to the 12-bit analog-to-digital conversion outputting effectively zero. My analog input proved to be accurate when tested against a calibrated voltage source. I plan to investigate why the CJ instructions only seem to work with one CJ and not with additional ones. I suspect there may be differences between the clone version and older firmware versions compared to more up-to-date FX3's.