<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title><![CDATA[Smart Home Automation Forum - Portal]]></title>
		<link>https://www.kincony.com/forum/</link>
		<description><![CDATA[Smart Home Automation Forum - https://www.kincony.com/forum]]></description>
		<pubDate>Tue, 01 Sep 2026 10:36:37 +0000</pubDate>
		<generator>MyBB</generator>
		<item>
			<title><![CDATA[[arduino code examples for CO16]-10 ST7789 TFT color display]]></title>
			<link>https://www.kincony.com/forum/showthread.php?tid=9791</link>
			<pubDate>Mon, 31 Aug 2026 08:16:23 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://www.kincony.com/forum/member.php?action=profile&uid=1">admin</a>]]></dc:creator>
			<guid isPermaLink="false">https://www.kincony.com/forum/showthread.php?tid=9791</guid>
			<description><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#include &lt;Adafruit_GFX.h&gt;<br />
#include &lt;driver/gpio.h&gt;<br />
#include &lt;driver/spi_master.h&gt;<br />
#include &lt;esp_heap_caps.h&gt;<br />
<br />
namespace {<br />
<br />
// CO16 ST7789 (GMT020-02-7P) pin mapping from kcs_co16.h.<br />
constexpr gpio_num_t kTftSclk = GPIO_NUM_11;<br />
constexpr gpio_num_t kTftMosi = GPIO_NUM_10;<br />
constexpr gpio_num_t kTftMiso = GPIO_NUM_12;<br />
constexpr gpio_num_t kTftCs = GPIO_NUM_4;<br />
constexpr gpio_num_t kTftDc = GPIO_NUM_0;<br />
constexpr gpio_num_t kTftReset = GPIO_NUM_5;<br />
constexpr gpio_num_t kTftBacklight = GPIO_NUM_40;<br />
<br />
constexpr int16_t kDisplayWidth = 320;<br />
constexpr int16_t kDisplayHeight = 240;<br />
constexpr int16_t kTransferChunkHeight = 10;<br />
constexpr uint32_t kDisplaySpiFrequency = 20 * 1000 * 1000;<br />
constexpr uint8_t kCo16Madctl = 0x68;  // MX | MV | BGR.<br />
<br />
constexpr uint16_t kBlack = 0x0000;<br />
constexpr uint16_t kBlue = 0x001F;<br />
constexpr uint16_t kRed = 0xF800;<br />
constexpr uint16_t kGreen = 0x07E0;<br />
constexpr uint16_t kCyan = 0x07FF;<br />
constexpr uint16_t kMagenta = 0xF81F;<br />
constexpr uint16_t kYellow = 0xFFE0;<br />
constexpr uint16_t kWhite = 0xFFFF;<br />
<br />
class Co16St7789 : public Adafruit_GFX {<br />
 public:<br />
  Co16St7789() : Adafruit_GFX(kDisplayWidth, kDisplayHeight) {}<br />
<br />
  bool begin() {<br />
    gpio_reset_pin(kTftCs);<br />
    gpio_set_direction(kTftCs, GPIO_MODE_OUTPUT);<br />
    gpio_set_level(kTftCs, 1);<br />
<br />
    gpio_reset_pin(kTftDc);<br />
    gpio_set_direction(kTftDc, GPIO_MODE_OUTPUT);<br />
    gpio_set_level(kTftDc, 1);<br />
<br />
    gpio_reset_pin(kTftBacklight);<br />
    gpio_set_direction(kTftBacklight, GPIO_MODE_OUTPUT);<br />
    gpio_set_level(kTftBacklight, 0);<br />
<br />
    spi_bus_config_t busConfig = {};<br />
    busConfig.sclk_io_num = kTftSclk;<br />
    busConfig.mosi_io_num = kTftMosi;<br />
    busConfig.miso_io_num = kTftMiso;<br />
    busConfig.quadwp_io_num = -1;<br />
    busConfig.quadhd_io_num = -1;<br />
    busConfig.max_transfer_sz =<br />
        kDisplayWidth * kTransferChunkHeight * sizeof(uint16_t);<br />
<br />
    esp_err_t err =<br />
        spi_bus_initialize(SPI3_HOST, &amp;busConfig, SPI_DMA_CH_AUTO);<br />
    if (err != ESP_OK) {<br />
      Serial.printf("SPI3 initialization failed: %s&#92;n", esp_err_to_name(err));<br />
      return false;<br />
    }<br />
<br />
    spi_device_interface_config_t deviceConfig = {};<br />
    deviceConfig.clock_speed_hz = kDisplaySpiFrequency;<br />
    deviceConfig.mode = 0;<br />
    deviceConfig.spics_io_num = -1;<br />
    deviceConfig.queue_size = 1;<br />
<br />
    err = spi_bus_add_device(SPI3_HOST, &amp;deviceConfig, &amp;spiDevice_);<br />
    if (err != ESP_OK) {<br />
      Serial.printf("ST7789 SPI device setup failed: %s&#92;n",<br />
                    esp_err_to_name(err));<br />
      return false;<br />
    }<br />
<br />
    drawBuffer_ = static_cast&lt;uint8_t*&gt;(heap_caps_malloc(<br />
        kDisplayWidth * kTransferChunkHeight * sizeof(uint16_t),<br />
        MALLOC_CAP_DMA));<br />
    if (drawBuffer_ == nullptr) {<br />
      Serial.println("ST7789 DMA buffer allocation failed");<br />
      return false;<br />
    }<br />
<br />
    // GPIO5 is shared with the optional LoRa module. Match the working KCS<br />
    // firmware and issue one reset pulse before initializing the controller.<br />
    gpio_reset_pin(kTftReset);<br />
    gpio_set_direction(kTftReset, GPIO_MODE_OUTPUT);<br />
    gpio_set_level(kTftReset, 1);<br />
    delay(1);<br />
    gpio_set_level(kTftReset, 0);<br />
    delay(1);<br />
    gpio_set_level(kTftReset, 1);<br />
    delay(10);<br />
<br />
    if (!initializeController()) {<br />
      return false;<br />
    }<br />
<br />
    fillScreen(kBlack);<br />
    delay(120);<br />
    if (!writeCommand(0x29)) {  // Display on.<br />
      return false;<br />
    }<br />
    delay(120);<br />
<br />
    gpio_set_level(kTftBacklight, 1);<br />
    initialized_ = true;<br />
    return true;<br />
  }<br />
<br />
  void drawPixel(int16_t x, int16_t y, uint16_t color) override {<br />
    fillRect(x, y, 1, 1, color);<br />
  }<br />
<br />
  void writePixel(int16_t x, int16_t y, uint16_t color) override {<br />
    fillRect(x, y, 1, 1, color);<br />
  }<br />
<br />
  void fillRect(int16_t x, int16_t y, int16_t width, int16_t height,<br />
                uint16_t color) override {<br />
    if (x &lt; 0) {<br />
      width += x;<br />
      x = 0;<br />
    }<br />
    if (y &lt; 0) {<br />
      height += y;<br />
      y = 0;<br />
    }<br />
    if (x + width &gt; kDisplayWidth) {<br />
      width = kDisplayWidth - x;<br />
    }<br />
    if (y + height &gt; kDisplayHeight) {<br />
      height = kDisplayHeight - y;<br />
    }<br />
    if (drawBuffer_ == nullptr || width &lt;= 0 || height &lt;= 0) {<br />
      return;<br />
    }<br />
<br />
    const uint8_t high = color &gt;&gt; 8;<br />
    const uint8_t low = color;<br />
    for (int16_t row = y; row &lt; y + height;<br />
       &nbsp;&nbsp;row += kTransferChunkHeight) {<br />
      const int16_t chunkHeight =<br />
          min&lt;int16_t&gt;(kTransferChunkHeight, y + height - row);<br />
      const size_t pixelCount = width * chunkHeight;<br />
      for (size_t index = 0; index &lt; pixelCount; ++index) {<br />
        drawBuffer_[index * 2] = high;<br />
        drawBuffer_[index * 2 + 1] = low;<br />
      }<br />
<br />
      if (!setWindow(x, row, x + width, row + chunkHeight) ||<br />
          !writePixels(drawBuffer_, pixelCount * sizeof(uint16_t))) {<br />
        Serial.println("ST7789 pixel transfer failed");<br />
        return;<br />
      }<br />
    }<br />
  }<br />
<br />
  void writeFillRect(int16_t x, int16_t y, int16_t width, int16_t height,<br />
                   &nbsp;&nbsp;uint16_t color) override {<br />
    fillRect(x, y, width, height, color);<br />
  }<br />
<br />
  bool initialized() const { return initialized_; }<br />
<br />
 private:<br />
  bool transmit(const void* data, size_t length, int dcLevel) {<br />
    if (data == nullptr || length == 0) {<br />
      return true;<br />
    }<br />
<br />
    gpio_set_level(kTftDc, dcLevel);<br />
    spi_transaction_t transaction = {};<br />
    transaction.length = length * 8;<br />
    transaction.tx_buffer = data;<br />
    const esp_err_t err = spi_device_polling_transmit(spiDevice_, &amp;transaction);<br />
    if (err != ESP_OK) {<br />
      Serial.printf("ST7789 SPI transfer failed: %s&#92;n", esp_err_to_name(err));<br />
      return false;<br />
    }<br />
    return true;<br />
  }<br />
<br />
  bool writeCommand(uint8_t command) {<br />
    gpio_set_level(kTftCs, 0);<br />
    const bool success = transmit(&amp;command, sizeof(command), 0);<br />
    gpio_set_level(kTftCs, 1);<br />
    return success;<br />
  }<br />
<br />
  bool writeCommandData(uint8_t command, const uint8_t* data, size_t length) {<br />
    gpio_set_level(kTftCs, 0);<br />
    const bool success = transmit(&amp;command, sizeof(command), 0) &amp;&amp;<br />
                       &nbsp;&nbsp;transmit(data, length, 1);<br />
    gpio_set_level(kTftCs, 1);<br />
    return success;<br />
  }<br />
<br />
  bool setWindow(int16_t x1, int16_t y1, int16_t x2, int16_t y2) {<br />
    const uint8_t columns[] = {<br />
        static_cast&lt;uint8_t&gt;(x1 &gt;&gt; 8), static_cast&lt;uint8_t&gt;(x1),<br />
        static_cast&lt;uint8_t&gt;((x2 - 1) &gt;&gt; 8), static_cast&lt;uint8_t&gt;(x2 - 1),<br />
    };<br />
    const uint8_t rows[] = {<br />
        static_cast&lt;uint8_t&gt;(y1 &gt;&gt; 8), static_cast&lt;uint8_t&gt;(y1),<br />
        static_cast&lt;uint8_t&gt;((y2 - 1) &gt;&gt; 8), static_cast&lt;uint8_t&gt;(y2 - 1),<br />
    };<br />
    return writeCommandData(0x2A, columns, sizeof(columns)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0x2B, rows, sizeof(rows));<br />
  }<br />
<br />
  bool writePixels(const uint8_t* data, size_t length) {<br />
    constexpr uint8_t kRamWrite = 0x2C;<br />
    gpio_set_level(kTftCs, 0);<br />
    const bool success = transmit(&amp;kRamWrite, sizeof(kRamWrite), 0) &amp;&amp;<br />
                       &nbsp;&nbsp;transmit(data, length, 1);<br />
    gpio_set_level(kTftCs, 1);<br />
    return success;<br />
  }<br />
<br />
  bool initializeController() {<br />
    const uint8_t madctl[] = {kCo16Madctl};<br />
    const uint8_t displayFunction[] = {0x0A, 0x82};<br />
    const uint8_t pixelFormat[] = {0x55};<br />
    const uint8_t porchControl[] = {0x0C, 0x0C, 0x00, 0x33, 0x33};<br />
    const uint8_t gateControl[] = {0x35};<br />
    const uint8_t vcom[] = {0x28};<br />
    const uint8_t lcmControl[] = {0x0C};<br />
    const uint8_t vdvVrhEnable[] = {0x01, 0xFF};<br />
    const uint8_t vrh[] = {0x10};<br />
    const uint8_t vdv[] = {0x20};<br />
    const uint8_t frameRate[] = {0x0F};<br />
    const uint8_t powerControl[] = {0xA4, 0xA1};<br />
    const uint8_t positiveGamma[] = {<br />
        0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x32,<br />
        0x44, 0x42, 0x06, 0x0E, 0x12, 0x14, 0x17,<br />
    };<br />
    const uint8_t negativeGamma[] = {<br />
        0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x31,<br />
        0x54, 0x47, 0x0E, 0x1C, 0x17, 0x1B, 0x1E,<br />
    };<br />
<br />
    if (!writeCommand(0x11)) {  // Sleep out.<br />
      return false;<br />
    }<br />
    delay(120);<br />
<br />
    return writeCommand(0x13) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0x36, madctl, sizeof(madctl)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xB6, displayFunction, sizeof(displayFunction)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0x3A, pixelFormat, sizeof(pixelFormat)) &amp;&amp;<br />
         &nbsp;&nbsp;(delay(10), true) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xB2, porchControl, sizeof(porchControl)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xB7, gateControl, sizeof(gateControl)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xBB, vcom, sizeof(vcom)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xC0, lcmControl, sizeof(lcmControl)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xC2, vdvVrhEnable, sizeof(vdvVrhEnable)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xC3, vrh, sizeof(vrh)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xC4, vdv, sizeof(vdv)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xC6, frameRate, sizeof(frameRate)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xD0, powerControl, sizeof(powerControl)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xE0, positiveGamma, sizeof(positiveGamma)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xE1, negativeGamma, sizeof(negativeGamma)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommand(0x21);  // Display inversion on.<br />
  }<br />
<br />
  spi_device_handle_t spiDevice_ = nullptr;<br />
  uint8_t* drawBuffer_ = nullptr;<br />
  bool initialized_ = false;<br />
};<br />
<br />
Co16St7789 display;<br />
uint32_t frameCount = 0;<br />
<br />
void drawColorBars() {<br />
  constexpr uint16_t colors[] = {<br />
      kRed,<br />
      kGreen,<br />
      kBlue,<br />
      kCyan,<br />
      kMagenta,<br />
      kYellow,<br />
  };<br />
  constexpr size_t colorCount = sizeof(colors) / sizeof(colors[0]);<br />
  const int barWidth = kDisplayWidth / colorCount;<br />
<br />
  for (size_t index = 0; index &lt; colorCount; ++index) {<br />
    const int x = index * barWidth;<br />
    const int width =<br />
        (index == colorCount - 1) ? kDisplayWidth - x : barWidth;<br />
    display.fillRect(x, 132, width, 44, colors[index]);<br />
  }<br />
}<br />
<br />
void drawStaticScreen() {<br />
  display.fillScreen(kBlack);<br />
  display.drawRect(0, 0, kDisplayWidth, kDisplayHeight, kWhite);<br />
<br />
  display.setTextWrap(false);<br />
  display.setTextColor(kCyan);<br />
  display.setTextSize(3);<br />
  display.setCursor(34, 20);<br />
  display.print("KinCony CO16");<br />
<br />
  display.setTextColor(kWhite);<br />
  display.setTextSize(2);<br />
  display.setCursor(24, 64);<br />
  display.print("ST7789 display test");<br />
  display.setCursor(24, 92);<br />
  display.print("SPI3 native driver");<br />
<br />
  drawColorBars();<br />
<br />
  display.setTextColor(kGreen);<br />
  display.setCursor(24, 194);<br />
  display.print("Frame:");<br />
}<br />
<br />
void updateFrameCounter() {<br />
  display.fillRect(108, 190, 190, 28, kBlack);<br />
  display.setTextColor(kGreen);<br />
  display.setTextSize(2);<br />
  display.setCursor(108, 194);<br />
  display.print(frameCount++);<br />
}<br />
<br />
}  // namespace<br />
<br />
void setup() {<br />
  Serial.begin(115200);<br />
  delay(1000);<br />
<br />
  Serial.println();<br />
  Serial.println("KinCony CO16 standalone ST7789 example");<br />
  Serial.printf("SPI3 SCLK=%d MOSI=%d MISO=%d CS=%d mode=0 clock=%u Hz&#92;n",<br />
                kTftSclk, kTftMosi, kTftMiso, kTftCs,<br />
                kDisplaySpiFrequency);<br />
  Serial.printf("LCD DC=%d RESET=%d BACKLIGHT=%d&#92;n", kTftDc, kTftReset,<br />
                kTftBacklight);<br />
<br />
  if (!display.begin()) {<br />
    Serial.println("Display initialization failed");<br />
    while (true) {<br />
      delay(1000);<br />
    }<br />
  }<br />
<br />
  drawStaticScreen();<br />
  updateFrameCounter();<br />
<br />
  Serial.printf("Display initialized: %dx%d, MADCTL=0x%02X, invert=on&#92;n",<br />
                display.width(), display.height(), kCo16Madctl);<br />
}<br />
<br />
void loop() {<br />
  <br />
  updateFrameCounter();<br />
  delay(1000);<br />
}</code></div></div><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/image.png" title="JPG Image" border="0" alt=".jpg" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10356" target="_blank" title="">ST7789.jpg</a> (Size: 262.38 KB / Downloads: 12)
<!-- end: postbit_attachments_attachment --><br />
arduino ino file download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10352" target="_blank" title="">10-TFT-LCD-ST7789.zip</a> (Size: 3.05 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download: <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10353" target="_blank" title="">10-TFT-LCD-ST7789.ino.merged.zip</a> (Size: 211.33 KB / Downloads: 9)
<!-- end: postbit_attachments_attachment --><br />
before run code , need install these arduino library:<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/image.png" title="PNG Image" border="0" alt=".png" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10354" target="_blank" title="">Adafruit-GFX-Library.png</a> (Size: 122.69 KB / Downloads: 14)
<!-- end: postbit_attachments_attachment --><br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/image.png" title="PNG Image" border="0" alt=".png" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10355" target="_blank" title="">Adafruit-ST7735-and-ST7789-Library.png</a> (Size: 118.05 KB / Downloads: 12)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#include &lt;Adafruit_GFX.h&gt;<br />
#include &lt;driver/gpio.h&gt;<br />
#include &lt;driver/spi_master.h&gt;<br />
#include &lt;esp_heap_caps.h&gt;<br />
<br />
namespace {<br />
<br />
// CO16 ST7789 (GMT020-02-7P) pin mapping from kcs_co16.h.<br />
constexpr gpio_num_t kTftSclk = GPIO_NUM_11;<br />
constexpr gpio_num_t kTftMosi = GPIO_NUM_10;<br />
constexpr gpio_num_t kTftMiso = GPIO_NUM_12;<br />
constexpr gpio_num_t kTftCs = GPIO_NUM_4;<br />
constexpr gpio_num_t kTftDc = GPIO_NUM_0;<br />
constexpr gpio_num_t kTftReset = GPIO_NUM_5;<br />
constexpr gpio_num_t kTftBacklight = GPIO_NUM_40;<br />
<br />
constexpr int16_t kDisplayWidth = 320;<br />
constexpr int16_t kDisplayHeight = 240;<br />
constexpr int16_t kTransferChunkHeight = 10;<br />
constexpr uint32_t kDisplaySpiFrequency = 20 * 1000 * 1000;<br />
constexpr uint8_t kCo16Madctl = 0x68;  // MX | MV | BGR.<br />
<br />
constexpr uint16_t kBlack = 0x0000;<br />
constexpr uint16_t kBlue = 0x001F;<br />
constexpr uint16_t kRed = 0xF800;<br />
constexpr uint16_t kGreen = 0x07E0;<br />
constexpr uint16_t kCyan = 0x07FF;<br />
constexpr uint16_t kMagenta = 0xF81F;<br />
constexpr uint16_t kYellow = 0xFFE0;<br />
constexpr uint16_t kWhite = 0xFFFF;<br />
<br />
class Co16St7789 : public Adafruit_GFX {<br />
 public:<br />
  Co16St7789() : Adafruit_GFX(kDisplayWidth, kDisplayHeight) {}<br />
<br />
  bool begin() {<br />
    gpio_reset_pin(kTftCs);<br />
    gpio_set_direction(kTftCs, GPIO_MODE_OUTPUT);<br />
    gpio_set_level(kTftCs, 1);<br />
<br />
    gpio_reset_pin(kTftDc);<br />
    gpio_set_direction(kTftDc, GPIO_MODE_OUTPUT);<br />
    gpio_set_level(kTftDc, 1);<br />
<br />
    gpio_reset_pin(kTftBacklight);<br />
    gpio_set_direction(kTftBacklight, GPIO_MODE_OUTPUT);<br />
    gpio_set_level(kTftBacklight, 0);<br />
<br />
    spi_bus_config_t busConfig = {};<br />
    busConfig.sclk_io_num = kTftSclk;<br />
    busConfig.mosi_io_num = kTftMosi;<br />
    busConfig.miso_io_num = kTftMiso;<br />
    busConfig.quadwp_io_num = -1;<br />
    busConfig.quadhd_io_num = -1;<br />
    busConfig.max_transfer_sz =<br />
        kDisplayWidth * kTransferChunkHeight * sizeof(uint16_t);<br />
<br />
    esp_err_t err =<br />
        spi_bus_initialize(SPI3_HOST, &amp;busConfig, SPI_DMA_CH_AUTO);<br />
    if (err != ESP_OK) {<br />
      Serial.printf("SPI3 initialization failed: %s&#92;n", esp_err_to_name(err));<br />
      return false;<br />
    }<br />
<br />
    spi_device_interface_config_t deviceConfig = {};<br />
    deviceConfig.clock_speed_hz = kDisplaySpiFrequency;<br />
    deviceConfig.mode = 0;<br />
    deviceConfig.spics_io_num = -1;<br />
    deviceConfig.queue_size = 1;<br />
<br />
    err = spi_bus_add_device(SPI3_HOST, &amp;deviceConfig, &amp;spiDevice_);<br />
    if (err != ESP_OK) {<br />
      Serial.printf("ST7789 SPI device setup failed: %s&#92;n",<br />
                    esp_err_to_name(err));<br />
      return false;<br />
    }<br />
<br />
    drawBuffer_ = static_cast&lt;uint8_t*&gt;(heap_caps_malloc(<br />
        kDisplayWidth * kTransferChunkHeight * sizeof(uint16_t),<br />
        MALLOC_CAP_DMA));<br />
    if (drawBuffer_ == nullptr) {<br />
      Serial.println("ST7789 DMA buffer allocation failed");<br />
      return false;<br />
    }<br />
<br />
    // GPIO5 is shared with the optional LoRa module. Match the working KCS<br />
    // firmware and issue one reset pulse before initializing the controller.<br />
    gpio_reset_pin(kTftReset);<br />
    gpio_set_direction(kTftReset, GPIO_MODE_OUTPUT);<br />
    gpio_set_level(kTftReset, 1);<br />
    delay(1);<br />
    gpio_set_level(kTftReset, 0);<br />
    delay(1);<br />
    gpio_set_level(kTftReset, 1);<br />
    delay(10);<br />
<br />
    if (!initializeController()) {<br />
      return false;<br />
    }<br />
<br />
    fillScreen(kBlack);<br />
    delay(120);<br />
    if (!writeCommand(0x29)) {  // Display on.<br />
      return false;<br />
    }<br />
    delay(120);<br />
<br />
    gpio_set_level(kTftBacklight, 1);<br />
    initialized_ = true;<br />
    return true;<br />
  }<br />
<br />
  void drawPixel(int16_t x, int16_t y, uint16_t color) override {<br />
    fillRect(x, y, 1, 1, color);<br />
  }<br />
<br />
  void writePixel(int16_t x, int16_t y, uint16_t color) override {<br />
    fillRect(x, y, 1, 1, color);<br />
  }<br />
<br />
  void fillRect(int16_t x, int16_t y, int16_t width, int16_t height,<br />
                uint16_t color) override {<br />
    if (x &lt; 0) {<br />
      width += x;<br />
      x = 0;<br />
    }<br />
    if (y &lt; 0) {<br />
      height += y;<br />
      y = 0;<br />
    }<br />
    if (x + width &gt; kDisplayWidth) {<br />
      width = kDisplayWidth - x;<br />
    }<br />
    if (y + height &gt; kDisplayHeight) {<br />
      height = kDisplayHeight - y;<br />
    }<br />
    if (drawBuffer_ == nullptr || width &lt;= 0 || height &lt;= 0) {<br />
      return;<br />
    }<br />
<br />
    const uint8_t high = color &gt;&gt; 8;<br />
    const uint8_t low = color;<br />
    for (int16_t row = y; row &lt; y + height;<br />
       &nbsp;&nbsp;row += kTransferChunkHeight) {<br />
      const int16_t chunkHeight =<br />
          min&lt;int16_t&gt;(kTransferChunkHeight, y + height - row);<br />
      const size_t pixelCount = width * chunkHeight;<br />
      for (size_t index = 0; index &lt; pixelCount; ++index) {<br />
        drawBuffer_[index * 2] = high;<br />
        drawBuffer_[index * 2 + 1] = low;<br />
      }<br />
<br />
      if (!setWindow(x, row, x + width, row + chunkHeight) ||<br />
          !writePixels(drawBuffer_, pixelCount * sizeof(uint16_t))) {<br />
        Serial.println("ST7789 pixel transfer failed");<br />
        return;<br />
      }<br />
    }<br />
  }<br />
<br />
  void writeFillRect(int16_t x, int16_t y, int16_t width, int16_t height,<br />
                   &nbsp;&nbsp;uint16_t color) override {<br />
    fillRect(x, y, width, height, color);<br />
  }<br />
<br />
  bool initialized() const { return initialized_; }<br />
<br />
 private:<br />
  bool transmit(const void* data, size_t length, int dcLevel) {<br />
    if (data == nullptr || length == 0) {<br />
      return true;<br />
    }<br />
<br />
    gpio_set_level(kTftDc, dcLevel);<br />
    spi_transaction_t transaction = {};<br />
    transaction.length = length * 8;<br />
    transaction.tx_buffer = data;<br />
    const esp_err_t err = spi_device_polling_transmit(spiDevice_, &amp;transaction);<br />
    if (err != ESP_OK) {<br />
      Serial.printf("ST7789 SPI transfer failed: %s&#92;n", esp_err_to_name(err));<br />
      return false;<br />
    }<br />
    return true;<br />
  }<br />
<br />
  bool writeCommand(uint8_t command) {<br />
    gpio_set_level(kTftCs, 0);<br />
    const bool success = transmit(&amp;command, sizeof(command), 0);<br />
    gpio_set_level(kTftCs, 1);<br />
    return success;<br />
  }<br />
<br />
  bool writeCommandData(uint8_t command, const uint8_t* data, size_t length) {<br />
    gpio_set_level(kTftCs, 0);<br />
    const bool success = transmit(&amp;command, sizeof(command), 0) &amp;&amp;<br />
                       &nbsp;&nbsp;transmit(data, length, 1);<br />
    gpio_set_level(kTftCs, 1);<br />
    return success;<br />
  }<br />
<br />
  bool setWindow(int16_t x1, int16_t y1, int16_t x2, int16_t y2) {<br />
    const uint8_t columns[] = {<br />
        static_cast&lt;uint8_t&gt;(x1 &gt;&gt; 8), static_cast&lt;uint8_t&gt;(x1),<br />
        static_cast&lt;uint8_t&gt;((x2 - 1) &gt;&gt; 8), static_cast&lt;uint8_t&gt;(x2 - 1),<br />
    };<br />
    const uint8_t rows[] = {<br />
        static_cast&lt;uint8_t&gt;(y1 &gt;&gt; 8), static_cast&lt;uint8_t&gt;(y1),<br />
        static_cast&lt;uint8_t&gt;((y2 - 1) &gt;&gt; 8), static_cast&lt;uint8_t&gt;(y2 - 1),<br />
    };<br />
    return writeCommandData(0x2A, columns, sizeof(columns)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0x2B, rows, sizeof(rows));<br />
  }<br />
<br />
  bool writePixels(const uint8_t* data, size_t length) {<br />
    constexpr uint8_t kRamWrite = 0x2C;<br />
    gpio_set_level(kTftCs, 0);<br />
    const bool success = transmit(&amp;kRamWrite, sizeof(kRamWrite), 0) &amp;&amp;<br />
                       &nbsp;&nbsp;transmit(data, length, 1);<br />
    gpio_set_level(kTftCs, 1);<br />
    return success;<br />
  }<br />
<br />
  bool initializeController() {<br />
    const uint8_t madctl[] = {kCo16Madctl};<br />
    const uint8_t displayFunction[] = {0x0A, 0x82};<br />
    const uint8_t pixelFormat[] = {0x55};<br />
    const uint8_t porchControl[] = {0x0C, 0x0C, 0x00, 0x33, 0x33};<br />
    const uint8_t gateControl[] = {0x35};<br />
    const uint8_t vcom[] = {0x28};<br />
    const uint8_t lcmControl[] = {0x0C};<br />
    const uint8_t vdvVrhEnable[] = {0x01, 0xFF};<br />
    const uint8_t vrh[] = {0x10};<br />
    const uint8_t vdv[] = {0x20};<br />
    const uint8_t frameRate[] = {0x0F};<br />
    const uint8_t powerControl[] = {0xA4, 0xA1};<br />
    const uint8_t positiveGamma[] = {<br />
        0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x32,<br />
        0x44, 0x42, 0x06, 0x0E, 0x12, 0x14, 0x17,<br />
    };<br />
    const uint8_t negativeGamma[] = {<br />
        0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x31,<br />
        0x54, 0x47, 0x0E, 0x1C, 0x17, 0x1B, 0x1E,<br />
    };<br />
<br />
    if (!writeCommand(0x11)) {  // Sleep out.<br />
      return false;<br />
    }<br />
    delay(120);<br />
<br />
    return writeCommand(0x13) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0x36, madctl, sizeof(madctl)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xB6, displayFunction, sizeof(displayFunction)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0x3A, pixelFormat, sizeof(pixelFormat)) &amp;&amp;<br />
         &nbsp;&nbsp;(delay(10), true) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xB2, porchControl, sizeof(porchControl)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xB7, gateControl, sizeof(gateControl)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xBB, vcom, sizeof(vcom)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xC0, lcmControl, sizeof(lcmControl)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xC2, vdvVrhEnable, sizeof(vdvVrhEnable)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xC3, vrh, sizeof(vrh)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xC4, vdv, sizeof(vdv)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xC6, frameRate, sizeof(frameRate)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xD0, powerControl, sizeof(powerControl)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xE0, positiveGamma, sizeof(positiveGamma)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommandData(0xE1, negativeGamma, sizeof(negativeGamma)) &amp;&amp;<br />
         &nbsp;&nbsp;writeCommand(0x21);  // Display inversion on.<br />
  }<br />
<br />
  spi_device_handle_t spiDevice_ = nullptr;<br />
  uint8_t* drawBuffer_ = nullptr;<br />
  bool initialized_ = false;<br />
};<br />
<br />
Co16St7789 display;<br />
uint32_t frameCount = 0;<br />
<br />
void drawColorBars() {<br />
  constexpr uint16_t colors[] = {<br />
      kRed,<br />
      kGreen,<br />
      kBlue,<br />
      kCyan,<br />
      kMagenta,<br />
      kYellow,<br />
  };<br />
  constexpr size_t colorCount = sizeof(colors) / sizeof(colors[0]);<br />
  const int barWidth = kDisplayWidth / colorCount;<br />
<br />
  for (size_t index = 0; index &lt; colorCount; ++index) {<br />
    const int x = index * barWidth;<br />
    const int width =<br />
        (index == colorCount - 1) ? kDisplayWidth - x : barWidth;<br />
    display.fillRect(x, 132, width, 44, colors[index]);<br />
  }<br />
}<br />
<br />
void drawStaticScreen() {<br />
  display.fillScreen(kBlack);<br />
  display.drawRect(0, 0, kDisplayWidth, kDisplayHeight, kWhite);<br />
<br />
  display.setTextWrap(false);<br />
  display.setTextColor(kCyan);<br />
  display.setTextSize(3);<br />
  display.setCursor(34, 20);<br />
  display.print("KinCony CO16");<br />
<br />
  display.setTextColor(kWhite);<br />
  display.setTextSize(2);<br />
  display.setCursor(24, 64);<br />
  display.print("ST7789 display test");<br />
  display.setCursor(24, 92);<br />
  display.print("SPI3 native driver");<br />
<br />
  drawColorBars();<br />
<br />
  display.setTextColor(kGreen);<br />
  display.setCursor(24, 194);<br />
  display.print("Frame:");<br />
}<br />
<br />
void updateFrameCounter() {<br />
  display.fillRect(108, 190, 190, 28, kBlack);<br />
  display.setTextColor(kGreen);<br />
  display.setTextSize(2);<br />
  display.setCursor(108, 194);<br />
  display.print(frameCount++);<br />
}<br />
<br />
}  // namespace<br />
<br />
void setup() {<br />
  Serial.begin(115200);<br />
  delay(1000);<br />
<br />
  Serial.println();<br />
  Serial.println("KinCony CO16 standalone ST7789 example");<br />
  Serial.printf("SPI3 SCLK=%d MOSI=%d MISO=%d CS=%d mode=0 clock=%u Hz&#92;n",<br />
                kTftSclk, kTftMosi, kTftMiso, kTftCs,<br />
                kDisplaySpiFrequency);<br />
  Serial.printf("LCD DC=%d RESET=%d BACKLIGHT=%d&#92;n", kTftDc, kTftReset,<br />
                kTftBacklight);<br />
<br />
  if (!display.begin()) {<br />
    Serial.println("Display initialization failed");<br />
    while (true) {<br />
      delay(1000);<br />
    }<br />
  }<br />
<br />
  drawStaticScreen();<br />
  updateFrameCounter();<br />
<br />
  Serial.printf("Display initialized: %dx%d, MADCTL=0x%02X, invert=on&#92;n",<br />
                display.width(), display.height(), kCo16Madctl);<br />
}<br />
<br />
void loop() {<br />
  <br />
  updateFrameCounter();<br />
  delay(1000);<br />
}</code></div></div><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/image.png" title="JPG Image" border="0" alt=".jpg" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10356" target="_blank" title="">ST7789.jpg</a> (Size: 262.38 KB / Downloads: 12)
<!-- end: postbit_attachments_attachment --><br />
arduino ino file download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10352" target="_blank" title="">10-TFT-LCD-ST7789.zip</a> (Size: 3.05 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download: <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10353" target="_blank" title="">10-TFT-LCD-ST7789.ino.merged.zip</a> (Size: 211.33 KB / Downloads: 9)
<!-- end: postbit_attachments_attachment --><br />
before run code , need install these arduino library:<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/image.png" title="PNG Image" border="0" alt=".png" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10354" target="_blank" title="">Adafruit-GFX-Library.png</a> (Size: 122.69 KB / Downloads: 14)
<!-- end: postbit_attachments_attachment --><br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/image.png" title="PNG Image" border="0" alt=".png" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10355" target="_blank" title="">Adafruit-ST7735-and-ST7789-Library.png</a> (Size: 118.05 KB / Downloads: 12)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[arduino code examples for CO16]-09 digital INPUT trigger OUTPUT directly]]></title>
			<link>https://www.kincony.com/forum/showthread.php?tid=9790</link>
			<pubDate>Mon, 31 Aug 2026 08:11:58 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://www.kincony.com/forum/member.php?action=profile&uid=1">admin</a>]]></dc:creator>
			<guid isPermaLink="false">https://www.kincony.com/forum/showthread.php?tid=9790</guid>
			<description><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
  Made by KinCony IoT: https://www.kincony.com<br />
