<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Industrial on Ronan's Blog</title><link>https://www.rfontenay.fr/categories/industrial/</link><description>Recent content in Industrial on Ronan's Blog</description><generator>Hugo -- gohugo.io</generator><language>en-en</language><lastBuildDate>Tue, 16 Jan 2024 00:00:00 +0000</lastBuildDate><atom:link href="https://www.rfontenay.fr/categories/industrial/index.xml" rel="self" type="application/rss+xml"/><item><title>PID regulation : Led brightness regulation with Arduino</title><link>https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/</link><pubDate>Tue, 16 Jan 2024 00:00:00 +0000</pubDate><guid>https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/</guid><description>&lt;img src="https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/arduino-PID-regulation.png" alt="Featured image of post PID regulation : Led brightness regulation with Arduino" /&gt;&lt;p&gt;&lt;a class="link" href="https://docs.arduino.cc/libraries/pid/" target="_blank" rel="noopener"
 &gt;PID regulation&lt;/a&gt; : Led brightness regulation with Arduino. To get this done we&amp;rsquo;ll first do a bit of wiring and then program our Arduino.&lt;/p&gt;
&lt;h2 id="led-wiring-and-control"&gt;Led wiring and control
&lt;/h2&gt;&lt;h3 id="wiring"&gt;Wiring
&lt;/h3&gt;&lt;p&gt;Our led is a Yellow led with a 2.4v forward voltage at 20mA.&lt;br&gt;
Our current source (Arduino) delivers 3.3v.&lt;br&gt;
Resistor calculation : R = (3.3v - 2.4 V) / 25 mA = 0.9v / 0.02A = 45Ω&lt;/p&gt;
&lt;p&gt;We’ll wire the cathode to one of the digital I/O of the Arduino. Note, we chose the digital I/O #3 as we’ll need to use PWM (described below).&lt;/p&gt;
&lt;p&gt;As I just had a 47Ω resistor, this will work :&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="411px" data-flex-grow="171" height="732" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/LED-simple.png" srcset="https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/LED-simple_hu_556f4fbc4c710a82.png 800w, https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/LED-simple.png 1254w" width="1254"&gt;&lt;/p&gt;
&lt;h3 id="control"&gt;Control
&lt;/h3&gt;&lt;p&gt;In order to control the brightness of the LED, we’ll use the Pulse-width modulation (PWM), or pulse-duration modulation (PDM) :&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="330px" data-flex-grow="137" height="536" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/PWM.png" width="737"&gt;&lt;/p&gt;
&lt;p&gt;To do this, we’ll use the following function : analogWrite(pin, value)&lt;br&gt;
- pin: the pin to write to.&lt;br&gt;
- value: the duty cycle: between 0 (always off) and 255 (always on)&lt;/p&gt;
&lt;p&gt;Code sample :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;void setup()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pinMode(3, OUTPUT); 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;void loop()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;//Analog write
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;analogWrite(3, 64); 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Results (0, 25%, 75%, 100%) :&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="PWM-0-25-75-100-1.jpg"&gt;&lt;/p&gt;
&lt;h2 id="led-brightness-regulation"&gt;Led brightness regulation
&lt;/h2&gt;&lt;h4 id="sensor"&gt;Sensor
&lt;/h4&gt;&lt;p&gt;We’ll add a light sensor as wired below :&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="290px" data-flex-grow="121" height="1035" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/LED-and-light-sensor.png" srcset="https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/LED-and-light-sensor_hu_e7e3186fe65eb7eb.png 800w, https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/LED-and-light-sensor.png 1254w" width="1254"&gt;&lt;/p&gt;
&lt;p&gt;Just place the sensor in front of the LED:&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="484px" data-flex-grow="201" height="989" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/led-and-light-sensor-picture-assembly.jpg" srcset="https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/led-and-light-sensor-picture-assembly_hu_f624e137c212898f.jpg 800w, https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/led-and-light-sensor-picture-assembly_hu_230051e5c5e3f798.jpg 1600w, https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/led-and-light-sensor-picture-assembly.jpg 1995w" width="1995"&gt;&lt;/p&gt;
&lt;h3 id="regulation"&gt;Regulation
&lt;/h3&gt;&lt;p&gt;In order to regulate, we’ll use a proportional–integral–derivative controller. A PID controller is a control loop feedback mechanism (controller) commonly used in industrial control systems. A PID controller continuously calculates an error value as the difference between a desired setpoint and a measured process variable. The controller attempts to minimize the error over time by adjustment of a control variable.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="521px" data-flex-grow="217" height="738" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/PID.png" srcset="https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/PID_hu_61fc8e91469d82e5.png 800w, https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/PID_hu_590a483b7546d8ee.png 1600w, https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/PID.png 1604w" width="1604"&gt;&lt;/p&gt;
&lt;p&gt;Here is the code :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;PID_v1.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//Variables
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;double&lt;/span&gt; Setpoint, Input, Output;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//PID parameters
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;double&lt;/span&gt; Kp&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, Ki&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, Kd&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//Start PID instance
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PID &lt;span style="color:#a6e22e"&gt;myPID&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;Input, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;Output, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;Setpoint, Kp, Ki, Kd, DIRECT);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setup&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//Start a serial connection to send data by serial connection
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Serial.&lt;span style="color:#a6e22e"&gt;begin&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;9600&lt;/span&gt;); 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//Set point : Here is the brightness target
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Setpoint &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//Turn the PID on
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; myPID.&lt;span style="color:#a6e22e"&gt;SetMode&lt;/span&gt;(AUTOMATIC);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//Adjust PID values
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; myPID.&lt;span style="color:#a6e22e"&gt;SetTunings&lt;/span&gt;(Kp, Ki, Kd);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;loop&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//Read the value from the light sensor. Analog input : 0 to 1024. We map is to a value from 0 to 255 as it&amp;#39;s used for our PWM function.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Input &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;analogRead&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;), &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;255&lt;/span&gt;); 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//PID calculation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; myPID.&lt;span style="color:#a6e22e"&gt;Compute&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//Write the output as calculated by the PID function
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;analogWrite&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;,Output);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//Send data by serial for plotting 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Serial.&lt;span style="color:#a6e22e"&gt;print&lt;/span&gt;(Input);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Serial.&lt;span style="color:#a6e22e"&gt;print&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34; &amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Serial.&lt;span style="color:#a6e22e"&gt;println&lt;/span&gt;(Output); 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;PID Parameters :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Kp accounts for present values of the error (e.g. if the error is large and positive, the control variable will be large and negative).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ki accounts for past values of the error (e.g. if the output is not sufficient to reduce the size of the error, the control variable will accumulate over time, causing the controller to apply a stronger action).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Kd accounts for possible future values of the error, based on its current rate of change.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Arduino 1.6.6 comes with a tool called “Serial plotter”, that might be useful to graph our data:&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="577px" data-flex-grow="240" height="529" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/arduino-plotting-PID.png" srcset="https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/arduino-plotting-PID_hu_8ebe59041c979963.png 800w, https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/arduino-plotting-PID.png 1272w" width="1272"&gt;&lt;/p&gt;
&lt;p&gt;The measured value is note stable, probably due to the PWM. A solution would be to smooth the results by doing an average on the lasts results, in order to filter the high frequency changes.&lt;/p&gt;
&lt;p&gt;Note : You can graph several values at the same time, you just need to send them on the same line, with a space as a delimiter.&lt;/p&gt;
&lt;p&gt;When I disrupt the system with an external light, we clearly see that the system tries to keep the brightness at the setpoint (100) by managing the led control value :&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="646px" data-flex-grow="269" height="371" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/arduino-plotting-PID-external-factors.png" srcset="https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/arduino-plotting-PID-external-factors_hu_cbc6aeb160426c06.png 800w, https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/arduino-plotting-PID-external-factors.png 999w" width="999"&gt;&lt;/p&gt;
&lt;p&gt;To conclude, here is how the system is handling a change from 0 to setpoint, or from setpoint to 0 :&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="480px" data-flex-grow="200" height="375" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/pid-regulation-led-brightness-regulation-with-arduino/arduino-plotting-PID-transition.png" width="750"&gt;&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;re done with PID regulation : Led brightness regulation with Arduino&lt;/p&gt;</description></item><item><title>Siemens PLC simulation with virtual commissioning</title><link>https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/</link><pubDate>Sun, 14 Jan 2024 00:00:00 +0000</pubDate><guid>https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/</guid><description>&lt;img src="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/virtual-commissionning-plc-siemens-s7.png" alt="Featured image of post Siemens PLC simulation with virtual commissioning" /&gt;&lt;p&gt;For Siemens PLC simulation with virtual commissioning we&amp;rsquo;ll use &lt;a class="link" href="https://www.siemens.com/global/en/products/automation/systems/industrial/plc/s7-plcsim-advanced.html" target="_blank" rel="noopener"
 &gt;PLCSIM Advanced&lt;/a&gt; and C# co-simulation.&lt;/p&gt;
