<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Daniel Guerrero</title>
    <description>The latest articles on DEV Community by Daniel Guerrero (@danielmx).</description>
    <link>https://dev.to/danielmx</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3420880%2F2ad63621-f20a-42ac-b3bc-a5f09fb6f533.png</url>
      <title>DEV Community: Daniel Guerrero</title>
      <link>https://dev.to/danielmx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/danielmx"/>
    <language>en</language>
    <item>
      <title>BIO Baochip/Dabao - FIFO and Events</title>
      <dc:creator>Daniel Guerrero</dc:creator>
      <pubDate>Thu, 13 Aug 2026 02:00:00 +0000</pubDate>
      <link>https://dev.to/danielmx/bio-baochipdabao-fifo-and-events-25jf</link>
      <guid>https://dev.to/danielmx/bio-baochipdabao-fifo-and-events-25jf</guid>
      <description>&lt;h2&gt;
  
  
  FIFO
&lt;/h2&gt;

&lt;p&gt;The BIO has 4 FIFOs mapped to the BIO processors as &lt;code&gt;x16-x19&lt;/code&gt; r/w registers (blocking on read until new data is pushed), and in the host through &lt;code&gt;BIO_BDMA_SFR_TXFx&lt;/code&gt; for writing data (PUSH) and &lt;code&gt;BIO_BDMA_SFR_RXFx&lt;/code&gt; for reading (POP) data (or returning the last data read if nothing else is found), where &lt;code&gt;x&lt;/code&gt; is a number &lt;code&gt;0-3&lt;/code&gt; for the 4 FIFOs.&lt;/p&gt;

&lt;p&gt;So in a BIO processor, an instruction like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mv t0, x16      # wait for FIFO0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will block until there is info in FIFO0.&lt;br&gt;
To unblock it, you need, from another BIO processor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;li x16, 0x10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or from the host processor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;BIO_BDMA_SFR_TXF0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// bio_push_fifo0(0x10); in SDK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To read in the host processor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BIO_BDMA_SFR_RXF0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// bio_pop_fifo0(); in SDK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will always return a value and won't block execution, so for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;BIO_BDMA_SFR_TXF0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// FIFO0 has 0x10&lt;/span&gt;
&lt;span class="n"&gt;BIO_BDMA_SFR_TXF0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// FIFO0 has 0x10,0x20&lt;/span&gt;

&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BIO_BDMA_SFR_RXF0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// data = 0x10&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BIO_BDMA_SFR_RXF0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// data = 0x20&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BIO_BDMA_SFR_RXF0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// data = 0x20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the last data read/popped will always be available to the host.&lt;/p&gt;

&lt;p&gt;There is an example here: &lt;a href="https://github.com/danguer/embedded-boards101/tree/main/daobao-baochip/bio_multiply_fifo" rel="noopener noreferrer"&gt;https://github.com/danguer/embedded-boards101/tree/main/daobao-baochip/bio_multiply_fifo&lt;/a&gt;&lt;br&gt;
To test the hardware multiplier in the BIO Processor, the following instructions are needed for BIO:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mv t0, x16      # wait for FIFO0
li t1, 2        # load multiplier
mul x16, t0, t1 # multiply and store back in fifo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the BIO will get a value from FIFO0, multiply by 2, and store it again in FIFO0.&lt;br&gt;
Because we are reusing the same FIFO, if we read the value before the BIO does the multiplication, we are going to read the original value and not the result (I know this is poor design, as another FIFO should be used, but this is to show the communication with the host).&lt;br&gt;
So the host will do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;add the value to FIFO0&lt;/li&gt;
&lt;li&gt;read the value from FIFO0&lt;/li&gt;
&lt;li&gt;check that the value is different from the original value
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;bio_start_cores&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;bio_push_fifo0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multiplicand&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// wait until is multiplied&lt;/span&gt;
&lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bio_pop_fifo0&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;multiplicand&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;bio_stop_cores&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BIO_CORE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Even though this code works, the issue is that the FIFO read register will ALWAYS return a value.&lt;/p&gt;

&lt;p&gt;To avoid this issue, there is another register called &lt;a href="https://baochip.github.io/baochip-1x/ch02-00-bio-overview.html#bio_bdma_sfr_flevel" rel="noopener noreferrer"&gt;&lt;code&gt;BIO_BDMA_SFR_FLEVEL&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
This register will return all the FIFO "levels" (number of entries or length), with 4 bits for each FIFO (as there is a maximum of 16 entries per FIFO). So, to know how many items exist, it can be used like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;fifo0_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BIO_BDMA_SFR_FLEVEL&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// or bio_fifo_level(0); in SDK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Still, for this example, the issue is that we need to use another FIFO to avoid collisions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mv t0, x16      # wait for FIFO0
li t1, 2        # load multiplier
mul x17, t0, t1 # multiply and store in fifo1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;bio_push_fifo0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multiplicand&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// wait until fifo1 has data&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bio_fifo_level&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bio_pop_fifo1&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that there is a way to "reset" the FIFO levels/length through the register &lt;a href="https://baochip.github.io/baochip-1x/ch02-00-bio-overview.html#bio_bdma_sfr_fifo_clr" rel="noopener noreferrer"&gt;&lt;code&gt;BIO_BDMA_SFR_FIFO_CLR&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
This is a 4-bit config where each bit corresponds to a FIFO number, and a &lt;code&gt;1&lt;/code&gt; means clearing the levels (but not the contents), so for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;BIO_BDMA_SFR_FIFO_CLR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This resets all the FIFO levels/length.&lt;/p&gt;

&lt;h2&gt;
  
  
  Events
&lt;/h2&gt;

&lt;p&gt;The events register is a shared 32-bit register, where bits [23:0] are standard bits and can be changed with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;x28&lt;/code&gt; to SET in the BIO Processors (or &lt;code&gt;BIO_BDMA_SFR_EVENT_SET&lt;/code&gt; in host, &lt;code&gt;bio_event_set&lt;/code&gt; in SDK)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;x29&lt;/code&gt; to CLEAR in the BIO Processors (or &lt;code&gt;BIO_BDMA_SFR_EVENT_CLR&lt;/code&gt; in host, &lt;code&gt;bio_event_clear&lt;/code&gt; in SDK)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the BIO Processor there are two more registers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;x27&lt;/code&gt; is a mask to only halt on certain events&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;x30&lt;/code&gt; is a Halt-on-Event register: when you try to read it, it will halt until &lt;code&gt;(x27 &amp;amp; events) != 0&lt;/code&gt; or until an event has happened; reading this will return all the event data, regardless of the event mask&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the host, &lt;code&gt;BIO_BDMA_SFR_EVENT_STATUS&lt;/code&gt; is similar to &lt;code&gt;x30&lt;/code&gt;, so it is a READ ONLY register.&lt;/p&gt;

&lt;p&gt;So, you can wait for a signal, for example:&lt;br&gt;
BIO Processor&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mv t0, x16      # wait for FIFO0
mul x17, t0, t1 # multiply and store back in FIFO1
li x28, 0x4     # signal that multiply has finished
j cycle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the host, this code can be added:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;bio_push_fifo0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multiplicand&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// sdk&lt;/span&gt;

&lt;span class="c1"&gt;// wait until signal happens&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;BIO_SFR_EVENT_STATUS&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, the host will be waiting for a signal from the event register.&lt;/p&gt;

&lt;h2&gt;
  
  
  Event Thresholds
&lt;/h2&gt;

&lt;p&gt;Bits [31:24] are special bits; for each FIFO there will be 2 comparators, which will set those 8 bits if they match one of three possible options — &lt;code&gt;&amp;lt; (less than)&lt;/code&gt;, &lt;code&gt;== (equal)&lt;/code&gt;, &lt;code&gt;&amp;gt; (greater than)&lt;/code&gt; — compared against the value of the level/length of the FIFO.&lt;/p&gt;

&lt;p&gt;So you can configure logic testing like:&lt;br&gt;
&lt;code&gt;IF FIFO0_LEVEL == 4 OR FIFO_LEVEL &amp;gt; 4&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If the comparator matches, it will set the proper event bit. So, let's say the previous example was for Thresh0/Comparator0; then, when it matches, it will set &lt;code&gt;1&lt;/code&gt; in the Event[24] bit, which can be used in the host or the BIO Processor.&lt;/p&gt;

&lt;p&gt;The comparators need to be set in the host through two variables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://baochip.github.io/baochip-1x/ch02-00-bio-overview.html#bio_bdma_sfr_elevel" rel="noopener noreferrer"&gt;&lt;code&gt;BIO_BDMA_SFR_ELEVEL&lt;/code&gt;&lt;/a&gt; for setting the value to compare&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://baochip.github.io/baochip-1x/ch02-00-bio-overview.html#bio_bdma_sfr_etype" rel="noopener noreferrer"&gt;&lt;code&gt;BIO_BDMA_SFR_ETYPE&lt;/code&gt;&lt;/a&gt; for setting the type of comparator&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the &lt;code&gt;BIO_BDMA_SFR_ELEVEL&lt;/code&gt;, there are 8 comparators, and each one can have a value of 4 bits (FIFO has a max of 16 entries). So let's say we want the first comparator (FIFO0, Thresh0) to match the value &lt;code&gt;4&lt;/code&gt; or &lt;code&gt;0b0100&lt;/code&gt;; it needs to be set like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;BIO_BDMA_SFR_ELEVEL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;BIO_BDMA_SFR_ETYPE&lt;/code&gt; contains 3 groups of 8 bits for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[7:0] &lt;code&gt;LT&lt;/code&gt; or Less Than&lt;/li&gt;
&lt;li&gt;[15:8] &lt;code&gt;EQ&lt;/code&gt; or Equal&lt;/li&gt;
&lt;li&gt;[31:16] &lt;code&gt;GT&lt;/code&gt; or Greater Than&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As this is 8 bits long for each type, a &lt;code&gt;1&lt;/code&gt; in the proper bit will set the comparator type; so if we want to check &lt;code&gt;EQ&lt;/code&gt; for the first comparator, bit 8 (or &lt;code&gt;0x100&lt;/code&gt;) should be set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;BIO_SFR_ETYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the BIO Processor you can wait for the signal like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    li x27, 0x1000000  # mask for event[24]
wait_for_event:
    mv t1, x30      # halt for event
    # run here all the code for event
    j wait_for_event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So what this does is the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Asks to only be woken up when the event matches mask &lt;code&gt;0x1000000&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Halts on event by reading &lt;code&gt;x30&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;When there are 4 items in FIFO0, it will continue&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's note that the Event Register contains other registers and is not documented yet, so either set the mask through &lt;code&gt;x27&lt;/code&gt; for a specific event, or wait for an event and check through a separate mask whether it is the event you want.&lt;/p&gt;

&lt;p&gt;An example that adds 4 values using a signal is here: &lt;a href="https://github.com/danguer/embedded-boards101/tree/main/daobao-baochip/bio_add_four" rel="noopener noreferrer"&gt;https://github.com/danguer/embedded-boards101/tree/main/daobao-baochip/bio_add_four&lt;/a&gt;&lt;/p&gt;

</description>
      <category>coding</category>
      <category>hardware</category>
      <category>programming</category>
      <category>systems</category>
    </item>
    <item>
      <title>BIO Baochip/Dabao - Introduction and GPIO</title>
      <dc:creator>Daniel Guerrero</dc:creator>
      <pubDate>Mon, 10 Aug 2026 09:09:14 +0000</pubDate>
      <link>https://dev.to/danielmx/bio-baochipdabao-introduction-and-gpio-h6</link>
      <guid>https://dev.to/danielmx/bio-baochipdabao-introduction-and-gpio-h6</guid>
      <description>&lt;p&gt;The &lt;a href="https://baochip.com/" rel="noopener noreferrer"&gt;Baochip&lt;/a&gt; is a new MCU using RISC-V which has a &lt;code&gt;BIO&lt;/code&gt; feature. This feature contains 4 PicoRV32E processors that can run in parallel with access to memory and GPIO.&lt;br&gt;
It also features 16 special registers (&lt;code&gt;x16&lt;/code&gt;-&lt;code&gt;x31&lt;/code&gt;) compared to the RV32E specification, which contains only 16 (&lt;code&gt;x0&lt;/code&gt;-&lt;code&gt;x15&lt;/code&gt;); it also supports the &lt;code&gt;Zmmul&lt;/code&gt; extension (integer multiplication).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://danguer.github.io/boards101/dabao/baochip1x.html" rel="noopener noreferrer"&gt;A brief introduction of the board is here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://baochip.github.io/baochip-1x/ch02-00-bio-overview.html" rel="noopener noreferrer"&gt;The official documentation is here&lt;/a&gt; and I will use an image from the documentation:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ks5xfpi0ah0iilw222b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ks5xfpi0ah0iilw222b.png" alt="BIO Diagram" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the SDK, I will use the &lt;a href="https://github.com/ArmstrongSubero/dabao-sdk/tree/main" rel="noopener noreferrer"&gt;Dabao SDK&lt;/a&gt;, and for compiling BIO I will use the &lt;a href="https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases" rel="noopener noreferrer"&gt;xpack riscv-none-elf-gcc 15.2.0&lt;/a&gt;, which is what the SDK uses — though any RISC-V gcc should work.&lt;/p&gt;
&lt;h2&gt;
  
  
  General Description
&lt;/h2&gt;