<br />
  Program functionality:<br />
  This program uses ESP32-S3 to read inputs from PCA9555 I/O expander chip (I2C address 0x24)<br />
  for channels 1-16, and control corresponding relays using PCF8575 I/O expander chip (I2C address 0x22)<br />
  for controlling 16 relays (1-16). When input (DI) is triggered (LOW), corresponding relay (OUTPUT) is activated (LOW).<br />
*/<br />
<br />
#include &lt;PCA95x5.h&gt;<br />
#include &lt;Wire.h&gt;<br />
#include &lt;PCF8575.h&gt;<br />
<br />
// Initialize the PCA9555 objects for reading inputs (channels 1-16)<br />
PCA9555 input_ioex1;  // For channels 1-16 (I2C address 0x24)<br />
<br />
// Set I2C address of the PCF8575 module for output relays<br />
#define I2C_ADDRESS 0x22<br />
PCF8575 pcf8575_R1(I2C_ADDRESS);<br />
<br />
void setup() {<br />
    Serial.begin(115200);<br />
    delay(10);<br />
<br />
    // Initialize I2C bus: SDA=GPIO8, SCL=GPIO18, 100kHz<br />
    Wire.begin(8, 18, 100000);<br />
<br />
    // Initialize PCF8575 for outputs<br />
    pcf8575_R1.begin();<br />
<br />
    // Turn off all relays initially (set all pins HIGH - relay OFF)<br />
    for (int i = 0; i &lt; 16; i++) {<br />
        pcf8575_R1.write(i, HIGH);<br />
    }<br />
<br />
    // Configure input PCA9555 (for inputs 1-16)<br />
    input_ioex1.attach(Wire, 0x24);<br />
    input_ioex1.polarity(PCA95x5::Polarity::ORIGINAL_ALL);<br />
    input_ioex1.direction(PCA95x5::Direction::IN_ALL);<br />
<br />
    delay(50);<br />
}<br />
<br />
void loop() {<br />
    // Read input states from XL9535 (inputs 1-16)<br />
    uint16_t inputs_1_16 = input_ioex1.read();<br />
    <br />
    // Control outputs based on inputs<br />
    // When input is LOW, set corresponding output to LOW (activate relay)<br />
    for (int channel = 0; channel &lt; 16; channel++) {<br />
        if (!(inputs_1_16 &amp; (1 &lt;&lt; channel))) {<br />
            pcf8575_R1.write(channel, LOW); &nbsp;&nbsp;// Input triggered, activate relay<br />
        } else {<br />
            pcf8575_R1.write(channel, HIGH);  // Input not triggered, deactivate relay<br />
        }<br />
    }<br />
    <br />
    delay(100);<br />
}</code></div></div> arduino ino file download: <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10350" target="_blank" title="">9-input-trigger-output.zip</a> (Size: 997 bytes / Downloads: 6)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download: <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10351" target="_blank" title="">9-input-trigger-output.ino.merged.zip</a> (Size: 197.75 KB / Downloads: 5)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
  Made by KinCony IoT: https://www.kincony.com<br />
