Back
Module09
Title

A blending station in SCL

Synthetic Course: written to test the Site template, from no Professor's material

Worked examples

TopicA blending station in SCL
Title

Weighing the hopper in one scan

ExampleW09.1
Step1 / 3
Mode
Given
Given

An S7-300 runs the Blender function block below once a scan. Its three load cells read 00 to 2764827648 for 00 to 500500 kg, and the recipe wants 120120, 8080 and 120120 kg. For each set of raw values, fill in the weight in the hopper, how full the batch is, and how many 2525 kg bags it fills, rounded to the nearest bag.

  • load cells: raw 00 to 2764827648 is 00 to 500500 kg
  • recipe: 120120, 8080 and 120120 kg
  • bags of 2525 kg
One scan, three sets of raw values
raw 1raw 2raw 3totalkgfill%bags
345625924320187.5
648043206480312.5
734445366912339.8

Weigh the silos

The FOR loop scales each load cell with ToKg, kg=raw27648⋅500\text{kg} = \frac{\text{raw}}{27648} \cdot 500, and adds it up: 117.1875+78.125+117.1875=312.5117.1875 + 78.125 + 117.1875 = 312.5 kg.
Sim

The blending station, running

Set the load cells and the buttons, then step a statement or run a whole scan. Each scan calls the Blender block once; the trace shows what every statement decided and wrote.

  1. // A blending station: three silos dose into one hopper, then a mixer runs the batch.
  2. TYPE "Silo"
  3. STRUCT
  4. target_kg : REAL; // the recipe's weight from this silo
  5. raw : INT; // load cell: 0..27648 = 0..500 kg
  6. kg : REAL; // the weight it reads
  7. short : BOOL; // still under its target
  8. END_STRUCT
  9. END_TYPE
  10. DATA_BLOCK "Recipe"
  11. VAR
  12. silo : ARRAY[1..3] OF "Silo";
  13. batches : INT; // batches mixed so far
  14. END_VAR
  15. BEGIN
  16. silo[1].target_kg := 120.0;
  17. silo[2].target_kg := 80.0;
  18. silo[3].target_kg := 120.0;
  19. END_DATA_BLOCK
  20. FUNCTION ToKg : REAL
  21. VAR_INPUT
  22. raw : INT;
  23. END_VAR
  24. BEGIN
  25. ToKg := INT_TO_REAL(raw) / 27648.0 * 500.0;
  26. END_FUNCTION
  27. FUNCTION_BLOCK "Blender"
  28. VAR_INPUT
  29. start : BOOL; // the operator's start button
  30. raw1 : INT; // the three load cells
  31. raw2 : INT;
  32. raw3 : INT;
  33. mixed : BOOL; // the mixer's timer has run out
  34. END_VAR
  35. VAR_OUTPUT
  36. valve : INT; // the silo dosing now, 0 = none
  37. total_kg : REAL; // in the hopper
  38. fill_pct : REAL; // of the batch's weight
  39. bags : INT; // 25 kg bags the hopper fills
  40. mixer : BOOL;
  41. END_VAR
  42. VAR
  43. step : INT; // 0 IDLE, 1 DOSE, 2 MIX
  44. last_start : BOOL; // start, one scan ago
  45. END_VAR
  46. VAR_TEMP
  47. i : INT;
  48. target : REAL;
  49. END_VAR
  50. BEGIN
  51. "Recipe".silo[1].raw := raw1;
  52. "Recipe".silo[2].raw := raw2;
  53. "Recipe".silo[3].raw := raw3;
  54. total_kg := 0.0;
  55. target := 0.0;
  56. FOR i := 1 TO 3 DO
  57. "Recipe".silo[i].kg := ToKg(raw := "Recipe".silo[i].raw);
  58. "Recipe".silo[i].short := "Recipe".silo[i].kg < "Recipe".silo[i].target_kg;
  59. total_kg := total_kg + "Recipe".silo[i].kg;
  60. target := target + "Recipe".silo[i].target_kg;
  61. END_FOR;
  62. fill_pct := total_kg / target * 100.0;
  63. bags := REAL_TO_INT(total_kg / 25.0); // 312.5 kg is 12.5 bags (a Divergence: the exam's answer differs from a real S7)
  64. valve := 0;
  65. CASE step OF
  66. 0: // IDLE: wait for start to rise
  67. IF start AND NOT last_start THEN
  68. step := 1;
  69. END_IF;
  70. 1: // DOSE: open the first silo still short
  71. FOR i := 1 TO 3 DO
  72. IF "Recipe".silo[i].short THEN
  73. valve := i;
  74. EXIT;
  75. END_IF;
  76. END_FOR;
  77. IF valve = 0 THEN
  78. step := 2;
  79. END_IF;
  80. 2: // MIX: run the mixer until its timer runs out
  81. mixer := NOT mixed;
  82. IF mixed THEN
  83. "Recipe".batches := "Recipe".batches + 1;
  84. step := 0;
  85. END_IF;
  86. ELSE
  87. step := 0;
  88. END_CASE;
  89. last_start := start;
  90. END_FUNCTION_BLOCK

