mirror of
				https://github.com/alexandrebobkov/ESP-Nodes.git
				synced 2025-10-31 18:34:34 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			406 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			406 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <!DOCTYPE html>
 | ||
| 
 | ||
| <html lang="en" data-content_root="./">
 | ||
|   <head>
 | ||
|     <meta charset="utf-8" />
 | ||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
 | ||
| 
 | ||
|     <title>2. HOW DOES IT WORK? — Byte Rider 06-2025 documentation</title>
 | ||
|     <link rel="stylesheet" type="text/css" href="_static/pygments.css?v=5ecbeea2" />
 | ||
|     <link rel="stylesheet" type="text/css" href="_static/basic.css?v=b08954a9" />
 | ||
|     <link rel="stylesheet" type="text/css" href="_static/alabaster.css?v=27fed22d" />
 | ||
|     <script src="_static/documentation_options.js?v=e6ef2064"></script>
 | ||
|     <script src="_static/doctools.js?v=9bcbadda"></script>
 | ||
|     <script src="_static/sphinx_highlight.js?v=dc90522c"></script>
 | ||
|     <link rel="index" title="Index" href="genindex.html" />
 | ||
|     <link rel="search" title="Search" href="search.html" />
 | ||
|     <link rel="next" title="3. DATA STRUCTS" href="data.html" />
 | ||
|     <link rel="prev" title="1. OVERVIEW" href="intro.html" />
 | ||
|    
 | ||
|   <link rel="stylesheet" href="_static/custom.css" type="text/css" />
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|   
 | ||
| 
 | ||
|   </head><body>
 | ||
|   
 | ||
| 
 | ||
|     <div class="document">
 | ||
|       <div class="documentwrapper">
 | ||
|         <div class="bodywrapper">
 | ||
|           
 | ||
| 
 | ||
|           <div class="body" role="main">
 | ||
|             
 | ||
|   <section id="how-does-it-work">
 | ||
| <h1><span class="section-number">2. </span>HOW DOES IT WORK?<a class="headerlink" href="#how-does-it-work" title="Link to this heading">¶</a></h1>
 | ||
| <p>The bitByteRider RC car is powered by ESP32-C3 bitBoard. The Schematic and KiCAd PCB board files are available
 | ||
| on <a class="reference external" href="https://github.com/alexandrebobkov/ESP32-C3_Breadboard-Adapter">GitHub</a>: <a class="reference external" href="https://github.com/alexandrebobkov/ESP32-C3_Breadboard-Adapter">https://github.com/alexandrebobkov/ESP32-C3_Breadboard-Adapter</a></p>
 | ||
| <p>The bitByteRider RC car operates using two main units: the <em>transmitter</em>, which reads and sends the joystick’s X and Y values, and
 | ||
| the <em>receiver</em>, which interprets these values and converts them into PWM signals to control the DC motors. Both units communicate
 | ||
| via <strong>ESP-NOW</strong>, a low-latency, connectionless wireless protocol that requires no Wi-Fi network or pairing.</p>
 | ||
| <p>In addition to enabling real-time control, using ESP-NOW introduces key networking concepts such as <strong>data encapsulation</strong> and
 | ||
| structured communication. By using data structures to group control variables, you gain hands-on experience with how information
 | ||
| is packaged and transmitted, laying the groundwork for understanding the fundamentals of network communication in embedded systems.</p>
 | ||
| <p>The joystick used in the bitByteRider RC car remote unit outputs analog voltages ranging from 0V to 3.3V on both the x- and y-axes,
 | ||
| depending on the position of the joystick. These voltage levels are read by the ESP32-C3’s ADC (Analog-to-Digital Converter) inputs.</p>
 | ||
| <p>When the joystick is in its neutral (centred) position, the ADC inputs on the ESP32-C3 receive approximately 1.65V on both axes.
 | ||
| This midpoint voltage is interpreted and interpolated into a PWM (Pulse Width Modulation) value of 0, indicating no movement or
 | ||
| motor activity.</p>
 | ||
| <p>As the joystick is pushed to its maximum positions along the x- and y-axis, the voltage increases up to 3.3V. This maximum voltage
 | ||