<br />
  Program functionality:<br />
  This program uses ESP32-S3 to read inputs from PCA9555 I/O expander chip (I2C address 0x24)<br />
  for channels 1-16, and control corresponding relays using PCF8575 I/O expander chip (I2C address 0x22)<br />
  for controlling 16 relays (1-16). When input (DI) is triggered (LOW), corresponding relay (OUTPUT) is activated (LOW).<br />
*/<br />
<br />
#include &lt;PCA95x5.h&gt;<br />
#include &lt;Wire.h&gt;<br />
#include &lt;PCF8575.h&gt;<br />
<br />
// Initialize the PCA9555 objects for reading inputs (channels 1-16)<br />
PCA9555 input_ioex1;  // For channels 1-16 (I2C address 0x24)<br />
<br />
// Set I2C address of the PCF8575 module for output relays<br />
#define I2C_ADDRESS 0x22<br />
PCF8575 pcf8575_R1(I2C_ADDRESS);<br />
<br />
void setup() {<br />
    Serial.begin(115200);<br />
    delay(10);<br />
<br />
    // Initialize I2C bus: SDA=GPIO8, SCL=GPIO18, 100kHz<br />
    Wire.begin(8, 18, 100000);<br />
<br />
    // Initialize PCF8575 for outputs<br />
    pcf8575_R1.begin();<br />
<br />
    // Turn off all relays initially (set all pins HIGH - relay OFF)<br />
    for (int i = 0; i &lt; 16; i++) {<br />
        pcf8575_R1.write(i, HIGH);<br />
    }<br />
<br />
    // Configure input PCA9555 (for inputs 1-16)<br />
    input_ioex1.attach(Wire, 0x24);<br />
    input_ioex1.polarity(PCA95x5::Polarity::ORIGINAL_ALL);<br />
    input_ioex1.direction(PCA95x5::Direction::IN_ALL);<br />
<br />
    delay(50);<br />
}<br />
<br />
void loop() {<br />
    // Read input states from XL9535 (inputs 1-16)<br />
    uint16_t inputs_1_16 = input_ioex1.read();<br />
    <br />
    // Control outputs based on inputs<br />
    // When input is LOW, set corresponding output to LOW (activate relay)<br />
    for (int channel = 0; channel &lt; 16; channel++) {<br />
        if (!(inputs_1_16 &amp; (1 &lt;&lt; channel))) {<br />
            pcf8575_R1.write(channel, LOW); &nbsp;&nbsp;// Input triggered, activate relay<br />
        } else {<br />
            pcf8575_R1.write(channel, HIGH);  // Input not triggered, deactivate relay<br />
        }<br />
    }<br />
    <br />
    delay(100);<br />
}</code></div></div> arduino ino file download: <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10350" target="_blank" title="">9-input-trigger-output.zip</a> (Size: 997 bytes / Downloads: 6)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download: <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10351" target="_blank" title="">9-input-trigger-output.ino.merged.zip</a> (Size: 197.75 KB / Downloads: 5)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[arduino code examples for CO16]-08 Ethernet W5500 chip work with TCP Server mode]]></title>
			<link>https://www.kincony.com/forum/showthread.php?tid=9789</link>
			<pubDate>Mon, 31 Aug 2026 08:09:39 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://www.kincony.com/forum/member.php?action=profile&uid=1">admin</a>]]></dc:creator>
			<guid isPermaLink="false">https://www.kincony.com/forum/showthread.php?tid=9789</guid>
			<description><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
 * Made by KinCony IoT: https://www.kincony.com<br />
 *<br />
 * This Arduino program sets up an ESP32-S3 with a W5500 Ethernet module<br />
 * as a TCP server. It listens on port 4196 and echoes back any string <br />
 * received from a client.<br />
 *<br />
 * Hardware connections:<br />
 * - CLK: GPIO1<br />
 * - MOSI: GPIO2<br />
 * - MISO: GPIO41<br />
 * - CS: GPIO42<br />
 * - RST: GPIO44<br />
 * - INT: GPIO43<br />
 *<br />
 * Static IP address: 192.168.3.55<br />
 * Subnet Mask: 255.255.255.0<br />
 * Gateway: 192.168.3.1<br />
 * DNS: 192.168.3.1<br />
 */<br />
<br />
#include &lt;SPI.h&gt;<br />
#include &lt;Ethernet.h&gt;<br />
<br />
// Define the W5500 Ethernet module pins<br />
#define W5500_CS_PIN  42<br />
#define W5500_RST_PIN 44<br />
#define W5500_INT_PIN 43<br />
#define W5500_CLK_PIN 1<br />
#define W5500_MOSI_PIN 2<br />
#define W5500_MISO_PIN 41<br />
<br />
// MAC address for your Ethernet shield (must be unique on your network)<br />
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };<br />
<br />
// Static IP address configuration<br />
IPAddress ip(192, 168, 3, 55);     &nbsp;&nbsp;// Static IP address<br />
IPAddress subnet(255, 255, 255, 0); &nbsp;&nbsp;// Subnet mask<br />
IPAddress gateway(192, 168, 3, 1);    // Default gateway<br />
IPAddress dns(192, 168, 3, 1);        // DNS server address<br />
<br />
// Create an EthernetServer object to handle TCP connections<br />
EthernetServer server(4196);<br />
<br />
void setup() {<br />
  // Initialize serial communication<br />
  Serial.begin(115200);<br />
  while (!Serial) {<br />
    ; // Wait for serial port to connect<br />
  }<br />
<br />
  // Initialize the W5500 module<br />
  pinMode(W5500_RST_PIN, OUTPUT);<br />
  pinMode(W5500_INT_PIN, INPUT);<br />
  digitalWrite(W5500_RST_PIN, LOW);  // Reset the W5500 module<br />
  delay(100);                     &nbsp;&nbsp;// Wait for reset to complete<br />
  digitalWrite(W5500_RST_PIN, HIGH); // Release reset<br />
<br />
  // Initialize SPI with the correct pin definitions<br />
  SPI.begin(W5500_CLK_PIN, W5500_MISO_PIN, W5500_MOSI_PIN);<br />
<br />
  // Set up the Ethernet library with W5500-specific pins<br />
  Ethernet.init(W5500_CS_PIN);<br />
<br />
  // Start the Ethernet connection with static IP configuration<br />
  Ethernet.begin(mac, ip, dns, gateway, subnet);<br />
<br />
  // Print the IP address to the serial monitor<br />
  Serial.print("IP Address: ");<br />
  Serial.println(Ethernet.localIP());<br />
<br />
  // Start listening for incoming TCP connections<br />
  server.begin();<br />
}<br />
<br />
void loop() {<br />
  // Check for incoming client connections<br />
  EthernetClient client = server.available();<br />
  if (client) {<br />
    Serial.println("New client connected");<br />
<br />
    // Read data from the client and echo it back<br />
    while (client.connected()) {<br />
      if (client.available()) {<br />
        char c = client.read();<br />
        server.write(c);<br />
      }<br />
    }<br />
<br />
    // Close the connection when done<br />
    client.stop();<br />
    Serial.println("Client disconnected");<br />
  }<br />
}</code></div></div> arduino ino file download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10348" target="_blank" title="">8-Ethernet-W5500.zip</a> (Size: 1.23 KB / Downloads: 9)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10349" target="_blank" title="">8-Ethernet-W5500.ino.merged.zip</a> (Size: 188.93 KB / Downloads: 7)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
 * Made by KinCony IoT: https://www.kincony.com<br />
 *<br />
 * This Arduino program sets up an ESP32-S3 with a W5500 Ethernet module<br />
 * as a TCP server. It listens on port 4196 and echoes back any string <br />
 * received from a client.<br />
 *<br />
 * Hardware connections:<br />
 * - CLK: GPIO1<br />
 * - MOSI: GPIO2<br />
 * - MISO: GPIO41<br />
 * - CS: GPIO42<br />
 * - RST: GPIO44<br />
 * - INT: GPIO43<br />
 *<br />
 * Static IP address: 192.168.3.55<br />
 * Subnet Mask: 255.255.255.0<br />
 * Gateway: 192.168.3.1<br />
 * DNS: 192.168.3.1<br />
 */<br />
