{"id":1809,"date":"2021-01-26T11:33:57","date_gmt":"2021-01-26T17:33:57","guid":{"rendered":"http:\/\/jimlund.org\/blog\/?page_id=1809"},"modified":"2023-08-06T23:18:38","modified_gmt":"2023-08-07T04:18:38","slug":"esp32-kiln-controller","status":"publish","type":"page","link":"https:\/\/jimlund.org\/blog\/?page_id=1809","title":{"rendered":"ESP32 Kiln controller"},"content":{"rendered":"\n<p>This project connects an ESP32 S2 on an ESP32-S2 Saola-1 development board to a Temperature controller, and has WiFi to provide remote monitoring and programming of the kiln.<br><br>The kiln was fit with a Solo SL4848-VR temperature controller connected to two SLR relays that control the kiln coils.<br><br>The SL4848 has RS-485 output, and is connected to a generic RS-485 to serial USART module (MAX485), and then connected to two pins on ESP32 configured as a USART.  The ESP32 communicates using the Modbus protocol with the SL4848.  <\/p>\n\n\n\n<p>The ESP32 is running software written using the Arduino IDE that connects to WiFi and acts as a web server.  The web page shows a graph of the programmed and actual temperature and allows the SL4848 program to be updated.  The ESP32 is powered by a reused wall wart (5V, 800mA output).<\/p>\n\n\n\n<p><strong>TODO<\/strong><br>1. Add current sensors.  Track coil aging and power use.<br>2. Have the ESP32 save programs.<br>3. Record of runs.<br>4. Start as an access point, have user set ssid\/passwd, then connect to the local network for a normal run.<br>5. Done! Show state at top: temp, program segment, time, set point, current draw.<br>6. Adjust PID params to follow temp program better.  [Not really needed.  After auto-setting the PIDs for 500F, 1000F, 1250F, 1500F, and then setting temp points every 30 min, it follows pretty closely on the heating side.]<br><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><strong>Update on setup process, 2022<\/strong><br>1. Add &#8216;Additional Boards Manager&#8217; in Prefs: https:\/\/raw.githubusercontent.com\/espressif\/arduino-esp32\/gh-pages\/package_esp32_dev_index.json<br>2. Install library AsyncHTTPRequest_Generic from library manager.<br>3. Install AyncTCP from git to Arduino\/libraries\/ dir: https:\/\/github.com\/me-no-dev\/AsyncTCP<br>Now it builds!  <br>4. Enable PSRAM in Arduino->Tools.  Use default partition scheme.<br><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><strong>Getting ESP32 dev environment going<\/strong><br>Installed the Arduino IDE, but no support for the S2 board.<br><br>Installing the ESP idf allowed command line programming to work, got the Blink program working. <br><a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/espressif\/esp-idf\/releases\" target=\"_blank\">https:\/\/github.com\/espressif\/esp-idf\/release<\/a><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">mkdir -p ~\/Documents\/Arduino\/hardware\/espressif &amp;&amp; cd ~\/Documents\/Arduino\/hardware\/espressif &amp;&amp; git clone https:\/\/github.com\/espressif\/arduino-esp32.git esp32 &amp;&amp; cd esp32 &amp;&amp; git submodule update --init --recursive &amp;&amp; cd tools &amp;&amp; python get.py<br> <br>git clone https:\/\/github.com\/espressif\/arduino-esp32.git esp32s2 <br>git submodule update --init --recursive<\/pre>\n\n\n\n<p>Then follow these directions to get it to work with the Arduino IDE, <a href=\"https:\/\/www.mischianti.org\/2020\/12\/01\/esp32-s2-pinout-specs-and-arduino-ide-configuration-1\/\">link<\/a>.<br>Download xtensa-esp32s2-elf and the latest esptool, copy to .\/Documents\/Arduino\/hardware\/espressif\/esp32<\/p>\n\n\n\n<p>To get it working with the IDE, tried a few things and finally got it working.<br>\nInstalled the esp32s2 repository with git:<\/p>\n\n\n\n<p>wget https:\/\/github.com\/espressif\/crosstool-NG\/releases\/download\/esp-2020r3\/xtensa-esp32s2-elf-gcc8_4_0-esp-2020r3-macos.tar.gz<br>   wget https:\/\/github.com\/espressif\/esptool\/archive\/v3.0.tar.gz<\/p>\n\n\n\n<p>Run Blink (add &#8220;define LED_BUILTIN 5&#8221;), LED blinks!<br>Run WiFiScan, works!<\/p>\n\n\n\n<p>Date\/Time<br>Got date\/time setting via NTP working with these examples, <a href=\"https:\/\/randomnerdtutorials.com\/esp32-date-time-ntp-client-server-arduino\/\">1<\/a>, <a href=\"https:\/\/gist.github.com\/kuc-arc-f\/fc1f06317f86242c4a980337093a94f2\">2<\/a><\/p>\n\n\n\n<p>Tried several Modbus libraries but they didn&#8217;t work.  Some weren&#8217;t supported on ESP32.  After trying different libraries for a while, I switched the controller to ASCII and started sending requests using my own code.<br>The final step in getting it working was to switch the TX\/DX connection at the RS-485 to USART breakout board.<\/p>\n\n\n\n<p><strong>Hardware<\/strong><br>Solo SL4848-VR (<a href=\".\/pics\/glass\/manuals\/solocontrolm.pdf\">manual<\/a>), $60 on ebay.  Supports Modbus communications over RS-485, supports both RTU and ASCII.<br><br>RS-485 to USART module (<a href=\"https:\/\/www.amazon.com\/gp\/product\/B07YZTGHGG\/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&amp;psc=1\">link<\/a>), 5 for $7.<br><br>ESP32 S2 Saola-1 development board (<a href=\"https:\/\/www.adafruit.com\/product\/4693\">link<\/a>), $14.50.  Docs <a href=\"https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32s2\/hw-reference\/esp32s2\/user-guide-saola-1-v1.2.html#\">link<\/a>.<br>Bare ESP32 S2 module (<a href=\"https:\/\/www.adafruit.com\/product\/4760\">link<\/a>), $4.<br>WiFi uFL antenna (<a href=\"https:\/\/www.adafruit.com\/product\/2308\">link<\/a>), $3<\/p>\n\n\n\n<p><strong>Modbus<\/strong><br>Need to  terminate line at each end.  RS485 can drive about 50 ohms total, or  doubly terminated with 100 ohms.  Typical value is 120 Ohm resistors at  each end.<br>Info: <a href=\"http:\/\/www.simplymodbus.ca\/ASCII.htm\">Modbus ASCII vs Modbus RTU<\/a>, <a href=\"https:\/\/www.rfwireless-world.com\/Tutorials\/Modbus-Protocol-tutorial.html\">Modbus protocol<\/a>, <a href=\"http:\/\/www.simplymodbus.ca\/ASCII.htm\">Modbus ASCII<\/a><br>Modbus ASCII, send each byte as two ASCII hex digits.  One checksum byte, a LRC<\/p>\n\n\n\n<p>To calculate the LRC:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Add up all the data bytes in the message (before converting to ASCII and without the initial colon and final CR\/LF).<\/li><li>Throw away any bits that carry over 8 bits.<\/li><li>Make the result negative (by twos compliment) to get the LRC byte.<\/li><\/ol>\n\n\n\n<p>Example: &#8220;: 01&nbsp; 03&nbsp; 10&nbsp; 00&nbsp; 00&nbsp; 03&nbsp; 7E&nbsp; CR LF&#8221; (without the spaces).<br>: Start of message<br>01 ID<br>03 Read Holding Register<br>10 00 Register address<br>00 03 Request 3 registers<br>7E Checksum byte (incorrect here)<br>CR LF End of message, bytes 0D 0A<br><br>Response example: &#8220;:0103022328AF&#8221; &#8212; ID, request code, bytes in response, data bytes (2328), LRC (AF)<\/p>\n\n\n\n<p><strong>Solo controller setup<\/strong><br> C-sl &#8212; Modbus Protocol (ASCII or RTU)<br> C-no &#8212; Network address (1-247)<br> bps &#8212; Baud rate <br> len &#8212; Bit length (7\/8)<br> Prty  &#8212; Parity (None\/Even\/Odd)<br> Stop &#8212; STOP BIT (1\/2)<br><br>Register conventions:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>The <em>coils<\/em> are numbered from 00001 onward<\/li><li>The <em>input bits<\/em> are numbered from 10001 onward<\/li><li>The <em>input registers<\/em> are numbered from 30001 onward<\/li><li>The <em>holding registers<\/em> are numbered from 40001 onward<\/li><\/ul>\n\n\n\n<p><strong>Type K thermocouples<\/strong><br>Analog Output K-Type Thermocouple Amplifier &#8211; AD8495 Breakout, <a href=\"https:\/\/www.adafruit.com\/product\/1778\">Adafruit $12<\/a><br>&#8220;Its low level output (typically tens of microvolts per \u00b0C) requires amplification.&#8221;<br><a href=\"https:\/\/www.analog.com\/en\/app-notes\/an-1087.html\">AN-1087: Thermocouple Linearization When Using the AD84<\/a><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><strong>Other kilns that could be retrofit <\/strong><br>Orton AutoFire 3000 (<a href=\".\/pics\/glass\/manuals\/AF3000Manual.pdf\">manual<\/a>) has a serial output (Rx\/Tx), could be adapted.  Control language is not documented, Modbus?<\/p>\n\n\n\n<p>Orton AutoFire 4000 (<a href=\".\/pics\/glass\/manuals\/AF4000_Manual_E.pdf\">manual<\/a>).  USB output.  Protocol not documented<\/p>\n\n\n\n<p>Orton AutoFire Slide AF4TS (<a href=\"http:\/\/pics\/glass\/manuals\/AFSlide_Manual_B.pdf\">manual<\/a>).  Same USB output as the AutoFire 4000.<\/p>\n\n\n\n<p>Orton AutoFire Kiln Controller Model AF4X (<a href=\"http:\/\/pics\/glass\/manual\/AF4X_Manual_B.pdf\">manual<\/a>).  &#8220;The controller has a USB interface that outputs TIME, Temperature and Setpoint data.&#8221; &#8220;&#8230;for remote monitoring and datalogging.&#8221;  Not clear if the controller can be programmed remotely.<\/p>\n\n\n\n<p>Skutt KilnMaster Controller (<a href=\"http:\/\/pics\/glass\/manual\/KilnMaster-Manual-2000_2006.pdf\">manual<\/a>).  No documented communication output.<br><br>LinkBoard is available for KilnMaster Kilns (KM and GM Models) (<a href=\".\/pics\/glass\/manuals\/KilnLink-Manual-w-KMT.pdf\">manual<\/a>, <a href=\"https:\/\/skutt.com\/ceramic-kilns\/kiln-upgrades\/linkboard\/\">link<\/a>).  It provides a data interface (over RJ11), likely RS-485, and connects to a KilnLink (<a href=\"https:\/\/skutt.com\/kilnlink-page\/\">link<\/a>), a WiFi gateway to cloud-based monitoring.  Includes Amperage and Voltage Readings by Section along with temp and time.  Programming is not supported<\/p>\n\n\n\n<p>Skutt KMT-1 Touchscreen Controller (manual).  Built-in WiFi.  <\/p>\n\n\n\n<p>Bartlett RTC1000 (<a href=\"http:\/\/pics\/glass\/manuals\/RTC1000_rtctechman.pdf\">manual<\/a>).  Contains SMT600, &#8220;Bartlett Instrument&#8217;s fifth generation kiln controller circuit board&#8221;.  KISS (Kiln Interface Software System). &#8220;KISS is an easy to use interface for programming and monitoring of the controller from a computer.&#8221;  Kiln output is <strong>RS-485<\/strong>.<\/p>\n\n\n\n<p>Bartlett V6-CF (<a href=\".\/pics\/glass\/manuals\/v6cftechnicalmanual.pdf\">manual<\/a>).  &#8220;The series 700 is Bartlett Instrument&#8217;s seventh generation kiln controller board.&#8221; Kiln output is <strong>RS-485<\/strong>.<\/p>\n\n\n\n<p>Bartlett Genesis Model LT3140 Controller (<a href=\".\/pics\/glass\/manuals\/Genesis_Manual_-_Version_3.6.pdf\">manual<\/a>).  Built-in WiFi.  KISS (Kiln Interface Software System). &#8220;10 Pin Housed Header for computer and radio connection.&#8221;<em> <\/em><\/p>\n\n\n\n<p>Make a file system:<br>\/Users\/jimlund\/Downloads\/esp-idf-v4.2.bak\/esp32s2\/tools\/mklittlefs -c \/Users\/jimlund\/Documents\/Arduino\/WiFiServer.modbus.v4.Xhttp\/data -b 4096 -p 256 -d 5 -s 1507328 \/Users\/jimlund\/Documents\/Arduino\/WiFiServer.modbus.v4.Xhttp\/spiffs.bin<br><br>\/Users\/jimlund\/Library\/Arduino15\/packages\/esp32\/tools\/esptool_py\/4.2.1\/esptool &#8211;chip esp32s2 &#8211;port  &#8220;\/dev\/cu.usbserial-1410&#8221; &#8211;baud 921600 &#8211;before default_reset &#8211;after hard_reset write_flash -z 0x290000 \/Users\/jimlund\/Documents\/Arduino\/WiFiServer.modbus.v4.Xhttp\/spiffs.bin<br><br><br><strong>ESP32-S3-WROOM-1<\/strong><br>Trying a ESP32-S3-DevKitC-1-N8R8, ESP32-S3-WROOM-1 Module, Wi-Fi+BT+BLE, 8MB Flash 8MB PSRAM.<br><br><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This project connects an ESP32 S2 on an ESP32-S2 Saola-1 development board to a Temperature controller, and has WiFi to provide remote monitoring and programming of the kiln. The kiln was fit with a Solo SL4848-VR temperature controller connected to two SLR relays that control the kiln coils. The SL4848 has RS-485 output, and is [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1809","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/jimlund.org\/blog\/index.php?rest_route=\/wp\/v2\/pages\/1809","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jimlund.org\/blog\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/jimlund.org\/blog\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/jimlund.org\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jimlund.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1809"}],"version-history":[{"count":13,"href":"https:\/\/jimlund.org\/blog\/index.php?rest_route=\/wp\/v2\/pages\/1809\/revisions"}],"predecessor-version":[{"id":2327,"href":"https:\/\/jimlund.org\/blog\/index.php?rest_route=\/wp\/v2\/pages\/1809\/revisions\/2327"}],"wp:attachment":[{"href":"https:\/\/jimlund.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1809"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}