| is interpolated to a PWM value of 1024, which corresponds to a 100% duty cycle on the receiver side, resulting in full-speed
 | ||
| operation of the DC motors.</p>
 | ||
| <p>To transmit control data, the X and Y axis values are encapsulated in a C struct, along with the receiver’s <strong>MAC</strong> address, and sent
 | ||
| wirelessly using ESP-NOW. This protocol enables low-latency, connectionless communication between the transmitter and receiver
 | ||
| without requiring a Wi-Fi network or pairing.</p>
 | ||
| <p>Upon reception, the RC car’s receiver decapsulates the data, extracts the joystick values, and interpolates them into PWM
 | ||
| signals. These signals are then used to control the rotation speeds of the DC motors, enabling smooth and responsive remote control.</p>
 | ||
| <p>This process not only facilitates real-time control but also introduces you to key networking concepts such as data
 | ||
| encapsulation, data structs, and the fundamentals of wireless data transmission in embedded systems.</p>
 | ||
| <div class="admonition-what-is-encapsulation admonition">
 | ||
| <p class="admonition-title">What is encapsulation?</p>
 | ||
| <p>Encapsulation refers to the process of organizing and packaging data into a structured format before it is transmitted between
 | ||
| devices. This is a fundamental concept in networking and communication protocols, including those used in IoT systems.</p>
 | ||
| </div>
 | ||
| <section id="reserved-pins-gpios">
 | ||
| <h2><span class="section-number">2.1. </span>Reserved Pins & GPIOs<a class="headerlink" href="#reserved-pins-gpios" title="Link to this heading">¶</a></h2>
 | ||
| <p>The following table summarizes GPIOs and pins reserved for operations purposes.</p>
 | ||
| <p>The GPIO numbers correspond to those on the ESP32-C3 WROOM microcontroller. The Pin number corresponds to the pin on the Breadboard and Power adapter development board.</p>
 | ||
| <section id="reading-the-joystick-x-and-y-axis">
 | ||
| <h3><span class="section-number">2.1.1. </span>Reading the Joystick x- and y- axis<a class="headerlink" href="#reading-the-joystick-x-and-y-axis" title="Link to this heading">¶</a></h3>
 | ||
| <p>To determine the position of the Joystick, the BitRider RC car uses ADC to measure voltage on two GPIOs connected to the joystick
 | ||
| x- and y- axis potentionometers (<strong>GPIO0</strong> and <strong>GPIO1</strong>).</p>
 | ||
| </section>
 | ||
| <section id="controlling-the-direction-and-speed">
 | ||
| <h3><span class="section-number">2.1.2. </span>Controlling the Direction and Speed<a class="headerlink" href="#controlling-the-direction-and-speed" title="Link to this heading">¶</a></h3>
 | ||
| <p>To set any desired speed of BiteRider RC car, the <em>ESP32-C3 Breadboard Adapter DevBoard</em> uses PWM to control the rotation speed
 | ||
| of DR motors. Similarly, to set the direction of the RC car, the rotation speed of corresponding DC motors is changed as required.</p>
 | ||
| <p>Due to the design and limited number of available GPIOs, the <em>ESP32-C3 Breadboard DevBoard</em> can control rotation speed and direction
 | ||
| of DC motors in pairs only (i.e. left and right side). Consequently, this means that the four PWM channels used for controlling the
 | ||
| direction of the RC car.</p>
 | ||
| <p>Based on this constraint, the RC car can only move front, back, and turn/rotate left and right. Any other movements are not
 | ||
| possible (i.e. diagonal or sideways).</p>
 | ||
| <table class="docutils align-default">
 | ||
| <tbody>
 | ||
| <tr class="row-odd"><td><p>PWM of DC Motors</p></td>
 | ||
| <td><p>Direction</p></td>
 | ||
| </tr>
 | ||
| <tr class="row-even"><td><p>PWM(left) = PWM(right)</p></td>
 | ||
| <td><p>Straight</p></td>
 | ||
| </tr>
 | ||
| <tr class="row-odd"><td><p>PWM(left) > PWM(right)</p></td>
 | ||
| <td><p>Left</p></td>
 | ||
| </tr>
 | ||
| <tr class="row-even"><td><p>PWM(left) < PWM(right)</p></td>
 | ||