<br />
#include &lt;SPI.h&gt;<br />
#include &lt;Ethernet.h&gt;<br />
<br />
// Define the W5500 Ethernet module pins<br />
#define W5500_CS_PIN  42<br />
#define W5500_RST_PIN 44<br />
#define W5500_INT_PIN 43<br />
#define W5500_CLK_PIN 1<br />
#define W5500_MOSI_PIN 2<br />
#define W5500_MISO_PIN 41<br />
<br />
// MAC address for your Ethernet shield (must be unique on your network)<br />
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };<br />
<br />
// Static IP address configuration<br />
IPAddress ip(192, 168, 3, 55);     &nbsp;&nbsp;// Static IP address<br />
IPAddress subnet(255, 255, 255, 0); &nbsp;&nbsp;// Subnet mask<br />
IPAddress gateway(192, 168, 3, 1);    // Default gateway<br />
IPAddress dns(192, 168, 3, 1);        // DNS server address<br />
<br />
// Create an EthernetServer object to handle TCP connections<br />
EthernetServer server(4196);<br />
<br />
void setup() {<br />
  // Initialize serial communication<br />
  Serial.begin(115200);<br />
  while (!Serial) {<br />
    ; // Wait for serial port to connect<br />
  }<br />
<br />
  // Initialize the W5500 module<br />
  pinMode(W5500_RST_PIN, OUTPUT);<br />
  pinMode(W5500_INT_PIN, INPUT);<br />
  digitalWrite(W5500_RST_PIN, LOW);  // Reset the W5500 module<br />
  delay(100);                     &nbsp;&nbsp;// Wait for reset to complete<br />
  digitalWrite(W5500_RST_PIN, HIGH); // Release reset<br />
<br />
  // Initialize SPI with the correct pin definitions<br />
  SPI.begin(W5500_CLK_PIN, W5500_MISO_PIN, W5500_MOSI_PIN);<br />
<br />
  // Set up the Ethernet library with W5500-specific pins<br />
  Ethernet.init(W5500_CS_PIN);<br />
<br />
  // Start the Ethernet connection with static IP configuration<br />
  Ethernet.begin(mac, ip, dns, gateway, subnet);<br />
<br />
  // Print the IP address to the serial monitor<br />
  Serial.print("IP Address: ");<br />
  Serial.println(Ethernet.localIP());<br />
<br />
  // Start listening for incoming TCP connections<br />
  server.begin();<br />
}<br />
<br />
void loop() {<br />
  // Check for incoming client connections<br />
  EthernetClient client = server.available();<br />
  if (client) {<br />
    Serial.println("New client connected");<br />
<br />
    // Read data from the client and echo it back<br />
    while (client.connected()) {<br />
      if (client.available()) {<br />
        char c = client.read();<br />
        server.write(c);<br />
      }<br />
    }<br />
<br />
    // Close the connection when done<br />
    client.stop();<br />
    Serial.println("Client disconnected");<br />
  }<br />
}</code></div></div> arduino ino file download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10348" target="_blank" title="">8-Ethernet-W5500.zip</a> (Size: 1.23 KB / Downloads: 9)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10349" target="_blank" title="">8-Ethernet-W5500.ino.merged.zip</a> (Size: 188.93 KB / Downloads: 7)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[arduino code examples for CO16]-07 how to DS3231 RTC clock]]></title>
			<link>https://www.kincony.com/forum/showthread.php?tid=9788</link>
			<pubDate>Mon, 31 Aug 2026 08:08:28 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://www.kincony.com/forum/member.php?action=profile&uid=1">admin</a>]]></dc:creator>
			<guid isPermaLink="false">https://www.kincony.com/forum/showthread.php?tid=9788</guid>
			<description><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
 * Made by KinCony IoT: https://www.kincony.com<br />
 *<br />
 * DS3231 RTC with Arduino<br />
 *<br />
 * This program demonstrates how to use the DS3231 RTC (Real-Time Clock) module with the Arduino.<br />
 * It includes functionality to:<br />
 * - Initialize the DS3231 RTC module<br />
 * - Read the current date and time from the RTC<br />
 * - Set the RTC time based on a serial command:Command format: DYYYY-MM-DDTHH:MM:SS<br />
*    Set date and time command example: D2024-09-19T11:50:22<br />
*    print current date and time command: current time<br />
*<br />
 *<br />
 * Hardware Connections:<br />
 * - SDA: GPIO 8<br />
 * - SCL: GPIO 18<br />
 */<br />
<br />
#include &lt;DS3231.h&gt;<br />
#include &lt;Wire.h&gt;<br />
<br />
String serial_cmd_rcv = ""; // Serial port receiver<br />
<br />
typedef struct<br />
{<br />
  byte year;    // Last two digits of the year, library adds 2000.<br />
  byte month;<br />
  byte day;<br />
  byte hour;<br />
  byte minute;<br />
  byte second;<br />
} MY_DATE_STR;<br />
<br />
MY_DATE_STR my_date_str = {0};<br />
<br />
// Define constants for relay control<br />
#define OPEN_RLY_DATA    26<br />
#define OPEN_RLY_MONTH &nbsp;&nbsp;4<br />
#define CLOSE_RLY_DATA &nbsp;&nbsp;2<br />
#define CLOSE_RLY_MONTH  5<br />
<br />
// Define pin connections<br />
#define SDA_PIN &nbsp;&nbsp;8<br />
#define SCL_PIN &nbsp;&nbsp;18<br />
<br />
DS3231 rtc; // Create an instance of the DS3231 RTC<br />
bool h12Flag;<br />
bool pmFlag;<br />
static bool bCentury = false;<br />
static bool old_level_high = false;<br />
static bool old_level_low = false;<br />
<br />
<br />
/**<br />
 * @brief Print the current time from the RTC to the Serial Monitor.<br />
 */<br />
static void PrintfCurTime()<br />
{<br />
  Serial.print("Current time is: ");<br />
  int year = rtc.getYear() + 2000;<br />
  Serial.print(year);<br />
  Serial.print("-");<br />
<br />
  Serial.print(rtc.getMonth(bCentury), DEC);<br />
  Serial.print("-");<br />
<br />
  Serial.print(rtc.getDate(), DEC);<br />
  Serial.print(" ");<br />
<br />
  Serial.print(rtc.getHour(h12Flag, pmFlag), DEC);<br />
  Serial.print(":");<br />
  Serial.print(rtc.getMinute(), DEC);<br />
  Serial.print(":");<br />
  Serial.println(rtc.getSecond(), DEC);<br />
}<br />
<br />
/**<br />
 * @brief Process serial commands to set the RTC time.<br />
 * Command format: DYYYY-MM-DDTHH:MM:SS<br />
 */<br />
static void GetSerialCmd()<br />
{<br />
  if (Serial.available() &gt; 0)<br />
  {<br />
    delay(100);<br />
    int num_read = Serial.available();<br />
    while (num_read--)<br />
      serial_cmd_rcv += char(Serial.read());<br />
  }<br />
  else return;<br />
<br />
  serial_cmd_rcv.trim();<br />
<br />
  if (serial_cmd_rcv == "current time")<br />
  {<br />
    PrintfCurTime();<br />
    serial_cmd_rcv = "";<br />
    return;<br />
  }<br />
<br />
  Serial.print("Received length: ");<br />
  Serial.println(serial_cmd_rcv.length());<br />
<br />
  int indexof_d = serial_cmd_rcv.indexOf('D');<br />
  int indexof_t = serial_cmd_rcv.indexOf('T');<br />
<br />
  Serial.print("D index: ");<br />
  Serial.print(indexof_d);<br />
  Serial.print(" T index: ");<br />
  Serial.println(indexof_t);<br />
<br />
  if (serial_cmd_rcv.length() != 20 || <br />
      serial_cmd_rcv.substring(0, 1) != "D" ||<br />
      serial_cmd_rcv.substring(11, 12) != "T")  <br />
  {<br />
    Serial.println(serial_cmd_rcv);<br />
    serial_cmd_rcv = "";<br />
    return;<br />
  }<br />
<br />
  Serial.println("Setting time...");<br />
<br />
  my_date_str.year = (byte)serial_cmd_rcv.substring(3, 5).toInt();<br />
  my_date_str.month = (byte)serial_cmd_rcv.substring(6, 8).toInt();<br />
  my_date_str.day = (byte)serial_cmd_rcv.substring(9, 11).toInt();<br />
  my_date_str.hour = (byte)serial_cmd_rcv.substring(12, 14).toInt();<br />
  my_date_str.minute = (byte)serial_cmd_rcv.substring(15, 17).toInt();<br />
  my_date_str.second = (byte)serial_cmd_rcv.substring(18).toInt();<br />
<br />
  rtc.setYear(my_date_str.year);<br />
  rtc.setMonth(my_date_str.month);<br />
  rtc.setDate(my_date_str.day);<br />
  rtc.setHour(my_date_str.hour);<br />
  rtc.setMinute(my_date_str.minute);<br />
  rtc.setSecond(my_date_str.second);<br />
<br />
  serial_cmd_rcv = "";<br />
<br />
  Serial.println("Time set.");<br />
}<br />
<br />
void setup() {<br />
  // Initialize the I2C interface<br />
  Wire.begin(SDA_PIN, SCL_PIN, 40000);<br />
  <br />
  // Initialize Serial communication<br />
  Serial.begin(115200);<br />
 &nbsp;&nbsp;<br />
  // Set the RTC to 24-hour mode<br />
  rtc.setClockMode(false); // 24-hour format<br />
<br />
  // Print current time to Serial Monitor<br />
  PrintfCurTime();<br />
<br />
  // Clear any remaining serial data<br />
  while (Serial.read() &gt;= 0) {}<br />
}<br />
<br />
void loop() {<br />
  // Process incoming serial commands<br />
  GetSerialCmd(); <br />
  delay(1000); // Delay for 1 second<br />
}</code></div></div> arduino ino file download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10346" target="_blank" title="">7-DS3231-RTC.zip</a> (Size: 1.56 KB / Downloads: 7)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10347" target="_blank" title="">7-DS3231-RTC.ino.merged.zip</a> (Size: 191.08 KB / Downloads: 7)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
 * Made by KinCony IoT: https://www.kincony.com<br />
 *<br />
 * DS3231 RTC with Arduino<br />
 *<br />
 * This program demonstrates how to use the DS3231 RTC (Real-Time Clock) module with the Arduino.<br />
 * It includes functionality to:<br />
 * - Initialize the DS3231 RTC module<br />
 * - Read the current date and time from the RTC<br />
 * - Set the RTC time based on a serial command:Command format: DYYYY-MM-DDTHH:MM:SS<br />
*    Set date and time command example: D2024-09-19T11:50:22<br />
*    print current date and time command: current time<br />
*<br />
 *<br />
 * Hardware Connections:<br />
 * - SDA: GPIO 8<br />
 * - SCL: GPIO 18<br />
 */<br />
<br />
#include &lt;DS3231.h&gt;<br />
#include &lt;Wire.h&gt;<br />
<br />
String serial_cmd_rcv = ""; // Serial port receiver<br />
<br />
typedef struct<br />
{<br />
  byte year;    // Last two digits of the year, library adds 2000.<br />
  byte month;<br />
  byte day;<br />
  byte hour;<br />
  byte minute;<br />
  byte second;<br />
} MY_DATE_STR;<br />
<br />
MY_DATE_STR my_date_str = {0};<br />
<br />
// Define constants for relay control<br />
#define OPEN_RLY_DATA    26<br />
#define OPEN_RLY_MONTH &nbsp;&nbsp;4<br />
#define CLOSE_RLY_DATA &nbsp;&nbsp;2<br />
#define CLOSE_RLY_MONTH  5<br />
<br />
// Define pin connections<br />
#define SDA_PIN &nbsp;&nbsp;8<br />
#define SCL_PIN &nbsp;&nbsp;18<br />
<br />
DS3231 rtc; // Create an instance of the DS3231 RTC<br />
bool h12Flag;<br />
bool pmFlag;<br />
static bool bCentury = false;<br />
static bool old_level_high = false;<br />
static bool old_level_low = false;<br />
<br />
<br />
/**<br />
 * @brief Print the current time from the RTC to the Serial Monitor.<br />
 */<br />
static void PrintfCurTime()<br />
{<br />
  Serial.print("Current time is: ");<br />
  int year = rtc.getYear() + 2000;<br />
  Serial.print(year);<br />
  Serial.print("-");<br />
<br />
  Serial.print(rtc.getMonth(bCentury), DEC);<br />
  Serial.print("-");<br />
<br />
  Serial.print(rtc.getDate(), DEC);<br />
  Serial.print(" ");<br />
<br />
  Serial.print(rtc.getHour(h12Flag, pmFlag), DEC);<br />
  Serial.print(":");<br />
  Serial.print(rtc.getMinute(), DEC);<br />
  Serial.print(":");<br />
  Serial.println(rtc.getSecond(), DEC);<br />
}<br />
<br />
/**<br />
 * @brief Process serial commands to set the RTC time.<br />
 * Command format: DYYYY-MM-DDTHH:MM:SS<br />
 */<br />
static void GetSerialCmd()<br />
{<br />
  if (Serial.available() &gt; 0)<br />
  {<br />
    delay(100);<br />
    int num_read = Serial.available();<br />
    while (num_read--)<br />
      serial_cmd_rcv += char(Serial.read());<br />
  }<br />
  else return;<br />
<br />
  serial_cmd_rcv.trim();<br />
<br />
  if (serial_cmd_rcv == "current time")<br />
  {<br />
    PrintfCurTime();<br />
    serial_cmd_rcv = "";<br />
    return;<br />
  }<br />
<br />
  Serial.print("Received length: ");<br />
  Serial.println(serial_cmd_rcv.length());<br />
<br />
  int indexof_d = serial_cmd_rcv.indexOf('D');<br />
  int indexof_t = serial_cmd_rcv.indexOf('T');<br />
<br />
  Serial.print("D index: ");<br />
  Serial.print(indexof_d);<br />
  Serial.print(" T index: ");<br />
  Serial.println(indexof_t);<br />
<br />
  if (serial_cmd_rcv.length() != 20 || <br />
      serial_cmd_rcv.substring(0, 1) != "D" ||<br />
      serial_cmd_rcv.substring(11, 12) != "T")  <br />
  {<br />
    Serial.println(serial_cmd_rcv);<br />
    serial_cmd_rcv = "";<br />
    return;<br />
  }<br />
<br />
  Serial.println("Setting time...");<br />
<br />
  my_date_str.year = (byte)serial_cmd_rcv.substring(3, 5).toInt();<br />
  my_date_str.month = (byte)serial_cmd_rcv.substring(6, 8).toInt();<br />
  my_date_str.day = (byte)serial_cmd_rcv.substring(9, 11).toInt();<br />
  my_date_str.hour = (byte)serial_cmd_rcv.substring(12, 14).toInt();<br />
  my_date_str.minute = (byte)serial_cmd_rcv.substring(15, 17).toInt();<br />
  my_date_str.second = (byte)serial_cmd_rcv.substring(18).toInt();<br />
<br />
  rtc.setYear(my_date_str.year);<br />
  rtc.setMonth(my_date_str.month);<br />
  rtc.setDate(my_date_str.day);<br />
  rtc.setHour(my_date_str.hour);<br />
  rtc.setMinute(my_date_str.minute);<br />
  rtc.setSecond(my_date_str.second);<br />
<br />
  serial_cmd_rcv = "";<br />
<br />
  Serial.println("Time set.");<br />
}<br />
<br />
void setup() {<br />
  // Initialize the I2C interface<br />
  Wire.begin(SDA_PIN, SCL_PIN, 40000);<br />
  <br />
  // Initialize Serial communication<br />
  Serial.begin(115200);<br />
 &nbsp;&nbsp;<br />
  // Set the RTC to 24-hour mode<br />
  rtc.setClockMode(false); // 24-hour format<br />
<br />
  // Print current time to Serial Monitor<br />
  PrintfCurTime();<br />
<br />
  // Clear any remaining serial data<br />
  while (Serial.read() &gt;= 0) {}<br />
}<br />
<br />
void loop() {<br />
  // Process incoming serial commands<br />
  GetSerialCmd(); <br />
  delay(1000); // Delay for 1 second<br />
}</code></div></div> arduino ino file download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10346" target="_blank" title="">7-DS3231-RTC.zip</a> (Size: 1.56 KB / Downloads: 7)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10347" target="_blank" title="">7-DS3231-RTC.ino.merged.zip</a> (Size: 191.08 KB / Downloads: 7)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[arduino code examples for CO16]-06 How to use SD Card]]></title>
			<link>https://www.kincony.com/forum/showthread.php?tid=9787</link>
			<pubDate>Mon, 31 Aug 2026 08:06:31 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://www.kincony.com/forum/member.php?action=profile&uid=1">admin</a>]]></dc:creator>
			<guid isPermaLink="false">https://www.kincony.com/forum/showthread.php?tid=9787</guid>
			<description><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
 * Made by KinCony IoT: https://www.kincony.com<br />
 *<br />
 * SD Card File Operations<br />
 *<br />
 * This program demonstrates basic file operations on an SD card using the ESP32.<br />
 * It includes functionality to:<br />
 * - Initialize and test the SD card<br />
 * - Read from, write to, append to, and delete files on the SD card<br />
 * - Measure file read and write performance<br />
 *<br />
 * Hardware Connections:<br />
 * - SCK: GPIO 11<br />
 * - MISO: GPIO 12<br />
 * - MOSI: GPIO 10<br />
 * - CS: GPIO 9<br />
 */<br />