&lt;p&gt;The BIO consists of 4 PicoRV32E processors that can run in parallel up to 720 MHz (it takes 3 cycles for each instruction without pipelining, so the real speed is around 240 MHz).&lt;br&gt;
Each processor has &lt;code&gt;4 kiB&lt;/code&gt; of RAM, meaning it can hold up to 1024 instructions. Each processor also has the &lt;code&gt;Zmmul&lt;/code&gt; extension, so it has a hardware multiplier.&lt;br&gt;
Each BIO Processor has special registers &lt;code&gt;x16-x31&lt;/code&gt; to communicate with other processors and the Host Processor; some of the registers will halt CPU execution until an external event happens.&lt;br&gt;
The BIO Processor can have access to GPIO, so it allows "bit banging" at higher speeds and running in parallel without main CPU slowdown; it can also have access to host memory.&lt;/p&gt;

&lt;p&gt;The special registers are (taken from the official documentation, with more info added):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FIFO - 8-deep fifo head/tail access. Cores halt on overflow/underflow.
Each FIFO can have up to 16 items of 32 bits
- x16 r/w  fifo[0]
- x17 r/w  fifo[1]
- x18 r/w  fifo[2]
- x19 r/w  fifo[3]

Quantum - core will halt until host-configured clock pulse occurs, or an external event comes in a GPIO pin.
- x20 -/w  halt to quantum

GPIO
- x26 r/w  mask GPIO action outputs
- x21 r/w  write: (x26 &amp;amp; x21) -&amp;gt; gpio pins; read: gpio pins -&amp;gt; x21
- x22 -/w  (x26 &amp;amp; x22) -&amp;gt; a `1` in x22 will set corresponding pin on gpio
- x23 -/w  (x26 &amp;amp; ~x23) -&amp;gt; a `0` in x23 will clear corresponding pin on gpio
- x24 -/w  (x26 &amp;amp; x24) -&amp;gt; a `1` in x24 will make corresponding gpio pin an output
- x25 -/w  (x26 &amp;amp; x25) -&amp;gt; a `1` in x25 will make corresponding gpio pin an input


Events
Bits [31:24] are hard-wired to FIFO level flags, configured by the host; writes to bits [31:24] are ignored.
These bits are for comparators against FIFO levels (FIFO length), there are 2 possible comparators for each FIFO, so 8 comparators in total.

- x27 -/w  event mask
- x28 -/w  `1` will set the corresponding event bit. Only [23:0] are wired up.
- x29 -/w  `1` will clear the corresponding event bit. Only [23:0] are wired up.
- x30 r/-  halt until ((x27 &amp;amp; events) != 0), and return unmasked `events` value

Core ID &amp;amp; debug:
- x31 r/-  [31:30] -&amp;gt; core ID; [29:0] -&amp;gt; cpu clocks since reset
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  BIO Setup
&lt;/h2&gt;