| <td><p>Right</p></td>
 | ||
| </tr>
 | ||
| </tbody>
 | ||
| </table>
 | ||
| <div class="admonition-what-is-pwm admonition">
 | ||
| <p class="admonition-title">What is PWM?</p>
 | ||
| <p><strong>PWM</strong> stands for Pulse Width Modulation. It is a technique used to simulate analog voltage levels using discrete digital signals. It works by
 | ||
| rapidly switching a digital GPIO pin between HIGH (on) and LOW (off) states at a fixed frequency (often, at base frequency of 5 kHz).
 | ||
| The duty cycle—the percentage of time the signal is HIGH in one cycle determines the effective voltage delivered to a device.
 | ||
| A higher duty cycle increases the motor speed, and a lower duty cycle decreases the motor speed. This allows for fine-grained speed control
 | ||
| without needing analog voltage regulators.</p>
 | ||
| </div>
 | ||
| <p>A pair of PWM channels are used per DC motor for defining their rotation speed and direction on each side.
 | ||
| In particular, <strong>GPIO6</strong> and <strong>GPIO5</strong> provide PWM to the left- and right- side DC motors to rotate in a <strong>clockwise</strong> direction.
 | ||
| Similarly, <strong>GPIO4</strong> and <strong>GPIO7</strong> provide PWM to the left- and right- side DC motors to rotate in a <strong>counter-clockwise</strong> direction.
 | ||
| Changing PWM on each channel determines the speed and direction of the RC car.</p>
 | ||
| <p>The table below summarizes the GPIO pins used for PWM to control the direction of the DC motors in the remote-controlled car.</p>
 | ||
| <table class="docutils align-default">
 | ||
| <thead>
 | ||
| <tr class="row-odd"><th class="head"><p>GPIOs</p></th>
 | ||
| <th class="head"><p>State</p></th>
 | ||
| <th class="head"><p>Description</p></th>
 | ||
| <th class="head"><p>Function</p></th>
 | ||
| </tr>
 | ||
| </thead>
 | ||
| <tbody>
 | ||
| <tr class="row-even"><td><p>GPIO6,
 | ||
| GPIO4</p></td>
 | ||
| <td><p>PWM</p></td>
 | ||
| <td><p>Left & Right DC Motors spin
 | ||
| clockwise</p></td>
 | ||
| <td><p>Forward</p></td>
 | ||
| </tr>
 | ||
| <tr class="row-odd"><td><p>GPIO5,
 | ||
| GPIO7</p></td>
 | ||
| <td><p>PWM</p></td>
 | ||
| <td><p>Left & Right DC Motors spin
 | ||
| counterclockwise</p></td>
 | ||
| <td><p>Reverse</p></td>
 | ||
| </tr>
 | ||
| <tr class="row-even"><td><p>GPIO6,
 | ||
| GPIO7</p></td>
 | ||
| <td><p>PWM</p></td>
 | ||
| <td><p>Left DC Motors spin clockwise.
 | ||
| Right DC Motors spin counterclockwise</p></td>
 | ||
| <td><p>Left</p></td>
 | ||
| </tr>
 | ||
| <tr class="row-odd"><td><p>GPIO4,
 | ||
| GPIO5</p></td>
 | ||
| <td><p>PWM</p></td>
 | ||
| <td><p>Left DC Motors spin counterclockwise.
 | ||
| Right DC Motors spin clockwise</p></td>
 | ||
| <td><p>Right</p></td>
 | ||
| </tr>
 | ||
| </tbody>
 | ||
| </table>
 | ||
| <p>The following images illustrate various PWM duty cycles registered by oscilloscope (duty cycles 0%, 48% and 91%, resp.).</p>
 | ||
| <figure class="align-default" id="id1">
 | ||
| <img alt="_images/ESP-IDF_Robot_PWM_Duty-0.bmp" src="_images/ESP-IDF_Robot_PWM_Duty-0.bmp" />
 | ||
| <figcaption>
 | ||
| <p><span class="caption-text">DC Motor PWM duty cycle 0%</span><a class="headerlink" href="#id1" title="Link to this image">¶</a></p>
 | ||
| </figcaption>
 | ||
| </figure>
 | ||
