That calculation will not work the way you expect it to. If PumpFillSpeed is limitied to 0-50 then the only whole number would be 50/50 = 1 everything else is 0.0-0.9999... and since you are using word and integer only 50 would work since there is no representation for mantissa in integer values. Declare a temporary real variable and do the calculation and then do a REAL_TO_WORD in the DRV2Speed assignment.
You need to change it in the "var" section at the top. Ex: "y1 AT %IX0.5 : bool = 0;" -> "y1 AT %QX0.5 : bool = 0;"
It looks like you are trying to write (assign) to inputs (%IX0.x) instead of outputs (%QX0.x).
Use VAR_OUTPUT for pins on the right side or VAR_INOUT for pins on the left side. i cant see any other way.
I miss understood the question. How do you imagine the FBs being reusable if you have hard coded global variables in them? Somehow you need to pass the variables to the FB. I suppose you could pass pointers as inputs to the blocks and modify the dereferenced pointer inside the function block but i cant see the gain in that.
This concept of "OOP" has been around for decades in PLC programming and is a standard way of working when you have more than one identical objects to control. When you create a POU chose typ FB and then you will be able to createinstances of this function block in your program.
How about a CASE statement? Or maybe put the data in an array and loop through it to find the match. This is probably the shortest code. But usually you only write the code once and maybe using brute force IF Else statements is easier to maintain.
Why not always go with the st_MES_Result_SN type, if the only difference is the serial member(?).
Im not sure i understand the question. Do you need to change the structure of the struct or simply swap struct type?
Initializing to zero is always a good idea to be sure variables are empty before a calculation.
Okay so here is the loop(s) needed for the calculation: for i := 1 to 5 do for j := 1 to 5 do for k := 1 to 2 do c[k,i] := c[k,i] + (a[k,j]*b[j,i]); end_for; end_for; end_for;
But C would be a new array, or do you want the array elements of C summed up?
Maybe i do not understand how you want them multiplied? I was thinking of something like this: c := 1; for i := 1 to 2 do for j := 1 to 5 do c := c * a[j] * b[j]; end_for; end_for;
Maybe i do not understand how you want them multiplied? I was thinking of something like this: c := 1; for i := 1 to 2 do for j := 1 to 5 do c := c * a[j] * b[j]; end_for; end_for;
Maybe i do not understand how you want them multiplied? I was thinking of something like this: c := 1; for i := 1 to 2 do for j := 1 to 5 do c := c * a[i] * b[i]; end_for; end_for;
Since you already got the values in arrays cant you just loop through them?
There are a couple of ways to do this. The easiest would be to have a 1 second task that simply move the momentary analog value to another variable. But you should probably add some kind of a filter to the input so that one misread value wont effect the whole reading. If you use an array of 3600 records you will have one hour, then you can shift new values in and old values out of the array and do the calculations. Best would be to initialize the array with the first value and then let the shifting...
An explaination what is happening: When you declare the array it is basically a custom variable type and the input to the function needs to match exactly that even though the second dimension would look the same as a one dimensional array uncompiled.
Ah so the FB instance is embedded in the array, it seems clear now that i re-read everything. It is very difficult to say without seeing the actual code. Have you tried splitting it up so you keep your values in one array and the FB instances in another? Simply call the FB and inserting the values from the first array. If you want everything packaged then maybe look into making a custom STRUCT (user defined type record) that has one setup of what you need, including FB type, and then make an array...
Your login probably has permissions but not neccessarily codesys itself. You have to check what permissions (group) codesys belongs to and if that group has permission to the SPI device.
Are you sure that codesys have (Linux) permissions to access SPI device?
Can you please describe what you want to do in more detail. There might be a risk of xy problem
The SPI "devices" are specific hardware peripherals in the CPU SoC, meaning you cannot change the CS, MOSI, MISO pins to regular GPIO pins. While you can bitbang SPI i doubt it will be efficient to code that in Codesys. Theoretically it should be possible to multiplex the CS line using transistors as gates controlled by GPIO's, however i have not tried this - and it still relies on the specific CS line. For the raspberry pi there is an example project called "PiFace_FB" that uses the SPI drivers...
Thank you for your quick answer Marcel. Great to hear that it will soon be here.
Is there any ETA for this feature? I'm trying to create templates for different control objects (like motors, valves etc) with a popup dialog faceplate to control the object, it would be very nice to be able to move them around instead of having fixed positions.
XML file + Library would be one way if you want to hard code a driver. Otherwise you can do it in logic using the method "SPI_master.transferExt(...)". Then you can define what you want to send and receive at runtime. For example, the messages sent/received will be different for the MCP23017 (Microchip 16xGPIO chip) and MCP3208 (Microchip 8xADC inputs). Look at the example project "PiFace_FB.project" to see how it is used. It is very flexible.
I might be wrong but i am fairly sure codesys is leveraging the same low level linux spi driver as the python library does. A driver for codesys would be equal to the library for python. However there are very flexible drivers that lets you define the protocol yourself to write "soft" drivers in plc code and then feed it to a function.
If you define a new variable as Dint for example you can use: diNewVar := SHL(int1, 16) + int2; real3 := dint_to_real(diMyVar); Ofcourse real3 will still be an integer value in that case. Edit: Im not in front of an IDE right now so i assumed there is an Dint_to_real function, otherwise use a format that is convertable for the "diNewVar".
If you define a new variable as Dint for example you can use: diNewVar := SHL(int1, 16) + int2; real3 := dint_to_real(diMyVar); Ofcourse real3 will still be an integer value in that case.
Otherwise make one block with all the different inputs (int, real, uint etc). Then just use one of the inputs and leave the others at 0 and if input_type > 0 convert to real and do the calculation. Do the same with the outputs, convert the result to every type you want and then you can use whatever you need for the moment. This wont work as return value though.
I feel with you, i had the same frustration with getting the MCP3208 working. However i finally cracked it and when you know how to use the SPI function it is really easy to modify however you want (the opcodes for various SPI slaves are different). Unfortunately im at work now and the example code is in my private pc at home so i wont be able to post it until tonight to give you a little pointers on what to modify to get it working with the MCP3204.
Without knowing further details i would assume that the prevention is only temporary and when you release the forced FALSE it will probably do a calibration cycle. The text in the picture says "..to move up all blinds, which is undesired some times in your absence." - so once you are present again you can do a controlled reset with calibration?
What happens if you write: result := (num01+num02); ?
Nothing special at all. Since the VPN is a tunnel to the local network you wont notice any difference, except the latency compared to being in the local network.
Last spring i used Wireguard VPN to connect Codesys to the controller (RPi Zero) without any problems.
There should be an example project in the installation. Otherwise i think there are examples in the drivers section of codesys forge.
You might want to look into SPI/I2C for GPIO expander chips, like the MCP17S23.
I havent tried that in codesys. I imagine that you first would need two transitions to check whether your "disabled" variable is true or false and then diverge (create a parallel) in the middle of them. (It would be easier to explain it in Swedish). No you dont need to use the else, its there to reduce code if you need to another action if the first statement isnt evaluated true.
First off: ":=" is assignment, dont use it for evaluation. I simply use "if auto_manual then" since its a bool. I think you should look into a parallel branch if your disable condition is enabled.
Do you perform a cyclic I2C already and it is not enough? Or do you only want to read I2C only when there is a change (interrupt) in the slave? If its the latter then you can use a GPIO as input to trigger a I2C read as Morberis said.
Yes saw that now that the key is up for sale again. In my profession for work it would be pocket change but for a hobby its pretty steep. Thanks for the heads up.
Yes i feel more and more that a key might be a good insurance for this. Unfortunately i cant check the price in store right now (no price info during christmas holiday it seems) but on US store it said $45 so i guess that roughly translates into β¬45 without VAT. So suppose i would have lost one license or upgraded hardware it would be break even - thats not much of a gamble.
I will check out that faq when its back. So if i understand it right, once you apply the license its locked to that unique device or are you able to use it with another same type device? Related to this, you will not be able to upgrade from - lets say a pi zero to pi 4 with the same license? Sorry for the many questions, i just want to plan it out right before buying a license.
Thank you for the fast response! Looks very positive. I would never have thought to look in the german section of the forum, my german is very slim at best.
Hello, I have a question regarding the runtime license for the Raspberry PI SL. When reading about the license in store it says: "Licensing via CODESYS Softcontainer is strictly linked to the selected hardware." I assume this applies to all supported Raspberry PI models. When reading about CODESYS key (for license it says the following under disadvantages with Softcontainer: " - No transfer of the license to another device - Loss of the license in case of a defect of the device" So for my case; Lets...
If you know the scan time you can simply implement a counter in ST and count the cycles between the events. Say you have a scan time of 100ms then do: IF event1 THEN Count := Count + 0.1; // Increment by 0.1s END_IF; IF event2 THEN Time := Count; // Set time value to Count Count := 0; // Rsset counter value for next run END_IF; This is just a simple example to give you inspiration.