<br />
#include "FS.h"<br />
#include "SD.h"<br />
#include "SPI.h"<br />
<br />
// Pin definitions for SD card<br />
#define SCK  11<br />
#define MISO 12<br />
#define MOSI 10<br />
#define CS &nbsp;&nbsp;9<br />
<br />
/**<br />
 * @brief Reads the contents of a file from the SD card and prints it to the serial monitor.<br />
 * <br />
 * @param fs File system to use (in this case, SD).<br />
 * @param path Path of the file to read.<br />
 */<br />
void readFile(fs::FS &amp;fs, const char * path) {<br />
  Serial.printf("Reading file: %s&#92;n", path);<br />
<br />
  File file = fs.open(path);<br />
  if (!file) {<br />
    Serial.println("Failed to open file for reading");<br />
    return;<br />
  }<br />
<br />
  Serial.print("Read from file: ");<br />
  while (file.available()) {<br />
    Serial.print((char)file.read());<br />
  }<br />
  file.close();<br />
}<br />
<br />
/**<br />
 * @brief Writes a message to a file on the SD card.<br />
 * <br />
 * @param fs File system to use (in this case, SD).<br />
 * @param path Path of the file to write.<br />
 * @param message Message to write to the file.<br />
 */<br />
void writeFile(fs::FS &amp;fs, const char * path, const char * message) {<br />
  Serial.printf("Writing file: %s&#92;n", path);<br />
<br />
  File file = fs.open(path, FILE_WRITE);<br />
  if (!file) {<br />
    Serial.println("Failed to open file for writing");<br />
    return;<br />
  }<br />
  if (file.print(message)) {<br />
    Serial.println("File written");<br />
  } else {<br />
    Serial.println("Write failed");<br />
  }<br />
  file.close();<br />
}<br />
<br />
/**<br />
 * @brief Appends a message to a file on the SD card.<br />
 * <br />
 * @param fs File system to use (in this case, SD).<br />
 * @param path Path of the file to append.<br />
 * @param message Message to append to the file.<br />
 */<br />
void appendFile(fs::FS &amp;fs, const char * path, const char * message) {<br />
  Serial.printf("Appending to file: %s&#92;n", path);<br />
<br />
  File file = fs.open(path, FILE_APPEND);<br />
  if (!file) {<br />
    Serial.println("Failed to open file for appending");<br />
    return;<br />
  }<br />
  if (file.print(message)) {<br />
    Serial.println("Message appended");<br />
  } else {<br />
    Serial.println("Append failed");<br />
  }<br />
  file.close();<br />
}<br />
<br />
/**<br />
 * @brief Deletes a file from the SD card.<br />
 * <br />
 * @param fs File system to use (in this case, SD).<br />
 * @param path Path of the file to delete.<br />
 */<br />
void deleteFile(fs::FS &amp;fs, const char * path) {<br />
  Serial.printf("Deleting file: %s&#92;n", path);<br />
  if (fs.remove(path)) {<br />
    Serial.println("File deleted");<br />
  } else {<br />
    Serial.println("Delete failed");<br />
  }<br />
}<br />
<br />
/**<br />
 * @brief Tests file read and write performance.<br />
 * <br />
 * @param fs File system to use (in this case, SD).<br />
 * @param path Path of the file to test.<br />
 */<br />
void testFileIO(fs::FS &amp;fs, const char * path) {<br />
  File file = fs.open(path);<br />
  static uint8_t buf[512];<br />
  size_t len = 0;<br />
  uint32_t start = millis();<br />
  uint32_t end = start;<br />
<br />
  if (file) {<br />
    len = file.size();<br />
    size_t flen = len;<br />
    start = millis();<br />
    while (len) {<br />
      size_t toRead = len;<br />
      if (toRead &gt; 512) {<br />
        toRead = 512;<br />
      }<br />
      file.read(buf, toRead);<br />
      len -= toRead;<br />
    }<br />
    end = millis() - start;<br />
    Serial.printf("%u bytes read for %u ms&#92;n", flen, end);<br />
    file.close();<br />
  } else {<br />
    Serial.println("Failed to open file for reading");<br />
  }<br />
<br />
  file = fs.open(path, FILE_WRITE);<br />
  if (!file) {<br />
    Serial.println("Failed to open file for writing");<br />
    return;<br />
  }<br />
<br />
  size_t i;<br />
  start = millis();<br />
  for (i = 0; i &lt; 2048; i++) {<br />
    file.write(buf, 512);<br />
  }<br />
  end = millis() - start;<br />
  Serial.printf("%u bytes written for %u ms&#92;n", 2048 * 512, end);<br />
  file.close();<br />
}<br />
<br />
void setup() {<br />
  // Initialize serial communication<br />
  Serial.begin(115200);<br />
  <br />
  // Initialize SPI and SD card<br />
  SPIClass spi = SPIClass(HSPI);<br />
  spi.begin(SCK, MISO, MOSI, CS);<br />
<br />
  if (!SD.begin(CS, spi, 80000000)) {<br />
    Serial.println("Card Mount Failed");<br />
    return;<br />
  }<br />
<br />
  uint8_t cardType = SD.cardType();<br />
<br />
  if (cardType == CARD_NONE) {<br />
    Serial.println("No SD card attached");<br />
    return;<br />
  }<br />
<br />
  Serial.print("SD Card Type: ");<br />
  if (cardType == CARD_MMC) {<br />
    Serial.println("MMC");<br />
  } else if (cardType == CARD_SD) {<br />
    Serial.println("SDSC");<br />
  } else if (cardType == CARD_SDHC) {<br />
    Serial.println("SDHC");<br />
  } else {<br />
    Serial.println("UNKNOWN");<br />
  }<br />
<br />
  uint64_t cardSize = SD.cardSize() / (1024 * 1024);<br />
  Serial.printf("SD Card Size: %lluMB&#92;n", cardSize);<br />
  delay(2000);<br />
<br />
  // Perform file operations<br />
  deleteFile(SD, "/hello.txt");<br />
  writeFile(SD, "/hello.txt", "Hello ");<br />
  appendFile(SD, "/hello.txt", "World!&#92;n");<br />
  readFile(SD, "/hello.txt");<br />
  testFileIO(SD, "/test.txt");<br />
  Serial.printf("Total space: %lluMB&#92;n", SD.totalBytes() / (1024 * 1024));<br />
  Serial.printf("Used space: %lluMB&#92;n", SD.usedBytes() / (1024 * 1024));<br />
}<br />
<br />
void loop() {<br />
  // No operation in loop<br />
}</code></div></div> arduino ino file download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10344" target="_blank" title="">6-SD.zip</a> (Size: 1.53 KB / Downloads: 8)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10345" target="_blank" title="">6-SD.ino.merged.zip</a> (Size: 221.25 KB / Downloads: 10)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
 * Made by KinCony IoT: https://www.kincony.com<br />
 *<br />
 * SD Card File Operations<br />
 *<br />
 * This program demonstrates basic file operations on an SD card using the ESP32.<br />
 * It includes functionality to:<br />
 * - Initialize and test the SD card<br />
 * - Read from, write to, append to, and delete files on the SD card<br />
 * - Measure file read and write performance<br />
 *<br />
 * Hardware Connections:<br />
 * - SCK: GPIO 11<br />
 * - MISO: GPIO 12<br />
 * - MOSI: GPIO 10<br />
 * - CS: GPIO 9<br />
 */<br />
<br />
#include "FS.h"<br />
#include "SD.h"<br />
#include "SPI.h"<br />
<br />
// Pin definitions for SD card<br />
#define SCK  11<br />
#define MISO 12<br />
#define MOSI 10<br />
#define CS &nbsp;&nbsp;9<br />
<br />
/**<br />
 * @brief Reads the contents of a file from the SD card and prints it to the serial monitor.<br />
 * <br />
 * @param fs File system to use (in this case, SD).<br />
 * @param path Path of the file to read.<br />
 */<br />
void readFile(fs::FS &amp;fs, const char * path) {<br />
  Serial.printf("Reading file: %s&#92;n", path);<br />
<br />
  File file = fs.open(path);<br />
  if (!file) {<br />
    Serial.println("Failed to open file for reading");<br />
    return;<br />
  }<br />
<br />
  Serial.print("Read from file: ");<br />
  while (file.available()) {<br />
    Serial.print((char)file.read());<br />
  }<br />
  file.close();<br />
}<br />
<br />
/**<br />
 * @brief Writes a message to a file on the SD card.<br />
 * <br />
 * @param fs File system to use (in this case, SD).<br />
 * @param path Path of the file to write.<br />
 * @param message Message to write to the file.<br />
 */<br />
void writeFile(fs::FS &amp;fs, const char * path, const char * message) {<br />
  Serial.printf("Writing file: %s&#92;n", path);<br />
<br />
  File file = fs.open(path, FILE_WRITE);<br />
  if (!file) {<br />
    Serial.println("Failed to open file for writing");<br />
    return;<br />
  }<br />
  if (file.print(message)) {<br />
    Serial.println("File written");<br />
  } else {<br />
    Serial.println("Write failed");<br />
  }<br />
  file.close();<br />
}<br />
<br />
/**<br />
 * @brief Appends a message to a file on the SD card.<br />
 * <br />
 * @param fs File system to use (in this case, SD).<br />
 * @param path Path of the file to append.<br />
 * @param message Message to append to the file.<br />
 */<br />
void appendFile(fs::FS &amp;fs, const char * path, const char * message) {<br />
  Serial.printf("Appending to file: %s&#92;n", path);<br />
<br />
  File file = fs.open(path, FILE_APPEND);<br />
  if (!file) {<br />
    Serial.println("Failed to open file for appending");<br />
    return;<br />
  }<br />
  if (file.print(message)) {<br />
    Serial.println("Message appended");<br />
  } else {<br />
    Serial.println("Append failed");<br />
  }<br />
  file.close();<br />
}<br />
<br />
/**<br />
 * @brief Deletes a file from the SD card.<br />
 * <br />
 * @param fs File system to use (in this case, SD).<br />
 * @param path Path of the file to delete.<br />
 */<br />
void deleteFile(fs::FS &amp;fs, const char * path) {<br />
  Serial.printf("Deleting file: %s&#92;n", path);<br />
  if (fs.remove(path)) {<br />
    Serial.println("File deleted");<br />
  } else {<br />
    Serial.println("Delete failed");<br />
  }<br />
}<br />
<br />
/**<br />
 * @brief Tests file read and write performance.<br />
 * <br />
 * @param fs File system to use (in this case, SD).<br />
 * @param path Path of the file to test.<br />
 */<br />
void testFileIO(fs::FS &amp;fs, const char * path) {<br />
  File file = fs.open(path);<br />
  static uint8_t buf[512];<br />
  size_t len = 0;<br />
  uint32_t start = millis();<br />
  uint32_t end = start;<br />
<br />
  if (file) {<br />
    len = file.size();<br />
    size_t flen = len;<br />
    start = millis();<br />
    while (len) {<br />
      size_t toRead = len;<br />
      if (toRead &gt; 512) {<br />
        toRead = 512;<br />
      }<br />
      file.read(buf, toRead);<br />
      len -= toRead;<br />
    }<br />
    end = millis() - start;<br />
    Serial.printf("%u bytes read for %u ms&#92;n", flen, end);<br />
    file.close();<br />
  } else {<br />
    Serial.println("Failed to open file for reading");<br />
  }<br />
<br />
  file = fs.open(path, FILE_WRITE);<br />
  if (!file) {<br />
    Serial.println("Failed to open file for writing");<br />
    return;<br />
  }<br />
<br />
  size_t i;<br />
  start = millis();<br />
  for (i = 0; i &lt; 2048; i++) {<br />
    file.write(buf, 512);<br />
  }<br />
  end = millis() - start;<br />
  Serial.printf("%u bytes written for %u ms&#92;n", 2048 * 512, end);<br />
  file.close();<br />
}<br />
<br />
void setup() {<br />
  // Initialize serial communication<br />
  Serial.begin(115200);<br />
  <br />
  // Initialize SPI and SD card<br />
  SPIClass spi = SPIClass(HSPI);<br />
  spi.begin(SCK, MISO, MOSI, CS);<br />
<br />
  if (!SD.begin(CS, spi, 80000000)) {<br />
    Serial.println("Card Mount Failed");<br />
    return;<br />
  }<br />
<br />
  uint8_t cardType = SD.cardType();<br />
<br />
  if (cardType == CARD_NONE) {<br />
    Serial.println("No SD card attached");<br />
    return;<br />
  }<br />
<br />
  Serial.print("SD Card Type: ");<br />
  if (cardType == CARD_MMC) {<br />
    Serial.println("MMC");<br />
  } else if (cardType == CARD_SD) {<br />
    Serial.println("SDSC");<br />
  } else if (cardType == CARD_SDHC) {<br />
    Serial.println("SDHC");<br />
  } else {<br />
    Serial.println("UNKNOWN");<br />
  }<br />
<br />
  uint64_t cardSize = SD.cardSize() / (1024 * 1024);<br />
  Serial.printf("SD Card Size: %lluMB&#92;n", cardSize);<br />
  delay(2000);<br />
<br />
  // Perform file operations<br />
  deleteFile(SD, "/hello.txt");<br />
  writeFile(SD, "/hello.txt", "Hello ");<br />
  appendFile(SD, "/hello.txt", "World!&#92;n");<br />
  readFile(SD, "/hello.txt");<br />
  testFileIO(SD, "/test.txt");<br />
  Serial.printf("Total space: %lluMB&#92;n", SD.totalBytes() / (1024 * 1024));<br />
  Serial.printf("Used space: %lluMB&#92;n", SD.usedBytes() / (1024 * 1024));<br />
}<br />
<br />
void loop() {<br />
  // No operation in loop<br />
}</code></div></div> arduino ino file download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10344" target="_blank" title="">6-SD.zip</a> (Size: 1.53 KB / Downloads: 8)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10345" target="_blank" title="">6-SD.ino.merged.zip</a> (Size: 221.25 KB / Downloads: 10)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[arduino code examples for CO16]-05 Read PT100 temperature sensor]]></title>
			<link>https://www.kincony.com/forum/showthread.php?tid=9786</link>
			<pubDate>Mon, 31 Aug 2026 08:04:58 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://www.kincony.com/forum/member.php?action=profile&uid=1">admin</a>]]></dc:creator>
			<guid isPermaLink="false">https://www.kincony.com/forum/showthread.php?tid=9786</guid>
			<description><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#include &lt;Adafruit_MAX31865.h&gt;<br />