| <figure class="align-default" id="id2">
 | ||
| <img alt="_images/ESP-IDF_Robot_PWM_Duty-50.bmp" src="_images/ESP-IDF_Robot_PWM_Duty-50.bmp" />
 | ||
| <figcaption>
 | ||
| <p><span class="caption-text">DC Motor PWM duty cycle 47.6%</span><a class="headerlink" href="#id2" title="Link to this image">¶</a></p>
 | ||
| </figcaption>
 | ||
| </figure>
 | ||
| <figure class="align-default" id="id3">
 | ||
| <img alt="_images/ESP-IDF_Robot_PWM_Duty-95.bmp" src="_images/ESP-IDF_Robot_PWM_Duty-95.bmp" />
 | ||
| <figcaption>
 | ||
| <p><span class="caption-text">DC Motor PWM duty cycle 90.8%</span><a class="headerlink" href="#id3" title="Link to this image">¶</a></p>
 | ||
| </figcaption>
 | ||
| </figure>
 | ||
| <br/><br/><br/><br/></section>
 | ||
| </section>
 | ||
| <section id="fusion-of-software-with-hardware">
 | ||
| <h2><span class="section-number">2.2. </span>Fusion of Software with Hardware<a class="headerlink" href="#fusion-of-software-with-hardware" title="Link to this heading">¶</a></h2>
 | ||
| <p>On one hand, we have the hardware designed so that the joystic x- and y- axis, and DC motors are wired to the proper GPIOs on the
 | ||
| ESP32-C3 WROOM microcontroller. On the other hand, we have the software that reads the joystick x- and y- axis, sends the data
 | ||
| to the receiver device, and converts that to PWM values on the receiver device.</p>
 | ||
| <p>In essense, the direction and speed of the bitByte Rider car is controlled by the two variables. On the remote controller device,
 | ||
| the joystic x- and y- axis values are sent to the receiver device in a raw format (i.e. analog voltages, “as-is”). On the receover
 | ||
| device, these two values are converted to the two PWM values; one for each pair of DC motors on left and right side.</p>
 | ||
| <p>When the joystick is pushed forward, the X-axis voltage remains at 1.65V (neutral), while the Y-axis voltage rises to 3.3V. The
 | ||
| receiver on the RC car interprets this input and generates 100% PWM duty cycle signals on both sides, driving the car forward at
 | ||
| full speed.</p>
 | ||
| <p>Similarly, when the joystick is pushed fully to the left or right, the X-axis voltage shifts while the Y-axis remains neutral. For a
 | ||
| left turn, the receiver translates the signal into 100% PWM on the left-side motors and 0% on the right-side motors, causing the car
 | ||
| to pivot. The opposite occurs for a right turn, with 100% PWM on the right and 0% on the left, enabling precise directional control.</p>
 | ||
| <p>The table below summarizes the reserved GPIOs. These GPIOs are hard-wired to the corresponding components, and hard-coded in the
 | ||
| corresponding functions. For example, the GPIOs 0 and 1 are hard-wired to the joystick x- and y- axis, respectively; and, hard-coded
 | ||
| to read analog values and store them in the corresponding x- and y- variables.</p>
 | ||
| <table class="docutils align-default">
 | ||
| <thead>
 | ||
| <tr class="row-odd"><th class="head"><p>GPIO</p></th>
 | ||
| <th class="head"><p>Pin</p></th>
 | ||
| <th class="head"><p>Function</p></th>
 | ||
| <th class="head"><p>Notes</p></th>
 | ||
| </tr>
 | ||
| </thead>
 | ||
| <tbody>
 | ||
| <tr class="row-even"><td><p>0</p></td>
 | ||
| <td><p>16</p></td>
 | ||
| <td><p>Joystick x-axis</p></td>
 | ||
| <td><p>ADC1_CH0</p></td>
 | ||
| </tr>
 | ||
| <tr class="row-odd"><td><p>1</p></td>
 | ||
| <td><p>15</p></td>
 | ||
| <td><p>Joystick y-axis</p></td>
 | ||
| <td><p>ADC1_CH1</p></td>
 | ||
| </tr>
 | ||
| <tr class="row-even"><td><p>8</p></td>
 | ||
