Recent Posts

Pages: 1 [2] 3 4 ... 10
11
Technical support / Re: Handling more than 1000 #Define entries
« Last post by njlaw on March 08, 2021, 09:42:07 AM »
Hi Gary,

Thank you for all the tips!  In particular, I hadn't considered using another variable reference inside the Value of a #Define entry.  I've also been avoiding using the EEPROM, but might need to look at that since I'm down to 240 free DM addresses and 90 free FP addresses.

Thanks again!

Nathanael Law
12
Technical support / Re: Handling more than 1000 #Define entries
« Last post by garysdickinson on March 06, 2021, 03:42:22 PM »
Nathanael,

You have figured out about the same solution to handling arrays of structures in TBASIC as I did.  So I may not be able to reduce the number of define table entries that you desire.

My approach is slightly different. This is an exert from the #Define table for a single structure. My application has an array of 8 of these structures


Code: [Select]
#   #Define Name        Value
45  FillerArrayBase     1
46  FillerArraySize     10
47  FillerStatus        DM32[y+0]
48  FillerCapacity      DM32[y+1]
49  FillerVolume        DM32[y+2]
50  FillerUllage        DM32[y+3]
51  FillerDvDt          DM32[y+4]
52  FillerTtlDvDt       DM32[y+5]
53  FillerBOL           DM32[y+6]
54  FillerDeliveryVol   DM32[y+7]
55  Delivered           DM32[y+8]
56  FillerReserved09    DM32[y+9]

FillerArrayBase is the index into DM32[] for the first entry of the first data structure.
FillerArraySize is the size of the data structure in 32-bit words.
There are 8 of these structures in the array. The maximum number of structures is defined as MaxFillerN. This allows me to change the size
of the array without having to change any of the CFs that act on the array of structures (there are no hard-coded values in my code for this sort of thing).
 
What I do differently that you is the computation of the index into DM32[] to access a individual member of a structure. I compute the index to the the first member
of the structure that I am interested in and assign this to the variable "y".  This keeps me from making simple mistakes in my coding that will be hard to find during debug.

The variable "y" is set to the starting address of of the "current" data structure once on each loop through the for..next structure.

Code: [Select]
' UpdateStatus - Now that all of the tank measurements have been made, 
'   this function will update the filler status information for each filler.
'
for FillerIndex = 0 to MaxFillerN       ' for each fill point
    ' The variable, "y", is the index into the array of data structures that
    '   represent the state of an individual filler.
    '
    y = FillerArrayBase + FillerIndex * FillerArraySize
   
    ' a mountain of code was deleted out of this function. The missing code
    '   assigned values to the XXXXTemp variables based on the state of 16
    '   fuel tanks that may be connected to the system. the XXXXTemp variables
    '   are defined as locations in DM32[] with the #Define mechanism.
    '
    FillerStatus    = StatusTemp
    FillerVolume    = VolumeTemp
    FillerUllage    = UllageTemp
    FillerDvDt      = DvDtTemp
    FillerTtlDvDt   = TotalizerDvDtTemp
    FillerCapacity  = CapacityTemp

next    ' FillerIndex (next filler)

OK. What might I suggest that you do to cut down on the number of #Define entries?  It sort of depends on how you have structured your program.

If you have 5 different recipes, do you save all five in the EEP?  As you appear to be using a Fx or Tile-based PLC you may have as much as 11K 16-bit words of EEP that you can store the recipes. If this is true, then you only need to access the current active recipe. You could copy the active recipe into a fixed location in DM32[] or you could access the EEP for the active recipe directly.  Load_EEP32[(y+n)] ... where y is that stating index into EEP32 for the active structure and n is the offset within the array.

Another thing that you could do to simplify your life is to store all of the data in the same place. I notice that you have some 32-bit float values and some 32-bit integer values. If you have only a few float values you could:

1. Convert them to scaled integers and save them in DM32[]. Lets say that the float value is 32.467 and your system only needs the number to be accurate to +/-0.1 then save the float      DM32[n] = round(32.467,1) * 10    This is a scaled integer. When you need to use it covert it to what ever units your system actually uses.
2. Save the float value DM32 as a bit pattern.  DM32[n] = Float2Bits(32.467).  When you need to use the value as a float convert it back   BitsFloat(DM32[n]).