<br />
namespace {<br />
<br />
// CO16 MAX31865 software-SPI pins.<br />
constexpr int kPt100Sclk = 11;<br />
constexpr int kPt100Mosi = 10;<br />
constexpr int kPt100Miso = 12;<br />
constexpr int kPt100Cs = 14;<br />
<br />
// NX3L4051PW channel select pins. S3 is fixed LOW on CO16.<br />
constexpr int kMuxS1 = 7;<br />
constexpr int kMuxS2 = 21;<br />
constexpr uint8_t kPt100ChannelCount = 4;<br />
constexpr uint32_t kMuxSettlingTimeMs = 20;<br />
<br />
constexpr float kRtdNominalOhms = 100.0F;<br />
constexpr float kReferenceResistorOhms = 400.0F;<br />
<br />
Adafruit_MAX31865 pt100(kPt100Cs, kPt100Mosi, kPt100Miso, kPt100Sclk);<br />
<br />
void selectPt100Channel(uint8_t channel) {<br />
  const uint8_t muxAddress = channel - 1;<br />
<br />
  // S3 is fixed LOW, so S2/S1 select PT100 channels 1-4.<br />
  digitalWrite(kMuxS1, muxAddress &amp; 0x01);<br />
  digitalWrite(kMuxS2, (muxAddress &gt;&gt; 1) &amp; 0x01);<br />
  delay(kMuxSettlingTimeMs);<br />
}<br />
<br />
void printFault(uint8_t fault) {<br />
  Serial.printf(" fault=0x%02X", fault);<br />
  if (fault &amp; MAX31865_FAULT_HIGHTHRESH) {<br />
    Serial.print(" RTD_HIGH_THRESHOLD");<br />
  }<br />
  if (fault &amp; MAX31865_FAULT_LOWTHRESH) {<br />
    Serial.print(" RTD_LOW_THRESHOLD");<br />
  }<br />
  if (fault &amp; MAX31865_FAULT_REFINLOW) {<br />
    Serial.print(" REFIN_HIGH");<br />
  }<br />
  if (fault &amp; MAX31865_FAULT_REFINHIGH) {<br />
    Serial.print(" REFIN_LOW_OR_FORCE_OPEN");<br />
  }<br />
  if (fault &amp; MAX31865_FAULT_RTDINLOW) {<br />
    Serial.print(" RTDIN_LOW_OR_FORCE_OPEN");<br />
  }<br />
  if (fault &amp; MAX31865_FAULT_OVUV) {<br />
    Serial.print(" OVER_UNDERVOLTAGE");<br />
  }<br />
}<br />
<br />
}  // namespace<br />
<br />
void setup() {<br />
  Serial.begin(115200);<br />
  delay(1000);<br />
<br />
  pinMode(kMuxS1, OUTPUT);<br />
  pinMode(kMuxS2, OUTPUT);<br />
  selectPt100Channel(1);<br />
<br />
  Serial.println();<br />
  Serial.println("KinCony CO16 four-channel PT100 example");<br />
  Serial.printf("MUX S3=LOW S2=%d S1=%d; SPI SCLK=%d MOSI=%d MISO=%d CS=%d&#92;n",<br />
                kMuxS2, kMuxS1, kPt100Sclk, kPt100Mosi, kPt100Miso,<br />
                kPt100Cs);<br />
<br />
  pt100.begin(MAX31865_3WIRE);<br />
  pt100.enable50Hz(true);<br />
}<br />
<br />
void loop() {<br />
  for (uint8_t channel = 1; channel &lt;= kPt100ChannelCount; ++channel) {<br />
    selectPt100Channel(channel);<br />
<br />
    const uint16_t raw = pt100.readRTD();<br />
    const float resistance =<br />
        static_cast&lt;float&gt;(raw) * kReferenceResistorOhms / 32768.0F;<br />
    const float temperature = pt100.calculateTemperature(<br />
        raw, kRtdNominalOhms, kReferenceResistorOhms);<br />
    const uint8_t fault = pt100.readFault(MAX31865_FAULT_NONE);<br />
<br />
    Serial.printf("CH%u raw=%u resistance=%.3f ohm temperature=%.2f C",<br />
                  channel, raw, resistance, temperature);<br />
    if (fault != 0) {<br />
      printFault(fault);<br />
      pt100.clearFault();<br />
    } else {<br />
      Serial.print(" fault=0x00");<br />
    }<br />
    Serial.println();<br />
  }<br />
<br />
  Serial.println();<br />
  delay(1000);<br />
}</code></div></div> arduino ino file download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10341" target="_blank" title="">5-PT100.zip</a> (Size: 1.11 KB / Downloads: 8)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download: <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10342" target="_blank" title="">5-PT100.ino.merged.zip</a> (Size: 198.5 KB / Downloads: 12)
<!-- end: postbit_attachments_attachment --><br />
before run code , need install max31865 arduino library<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/image.png" title="PNG Image" border="0" alt=".png" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10343" target="_blank" title="">max31865-library.png</a> (Size: 122.09 KB / Downloads: 13)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#include &lt;Adafruit_MAX31865.h&gt;<br />
<br />
namespace {<br />
<br />
// CO16 MAX31865 software-SPI pins.<br />
constexpr int kPt100Sclk = 11;<br />
constexpr int kPt100Mosi = 10;<br />
constexpr int kPt100Miso = 12;<br />
constexpr int kPt100Cs = 14;<br />
<br />
// NX3L4051PW channel select pins. S3 is fixed LOW on CO16.<br />
constexpr int kMuxS1 = 7;<br />
constexpr int kMuxS2 = 21;<br />
constexpr uint8_t kPt100ChannelCount = 4;<br />
constexpr uint32_t kMuxSettlingTimeMs = 20;<br />
<br />
constexpr float kRtdNominalOhms = 100.0F;<br />
constexpr float kReferenceResistorOhms = 400.0F;<br />
<br />
Adafruit_MAX31865 pt100(kPt100Cs, kPt100Mosi, kPt100Miso, kPt100Sclk);<br />
<br />
void selectPt100Channel(uint8_t channel) {<br />
  const uint8_t muxAddress = channel - 1;<br />
<br />
  // S3 is fixed LOW, so S2/S1 select PT100 channels 1-4.<br />
  digitalWrite(kMuxS1, muxAddress &amp; 0x01);<br />
  digitalWrite(kMuxS2, (muxAddress &gt;&gt; 1) &amp; 0x01);<br />
  delay(kMuxSettlingTimeMs);<br />
}<br />
<br />
void printFault(uint8_t fault) {<br />
  Serial.printf(" fault=0x%02X", fault);<br />
  if (fault &amp; MAX31865_FAULT_HIGHTHRESH) {<br />
    Serial.print(" RTD_HIGH_THRESHOLD");<br />
  }<br />
  if (fault &amp; MAX31865_FAULT_LOWTHRESH) {<br />
    Serial.print(" RTD_LOW_THRESHOLD");<br />
  }<br />
  if (fault &amp; MAX31865_FAULT_REFINLOW) {<br />
    Serial.print(" REFIN_HIGH");<br />
  }<br />
  if (fault &amp; MAX31865_FAULT_REFINHIGH) {<br />
    Serial.print(" REFIN_LOW_OR_FORCE_OPEN");<br />
  }<br />
  if (fault &amp; MAX31865_FAULT_RTDINLOW) {<br />
    Serial.print(" RTDIN_LOW_OR_FORCE_OPEN");<br />
  }<br />
  if (fault &amp; MAX31865_FAULT_OVUV) {<br />
    Serial.print(" OVER_UNDERVOLTAGE");<br />
  }<br />
}<br />
<br />
}  // namespace<br />
<br />
void setup() {<br />
  Serial.begin(115200);<br />
  delay(1000);<br />
<br />
  pinMode(kMuxS1, OUTPUT);<br />
  pinMode(kMuxS2, OUTPUT);<br />
  selectPt100Channel(1);<br />
<br />
  Serial.println();<br />
  Serial.println("KinCony CO16 four-channel PT100 example");<br />
  Serial.printf("MUX S3=LOW S2=%d S1=%d; SPI SCLK=%d MOSI=%d MISO=%d CS=%d&#92;n",<br />
                kMuxS2, kMuxS1, kPt100Sclk, kPt100Mosi, kPt100Miso,<br />
                kPt100Cs);<br />
<br />
  pt100.begin(MAX31865_3WIRE);<br />
  pt100.enable50Hz(true);<br />
}<br />
<br />
void loop() {<br />
  for (uint8_t channel = 1; channel &lt;= kPt100ChannelCount; ++channel) {<br />
    selectPt100Channel(channel);<br />
<br />
    const uint16_t raw = pt100.readRTD();<br />
    const float resistance =<br />
        static_cast&lt;float&gt;(raw) * kReferenceResistorOhms / 32768.0F;<br />
    const float temperature = pt100.calculateTemperature(<br />
        raw, kRtdNominalOhms, kReferenceResistorOhms);<br />
    const uint8_t fault = pt100.readFault(MAX31865_FAULT_NONE);<br />
<br />
    Serial.printf("CH%u raw=%u resistance=%.3f ohm temperature=%.2f C",<br />
                  channel, raw, resistance, temperature);<br />
    if (fault != 0) {<br />
      printFault(fault);<br />
      pt100.clearFault();<br />
    } else {<br />
      Serial.print(" fault=0x00");<br />
    }<br />
    Serial.println();<br />
  }<br />
<br />
  Serial.println();<br />
  delay(1000);<br />
}</code></div></div> arduino ino file download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10341" target="_blank" title="">5-PT100.zip</a> (Size: 1.11 KB / Downloads: 8)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download: <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10342" target="_blank" title="">5-PT100.ino.merged.zip</a> (Size: 198.5 KB / Downloads: 12)
<!-- end: postbit_attachments_attachment --><br />
before run code , need install max31865 arduino library<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/image.png" title="PNG Image" border="0" alt=".png" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10343" target="_blank" title="">max31865-library.png</a> (Size: 122.09 KB / Downloads: 13)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[arduino code examples for CO16]-04 RS485 communication test]]></title>
			<link>https://www.kincony.com/forum/showthread.php?tid=9785</link>
			<pubDate>Mon, 31 Aug 2026 08:02:27 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://www.kincony.com/forum/member.php?action=profile&uid=1">admin</a>]]></dc:creator>
			<guid isPermaLink="false">https://www.kincony.com/forum/showthread.php?tid=9785</guid>
			<description><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
 * Made by KinCony IoT: https://www.kincony.com<br />
 *<br />
 * RS485 Communication Test<br />
 *<br />
 * This program is a simple test for RS485 communication using ESP32-S3.<br />
 * It will send a message over RS485 and then read incoming messages.<br />
 * The TXD pin is defined as GPIO 18 and RXD pin is defined as GPIO 8.<br />
 */<br />
<br />
#include &lt;HardwareSerial.h&gt;<br />
<br />
// Define RS485 pins<br />
#define RS485_RXD 38<br />
#define RS485_TXD 39<br />
<br />
// Create a hardware serial object<br />
HardwareSerial rs485Serial(1);<br />
<br />
void setup() {<br />
  // Start serial communication for debugging<br />
  Serial.begin(115200);<br />
  while (!Serial);<br />
<br />
  // Initialize RS485 Serial communication<br />
  rs485Serial.begin(9600, SERIAL_8N1, RS485_RXD, RS485_TXD);<br />
  <br />
  Serial.println("RS485 Test Start");<br />
}<br />
<br />
void loop() {<br />
  // Send a test message<br />
  rs485Serial.println("Hello from KinCony!");<br />
<br />
  // Wait for a short period<br />
  delay(1000);<br />
<br />
  // Check if data is available to read<br />
  if (rs485Serial.available()) {<br />
    String receivedMessage = "";<br />
    while (rs485Serial.available()) {<br />
      char c = rs485Serial.read();<br />
      receivedMessage += c;<br />
    }<br />
    // Print the received message<br />
    Serial.print("Received: ");<br />
    Serial.println(receivedMessage);<br />
  }<br />
<br />
  // Wait before sending the next message<br />
  delay(2000);<br />
}</code></div></div> arduino ino file download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10339" target="_blank" title="">4-RS485-Test.zip</a> (Size: 760 bytes / Downloads: 7)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10340" target="_blank" title="">4-RS485-Test.ino.merged.zip</a> (Size: 190.1 KB / Downloads: 5)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
 * Made by KinCony IoT: https://www.kincony.com<br />
 *<br />
 * RS485 Communication Test<br />
 *<br />
 * This program is a simple test for RS485 communication using ESP32-S3.<br />
 * It will send a message over RS485 and then read incoming messages.<br />
 * The TXD pin is defined as GPIO 18 and RXD pin is defined as GPIO 8.<br />
 */<br />
<br />
#include &lt;HardwareSerial.h&gt;<br />
<br />
// Define RS485 pins<br />
#define RS485_RXD 38<br />
#define RS485_TXD 39<br />
<br />
// Create a hardware serial object<br />
HardwareSerial rs485Serial(1);<br />
<br />
void setup() {<br />
  // Start serial communication for debugging<br />
  Serial.begin(115200);<br />
  while (!Serial);<br />
<br />
  // Initialize RS485 Serial communication<br />
  rs485Serial.begin(9600, SERIAL_8N1, RS485_RXD, RS485_TXD);<br />
  <br />
  Serial.println("RS485 Test Start");<br />
}<br />
<br />
void loop() {<br />
  // Send a test message<br />
  rs485Serial.println("Hello from KinCony!");<br />
<br />
  // Wait for a short period<br />
  delay(1000);<br />
<br />
  // Check if data is available to read<br />
  if (rs485Serial.available()) {<br />
    String receivedMessage = "";<br />
    while (rs485Serial.available()) {<br />
      char c = rs485Serial.read();<br />
      receivedMessage += c;<br />
    }<br />
    // Print the received message<br />
    Serial.print("Received: ");<br />
    Serial.println(receivedMessage);<br />
  }<br />
<br />
  // Wait before sending the next message<br />
  delay(2000);<br />
}</code></div></div> arduino ino file download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10339" target="_blank" title="">4-RS485-Test.zip</a> (Size: 760 bytes / Downloads: 7)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download:  <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10340" target="_blank" title="">4-RS485-Test.ino.merged.zip</a> (Size: 190.1 KB / Downloads: 5)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[arduino code examples for CO16]-03 Read analog input ports value]]></title>
			<link>https://www.kincony.com/forum/showthread.php?tid=9784</link>
			<pubDate>Mon, 31 Aug 2026 08:00:50 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://www.kincony.com/forum/member.php?action=profile&uid=1">admin</a>]]></dc:creator>
			<guid isPermaLink="false">https://www.kincony.com/forum/showthread.php?tid=9784</guid>
			<description><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
 * KinCony 16-Channel Analog Input Monitor<br />
 *<br />
 * Four ADS1115 ADC modules are used:<br />
 *<br />
 * ADS1115-1 (U35): CH1-CH4 &nbsp;&nbsp;I2C address: 0x48<br />
 * ADS1115-2 (U7):  CH5-CH8 &nbsp;&nbsp;I2C address: 0x49<br />
 * ADS1115-3 (U15): CH9-CH12  I2C address: 0x4B<br />
 * ADS1115-4 (U19): CH13-CH16 I2C address: 0x4A<br />
 *<br />
 * ESPHome equivalent configuration:<br />
 *<br />
 * gain: 4.096<br />
 * filters:<br />
 * &nbsp;&nbsp;- lambda: 'return x &lt;= 0.0025f ? 0.0f : x;'<br />
 * &nbsp;&nbsp;- multiply: 5.16696<br />
 * &nbsp;&nbsp;- clamp:<br />
 *     &nbsp;&nbsp;min_value: 0.0<br />
 *     &nbsp;&nbsp;max_value: 10.0<br />
 *<br />
 * Only channels with an input voltage greater than 0.5V<br />
 * will be printed.<br />
 *<br />
 * Copyright: Made by KinCony IoT: https://www.kincony.com<br />
 */<br />