&lt;p&gt;In order to run the BIO, it needs the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;set the clock settings (SDK: &lt;code&gt;bio_init(FCLK_HZ);&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;flush core instructions/fifo and set up stack pointers; this is done in &lt;a href="https://github.com/ArmstrongSubero/dabao-sdk/blob/main/src/bao1x/hardware_bio/bio.c#L26" rel="noopener noreferrer"&gt;&lt;code&gt;bio_init&lt;/code&gt;&lt;/a&gt; (&lt;a href="https://github.com/betrusted-io/xous-core/blob/5d5bbbfa95c0dcef26fe1fe9b496b7f6f31d191b/libs/bao1x-hal/src/bio_hw.rs#L185" rel="noopener noreferrer"&gt;other example&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;set the code to execute in binary opcodes (SDK: &lt;code&gt;bio_load_code_words(core, *buffer, length)&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;start the code (SDK: &lt;code&gt;bio_start_cores(core_number_1_to_4)&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So you need to compile instructions into RISC-V opcodes for each core; &lt;a href="https://github.com/danguer/embedded-boards101/blob/main/daobao-baochip/compile-bio.sh" rel="noopener noreferrer"&gt;here is a script&lt;/a&gt; to compile ASM into bytecode for each core.&lt;br&gt;
The script can be used like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;GCC_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"YOUR_PATH_TO/xpack-riscv-none-elf-gcc-15.2.0-1"&lt;/span&gt; ./compile-bio.sh source.s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And will output a block like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;bio_program_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;bio_program&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="mh"&gt;0x010002b7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can copy and paste this code into the C implementation. This tool needs xpack (in theory, it can work with any RISC-V gcc compiler) and the &lt;code&gt;hexdump&lt;/code&gt; command.&lt;/p&gt;

&lt;h2&gt;
  
  
  GPIO Handling
&lt;/h2&gt;

&lt;p&gt;Since the GPIO is handled through 32-bit registers, there are up to 32 GPIO pins available to use; &lt;a href="https://baochip.github.io/baochip-1x/ch03-00-io-configuration.html" rel="noopener noreferrer"&gt;here is more info about the internal details&lt;/a&gt;.&lt;br&gt;
The 32 pins are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;bits [15:0] -&amp;gt; &lt;code&gt;PB[15:0]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;bits [31:16] -&amp;gt; &lt;code&gt;PC[16:0]&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In order to use GPIO, you need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set the pin you want to use to &lt;code&gt;AF1&lt;/code&gt; (Alternate Function 1) through the proper register. For example, &lt;code&gt;AFSELBL&lt;/code&gt; contains the config for &lt;code&gt;Port B, Pin 0-7&lt;/code&gt; and &lt;code&gt;AFSELBH&lt;/code&gt; for &lt;code&gt;Port B, Pin 8-15&lt;/code&gt; &lt;a href="https://baochip.github.io/baochip-1x/ch03-00-io-configuration.html#afsel--alternate-function-selection-register" rel="noopener noreferrer"&gt;Reference&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Configure &lt;code&gt;BIOSEL&lt;/code&gt; to set the proper bit &lt;a href="https://baochip.github.io/baochip-1x/ch03-00-io-configuration.html#biosel--bio-function-selection-register" rel="noopener noreferrer"&gt;Reference&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, for example, to use pin &lt;code&gt;PB2&lt;/code&gt;, this needs to be done:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;AFSELBL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 0b_00_00_00_00_00_01_00_00 or PortB,Pin2=AF1&lt;/span&gt;
&lt;span class="n"&gt;BIOSEL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 1 &amp;lt;&amp;lt; 2 to select Pin2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the SDK: &lt;code&gt;bio_map_pin(pin_number)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I will use this as an example:&lt;br&gt;
&lt;a href="https://github.com/ArmstrongSubero/dabao-sdk/blob/main/examples/bio_blink/bio_blink.c" rel="noopener noreferrer"&gt;https://github.com/ArmstrongSubero/dabao-sdk/blob/main/examples/bio_blink/bio_blink.c&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The name is a bit confusing since the LED won't blink, but it will actually be a &lt;code&gt;PWM&lt;/code&gt; using &lt;code&gt;BIO&lt;/code&gt; instead of the main &lt;code&gt;CPU&lt;/code&gt;.&lt;br&gt;
So in order to generate a &lt;code&gt;PWM&lt;/code&gt;, a pulse clock with a certain frequency is needed. For this, &lt;code&gt;x20&lt;/code&gt; will halt until a pulse happens, and this can be configured using the &lt;a href="https://baochip.github.io/baochip-1x/ch02-00-bio-overview.html#bio_bdma_sfr_qdiv0" rel="noopener noreferrer"&gt;&lt;code&gt;QDIV&lt;/code&gt; register&lt;/a&gt; for the processor being used, or in the SDK: &lt;code&gt;bio_set_divider(core, divider_int, divider_frac)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Note that in the SDK they use the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;bio_set_divider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1750&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="cm"&gt;/* 100 kHz output (fclk / 1750 / 4) */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I haven't confirmed if this is accurate, since &lt;code&gt;FCLK = 700 MHz&lt;/code&gt; (or &lt;code&gt;700,000&lt;/code&gt;) and they use 4 cycles per instruction, but according to the official documentation it is 3 cycles; but maybe this is due to rounding.&lt;/p&gt;

&lt;p&gt;So when setting the divider, the &lt;code&gt;x20&lt;/code&gt; or quantum pulse will be delivered every 1/100,000s.&lt;br&gt;
So in ASM, if you do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;addi  x20, x0, 0
# mv x20,x0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This instruction will halt until a quantum pulse happens.&lt;/p&gt;

&lt;p&gt;So in order to "blink", the following needs to happen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;setup gpio&lt;/li&gt;
&lt;li&gt;wait for quantum pulse&lt;/li&gt;
&lt;li&gt;turn ON gpio&lt;/li&gt;
&lt;li&gt;wait for quantum pulse&lt;/li&gt;
&lt;li&gt;turn OFF gpio&lt;/li&gt;
&lt;li&gt;jump to 2.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So the following code is in the example (I'm using pseudo instructions to make it easier to read):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    li x5, 0x4     # bit mask for pin 2
    mv x26, x5     # GPIO mask = pin 2, for this example this is optional
    mv x24, x5     # x24 configures output pins, so pin 2 = output
loop:
    mv x22, x5     # x22 is SET GPIO, so pin 2=HIGH
    mv x20, x0     # wait quantum pulse
    mv x23, x0     # x23 is CLEAR GPIO, so pin 2=LOW
    mv x20, x0     # wait quantum pulse
    j loop         # loop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Starting with ESP32P4-M3-DEV</title>
      <dc:creator>Daniel Guerrero</dc:creator>
      <pubDate>Sun, 19 Jul 2026 08:40:20 +0000</pubDate>
      <link>https://dev.to/danielmx/starting-with-esp32p4-m3-dev-2ng0</link>
      <guid>https://dev.to/danielmx/starting-with-esp32p4-m3-dev-2ng0</guid>
      <description>&lt;p&gt;I just got a ESP32P4-M3-DEV Board (under several names &lt;code&gt;Guiton ESP32P4-M3-DEV&lt;/code&gt; or &lt;code&gt;JC-ESP32P4-M3-DEV&lt;/code&gt;)&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7fnn34tf5za8nqmwpw79.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7fnn34tf5za8nqmwpw79.webp" alt="ESP32P4-M3-DEV" width="569" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This board have a module with ESP32-P4 and ESP32-C6 as co-processor for WIFI/Bluetooth.&lt;/p&gt;

&lt;p&gt;The board also have a number of helper chips and I/O like Mic, Speaker, 2 USB ports, Camera / Display, Ethernet, Battery, RS485 and Capacitive Touch&lt;/p&gt;

&lt;p&gt;The big problem of this board is there is few documentation available, so I started a document to keep track of most of the features and will add some code for testing (even one of the schematics link already have some examples).&lt;/p&gt;

&lt;p&gt;The quick details to start are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need to connect USB to middle port to power board and enable &lt;code&gt;UART&lt;/code&gt; from MCU&lt;/li&gt;
&lt;li&gt;You need to select &lt;code&gt;UART&lt;/code&gt; as &lt;code&gt;Flash Method&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;You need to use &lt;code&gt;Rev v1.0&lt;/code&gt; for compiling as chip is revision 1.3 and by default newer sdk use chip version &amp;gt;= 3.x&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To use proper revision:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select &lt;code&gt;Component config -&amp;gt; Hardware Settings -&amp;gt; Chip Revision&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Check &lt;code&gt;Select ESP32-P4 revisions &amp;lt;3.0 (No &amp;gt;=3.x Support)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Minimum Supported ESP32-P4 Revision&lt;/code&gt; select &lt;code&gt;Rev v1.0&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Get the full details&lt;br&gt;
&lt;a href="https://danguer.github.io/boards101/guition/jc-esp32p4-m3-dev.html" rel="noopener noreferrer"&gt;https://danguer.github.io/boards101/guition/jc-esp32p4-m3-dev.html&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>CH341 with python</title>
      <dc:creator>Daniel Guerrero</dc:creator>
      <pubDate>Fri, 03 Apr 2026 22:02:02 +0000</pubDate>
      <link>https://dev.to/danielmx/ch341-with-python-52en</link>
      <guid>https://dev.to/danielmx/ch341-with-python-52en</guid>
      <description>&lt;p&gt;Some time ago I found the CH341a programmer.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fntt3wx8hssnreqksauat.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fntt3wx8hssnreqksauat.jpg" alt="CH341a Programmer" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
The board seems a bit intimidating with its ZIF socket, but once you realize the low component count, it becomes more approachable. When I found a CH341 "dev" board, I started looking for documentation on how to develop with it.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F98qeywsle2bo6h8zgcia.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F98qeywsle2bo6h8zgcia.jpg" alt="CH341a Dev Board" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first step was, of course, finding the &lt;a href="https://www.wch-ic.com/downloads/CH341DS1_PDF.html" rel="noopener noreferrer"&gt;datasheet&lt;/a&gt;, but it turned out to be quite short. After checking the basics, there was nothing more - no programming guide, no registers, nothing.&lt;br&gt;
Looking for a programming manual, I could only find drivers for Linux, Windows, and Android.&lt;/p&gt;

&lt;p&gt;The good news is that this chip has been extensively reverse engineered, so there is a lot of code available. This post is more about the journey of finding all the details.&lt;/p&gt;

&lt;p&gt;If you just want to check the code, jump to: &lt;a href="https://github.com/danguer/pych341" rel="noopener noreferrer"&gt;https://github.com/danguer/pych341&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Three Modes of CH341
&lt;/h2&gt;

&lt;p&gt;The first thing you will notice is that the CH341 behaves as three different devices depending on some pin configuration.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F17fsjcfwoqevhjnjwix8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F17fsjcfwoqevhjnjwix8.png" alt="Pin Configuration" width="800" height="487"&gt;&lt;/a&gt;&lt;br&gt;
The modes are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;UART&lt;/strong&gt; — in this mode the device shows up as a VCOM or Serial Port adapter. There is not much interest in this mode; aside from the full signals available, everything is transparent: you plug it in and it is recognized as a serial device, so no extra work is needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PRINT&lt;/strong&gt; — in this mode it behaves as a "standard Centronics printer interface" and should appear as a parallel printer. This also seems to be a transparent mode, so there is not much interesting here (for now).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EPP/MEM&lt;/strong&gt; — this is the most interesting mode, as you can use the device as an I2C master, SPI interface, or GPIO controller (it was apparently also designed to read/write parallel memory chips).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The datasheet shows how the pins have different uses under each mode.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz84wlxlqq4yqzm7fjnhe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz84wlxlqq4yqzm7fjnhe.png" alt="The three modes of CH341" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Starting with USB Programming
&lt;/h2&gt;

&lt;p&gt;Accessing the USB with &lt;code&gt;pyusb&lt;/code&gt; is quite straightforward:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find a device using the vendor ID and product ID (for EPP/MEM, &lt;code&gt;vendor_id=0x1A86, product_id=0x5512&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;List the endpoints.&lt;/li&gt;
&lt;li&gt;Find a bulk input (to read) and output (to write).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The write operation is usually wrapped in some special opcodes (more on this later), and the read is transparent - the data you receive comes from GPIO/I2C/SPI without extra frames or opcodes.&lt;/p&gt;
&lt;h2&gt;
  
  
  Reverse Engineering
&lt;/h2&gt;

&lt;p&gt;Here is where the fun starts. The WCH website contains this file: &lt;a href="https://www.wch-ic.com/downloads/CH341PAR_LINUX_ZIP.html" rel="noopener noreferrer"&gt;https://www.wch-ic.com/downloads/CH341PAR_LINUX_ZIP.html&lt;/a&gt;, and searching further leads to this repository:&lt;br&gt;
&lt;a href="https://github.com/WCHSoftGroup/ch341par_linux" rel="noopener noreferrer"&gt;https://github.com/WCHSoftGroup/ch341par_linux&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code is basically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A demo (testing all functions)&lt;/li&gt;
&lt;li&gt;A library&lt;/li&gt;
&lt;li&gt;A kernel driver/module&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The library calls the kernel driver and passes some arguments. It contains a lot of functions, some for different chips like CH347, and others that seem to not work at all (for example, calls to write/read from parallel memory chips).&lt;br&gt;
This looked like it would just be a matter of reading the source code and following along — except there is no source code for the library.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;README.md&lt;/code&gt; from the zip file points to: &lt;a href="https://github.com/WCHSoftGroup/ch34x_mphsi_master_linux" rel="noopener noreferrer"&gt;https://github.com/WCHSoftGroup/ch34x_mphsi_master_linux&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This repository contains a much simpler and more straightforward implementation. My first guess was that this was all that was needed, so I started with the I2C implementation.&lt;/p&gt;
&lt;h2&gt;
  
  
  I2C Implementation
&lt;/h2&gt;

&lt;p&gt;The implementation is based on the &lt;code&gt;ch341_i2c_stream&lt;/code&gt; function. The sequence in the original is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;CH341_CMD_I2C_STREAM&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CH341_CMD_I2C_STM_STA&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CH341_CMD_I2C_STM_OUT&lt;/code&gt; (&lt;code&gt;OR&lt;/code&gt; with the length of data)&lt;/li&gt;
&lt;li&gt;If reading: &lt;code&gt;CH341_CMD_I2C_STM_IN&lt;/code&gt; (&lt;code&gt;OR&lt;/code&gt; with the length of data)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CH341_CMD_I2C_STM_STO&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CH341_CMD_I2C_STM_END&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first thing to note is that there is a "packet" wrapped between &lt;code&gt;CH341_CMD_I2C_STREAM&lt;/code&gt; and &lt;code&gt;CH341_CMD_I2C_STM_END&lt;/code&gt;, meaning those opcodes are for the chip itself.&lt;br&gt;
After verifying with a logic analyzer and the I2C protocol, &lt;code&gt;CH341_CMD_I2C_STM_STA&lt;/code&gt; sends a &lt;strong&gt;Start&lt;/strong&gt; signal and &lt;code&gt;CH341_CMD_I2C_STM_STO&lt;/code&gt; sends a &lt;strong&gt;Stop&lt;/strong&gt; signal.&lt;/p&gt;

&lt;p&gt;The next thing to note is how you send/receive I2C data. The tricky part is that you must always send the address, which is defined as a 7-bit address plus an &lt;code&gt;R/W&lt;/code&gt; bit (&lt;code&gt;Read=1&lt;/code&gt;, &lt;code&gt;Write=0&lt;/code&gt;). Most libraries handle this automatically, but here you handle the sending and receiving of data directly.&lt;/p&gt;

&lt;p&gt;To write data to a device is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# send a 0xFF as message to address 0xC0
&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xC0&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xFF&lt;/span&gt;
&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;I2CCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MODE_STREAM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;I2CCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;START&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;# start signal
&lt;/span&gt;  &lt;span class="n"&gt;I2CCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DIR_OUT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# sending just 1 byte of data plus 1 byte of address
&lt;/span&gt;  &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;# sending 7-bit address and 0 as R/W bit
&lt;/span&gt;  &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;I2CCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STOP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;# stop signal
&lt;/span&gt;  &lt;span class="n"&gt;I2CCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To read data is a bit different, since you first need to write the address to the device and then read from it. For example, to read 1 byte from the device:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xC0&lt;/span&gt;
&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;I2CCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MODE_STREAM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;I2CCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;START&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;# start signal
&lt;/span&gt;  &lt;span class="c1"&gt;# write the address
&lt;/span&gt;  &lt;span class="n"&gt;I2CCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DIR_OUT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# sending just 1 byte of address
&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# sending 7-bit address and 1 as R/W bit
&lt;/span&gt;  &lt;span class="c1"&gt;# now actually read data from device
&lt;/span&gt;  &lt;span class="n"&gt;I2CCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DIR_IN&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# just read 1 byte
&lt;/span&gt;  &lt;span class="n"&gt;I2CCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STOP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;# stop signal
&lt;/span&gt;  &lt;span class="n"&gt;I2CCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;i2c.py&lt;/code&gt; module follows the &lt;code&gt;Arduino Wire&lt;/code&gt; library approach.&lt;/p&gt;

&lt;p&gt;More information about I2C: &lt;a href="https://www.ti.com/lit/an/sbaa565/sbaa565.pdf" rel="noopener noreferrer"&gt;https://www.ti.com/lit/an/sbaa565/sbaa565.pdf&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  GPIO Implementation
&lt;/h2&gt;

&lt;p&gt;This is probably the trickiest part. The first implementation appears to target CH347 and uses a control endpoint instead of bulk:&lt;br&gt;
&lt;a href="https://github.com/WCHSoftGroup/ch34x_mphsi_master_linux/blob/main/driver/ch34x_mphsi_master_gpio.c#L345" rel="noopener noreferrer"&gt;https://github.com/WCHSoftGroup/ch34x_mphsi_master_linux/blob/main/driver/ch34x_mphsi_master_gpio.c#L345&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The driver has &lt;code&gt;CH34xSetOutput&lt;/code&gt; and &lt;code&gt;CH34xSet_D5_D0&lt;/code&gt;, so I decided to cross-reference this against the older library source code: &lt;a href="https://github.com/zoobab/ch341-parport/blob/master/CH341PAR_LINUX/lib/ch34x_lib.c#L593" rel="noopener noreferrer"&gt;https://github.com/zoobab/ch341-parport/blob/master/CH341PAR_LINUX/lib/ch34x_lib.c#L593&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is also a simpler implementation here: &lt;a href="https://github.com/frank-zago/ch341-i2c-spi-gpio/blob/master/gpio-ch341.c#L198" rel="noopener noreferrer"&gt;https://github.com/frank-zago/ch341-i2c-spi-gpio/blob/master/gpio-ch341.c#L198&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Writing GPIO
&lt;/h3&gt;

&lt;p&gt;There are some undocumented values, but here is the packet structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[byte0] 0xA1 (output command)
[byte1] 0x6A (magic value)
[byte2] enable mask
[byte3] Byte 1 Data (0 for LOW, 1 for HIGH)
[byte4] Byte 1 Direction (0 for INPUT, 1 for OUTPUT)
[byte5] Byte 0 Data (0 for LOW, 1 for HIGH)
[byte6] Byte 0 Direction (0 for INPUT, 1 for OUTPUT)
[byte7] Byte 2 Data (0 for LOW, 1 for HIGH)
[byte8] Byte 2 Direction (should be 0x00)
[byte9] Byte 3 Data (0 for LOW, 1 for HIGH)
[byte10] Byte 3 Direction (should be 0x00)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The packet must be exactly 11 bytes.&lt;/p&gt;

&lt;h4&gt;
  
  
  GPIO Bytes
&lt;/h4&gt;

&lt;p&gt;There are 4 GPIO bytes in the following order:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Byte 1 (bits 8–15), pins: &lt;code&gt;ERR, PEMP, INT, SLCT, unknown, WAIT, READ, ADDR&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Byte 0 (bits 0–7), pins: &lt;code&gt;D0–D7&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Byte 2 (bits 16–23), pins: &lt;code&gt;WRITE, SCL&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Byte 3 (bits 24–31), pins: &lt;code&gt;SDA&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Enable Mask
&lt;/h4&gt;

&lt;p&gt;The enable mask consists of pairs of bits that enable output and direction. Since this function is only for writing outputs, you need to always set both to 1. It follows the same order as the GPIO bytes, meaning the first two bits control enable and data direction for Byte 1 (bits 8–15):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bits 0,1 = Byte 1 Enable, Direction
bits 2,3 = Byte 0 Enable, Direction
bits 4,5 = Byte 2 Enable, Direction
bits 6,7 = Byte 3 Enable, Direction
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that Byte 2 and Byte 3 only allow output direction, but you need to set Enable=0, Direction=1. The documentation is not very clear about the meaning of "enable" here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing with &lt;code&gt;CH34xSet_D5_D0&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;A special message exists to set only pins D0–D5. The packet is very simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;GPIOCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UIO_STREAM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;              &lt;span class="c1"&gt;# 0xAB
&lt;/span&gt;    &lt;span class="n"&gt;GPIOCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UIO_DIR&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mh"&gt;0x3F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;# 0x40
&lt;/span&gt;    &lt;span class="n"&gt;GPIOCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UIO_OUT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x3F&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;# 0x80
&lt;/span&gt;    &lt;span class="n"&gt;GPIOCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UIO_STREAM_END&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;# 0x20
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;mask&lt;/code&gt; bits represent the pins to set HIGH. For example, to set &lt;code&gt;D0&lt;/code&gt; HIGH use &lt;code&gt;0x1&lt;/code&gt;, and to set &lt;code&gt;D0&lt;/code&gt; and &lt;code&gt;D2&lt;/code&gt; HIGH use &lt;code&gt;0x5&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reading
&lt;/h3&gt;

&lt;p&gt;Reading is simple, though it involves some undocumented behavior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GPIOCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INPUT&lt;/span&gt; &lt;span class="c1"&gt;# 0xA0
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After sending the command, read 6 bytes of data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[byte0] Byte 0 Data
[byte1] Byte 1 Data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All other bytes are undocumented or represent output pins.&lt;br&gt;
To read the value of &lt;code&gt;D0&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;d0_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  SPI Implementation
&lt;/h2&gt;

&lt;p&gt;This is the simplest implementation, but it does require some understanding of SPI. The implementation needs to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Send X bytes&lt;/li&gt;
&lt;li&gt;Read X bytes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is because SPI is full-duplex, meaning that when you send data you also receive data within the same clock cycle. You must send and read simultaneously, or the buffers will overflow.&lt;/p&gt;

&lt;p&gt;The implementation is based on: &lt;a href="https://github.com/WCHSoftGroup/ch34x_mphsi_master_linux/blob/main/driver/ch34x_mphsi_master_spi.c#L511" rel="noopener noreferrer"&gt;https://github.com/WCHSoftGroup/ch34x_mphsi_master_linux/blob/main/driver/ch34x_mphsi_master_spi.c#L511&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The command is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;data_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;bytearray&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SPICmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MODE_STREAM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 0xA8
&lt;/span&gt;  &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;

  &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# after writing, read the controller response
&lt;/span&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is all there is to it. To read from SPI, simply call &lt;code&gt;data = write(0xFF)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The one tricky part is that the chip always transmits in LSB-first order, so sending &lt;code&gt;1&lt;/code&gt; is transmitted as &lt;code&gt;1 0 0 0 0 0 0 0&lt;/code&gt;. Most devices expect MSB-first (&lt;code&gt;0 0 0 0 0 0 0 1&lt;/code&gt;), so you can use a lookup table to convert between the two.&lt;/p&gt;

&lt;h3&gt;
  
  
  Chip Select
&lt;/h3&gt;

&lt;p&gt;The board has &lt;code&gt;CS0&lt;/code&gt;, &lt;code&gt;CS1&lt;/code&gt;, and &lt;code&gt;CS2&lt;/code&gt;, but there is no dedicated command for chip select. Instead, you enable it through GPIO using &lt;code&gt;CH34xSet_D5_D0&lt;/code&gt;. For example, set &lt;code&gt;D0&lt;/code&gt; HIGH before a transaction and LOW after to use it as a chip select signal.&lt;/p&gt;

</description>
      <category>wch</category>
      <category>python</category>
    </item>
    <item>
      <title>Zephyr on Arduino UNO Q MCU</title>
      <dc:creator>Daniel Guerrero</dc:creator>
      <pubDate>Fri, 02 Jan 2026 19:53:20 +0000</pubDate>
      <link>https://dev.to/danielmx/zephyr-on-arduino-uno-q-mcu-5974</link>
      <guid>https://dev.to/danielmx/zephyr-on-arduino-uno-q-mcu-5974</guid>
      <description>&lt;p&gt;The Arduino UNO Q have a &lt;a href="https://www.st.com/en/microcontrollers-microprocessors/stm32u575-585.html" rel="noopener noreferrer"&gt;STM32U585&lt;/a&gt; inside doing all the Arduino stuff, it communicates with main processor and GPIO pins on board; it seems the only way to get a pinout is the schematics:&lt;br&gt;
&lt;a href="https://docs.arduino.cc/resources/schematics/ABX00162-schematics.pdf" rel="noopener noreferrer"&gt;https://docs.arduino.cc/resources/schematics/ABX00162-schematics.pdf&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The pinout image have brief information about the MCU pins&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F057pus6kjj26qsn284xj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F057pus6kjj26qsn284xj.png" alt="Arduino UNO Q Pinout" width="800" height="755"&gt;&lt;/a&gt; &lt;br&gt;
&lt;a href="https://docs.arduino.cc/tutorials/uno-q/user-manual/#pinout" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But only shows that pins belong to MCU, and the only indication are on RGB LED 3 and 4 that shows the GPIO used for the MCU.&lt;/p&gt;

&lt;p&gt;For this example it will be needed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zephyr (on the PC Host, probably can be reused the version in UNO Q)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.android.com/tools/releases/platform-tools" rel="noopener noreferrer"&gt;ADB tools&lt;/a&gt; (to connect to the device from PC Host)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Zephyr
&lt;/h2&gt;

&lt;p&gt;You need to &lt;a href="https://docs.zephyrproject.org/latest/develop/getting_started/index.html" rel="noopener noreferrer"&gt;install&lt;/a&gt; / update Zephyr. Is important to have at least &lt;a href="https://github.com/zephyrproject-rtos/zephyr/tree/v4.3.0/boards/arduino/uno_q" rel="noopener noreferrer"&gt;version 4.3.0&lt;/a&gt; as that is the first version with support&lt;/p&gt;
&lt;h2&gt;
  
  
  Compile example
&lt;/h2&gt;

&lt;p&gt;It can be used the &lt;code&gt;blinky&lt;/code&gt; &lt;a href="https://docs.zephyrproject.org/latest/develop/getting_started/index.html#build-the-blinky-sample" rel="noopener noreferrer"&gt;example directly from documentation&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# use the path to your zephyr setup
cd ~/zephyrproject/zephyr
west build -p always -b arduino_uno_q samples/basic/blinky
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Upload to device
&lt;/h2&gt;

&lt;p&gt;Once compiled it needs to be copied to UNO Q device using adb:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;adb push build/zephyr/zephyr.elf /tmp/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Flash MCU
&lt;/h2&gt;

&lt;p&gt;The only remaining step is to flash the STM32 MCU this can be done with the tools already installed in the UNO Q&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;adb shell

# following commands must be in the UNO Q
# paths are hardcoded but should work
# probably some paths needs to be updated with proper versions
/home/arduino/.arduino15/packages/arduino/tools/remoteocd/0.0.4-rc.4/remoteocd \
    upload \
    --adb-path "/home/arduino/.arduino15/packages/arduino/tools/adb/32.0.0/adb" \
    -s "{upload.port.properties.serialNumber}" \
    -f "/home/arduino/.arduino15/packages/arduino/hardware/zephyr/0.52.0/variants/arduino_uno_q_stm32u585xx/flash_bootloader.cfg" \
    "--verbose" \
    /tmp/zephyr.elf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything is fine, the &lt;code&gt;LED3&lt;/code&gt; will blink with a green color&lt;/p&gt;

&lt;h2&gt;
  
  
  Restoring Sketch Bootloader
&lt;/h2&gt;

&lt;p&gt;If you use Arduino App Lab and try to upload a new sketch, you will notice there will be error on uploading, this is because the MCU contains a called "Sketch Bootloader" and the sketch code is added on top of that. &lt;br&gt;
But the Arduino UNO Q have the commands to restore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;arduino-cli burn-bootloader -b arduino:zephyr:unoq -P jlink
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this command will upload the Sketch Bootloader so you can upload code from the App Lab. Nice!&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.zephyrproject.org/latest/boards/arduino/uno_q/doc/index.html" rel="noopener noreferrer"&gt;https://docs.zephyrproject.org/latest/boards/arduino/uno_q/doc/index.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/arduino/remoteocd" rel="noopener noreferrer"&gt;https://github.com/arduino/remoteocd&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>arduino</category>
    </item>
    <item>
      <title>MAX7219 Example (8 digit segment driver)</title>
      <dc:creator>Daniel Guerrero</dc:creator>
      <pubDate>Wed, 31 Dec 2025 20:35:00 +0000</pubDate>
      <link>https://dev.to/danielmx/max7219-example-8-digit-segment-driver-52m8</link>
      <guid>https://dev.to/danielmx/max7219-example-8-digit-segment-driver-52m8</guid>
      <description>&lt;p&gt;The MAX7219 is a 8 digit segment driver, it can also work as standard 8x8 LED driver, but since there is BCD support, it works much better with 7-segment parts.&lt;/p&gt;

&lt;p&gt;The board I used have 8 segments and the MAX7219&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg7tcvmp74kotqlhb9iev.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg7tcvmp74kotqlhb9iev.jpg" alt="MAX7219 8 digit 7-segment" width="600" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The inputs are just Power(&lt;code&gt;GND&lt;/code&gt;, &lt;code&gt;VCC&lt;/code&gt;), &lt;code&gt;DIN&lt;/code&gt; (Serial Data Input), &lt;code&gt;CLK&lt;/code&gt; and &lt;code&gt;LOAD/CS&lt;/code&gt;&lt;br&gt;
Even it looks like a SPI module, only the MAX7221 supports it, so the input for MAX7219 is serial and is simple to use.&lt;/p&gt;

&lt;p&gt;It needs to be sent 16 bit data which are split into lower 8 bits for the data and higher 8 bits for register.&lt;/p&gt;

&lt;p&gt;The datasheet is very clear and helpful about all parts, my only complain is the functional diagram suggest the data is loaded with LSB first which is not the case.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwwd83go68xrsp676yvjm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwwd83go68xrsp676yvjm.png" alt="Serial Data Format" width="800" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the address, there are few commands:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faulx9324yalt3xwcl7t0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faulx9324yalt3xwcl7t0.png" alt="Register Address Map" width="439" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Digit 0-7 data (&lt;code&gt;0x1&lt;/code&gt; to &lt;code&gt;0x8&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Decode mode &lt;code&gt;0x9&lt;/code&gt; (Disable / Enable BCD for each digit)&lt;/li&gt;
&lt;li&gt;Intensity &lt;code&gt;0xA&lt;/code&gt; (16  levels of intensity going from &lt;code&gt;0x0&lt;/code&gt; to &lt;code&gt;0xF&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Scan Limit &lt;code&gt;0xB&lt;/code&gt; (Disable / Enable digit output)&lt;/li&gt;
&lt;li&gt;Shutdown &lt;code&gt;0xC&lt;/code&gt; (Disable / Enable output)&lt;/li&gt;
&lt;li&gt;Display Test &lt;code&gt;0xF&lt;/code&gt; (Disable / Enable test mode).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;Display Test&lt;/code&gt; just enable all segments and all digits at full intensity.&lt;br&gt;
For &lt;code&gt;Shutdown&lt;/code&gt; if data is &lt;code&gt;0x1&lt;/code&gt; will enable output (TBH a bit odd to use that naming) &lt;/p&gt;
&lt;h2&gt;
  
  
  Register: Scan Limit
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Scan Limit&lt;/code&gt; allows to how many digits to be display, so it can be up to &lt;code&gt;0x7&lt;/code&gt; (to display 8 digits). As note, the reset value of &lt;code&gt;0x0&lt;/code&gt; means that will show first digit; if you want to disable all output then you need to use the &lt;code&gt;Shutdown&lt;/code&gt; command, or just set the first digit to &lt;code&gt;0x0&lt;/code&gt; (no segment on) for &lt;code&gt;No Decode&lt;/code&gt; mode, or &lt;code&gt;0xF&lt;/code&gt; for &lt;code&gt;BCD&lt;/code&gt; mode&lt;/p&gt;
&lt;h2&gt;
  
  
  Register: Digit
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Digit&lt;/code&gt; data will store 8 bits for the specific digit, the data can be stored in two ways: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Standard (No BCD / No Decode)&lt;/li&gt;
&lt;li&gt;BCD&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the Standard, you need to select through bits which part to show from the 7-segment, so for example to display a &lt;code&gt;1&lt;/code&gt; you can store &lt;code&gt;0x30&lt;/code&gt; or &lt;code&gt;D5=1,D4=1&lt;/code&gt; (&lt;code&gt;B=1,C=1&lt;/code&gt;)&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1n2kzr8a7qdpfgwn16ga.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1n2kzr8a7qdpfgwn16ga.png" alt="No Decode Mode" width="446" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the BCD mode, the value from &lt;code&gt;0x0&lt;/code&gt; to &lt;code&gt;0x9&lt;/code&gt; (or &lt;code&gt;0-9&lt;/code&gt;) will be converted into the proper segments on, so if a &lt;code&gt;0x1&lt;/code&gt; is stored, the driver will properly convert to show segments &lt;code&gt;B=1,C=1&lt;/code&gt;.&lt;br&gt;
There are some special characters going from &lt;code&gt;0xA&lt;/code&gt; to &lt;code&gt;0xF&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0xA = dash(-)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0xB = E&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0xC = H&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0xD = L&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0xE = P&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0xF&lt;/code&gt; blank, so no output, the same as &lt;code&gt;0x0&lt;/code&gt; in &lt;code&gt;No Decode Mode&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Yes you can send a &lt;code&gt;HELP&lt;/code&gt; message with &lt;code&gt;0x040C 0x030B 0x020D 0x010E&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Register: Decode Mode
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Decode Mode&lt;/code&gt;register allows to use the &lt;code&gt;No Decode/BCD&lt;/code&gt; mode, and the register is a bit interesting since is a mask, if the value is &lt;code&gt;0x0&lt;/code&gt; means no decode so the data are just the segment to set on.&lt;br&gt;
But if you want a specific digit to use BCD, you can use as mask, so for example to enable BCD on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Digit 0 &lt;code&gt;0x1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Digit 1 &lt;code&gt;0x2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Digit 0 and 1 &lt;code&gt;0x3&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Register: Loading Data
&lt;/h2&gt;

&lt;p&gt;The loading data is very simple, when you rise the &lt;code&gt;CLK&lt;/code&gt; it will read the &lt;code&gt;DIN&lt;/code&gt; and add to serial buffer (&lt;code&gt;MSB&lt;/code&gt; to &lt;code&gt;LSB&lt;/code&gt; order).&lt;br&gt;
So sending a bit is very simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;digitalWrite(PIN_CLK, LOW);
// check if MSB bit is on
if (cmd &amp;amp; 0x8000) {
    digitalWrite(PIN_DIN, HIGH);
} else {
    digitalWrite(PIN_DIN, LOW);
}
digitalWrite(PIN_CLK, HIGH);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And to send a 16 bit value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// enable test mode
// 0x0F is test mode register
// 0x01 is enable data
uint16_t cmd = 0x0F01;
for (int i = 0; i &amp;lt; 16; i++) {
    digitalWrite(PIN_CLK, LOW);
    // check if MSB bit is on
    if (cmd &amp;amp; 0x8000) {
        digitalWrite(PIN_DIN, HIGH);
    } else {
        digitalWrite(PIN_DIN, LOW);
    }
    digitalWrite(PIN_CLK, HIGH);
    // shift one bit
    cmd &amp;lt;&amp;lt;= 1;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the case of the MAX7219 when &lt;code&gt;LOAD&lt;/code&gt; rises, it will load the last 16 bits from the &lt;code&gt;DIN&lt;/code&gt; input into the decoder and run the command.&lt;br&gt;
So this is achieved after sending the data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// latch the data
// rise the LOAD pin from low to high and go back into low after that
digitalWrite(PIN_LOAD, LOW);
digitalWrite(PIN_LOAD, HIGH);
digitalWrite(PIN_LOAD, LOW);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Commands
&lt;/h2&gt;

&lt;p&gt;Everything is a 16 bit data, so there is a helper function to build the data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uint16_t buildCmd(uint8_t registerAddress, uint8_t data)
{
    return ((uint16_t)registerAddress &amp;lt;&amp;lt; 8) | data;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that this can be converted into a macro if is needed better performance.&lt;/p&gt;

&lt;p&gt;So the commands are very easy to build, for example to send a number 6 to digit 0 (using BCD):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// 0x1 is the register for digit 0
uint16_t cmd = buildCmd(0x1, 6);
// this is the function using code previously 
// posted to send data to module
sendCmd(cmd);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or if not using BCD:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// 0x1 is the register for digit 0
// 6 uses A,C,D,E,F,G so is 
// 0101 1111 or 0x5F
uint16_t cmd = buildCmd(0x1, 0x5F);
// this is the function using code previously 
// posted to send data to module
sendCmd(cmd);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;The example uses the test mode, but later sets all the registers to "reset" most of them, note that this is not really needed if you only reset the module and never use the test mode.&lt;br&gt;
But I think is good to have it so you can configure everything before use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cmdSetScanLimit(7); // Enable all 8 digits
cmdSetIntensity(0); // lowest intensity
cmdSetDecodeMode(0xFF); // all digits will use BCD

// set all segments to blank
for (uint8_t i = 0; i &amp;lt; 8; i++) {
  uint16_t cmd = buildCmd(REGISTER_DIGIT0 + i, 0xF);
  sendCmd(cmd);
}

// send all the possible values on BCD, finishing with blank
for (uint8_t i = 0; i &amp;lt; 8; i++) {
  for (uint8_t j = 0; j &amp;lt; 16; j++) {
    uint16_t cmd = buildCmd(REGISTER_DIGIT0 + i, j); 
    sendCmd(cmd);
    delay(200);
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example url
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/danguer/arduino-examples/tree/main/max7219" rel="noopener noreferrer"&gt;https://github.com/danguer/arduino-examples/tree/main/max7219&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Datasheet
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.analog.com/media/en/technical-documentation/data-sheets/max7219-max7221.pdf" rel="noopener noreferrer"&gt;https://www.analog.com/media/en/technical-documentation/data-sheets/max7219-max7221.pdf&lt;/a&gt;&lt;/p&gt;

</description>
      <category>arduino</category>
    </item>
    <item>
      <title>MAX7219 Example (8 digit segment driver)</title>
      <dc:creator>Daniel Guerrero</dc:creator>
      <pubDate>Wed, 31 Dec 2025 20:35:00 +0000</pubDate>
      <link>https://dev.to/danielmx/max7219-example-8-digit-segment-driver-1dfa</link>
      <guid>https://dev.to/danielmx/max7219-example-8-digit-segment-driver-1dfa</guid>
      <description>&lt;p&gt;The MAX7219 is a 8 digit segment driver, it can also work as standard 8x8 LED driver, but since there is BCD support, it works much better with 7-segment parts.&lt;/p&gt;

&lt;p&gt;The board I used have 8 segments and the MAX7219&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg7tcvmp74kotqlhb9iev.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg7tcvmp74kotqlhb9iev.jpg" alt="MAX7219 8 digit 7-segment" width="600" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The inputs are just Power(&lt;code&gt;GND&lt;/code&gt;, &lt;code&gt;VCC&lt;/code&gt;), &lt;code&gt;DIN&lt;/code&gt; (Serial Data Input), &lt;code&gt;CLK&lt;/code&gt; and &lt;code&gt;LOAD/CS&lt;/code&gt;&lt;br&gt;
Even it looks like a SPI module, only the MAX7221 supports it, so the input for MAX7219 is serial and is simple to use.&lt;/p&gt;

&lt;p&gt;It needs to be sent 16 bit data which are split into lower 8 bits for the data and higher 8 bits for register.&lt;/p&gt;

&lt;p&gt;The datasheet is very clear and helpful about all parts, my only complain is the functional diagram suggest the data is loaded with LSB first which is not the case.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwwd83go68xrsp676yvjm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwwd83go68xrsp676yvjm.png" alt="Serial Data Format" width="800" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the address, there are few commands:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faulx9324yalt3xwcl7t0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faulx9324yalt3xwcl7t0.png" alt="Register Address Map" width="439" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Digit 0-7 data (&lt;code&gt;0x1&lt;/code&gt; to &lt;code&gt;0x8&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Decode mode &lt;code&gt;0x9&lt;/code&gt; (Disable / Enable BCD for each digit)&lt;/li&gt;
&lt;li&gt;Intensity &lt;code&gt;0xA&lt;/code&gt; (16  levels of intensity going from &lt;code&gt;0x0&lt;/code&gt; to &lt;code&gt;0xF&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Scan Limit &lt;code&gt;0xB&lt;/code&gt; (Disable / Enable digit output)&lt;/li&gt;
&lt;li&gt;Shutdown &lt;code&gt;0xC&lt;/code&gt; (Disable / Enable output)&lt;/li&gt;
&lt;li&gt;Display Test &lt;code&gt;0xF&lt;/code&gt; (Disable / Enable test mode).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;Display Test&lt;/code&gt; just enable all segments and all digits at full intensity.&lt;br&gt;
For &lt;code&gt;Shutdown&lt;/code&gt; if data is &lt;code&gt;0x1&lt;/code&gt; will enable output (TBH a bit odd to use that naming) &lt;/p&gt;
&lt;h2&gt;
  
  
  Register: Scan Limit
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Scan Limit&lt;/code&gt; allows to how many digits to be display, so it can be up to &lt;code&gt;0x7&lt;/code&gt; (to display 8 digits). As note, the reset value of &lt;code&gt;0x0&lt;/code&gt; means that will show first digit; if you want to disable all output then you need to use the &lt;code&gt;Shutdown&lt;/code&gt; command, or just set the first digit to &lt;code&gt;0x0&lt;/code&gt; (no segment on) for &lt;code&gt;No Decode&lt;/code&gt; mode, or &lt;code&gt;0xF&lt;/code&gt; for &lt;code&gt;BCD&lt;/code&gt; mode&lt;/p&gt;
&lt;h2&gt;
  
  
  Register: Digit
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Digit&lt;/code&gt; data will store 8 bits for the specific digit, the data can be stored in two ways: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Standard (No BCD / No Decode)&lt;/li&gt;
&lt;li&gt;BCD&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the Standard, you need to select through bits which part to show from the 7-segment, so for example to display a &lt;code&gt;1&lt;/code&gt; you can store &lt;code&gt;0x30&lt;/code&gt; or &lt;code&gt;D5=1,D4=1&lt;/code&gt; (&lt;code&gt;B=1,C=1&lt;/code&gt;)&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1n2kzr8a7qdpfgwn16ga.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1n2kzr8a7qdpfgwn16ga.png" alt="No Decode Mode" width="446" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the BCD mode, the value from &lt;code&gt;0x0&lt;/code&gt; to &lt;code&gt;0x9&lt;/code&gt; (or &lt;code&gt;0-9&lt;/code&gt;) will be converted into the proper segments on, so if a &lt;code&gt;0x1&lt;/code&gt; is stored, the driver will properly convert to show segments &lt;code&gt;B=1,C=1&lt;/code&gt;.&lt;br&gt;
There are some special characters going from &lt;code&gt;0xA&lt;/code&gt; to &lt;code&gt;0xF&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0xA = dash(-)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0xB = E&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0xC = H&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0xD = L&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0xE = P&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0xF&lt;/code&gt; blank, so no output, the same as &lt;code&gt;0x0&lt;/code&gt; in &lt;code&gt;No Decode Mode&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Yes you can send a &lt;code&gt;HELP&lt;/code&gt; message with &lt;code&gt;0x040C 0x030B 0x020D 0x010E&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Register: Decode Mode
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Decode Mode&lt;/code&gt;register allows to use the &lt;code&gt;No Decode/BCD&lt;/code&gt; mode, and the register is a bit interesting since is a mask, if the value is &lt;code&gt;0x0&lt;/code&gt; means no decode so the data are just the segment to set on.&lt;br&gt;
But if you want a specific digit to use BCD, you can use as mask, so for example to enable BCD on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Digit 0 &lt;code&gt;0x1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Digit 1 &lt;code&gt;0x2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Digit 0 and 1 &lt;code&gt;0x3&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Register: Loading Data
&lt;/h2&gt;

&lt;p&gt;The loading data is very simple, when you rise the &lt;code&gt;CLK&lt;/code&gt; it will read the &lt;code&gt;DIN&lt;/code&gt; and add to serial buffer (&lt;code&gt;MSB&lt;/code&gt; to &lt;code&gt;LSB&lt;/code&gt; order).&lt;br&gt;
So sending a bit is very simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;digitalWrite(PIN_CLK, LOW);
// check if MSB bit is on
if (cmd &amp;amp; 0x8000) {
    digitalWrite(PIN_DIN, HIGH);
} else {
    digitalWrite(PIN_DIN, LOW);
}
digitalWrite(PIN_CLK, HIGH);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And to send a 16 bit value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// enable test mode
// 0x0F is test mode register
// 0x01 is enable data
uint16_t cmd = 0x0F01;
for (int i = 0; i &amp;lt; 16; i++) {
    digitalWrite(PIN_CLK, LOW);
    // check if MSB bit is on
    if (cmd &amp;amp; 0x8000) {
        digitalWrite(PIN_DIN, HIGH);
    } else {
        digitalWrite(PIN_DIN, LOW);
    }
    digitalWrite(PIN_CLK, HIGH);
    // shift one bit
    cmd &amp;lt;&amp;lt;= 1;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the case of the MAX7219 when &lt;code&gt;LOAD&lt;/code&gt; rises, it will load the last 16 bits from the &lt;code&gt;DIN&lt;/code&gt; input into the decoder and run the command.&lt;br&gt;
So this is achieved after sending the data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// latch the data
// rise the LOAD pin from low to high and go back into low after that
digitalWrite(PIN_LOAD, LOW);
digitalWrite(PIN_LOAD, HIGH);
digitalWrite(PIN_LOAD, LOW);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Commands
&lt;/h2&gt;

&lt;p&gt;Everything is a 16 bit data, so there is a helper function to build the data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uint16_t buildCmd(uint8_t registerAddress, uint8_t data)
{
    return ((uint16_t)registerAddress &amp;lt;&amp;lt; 8) | data;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that this can be converted into a macro if is needed better performance.&lt;/p&gt;

&lt;p&gt;So the commands are very easy to build, for example to send a number 6 to digit 0 (using BCD):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// 0x1 is the register for digit 0
uint16_t cmd = buildCmd(0x1, 6);
// this is the function using code previously 
// posted to send data to module
sendCmd(cmd);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or if not using BCD:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// 0x1 is the register for digit 0
// 6 uses A,C,D,E,F,G so is 
// 0101 1111 or 0x5F
uint16_t cmd = buildCmd(0x1, 0x5F);
// this is the function using code previously 
// posted to send data to module
sendCmd(cmd);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;The example uses the test mode, but later sets all the registers to "reset" most of them, note that this is not really needed if you only reset the module and never use the test mode.&lt;br&gt;
But I think is good to have it so you can configure everything before use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cmdSetScanLimit(7); // Enable all 8 digits
cmdSetIntensity(0); // lowest intensity
cmdSetDecodeMode(0xFF); // all digits will use BCD

// set all segments to blank
for (uint8_t i = 0; i &amp;lt; 8; i++) {
  uint16_t cmd = buildCmd(REGISTER_DIGIT0 + i, 0xF);
  sendCmd(cmd);
}

// send all the possible values on BCD, finishing with blank
for (uint8_t i = 0; i &amp;lt; 8; i++) {
  for (uint8_t j = 0; j &amp;lt; 16; j++) {
    uint16_t cmd = buildCmd(REGISTER_DIGIT0 + i, j); 
    sendCmd(cmd);
    delay(200);
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example url
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/danguer/arduino-examples/tree/main/max7219" rel="noopener noreferrer"&gt;https://github.com/danguer/arduino-examples/tree/main/max7219&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Datasheet
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.analog.com/media/en/technical-documentation/data-sheets/max7219-max7221.pdf" rel="noopener noreferrer"&gt;https://www.analog.com/media/en/technical-documentation/data-sheets/max7219-max7221.pdf&lt;/a&gt;&lt;/p&gt;

</description>
      <category>arduino</category>
    </item>
    <item>
      <title>TM1637 Board Arduino Example</title>
      <dc:creator>Daniel Guerrero</dc:creator>
      <pubDate>Tue, 18 Nov 2025 07:10:10 +0000</pubDate>
      <link>https://dev.to/danielmx/tm1637-board-arduino-example-1po1</link>
      <guid>https://dev.to/danielmx/tm1637-board-arduino-example-1po1</guid>
      <description>&lt;p&gt;The TM1637 is a 8 segments led controller which can control up to 6 displays and key scan of 16 inputs.&lt;br&gt;
There are multiple boards but the most common is using 4 displays with two dots in the middle so can be used as a timer display.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foy8e9upz01mn8q1zm1gb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foy8e9upz01mn8q1zm1gb.jpg" alt="TM1637 Board" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The protocol is similar to I2C but is simpler as there is no need of device address.&lt;br&gt;
So the protocol is the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start Signal&lt;/li&gt;
&lt;li&gt;Command Data Byte&lt;/li&gt;
&lt;li&gt;Optional Data Byte(s)&lt;/li&gt;
&lt;li&gt;End Signal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftrl8lek7kpru49666k48.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftrl8lek7kpru49666k48.png" alt="Example of protocol" width="800" height="212"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Start Signal
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CLK&lt;/code&gt; must be &lt;code&gt;HIGH&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DIO&lt;/code&gt; must transition from &lt;code&gt;HIGH&lt;/code&gt; to &lt;code&gt;LOW&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  End Signal
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CLK&lt;/code&gt; must be &lt;code&gt;HIGH&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DIO&lt;/code&gt; must transition from &lt;code&gt;LOW&lt;/code&gt; to &lt;code&gt;HIGH&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Sending Data
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DIO&lt;/code&gt; must be set to value when &lt;code&gt;CLK&lt;/code&gt; is low&lt;/li&gt;
&lt;li&gt;Send 8 bits, each clock cycle can be at most &lt;code&gt;2us&lt;/code&gt; (maximum speed of &lt;code&gt;500Khz&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;After 8 bits the 9th clock cycle the chip will send an ACK setting DIO to &lt;code&gt;LOW&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are 3 types of commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data&lt;/strong&gt; command (write to displays or read key scan)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Address&lt;/strong&gt; command (which display to use, it can be up to 6 displays, but the board only contain 4)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Display&lt;/strong&gt;, set displays &lt;code&gt;ON&lt;/code&gt;/&lt;code&gt;OFF&lt;/code&gt; and set brightness (8 possible levels)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;Data&lt;/strong&gt; command allows to send a specific address or auto-increment (the most common scenario) so after setting the initial address it can be sent all the data to write in the displays without need to keep setting the address after each command.&lt;/p&gt;

&lt;p&gt;The examples in the datasheet shows that &lt;strong&gt;Display&lt;/strong&gt; commands are sent at the end; but there is no need for that, it can be sent before any &lt;strong&gt;Data&lt;/strong&gt; command to set the configuration; after set, there is no need to be changed (except for some reason the display is reset)&lt;/p&gt;

&lt;p&gt;The displays in the board are 8 Segments Displays&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fepo5n21sm8nuse8dfzzl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fepo5n21sm8nuse8dfzzl.png" alt="8 Segments Display" width="378" height="507"&gt;&lt;/a&gt;&lt;br&gt;
Actually are 7 Segments Displays as there is no dot and the two dots in the middle are handled by the second display.&lt;br&gt;
The byte order is: &lt;code&gt;Xgfedcba&lt;/code&gt; where X is the dot or &lt;code&gt;DP&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Arduino Code
&lt;/h2&gt;

&lt;p&gt;To make work in Arduino, you need 2 pin inputs and three functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start Transfer&lt;/li&gt;
&lt;li&gt;End Transfer&lt;/li&gt;
&lt;li&gt;Byte Write
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void dataTransferStart() {
  // according to doc, start must be
  // a transition of DIO from LOW to HIGH
  // when a CLK clock is HIGH
  digitalWrite(PIN_DIO, HIGH);
  digitalWrite(PIN_CLK, HIGH);
  delayClock();
  digitalWrite(PIN_DIO, LOW);
  delayClock();
  digitalWrite(PIN_CLK, LOW);
  delayClock();
}

void dataTransferEnd() {
  // according to doc, end must be
  // a transition of DIO from HIGH to LOW
  // when a CLK clock is HIGH
  digitalWrite(PIN_DIO, LOW);
  digitalWrite(PIN_CLK, HIGH);
  delayClock();
  digitalWrite(PIN_DIO, HIGH);
  digitalWrite(PIN_CLK, LOW);
  delayClock();
}

unsigned char writeByte(unsigned char data) {
  // clock is assumed to be low, but just in case
  digitalWrite(PIN_CLK, LOW);

  for (unsigned char i = 0; i &amp;lt; 8; i++) {
    digitalWrite(PIN_DIO, (data &amp;amp; 0x1) ? HIGH : LOW);
    data = data &amp;gt;&amp;gt; 1;

    // run a clock cycle
    delayClock();
    digitalWrite(PIN_CLK, HIGH);
    delayClock();
    digitalWrite(PIN_CLK, LOW);
  }

  // here the chip does an ACK for one cycle
  pinMode(PIN_DIO, INPUT);
  delayClock();
  unsigned char ack = digitalRead(PIN_DIO);

  // finish clock cycle
  digitalWrite(PIN_CLK, HIGH);
  delayClock();
  digitalWrite(PIN_CLK, LOW);
  pinMode(PIN_DIO, OUTPUT);

  return ack;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The commands are very simple, the two MSB bits define the type of command:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;01&lt;/code&gt; &lt;strong&gt;Data&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;10&lt;/code&gt; &lt;strong&gt;Display&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;11&lt;/code&gt; &lt;strong&gt;Address&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most simple is the display:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void setBrightness(unsigned char brightness) {
  // display settings
  dataTransferStart();
  // this will be 0b10_00_1_XXX
  writeByte(CMD_DISPLAY | CMD_DISPLAY_ON | (brightness &amp;amp; 0x7));
  dataTransferEnd();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the &lt;code&gt;0b10_00_1_XXX&lt;/code&gt; means: &lt;code&gt;10&lt;/code&gt; is the &lt;strong&gt;Display&lt;/strong&gt; command, the &lt;code&gt;00&lt;/code&gt; are "irrelevant" items in the datasheet, &lt;code&gt;1&lt;/code&gt; is to enable the display and &lt;code&gt;XXX&lt;/code&gt; is the level of the brightness.&lt;/p&gt;

&lt;p&gt;The full code and example is here: &lt;a href="https://github.com/danguer/arduino-examples/tree/main/tm1637" rel="noopener noreferrer"&gt;https://github.com/danguer/arduino-examples/tree/main/tm1637&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/avishorp/TM1637/blob/master/docs/TM1637_V2.4_EN.pdf" rel="noopener noreferrer"&gt;Datasheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dmadison/LED-Segment-ASCII/tree/master/7-Segment" rel="noopener noreferrer"&gt;ASCII library&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>arduino</category>
    </item>
    <item>
      <title>HC05 / XBee First Steps</title>
      <dc:creator>Daniel Guerrero</dc:creator>
      <pubDate>Sun, 19 Oct 2025 03:17:16 +0000</pubDate>
      <link>https://dev.to/danielmx/hc05-xbee-first-steps-3h48</link>
      <guid>https://dev.to/danielmx/hc05-xbee-first-steps-3h48</guid>
      <description>&lt;p&gt;Long time ago, while researching ways to communicate through arduino, I found XBee modules, I was looking LoRa modules and this seems to fit so I got several of them&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhp9sohh174d492wl1g9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhp9sohh174d492wl1g9.jpg" alt="XBee Modules" width="458" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;since the pins are smaller than regular later I got something called an XBee Explorer to connect to computer&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fge3giyi8at49h96c2twb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fge3giyi8at49h96c2twb.jpg" alt="XBee Explorer" width="400" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I didn't know at the time much about communication modules so didn't do much research. &lt;br&gt;
Recently I wanted to test the modules again, so I started doing the research.&lt;/p&gt;

&lt;p&gt;The original XBee are devices from &lt;a href="https://www.digi.com/products/embedded-systems/digi-xbee/rf-modules" rel="noopener noreferrer"&gt;Zigbee&lt;/a&gt; that have a specific shape and specific pins, there are different options for modules, including LoRa, WiFi and Bluetooth&lt;/p&gt;

&lt;p&gt;The pinout for the Xbee is this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fauyyy8b7rdpklzudpqk0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fauyyy8b7rdpklzudpqk0.png" alt="XBee Pinout" width="800" height="509"&gt;&lt;/a&gt; &lt;br&gt;
&lt;a href="https://www.electronicwings.com/sensors-modules/xbee-module" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, the modules I got are labeled "HC05" it turns those are actually a breakout board for a module called HC05 which is soldered to the pin, the module is this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1ik0c1ump54nfes89dd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1ik0c1ump54nfes89dd.jpg" alt="HC05" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This module is also a breakout board to only use Serial capabilities&lt;/p&gt;

&lt;p&gt;The pinout for the module is this: &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl58sonfpjx91fg69p9ex.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl58sonfpjx91fg69p9ex.png" alt="HC05 Pinout" width="254" height="319"&gt;&lt;/a&gt; &lt;a href="https://components101.com/sites/default/files/component_datasheet/HC-05%20Datasheet.pdf" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So contain a lot of pins that are not used in any board&lt;/p&gt;

&lt;p&gt;The HC05 is a Bluetooth module that supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Master / Slave Mode&lt;/li&gt;
&lt;li&gt;AT Commands&lt;/li&gt;
&lt;li&gt;Serial data transmission&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the module is a bit similar to the &lt;a href="https://dev.to/danielmx/example-code-for-ch9143-13e5"&gt;CH9143&lt;/a&gt; except:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CH9143 is a BLE device and HC05 only supports Bluetooth pairing&lt;/li&gt;
&lt;li&gt;Master mode can pair to any other device&lt;/li&gt;
&lt;li&gt;There is no USB support on HC05, only Serial&lt;/li&gt;
&lt;li&gt;You can set name of the device (among other things)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Connect to module
&lt;/h2&gt;

&lt;p&gt;There is a lot of examples using Arduino to send Serial data, but in this case will be directly connected to computer with python.&lt;/p&gt;

&lt;p&gt;So to connect to computer the XBee Explorer seems like a good solution, this contains an USB to Serial solution. The main issue is to enter into AT Commands you need to set AD0 / Key / BTN pin to VCC, otherwise the module will be in pairing and only sending / receiving data but can't configure.&lt;/p&gt;

&lt;p&gt;So a solution is to use a USB to Serial module and a breakout board (to convert 2mm pins from xbee to standard 2.5mm, an alternative could be to solder into the pin of the XBee Explorer), so the connection is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3.3v -&amp;gt; VCC (PIN 1)&lt;/li&gt;
&lt;li&gt;RX -&amp;gt; Dout (PIN 2)&lt;/li&gt;
&lt;li&gt;TX -&amp;gt; Din (PIN 3)&lt;/li&gt;
&lt;li&gt;GND -&amp;gt; Dout (PIN 10)&lt;/li&gt;
&lt;li&gt;RTS -&amp;gt; AD0/Key/BTN (PIN 20)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F72smq2glg38j23pbwbe6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F72smq2glg38j23pbwbe6.jpg" alt="Xbee Breakout Board" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The RTS is needed to enter into AT Mode, the serial code will send this signal to enter and leave after paired with other device.&lt;/p&gt;

&lt;p&gt;To test you could use the app &lt;a href="https://play.google.com/store/apps/details?id=de.kai_morich.serial_bluetooth_terminal&amp;amp;gl=US" rel="noopener noreferrer"&gt;Serial Bluetooth Terminal&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can run with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python3 ch05.py /dev/ttyACM1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output will show some info about the device and wait until you pair the device in the app&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Opening port:  /dev/ttyACM1
Entering into AT mode
Sending AT... (checking if AT is enabled)
Response:  ['ERROR:(0)']
AT+VERSION? ['+VERSION:2.0-20100601', 'OK']
device MAC XX:XX:XX:XX:XX:XX
AT+NAME?: [device name] H-C-2010-06-01
AT+ROLE?: [role, 0=Slave, 1=Master] ['+ROLE:0', 'OK']
AT+ADCN?:  ['+ADCN:7', 'OK']
AT+MRAD? [connected device mac]:  XX:XX:XX:XX:XX:XX
Pair to the device: H-C-2010-06-01 with password 1234
Waiting until is paired
Sending and receiving messages, press CTRL+C to stop
Creating background receiving thread
Sending ping 0
Sending ping 1
Sending ping 2
Sending ping 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To pair in device, in the app select the three dots, then &lt;code&gt;Devices&lt;/code&gt; and later the &lt;code&gt;H-C-2010-06-01&lt;/code&gt; (note that name can be different like &lt;code&gt;HC05&lt;/code&gt; or similar but that will show in the console)&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi5ho2murqre7v7tu7ypp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi5ho2murqre7v7tu7ypp.jpg" alt="Devices Menu" width="800" height="1587"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3av6self64sla98mce73.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3av6self64sla98mce73.jpg" alt="List of Devices" width="800" height="1588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And on device will show the ping&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2satdhjgzyvy8xxhpms.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2satdhjgzyvy8xxhpms.jpg" alt="Android Bluetooth Serial Terminal" width="800" height="1587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;serial&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;argparse&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;

&lt;span class="n"&gt;keep_reading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read_serial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;keep_reading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;in_waiting&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;waiting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;in_waiting&lt;/span&gt;
            &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;waiting&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Serial Input: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_at_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="c1"&gt;# send command
&lt;/span&gt;    &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ascii&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c1"&gt;# read command back
&lt;/span&gt;    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ascii&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OK&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ERROR&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;clean_mac_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# first part is always from response
&lt;/span&gt;    &lt;span class="n"&gt;mac&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
    &lt;span class="c1"&gt;# make a single string
&lt;/span&gt;    &lt;span class="n"&gt;mac&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# split into groups of 2 values
&lt;/span&gt;    &lt;span class="n"&gt;mac&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argparse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ArgumentParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prog&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HC05 Uart Example&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;serial_port&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Serial port like /dev/ttyACM0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse_args&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serial_port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;baudrate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;38400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bytesize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EIGHTBITS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;parity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PARITY_NONE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stopbits&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STOPBITS_ONE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timeout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Opening port: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serial_port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Entering into AT mode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# this will set RTS=3.3v 
&lt;/span&gt;    &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sending AT... (checking if AT is enabled)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Response: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;send_at_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AT...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AT+VERSION?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;send_at_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AT+VERSION?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;mac&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;send_at_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AT+ADDR?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ERROR&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;device MAC&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;clean_mac_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;device_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;send_at_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AT+NAME?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;+NAME:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AT+NAME?: [device name]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;device_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AT+ROLE?: [role, 0=Slave, 1=Master]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;send_at_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AT+ROLE?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AT+ADCN?: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;send_at_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AT+ADCN?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;mac&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;send_at_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AT+MRAD?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ERROR&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AT+MRAD? [connected device mac]: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;clean_mac_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# wait until is paired
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pair to the device: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;device_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; with password 1234&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Waiting until is paired&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;send_at_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AT+STATE?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OK&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;+STATE:PAIRED&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;+STATE:CONNECTED&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="c1"&gt;# disable AT mode
&lt;/span&gt;    &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

    &lt;span class="c1"&gt;# send and receive data
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sending and receiving messages, press CTRL+C to stop&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Creating background receiving thread&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;thread_read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;read_serial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;,))&lt;/span&gt;
    &lt;span class="n"&gt;thread_read&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;send_idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sending ping &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;send_idx&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;UART PING &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;send_idx&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ascii&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;send_idx&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;
    &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Finishing reading thread&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;keep_reading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
        &lt;span class="n"&gt;thread_read&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will need &lt;a href="https://pyserial.readthedocs.io/en/latest/pyserial_api.html" rel="noopener noreferrer"&gt;&lt;code&gt;pyserial&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install pyserial
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final Notes
&lt;/h2&gt;

&lt;p&gt;There are more commands in AT mode, here is a simple list of all: &lt;a href="https://s3-sa-east-1.amazonaws.com/robocore-lojavirtual/709/HC-05_ATCommandSet.pdf" rel="noopener noreferrer"&gt;https://s3-sa-east-1.amazonaws.com/robocore-lojavirtual/709/HC-05_ATCommandSet.pdf&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The HC05 module is actually a MCU &lt;a href="https://cdn.sparkfun.com/datasheets/Wireless/Bluetooth/CSR-BC417-datasheet.pdf" rel="noopener noreferrer"&gt;BC417&lt;/a&gt; with a flash memory with the firmware.&lt;br&gt;
The MCU seems very capable of different things, including sending audio and controlling several GPIO and SPI, but there is no documentation about how to program it.&lt;/p&gt;

</description>
      <category>bluetooth</category>
    </item>
    <item>
      <title>Starting With Luckfox Lyra Zero W</title>
      <dc:creator>Daniel Guerrero</dc:creator>
      <pubDate>Sat, 04 Oct 2025 21:43:55 +0000</pubDate>
      <link>https://dev.to/danielmx/starting-with-lucfox-lyra-zero-w-9ko</link>
      <guid>https://dev.to/danielmx/starting-with-lucfox-lyra-zero-w-9ko</guid>
      <description>&lt;p&gt;The &lt;a href="https://www.luckfox.com/Luckfox-Lyra-Zero-W" rel="noopener noreferrer"&gt;Luckfox Lyra Zero W&lt;/a&gt; is a Development Board with RK3506B Chip, Triple-core Arm Cortex-A7 and Arm Cortex-M0 Processors.&lt;/p&gt;

&lt;p&gt;The Ubuntu image is here:&lt;br&gt;
&lt;a href="https://github.com/platima/SBC-Images/tree/main/Luckfox/Lyra/Lyra%20Zero%20W" rel="noopener noreferrer"&gt;https://github.com/platima/SBC-Images/tree/main/Luckfox/Lyra/Lyra%20Zero%20W&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The main issue with image is there no extra disk space so you can't do any resize operation in the same device.&lt;/p&gt;

&lt;p&gt;So the options are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resize the &lt;code&gt;img&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;Resize the SD partition&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For both operations you'll need a Linux machine to run the commands&lt;/p&gt;
&lt;h2&gt;
  
  
  Resize the &lt;code&gt;img&lt;/code&gt; file
&lt;/h2&gt;

&lt;p&gt;When you have the &lt;code&gt;img&lt;/code&gt; file after bunzip it, run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# grow the image by 7GB so final will be 8GB, change to proper SD size
dd if=/dev/zero bs=1G count=7 \
  oflag=append conv=notrunc \
  of=Luckfox_Lyra_Zero_W-2503_Ubuntu.img

sudo losetup --find --partscan \
  Luckfox_Lyra_Zero_W-2503_Ubuntu.img

# check with lsblk which loop device 
# (there will be 3 partitions)
# in my case the device is /dev/loop2
lsblk

# data is partition 3 so check for failed sectors
sudo e2fsck -y /dev/loop2p3

# grow partition
sudo growpart -v /dev/loop2 3

# resize ext4 partition
sudo resize2fs /dev/loop2p3

# unmount loop file
sudo losetup --detach /dev/loop2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new size of the &lt;code&gt;img&lt;/code&gt; file will be of 8GB after this so the root will have now 7GB of free space, this is simpler as you don't need to mount the SD card, but the problem is that you will get unused space in the card.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resize the SD card
&lt;/h2&gt;

&lt;p&gt;Once you write the img to SD using a tool like Balena Etcher or Rufus, you need to do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# check the device used
lsblk

# in my case is /dev/sdd

# if is automatically mounted, unmount it
sudo umount /dev/sdd3

# data is partition 3 so check for failed sectors
sudo e2fsck -y -f /dev/sdd3

# grow partition
sudo growpart -v /dev/sdd 3

# resize ext4 partition
sudo resize2fs /dev/sdd3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Connect through USB
&lt;/h2&gt;

&lt;p&gt;To connect to device, &lt;a href="https://developer.android.com/tools/releases/platform-tools" rel="noopener noreferrer"&gt;ADB tools&lt;/a&gt; can be used&lt;/p&gt;

&lt;p&gt;Run adb to list devices&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;adb devices -l
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a device is present, then connect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;adb shell
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  WiFi setup
&lt;/h2&gt;

&lt;p&gt;You need to provide the details of your network, for this edit the &lt;code&gt;/etc/wpa_supplicant.conf&lt;/code&gt;&lt;br&gt;
The original contents will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ctrl_interface=/var/run/wpa_supplicant
ap_scan=1
update_config=1

network={
        ssid="SSID"
        psk="PASSWORD"
        key_mgmt=WPA-PSK
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change the &lt;code&gt;SSID&lt;/code&gt; and &lt;code&gt;PASSWORD&lt;/code&gt; for the details of your WiFi network.&lt;br&gt;
After that create a file &lt;code&gt;/etc/network/interfaces.d/wlan0&lt;/code&gt;&lt;br&gt;
And there are two options: &lt;strong&gt;dhcp&lt;/strong&gt; (most common) or &lt;strong&gt;static ip&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  WiFi DHCP
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;auto wlan0
iface wlan0 inet dhcp
    wpa-conf /etc/wpa_supplicant.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  WiFi Static IP
&lt;/h3&gt;

&lt;p&gt;Change address, gateway and other params to your proper settings&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;auto wlan0
iface wlan0 inet static
    wpa-conf /etc/wpa_supplicant.conf
    address 192.168.2.100
    netmask 255.255.255.0
    gateway 192.168.2.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is an issue with &lt;code&gt;resolv.conf&lt;/code&gt; that image set to a docker nameserver, so needs to be replaced:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "nameserver 1.1.1.1 8.8.8.8" &amp;gt; /etc/resolv.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply the config with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl restart networking
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>tutorial</category>
      <category>cli</category>
      <category>linux</category>
      <category>iot</category>
    </item>
    <item>
      <title>Example using ST TOF VL53L4CD</title>
      <dc:creator>Daniel Guerrero</dc:creator>
      <pubDate>Sun, 21 Sep 2025 06:24:02 +0000</pubDate>
      <link>https://dev.to/danielmx/example-using-st-tof-vl53l4cd-160m</link>
      <guid>https://dev.to/danielmx/example-using-st-tof-vl53l4cd-160m</guid>
      <description>&lt;p&gt;The &lt;a href="https://www.st.com/en/imaging-and-photonics-solutions/vl53l4cd.html" rel="noopener noreferrer"&gt;VL53L4CD&lt;/a&gt; is a TOF (Time of Flight) sensor capable of measure distances from 1mm to 1200mm.&lt;/p&gt;

&lt;p&gt;Unfortunately the datasheet doesn't provide any register information. But they &lt;a href="https://www.st.com/resource/en/user_manual/um2931-a-guide-to-using-the-vl53l4cd-ultra-lite-driver-uld-stmicroelectronics.pdf" rel="noopener noreferrer"&gt;provide an API&lt;/a&gt; but no good documentation about api functions.&lt;/p&gt;

&lt;p&gt;The STM32Cube have a package for this: &lt;a href="https://www.st.com/en/embedded-software/x-cube-tof1.html" rel="noopener noreferrer"&gt;X-CUBE-TOF1&lt;/a&gt; there are several applications but all uses a lot of abstractions to handle all the devices, so my goal was to have a very simple example for this specific board based on that.&lt;/p&gt;

&lt;p&gt;To setup the project, you need to do:&lt;br&gt;
&lt;strong&gt;Enable I2C1&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7e6yi5lfeuh1mfrjtr3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7e6yi5lfeuh1mfrjtr3.png" alt="Enable I2C1" width="786" height="685"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enable X-CUBE-TOF1 in the Middleware &amp;amp; Software section&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk7hg5o1vw0mr7mug4im8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk7hg5o1vw0mr7mug4im8.png" alt="Enable X-CUBE-TOF1" width="266" height="682"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Select Board Part Ranging, and select VL53L4CD&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2aodw3xainuxa9wb5w6p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2aodw3xainuxa9wb5w6p.png" alt="Select Board Part Ranging" width="572" height="858"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configure to use the I2C1 and XShut pin&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhealu13p8g9b4rifcea9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhealu13p8g9b4rifcea9.png" alt="Configure Package" width="800" height="805"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will create a project that will contain one file called &lt;code&gt;custom_tof_conf.h&lt;/code&gt; which contains some defines, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#define USE_CUSTOM_RANGING_VL53L4CD (1U)

#define CUSTOM_VL53L4CD_XSHUT_PORT    GPIOA
#define CUSTOM_VL53L4CD_XSHUT_PIN     GPIO_PIN_1

#define CUSTOM_VL53L4CD_I2C_INIT      BSP_I2C1_Init
#define CUSTOM_VL53L4CD_I2C_DEINIT    BSP_I2C1_DeInit
#define CUSTOM_VL53L4CD_I2C_WRITEREG  BSP_I2C1_Send
#define CUSTOM_VL53L4CD_I2C_READREG   BSP_I2C1_Recv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need to create a file to use the API, I've created two files: &lt;code&gt;tof.c&lt;/code&gt; and &lt;code&gt;tof.h&lt;/code&gt;&lt;br&gt;
The code is very simple it will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Init the device (check device is reachable through I2C and get capabilities)&lt;/li&gt;
&lt;li&gt;Configure the device (set device settings and set the measure as continuous)&lt;/li&gt;
&lt;li&gt;Get the distance&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Is important to note that the XShut pin in the TOF is an enable pin and the API is toggling automatically, so for this example the XShut is connected to VCC (3.3v) to be always enabled, if you have multiple I2C devices, you will need to enable / disable using the &lt;code&gt;CUSTOM_VL53L4CD_XSHUT_PORT&lt;/code&gt; and &lt;code&gt;CUSTOM_VL53L4CD_XSHUT_PIN&lt;/code&gt; before any API call (or add in the &lt;code&gt;tof.c&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;UM2931&lt;/strong&gt; contains more information about how to connect each pin in TOF board and dev board.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;tof.c&lt;/code&gt; code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"tof.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"custom_tof_conf.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="n"&gt;VL53L4CD_Object_t&lt;/span&gt;   &lt;span class="n"&gt;tof_obj&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;VL53L4CD_Capabilities_t&lt;/span&gt; &lt;span class="n"&gt;tof_cap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;VL53L4CD_ProfileConfig_t&lt;/span&gt; &lt;span class="n"&gt;tof_profile&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="nf"&gt;decimal_part&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;float_t&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;int_part&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)((&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;int_part&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VL53L4CD_Result_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;NumberOfZones&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Targets = %lu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ZoneResult&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;NumberOfTargets&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ZoneResult&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;NumberOfTargets&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt; |---&amp;gt; "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Status = %ld, Distance = %5ld mm "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ZoneResult&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ZoneResult&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Distance&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tof_profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnableAmbient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;", Ambient = %ld.%02ld kcps/spad"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ZoneResult&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Ambient&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;decimal_part&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ZoneResult&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Ambient&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tof_profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnableSignal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;", Signal = %ld.%02ld kcps/spad"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ZoneResult&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;decimal_part&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ZoneResult&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="nf"&gt;TOF_Init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;VL53L4CD_IO_t&lt;/span&gt;              &lt;span class="n"&gt;IOCtx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;uint32_t&lt;/span&gt;                   &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/* Configure the ranging sensor driver */&lt;/span&gt;
    &lt;span class="n"&gt;IOCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_DEVICE_ADDRESS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;IOCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Init&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CUSTOM_VL53L4CD_I2C_INIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;IOCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DeInit&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CUSTOM_VL53L4CD_I2C_DEINIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;IOCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteReg&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CUSTOM_VL53L4CD_I2C_WRITEREG&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;IOCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadReg&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CUSTOM_VL53L4CD_I2C_READREG&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;IOCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetTick&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BSP_GetTick&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VL53L4CD_RegisterBusIO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tof_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;IOCtx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_OK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cannot register bus&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BSP_ERROR_COMPONENT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_ReadID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tof_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cannot read ID %ld&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BSP_ERROR_COMPONENT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_ID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Wrong ID %ld&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BSP_ERROR_UNKNOWN_COMPONENT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Got device id: %ld&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;//init device&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VL53L4CD_Init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tof_obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_OK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cannot init tof&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BSP_ERROR_COMPONENT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VL53L4CD_GetCapabilities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tof_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tof_cap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_OK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cannot get capabilities&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BSP_ERROR_COMPONENT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TOF Initialized&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BSP_ERROR_NONE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="nf"&gt;TOF_Configure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tof_profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RangingProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_PROFILE_CONTINUOUS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;tof_profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TimingBudget&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;tof_profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Frequency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* Induces intermeasurement period, NOT USED for normal ranging */&lt;/span&gt;
    &lt;span class="n"&gt;tof_profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnableAmbient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* Enable: 1, Disable: 0 */&lt;/span&gt;
    &lt;span class="n"&gt;tof_profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnableSignal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* Enable: 1, Disable: 0 */&lt;/span&gt;

    &lt;span class="cm"&gt;/* set the profile if different from default one */&lt;/span&gt;
    &lt;span class="n"&gt;VL53L4CD_ConfigProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tof_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tof_profile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_Start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tof_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_MODE_BLOCKING_CONTINUOUS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="nf"&gt;TOF_GetDistance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VL53L4CD_Result_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_GetDistance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tof_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;BSP_ERROR_NONE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;print_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to get measure: %ld&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;tof.h&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;
&lt;span class="cp"&gt;#ifndef INC_TOF_H_
#define INC_TOF_H_
&lt;/span&gt;
&lt;span class="cp"&gt;#ifdef __cplusplus
&lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="cp"&gt;#endif
&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"vl53l4cd.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;TOF_Init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;TOF_Configure&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;TOF_GetDistance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VL53L4CD_Result_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cp"&gt;#ifdef __cplusplus
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;#endif
#endif &lt;/span&gt;&lt;span class="cm"&gt;/* INC_TOF_H_ */&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The use is very simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"tof.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/* USER CODE BEGIN 2 */&lt;/span&gt;
  &lt;span class="c1"&gt;// init TOF device&lt;/span&gt;
  &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;tof_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TOF_Init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tof_status&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to init TOF: %ld&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tof_status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;TOF_Configure&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="cm"&gt;/* USER CODE END 2 */&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;

  &lt;span class="cm"&gt;/* USER CODE BEGIN WHILE */&lt;/span&gt;
  &lt;span class="n"&gt;VL53L4CD_Result_t&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="cm"&gt;/* USER CODE END WHILE */&lt;/span&gt;

      &lt;span class="cm"&gt;/* USER CODE BEGIN 3 */&lt;/span&gt;
      &lt;span class="n"&gt;TOF_GetDistance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;HAL_Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="cm"&gt;/* USER CODE END 3 */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will initialize the device and configure it.&lt;br&gt;
After that it will get the distance, the &lt;code&gt;tof.c&lt;/code&gt; will by default print the results like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Targets = 1
 |---&amp;gt; Status = 0, Distance =   110 mm , Ambient = 0.00 kcps/spad, Signal = 112.00 kcps/spad
Targets = 1
 |---&amp;gt; Status = 0, Distance =   112 mm , Ambient = 0.00 kcps/spad, Signal = 113.00 kcps/spad
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But can be changed to not print it.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Example using ST TOF VL53L4CD</title>
      <dc:creator>Daniel Guerrero</dc:creator>
      <pubDate>Sun, 21 Sep 2025 06:24:02 +0000</pubDate>
      <link>https://dev.to/danielmx/example-using-st-tof-vl53l4cd-5ch3</link>
      <guid>https://dev.to/danielmx/example-using-st-tof-vl53l4cd-5ch3</guid>
      <description>&lt;p&gt;The &lt;a href="https://www.st.com/en/imaging-and-photonics-solutions/vl53l4cd.html" rel="noopener noreferrer"&gt;VL53L4CD&lt;/a&gt; is a TOF (Time of Flight) sensor capable of measure distances from 1mm to 1200mm.&lt;/p&gt;

&lt;p&gt;Unfortunately the datasheet doesn't provide any register information. But they &lt;a href="https://www.st.com/resource/en/user_manual/um2931-a-guide-to-using-the-vl53l4cd-ultra-lite-driver-uld-stmicroelectronics.pdf" rel="noopener noreferrer"&gt;provide an API&lt;/a&gt; but no good documentation about api functions.&lt;/p&gt;

&lt;p&gt;The STM32Cube have a package for this: &lt;a href="https://www.st.com/en/embedded-software/x-cube-tof1.html" rel="noopener noreferrer"&gt;X-CUBE-TOF1&lt;/a&gt; there are several applications but all uses a lot of abstractions to handle all the devices, so my goal was to have a very simple example for this specific board based on that.&lt;/p&gt;

&lt;p&gt;To setup the project, you need to do:&lt;br&gt;
&lt;strong&gt;Enable I2C1&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7e6yi5lfeuh1mfrjtr3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7e6yi5lfeuh1mfrjtr3.png" alt="Enable I2C1" width="786" height="685"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enable X-CUBE-TOF1 in the Middleware &amp;amp; Software section&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk7hg5o1vw0mr7mug4im8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk7hg5o1vw0mr7mug4im8.png" alt="Enable X-CUBE-TOF1" width="266" height="682"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Select Board Part Ranging, and select VL53L4CD&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2aodw3xainuxa9wb5w6p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2aodw3xainuxa9wb5w6p.png" alt="Select Board Part Ranging" width="572" height="858"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configure to use the I2C1 and XShut pin&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhealu13p8g9b4rifcea9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhealu13p8g9b4rifcea9.png" alt="Configure Package" width="800" height="805"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will create a project that will contain one file called &lt;code&gt;custom_tof_conf.h&lt;/code&gt; which contains some defines, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#define USE_CUSTOM_RANGING_VL53L4CD (1U)

#define CUSTOM_VL53L4CD_XSHUT_PORT    GPIOA
#define CUSTOM_VL53L4CD_XSHUT_PIN     GPIO_PIN_1

#define CUSTOM_VL53L4CD_I2C_INIT      BSP_I2C1_Init
#define CUSTOM_VL53L4CD_I2C_DEINIT    BSP_I2C1_DeInit
#define CUSTOM_VL53L4CD_I2C_WRITEREG  BSP_I2C1_Send
#define CUSTOM_VL53L4CD_I2C_READREG   BSP_I2C1_Recv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need to create a file to use the API, I've created two files: &lt;code&gt;tof.c&lt;/code&gt; and &lt;code&gt;tof.h&lt;/code&gt;&lt;br&gt;
The code is very simple it will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Init the device (check device is reachable through I2C and get capabilities)&lt;/li&gt;
&lt;li&gt;Configure the device (set device settings and set the measure as continuous)&lt;/li&gt;
&lt;li&gt;Get the distance&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Is important to note that the XShut pin in the TOF is an enable pin and the API is toggling automatically, so for this example the XShut is connected to VCC (3.3v) to be always enabled, if you have multiple I2C devices, you will need to enable / disable using the &lt;code&gt;CUSTOM_VL53L4CD_XSHUT_PORT&lt;/code&gt; and &lt;code&gt;CUSTOM_VL53L4CD_XSHUT_PIN&lt;/code&gt; before any API call (or add in the &lt;code&gt;tof.c&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;UM2931&lt;/strong&gt; contains more information about how to connect each pin in TOF board and dev board.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;tof.c&lt;/code&gt; code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"tof.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"custom_tof_conf.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="n"&gt;VL53L4CD_Object_t&lt;/span&gt;   &lt;span class="n"&gt;tof_obj&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;VL53L4CD_Capabilities_t&lt;/span&gt; &lt;span class="n"&gt;tof_cap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;VL53L4CD_ProfileConfig_t&lt;/span&gt; &lt;span class="n"&gt;tof_profile&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="nf"&gt;decimal_part&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;float_t&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;int_part&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)((&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;int_part&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VL53L4CD_Result_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;NumberOfZones&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Targets = %lu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ZoneResult&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;NumberOfTargets&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ZoneResult&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;NumberOfTargets&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt; |---&amp;gt; "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Status = %ld, Distance = %5ld mm "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ZoneResult&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ZoneResult&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Distance&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tof_profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnableAmbient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;", Ambient = %ld.%02ld kcps/spad"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ZoneResult&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Ambient&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;decimal_part&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ZoneResult&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Ambient&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tof_profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnableSignal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;", Signal = %ld.%02ld kcps/spad"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ZoneResult&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;decimal_part&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ZoneResult&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="nf"&gt;TOF_Init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;VL53L4CD_IO_t&lt;/span&gt;              &lt;span class="n"&gt;IOCtx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;uint32_t&lt;/span&gt;                   &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/* Configure the ranging sensor driver */&lt;/span&gt;
    &lt;span class="n"&gt;IOCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_DEVICE_ADDRESS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;IOCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Init&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CUSTOM_VL53L4CD_I2C_INIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;IOCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DeInit&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CUSTOM_VL53L4CD_I2C_DEINIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;IOCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteReg&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CUSTOM_VL53L4CD_I2C_WRITEREG&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;IOCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadReg&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CUSTOM_VL53L4CD_I2C_READREG&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;IOCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetTick&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BSP_GetTick&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VL53L4CD_RegisterBusIO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tof_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;IOCtx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_OK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cannot register bus&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BSP_ERROR_COMPONENT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_ReadID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tof_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cannot read ID %ld&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BSP_ERROR_COMPONENT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_ID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Wrong ID %ld&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BSP_ERROR_UNKNOWN_COMPONENT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Got device id: %ld&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;//init device&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VL53L4CD_Init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tof_obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_OK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cannot init tof&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BSP_ERROR_COMPONENT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VL53L4CD_GetCapabilities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tof_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tof_cap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_OK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cannot get capabilities&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BSP_ERROR_COMPONENT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TOF Initialized&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BSP_ERROR_NONE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="nf"&gt;TOF_Configure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tof_profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RangingProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_PROFILE_CONTINUOUS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;tof_profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TimingBudget&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;tof_profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Frequency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* Induces intermeasurement period, NOT USED for normal ranging */&lt;/span&gt;
    &lt;span class="n"&gt;tof_profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnableAmbient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* Enable: 1, Disable: 0 */&lt;/span&gt;
    &lt;span class="n"&gt;tof_profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnableSignal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* Enable: 1, Disable: 0 */&lt;/span&gt;

    &lt;span class="cm"&gt;/* set the profile if different from default one */&lt;/span&gt;
    &lt;span class="n"&gt;VL53L4CD_ConfigProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tof_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tof_profile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_Start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tof_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_MODE_BLOCKING_CONTINUOUS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="nf"&gt;TOF_GetDistance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VL53L4CD_Result_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VL53L4CD_GetDistance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tof_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;BSP_ERROR_NONE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;print_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to get measure: %ld&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;tof.h&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;
&lt;span class="cp"&gt;#ifndef INC_TOF_H_
#define INC_TOF_H_
&lt;/span&gt;
&lt;span class="cp"&gt;#ifdef __cplusplus
&lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="cp"&gt;#endif
&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"vl53l4cd.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;TOF_Init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;TOF_Configure&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;TOF_GetDistance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VL53L4CD_Result_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cp"&gt;#ifdef __cplusplus
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;#endif
#endif &lt;/span&gt;&lt;span class="cm"&gt;/* INC_TOF_H_ */&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The use is very simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"tof.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/* USER CODE BEGIN 2 */&lt;/span&gt;
  &lt;span class="c1"&gt;// init TOF device&lt;/span&gt;
  &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;tof_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TOF_Init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tof_status&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to init TOF: %ld&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tof_status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;TOF_Configure&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="cm"&gt;/* USER CODE END 2 */&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;

  &lt;span class="cm"&gt;/* USER CODE BEGIN WHILE */&lt;/span&gt;
  &lt;span class="n"&gt;VL53L4CD_Result_t&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="cm"&gt;/* USER CODE END WHILE */&lt;/span&gt;

      &lt;span class="cm"&gt;/* USER CODE BEGIN 3 */&lt;/span&gt;
      &lt;span class="n"&gt;TOF_GetDistance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;HAL_Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="cm"&gt;/* USER CODE END 3 */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will initialize the device and configure it.&lt;br&gt;
After that it will get the distance, the &lt;code&gt;tof.c&lt;/code&gt; will by default print the results like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Targets = 1
 |---&amp;gt; Status = 0, Distance =   110 mm , Ambient = 0.00 kcps/spad, Signal = 112.00 kcps/spad
Targets = 1
 |---&amp;gt; Status = 0, Distance =   112 mm , Ambient = 0.00 kcps/spad, Signal = 113.00 kcps/spad
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But can be changed to not print it.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