By not having to split your recipes between DM32[] and FP[] might make your life a bit simpler(???).

Oh, and you can delete all uses of "THEN" from your if..else statements. "THEN" is purely optional and is purely useless.  Won't save you any execution time or reduce the number of #defines but it might make your .PC7 files a few bytes smaller.

Best regards,

Gary Dickinson
13
Technical support / Re: Handling more than 1000 #Define entries
« Last post by njlaw on March 06, 2021, 11:50:15 AM »
Hi Gary,

If you would be willing to share some snippets, that would be appreciated.  I am already trying to use arrays and offsets (basically like pointer math in C) to reduce the need for #Defines where possible, but any other techniques would be helpful.

E.g.,
Code: [Select]
ingredientMatched = 0
FOR I = 0 TO 5
IF FP[fpSrcStart + CONST_MD_Ingredient_FPOffset + I * CONST_MD_Ingredient_FPLength + CONST_MD_IngredientDosage_FPOffset] > 0.0 OR FP[fpSrcStart + CONST_MD_Ingredient_FPOffset + I * CONST_MD_Ingredient_FPLength + CONST_MD_IngredientMinDosage_FPOffset] > 0.0 OR FP[fpSrcStart + CONST_MD_Ingredient_FPOffset + I * CONST_MD_Ingredient_FPLength + CONST_MD_IngredientMaxDosage_FPOffset] > 0.0 THEN
matched = 0
FOR J = 0 TO 5
IF TestBit(DM16_ActiveComponents1, CONST_ActiveComponents1_Ingredient1 + J) AND CompDMMem(dmSrcStart + CONST_MD_Ingredient_DM16Offset + I * CONST_MD_Ingredient_DM16Length + CONST_MD_IngredientName_DM16Offset, CONST_Ingredient1Name_DM16Addr + J * 8, 8) = 0 THEN
matched = 1
SetBit ingredientMatched, J
ret = CopyDM(dmSrcStart + CONST_MD_Ingredient_DM16Offset + I * CONST_MD_Ingredient_DM16Length, dmDstStart + CONST_MD_Ingredient_DM16Offset + J * CONST_MD_Ingredient_DM16Length, CONST_MD_Ingredient_DM16Length)
ret = CopyFP(fpSrcStart + CONST_MD_Ingredient_FPOffset + I * CONST_MD_Ingredient_FPLength, fpDstStart + CONST_MD_Ingredient_FPOffset + J * CONST_MD_Ingredient_FPLength, CONST_MD_Ingredient_FPLength)
ENDIF
NEXT
IF matched = 0 THEN
SetBit DM16_StageMDErrFlags2, (CONST_StageMDErrFlags2_Ingredient1DoesNotMatch + I)
ENDIF
ENDIF
NEXT

In the above code, fpSrcStart points to the FP address at the start of the recipe that has been pushed from the cloud and fpDstStart points to the FP address of the recipe used in live batches.  (dmSrcStart and dmDstStart work the same way.)  It then goes through all the ingredients in the recipe and matches them to the ingredients loaded into the machine slots, and copies the dosage and other parameters from the recipe to the correct slot for operation.

This way, I don't use #Defines for all the components of each recipe (5 can be loaded into the PLC from the cloud at once), but only need the starting location and relative offsets for all six data structures (5 recipes from the cloud that can be selected at run time by the operator and the live recipe).

Best regards,

Nathanael
14
Technical support / Re: Handling more than 1000 #Define entries
« Last post by garysdickinson on March 06, 2021, 10:46:00 AM »
Nathanal,

I am not an expert on JSON, but I do have a method for making DMxx[] look like an array of data structures and not just a simple array of numeric values.

The approach that I have taken does use the #Define mechanism but does not need as many #Define entries as you are using.  I only use a #Define for each structure member, and the total size of the data structure.

If you are interested, I can post bits of my PLC code and #Define tables at some explanation for how I use the approach.  I have been using this approach for 10+ years, but have not posted it on the forum.

Best regards,

Gary Dickinson
15
Technical support / Handling more than 1000 #Define entries
« Last post by njlaw on March 05, 2021, 02:15:47 PM »
Hello,