<br />
#include &lt;Wire.h&gt;<br />
#include &lt;DFRobot_ADS1115.h&gt;<br />
<br />
// I2C pins<br />
#define SDA_PIN 8<br />
#define SCL_PIN 18<br />
<br />
// ADS1115 I2C addresses<br />
#define ADS1115_1_ADDR 0x48<br />
#define ADS1115_2_ADDR 0x49<br />
#define ADS1115_3_ADDR 0x4B<br />
#define ADS1115_4_ADDR 0x4A<br />
<br />
// ESPHome calibration multiplier<br />
#define VOLTAGE_MULTIPLIER 5.16696f<br />
<br />
// ESPHome zero threshold<br />
#define ADC_ZERO_THRESHOLD 0.0025f<br />
<br />
// Print threshold<br />
#define PRINT_THRESHOLD 0.5f<br />
<br />
// Maximum input voltage<br />
#define MAX_INPUT_VOLTAGE 10.0f<br />
<br />
<br />
// Create ADS1115 objects<br />
DFRobot_ADS1115 ads1(&amp;Wire);<br />
DFRobot_ADS1115 ads2(&amp;Wire);<br />
DFRobot_ADS1115 ads3(&amp;Wire);<br />
DFRobot_ADS1115 ads4(&amp;Wire);<br />
<br />
<br />
/*<br />
 * Read ADS1115 channel and convert to actual input voltage.<br />
 *<br />
 * DFRobot readVoltage() returns voltage in mV.<br />
 *<br />
 * ESPHome:<br />
 *   &nbsp;&nbsp;x &lt;= 0.0025V -&gt; 0V<br />
 *   &nbsp;&nbsp;x * 5.16696<br />
 *   &nbsp;&nbsp;clamp 0~10V<br />
 */<br />
float readInputVoltage(DFRobot_ADS1115 &amp;ads, uint8_t channel)<br />
{<br />
    // Read ADC voltage in mV<br />
    uint16_t adc_mV = ads.readVoltage(channel);<br />
<br />
    // Convert mV to V<br />
    float adcVoltage = adc_mV / 1000.0f;<br />
<br />
    // ESPHome lambda filter<br />
    if (adcVoltage &lt;= ADC_ZERO_THRESHOLD)<br />
    {<br />
        return 0.0f;<br />
    }<br />
<br />
    // ESPHome multiply filter<br />
    float inputVoltage = adcVoltage * VOLTAGE_MULTIPLIER;<br />
<br />
    // ESPHome clamp filter<br />
    if (inputVoltage &lt; 0.0f)<br />
    {<br />
        inputVoltage = 0.0f;<br />
    }<br />
<br />
    if (inputVoltage &gt; MAX_INPUT_VOLTAGE)<br />
    {<br />
        inputVoltage = MAX_INPUT_VOLTAGE;<br />
    }<br />
<br />
    return inputVoltage;<br />
}<br />
<br />
<br />
/*<br />
 * Check one analog channel.<br />
 *<br />
 * If the actual input voltage is greater than 0.5V,<br />
 * print the channel number and voltage.<br />
 */<br />
void checkChannel(<br />
    DFRobot_ADS1115 &amp;ads,<br />
    uint8_t adcChannel,<br />
    uint8_t channelNumber)<br />
{<br />
    float voltage = readInputVoltage(ads, adcChannel);<br />
<br />
    if (voltage &gt; PRINT_THRESHOLD)<br />
    {<br />
        Serial.print("CH");<br />
        Serial.print(channelNumber);<br />
        Serial.print(": ");<br />
<br />
        Serial.print(voltage, 2);<br />
<br />
        Serial.println(" V");<br />
    }<br />
}<br />
<br />
<br />
void setup(void)<br />
{<br />
    // Initialize serial communication<br />
    Serial.begin(115200);<br />
<br />
    // Initialize I2C<br />
    Wire.begin(SDA_PIN, SCL_PIN);<br />
<br />
    /*<br />
   &nbsp;&nbsp;* ADS1115 gain = 4.096V<br />
   &nbsp;&nbsp;*<br />
   &nbsp;&nbsp;* This corresponds to ESPHome:<br />
   &nbsp;&nbsp;*<br />
   &nbsp;&nbsp;* gain: 4.096<br />
   &nbsp;&nbsp;*<br />
   &nbsp;&nbsp;* DFRobot library:<br />
   &nbsp;&nbsp;* eGAIN_ONE = 4.096V<br />
   &nbsp;&nbsp;*/<br />
<br />
    // ADS1115-1<br />
    ads1.setAddr_ADS1115(ADS1115_1_ADDR);<br />
    ads1.setGain(eGAIN_ONE);<br />
    ads1.setMode(eMODE_SINGLE);<br />
    ads1.setRate(eRATE_128);<br />
    ads1.setOSMode(eOSMODE_SINGLE);<br />
    ads1.init();<br />
<br />
    // ADS1115-2<br />
    ads2.setAddr_ADS1115(ADS1115_2_ADDR);<br />
    ads2.setGain(eGAIN_ONE);<br />
    ads2.setMode(eMODE_SINGLE);<br />
    ads2.setRate(eRATE_128);<br />
    ads2.setOSMode(eOSMODE_SINGLE);<br />
    ads2.init();<br />
<br />
    // ADS1115-3<br />
    ads3.setAddr_ADS1115(ADS1115_3_ADDR);<br />
    ads3.setGain(eGAIN_ONE);<br />
    ads3.setMode(eMODE_SINGLE);<br />
    ads3.setRate(eRATE_128);<br />
    ads3.setOSMode(eOSMODE_SINGLE);<br />
    ads3.init();<br />
<br />
    // ADS1115-4<br />
    ads4.setAddr_ADS1115(ADS1115_4_ADDR);<br />
    ads4.setGain(eGAIN_ONE);<br />
    ads4.setMode(eMODE_SINGLE);<br />
    ads4.setRate(eRATE_128);<br />
    ads4.setOSMode(eOSMODE_SINGLE);<br />
    ads4.init();<br />
<br />
    Serial.println();<br />
    Serial.println("KinCony 16-Channel Analog Input Test");<br />
    Serial.println("--------------------------------------");<br />
    Serial.println("ADS1115 Gain: 4.096V");<br />
    Serial.println("Multiplier: 5.16696");<br />
    Serial.println("Print threshold: 0.50V");<br />
    Serial.println();<br />
}<br />
<br />
<br />
void loop(void)<br />
{<br />
    // ADS1115-1: CH1 ~ CH4<br />
    if (ads1.checkADS1115())<br />
    {<br />
        checkChannel(ads1, 0, 1);<br />
        checkChannel(ads1, 1, 2);<br />
        checkChannel(ads1, 2, 3);<br />
        checkChannel(ads1, 3, 4);<br />
    }<br />
    else<br />
    {<br />
        Serial.println("ADS1115-1 (0x48) Disconnected!");<br />
    }<br />
<br />
<br />
    // ADS1115-2: CH5 ~ CH8<br />
    if (ads2.checkADS1115())<br />
    {<br />
        checkChannel(ads2, 0, 5);<br />
        checkChannel(ads2, 1, 6);<br />
        checkChannel(ads2, 2, 7);<br />
        checkChannel(ads2, 3, 8);<br />
    }<br />
    else<br />
    {<br />
        Serial.println("ADS1115-2 (0x49) Disconnected!");<br />
    }<br />
<br />
<br />
    // ADS1115-3: CH9 ~ CH12<br />
    if (ads3.checkADS1115())<br />
    {<br />
        checkChannel(ads3, 0, 9);<br />
        checkChannel(ads3, 1, 10);<br />
        checkChannel(ads3, 2, 11);<br />
        checkChannel(ads3, 3, 12);<br />
    }<br />
    else<br />
    {<br />
        Serial.println("ADS1115-3 (0x4B) Disconnected!");<br />
    }<br />
<br />
<br />
    // ADS1115-4: CH13 ~ CH16<br />
    if (ads4.checkADS1115())<br />
    {<br />
        checkChannel(ads4, 0, 13);<br />
        checkChannel(ads4, 1, 14);<br />
        checkChannel(ads4, 2, 15);<br />
        checkChannel(ads4, 3, 16);<br />
    }<br />
    else<br />
    {<br />
        Serial.println("ADS1115-4 (0x4A) Disconnected!");<br />
    }<br />
<br />
<br />
    // Scan every 1 second<br />
    delay(1000);<br />
}</code></div></div> arduino ino file download:<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10337" target="_blank" title="">3-ads1115_adc.zip</a> (Size: 1.68 KB / Downloads: 10)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download: <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10338" target="_blank" title="">3-ads1115_adc.ino.merged.zip</a> (Size: 195.04 KB / Downloads: 6)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
 * KinCony 16-Channel Analog Input Monitor<br />
 *<br />
 * Four ADS1115 ADC modules are used:<br />
 *<br />
 * ADS1115-1 (U35): CH1-CH4 &nbsp;&nbsp;I2C address: 0x48<br />
 * ADS1115-2 (U7):  CH5-CH8 &nbsp;&nbsp;I2C address: 0x49<br />
 * ADS1115-3 (U15): CH9-CH12  I2C address: 0x4B<br />
 * ADS1115-4 (U19): CH13-CH16 I2C address: 0x4A<br />
 *<br />
 * ESPHome equivalent configuration:<br />
 *<br />
 * gain: 4.096<br />
 * filters:<br />
 * &nbsp;&nbsp;- lambda: 'return x &lt;= 0.0025f ? 0.0f : x;'<br />
 * &nbsp;&nbsp;- multiply: 5.16696<br />
 * &nbsp;&nbsp;- clamp:<br />
 *     &nbsp;&nbsp;min_value: 0.0<br />
 *     &nbsp;&nbsp;max_value: 10.0<br />
 *<br />
 * Only channels with an input voltage greater than 0.5V<br />
 * will be printed.<br />
 *<br />
 * Copyright: Made by KinCony IoT: https://www.kincony.com<br />
 */<br />
<br />
#include &lt;Wire.h&gt;<br />
#include &lt;DFRobot_ADS1115.h&gt;<br />
<br />
// I2C pins<br />
#define SDA_PIN 8<br />
#define SCL_PIN 18<br />
<br />
// ADS1115 I2C addresses<br />
#define ADS1115_1_ADDR 0x48<br />
#define ADS1115_2_ADDR 0x49<br />
#define ADS1115_3_ADDR 0x4B<br />
#define ADS1115_4_ADDR 0x4A<br />
<br />
// ESPHome calibration multiplier<br />
#define VOLTAGE_MULTIPLIER 5.16696f<br />
<br />
// ESPHome zero threshold<br />
#define ADC_ZERO_THRESHOLD 0.0025f<br />
<br />
// Print threshold<br />
#define PRINT_THRESHOLD 0.5f<br />
<br />
// Maximum input voltage<br />
#define MAX_INPUT_VOLTAGE 10.0f<br />
<br />
<br />
// Create ADS1115 objects<br />
DFRobot_ADS1115 ads1(&amp;Wire);<br />
DFRobot_ADS1115 ads2(&amp;Wire);<br />
DFRobot_ADS1115 ads3(&amp;Wire);<br />
DFRobot_ADS1115 ads4(&amp;Wire);<br />
<br />
<br />
/*<br />
 * Read ADS1115 channel and convert to actual input voltage.<br />
 *<br />
 * DFRobot readVoltage() returns voltage in mV.<br />
 *<br />
 * ESPHome:<br />
 *   &nbsp;&nbsp;x &lt;= 0.0025V -&gt; 0V<br />
 *   &nbsp;&nbsp;x * 5.16696<br />
 *   &nbsp;&nbsp;clamp 0~10V<br />
 */<br />
float readInputVoltage(DFRobot_ADS1115 &amp;ads, uint8_t channel)<br />
{<br />
    // Read ADC voltage in mV<br />
    uint16_t adc_mV = ads.readVoltage(channel);<br />
<br />
    // Convert mV to V<br />
    float adcVoltage = adc_mV / 1000.0f;<br />
<br />
    // ESPHome lambda filter<br />
    if (adcVoltage &lt;= ADC_ZERO_THRESHOLD)<br />
    {<br />
        return 0.0f;<br />
    }<br />
<br />
    // ESPHome multiply filter<br />
    float inputVoltage = adcVoltage * VOLTAGE_MULTIPLIER;<br />
<br />
    // ESPHome clamp filter<br />
    if (inputVoltage &lt; 0.0f)<br />
    {<br />
        inputVoltage = 0.0f;<br />
    }<br />
<br />
    if (inputVoltage &gt; MAX_INPUT_VOLTAGE)<br />
    {<br />
        inputVoltage = MAX_INPUT_VOLTAGE;<br />
    }<br />
<br />
    return inputVoltage;<br />
}<br />
<br />
<br />
/*<br />
 * Check one analog channel.<br />
 *<br />
 * If the actual input voltage is greater than 0.5V,<br />
 * print the channel number and voltage.<br />
 */<br />