&lt;h2 id="configuration"&gt;Configuration
&lt;/h2&gt;&lt;p&gt;We’ll run the simulator and the editor on two computers :&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="370px" data-flex-grow="154" height="450" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/network.png" width="695"&gt;&lt;/p&gt;
&lt;h3 id="simulator-configuration"&gt;Simulator configuration
&lt;/h3&gt;&lt;p&gt;First let’s start an instance with the following parameters :&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="134px" data-flex-grow="55" height="771" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/2_plcsim_advanced_configuration.png" width="431"&gt;&lt;/p&gt;
&lt;p&gt;Once started, it should be like that :&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="135px" data-flex-grow="56" height="771" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/2_plcsim_advanced_running.png" width="435"&gt;&lt;/p&gt;
&lt;h2 id="plc-programming"&gt;PLC Programming
&lt;/h2&gt;&lt;h3 id="hardware-configuration"&gt;Hardware configuration
&lt;/h3&gt;&lt;p&gt;Let’s do a simple configuration as follow :&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="680px" data-flex-grow="283" height="172" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/3_hardware_config.png" width="488"&gt;&lt;/p&gt;
&lt;p&gt;Network configuration :&lt;br&gt;
- PLC_1 : 192.168.1.1/24&lt;br&gt;
- IO device_1 : 192.168.1.2/24&lt;/p&gt;
&lt;p&gt;Note : On the simulator, we have different IP addresses for all the network interfaces : Ethernet adapter, PLCSIM virtual ethernet adapter, PLC and I/Os !&lt;/p&gt;
&lt;p&gt;With the following I/Os :&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="407px" data-flex-grow="169" height="313" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/4_ET200.png" width="531"&gt;&lt;/p&gt;
&lt;p&gt;Note that you’ll need to activate this option in the project settings :&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="937px" data-flex-grow="390" height="201" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/4_simulation_during_compil.png" width="785"&gt;&lt;/p&gt;
&lt;h3 id="program"&gt;Program
&lt;/h3&gt;&lt;p&gt;Our program will be very simple ! OB1 will toggle a bit every second :&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="301px" data-flex-grow="125" height="576" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/OB1-1.png" width="723"&gt;&lt;/p&gt;
&lt;p&gt;And FB1 will do a safety check between the relay output and the input feedback :&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="339px" data-flex-grow="141" height="544" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/FB1.png" width="770"&gt;&lt;/p&gt;
&lt;h3 id="compiling-and-loading"&gt;Compiling and loading
&lt;/h3&gt;&lt;p&gt;You should be able to compile and load :&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="281px" data-flex-grow="117" height="683" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/5_load_program.png" srcset="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/5_load_program_hu_fd51a9d9965a9156.png 800w, https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/5_load_program.png 801w" width="801"&gt;&lt;/p&gt;
&lt;h2 id="simulation"&gt;Simulation
&lt;/h2&gt;&lt;p&gt;As soon as you’ll run the program, you should have an error on the feedback monitoring :&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="240px" data-flex-grow="100" height="492" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/6_fb_error.png" width="492"&gt;&lt;/p&gt;
&lt;h3 id="co-simulation"&gt;Co-simulation
&lt;/h3&gt;&lt;p&gt;To solve this issue, we’ll running co-simulation with C#. The script will check the output value (%Q9.0) and set the feedback (%I0.0) accordingly. We’ll be using sharpdevelop as IDE.&lt;/p&gt;
&lt;h4 id="import-dll"&gt;Import DLL
&lt;/h4&gt;&lt;p&gt;Importing the DLL is easy :&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="560px" data-flex-grow="233" height="702" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/7_import_DLL.png" srcset="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/7_import_DLL_hu_4cfb5b204d97b7f2.png 800w, https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/7_import_DLL_hu_40828d15a56781ad.png 1600w, https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/7_import_DLL.png 1638w" width="1638"&gt;&lt;/p&gt;
&lt;p&gt;Then we write a short program :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; * Created by SharpDevelop.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; */
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;using System;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;using System.Threading;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;using Siemens.Simatic.Simulation.Runtime;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;namespace CPU1515F
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	class Program
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		public static void Main(string[] args)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			Console.WriteLine(&amp;#34;Starting simulation&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			//Use it for local instance
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			//IInstance myInstance = SimulationRuntimeManager.CreateInterface(&amp;#34;Golf8&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			//Use it for remote instance
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			IRemoteRuntimeManager myRemoteInstance = SimulationRuntimeManager.RemoteConnect(&amp;#34;192.168.1.101:50000&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			IInstance myInstance = myRemoteInstance.CreateInterface(&amp;#34;1515F&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			//Update tag list from API
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			Console.WriteLine(&amp;#34;Tags synchronization&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			myInstance.UpdateTagList();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			//Start a thread to synchronize feedbacks inputs 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			Thread tFeedbacks = new Thread(()=&amp;gt;synchroFeedbacks(myInstance));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			tFeedbacks.Start();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			//Allow the user to quit simulation
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			Console.WriteLine(&amp;#34;Simulation running&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			Console.WriteLine(&amp;#34;Press any key to quit . . . &amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			Console.ReadKey(true);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		static void synchroFeedbacks(IInstance myInstance)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			while(true){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				//Keep %I and %Q opposite
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				myInstance.WriteBool(&amp;#34;FB_KA1&amp;#34;, !myInstance.ReadBool(&amp;#34;KA1&amp;#34;));	
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And run it :&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="657px" data-flex-grow="273" height="435" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/8_simulation_running.png" srcset="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/8_simulation_running_hu_a8ab5ee14960c477.png 800w, https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/8_simulation_running.png 1191w" width="1191"&gt;&lt;/p&gt;
&lt;p&gt;Once acknowledged, we should not have any issue.&lt;/p&gt;
&lt;p&gt;Using the trace tool, we can confirm that it’s running perfectly fine, updating the input in around 100ms.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="770px" data-flex-grow="321" height="445" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/Trace1.png" srcset="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/Trace1_hu_28c04f5efa9d9cb3.png 800w, https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/Trace1.png 1429w" width="1429"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="770px" data-flex-grow="321" height="445" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/Trace2.png" srcset="https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/Trace2_hu_1797fb07c6e64169.png 800w, https://www.rfontenay.fr/posts/automation-virtual-commissioning-plcsim-advanced-2-0-with-csharp/Trace2.png 1429w" width="1429"&gt;&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;re done with Siemens PLC simulation with virtual commissioning.&lt;/p&gt;</description></item><item><title>Unrelated parallel machine scheduling optimization with a genetic algorithm</title><link>https://www.rfontenay.fr/posts/unrelated-parallel-machine-scheduling-problem-heuristic-genetic-algorithm/</link><pubDate>Sun, 14 Jan 2024 00:00:00 +0000</pubDate><guid>https://www.rfontenay.fr/posts/unrelated-parallel-machine-scheduling-problem-heuristic-genetic-algorithm/</guid><description>&lt;img src="https://www.rfontenay.fr/posts/unrelated-parallel-machine-scheduling-problem-heuristic-genetic-algorithm/genetic-algorithm-1.png" alt="Featured image of post Unrelated parallel machine scheduling optimization with a genetic algorithm" /&gt;&lt;p&gt;In this article, we will go through the process of unrelated parallel machine scheduling optimization with a genetic algorithm.&lt;/p&gt;
&lt;h2 id="introduction"&gt;Introduction
&lt;/h2&gt;&lt;p&gt;For the Scheduling on Unrelated Parallel Machines proble the goal is to find an jobs/machines assignment to minimize the overall makespan, so the goal is to have the best balance between machines.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="630px" data-flex-grow="262" height="265" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/unrelated-parallel-machine-scheduling-problem-heuristic-genetic-algorithm/Unrelated-parallel-machine-scheduling-problem-1.png" width="696"&gt;&lt;/p&gt;
&lt;figure&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="399px" data-flex-grow="166" height="452" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/unrelated-parallel-machine-scheduling-problem-heuristic-genetic-algorithm/not-balanced-machines.png" width="752"&gt;&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;Not well balanced schedule&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="399px" data-flex-grow="166" height="452" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/unrelated-parallel-machine-scheduling-problem-heuristic-genetic-algorithm/balanced-machines.png" width="752"&gt;&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;Well balanced schedule&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="problem-data"&gt;Problem data
&lt;/h2&gt;&lt;p&gt;For our problem, we will consider n jobs to be assigned on m machines.&lt;/p&gt;
&lt;h3 id="processing-time"&gt;Processing time
&lt;/h3&gt;&lt;p&gt;First, the jobs processing time will be manage as follow :&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="1295px" data-flex-grow="539" height="96" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/unrelated-parallel-machine-scheduling-problem-heuristic-genetic-algorithm/processing-times.png" width="518"&gt;&lt;/p&gt;
&lt;h3 id="job-assignment"&gt;Job assignment
&lt;/h3&gt;&lt;p&gt;We will manage the jobs/machines assignment as follow : If the job j is schedule on machine i then Xij = 1, else Xij = 0.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="299px" data-flex-grow="124" height="373" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/unrelated-parallel-machine-scheduling-problem-heuristic-genetic-algorithm/machines-jobs-assignement-table.png" width="465"&gt;&lt;/p&gt;
&lt;h2 id="genetic-algorithms"&gt;Genetic algorithms
&lt;/h2&gt;&lt;h3 id="introduction-1"&gt;Introduction
&lt;/h3&gt;&lt;p&gt;A &lt;strong&gt;genetic algorithm&lt;/strong&gt; (GA) is a search heuristic that is used to solve optimization and search problems. It is inspired by the process of natural selection and the principles of genetics. The algorithm simulates the process of evolution, where the fittest individuals are selected for reproduction to produce the offspring of the next generation.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how it works in general:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Initial Population&lt;/strong&gt;: The algorithm starts with a randomly generated population of possible solutions (individuals), often represented as strings of binary values, real numbers, or other data structures.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Selection&lt;/strong&gt;: Individuals are selected based on their fitness, which is usually evaluated using a fitness function. The more suitable or &amp;ldquo;fit&amp;rdquo; an individual is for solving the problem, the higher its chance of being selected for reproduction.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Crossover (Recombination)&lt;/strong&gt;: Selected individuals are paired, and their genetic information is combined (crossover) to produce offspring. This mimics the natural genetic recombination that occurs during reproduction.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mutation&lt;/strong&gt;: After crossover, some offspring undergo mutation, where random changes are made to their genetic structure. This introduces variability and helps explore new solutions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Evaluation and Replacement&lt;/strong&gt;: The new generation of solutions is evaluated, and the least fit individuals are replaced by the new, more fit offspring.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Termination&lt;/strong&gt;: The process repeats for several generations or until a termination criterion is met, such as finding a solution with sufficient fitness, a set number of generations, or convergence of the population.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Genetic algorithms are versatile and can be applied to various problems, including optimization, machine learning, scheduling, and engineering design. They are particularly useful for problems where the solution space is large, complex, and not easily navigable by traditional methods.&lt;/p&gt;
&lt;figure&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="1235px" data-flex-grow="514" height="114" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/unrelated-parallel-machine-scheduling-problem-heuristic-genetic-algorithm/genetic-algorithm-structure.png" width="587"&gt;&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;Genetic algorithm data structure&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="309px" data-flex-grow="129" height="247" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/unrelated-parallel-machine-scheduling-problem-heuristic-genetic-algorithm/genetic-algorithm-process.png" width="319"&gt;&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;Genetic algorithm process&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;To find better solutions, the process is:&lt;br&gt;
1- Evaluation: Sort the population based on chromosomes scores (fitness).&lt;br&gt;
2- Selection: Choose the best chromosomes to generate the next population (natural selection).&lt;br&gt;
3- Crossover: Mate the chromosomes between them by mixing their genome.&lt;br&gt;
4- Mutation: As in a natural environment, some genes are changed arbitrarily.&lt;/p&gt;
&lt;h3 id="example"&gt;Example
&lt;/h3&gt;&lt;p&gt;The goal is to give a practical idea of the genetic algorithm operations. We’ll consider a problem with 2 machines (m=2) and 4 jobs (n=4).&lt;/p&gt;
&lt;h4 id="processing-times"&gt;Processing times
&lt;/h4&gt;&lt;figure&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="1831px" data-flex-grow="763" height="49" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/unrelated-parallel-machine-scheduling-problem-heuristic-genetic-algorithm/example-processing-times-table.png" width="374"&gt;&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;Example for processing times&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h4 id="population"&gt;Population
&lt;/h4&gt;&lt;p&gt;Let’s generate 4 chromosomes randomly :&lt;/p&gt;
&lt;figure&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="852px" data-flex-grow="355" height="204" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/unrelated-parallel-machine-scheduling-problem-heuristic-genetic-algorithm/example-population-chromosomes.png" width="725"&gt;&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;Example for population&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h4 id="evaluation"&gt;Evaluation
&lt;/h4&gt;&lt;p&gt;Evaluation of the generated chromosomes :&lt;/p&gt;
&lt;figure&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="1274px" data-flex-grow="530" height="139" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/unrelated-parallel-machine-scheduling-problem-heuristic-genetic-algorithm/example-population-chromosomes-evaluation.png" width="738"&gt;&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;Example for evaluation&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h4 id="selection"&gt;Selection
&lt;/h4&gt;&lt;p&gt;Select only the bests chromosomes, here we’ll choose to keep 75% of the sorted population :&lt;/p&gt;
&lt;figure&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="423px" data-flex-grow="176" height="102" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/unrelated-parallel-machine-scheduling-problem-heuristic-genetic-algorithm/example-population-chromosomes-selection-1.png" width="180"&gt;&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;Example for selection&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h4 id="crossover"&gt;Crossover
&lt;/h4&gt;&lt;p&gt;1 – Choose two random chromosomes in the selected ones (the best ones).&lt;br&gt;
2 – Merge these two chromosomes by mixing their genome.&lt;br&gt;
3 – Store the new generated chromosome in the new population.&lt;br&gt;
4 – Repeat the crossover operation until the new population is fully generated.&lt;/p&gt;
&lt;figure&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="465px" data-flex-grow="193" height="297" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/unrelated-parallel-machine-scheduling-problem-heuristic-genetic-algorithm/example-population-chromosomes-crossover.png" width="576"&gt;&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;Example for crossover&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h4 id="mutation"&gt;Mutation
&lt;/h4&gt;&lt;p&gt;The mutation operation is not systematic. Usually, around 1% of the crossover chromosomes will go through a mutation. During this operation, we will randomly change a gene :&lt;/p&gt;
&lt;figure&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="1300px" data-flex-grow="541" height="108" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/unrelated-parallel-machine-scheduling-problem-heuristic-genetic-algorithm/example-population-chromosomes-mutation.png" width="585"&gt;&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;Example for mutation&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="code-example"&gt;Code example
&lt;/h2&gt;&lt;p&gt;Here is a &lt;a class="link" href="https://www.python.org/" target="_blank" rel="noopener"
 &gt;Python&lt;/a&gt; implementation.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; __author__ = &amp;#39;rfontenay&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; __description__ = &amp;#39;Genetic algorithm to solve a scheduling problem of N jobs on M parallel machines&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; import random
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; import time
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# ******************* Parameters ******************* #
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Jobs processing times
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;jobsProcessingTime = [543, 545, 854, 766, 599, 657, 556, 568, 242, 371, 5, 569, 9, 614, 464, 557, 460, 970, 772, 886,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;69, 423, 181, 98, 25, 642, 222, 842, 328, 799, 651, 197, 213, 666, 112, 136, 150, 810, 37, 620,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;139, 721, 823, 351, 953, 765, 204, 800, 840, 132, 764, 336, 587, 514, 948, 134, 203, 766, 954,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;537, 933, 458, 936, 835, 335, 690, 307, 102, 639, 635, 923, 699, 71, 913, 465, 664, 49, 198, 747,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;931, 124, 41, 214, 246, 954, 676, 811, 295, 977, 100, 316, 453, 903, 50, 120, 320, 517, 441, 874,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;842]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Number of jobs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n = len(jobsProcessingTime)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Number of machines
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;m = 2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Genetic Algorithm : Population size
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;GA_POPSIZE = 256
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Genetic Algorithm : Elite rate
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;GA_ELITRATE = 0.1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Genetic Algorithm : Mutation rate
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;GA_MUTATIONRATE = 0.25
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Genetic Algorithm : Iterations number
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;GA_ITERATIONS = 1000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# ******************* Functions ******************* #
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;def random_chromosome():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Description :Generate a chromosome with a random genome (for each job, assign a random machine).
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input : -Line 2 of comment...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output : Random chromosome.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Jobs assignment : Boolean matrix with 1 line by job, 1 column by machine
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;new_chromosome = [[0 for i in range(m)] for j in range(n)]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# For each job, assign a random machine
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;for i in range(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;new_chromosome[i][random.randint(0, m - 1)] = 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;return new_chromosome
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;def fitness(chromosome):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Description : Calculate the score of the specified chromosome.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;The score is the longest processing time among all the machines processing times.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input : A chromosome.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output : The score/fitness.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;max_processing_time = -1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;for i in range(m):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;machine_processing_time = 0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;for j in range(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;machine_processing_time += chromosome[j][i] * jobsProcessingTime[j]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Save the maximum processing time found
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;if machine_processing_time &amp;gt; max_processing_time:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;max_processing_time = machine_processing_time
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;return max_processing_time
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;def crossover(chromosome1, chromosome2):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Description : Crossover two chromosomes by alternative genes picking.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input : Two chromosome.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output : One chromosome.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;new_chromosome = [[0 for i in range(m)] for j in range(n)]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;for i in range(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Alternate the pickup between the two selected solutions
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;if not i % 2:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;new_chromosome[i] = chromosome1[i]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;else:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;new_chromosome[i] = chromosome2[i]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;return new_chromosome
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;def evolve(population):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Description : Create a new population based on the previous population.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;The new population is generated by mixing the best chromosomes of the previous population.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input : Old population.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output : New population.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;new_population = [[] for i in range(GA_POPSIZE)]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# First : Keep elites untouched
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;elites_size = int(GA_POPSIZE * GA_ELITRATE)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;for i in xrange(elites_size): # Elitism
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;new_population[i] = population[i]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Then generate the new population
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;for i in range(elites_size, GA_POPSIZE):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Generate new chromosome by crossing over two from the previous population
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;new_population[i] = crossover(population[random.randint(0, GA_POPSIZE / 2)],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;population[random.randint(0, GA_POPSIZE / 2)])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Mutate
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;if random.random() &amp;lt; GA_MUTATIONRATE:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;random_job = random.randint(0, n - 1)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Reset assignment
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;new_population[i][random_job] = [0 for j in range(m)]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Random re-assignment
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;new_population[i][random_job][random.randint(0, m - 1)] = 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;return new_population
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# ******************* Program ******************* #
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Measure execution time
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;start = time.time()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Generate an initial random population
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;population = [[] for i in range(GA_POPSIZE)]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;for i in range(GA_POPSIZE):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;population[i] = random_chromosome()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Sort the population based on the fitness of chromosomes
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;population = sorted(population, key=lambda c: fitness(c))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Print initial best makespan
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print “Starting makespan = %03d” % (fitness(population[0]))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;#Iterate
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;for i in range(GA_ITERATIONS):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Sort the population : order by chromosone’s scores.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;population = sorted(population, key=lambda c: fitness(c))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;#Generate the following generation (new population)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;population = evolve(population)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Print the best fitness and the execution time after iterations
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print &amp;#34;Ending makespan = %03d&amp;#34; % (fitness(population[0]))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print &amp;#34;Execution time = %02d s&amp;#34; % (time.time() - start)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You&amp;rsquo;re done with Unrelated parallel machine scheduling optimization with a genetic algorithm&lt;/p&gt;</description></item><item><title>EtherNet/IP simulation on Fanuc Roboguide</title><link>https://www.rfontenay.fr/posts/ethernet-ip-simulation-on-fanuc-roboguide/</link><pubDate>Thu, 11 Jan 2024 00:00:00 +0000</pubDate><guid>https://www.rfontenay.fr/posts/ethernet-ip-simulation-on-fanuc-roboguide/</guid><description>&lt;img src="https://www.rfontenay.fr/posts/ethernet-ip-simulation-on-fanuc-roboguide/fanuc-ethernetip-roboguide-simulation.png" alt="Featured image of post EtherNet/IP simulation on Fanuc Roboguide" /&gt;&lt;p&gt;In order to be able to do EtherNet/IP simulation on &lt;a class="link" href="https://www.fanuc.eu/be/fr/robots/accessoires/roboguide" target="_blank" rel="noopener"
 &gt;Fanuc Roboguide&lt;/a&gt;, we&amp;rsquo;ll go through a few configuration steps.&lt;/p&gt;
&lt;h2 id="ethernetip-introduction"&gt;EtherNet/IP Introduction
&lt;/h2&gt;&lt;p&gt;Ethernet/IP (Ethernet Industrial Protocol) is an industrial communication protocol used in automation systems to connect devices such as programmable logic controllers (PLCs), sensors, actuators, and other industrial equipment. It is based on standard Ethernet and uses the TCP/IP and UDP/IP protocols for communication. It is a widely adopted protocol in industries like manufacturing, automotive, and energy.&lt;/p&gt;
&lt;p&gt;Here are key details about Ethernet/IP:&lt;/p&gt;
&lt;h3 id="protocol-overview"&gt;&lt;strong&gt;Protocol Overview&lt;/strong&gt;
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Standard&lt;/strong&gt;: Ethernet/IP is defined by the ODVA (Open DeviceNet Vendors Association) and is built on the IEEE 802.3 Ethernet standard.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Application Layer&lt;/strong&gt;: It uses the Common Industrial Protocol (CIP) for communication. CIP is the application layer that provides services for devices in industrial automation systems, such as devices connected to ControlNet, DeviceNet, and EtherNet/IP.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Communication Media&lt;/strong&gt;: Ethernet (100Base-TX, 1000Base-T, etc.), using standard Ethernet cables and hardware.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="key-communication-types"&gt;&lt;strong&gt;Key Communication Types&lt;/strong&gt;
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Explicit Messaging&lt;/strong&gt;: Uses TCP/IP to send messages between devices for configuration, diagnostics, and data exchange.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Implicit Messaging (I/O Messaging)&lt;/strong&gt;: Uses UDP/IP for real-time data exchange (e.g., control signals, process data) between devices. This is typically used for high-performance applications where low latency is crucial.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ethernetip-architecture"&gt;&lt;strong&gt;Ethernet/IP Architecture&lt;/strong&gt;
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Devices&lt;/strong&gt;: Ethernet/IP networks consist of various devices like PLCs, I/O modules, HMIs, drives, and sensors. These devices communicate with each other through Ethernet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;I/O Devices&lt;/strong&gt;: The most common devices in Ethernet/IP networks are I/O devices (e.g., sensors and actuators) that use implicit messaging to exchange process data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Controller-to-Device Communication&lt;/strong&gt;: The PLC or controller exchanges data with the field devices via explicit or implicit messaging, depending on the requirements of the application.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="robot-creation-in-roboguide"&gt;Robot creation in Roboguide
&lt;/h2&gt;&lt;p&gt;While doing the robot creation process, install the following options :&lt;br&gt;
- R784 - Ethernet/IP Adapter&lt;br&gt;
- R785 - Ethernet/IP Scanner&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="317px" data-flex-grow="132" height="575" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/ethernet-ip-simulation-on-fanuc-roboguide/fanuc-roboguide-software-options-ethernetip-simulation.png" width="761"&gt;&lt;/p&gt;
&lt;h2 id="network-configuration"&gt;Network configuration
&lt;/h2&gt;&lt;p&gt;Configure the network as shown below.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="297px" data-flex-grow="124" height="543" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/ethernet-ip-simulation-on-fanuc-roboguide/fanuc-roboguide-network-configuration-ethernetip-simulation.png" width="674"&gt;&lt;/p&gt;
&lt;h2 id="enable-specific-variable-for-ethernetip-simulation-in-roboguide"&gt;Enable specific variable for Ethernet/IP simulation in Roboguide
&lt;/h2&gt;&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="200px" data-flex-grow="83" height="819" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.rfontenay.fr/posts/ethernet-ip-simulation-on-fanuc-roboguide/fanuc-roboguide-variable-ethernetip-simulation.png" width="685"&gt;&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;re done with EtherNet/IP simulation on Fanuc Roboguide !&lt;/p&gt;</description></item></channel></rss>