| <td><p>5</p></td>
 | ||
| <td><p>Joystick push button</p></td>
 | ||
| <td><p>NC</p></td>
 | ||
| </tr>
 | ||
| <tr class="row-odd"><td><p>6</p></td>
 | ||
| <td><p>4</p></td>
 | ||
| <td><p>PWM for clockwise rotation of left-side motors</p></td>
 | ||
| <td><p>LEDC_CHANNEL_1</p></td>
 | ||
| </tr>
 | ||
| <tr class="row-even"><td><p>5</p></td>
 | ||
| <td><p>3</p></td>
 | ||
| <td><p>PWM for clockwise rotation of right-side motors</p></td>
 | ||
| <td><p>LEDC_CHANNEL_0</p></td>
 | ||
| </tr>
 | ||
| <tr class="row-odd"><td><p>4</p></td>
 | ||
| <td><p>2</p></td>
 | ||
| <td><p>PWM for counter-clockwise rotation of right-side motors</p></td>
 | ||
| <td><p>LEDC_CHANNEL_2</p></td>
 | ||
| </tr>
 | ||
| <tr class="row-even"><td><p>7</p></td>
 | ||
| <td><p>6</p></td>
 | ||
| <td><p>PWM for counter-clockwise rotation of left-side motors</p></td>
 | ||
| <td><p>LEDC_CHANNEL_3</p></td>
 | ||
| </tr>
 | ||
| </tbody>
 | ||
| </table>
 | ||
| <p>The struct used to store motor PWM values is shown below. While the bitByteRider RC car can be effectively controlled using
 | ||
| just two PWM signals—one for each side—the structure is designed to hold four values, allowing room for future enhancements. This
 | ||
| forward-thinking design supports potential upgrades such as improved maneuverability, individual wheel control, or advanced driving
 | ||
| modes, making the system more adaptable and scalable for future development.</p>
 | ||
| <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">struct</span><span class="w"> </span><span class="nc">motors_rpm</span><span class="w"> </span><span class="p">{</span>
 | ||
| <span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="n">motor1_rpm_pwm</span><span class="p">;</span>
 | ||
| <span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="n">motor2_rpm_pwm</span><span class="p">;</span>
 | ||
| <span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="n">motor3_rpm_pwm</span><span class="p">;</span>
 | ||
| <span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="n">motor4_rpm_pwm</span><span class="p">;</span>
 | ||
| <span class="p">};</span>
 | ||
| </pre></div>
 | ||
| </div>
 | ||
| <p>On the transmitter device, the PWM values for the DC motors are sent to the receiver using the following function. The variable
 | ||
| <strong>receiver_mac</strong> stores the MAC address of the receiver device (ESP32-C3 bitBoard on the RC car).</p>
 | ||
| <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="c1">// Function to send data to the receiver</span>
 | ||
| <span class="kt">void</span><span class="w"> </span><span class="nf">sendData</span><span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
 | ||
| <span class="w">    </span><span class="n">sensors_data_t</span><span class="w"> </span><span class="n">buffer</span><span class="p">;</span><span class="w">              </span><span class="c1">// Declare data struct</span>
 | ||
| 
 | ||
| <span class="w">    </span><span class="n">buffer</span><span class="p">.</span><span class="n">crc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
 | ||
| <span class="w">    </span><span class="n">buffer</span><span class="p">.</span><span class="n">x_axis</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
 | ||
| <span class="w">    </span><span class="n">buffer</span><span class="p">.</span><span class="n">y_axis</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
 | ||
| <span class="w">    </span><span class="n">buffer</span><span class="p">.</span><span class="n">nav_bttn</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
 | ||
| <span class="w">    </span><span class="n">buffer</span><span class="p">.</span><span class="n">motor1_rpm_pwm</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
 | ||
| <span class="w">    </span><span class="n">buffer</span><span class="p">.</span><span class="n">motor2_rpm_pwm</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
 | ||
| <span class="w">    </span><span class="n">buffer</span><span class="p">.</span><span class="n">motor3_rpm_pwm</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
 | ||
| <span class="w">    </span><span class="n">buffer</span><span class="p">.</span><span class="n">motor4_rpm_pwm</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
 | ||
| 
 | ||