void checkChannel(<br />
    DFRobot_ADS1115 &amp;ads,<br />
    uint8_t adcChannel,<br />
    uint8_t channelNumber)<br />
{<br />
    float voltage = readInputVoltage(ads, adcChannel);<br />
<br />
    if (voltage &gt; PRINT_THRESHOLD)<br />
    {<br />
        Serial.print("CH");<br />
        Serial.print(channelNumber);<br />
        Serial.print(": ");<br />
<br />
        Serial.print(voltage, 2);<br />
<br />
        Serial.println(" V");<br />
    }<br />
}<br />
<br />
<br />
void setup(void)<br />
{<br />
    // Initialize serial communication<br />
    Serial.begin(115200);<br />
<br />
    // Initialize I2C<br />
    Wire.begin(SDA_PIN, SCL_PIN);<br />
<br />
    /*<br />
   &nbsp;&nbsp;* ADS1115 gain = 4.096V<br />
   &nbsp;&nbsp;*<br />
   &nbsp;&nbsp;* This corresponds to ESPHome:<br />
   &nbsp;&nbsp;*<br />
   &nbsp;&nbsp;* gain: 4.096<br />
   &nbsp;&nbsp;*<br />
   &nbsp;&nbsp;* DFRobot library:<br />
   &nbsp;&nbsp;* eGAIN_ONE = 4.096V<br />
   &nbsp;&nbsp;*/<br />
<br />
    // ADS1115-1<br />
    ads1.setAddr_ADS1115(ADS1115_1_ADDR);<br />
    ads1.setGain(eGAIN_ONE);<br />
    ads1.setMode(eMODE_SINGLE);<br />
    ads1.setRate(eRATE_128);<br />
    ads1.setOSMode(eOSMODE_SINGLE);<br />
    ads1.init();<br />
<br />
    // ADS1115-2<br />
    ads2.setAddr_ADS1115(ADS1115_2_ADDR);<br />
    ads2.setGain(eGAIN_ONE);<br />
    ads2.setMode(eMODE_SINGLE);<br />
    ads2.setRate(eRATE_128);<br />
    ads2.setOSMode(eOSMODE_SINGLE);<br />
    ads2.init();<br />
<br />
    // ADS1115-3<br />
    ads3.setAddr_ADS1115(ADS1115_3_ADDR);<br />
    ads3.setGain(eGAIN_ONE);<br />
    ads3.setMode(eMODE_SINGLE);<br />
    ads3.setRate(eRATE_128);<br />
    ads3.setOSMode(eOSMODE_SINGLE);<br />
    ads3.init();<br />
<br />
    // ADS1115-4<br />
    ads4.setAddr_ADS1115(ADS1115_4_ADDR);<br />
    ads4.setGain(eGAIN_ONE);<br />
    ads4.setMode(eMODE_SINGLE);<br />
    ads4.setRate(eRATE_128);<br />
    ads4.setOSMode(eOSMODE_SINGLE);<br />
    ads4.init();<br />
<br />
    Serial.println();<br />
    Serial.println("KinCony 16-Channel Analog Input Test");<br />
    Serial.println("--------------------------------------");<br />
    Serial.println("ADS1115 Gain: 4.096V");<br />
    Serial.println("Multiplier: 5.16696");<br />
    Serial.println("Print threshold: 0.50V");<br />
    Serial.println();<br />
}<br />
<br />
<br />
void loop(void)<br />
{<br />
    // ADS1115-1: CH1 ~ CH4<br />
    if (ads1.checkADS1115())<br />
    {<br />
        checkChannel(ads1, 0, 1);<br />
        checkChannel(ads1, 1, 2);<br />
        checkChannel(ads1, 2, 3);<br />
        checkChannel(ads1, 3, 4);<br />
    }<br />
    else<br />
    {<br />
        Serial.println("ADS1115-1 (0x48) Disconnected!");<br />
    }<br />
<br />
<br />
    // ADS1115-2: CH5 ~ CH8<br />
    if (ads2.checkADS1115())<br />
    {<br />
        checkChannel(ads2, 0, 5);<br />
        checkChannel(ads2, 1, 6);<br />
        checkChannel(ads2, 2, 7);<br />
        checkChannel(ads2, 3, 8);<br />
    }<br />
    else<br />
    {<br />
        Serial.println("ADS1115-2 (0x49) Disconnected!");<br />
    }<br />
<br />
<br />
    // ADS1115-3: CH9 ~ CH12<br />
    if (ads3.checkADS1115())<br />
    {<br />
        checkChannel(ads3, 0, 9);<br />
        checkChannel(ads3, 1, 10);<br />
        checkChannel(ads3, 2, 11);<br />
        checkChannel(ads3, 3, 12);<br />
    }<br />
    else<br />
    {<br />
        Serial.println("ADS1115-3 (0x4B) Disconnected!");<br />
    }<br />
<br />
<br />
    // ADS1115-4: CH13 ~ CH16<br />
    if (ads4.checkADS1115())<br />
    {<br />
        checkChannel(ads4, 0, 13);<br />
        checkChannel(ads4, 1, 14);<br />
        checkChannel(ads4, 2, 15);<br />
        checkChannel(ads4, 3, 16);<br />
    }<br />
    else<br />
    {<br />
        Serial.println("ADS1115-4 (0x4A) Disconnected!");<br />
    }<br />
<br />
<br />
    // Scan every 1 second<br />
    delay(1000);<br />
}</code></div></div> arduino ino file download:<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10337" target="_blank" title="">3-ads1115_adc.zip</a> (Size: 1.68 KB / Downloads: 10)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download: <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10338" target="_blank" title="">3-ads1115_adc.ino.merged.zip</a> (Size: 195.04 KB / Downloads: 6)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[arduino code examples for CO16]-02 Read digital input ports state]]></title>
			<link>https://www.kincony.com/forum/showthread.php?tid=9783</link>
			<pubDate>Mon, 31 Aug 2026 07:58:42 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://www.kincony.com/forum/member.php?action=profile&uid=1">admin</a>]]></dc:creator>
			<guid isPermaLink="false">https://www.kincony.com/forum/showthread.php?tid=9783</guid>
			<description><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
  Made by KinCony IoT: https://www.kincony.com<br />
<br />
  Program functionality:<br />
  This program uses an ESP32-S3 to read inputs from an XL9535 I/O expander chip <br />
  (I2C address 0x24) via I2C. The XL9535 chip handles channels 1-16. <br />
  The program reads the state of all these inputs and prints them in binary format <br />
  to the serial monitor.<br />
<br />
  Key points:<br />
  - The I2C bus is initialized on GPIO pins 8 (SDA) and 18 (SCL) with a frequency of 40kHz.<br />
  - The XL9535 chip reads the state of input pins for channels 1-16.<br />
  - The state of the inputs is printed to the serial monitor in binary format every second.<br />
  - Note: The original description mentioned three expander chips, but this implementation<br />
    currently uses only one XL9535 (PCA9555 compatible) at address 0x24.<br />
*/<br />
<br />
#include &lt;PCA95x5.h&gt;<br />
#include &lt;Wire.h&gt;<br />
<br />
// Initialize the PCA9555 object for XL9535 chip (channels 1-16)<br />
PCA9555 ioex1;  // XL9535 I/O expander at I2C address 0x24, handles channels 1-16<br />
<br />
void setup() {<br />
    // Start serial communication for debugging<br />
    Serial.begin(115200);<br />
    delay(2000);  // Wait for 2 seconds to ensure serial monitor is ready<br />
<br />
    // Initialize the I2C bus with GPIO 8 as SDA and GPIO 18 as SCL, 40kHz frequency<br />
    Wire.begin(8, 18, 40000);<br />
<br />
    // Attach the PCA9555 device at I2C address 0x24<br />
    ioex1.attach(Wire, 0x24);<br />
    <br />
    // Set polarity to original (no inversion)<br />
    ioex1.polarity(PCA95x5::Polarity::ORIGINAL_ALL);<br />
    <br />
    // Configure all 16 pins as inputs<br />
    ioex1.direction(PCA95x5::Direction::IN_ALL);<br />
}<br />
<br />
void loop() {<br />
    // Read and print the state of inputs from the XL9535 (channels 1-16)<br />
    Serial.print("1-16 input states: ");<br />
    // Read all 16 pins and print as 16-bit binary value<br />
    Serial.println(ioex1.read(), BIN);<br />
<br />
    delay(1000);  // Wait for 1 second before the next reading<br />
}</code></div></div> arduino ino file download: <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10335" target="_blank" title="">2-digital-input.zip</a> (Size: 1,013 bytes / Downloads: 5)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download: <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10336" target="_blank" title="">2-digital-input.ino.merged.zip</a> (Size: 197.84 KB / Downloads: 11)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
  Made by KinCony IoT: https://www.kincony.com<br />
<br />
  Program functionality:<br />
  This program uses an ESP32-S3 to read inputs from an XL9535 I/O expander chip <br />
  (I2C address 0x24) via I2C. The XL9535 chip handles channels 1-16. <br />
  The program reads the state of all these inputs and prints them in binary format <br />
  to the serial monitor.<br />
<br />
  Key points:<br />
  - The I2C bus is initialized on GPIO pins 8 (SDA) and 18 (SCL) with a frequency of 40kHz.<br />
  - The XL9535 chip reads the state of input pins for channels 1-16.<br />
  - The state of the inputs is printed to the serial monitor in binary format every second.<br />
  - Note: The original description mentioned three expander chips, but this implementation<br />
    currently uses only one XL9535 (PCA9555 compatible) at address 0x24.<br />
*/<br />
<br />
#include &lt;PCA95x5.h&gt;<br />
#include &lt;Wire.h&gt;<br />
<br />
// Initialize the PCA9555 object for XL9535 chip (channels 1-16)<br />
PCA9555 ioex1;  // XL9535 I/O expander at I2C address 0x24, handles channels 1-16<br />
<br />
void setup() {<br />
    // Start serial communication for debugging<br />
    Serial.begin(115200);<br />
    delay(2000);  // Wait for 2 seconds to ensure serial monitor is ready<br />
<br />
    // Initialize the I2C bus with GPIO 8 as SDA and GPIO 18 as SCL, 40kHz frequency<br />
    Wire.begin(8, 18, 40000);<br />
<br />
    // Attach the PCA9555 device at I2C address 0x24<br />
    ioex1.attach(Wire, 0x24);<br />
    <br />
    // Set polarity to original (no inversion)<br />
    ioex1.polarity(PCA95x5::Polarity::ORIGINAL_ALL);<br />
    <br />
    // Configure all 16 pins as inputs<br />
    ioex1.direction(PCA95x5::Direction::IN_ALL);<br />
}<br />
<br />
void loop() {<br />
    // Read and print the state of inputs from the XL9535 (channels 1-16)<br />
    Serial.print("1-16 input states: ");<br />
    // Read all 16 pins and print as 16-bit binary value<br />
    Serial.println(ioex1.read(), BIN);<br />
<br />
    delay(1000);  // Wait for 1 second before the next reading<br />
}</code></div></div> arduino ino file download: <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10335" target="_blank" title="">2-digital-input.zip</a> (Size: 1,013 bytes / Downloads: 5)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download: <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10336" target="_blank" title="">2-digital-input.ino.merged.zip</a> (Size: 197.84 KB / Downloads: 11)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[arduino code examples for CO16]-01 Turn ON/OFF relay]]></title>
			<link>https://www.kincony.com/forum/showthread.php?tid=9782</link>
			<pubDate>Mon, 31 Aug 2026 07:56:48 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://www.kincony.com/forum/member.php?action=profile&uid=1">admin</a>]]></dc:creator>
			<guid isPermaLink="false">https://www.kincony.com/forum/showthread.php?tid=9782</guid>
			<description><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
 * Made by KinCony IoT: https://www.kincony.com<br />
 *<br />
 * This program controls a 16-channel relay board via a PCF8575 I/O expander.<br />
 * It sequentially turns on each relay and then turns them off in a loop.<br />
 * <br />
 * Pin Definitions:<br />
 * - SDA: GPIO 8<br />
 * - SCL: GPIO 18<br />
 * <br />
 * Delay Time:<br />
 * - 200 milliseconds between switching relays<br />
 */<br />
<br />
#include &lt;Wire.h&gt;        // Include the Wire library for I2C communication<br />
#include &lt;PCF8575.h&gt;   &nbsp;&nbsp;// Include the PCF8575 library to control the I/O expander<br />
<br />
#define SDA 8         &nbsp;&nbsp;// Define the SDA pin<br />
#define SCL 18         &nbsp;&nbsp;// Define the SCL pin<br />
#define DELAY_TIME 200 &nbsp;&nbsp;// Define the delay time in milliseconds<br />
<br />
// Set I2C address of the PCF8575 module<br />
#define I2C_ADDRESS 0x22 // I2C address of the PCF8575 module<br />
<br />
PCF8575 pcf8575_R1(I2C_ADDRESS); // Create a PCF8575 object with the specified I2C address<br />
<br />
void setup() {<br />
  // Initialize I2C communication<br />
  Wire.begin(SDA, SCL); // SDA on GPIO 8, SCL on GPIO 18 (according to your board's configuration)<br />
  <br />
  // Initialize serial communication for debugging (optional)<br />
  Serial.begin(115200);<br />
  Serial.println("PCF8575 Relay Control: Starting...");<br />
<br />
  // Initialize the PCF8575 module<br />
  pcf8575_R1.begin();<br />
<br />
  // Turn off all relays initially (set all pins HIGH)<br />
  for (int i = 0; i &lt; 16; i++) {<br />
    pcf8575_R1.write(i, HIGH); // Set all relays to OFF (assuming HIGH means OFF for relays)<br />
  }<br />
}<br />
<br />
void loop() {<br />
  // Sequentially turn on each relay<br />
  for (int i = 0; i &lt; 16; i++) {<br />
    pcf8575_R1.write(i, LOW); &nbsp;&nbsp;// Turn on the relay at pin i (LOW means ON for the relay)<br />
    delay(DELAY_TIME);          // Wait for DELAY_TIME milliseconds<br />
  }<br />
<br />
  // Sequentially turn off each relay<br />
  for (int i = 0; i &lt; 16; i++) {<br />
    pcf8575_R1.write(i, HIGH);  // Turn off the relay at pin i (HIGH means OFF for the relay)<br />
    delay(DELAY_TIME);          // Wait for DELAY_TIME milliseconds<br />
  }<br />
}</code></div></div> arduino ino file download: <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10333" target="_blank" title="">1-output.zip</a> (Size: 926 bytes / Downloads: 9)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download: <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10334" target="_blank" title="">1-output.ino.merged.zip</a> (Size: 197.66 KB / Downloads: 11)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
 * Made by KinCony IoT: https://www.kincony.com<br />
 *<br />
 * This program controls a 16-channel relay board via a PCF8575 I/O expander.<br />
 * It sequentially turns on each relay and then turns them off in a loop.<br />
 * <br />
 * Pin Definitions:<br />
 * - SDA: GPIO 8<br />
 * - SCL: GPIO 18<br />
 * <br />
 * Delay Time:<br />
 * - 200 milliseconds between switching relays<br />
 */<br />
<br />
#include &lt;Wire.h&gt;        // Include the Wire library for I2C communication<br />
#include &lt;PCF8575.h&gt;   &nbsp;&nbsp;// Include the PCF8575 library to control the I/O expander<br />
<br />
#define SDA 8         &nbsp;&nbsp;// Define the SDA pin<br />
#define SCL 18         &nbsp;&nbsp;// Define the SCL pin<br />
#define DELAY_TIME 200 &nbsp;&nbsp;// Define the delay time in milliseconds<br />
<br />
// Set I2C address of the PCF8575 module<br />
#define I2C_ADDRESS 0x22 // I2C address of the PCF8575 module<br />
<br />
PCF8575 pcf8575_R1(I2C_ADDRESS); // Create a PCF8575 object with the specified I2C address<br />
<br />
void setup() {<br />
  // Initialize I2C communication<br />
  Wire.begin(SDA, SCL); // SDA on GPIO 8, SCL on GPIO 18 (according to your board's configuration)<br />
  <br />
  // Initialize serial communication for debugging (optional)<br />
  Serial.begin(115200);<br />
  Serial.println("PCF8575 Relay Control: Starting...");<br />
<br />
  // Initialize the PCF8575 module<br />
  pcf8575_R1.begin();<br />
<br />
  // Turn off all relays initially (set all pins HIGH)<br />
  for (int i = 0; i &lt; 16; i++) {<br />
    pcf8575_R1.write(i, HIGH); // Set all relays to OFF (assuming HIGH means OFF for relays)<br />
  }<br />
}<br />
<br />
void loop() {<br />
  // Sequentially turn on each relay<br />
  for (int i = 0; i &lt; 16; i++) {<br />
    pcf8575_R1.write(i, LOW); &nbsp;&nbsp;// Turn on the relay at pin i (LOW means ON for the relay)<br />
    delay(DELAY_TIME);          // Wait for DELAY_TIME milliseconds<br />
  }<br />
<br />
  // Sequentially turn off each relay<br />
  for (int i = 0; i &lt; 16; i++) {<br />
    pcf8575_R1.write(i, HIGH);  // Turn off the relay at pin i (HIGH means OFF for the relay)<br />
    delay(DELAY_TIME);          // Wait for DELAY_TIME milliseconds<br />
  }<br />
}</code></div></div> arduino ino file download: <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10333" target="_blank" title="">1-output.zip</a> (Size: 926 bytes / Downloads: 9)
<!-- end: postbit_attachments_attachment --><br />
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download: <br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://www.kincony.com/forum/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=10334" target="_blank" title="">1-output.ino.merged.zip</a> (Size: 197.66 KB / Downloads: 11)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
	</channel>
</rss>