Scan 1 · statement 27 of 27

Statement92 last_start := start;
Writtenlast_start := FALSE
VariableValue
step0
valve0
total_kg312.5
fill_pct97.65625
bags12
mixerFALSE
Recipe.silo[1].kg117.1875
Recipe.silo[2].kg78.125
Recipe.silo[3].kg117.1875
Recipe.batches0
LineStatementResult
54"Recipe".silo[1].raw := raw1;Recipe.silo[1].raw := 6480
55"Recipe".silo[2].raw := raw2;Recipe.silo[2].raw := 4320
56"Recipe".silo[3].raw := raw3;Recipe.silo[3].raw := 6480
57total_kg := 0.0;total_kg := 0.0
58target := 0.0;target := 0.0
59FOR i := 1 TO 3 DOinto the loop
60"Recipe".silo[i].kg := ToKg(raw := "Recipe".silo[i].raw);Recipe.silo[1].kg := 117.1875
61"Recipe".silo[i].short := "Recipe".silo[i].kg < "Recipe".silo[i].target_kg;Recipe.silo[1].short := TRUE
62total_kg := total_kg + "Recipe".silo[i].kg;total_kg := 117.1875
63target := target + "Recipe".silo[i].target_kg;target := 120.0
64END_FOR;again
60"Recipe".silo[i].kg := ToKg(raw := "Recipe".silo[i].raw);Recipe.silo[2].kg := 78.125
61"Recipe".silo[i].short := "Recipe".silo[i].kg < "Recipe".silo[i].target_kg;Recipe.silo[2].short := TRUE
62total_kg := total_kg + "Recipe".silo[i].kg;total_kg := 195.3125
63target := target + "Recipe".silo[i].target_kg;target := 200.0
64END_FOR;again
60"Recipe".silo[i].kg := ToKg(raw := "Recipe".silo[i].raw);Recipe.silo[3].kg := 117.1875
61"Recipe".silo[i].short := "Recipe".silo[i].kg < "Recipe".silo[i].target_kg;Recipe.silo[3].short := TRUE
62total_kg := total_kg + "Recipe".silo[i].kg;total_kg := 312.5
63target := target + "Recipe".silo[i].target_kg;target := 320.0
64END_FOR;done
65fill_pct := total_kg / target * 100.0;fill_pct := 97.65625
66bags := REAL_TO_INT(total_kg / 25.0);bags := 12
67valve := 0;valve := 0
68CASE step OF0: line 69
70IF start AND NOT last_start THENFALSE
92last_start := start;last_start := FALSE
Derived
worked out here, no official key: 12.512.5 bags, held as 1212
Divergence
The exam answer is 1313 bags, the Professor's. REAL_TO_INT rounds 12.512.5 to the even number on a real S7, so the CPU holds 1212.