| <span class="w">    </span><span class="c1">// Display brief summary of data being sent.</span>
 | ||
| <span class="w">    </span><span class="n">ESP_LOGI</span><span class="p">(</span><span class="n">TAG</span><span class="p">,</span><span class="w"> </span><span class="s">"Joystick (x,y) position ( 0x%04X, 0x%04X )"</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">uint8_t</span><span class="p">)</span><span class="n">buffer</span><span class="p">.</span><span class="n">x_axis</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">uint8_t</span><span class="p">)</span><span class="n">buffer</span><span class="p">.</span><span class="n">y_axis</span><span class="p">);</span>
 | ||
| <span class="w">    </span><span class="n">ESP_LOGI</span><span class="p">(</span><span class="n">TAG</span><span class="p">,</span><span class="w"> </span><span class="s">"pwm 1, pwm 2 [ 0x%04X, 0x%04X ]"</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">uint8_t</span><span class="p">)</span><span class="n">buffer</span><span class="p">.</span><span class="n">pwm</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">uint8_t</span><span class="p">)</span><span class="n">buffer</span><span class="p">.</span><span class="n">pwm</span><span class="p">);</span>
 | ||
| <span class="w">    </span><span class="n">ESP_LOGI</span><span class="p">(</span><span class="n">TAG</span><span class="p">,</span><span class="w"> </span><span class="s">"pwm 3, pwm 4 [ 0x%04X, 0x%04X ]"</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">uint8_t</span><span class="p">)</span><span class="n">buffer</span><span class="p">.</span><span class="n">pwm</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">uint8_t</span><span class="p">)</span><span class="n">buffer</span><span class="p">.</span><span class="n">pwm</span><span class="p">);</span>
 | ||
| 
 | ||
| <span class="w">    </span><span class="c1">// Call ESP-NOW function to send data (MAC address of receiver, pointer to the memory holding data & data length)</span>
 | ||
| <span class="w">    </span><span class="kt">uint8_t</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">esp_now_send</span><span class="p">(</span><span class="n">receiver_mac</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">buffer</span><span class="p">,</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
 | ||
| 
 | ||
| <span class="w">    </span><span class="c1">// If status is NOT OK, display error message and error code (in hexadecimal).</span>
 | ||
| <span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">result</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
 | ||
| <span class="w">        </span><span class="n">ESP_LOGE</span><span class="p">(</span><span class="s">"ESP-NOW"</span><span class="p">,</span><span class="w"> </span><span class="s">"Error sending data! Error code: 0x%04X"</span><span class="p">,</span><span class="w"> </span><span class="n">result</span><span class="p">);</span>
 | ||
| <span class="w">        </span><span class="n">deletePeer</span><span class="p">();</span>
 | ||
| <span class="w">    </span><span class="p">}</span>
 | ||
| <span class="w">    </span><span class="k">else</span>
 | ||
| <span class="w">        </span><span class="n">ESP_LOGW</span><span class="p">(</span><span class="s">"ESP-NOW"</span><span class="p">,</span><span class="w"> </span><span class="s">"Data was sent."</span><span class="p">);</span>
 | ||
| <span class="p">}</span>
 | ||
| </pre></div>
 | ||
| </div>
 | ||
| <p>This function is invoked by a dedicated FreeRTOS task every 100 milliseconds, ensuring consistent and timely transmission of
 | ||
| control data to the receiver device. By leveraging FreeRTOS’s precise task scheduling, the system maintains low-latency
 | ||
| communication and predictable behaviour, critical for real-time control in embedded applications.</p>
 | ||
| <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="c1">// Continous, periodic task that sends data.</span>
 | ||
| <span class="k">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">rc_send_data_task</span><span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="w"> </span><span class="o">*</span><span class="n">arg</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
 | ||
| 
 | ||
| <span class="w">    </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="nb">true</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
 | ||
| <span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">esp_now_is_peer_exist</span><span class="p">(</span><span class="n">receiver_mac</span><span class="p">))</span>
 | ||
| <span class="w">            </span><span class="n">sendData</span><span class="p">();</span>
 | ||