I have a program that continues to increase in size and complexity and am now out of #Define entries.  Since this is compiler-side and doesn't actually impact memory usage on the PLCs, 1000 seems like a rather arbitrary limit.  Is there any chance this could be increased?

And since I am sure that someone will be curious why we are using so many #Define entries, I'll try to explain.  We have a little computer (IoT gateway) that is deployed along side the PLCs.  It translates the content of the PLC memory to JSON and sends certain portions of it to the cloud live and certain portions on demand.  It is also able to take JSON documents from the cloud and use them to write to the PLC memory.  As such the program needs to be able to map between PLC memory and the JSON documents.  By using #Define entries for every variable, we are able to update memory addresses and mapping relatively easily: the PLC program stays the same and just by regenerating the #Define table from a database, we can move memory and preserve the mapping to JSON.

E.g. say we have,
DM32Arr_LUT1 | DM32[225]
DM32Arr_LUT2 | DM32[250]

Due to product / program revisions, we need to increase the size of the LUT1 lookup table.  With our system, I can just publish a new #Define table:

DM32Arr_LUT1 | DM32[225]
DM32Arr_LUT2 | DM32[270]

And I don't have to change the code in the TRiLOGI program at all.

Any thoughts or alternatives are welcome.

Best regards,

Nathanael
16
Technical support / Re: undefined interrupt F1616
« Last post by william on March 03, 2021, 11:25:06 AM »
Many thanks. I'll contact support.
17
Technical support / Re: undefined interrupt F1616
« Last post by support on March 02, 2021, 07:53:17 PM »
r71 firmware means that this F1616 PLC is likely about 13 years old and is one of the original F-series PLC. We are glad it is still operational.

However, note that the F1616-BA was EOL quite sometime ago and it was replaced by Fx1616-BA which is a drop in replacement but support more memory as well as floating point operation. The firmware of the original F1616-BA may not upgradable due to some hardware changes to the CPU board. However, it is possible to change out the CPU board of the F1616 to the new CPU board for Fx1616 and that will convert it into a Fx1616-BA. Please contact support@triplc.com to inquire for the option.

The two Nano-10 with r75 firmware are about 11 years old. There is some enhancement in subsequent hardware revision as well. If you are not using FRAM-RTC then the changes would not affect you and they are upgradable without issue even if the hardware is the oldest version. But if you are using FRAM-RTC then upgrading the firmware may affect its operation due to the hardware change. It is best to contact support@triplc.com to discuss if your board's hardware will be affected.
18
Technical support / undefined interrupt F1616
« Last post by william on March 02, 2021, 10:21:04 AM »
I have been running an F1616 plc for many years, and in recent years, occasionally (every 3-6 months) the plc locks up. 
Please see attached screenshot for the error message, Run time error in function #6, DM32 out of range, with the LCD pointing me to line 033B in function 6, which has been commented out. I suspect my firmware version 71 is too old to implement intrdef 100,n,1
If I were to return it, could you check for a hardware fault, and then upgrade this old PLC to the latest firmware?
I would consider also returning two nano-10 r75 plcs in the same package for upgrading to upgradable firmware.
William
 
19
Technical support / Re: Interfacing Thermistors to TRI PLCs
« Last post by garysdickinson on October 14, 2020, 02:54:37 PM »
This message has the .zip version of my spreadsheet.

Gary Dickinson
20
Technical support / Interfacing Thermistors to TRI PLCs
« Last post by garysdickinson on October 14, 2020, 02:50:25 PM »
I am working on a PLC project that needed to use Thermistors for temperature measurements.  This is not a new topic, but for my current application I decided to see if I could do this without the traditional lookup table and linear interpolation algorithms.

My application did not only required accuracy over a range or 30 or 40 degrees C. 

I was able to get the math for converting ADC counts to temperature to a single equation for my application:
 
      y# = x * 2.1095E-2 - 3.3485E+1         

No lookup tables.

So I am sharing how I got to this sort of solution. Perhaps, it would be useful to others.

I have attached the documentation to this message. I will post the Excel spreadsheet on the next message in this thread.

Gary Dickinson
Pages: 1 [2] 3 4 ... 10