| <span class="w">        </span><span class="n">vTaskDelay</span><span class="w"> </span><span class="p">(</span><span class="mi">100</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">portTICK_PERIOD_MS</span><span class="p">);</span>
 | ||
| <span class="w">    </span><span class="p">}</span>
 | ||
| <span class="p">}</span>
 | ||
| </pre></div>
 | ||
| </div>
 | ||
| <p>As data is being sent, the function onDataSent() is called to check & display the status of the data transmission.</p>
 | ||
| <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="c1">// Call-back for the event when data is being sent</span>
 | ||
| <span class="kt">void</span><span class="w"> </span><span class="nf">onDataSent</span><span class="w"> </span><span class="p">(</span><span class="kt">uint8_t</span><span class="w"> </span><span class="o">*</span><span class="n">mac_addr</span><span class="p">,</span><span class="w"> </span><span class="n">esp_now_send_status_t</span><span class="w"> </span><span class="n">status</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
 | ||
| <span class="w">    </span><span class="n">ESP_LOGW</span><span class="p">(</span><span class="n">TAG</span><span class="p">,</span><span class="w"> </span><span class="s">"Packet send status: 0x%04X"</span><span class="p">,</span><span class="w"> </span><span class="n">status</span><span class="p">);</span>
 | ||
| <span class="p">}</span>
 | ||
| 
 | ||
| <span class="p">...</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="p">...</span>
 | ||
| <span class="p">...</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="p">...</span>
 | ||
| </pre></div>
 | ||
| </div>
 | ||
| <p>On the receiver device, the data is saved in the variables by the call-back function onDataReceived().</p>
 | ||
| <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="c1">// Call-back for the event when data is being received</span>
 | ||
| <span class="kt">void</span><span class="w"> </span><span class="nf">onDataReceived</span><span class="w"> </span><span class="p">(</span><span class="kt">uint8_t</span><span class="w"> </span><span class="o">*</span><span class="n">mac_addr</span><span class="p">,</span><span class="w"> </span><span class="kt">uint8_t</span><span class="w"> </span><span class="o">*</span><span class="n">data</span><span class="p">,</span><span class="w"> </span><span class="kt">uint8_t</span><span class="w"> </span><span class="n">data_len</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
 | ||
| 
 | ||
| <span class="w">    </span><span class="n">buf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">sensors_data_t</span><span class="o">*</span><span class="p">)</span><span class="n">data</span><span class="p">;</span><span class="w">                            </span><span class="c1">// Allocate memory for buffer to store data being received</span>
 | ||
| <span class="w">    </span><span class="n">ESP_LOGW</span><span class="p">(</span><span class="n">TAG</span><span class="p">,</span><span class="w"> </span><span class="s">"Data was received"</span><span class="p">);</span>
 | ||
| <span class="w">    </span><span class="n">ESP_LOGI</span><span class="p">(</span><span class="n">TAG</span><span class="p">,</span><span class="w"> </span><span class="s">"x-axis: 0x%04x"</span><span class="p">,</span><span class="w"> </span><span class="n">buf</span><span class="o">-></span><span class="n">x_axis</span><span class="p">);</span>
 | ||
| <span class="w">    </span><span class="n">ESP_LOGI</span><span class="p">(</span><span class="n">TAG</span><span class="p">,</span><span class="w"> </span><span class="s">"x-axis: 0x%04x"</span><span class="p">,</span><span class="w"> </span><span class="n">buf</span><span class="o">-></span><span class="n">y_axis</span><span class="p">);</span>
 | ||
| <span class="w">    </span><span class="n">ESP_LOGI</span><span class="p">(</span><span class="n">TAG</span><span class="p">,</span><span class="w"> </span><span class="s">"PWM 1: 0x%04x"</span><span class="p">,</span><span class="w"> </span><span class="n">buf</span><span class="o">-></span><span class="n">motor1_rpm_pwm</span><span class="p">);</span>
 | ||
| <span class="p">}</span>
 | ||
| </pre></div>
 | ||
| </div>
 | ||
| </section>
 | ||
| <section id="schematic">
 | ||
| <h2><span class="section-number">2.3. </span>Schematic<a class="headerlink" href="#schematic" title="Link to this heading">¶</a></h2>
 | ||
| <img alt="_images/ESP-IDF_Robot_schematic.png" src="_images/ESP-IDF_Robot_schematic.png" />
 | ||
| </section>
 | ||
| </section>
 | ||
| 
 | ||
| 
 | ||
|           </div>
 | ||
|           
 | ||
|         </div>
 | ||
|       </div>
 | ||
|       <div class="sphinxsidebar" role="navigation" aria-label="Main">
 | ||
|         <div class="sphinxsidebarwrapper">
 | ||
| <h1 class="logo"><a href="index.html">Byte Rider</a></h1>
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| <search id="searchbox" style="display: none" role="search">
 | ||
|     <div class="searchformwrapper">
 | ||
|     <form class="search" action="search.html" method="get">
 | ||
|       <input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" placeholder="Search"/>
 | ||
|       <input type="submit" value="Go" />
 | ||
|     </form>
 | ||
|     </div>
 | ||
| </search>
 | ||
| <script>document.getElementById('searchbox').style.display = "block"</script><h3>Navigation</h3>
 | ||
| <ul class="current">
 | ||
| <li class="toctree-l1"><a class="reference internal" href="intro.html">1. OVERVIEW</a></li>
 | ||
| <li class="toctree-l1 current"><a class="current reference internal" href="#">2. HOW DOES IT WORK?</a><ul>
 | ||
| <li class="toctree-l2"><a class="reference internal" href="#reserved-pins-gpios">2.1. Reserved Pins & GPIOs</a><ul>
 | ||
| <li class="toctree-l3"><a class="reference internal" href="#reading-the-joystick-x-and-y-axis">2.1.1. Reading the Joystick x- and y- axis</a></li>
 | ||
| <li class="toctree-l3"><a class="reference internal" href="#controlling-the-direction-and-speed">2.1.2. Controlling the Direction and Speed</a></li>
 | ||
| </ul>
 | ||
| </li>
 | ||
| <li class="toctree-l2"><a class="reference internal" href="#fusion-of-software-with-hardware">2.2. Fusion of Software with Hardware</a></li>
 | ||
| <li class="toctree-l2"><a class="reference internal" href="#schematic">2.3. Schematic</a></li>
 | ||
| </ul>
 | ||
| </li>
 | ||
| <li class="toctree-l1"><a class="reference internal" href="data.html">3. DATA STRUCTS</a></li>
 | ||
| <li class="toctree-l1"><a class="reference internal" href="transmitter.html">4. TRANSMITTER</a></li>
 | ||
| <li class="toctree-l1"><a class="reference internal" href="receiver.html">5. RECEIVER</a></li>
 | ||
| <li class="toctree-l1"><a class="reference internal" href="progress.html">6. WORK-IN-PROGRESS WALK THROUGH</a></li>
 | ||
| <li class="toctree-l1"><a class="reference internal" href="references.html">7. REFERENCES</a></li>
 | ||
| </ul>
 | ||
| 
 | ||
| <div class="relations">
 | ||
| <h3>Related Topics</h3>
 | ||
| <ul>
 | ||
|   <li><a href="index.html">Documentation overview</a><ul>
 | ||
|       <li>Previous: <a href="intro.html" title="previous chapter"><span class="section-number">1. </span>OVERVIEW</a></li>
 | ||
|       <li>Next: <a href="data.html" title="next chapter"><span class="section-number">3. </span>DATA STRUCTS</a></li>
 | ||
|   </ul></li>
 | ||
| </ul>
 | ||
| </div>
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         </div>
 | ||
|       </div>
 | ||
|       <div class="clearer"></div>
 | ||
|     </div>
 | ||
|     <div class="footer">
 | ||
|       ©2025, Alexander B.
 | ||
|       
 | ||
|       |
 | ||
|       Powered by <a href="https://www.sphinx-doc.org/">Sphinx 8.2.3</a>
 | ||
|       & <a href="https://alabaster.readthedocs.io">Alabaster 1.0.0</a>
 | ||
|       
 | ||
|       |
 | ||
|       <a href="_sources/overview.rst.txt"
 | ||
|           rel="nofollow">Page source</a>
 | ||
|     </div>
 | ||
| 
 | ||
|     
 | ||
| 
 | ||
|     
 | ||
|   </body>
 | ||
| </html> |