<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Raspberry Pi Tutorials | Teach Me Microcontrollers</title>
	<atom:link href="https://www.teachmemicro.com/category/tutorials/raspberry-pi-tutorial/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.teachmemicro.com/category/tutorials/raspberry-pi-tutorial/</link>
	<description>Microcontroller Tutorials and Resources</description>
	<lastBuildDate>Mon, 29 Jun 2026 22:56:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0.2</generator>

<image>
	<url>https://www.teachmemicro.com/wp-content/uploads/2019/04/blue-icon-65x65.png</url>
	<title>Raspberry Pi Tutorials | Teach Me Microcontrollers</title>
	<link>https://www.teachmemicro.com/category/tutorials/raspberry-pi-tutorial/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>RP2040-Zero Getting Started Guide: Pinout, Arduino IDE Setup, and RGB LED Blink</title>
		<link>https://www.teachmemicro.com/rp2040-zero-getting-started/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=rp2040-zero-getting-started</link>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Mon, 29 Jun 2026 22:54:59 +0000</pubDate>
				<category><![CDATA[Raspberry Pi Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=12145</guid>

					<description><![CDATA[<p>The RP2040-Zero from Waveshare is one of those boards that looks too small at first glance, but is actually a very capable microcontroller board. It is based on the same RP2040 chip used in the Raspberry Pi Pico, but Waveshare placed it on a much smaller board with a USB-C connector, castellated edges, reset and &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/rp2040-zero-getting-started/">RP2040-Zero Getting Started Guide: Pinout, Arduino IDE Setup, and RGB LED Blink</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The <strong>RP2040-Zero</strong> from Waveshare is one of those boards that looks too small at first glance, but is actually a very capable microcontroller board. It is based on the same RP2040 chip used in the Raspberry Pi Pico, but Waveshare placed it on a much smaller board with a USB-C connector, castellated edges, reset and boot buttons, and an onboard RGB LED.</p>
<p>I like boards like this for compact projects. If a <a href="https://www.teachmemicro.com/raspberry-pi-pico-pinout/">Raspberry Pi Pico</a> feels too long for your enclosure or breadboard layout, the RP2040-Zero is a nice alternative. The tradeoff is that the pin labels are tighter, some pins are on small pads, and the onboard LED is not a normal single-color LED. But once you know those details, it is quite easy to use.</p>
<p>In this tutorial, we will look at the RP2040-Zero features, pinout, Arduino IDE setup, boot mode, and a simple RGB LED blink program.</p>
<p><span id="more-12145"></span></p>
<h2><strong>RP2040-Zero Features</strong></h2>
<p>The RP2040-Zero uses the <strong>RP2040 microcontroller</strong>, which has a dual-core Arm Cortex-M0+ processor running up to 133 MHz and 264 kB of SRAM. Waveshare’s RP2040-Zero board adds 2 MB of onboard flash, USB-C, castellated edges, and brings out 29 GPIO pins, although only some are available through the main pin headers.</p>
<p>Here are the main features:</p>
<div class="TyagGW_tableContainer">
<div class="group TyagGW_tableWrapper flex flex-col-reverse w-fit" tabindex="-1">
<table class="w-fit min-w-(--thread-content-width)">
<thead>
<tr>
<th class="last:pe-10" data-col-size="sm">Feature</th>
<th class="last:pe-10" data-col-size="md">Details</th>
</tr>
</thead>
<tbody>
<tr>
<td data-col-size="sm">Microcontroller</td>
<td data-col-size="md">RP2040</td>
</tr>
<tr>
<td data-col-size="sm">CPU</td>
<td data-col-size="md">Dual-core Arm Cortex-M0+</td>
</tr>
<tr>
<td data-col-size="sm">Clock Speed</td>
<td data-col-size="md">Up to 133 MHz</td>
</tr>
<tr>
<td data-col-size="sm">SRAM</td>
<td data-col-size="md">264 KB</td>
</tr>
<tr>
<td data-col-size="sm">Flash</td>
<td data-col-size="md">2 MB onboard flash</td>
</tr>
<tr>
<td data-col-size="sm">USB</td>
<td data-col-size="md">USB-C, USB 1.1 device/host support</td>
</tr>
<tr>
<td data-col-size="sm">GPIO</td>
<td data-col-size="md">29 GPIO pins total</td>
</tr>
<tr>
<td data-col-size="sm">ADC</td>
<td data-col-size="md">4 × 12-bit ADC inputs</td>
</tr>
<tr>
<td data-col-size="sm">PWM</td>
<td data-col-size="md">16 PWM channels</td>
</tr>
<tr>
<td data-col-size="sm">Communication</td>
<td data-col-size="md">2 × UART, 2 × SPI, 2 × I2C</td>
</tr>
<tr>
<td data-col-size="sm">Extra feature</td>
<td data-col-size="md">Onboard WS2812B RGB LED</td>
</tr>
<tr>
<td data-col-size="sm">Programming</td>
<td data-col-size="md">USB drag-and-drop / Arduino IDE / MicroPython / C/C++</td>
</tr>
</tbody>
</table>
<p>The RP2040 also includes PIO, or Programmable I/O, which is one of the best features of this chip. PIO lets the chip handle special timing-heavy tasks such as custom serial protocols, LED driving, or unusual communication signals without forcing the CPU to bit-bang everything. Raspberry Pi lists 8 PIO state machines on the RP2040.</p>
<h2><strong>RP2040-Zero vs Raspberry Pi Pico</strong></h2>
<p>The easiest way to understand the RP2040-Zero is to think of it as a smaller Pico-like board.</p>
<p><img data-dominant-color="c7d7d2" data-has-transparency="false" style="--dominant-color: #c7d7d2;" decoding="async" class="aligncenter size-full wp-image-12151 not-transparent" src="https://www.teachmemicro.com/wp-content/uploads/2026/06/rp2040-zero-vs-raspberry-pi-pico.avif" alt="RP2040-zero vs Raspberry Pi Pico" width="836" height="471" srcset="https://www.teachmemicro.com/wp-content/uploads/2026/06/rp2040-zero-vs-raspberry-pi-pico.avif 836w, https://www.teachmemicro.com/wp-content/uploads/2026/06/rp2040-zero-vs-raspberry-pi-pico-300x169.avif 300w, https://www.teachmemicro.com/wp-content/uploads/2026/06/rp2040-zero-vs-raspberry-pi-pico-768x433.avif 768w" sizes="(max-width: 836px) 100vw, 836px" /></p>
<p>The Raspberry Pi Pico is easier to handle on a breadboard because it has a wider and longer layout. The RP2040-Zero is more compact, so it is better for small projects, wearables, custom PCBs, keyboards, USB devices, and projects where space matters.</p>
<p>The RP2040-Zero also uses USB-C, which is convenient because most newer cables and chargers already use it. Just make sure you use a <strong>data-capable USB-C cable</strong>, not a charge-only cable. A charge-only cable is one of the most common reasons the board powers up but does not appear in the Arduino IDE.</p>
<h2><strong>RP2040-Zero Pinout Overview</strong></h2>
<p>The RP2040-Zero exposes GPIO pins along the edge headers and extra pads. On the main 23-pin header, you get GPIO0 to GPIO15, GPIO26 to GPIO29, 3V3, GND, and VSYS. Two smaller 5-pin headers expose GPIO17 to GPIO21, and GPIO22 to GPIO25 plus GND. The schematic also shows the onboard WS2812B RGB LED connected to <strong>GPIO16</strong>.</p>
<div align="center"><iframe loading="lazy" style="border: 1px solid #e2e8f0; border-radius: 8px;" src="https://micropinouts.com/embed/board/rp2040-zero" width="800" height="600" frameborder="0"></iframe></div>
<p>Here is a simplified pin list:</p>
<div class="TyagGW_tableContainer">
<div class="group TyagGW_tableWrapper flex flex-col-reverse w-fit" tabindex="-1">
<table class="w-fit min-w-(--thread-content-width)">
<thead>
<tr>
<th class="last:pe-10" data-col-size="sm">Pin / GPIO</th>
<th class="last:pe-10" data-col-size="md">Common Use</th>
</tr>
</thead>
<tbody>
<tr>
<td data-col-size="sm">GPIO0 to GPIO15</td>
<td data-col-size="md">Digital I/O, PWM, UART, SPI, I2C depending on configuration</td>
</tr>
<tr>
<td data-col-size="sm">GPIO16</td>
<td data-col-size="md">Onboard WS2812B RGB LED</td>
</tr>
<tr>
<td data-col-size="sm">GPIO17 to GPIO25</td>
<td data-col-size="md">Digital I/O and peripheral functions</td>
</tr>
<tr>
<td data-col-size="sm">GPIO26 / ADC0</td>
<td data-col-size="md">Analog input</td>
</tr>
<tr>
<td data-col-size="sm">GPIO27 / ADC1</td>
<td data-col-size="md">Analog input</td>
</tr>
<tr>
<td data-col-size="sm">GPIO28 / ADC2</td>
<td data-col-size="md">Analog input</td>
</tr>
<tr>
<td data-col-size="sm">GPIO29 / ADC3</td>
<td data-col-size="md">Analog input</td>
</tr>
<tr>
<td data-col-size="sm">3V3</td>
<td data-col-size="md">3.3V output from onboard regulator</td>
</tr>
<tr>
<td data-col-size="sm">GND</td>
<td data-col-size="md">Ground</td>
</tr>
<tr>
<td data-col-size="sm">VSYS</td>
<td data-col-size="md">Main supply rail / USB-related supply path</td>
</tr>
</tbody>
</table>
<p>One important thing to remember is that RP2040 GPIO pins are <strong>3.3V logic pins</strong>. Do not connect a 5V signal directly to a GPIO pin. If you are working with 5V modules, use a level shifter or check if the module’s output is already 3.3V-safe.</p>
<h2><strong>Powering the RP2040-Zero</strong></h2>
<p>The easiest way to power the RP2040-Zero is through the USB-C connector. For most beginner projects, this is what I recommend.</p>
<p>You can also power the board through its power pins, but be careful. Waveshare notes that the board does not include battery protection, and if you power it from a battery you must handle charging, over-discharge protection, and backflow protection yourself.</p>
<p>For a first test, use USB-C. It removes many possible mistakes.</p>
<h2><strong>Setting Up Arduino IDE for RP2040-Zero</strong></h2>
<p>The RP2040-Zero can be programmed in different ways, including MicroPython, C/C++, and Arduino IDE. For this guide, we will use the Arduino IDE because it is usually the fastest way to test the board.</p>
<p>The Arduino support we will use is the <a href="https://github.com/earlephilhower/arduino-pico"><strong>Arduino-Pico core</strong> by Earle Philhower</a>. Its official installation instructions say to add the RP2040 package URL in Arduino IDE Preferences, then install the board package from Boards Manager.</p>
<h3><strong>Step 1: Install Arduino IDE</strong></h3>
<p>Download and install the latest Arduino IDE from the Arduino website.</p>
<h3><strong>Step 2: Add the RP2040 Board Manager URL</strong></h3>
<p>Open Arduino IDE, then go to:</p>
<p><strong>File &gt; Preferences</strong></p>
<p>In <strong>Additional Boards Manager URLs</strong>, add this URL:</p>
<pre class="cm-content q9tKkq_readonly m-0"><pre><code class="language-cpp">https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json</code></pre></pre>
<p>If you already have another URL there, such as the ESP32 board URL, separate the URLs with a comma.</p>
<h3><strong>Step 3: Install the RP2040 Board Package</strong></h3>
<p>Go to:</p>
<p><strong>Tools &gt; Board &gt; Boards Manager</strong></p>
<p>Search for:</p>
<pre class="cm-content q9tKkq_readonly m-0"><pre><code class="language-cpp">pico</code></pre></pre>
<p>Install:</p>
<pre class="cm-content q9tKkq_readonly m-0"><pre><code class="language-cpp">Raspberry Pi Pico/RP2040 by Earle F. Philhower, III</code></pre></pre>
<h3><strong>Step 4: Select the Board</strong></h3>
<p>After installation, go to:</p>
<p><strong>Tools &gt; Board &gt; Raspberry Pi RP2040 Boards</strong></p>
<p>Select the RP2040-Zero/Waveshare RP2040-Zero option if it appears in your installed version. If your Arduino-Pico version does not show a specific RP2040-Zero option, you can use a generic RP2040 or Raspberry Pi Pico selection for simple tests, but the dedicated board entry is preferred when available.</p>
<h2><strong>Entering Boot Mode</strong></h2>
<p>For the first upload, you may need to put the board into bootloader mode manually.</p>
<p>There are two common ways to do it.</p>
<p>If the board is unplugged:</p>
<ol>
<li style="list-style-type: none;">
<ol>
<li>Hold the <strong>BOOT</strong> button.</li>
<li>Plug the USB-C cable into your computer.</li>
<li>Release the <strong>BOOT</strong> button.</li>
<li>A drive named something like <strong>RPI-RP2</strong> should appear.</li>
</ol>
</li>
</ol>
<p>If the board is already plugged in:</p>
<ol>
<li style="list-style-type: none;">
<ol>
<li>Press and hold <strong>RESET</strong>.</li>
<li>Press and hold <strong>BOOT</strong>.</li>
<li>Release <strong>RESET</strong> first.</li>
<li>Release <strong>BOOT</strong>.</li>
<li>The board should enter flashing mode.</li>
</ol>
</li>
</ol>
<p>Waveshare’s FAQ gives the same reset-and-boot sequence for flashing firmware.</p>
<h2><strong>First Arduino Program: Blink the Onboard RGB LED</strong></h2>
<p>On many Arduino boards, the first test is usually the standard Blink sketch. The RP2040-Zero is a little different because its onboard LED is not a normal LED connected directly to a GPIO pin.</p>
<p>The onboard LED is a <strong>WS2812B RGB LED</strong>, so it needs a NeoPixel-style signal. According to the RP2040-Zero schematic, the RGB LED data pin is connected to <strong>GPIO16</strong>.</p>
<p>Before uploading the code, install the <strong>Adafruit NeoPixel</strong> library:</p>
<p><strong>Sketch &gt; Include Library &gt; Manage Libraries</strong></p>
<p>Search for:</p>
<pre class="cm-content q9tKkq_readonly m-0"><pre><code class="language-cpp">Adafruit NeoPixel</code></pre></pre>
<p>Install it, then upload this sketch:</p>
<pre class="cm-content q9tKkq_readonly m-0"><pre><code class="language-cpp">#include &lt;Adafruit_NeoPixel.h&gt;

#define RGB_LED_PIN 16
#define NUM_LEDS 1

Adafruit_NeoPixel pixel(NUM_LEDS, RGB_LED_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  pixel.begin();
  pixel.setBrightness(30);  // Keep it low so it is not too bright
  pixel.clear();
  pixel.show();
}

void loop() {
  // Red
  pixel.setPixelColor(0, pixel.Color(255, 0, 0));
  pixel.show();
  delay(500);

  // Green
  pixel.setPixelColor(0, pixel.Color(0, 255, 0));
  pixel.show();
  delay(500);

  // Blue
  pixel.setPixelColor(0, pixel.Color(0, 0, 255));
  pixel.show();
  delay(500);

  // Off
  pixel.clear();
  pixel.show();
  delay(500);
}</code></pre></pre>
<p>After uploading, the onboard RGB LED should cycle through red, green, blue, then turn off.</p>
<p>If you uploaded the ordinary Arduino Blink example and nothing happened, the board is probably fine. The issue is just that the onboard LED is not a simple LED. You need the WS2812/NeoPixel code above.</p>
<h2><strong>Testing a Normal GPIO Pin</strong></h2>
<p>After testing the onboard RGB LED, it is also a good idea to test a normal GPIO pin with an external LED. This confirms that the board pins work as expected.</p>
<p>Connect:</p>
<div class="TyagGW_tableContainer">
<div class="group TyagGW_tableWrapper flex flex-col-reverse w-fit" tabindex="-1">
<table class="w-fit min-w-(--thread-content-width)">
<thead>
<tr>
<th class="last:pe-10" data-col-size="sm">RP2040-Zero Pin</th>
<th class="last:pe-10" data-col-size="sm">Component</th>
</tr>
</thead>
<tbody>
<tr>
<td data-col-size="sm">GPIO0</td>
<td data-col-size="sm">220Ω resistor</td>
</tr>
<tr>
<td data-col-size="sm">Resistor other end</td>
<td data-col-size="sm">LED anode</td>
</tr>
<tr>
<td data-col-size="sm">LED cathode</td>
<td data-col-size="sm">GND</td>
</tr>
</tbody>
</table>
<p>Then upload this sketch:</p>
<pre class="cm-content q9tKkq_readonly m-0"><pre><code class="language-cpp">#define LED_PIN 0

void setup() {
  pinMode(LED_PIN, OUTPUT);
}

void loop() {
  digitalWrite(LED_PIN, HIGH);
  delay(500);

  digitalWrite(LED_PIN, LOW);
  delay(500);
}</code></pre></pre>
<p>This time we are using a normal LED, so the usual <em>digitalWrite()</em> method works.</p>
<h2><strong>Reading an Analog Input</strong></h2>
<p>The RP2040-Zero also has analog-capable pins. GPIO26, GPIO27, GPIO28, and GPIO29 can be used as ADC inputs. Waveshare lists 4 × 12-bit ADC channels for the board, and the schematic labels GPIO26 to GPIO29 as ADC0 to ADC3.</p>
<p>For example, connect a potentiometer like this:</p>
<table class="w-fit min-w-(--thread-content-width)">
<thead>
<tr>
<th class="last:pe-10" data-col-size="sm">Potentiometer Pin</th>
<th class="last:pe-10" data-col-size="sm">RP2040-Zero Pin</th>
</tr>
</thead>
<tbody>
<tr>
<td data-col-size="sm">One side</td>
<td data-col-size="sm">3V3</td>
</tr>
<tr>
<td data-col-size="sm">Middle pin</td>
<td data-col-size="sm">GPIO26 / ADC0</td>
</tr>
<tr>
<td data-col-size="sm">Other side</td>
<td data-col-size="sm">GND</td>
</tr>
</tbody>
</table>
<p>Then upload this sketch:</p>
<pre class="cm-content q9tKkq_readonly m-0"><pre><code class="language-cpp">#define POT_PIN 26

void setup() {
  Serial.begin(115200);
}

void loop() {
  int value = analogRead(POT_PIN);

  Serial.print(&quot;ADC value: &quot;);
  Serial.println(value);

  delay(300);
}</code></pre></pre>
<p>Open the Serial Monitor at <strong>115200 baud</strong> and turn the potentiometer. You should see the ADC value change.</p>
<h2><strong>Common Problems and Fixes</strong></h2>
<h3 style="padding-left: 40px;"><strong>The board powers on but does not appear in Arduino IDE</strong></h3>
<p style="padding-left: 40px;">Use a different USB-C cable. Many USB-C cables are charge-only and cannot transfer data.</p>
<h3 style="padding-left: 40px;"><strong>The first upload does not work</strong></h3>
<p style="padding-left: 40px;">Manually enter boot mode by holding <strong>BOOT</strong> while plugging in the board. After the first successful upload, the Arduino-Pico core usually handles reset automatically, but if the board hangs, you may need to enter boot mode manually again.</p>
<h3 style="padding-left: 40px;"><strong>The onboard LED does not blink with the normal Blink sketch</strong></h3>
<p style="padding-left: 40px;">That is expected. The onboard LED is a WS2812B RGB LED on GPIO16, not a simple LED. Use the NeoPixel example above.</p>
<h3 style="padding-left: 40px;"><strong>I cannot debug with SWD</strong></h3>
<p style="padding-left: 40px;">Waveshare notes that the RP2040-Zero does not expose the SWD debugging pins. If you need proper SWD debugging, a Raspberry Pi Pico or another RP2040 board with debug pins is easier to use.</p>
<h2><strong>Final Thoughts</strong></h2>
<p>The RP2040-Zero is a small but powerful board. For beginners, the only slightly confusing part is the onboard RGB LED because it does not behave like a normal Arduino LED. Once you know that it uses GPIO16 and needs WS2812/NeoPixel-style control, the board becomes much easier to test.</p>
<p data-is-last-node="" data-is-only-node="">For compact projects, USB devices, small sensor boards, tiny displays, custom PCBs, or keyboard-style projects, the RP2040-Zero is a very useful alternative to the Raspberry Pi Pico. It gives you the same RP2040 core in a smaller layout, and the USB-C connector is a nice bonus.</p>
</div>
</div>
</div>
</div>
</div>
</div>
<p>The post <a href="https://www.teachmemicro.com/rp2040-zero-getting-started/">RP2040-Zero Getting Started Guide: Pinout, Arduino IDE Setup, and RGB LED Blink</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Connect L298N to Raspberry Pi 5: Control DC Motors with Python</title>
		<link>https://www.teachmemicro.com/connect-l298n-to-raspberry-pi-5-control-dc-motors-with-python/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=connect-l298n-to-raspberry-pi-5-control-dc-motors-with-python</link>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Mon, 22 Jun 2026 01:00:25 +0000</pubDate>
				<category><![CDATA[Raspberry Pi Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=11856</guid>

					<description><![CDATA[<p>The Raspberry Pi 5 is powerful enough to run vision, robotics, and automation projects, but its GPIO pins cannot directly drive DC motors. A motor needs more current than a Raspberry Pi GPIO pin can provide, and motors also generate electrical noise that can damage sensitive electronics. That is where the L298N motor driver module &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/connect-l298n-to-raspberry-pi-5-control-dc-motors-with-python/">Connect L298N to Raspberry Pi 5: Control DC Motors with Python</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The Raspberry Pi 5 is powerful enough to run vision, robotics, and automation projects, but its GPIO pins cannot directly drive DC motors. A motor needs more current than a Raspberry Pi GPIO pin can provide, and motors also generate electrical noise that can damage sensitive electronics.</p>
<p>That is where the <a href="https://www.teachmemicro.com/use-l298n-motor-driver/"><strong>L298N motor driver module</strong></a> comes in. In this tutorial, you will learn how to connect an L298N to a Raspberry Pi 5 and control one or two DC motors using Python.</p>
<p>We will cover the wiring, power supply setup, GPIO pin connections, Python code, motor direction control, PWM speed control, and common troubleshooting tips.</p>
<p><span id="more-11856"></span></p>
<h2 id="why-use-an-l298n-with-raspberry-pi-5-">Why Use an L298N with Raspberry Pi 5?</h2>
<p>The Raspberry Pi 5 GPIO pins are for logic signals, not motor power. A GPIO pin can switch between LOW and HIGH, but it cannot safely supply the current needed by a DC motor.</p>
<p>The L298N module acts as a bridge between the Raspberry Pi 5 and the motor. The Raspberry Pi sends control signals to the L298N, and the L298N handles the higher motor voltage and current.</p>
<p>With an L298N module, you can:</p>
<ul>
<li>Control the direction of a DC motor</li>
<li>Control the speed of a DC motor using PWM</li>
<li>Drive two DC motors independently</li>
<li>Build a simple Raspberry Pi robot car</li>
<li>Control small pumps, fans, gear motors, or other DC loads</li>
</ul>
<h2 id="parts-needed">Parts Needed</h2>
<p>For this project, you will need:</p>
<ul>
<li>Raspberry Pi 5</li>
<li>L298N motor driver module</li>
<li>One or two DC motors</li>
<li>External motor power supply, such as a 6V, 7.4V, 9V, or 12V battery pack</li>
<li>Jumper wires</li>
<li>Breadboard or screw terminals</li>
<li>Raspberry Pi OS installed on your Raspberry Pi 5</li>
</ul>
<p>Do not power the motors directly from the Raspberry Pi 5 GPIO pins. Use a separate motor power supply connected to the L298N module.</p>
<h2 id="l298n-motor-driver-pinout">L298N Motor Driver Pinout</h2>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated.jpg"><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-1640" src="https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-1024x835.jpg" alt="L298N motor controller board" width="618" height="504" srcset="https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-1024x835.jpg 1024w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-300x245.jpg 300w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-768x626.jpg 768w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-24x20.jpg 24w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-36x29.jpg 36w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-48x39.jpg 48w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated.jpg 1516w" sizes="auto, (max-width: 618px) 100vw, 618px" /></a></p>
<p>Most L298N modules have the following pins:</p>
<table>
<thead>
<tr>
<th>L298N Pin</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>OUT1, OUT2</td>
<td>Motor A output terminals</td>
</tr>
<tr>
<td>OUT3, OUT4</td>
<td>Motor B output terminals</td>
</tr>
<tr>
<td>IN1, IN2</td>
<td>Direction control pins for Motor A</td>
</tr>
<tr>
<td>IN3, IN4</td>
<td>Direction control pins for Motor B</td>
</tr>
<tr>
<td>ENA</td>
<td>Speed control / enable pin for Motor A</td>
</tr>
<tr>
<td>ENB</td>
<td>Speed control / enable pin for Motor B</td>
</tr>
<tr>
<td>+12V / VIN</td>
<td>External motor power input</td>
</tr>
<tr>
<td>GND</td>
<td>Common ground</td>
</tr>
<tr>
<td>5V</td>
<td>Logic supply pin or 5V regulator output, depending on jumper setting</td>
</tr>
</tbody>
</table>
<p>The actual label may vary depending on your L298N module. Some boards label the motor supply as +12V, even though the module can be used with other motor voltages within its supported range.</p>
<h2 id="important-power-warning">Important Power Warning</h2>
<p>The L298N has separate power paths:</p>
<ol>
<li><strong>Motor power</strong> — connected to the L298N +12V or VIN terminal</li>
<li><strong>Logic power</strong> — used by the L298N control circuit</li>
<li><strong>GPIO signals</strong> — sent from the Raspberry Pi 5 to IN1, IN2, IN3, IN4, ENA, and ENB</li>
</ol>
<p>For most beginner L298N modules, if the onboard 5V regulator jumper is installed and your motor supply is around 7V to 12V, the module can power its own logic circuit from the motor supply.</p>
<p>However, do not use the L298N 5V pin to power the Raspberry Pi 5. The Raspberry Pi 5 should be powered through its USB-C power input using a proper Raspberry Pi 5 power supply.</p>
<p>Also, the Raspberry Pi 5 and L298N must share a common ground. Without a common ground, the L298N may not correctly understand the GPIO signals from the Raspberry Pi.</p>
<h2 id="raspberry-pi-5-gpio-pins-used">Raspberry Pi 5 GPIO Pins Used</h2>
<p>In this tutorial, we will use BCM GPIO numbering.</p>
<table>
<thead>
<tr>
<th>L298N Pin</th>
<th style="text-align: right;">Raspberry Pi 5 GPIO</th>
<th style="text-align: right;">Physical Pin</th>
</tr>
</thead>
<tbody>
<tr>
<td>IN1</td>
<td style="text-align: right;">GPIO17</td>
<td style="text-align: right;">Pin 11</td>
</tr>
<tr>
<td>IN2</td>
<td style="text-align: right;">GPIO27</td>
<td style="text-align: right;">Pin 13</td>
</tr>
<tr>
<td>ENA</td>
<td style="text-align: right;">GPIO22</td>
<td style="text-align: right;">Pin 15</td>
</tr>
<tr>
<td>IN3</td>
<td style="text-align: right;">GPIO23</td>
<td style="text-align: right;">Pin 16</td>
</tr>
<tr>
<td>IN4</td>
<td style="text-align: right;">GPIO24</td>
<td style="text-align: right;">Pin 18</td>
</tr>
<tr>
<td>ENB</td>
<td style="text-align: right;">GPIO25</td>
<td style="text-align: right;">Pin 22</td>
</tr>
<tr>
<td>GND</td>
<td style="text-align: right;">GND</td>
<td style="text-align: right;">Pin 6</td>
</tr>
</tbody>
</table>
<p>This pin selection avoids the Raspberry Pi 5 power pins and keeps the wiring simple.</p>
<h2 id="wiring-one-dc-motor-to-raspberry-pi-5-and-l298n">Wiring One DC Motor to Raspberry Pi 5 and L298N</h2>
<p>For one motor, connect Motor A only.</p>
<h3 id="motor-a-wiring">Motor A Wiring</h3>
<table>
<thead>
<tr>
<th>L298N</th>
<th>Connect To</th>
</tr>
</thead>
<tbody>
<tr>
<td>OUT1</td>
<td>Motor wire 1</td>
</tr>
<tr>
<td>OUT2</td>
<td>Motor wire 2</td>
</tr>
<tr>
<td>IN1</td>
<td>Raspberry Pi GPIO17</td>
</tr>
<tr>
<td>IN2</td>
<td>Raspberry Pi GPIO27</td>
</tr>
<tr>
<td>ENA</td>
<td>Raspberry Pi GPIO22</td>
</tr>
<tr>
<td>GND</td>
<td>Raspberry Pi GND and battery negative</td>
</tr>
<tr>
<td>+12V / VIN</td>
<td>External motor supply positive</td>
</tr>
</tbody>
</table>
<p>If your L298N module has a jumper on ENA, remove it if you want to control motor speed using PWM from the Raspberry Pi. If the ENA jumper stays installed, Motor A will be enabled all the time, and you can only control direction using IN1 and IN2.</p>
<h2 id="wiring-two-dc-motors">Wiring Two DC Motors</h2>
<p>To control two motors, connect Motor B as well.</p>
<table>
<thead>
<tr>
<th>L298N</th>
<th>Connect To</th>
</tr>
</thead>
<tbody>
<tr>
<td>OUT3</td>
<td>Motor B wire 1</td>
</tr>
<tr>
<td>OUT4</td>
<td>Motor B wire 2</td>
</tr>
<tr>
<td>IN3</td>
<td>Raspberry Pi GPIO23</td>
</tr>
<tr>
<td>IN4</td>
<td>Raspberry Pi GPIO24</td>
</tr>
<tr>
<td>ENB</td>
<td>Raspberry Pi GPIO25</td>
</tr>
</tbody>
</table>
<p>Remove the ENB jumper if you want PWM speed control for Motor B.</p>
<h2 id="l298n-direction-logic">L298N Direction Logic</h2>
<p>The L298N controls motor direction by changing the logic levels on its input pins.</p>
<h3 id="motor-a-direction-table">Motor A Direction Table</h3>
<table>
<thead>
<tr>
<th>IN1</th>
<th>IN2</th>
<th>Motor A</th>
</tr>
</thead>
<tbody>
<tr>
<td>LOW</td>
<td>LOW</td>
<td>Stop</td>
</tr>
<tr>
<td>HIGH</td>
<td>LOW</td>
<td>Forward</td>
</tr>
<tr>
<td>LOW</td>
<td>HIGH</td>
<td>Reverse</td>
</tr>
<tr>
<td>HIGH</td>
<td>HIGH</td>
<td>Brake / Stop</td>
</tr>
</tbody>
</table>
<p>Motor B works the same way, using IN3 and IN4.</p>
<h2 id="install-gpio-zero">Install GPIO Zero</h2>
<p>On Raspberry Pi OS Bookworm, <a href="https://gpiozero.readthedocs.io/en/stable/">GPIO Zero</a> is the recommended beginner-friendly Python library for GPIO control.</p>
<p>Open a terminal and run:</p>
<pre><code class="lang-bash">sudo apt <span class="hljs-keyword">update</span>
sudo apt install <span class="hljs-keyword">python3</span>-gpiozero <span class="hljs-keyword">python3</span>-lgpio
</code></pre>
<p>GPIO Zero provides a simple way to control motors, LEDs, buttons, and PWM outputs from Python.</p>
<h2 id="python-code-for-one-motor">Python Code for One Motor</h2>
<p>Create a new file:</p>
<pre><code class="lang-bash"><span class="hljs-selector-tag">nano</span> <span class="hljs-selector-tag">l298n_one_motor</span><span class="hljs-selector-class">.py</span>
</code></pre>
<p>Paste this code:</p>
<pre><code class="lang-python">from gpiozero import Motor
from <span class="hljs-built_in">time</span> import <span class="hljs-built_in">sleep</span>


<span class="hljs-meta"># BCM GPIO numbering</span>
<span class="hljs-meta"># Motor A:</span>
<span class="hljs-meta"># IN1 = GPIO17</span>
<span class="hljs-meta"># IN2 = GPIO27</span>
<span class="hljs-meta"># ENA = GPIO22</span>


motor_a = Motor(forward=<span class="hljs-number">17</span>, backward=<span class="hljs-number">27</span>, <span class="hljs-keyword">enable</span>=<span class="hljs-number">22</span>, pwm=True)


try:
    <span class="hljs-keyword">print</span>(<span class="hljs-string">"Motor forward"</span>)
    motor_a.forward(speed=<span class="hljs-number">0.7</span>)
    <span class="hljs-built_in">sleep</span>(<span class="hljs-number">2</span>)


    <span class="hljs-keyword">print</span>(<span class="hljs-string">"Motor stop"</span>)
    motor_a.<span class="hljs-keyword">stop</span>()
    <span class="hljs-built_in">sleep</span>(<span class="hljs-number">1</span>)


    <span class="hljs-keyword">print</span>(<span class="hljs-string">"Motor reverse"</span>)
    motor_a.backward(speed=<span class="hljs-number">0.7</span>)
    <span class="hljs-built_in">sleep</span>(<span class="hljs-number">2</span>)


    <span class="hljs-keyword">print</span>(<span class="hljs-string">"Motor stop"</span>)
    motor_a.<span class="hljs-keyword">stop</span>()


except KeyboardInterrupt:
    motor_a.<span class="hljs-keyword">stop</span>()
    <span class="hljs-keyword">print</span>(<span class="hljs-string">"Stopped"</span>)
</code></pre>
<p>Save the file by pressing<em> CTRL + X</em>, then <em>Y</em>, then <em>Enter</em>.</p>
<p>Run the program:</p>
<pre><code class="lang-bash"><span class="hljs-keyword">python3</span> l298n_one_motor.<span class="hljs-keyword">py</span>
</code></pre>
<p>The motor should spin forward, stop, spin in reverse, and stop again.</p>
<p>If the motor spins in the opposite direction from what you expect, swap the motor wires connected to OUT1 and OUT2, or swap the GPIO assignments for forward and backward in the code.</p>
<h2 id="python-code-for-two-motors">Python Code for Two Motors</h2>
<p>For a simple robot car, you can use both L298N channels.</p>
<p>Create a new file:</p>
<pre><code class="lang-bash"><span class="hljs-selector-tag">nano</span> <span class="hljs-selector-tag">l298n_two_motors</span><span class="hljs-selector-class">.py</span>
</code></pre>
<p>Paste this code:</p>
<pre><code class="lang-python">from gpiozero <span class="hljs-built_in">import</span> Motor
from time <span class="hljs-built_in">import</span> sleep


<span class="hljs-comment"># Motor A</span>
<span class="hljs-comment"># IN1 = GPIO17</span>
<span class="hljs-comment"># IN2 = GPIO27</span>
<span class="hljs-comment"># ENA = GPIO22</span>
<span class="hljs-attr">left_motor</span> = Motor(<span class="hljs-attr">forward=17,</span> <span class="hljs-attr">backward=27,</span> <span class="hljs-attr">enable=22,</span> <span class="hljs-attr">pwm=True)</span>


<span class="hljs-comment"># Motor B</span>
<span class="hljs-comment"># IN3 = GPIO23</span>
<span class="hljs-comment"># IN4 = GPIO24</span>
<span class="hljs-comment"># ENB = GPIO25</span>
<span class="hljs-attr">right_motor</span> = Motor(<span class="hljs-attr">forward=23,</span> <span class="hljs-attr">backward=24,</span> <span class="hljs-attr">enable=25,</span> <span class="hljs-attr">pwm=True)</span>


def stop():
    left_motor.stop()
    right_motor.stop()


try:
    print(<span class="hljs-string">"Forward"</span>)
    left_motor.forward(<span class="hljs-attr">speed=0.7)</span>
    right_motor.forward(<span class="hljs-attr">speed=0.7)</span>
    sleep(<span class="hljs-number">2</span>)


    print(<span class="hljs-string">"Backward"</span>)
    left_motor.backward(<span class="hljs-attr">speed=0.7)</span>
    right_motor.backward(<span class="hljs-attr">speed=0.7)</span>
    sleep(<span class="hljs-number">2</span>)


    print(<span class="hljs-string">"Turn left"</span>)
    left_motor.backward(<span class="hljs-attr">speed=0.6)</span>
    right_motor.forward(<span class="hljs-attr">speed=0.6)</span>
    sleep(<span class="hljs-number">1</span>)


    print(<span class="hljs-string">"Turn right"</span>)
    left_motor.forward(<span class="hljs-attr">speed=0.6)</span>
    right_motor.backward(<span class="hljs-attr">speed=0.6)</span>
    sleep(<span class="hljs-number">1</span>)


    print(<span class="hljs-string">"Stop"</span>)
    stop()


except KeyboardInterrupt:
    stop()
    print(<span class="hljs-string">"Stopped"</span>)
</code></pre>
<p>Run it:</p>
<pre><code class="lang-bash"><span class="hljs-keyword">python3</span> l298n_two_motors.<span class="hljs-keyword">py</span>
</code></pre>
<p>This code moves both motors forward, backward, then turns left and right by spinning the motors in opposite directions.</p>
<h2 id="controlling-motor-speed">Controlling Motor Speed</h2>
<p>The <em>speed</em> value in GPIO Zero can be set from 0 to 1.</p>
<p>For example:</p>
<pre><code class="lang-python">motor_a.forward(<span class="hljs-attr">speed=0.3)</span>  <span class="hljs-comment"># slow</span>
motor_a.forward(<span class="hljs-attr">speed=0.7)</span>  <span class="hljs-comment"># medium</span>
motor_a.forward(<span class="hljs-attr">speed=1.0)</span>  <span class="hljs-comment"># full speed</span>
</code></pre>
<p>If the motor does not move at very low speed values, that is normal. DC motors need enough voltage and current to overcome friction and start rotating. Try increasing the speed value until the motor starts moving reliably.</p>
<h2 id="why-the-motor-supply-should-be-separate">Why the Motor Supply Should Be Separate</h2>
<p>A common beginner mistake is trying to power the motor from the Raspberry Pi 5. This is not recommended.</p>
<p>Motors draw much more current than GPIO pins can provide. They also create voltage dips and electrical noise when starting, stopping, or changing direction. These dips can cause the Raspberry Pi to reboot, freeze, or behave unpredictably.</p>
<p>Use a separate battery pack or DC power supply for the motor side of the L298N. Then connect the grounds:</p>
<pre><code class="lang-text"><span class="hljs-comment">Raspberry</span> <span class="hljs-comment">Pi</span> <span class="hljs-comment">GND</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span> <span class="hljs-comment">L298N</span> <span class="hljs-comment">GND</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span> <span class="hljs-comment">Battery</span> <span class="hljs-comment">negative</span>
</code></pre>
<p>This common ground gives the GPIO signals a shared voltage reference.</p>
<h2 id="can-the-raspberry-pi-5-gpio-control-the-l298n-directly-">Can the Raspberry Pi 5 GPIO Control the L298N Directly?</h2>
<p>Yes. The Raspberry Pi 5 uses 3.3V GPIO logic, while the L298N accepts TTL-style logic input levels. In typical use, a Raspberry Pi HIGH signal is enough for the L298N input pins.</p>
<p>However, never feed 5V signals into the Raspberry Pi 5 GPIO pins. The Raspberry Pi GPIO pins are not 5V tolerant. The control direction should be from the Raspberry Pi GPIO pins to the L298N inputs, not the other way around.</p>
<h2 id="troubleshooting">Troubleshooting</h2>
<h3 id="motor-does-not-spin">Motor does not spin</h3>
<p>Check the following:</p>
<ul>
<li>Is the external motor power supply connected?</li>
<li>Is the L298N GND connected to Raspberry Pi GND?</li>
<li>Are the motor wires connected to OUT1 and OUT2?</li>
<li>Is the ENA jumper removed if you are using GPIO PWM?</li>
<li>Is the Python code using the correct BCM GPIO numbers?</li>
<li>Is the motor power supply strong enough for the motor?</li>
</ul>
<h3 id="motor-only-runs-at-full-speed">Motor only runs at full speed</h3>
<p>The ENA jumper may still be installed. Remove the ENA jumper and connect ENA to the Raspberry Pi PWM GPIO pin used in the code.</p>
<h3 id="raspberry-pi-reboots-when-motor-starts">Raspberry Pi reboots when motor starts</h3>
<p>The motor may be pulling too much current or causing a voltage drop. Use a separate motor power supply and do not power the motor from the Raspberry Pi. Also make sure your Raspberry Pi 5 power supply is strong enough.</p>
<h3 id="motor-direction-is-reversed">Motor direction is reversed</h3>
<p>Swap the two motor wires, or swap the forward and backward GPIO pins in the Python code.</p>
<h3 id="python-gpio-code-does-not-work-on-raspberry-pi-5">Python GPIO code does not work on Raspberry Pi 5</h3>
<p>Many older Raspberry Pi tutorials use <em>RPi.GPIO</em>. On Raspberry Pi 5, it is better to use GPIO Zero with a compatible backend such as <em>lgpio</em>. Install the needed packages using:</p>
<pre><code class="lang-bash">sudo apt install <span class="hljs-keyword">python3</span>-gpiozero <span class="hljs-keyword">python3</span>-lgpio
</code></pre>
<h2 id="final-thoughts">Final Thoughts</h2>
<p>Connecting an L298N to a Raspberry Pi 5 is a useful starting point for robot cars, motorized mechanisms, pumps, fans, and other DC motor projects. The most important thing to remember is that the Raspberry Pi controls the L298N with GPIO signals, but the motor itself must be powered separately.</p>
<p>Once you have the basic wiring working, you can expand this project by adding buttons, distance sensors, line sensors, camera-based object detection, or web-based motor control from a Raspberry Pi 5 dashboard.</p>
<p>The post <a href="https://www.teachmemicro.com/connect-l298n-to-raspberry-pi-5-control-dc-motors-with-python/">Connect L298N to Raspberry Pi 5: Control DC Motors with Python</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How I Built an Alexa-Like Voice Assistant Using Raspberry Pi 5 and an LLM</title>
		<link>https://www.teachmemicro.com/how-i-built-an-alexa-like-voice-assistant-using-raspberry-pi-5-and-an-llm/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=how-i-built-an-alexa-like-voice-assistant-using-raspberry-pi-5-and-an-llm</link>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Tue, 09 Dec 2025 10:27:04 +0000</pubDate>
				<category><![CDATA[Raspberry Pi Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=10157</guid>

					<description><![CDATA[<p>In this tutorial, I’m going to walk you through how I built my own voice assistant—similar to Alexa or Google Home—using only a Raspberry Pi 5, a USB microphone, a speaker, and an LLM with text-to-speech (TTS) and speech-to-text (STT) support. By the end of this guide, you’ll have a Raspberry-Pi-powered device that: Listens for &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/how-i-built-an-alexa-like-voice-assistant-using-raspberry-pi-5-and-an-llm/">How I Built an Alexa-Like Voice Assistant Using Raspberry Pi 5 and an LLM</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>In this tutorial, I’m going to walk you through how I built my own <strong>voice assistant</strong>—similar to Alexa or Google Home—using only a <strong>Raspberry Pi 5</strong>, a USB microphone, a speaker, and an LLM with text-to-speech (TTS) and speech-to-text (STT) support.</p>
<p>By the end of this guide, you’ll have a Raspberry-Pi-powered device that:</p>
<ul>
<li>Listens for your voice</li>
<li>Converts your speech into text</li>
<li>Sends that text to an LLM</li>
<li>Converts the LLM’s response into natural speech</li>
<li>Speaks it aloud</li>
</ul>
<p>It feels surprisingly close to a commercial smart assistant—just without the Amazon ecosystem behind it.</p>
<hr />
<h3><strong>Why I Chose Raspberry Pi 5 for My Voice Assistant</strong></h3>
<p>The Raspberry Pi 5 is powerful enough to handle:</p>
<ul>
<li>Live audio recording</li>
<li>Streaming data to an LLM</li>
<li>Playing back voice responses</li>
<li>Handling wake-word models like Porcupine</li>
</ul>
<p>Its quad-core CPU and USB 3.0 bandwidth make it perfect for a responsive, low-latency voice assistant.</p>
<hr />
<h3><strong>What You Need</strong></h3>
<h4><strong>Hardware</strong></h4>
<ul>
<li>Raspberry Pi 5 (4GB or 8GB recommended)</li>
<li>USB microphone (Blue Snowball, Fifine, or any generic USB mic)</li>
<li>Speakers or a USB sound card with speakers</li>
<li>Raspberry Pi OS (Bookworm), fully updated</li>
<li>Internet connection (Wi-Fi or Ethernet)</li>
</ul>
<h4><strong>Software &amp; APIs</strong></h4>
<ul>
<li>Python 3.11+ (pre-installed on Pi OS)</li>
<li>OpenAI Realtime API (or any LLM with STT + TTS endpoints)</li>
<li>Picovoice Porcupine (optional wake-word detection)</li>
<li>Python libraries: <em>sounddevice</em>, <em>pyaudio</em>, <em>websockets</em>, <em>requests</em></li>
</ul>
<hr />
<h3><strong>Step 1 — Updating My Raspberry Pi 5</strong></h3>
<p>I always begin by updating the Pi:</p>
<div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary">
<div class="sticky top-9">
<div class="absolute end-0 bottom-0 flex h-9 items-center pe-2">
<div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div>
</div>
</div>
<div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-bash">sudo apt update &amp;&amp; sudo apt upgrade -y<br />
</code></div>
</div>
<p>&nbsp;</p>
<p>Then install required audio tools:</p>
<div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary">
<div class="sticky top-9">
<div class="absolute end-0 bottom-0 flex h-9 items-center pe-2">
<div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div>
</div>
</div>
<div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-bash">sudo apt install python3-pip portaudio19-dev ffmpeg -y<br />
</code></div>
</div>
<hr />
<h3><strong>Step 2 — Setting Up My USB Microphone</strong></h3>
<p>I plugged in my mic and checked if the Pi detected it:</p>
<div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary">
<div class="sticky top-9">
<div class="absolute end-0 bottom-0 flex h-9 items-center pe-2">
<div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div>
</div>
</div>
<div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-bash">arecord -l<br />
</code></div>
</div>
<p>&nbsp;</p>
<p>To test recording:</p>
<div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary">
<div class="sticky top-9">
<div class="absolute end-0 bottom-0 flex h-9 items-center pe-2">
<div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div>
</div>
</div>
<div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-bash">arecord --format=S16_LE --duration=3 --rate=16000 --file-type=wav test.wav<br />
aplay test.wav<br />
</code></div>
</div>
<p>&nbsp;</p>
<p>If I heard my voice, the microphone and speaker were good to go.</p>
<hr />
<h3><strong>Step 3 — Installing Python Libraries</strong></h3>
<p>I installed everything I needed for recording audio, playing audio, and talking to the LLM:</p>
<div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary">
<div class="sticky top-9">
<div class="absolute end-0 bottom-0 flex h-9 items-center pe-2">
<div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div>
</div>
</div>
<div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-bash">pip3 install sounddevice pyaudio numpy websockets requests<br />
</code></div>
</div>
<p>&nbsp;</p>
<p>If I planned to add a wake word:</p>
<div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary">
<div class="sticky top-9">
<div class="absolute end-0 bottom-0 flex h-9 items-center pe-2">
<div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div>
</div>
</div>
<div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-bash">pip3 install pvporcupine<br />
</code></div>
</div>
<hr />
<h3><strong>Step 4 — Setting Up the LLM (OpenAI Realtime)</strong></h3>
<p>To get real-time conversational audio, I used the OpenAI Realtime WebSocket endpoint.<br />
This gives me:</p>
<ul>
<li>Streaming speech-to-text</li>
<li>Streaming conversation</li>
<li>Streaming text-to-speech</li>
</ul>
<p>All in one pipeline.</p>
<p>I simply created an API key in my OpenAI account and stored it:</p>
<div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary">
<div class="sticky top-9">
<div class="absolute end-0 bottom-0 flex h-9 items-center pe-2">
<div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div>
</div>
</div>
<div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-bash">nano ~/.openai_key<br />
</code></div>
</div>
<hr />
<h3><strong>Step 5 — Creating My Simple Push-to-Talk Voice Assistant (MVP)</strong></h3>
<p>Before getting fancy with wake words, I built a <strong>press-Enter-to-talk</strong> version.</p>
<p>This script:</p>
<ol>
<li>Records my voice</li>
<li>Sends audio to Whisper STT</li>
<li>Sends text to an LLM</li>
<li>Converts reply text to speech</li>
<li>Plays the audio</li>
</ol>
<p>Create the file:</p>
<div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary">
<div class="sticky top-9">
<div class="absolute end-0 bottom-0 flex h-9 items-center pe-2">
<div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div>
</div>
</div>
<div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-bash">nano assistant.py<br />
</code></div>
</div>
<p>&nbsp;</p>
<p>Paste this:</p>
<div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary">
<div class="sticky top-9">
<div class="absolute end-0 bottom-0 flex h-9 items-center pe-2">
<div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div>
</div>
</div>
<div class="overflow-y-auto p-4" dir="ltr">
<pre><code class="whitespace-pre! language-python">import sounddevice as sd
import numpy as np
import requests
import json
import subprocess
import tempfile

OPENAI_KEY = open("/home/pi/.openai_key").read().strip()

# Record function
def record_audio(duration=4, fs=16000):
    print("&#x1f399; Speak now...")
    audio = sd.rec(int(duration * fs), samplerate=fs, channels=1, dtype='int16')
    sd.wait()
    print("&#x23f9; Recording stopped")
    return audio.tobytes()

# Send audio -&gt; STT
def speech_to_text(audio_bytes):
    response = requests.post(
        "https://api.openai.com/v1/audio/transcriptions",
        headers={"Authorization": f"Bearer {OPENAI_KEY}"},
        files={"file": ("speech.wav", audio_bytes, "audio/wav")},
        data={"model": "gpt-4o-mini-transcribe"}
    )

    return response.json()["text"]

# LLM call
def ask_llm(text):
    payload = {
        "model": "gpt-4o-mini",
        "messages": [{"role": "user", "content": text}]
    }

    response = requests.post(
        "https://api.openai.com/v1/chat/completions",
        headers={
            "Authorization": f"Bearer {OPENAI_KEY}",
            "Content-Type": "application/json"
        },
        data=json.dumps(payload)
    )

    return response.json()["choices"][0]["message"]["content"]

# Text-to-speech
def tts(text):
    response = requests.post(
        "https://api.openai.com/v1/audio/speech",
        headers={
            "Authorization": f"Bearer {OPENAI_KEY}"
        },
        json={
            "model": "gpt-4o-mini-tts",
            "voice": "alloy",
            "input": text
        }
    )

    return response.content

# Play sound
def play_audio(audio_bytes):
    with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as f:
        f.write(audio_bytes)
        f.flush()
        subprocess.run(["ffplay", "-nodisp", "-autoexit", f.name])

# Main loop
while True:
    input("\n&#x1f449; Press Enter to talk...")
    audio = record_audio()
    text = speech_to_text(audio)
    print("&#x1f5e3; You said:", text)

    reply = ask_llm(text)
    print("&#x1f916; Assistant:", reply)

    audio_reply = tts(reply)
    play_audio(audio_reply)
</code></pre>
</div>
</div>
<p>Run it:</p>
<div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary">
<div class="sticky top-9">
<div class="absolute end-0 bottom-0 flex h-9 items-center pe-2">
<div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div>
</div>
</div>
<div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-bash">python3 assistant.py<br />
</code></div>
</div>
<p>&nbsp;</p>
<p>I now had a functional voice AI that:</p>
<ul>
<li>Listens when I press Enter</li>
<li>Understands what I say</li>
<li>Responds using natural speech</li>
</ul>
<hr />
<h3><strong>Step 6 — Adding Wake-Word Detection (Optional Upgrade)</strong></h3>
<p>To get that Alexa-like "always listening" experience, I added <strong>Porcupine</strong>.</p>
<p>Install the engine:</p>
<div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary">
<div class="sticky top-9">
<div class="absolute end-0 bottom-0 flex h-9 items-center pe-2">
<div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div>
</div>
</div>
<div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-bash">pip3 install pvporcupine<br />
</code></div>
</div>
<p>&nbsp;</p>
<p>I then created a second script, <pre><code class="language-cpp">wake_assistant.py</code></pre>, that:</p>
<ul>
<li>Continuously listens for the wake word (e.g., “Jarvis”)</li>
<li>When triggered, runs the same record → STT → LLM → TTS pipeline</li>
</ul>
<p>(Want me to include the full wake-word script? I can add it.)</p>
<hr />
<h3><strong>Step 7 — (Optional) Using OpenAI Realtime for Streaming Audio</strong></h3>
<p>For true Alexa behavior—interrupting, barge-in, low latency—I can give you the Realtime WebSocket version too. It allows:</p>
<ul>
<li>Speaking to the Pi without waiting for a stop signal</li>
<li>The LLM to start responding while I'm still talking</li>
<li>Beautifully fluid conversation</li>
</ul>
<p>Just tell me if you want the <strong>full Realtime streaming version</strong>.</p>
<hr />
<h3><strong>Step 8 — Autostarting My Voice Assistant on Boot</strong></h3>
<p>I made my AI device boot straight into “always listening” mode using systemd:</p>
<div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary">
<div class="sticky top-9">
<div class="absolute end-0 bottom-0 flex h-9 items-center pe-2">
<div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div>
</div>
</div>
<div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-bash">sudo nano /etc/systemd/system/voice.service<br />
</code></div>
</div>
<p>&nbsp;</p>
<p>Service file:</p>
<div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary">
<div class="sticky top-9">
<div class="absolute end-0 bottom-0 flex h-9 items-center pe-2">
<div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div>
</div>
</div>
<div class="overflow-y-auto p-4" dir="ltr">
<pre><code class="whitespace-pre! language-ini">[Unit]
Description=Raspberry Pi Voice Assistant
After=network.target

[Service]
ExecStart=/usr/bin/python3 /home/pi/assistant.py
WorkingDirectory=/home/pi
Restart=always
User=pi

[Install]
WantedBy=multi-user.target
</code></pre>
</div>
</div>
<p>&nbsp;</p>
<p>Enable it:</p>
<div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary">
<div class="sticky top-9">
<div class="absolute end-0 bottom-0 flex h-9 items-center pe-2">
<div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div>
</div>
</div>
<div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-bash">sudo systemctl enable voice.service<br />
sudo systemctl start voice.service<br />
</code></div>
</div>
<p>Now my Pi automatically behaves like a smart speaker.</p>
<hr />
<h3><strong>Final Thoughts</strong></h3>
<p>Building my own Alexa-style voice assistant on the Raspberry Pi 5 turned out to be:</p>
<ul>
<li>Easier than expected</li>
<li>Surprisingly powerful</li>
<li>Fully customizable</li>
<li>Not locked into any ecosystem</li>
</ul>
<p>I can choose any wake word, any personality, any LLM, and I fully own the device.</p>
<p>If you want to extend this project, here are ideas:</p>
<ul>
<li>Add home automation (MQTT, Home Assistant)</li>
<li>Display responses on a small touchscreen</li>
<li>Allow multi-room audio</li>
<li>Build a custom housing with 3D printing</li>
<li>Add LED rings like Alexa Echo</li>
</ul>
<p>The post <a href="https://www.teachmemicro.com/how-i-built-an-alexa-like-voice-assistant-using-raspberry-pi-5-and-an-llm/">How I Built an Alexa-Like Voice Assistant Using Raspberry Pi 5 and an LLM</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Using Raspberry Pi Pico as an HID to Control Mouse Movements and Keyboard Strokes</title>
		<link>https://www.teachmemicro.com/using-raspberry-pi-pico-as-an-hid-to-control-mouse-movements-and-keyboard-strokes/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-raspberry-pi-pico-as-an-hid-to-control-mouse-movements-and-keyboard-strokes</link>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Wed, 02 Apr 2025 21:46:45 +0000</pubDate>
				<category><![CDATA[Raspberry Pi Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=8416</guid>

					<description><![CDATA[<p>The Raspberry Pi Pico, a microcontroller based on the RP2040 chip, can emulate a Human Interface Device (HID) like a keyboard or mouse. This tutorial will guide you through setting up your Raspberry Pi Pico as an HID device to send keyboard strokes and control mouse movements. Prerequisites Hardware Software Flash MicroPython Firmware with HID &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/using-raspberry-pi-pico-as-an-hid-to-control-mouse-movements-and-keyboard-strokes/">Using Raspberry Pi Pico as an HID to Control Mouse Movements and Keyboard Strokes</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><span>The Raspberry Pi Pico, a microcontroller based on the RP2040 chip, can emulate a Human Interface Device (HID) like a keyboard or mouse. This tutorial will guide you through setting up your Raspberry Pi Pico as an HID device to send keyboard strokes and control mouse movements.</span></p>
<p><span id="more-8416"></span></p>
<h3><strong>Prerequisites</strong></h3>
<h4><strong>Hardware</strong></h4>
<div class="checklist tie-list-shortcode">
<ul>
<li><span>Raspberry Pi Pico</span></li>
<li><span>USB cable (for power and data transfer)</span></li>
<li><span>Computer running Windows, macOS, or Linux</span></li>
</ul>
</div>
<h4><span>Software</span></h4>
<div class="checklist tie-list-shortcode">
<ul>
<li><span>MicroPython firmware with HID support</span></li>
<li><span>Thonny IDE (or another MicroPython-compatible IDE)</span></li>
</ul>
</div>
<h3></h3>
<h3><span>Flash MicroPython Firmware with HID Support</span></h3>
<p><span>By default, the official MicroPython firmware does not include HID functionality. We will use a custom MicroPython firmware that supports HID.</span></p>
<ol data-spread="false" start="1">
<li><span>Download the MicroPython firmware with HID support from a trusted source (e.g., </span><a href="https://github.com/adafruit/circuitpython" disabled="disabled"><span>https://github.com/adafruit/circuitpython</span></a><span>).</span></li>
<li><span>Put the Pico in bootloader mode by holding the </span><span><strong>BOOTSEL</strong></span><span> button while plugging it into your computer via USB.</span></li>
<li><span>Drag and drop the downloaded <em>.uf2</em></span><span> file onto the mounted </span><span><strong>RPI-RP2</strong></span><span> drive.</span></li>
</ol>
<p><span>Once the Pico restarts, it is ready to run MicroPython.</span></p>
<h3></h3>
<h3><strong>Install Required Libraries</strong></h3>
<p><span>To use the HID functions, you need to install the <em>usb_hid</em></span><span> library.</span></p>
<ol data-spread="false" start="1">
<li><span>Open Thonny IDE.</span></li>
<li><span>Connect your Pico and open a new script.</span></li>
<li><span>Import the necessary libraries:</span></li>
</ol>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-python" data-lang="Python"><pre><code class="language-cpp">&lt;span&gt;import time
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
from adafruit_hid.mouse import Mouse&lt;/span&gt;</code></pre></pre>
</div>
<h3></h3>
<h3><strong>Emulating a Keyboard</strong></h3>
<p><span>The following code sends a "Hello, World!" message when the Pico is connected:</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-python" data-lang="Python"><pre><code class="language-cpp">&lt;span&gt;kbd = Keyboard(usb_hid.devices)
time.sleep(1)  # Allow time for HID initialization

kbd.send(Keycode.H, Keycode.E, Keycode.L, Keycode.L, Keycode.O, Keycode.COMMA, Keycode.SPACE,
         Keycode.W, Keycode.O, Keycode.R, Keycode.L, Keycode.D, Keycode.EXCLAMATION)&lt;/span&gt;</code></pre></pre>
</div>
<p><span>This script mimics pressing the keys HELLO, WORLD!</span><span> on a standard keyboard.</span></p>
<h3></h3>
<h3><strong>Controlling Mouse Movements</strong></h3>
<p><span>To control the mouse, use the <em>Mouse</em></span><span> class:</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-python" data-lang="Python"><pre><code class="language-cpp">&lt;span&gt;mouse = Mouse(usb_hid.devices)
time.sleep(1)

# Move the mouse to the right
mouse.move(x=50)
time.sleep(1)

# Move the mouse down
mouse.move(y=50)
time.sleep(1)

# Perform a left-click
mouse.click(Mouse.LEFT_BUTTON)&lt;/span&gt;</code></pre></pre>
</div>
<p><span>This code moves the mouse cursor and performs a left-click action.</span></p>
<p>&nbsp;</p>
<h3><strong>Automating Keyboard and Mouse Actions</strong></h3>
<p><span>You can create automation scripts, such as making the Pico send keystrokes when a button is pressed. Here’s an example:</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-python" data-lang="Python"><pre><code class="language-cpp">&lt;span&gt;import machine
button = machine.Pin(2, machine.Pin.IN, machine.Pin.PULL_UP)

while True:
    if not button.value():  # When button is pressed
        kbd.send(Keycode.A)  # Simulate pressing &#039;A&#039;
        time.sleep(0.5)  # Prevent spamming&lt;/span&gt;</code></pre></pre>
</div>
<h3></h3>
<h3><strong>Conclusion</strong></h3>
<p><span>With these steps, you can turn your Raspberry Pi Pico into a powerful HID device. You can use it for automation, accessibility solutions, or even creative input devices. Experiment with different key sequences and mouse movements to build your custom HID solutions!</span></p>
<p>The post <a href="https://www.teachmemicro.com/using-raspberry-pi-pico-as-an-hid-to-control-mouse-movements-and-keyboard-strokes/">Using Raspberry Pi Pico as an HID to Control Mouse Movements and Keyboard Strokes</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How to Turn a Raspberry Pi into a WiFi Repeater/Extender</title>
		<link>https://www.teachmemicro.com/how-to-turn-a-raspberry-pi-into-a-wifi-repeater-extender/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=how-to-turn-a-raspberry-pi-into-a-wifi-repeater-extender</link>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Fri, 31 Jan 2025 00:33:53 +0000</pubDate>
				<category><![CDATA[Raspberry Pi Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=8128</guid>

					<description><![CDATA[<p>In this tutorial, we’ll walk you through the steps to turn your Raspberry Pi into a WiFi repeater or extender. Each step includes explanations to help you understand why the commands and configurations are necessary. Step 1: Set Up Raspberry Pi OS Before turning your Raspberry Pi into a WiFi repeater, you need a working &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/how-to-turn-a-raspberry-pi-into-a-wifi-repeater-extender/">How to Turn a Raspberry Pi into a WiFi Repeater/Extender</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><span style="font-weight: 400;">In this tutorial, we’ll walk you through the steps to turn your Raspberry Pi into a <a href="https://wiboosters.online/what-is-a-wi-fi-extender-and-how-does-it-work/">WiFi repeater</a> or extender. Each step includes explanations to help you understand why the commands and configurations are necessary.</span></p>
<p><span id="more-8128"></span></p>
<h3><b>Step 1: Set Up Raspberry Pi OS</b></h3>
<p><span style="font-weight: 400;">Before turning your Raspberry Pi into a WiFi repeater, you need a working operating system. Raspberry Pi OS is lightweight and optimized for the Pi, making it ideal for this project.</span></p>
<h4><strong>Install Raspberry Pi OS:</strong></h4>
<p><span style="font-weight: 400;">Download the latest Raspberry Pi OS Lite (or Desktop) from the <a href="https://www.raspberrypi.com/software/">official website</a>.</span></p>
<p><span style="font-weight: 400;">Flash the OS to your microSD card using a tool like Raspberry Pi Imager or Balena Etcher.</span></p>
<h4><strong>Enable SSH:</strong></h4>
<p><span style="font-weight: 400;">SSH allows you to remotely access your Raspberry Pi’s terminal. This is especially useful if you’re running the Lite version (headless) without a graphical interface.</span></p>
<p><span style="font-weight: 400;">Create an empty file named ssh (no extension) in the boot partition of the microSD card to enable SSH.</span></p>
<h4><strong>Boot the Raspberry Pi:</strong></h4>
<p><span style="font-weight: 400;">Insert the microSD card into the Raspberry Pi, connect it to power, and boot it up.</span></p>
<h4><strong>Connect to the Raspberry Pi:</strong></h4>
<p><span style="font-weight: 400;">Use SSH to connect to your Raspberry Pi. If you’re using the desktop version, you can also use the terminal directly.</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">ssh pi@raspberrypi.local</code></pre></pre>
</div>
<p><span style="font-weight: 400;">The default password is <em>raspberry.</em></span></p>
<h4><strong>Update the system:</strong></h4>
<p><span style="font-weight: 400;">Updating the system ensures that you have the latest security patches and software updates.</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo apt update
sudo apt upgrade -y</code></pre></pre>
</div>
<h3><b>Step 2: Install Required Software</b></h3>
<p><span style="font-weight: 400;"> </span><span style="font-weight: 400;">To create a <a href="https://wiboosters.online/how-to-use-a-wi-fi-repeater-as-an-access-point/">WiFi repeater</a>, you need software to manage the access point (<em>hostapd</em>) and handle DHCP assignments (<em>dnsmasq</em>).</span></p>
<h4><strong>Install the necessary packages:</strong></h4>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo apt install hostapd dnsmasq -y</code></pre><pre><code class="language-cpp"></code></pre></pre>
</div>
<p><span style="font-weight: 400;">hostapd: Creates a wireless access point.</span></p>
<p><span style="font-weight: 400;">dnsmasq: Manages DHCP and DNS services for the devices connecting to your repeater.</span></p>
<h3><strong>Stop the services for now:</strong></h3>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo systemctl stop hostapd
sudo systemctl stop dnsmasq</code></pre></pre>
</div>
<p><span style="font-weight: 400;">We stop the services temporarily to configure them properly before starting them again.</span></p>
<h3><b>Step 3: Configure the WiFi Interfaces</b></h3>
<p><span style="font-weight: 400;"> </span><span style="font-weight: 400;">The Raspberry Pi needs to know how to handle its WiFi interfaces. We configure one interface (<em>wlan0</em>) to act as the access point and another (wlan1, if available) to connect to the main WiFi network.</span></p>
<h3><strong>Identify your WiFi interfaces:</strong></h3>
<p><span style="font-weight: 400;">Run the following command to see your wireless interfaces:</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash">iwconfig<pre><code class="language-cpp"></code></pre><pre><code class="language-cpp"></code></pre></pre>
</div>
<p><span style="font-weight: 400;">Typically, the built-in WiFi interface is named wlan0.</span></p>
<h3><strong>Edit the network interfaces file:</strong></h3>
<p><span style="font-weight: 400;">Open the network interfaces configuration file:</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo nano /etc/network/interfaces</code></pre></pre>
</div>
<p>Add the following lines to configure wlan0:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">auto wlan0
iface wlan0 inet static
    address 192.168.42.1
    netmask 255.255.255.0</code></pre></pre>
</div>
<p><span style="font-weight: 400;">This assigns a static IP address to wlan0, which will act as the access point.</span></p>
<p><span style="font-weight: 400;">Save and exit (Ctrl+X, then Y, then Enter).</span></p>
<p>&nbsp;</p>
<h3><b>Step 4: Configure hostapd</b></h3>
<p><span style="font-weight: 400;">hostapd is responsible for creating the WiFi access point. We configure it to broadcast a WiFi network with a specific SSID and password.</span></p>
<h3><strong>Create a configuration file for hostapd:</strong></h3>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo nano /etc/hostapd/hostapd.conf</code></pre></pre>
</div>
<p><span style="font-weight: 400;">Add the following configuration (adjust the SSID and password as needed):</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">interface=wlan0
driver=nl80211
ssid=MyRPiRepeater
hw_mode=g
channel=6
wmm_enabled=0
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=MySecurePassword
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP</code></pre></pre>
</div>
<p>interface=wlan0: Specifies the WiFi interface to use.</p>
<p><span style="font-weight: 400;">ssid=MyRPiRepeater: The name of the WiFi network.</span></p>
<p><span style="font-weight: 400;">wpa_passphrase=MySecurePassword: The password for the WiFi network.</span></p>
<h3><strong>Point hostapd to the configuration file:</strong></h3>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo nano /etc/default/hostapd</code></pre></pre>
</div>
<p><span style="font-weight: 400;">Find the line #DAEMON_CONF="" and replace it with:</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">DAEMON_CONF=&quot;/etc/hostapd/hostapd.conf&quot;</code></pre></pre>
</div>
<p><span style="font-weight: 400;">This tells hostapd where to find its configuration file.</span></p>
<p>&nbsp;</p>
<h3><b>Step 5: Configure dnsmasq</b></h3>
<p><span style="font-weight: 400;"> </span><span style="font-weight: 400;">dnsmasq assigns IP addresses to devices connecting to your repeater and handles DNS requests.</span></p>
<p><span style="font-weight: 400;">Edit the dnsmasq configuration file:</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo nano /etc/dnsmasq.conf</code></pre></pre>
</div>
<p><span style="font-weight: 400;">Add the following lines:</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">interface=wlan0
dhcp-range=192.168.42.10,192.168.42.100,255.255.255.0,24h</code></pre></pre>
</div>
<p><span style="font-weight: 400;">interface=wlan0: Specifies the interface to manage.</span></p>
<p><span style="font-weight: 400;">dhcp-range: Defines the range of IP addresses to assign to connected devices.</span></p>
<p>&nbsp;</p>
<h3><b>Step 6: Enable IP Forwarding</b></h3>
<p><span style="font-weight: 400;">IP forwarding allows the Raspberry Pi to route traffic between the WiFi repeater and the main network.</span></p>
<p><span style="font-weight: 400;">Enable IP forwarding by editing the <em>sysctl.conf</em> file:</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo nano /etc/sysctl.conf</code></pre></pre>
</div>
<p>Uncomment or add the following line:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">net.ipv4.ip_forward=1</code></pre></pre>
</div>
<p><span style="font-weight: 400;">This enables IP forwarding at the kernel level.</span></p>
<p><span style="font-weight: 400;">Apply the changes:</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo sh -c &quot;echo 1 &gt; /proc/sys/net/ipv4/ip_forward&quot;</code></pre></pre>
</div>
<p>Set up NAT (Network Address Translation):</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo iptables -t nat -A POSTROUTING -o wlan1 -j MASQUERADE
sudo sh -c &quot;iptables-save &gt; /etc/iptables.ipv4.nat&quot;</code></pre></pre>
</div>
<p><span style="font-weight: 400;">NAT allows devices connected to the repeater to access the internet through the main network.</span></p>
<h3><strong>Make the iptables rule persistent:</strong></h3>
<p><span style="font-weight: 400;">Edit the rc.local file:</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo nano /etc/rc.local</code></pre></pre>
</div>
<p><span style="font-weight: 400;">Add the following line before exit 0:</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">iptables-restore &lt; /etc/iptables.ipv4.nat</code></pre></pre>
</div>
<p><span style="font-weight: 400;">This ensures the NAT rule is applied on boot.</span></p>
<p>&nbsp;</p>
<h3><b>Step 7: Start the Services</b></h3>
<p><span style="font-weight: 400;"> </span><span style="font-weight: 400;">Starting hostapd and dnsmasq activates the WiFi repeater functionality.</span></p>
<h4><strong>Start and enable hostapd and dnsmasq:</strong></h4>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo systemctl unmask hostapd
sudo systemctl enable hostapd
sudo systemctl start hostapd
sudo systemctl start dnsmasq</code></pre></pre>
</div>
<h4><strong>Reboot the Raspberry Pi:</strong></h4>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo reboot</code></pre></pre>
</div>
<h3><b>Step 8: Connect to Your WiFi Repeater</b></h3>
<p><span style="font-weight: 400;"> </span><span style="font-weight: 400;">Once the Raspberry Pi is set up, you need to connect your devices to the new WiFi network.</span></p>
<p><span style="font-weight: 400;">After the Raspberry Pi reboots, it will act as a WiFi repeater.</span></p>
<p><span style="font-weight: 400;">Search for the SSID you configured (e.g., MyRPiRepeater) on your devices and connect using the password you set.</span></p>
<h4><strong>Optional: Automate the Process</strong></h4>
<p><span style="font-weight: 400;">If you want the Raspberry Pi to automatically connect to your main WiFi network and extend it, you can configure wpa_supplicant.</span></p>
<p><span style="font-weight: 400;">Edit the wpa_supplicant configuration:</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo nano /etc/wpa_supplicant/wpa_supplicant.conf</code></pre></pre>
</div>
<p><span style="font-weight: 400;">Add the following lines (replace YourMainSSID and YourMainPassword with your network details):</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">network={
    ssid=&quot;YourMainSSID&quot;
    psk=&quot;YourMainPassword&quot;
}</code></pre></pre>
</div>
<p>Reboot the Raspberry Pi to apply the changes.</p>
<h3><b>Conclusion</b></h3>
<p><span style="font-weight: 400;">By following these steps, you’ve turned your Raspberry Pi into a WiFi repeater/extender. Each step is designed to configure the necessary components (access point, DHCP, IP forwarding, etc.) to ensure seamless operation. If you encounter issues, double-check the configuration files and ensure all services are running properly. Enjoy your extended WiFi coverage!</span></p>
<p>The post <a href="https://www.teachmemicro.com/how-to-turn-a-raspberry-pi-into-a-wifi-repeater-extender/">How to Turn a Raspberry Pi into a WiFi Repeater/Extender</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How to Use a Rotary Encoder with Raspberry Pi</title>
		<link>https://www.teachmemicro.com/how-to-use-a-rotary-encoder-with-raspberry-pi/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=how-to-use-a-rotary-encoder-with-raspberry-pi</link>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Thu, 09 Jan 2025 01:00:56 +0000</pubDate>
				<category><![CDATA[Raspberry Pi Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=7658</guid>

					<description><![CDATA[<p>A rotary encoder is a versatile device often used as an input knob to control volume, scroll menus, or adjust values. It can detect rotation direction and the amount of rotation, making it perfect for Raspberry Pi projects. What You'll Need Step 1: Understand the Rotary Encoder A rotary encoder typically has: Two outputs (A &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/how-to-use-a-rotary-encoder-with-raspberry-pi/">How to Use a Rotary Encoder with Raspberry Pi</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><span style="font-weight: 400;">A </span><b>rotary encoder</b><span style="font-weight: 400;"> is a versatile device often used as an input knob to control volume, scroll menus, or adjust values. It can detect rotation direction and the amount of rotation, making it perfect for Raspberry Pi projects.</span></p>
<p><span id="more-7658"></span></p>
<h3><b>What You'll Need</b></h3>
<div class="checklist tie-list-shortcode">
<ul>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Raspberry Pi (any model with GPIO pins)</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Rotary encoder (with a push button if possible)</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Breadboard</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Jumper wires</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Python (pre-installed on Raspberry Pi)</span></li>
</ul>
</div>
<h4><b>Step 1: Understand the Rotary Encoder</b></h4>
<p><span style="font-weight: 400;">A rotary encoder typically has:</span></p>
<ol>
<li style="font-weight: 400;" aria-level="1"><b>Two outputs (A and B)</b><span style="font-weight: 400;"> that produce pulses as the encoder shaft rotates. The phase difference between these pulses determines the rotation direction.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>A push-button (optional)</b><span style="font-weight: 400;"> that can act as an additional input.</span></li>
</ol>
<h4><b>Pinout Example (common encoders):</b></h4>
<ul>
<li style="font-weight: 400;" aria-level="1"><b>CLK (A):</b><span style="font-weight: 400;"> Clock pulse output</span></li>
<li style="font-weight: 400;" aria-level="1"><b>DT (B):</b><span style="font-weight: 400;"> Direction pulse output</span></li>
<li style="font-weight: 400;" aria-level="1"><b>SW:</b><span style="font-weight: 400;"> Push-button output</span></li>
<li style="font-weight: 400;" aria-level="1"><b>+:</b><span style="font-weight: 400;"> Power (3.3V or 5V)</span></li>
<li style="font-weight: 400;" aria-level="1"><b>GND:</b><span style="font-weight: 400;"> Ground</span></li>
</ul>
<h4><b>Step 2: Wire the Rotary Encoder to Raspberry Pi</b></h4>
<ol>
<li><b>Power the Encoder:</b>
<ul>
<li><span style="font-weight: 400;">Connect the encoder’s </span><b>+</b><span style="font-weight: 400;"> pin to Raspberry Pi's </span><b>3.3V</b><span style="font-weight: 400;"> pin.</span></li>
<li><span style="font-weight: 400;">Connect the </span><b>GND</b><span style="font-weight: 400;"> pin to a Raspberry Pi </span><b>GND</b><span style="font-weight: 400;"> pin.</span></li>
</ul>
</li>
<li><b>Connect the Output Pins:</b>
<ul>
<li><span style="font-weight: 400;">Connect the </span><b>CLK (A)</b><span style="font-weight: 400;"> pin to </span><b>GPIO17</b><span style="font-weight: 400;"> (physical pin 11).</span></li>
<li><span style="font-weight: 400;">Connect the </span><b>DT (B)</b><span style="font-weight: 400;"> pin to </span><b>GPIO18</b><span style="font-weight: 400;"> (physical pin 12).</span></li>
</ul>
</li>
<li><b>Connect the Push Button (if available):</b>
<ul>
<li><span style="font-weight: 400;">Connect the </span><b>SW</b><span style="font-weight: 400;"> pin to </span><b>GPIO27</b><span style="font-weight: 400;"> (physical pin 13).</span></li>
<li><span style="font-weight: 400;">Add a pull-down resistor (10kΩ) if necessary.</span></li>
</ul>
</li>
</ol>
<h2><b>Step 3: Install Required Libraries</b></h2>
<p><span style="font-weight: 400;">Ensure your Raspberry Pi has Python and GPIO libraries installed:</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo apt update
sudo apt install python3-rpi.gpio</code></pre></pre>
</div>
<h2><b>Step 4: Write the Python Code</b></h2>
<p><span style="font-weight: 400;">Here's an example script to read rotary encoder inputs:</span></p>
<h4><b>Code:</b></h4>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-python" data-lang="Python"><pre><code class="language-cpp">import RPi.GPIO as GPIO

from time import sleep


# GPIO Pins
CLK = 17
DT = 18
SW = 27  # Optional: Push button

# Setup
GPIO.setmode(GPIO.BCM)
GPIO.setup(CLK, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(DT, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(SW, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # Pull-up for button

# Variables
counter = 0
last_clk = GPIO.input(CLK)

try:
    while True:
        # Read current state of CLK
        current_clk = GPIO.input(CLK)
        current_dt = GPIO.input(DT)

        if current_clk != last_clk:  # Detect a change in CLK
            if current_dt != current_clk:
                counter += 1  # Clockwise
            else:
                counter -= 1  # Counter-clockwise
            print(f&quot;Counter: {counter}&quot;)

        last_clk = current_clk

        # Check button press
        if GPIO.input(SW) == GPIO.LOW:
            print(&quot;Button pressed!&quot;)
            sleep(0.3)  # Debounce delay

        sleep(0.01)  # Small delay to stabilize readings

except KeyboardInterrupt:
    print(&quot;\nExiting...&quot;)

finally:
    GPIO.cleanup()</code></pre></pre>
</div>
<h3><b>Step 5: Run the Script</b></h3>
<p><span style="font-weight: 400;">Save the script as </span><span style="font-weight: 400;">rotary_encoder.py</span><span style="font-weight: 400;"> and run it:</span><span style="font-weight: 400;"></span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">python3 rotary_encoder.py</code></pre></pre>
</div>
<p><span style="font-weight: 400;">Rotate the encoder and observe the printed values in the terminal. Press the button (if available) to test its functionality.</span></p>
<h3><b>Step 6: Implement in a Project</b></h3>
<p><span style="font-weight: 400;">Once you've mastered the basics, you can integrate the rotary encoder into projects like:</span></p>
<ul>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Volume controllers</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Menu navigation</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Custom input devices</span></li>
</ul>
<h3><b>Tips:</b></h3>
<ul>
<li style="font-weight: 400;" aria-level="1"><b>Debouncing:</b><span style="font-weight: 400;"> Rotary encoders might generate false pulses due to mechanical noise. Use software debouncing if needed.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Interrupts:</b><span style="font-weight: 400;"> For real-time response, consider using GPIO interrupts instead of polling.</span></li>
</ul>
<p><span style="font-weight: 400;">By following this guide, you can harness the power of a rotary encoder in your Raspberry Pi projects!</span></p>
<p>The post <a href="https://www.teachmemicro.com/how-to-use-a-rotary-encoder-with-raspberry-pi/">How to Use a Rotary Encoder with Raspberry Pi</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Building a Django Webserver on Raspberry Pi: A Step-by-Step Guide</title>
		<link>https://www.teachmemicro.com/building-a-django-webserver-on-raspberry-pi-a-step-by-step-guide/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=building-a-django-webserver-on-raspberry-pi-a-step-by-step-guide</link>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Thu, 12 Dec 2024 22:26:16 +0000</pubDate>
				<category><![CDATA[Raspberry Pi Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=7528</guid>

					<description><![CDATA[<p>Django, a high-level Python web framework, can be a perfect choice for building dynamic web applications. Combining this with the Raspberry Pi—a versatile, compact computer—enables developers to deploy a robust and affordable web server. This guide walks you through setting up a Django web server on a Raspberry Pi. Prerequisites Step 1: Update Your Raspberry &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/building-a-django-webserver-on-raspberry-pi-a-step-by-step-guide/">Building a Django Webserver on Raspberry Pi: A Step-by-Step Guide</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Django, a high-level Python web framework, can be a perfect choice for building dynamic web applications. Combining this with the Raspberry Pi—a versatile, compact computer—enables developers to deploy a robust and affordable web server. This guide walks you through setting up a Django web server on a Raspberry Pi.</p>
<p><span id="more-7528"></span></p>
<h3><strong>Prerequisites</strong></h3>
<div class="checklist tie-list-shortcode">
<ul>
<li><strong>Raspberry Pi</strong>:
<ul>
<li>A Raspberry Pi 3, 4, or newer.</li>
<li>Raspbian OS (preferably Raspberry Pi OS Lite or Desktop) installed.</li>
</ul>
</li>
<li><strong>Hardware</strong>:
<ul>
<li>A microSD card (8GB or more).</li>
<li>Internet connection (Wi-Fi or Ethernet).</li>
</ul>
</li>
<li><strong>Software</strong>:
<ul>
<li>Python 3.7 or newer (pre-installed on Raspberry Pi OS).</li>
<li>Basic understanding of Linux and Python.</li>
</ul>
</li>
</ul>
</div>
<h3><strong>Step 1: Update Your Raspberry Pi</strong></h3>
<p>Before installing Django, ensure your Raspberry Pi is up to date:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo apt update
sudo apt upgrade -y</code></pre></pre>
</div>
<h3><strong>Step 2: Install Python and Required Tools</strong></h3>
<p>Django requires Python 3 and pip (Python’s package manager). These are typically pre-installed, but verify their presence:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">python3 --version
pip3 --version</code></pre></pre>
</div>
<p>If missing, install them:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo apt install python3 python3-pip -y</code></pre></pre>
</div>
<p>Install venv to create isolated Python environments:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo apt install python3-venv -y</code></pre></pre>
</div>
<h3><strong>Step 3: Set Up a Virtual Environment</strong></h3>
<p>It's best to run Django in a virtual environment to avoid conflicts with system-wide packages.</p>
<ol>
<li>Create a directory for your project:</li>
<li>mkdir ~/django_project</li>
<li>cd ~/django_project</li>
<li>Create and activate the virtual environment:</li>
<li>python3 -m venv env</li>
<li>source env/bin/activate</li>
</ol>
<p>You’ll notice your shell prompt changes to indicate the environment is active.</p>
<h3><strong>Step 4: Install Django</strong></h3>
<p>With the virtual environment active, install Django using pip:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">pip install django</code></pre></pre>
</div>
<p>Verify the installation:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">django-admin --version</code></pre></pre>
</div>
<h3><strong>Step 5: Start a Django Project</strong></h3>
<p>Create a new Django project:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">django-admin startproject mysite
cd mysite</code></pre></pre>
</div>
<p>Next, run the development server to ensure everything works:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">python manage.py runserver 0.0.0.0:8000</code></pre></pre>
</div>
<p>After this, visit <em>http://&lt;Raspberry_Pi_IP&gt;:8000</em> in a browser to see the Django welcome page.</p>
<h3><strong>Step 6: Configure Django for Deployment</strong></h3>
<p><strong>Update settings.py:</strong></p>
<p>To allow external connections, open the settings.py using nano or vim. Look for this line:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">ALLOWED_HOSTS = [&#039;&lt;Raspberry_Pi_IP&gt;&#039;, &#039;localhost&#039;]</code></pre></pre>
</div>
<p>Set up static files:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-json" data-lang="JSON"><pre><code class="language-cpp">STATIC_ROOT = BASE_DIR / &#039;staticfiles&#039;</code></pre></pre>
</div>
<p>Run the following to collect static files:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">python manage.py collectstatic</code></pre></pre>
</div>
<h3><strong>Step 7: Install and Configure Gunicorn</strong></h3>
<p>Gunicorn is a Python WSGI server that helps deploy Django applications. To install, run:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">pip install gunicorn</code></pre></pre>
</div>
<p>After this, test <em>gunicorn</em> it with your project:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">gunicorn mysite.wsgi:application --bind 0.0.0.0:8000</code></pre></pre>
</div>
<h3><strong>Step 8: Set Up Nginx as a Reverse Proxy</strong></h3>
<p>Nginx will serve as a reverse proxy for Gunicorn. Install Nginx using:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo apt install nginx -y</code></pre></pre>
</div>
<p>Then configure Nginx for your Django project. For this, we create a new configuration file:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo nano /etc/nginx/sites-available/mysite</code></pre></pre>
</div>
<p>Then we write the following to the configuration file:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">server {
    listen 80;
    server_name &lt;Raspberry_Pi_IP&gt;;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location /static/ {
        alias /home/pi/django_project/mysite/staticfiles/;
    }
}</code></pre></pre>
</div>
<p>Next, enable the configuration:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo ln -s /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/</code></pre></pre>
</div>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo nginx -t
sudo systemctl restart nginx</code></pre></pre>
</div>
<h3><strong>Step 9: Enable Gunicorn to Start at Boot</strong></h3>
<p>Create a <em>systemd</em> service file for Gunicorn:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">sudo nano /etc/systemd/system/gunicorn.service</code></pre></pre>
</div>
<p>Add the following:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">[Unit]

Description=gunicorn daemon for Django
After=network.target

[Service]
User=pi
Group=www-data
WorkingDirectory=/home/pi/django_project/mysite
ExecStart=/home/pi/django_project/env/bin/gunicorn --workers 3 --bind unix:/home/pi/django_project/mysite.sock mysite.wsgi:application

[Install]
WantedBy=multi-user.target
Start and enable the service:
sudo systemctl start gunicorn
sudo systemctl enable gunicorn</code></pre></pre>
</div>
<h3><strong>Step 10: Test the Deployment</strong></h3>
<p>Visit <em>http://&lt;Raspberry_Pi_IP&gt;</em> in a browser. You should see your Django application served by Nginx and Gunicorn.</p>
<h3><strong>Conclusion</strong></h3>
<p>You've successfully set up a Django web server on a Raspberry Pi! This setup is perfect for small-scale projects, educational purposes, or prototyping IoT applications. For production environments, consider securing your server with HTTPS using tools like Let's Encrypt.</p>
<p>Feel free to extend your application with features or integrate it with sensors and GPIO for an IoT-powered web solution.</p>
<p>&nbsp;</p>
<p>The post <a href="https://www.teachmemicro.com/building-a-django-webserver-on-raspberry-pi-a-step-by-step-guide/">Building a Django Webserver on Raspberry Pi: A Step-by-Step Guide</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Raspberry Pi Pico L298N Motor Control</title>
		<link>https://www.teachmemicro.com/raspberry-pi-pico-l298n-motor-control/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=raspberry-pi-pico-l298n-motor-control</link>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Sat, 27 Jan 2024 02:55:47 +0000</pubDate>
				<category><![CDATA[Raspberry Pi Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=7045</guid>

					<description><![CDATA[<p>Introduction The Raspberry Pi Pico is a versatile microcontroller from the Raspberry Pi Foundation. It features the RP2040 microcontroller chip, offering dual-core ARM Cortex-M0+ processors and a variety of I/O pins.  Its affordability, GPIO flexibility, and programmability make it an excellent choice for various applications, including motor control projects using devices like the L298N motor &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/raspberry-pi-pico-l298n-motor-control/">Raspberry Pi Pico L298N Motor Control</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h3><strong>Introduction</strong></h3>
<p>The Raspberry Pi Pico is a versatile microcontroller from the Raspberry Pi Foundation. It features the RP2040 microcontroller chip, offering dual-core ARM Cortex-M0+ processors and a variety of I/O pins.  Its affordability, GPIO flexibility, and programmability make it an excellent choice for various applications, including motor control projects using devices like the <a href="https://www.teachmemicro.com/use-l298n-motor-driver/">L298N motor driver</a>.</p>
<p><span id="more-7045"></span></p>
<p>The L298N simplifies the management of DC and stepper motors, allowing for control over speed and direction. This level of motor control is indispensable in scenarios where accuracy and reliability are key factors, such as in robotic vehicles, automated systems, and various electromechanical projects. Integrating the L298N with the Raspberry Pi Pico enhances the capabilities of the microcontroller, providing users with a powerful but cheap solution for motor-driven applications.</p>
<p>This tutorial serves as a guide for makers looking to build projects featuring the Raspberry Pi Pico and the L298N motor driver. My goal is to provide instructions on how to set up, program, and control motors seamlessly. This tutorial aims to help both beginners and experienced hobbyists easily understand Raspberry Pi Pico and L298N motor control for creative DIY projects.</p>
<h3><strong>Setting Up Raspberry Pi Pico and Arduino IDE</strong></h3>
<p>This tutorial uses Arduino to program the Raspberry Pi Pico. To know how to add the Pico to your Arduino IDE, read <a href="https://www.teachmemicro.com/raspberry-pi-pico-with-arduino/">this tutorial</a>.</p>
<h3><strong>Understanding L298N Motor Driver</strong></h3>
<h4><strong>Overview of L298N motor driver features</strong></h4>
<p><img decoding="async" src="https://i0.wp.com/www.teachmemicro.com/wp-content/uploads/2019/05/img_5ce3b551cbce3.png?resize=668%2C293&amp;ssl=1" class="aligncenter" /></p>
<p>The L298N motor driver boasts essential features for effective motor control. With a dual H-bridge configuration, it supports bidirectional control, enabling precise management of DC motors in both forward and backward directions. This IC drives two motors through two channels, A and B. For example, if a motor is using channel A, its terminals must be connected to pins Out 1 and Out 2. The Enable A pin must be high to turn on the motor. To drive a motor to a direction, say, clockwise, the pin Input 1 must be high while the pin Input 2 must be low. To drive the motor counterclockwise, the pin Input 1 is low while the pin Input 2 is high.<strong></strong></p>
<h4><strong>L298N motor controller board</strong></h4>
<p>Makers will consider using the L298N breakout board as it is easier for prototyping.</p>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated.jpg"><img loading="lazy" decoding="async" src="https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-300x245.jpg" alt="L298N motor controller board" width="549" height="448" class="aligncenter wp-image-1640" srcset="https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-300x245.jpg 300w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-768x626.jpg 768w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-1024x835.jpg 1024w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-24x20.jpg 24w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-36x29.jpg 36w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-48x39.jpg 48w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated.jpg 1516w" sizes="auto, (max-width: 549px) 100vw, 549px" /></a></p>
<p>The controller board, shown above, has terminals with labels +12V and +5V. The +12V terminal is where the motor power connects. While it is common to put in +12 VDC to this terminal, it can accept voltages from +7 VDC to +35 VDC. Just remove the jumper behind the +12V terminal if you are planning to power the motors higher than +12V.</p>
<p>When the +12V jumper is attached, the onboard voltage regulator is now usable, and you can source +5V from the +5V terminal. This means the +5V terminal is not for powering the board but for powering a 5V external device.</p>
<p>You have Motor A inputs and Motor B inputs. These connect to the microcontroller. The minimum high voltage is 2.3V, which means the 3.3V logic high from Raspberry Pi Pico is good enough.</p>
<p>The motor terminals connect to Motor Terminals 1, 2, 3, 4. Specifically, motor A connects to terminals 1 and 2 while Motor B connects to terminals 3 and 4.</p>
<p>There are also two other jumpers on the board, as shown. Remove these jumpers if you are using DC motors and keep them for stepper motors. Speed control for Motor A and Motor B is achieved via PWM on these pins.</p>
<h3><strong>Connecting L298N to Raspberry Pi Pico and DC Motors</strong></h3>
<p><img loading="lazy" decoding="async" src="https://www.teachmemicro.com/wp-content/uploads/2024/01/raspberry-pi-pico-l298n-wiring-diagram.png" alt="raspberry-pi-pico-l298n-dc-motor" width="626" height="398" class="aligncenter wp-image-7059 size-full" srcset="https://www.teachmemicro.com/wp-content/uploads/2024/01/raspberry-pi-pico-l298n-wiring-diagram.png 626w, https://www.teachmemicro.com/wp-content/uploads/2024/01/raspberry-pi-pico-l298n-wiring-diagram-300x191.png 300w" sizes="auto, (max-width: 626px) 100vw, 626px" /></p>
<p>The motor input pins can be connected to any digital I/O pin of the Raspberry Pi Pico. Conversely, the motor-enable pins must be wired to PWM-capable pins. Thankfully for the Pico, almost all of its GPIO pins are PWM-capable.</p>
<p>The Raspberry Pi Pico here gets its power from the L298N board via the 5V terminal. A Schottky diode is added to prevent backpowering. This is a setup suggested in the Raspberry Pi Pico datasheet, section 4.5.</p>
<h3><strong>Writing Arduino Code for DC Motor Control</strong></h3>
<p>Using the L298N is straightforward. Imagine a robot with two wheels. If you want the robot to move to the left, rotate the right motor forward and rotate the left motor backward.</p>
<p>For the left motor (motor A) to rotate in one direction, apply a high pulse to IN1 and a low pulse to IN2. To reverse the direction, reverse the pulses to IN1 and IN2. The same applies to the right motor (motor B).</p>
<p>Here’s a table that summarizes the pins and corresponding motor direction. This assumes that the upper DC motor is the left motor and the lower one is the right motor.</p>
<p><img loading="lazy" decoding="async" src="https://www.teachmemicro.com/wp-content/uploads/2024/01/l298n-motor-direction-table.jpg" alt="" width="790" height="336" class="size-full wp-image-7065 aligncenter" srcset="https://www.teachmemicro.com/wp-content/uploads/2024/01/l298n-motor-direction-table.jpg 790w, https://www.teachmemicro.com/wp-content/uploads/2024/01/l298n-motor-direction-table-300x128.jpg 300w, https://www.teachmemicro.com/wp-content/uploads/2024/01/l298n-motor-direction-table-768x327.jpg 768w" sizes="auto, (max-width: 790px) 100vw, 790px" /></p>
<p>In the code, first, let us define the pins according to the wiring diagram above:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-cpp" data-lang="C++"><pre><code class="language-cpp">#define EnA 22
#define EnB 21
#define In1 24
#define In2 25
#define In3 26
#define In4 27</code></pre></pre>
</div>
<p>Then we initialize all of them as output pins:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-cpp" data-lang="C++"><pre><code class="language-cpp">void setup()
{
// All motor control pins are outputs
  pinMode(EnA, OUTPUT);
  pinMode(EnB, OUTPUT);
  pinMode(In1, OUTPUT);
  pinMode(In2, OUTPUT);
  pinMode(In3, OUTPUT);
  pinMode(In4, OUTPUT);
}</code></pre></pre>
</div>
<p>Next, we create functions corresponding to the actions in the table above: stop, forward, reverse, left, and right.</p>
<p>For stopping the motors, we make all of the motor control pins low, including EnA and EnB.</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-cpp" data-lang="C++"><pre><code class="language-cpp">// Function to stop all motors
void stop ()
{
  digitalWrite(EnA, LOW);
  digitalWrite(EnB, LOW);
  digitalWrite(In1, LOW);
  digitalWrite(In2, LOW);
  digitalWrite(In3, LOW);
  digitalWrite(In4, LOW);
}</code></pre></pre>
</div>
<p>To move forward, we enable both motors and make them turn in the same direction. Enabling the motors requires a pulse to EnA/EnB, doable via the <em>analogWrite()</em> command. Here we use a value of 100 out of 255 for our duty cycle. Experiment with which duty cycle value is right for your motors.</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-cpp" data-lang="C++"><pre><code class="language-cpp">// Function to move forward
void forward ()
{
  analogWrite(EnA, 100);
  analogWrite(EnB, 100);
  digitalWrite(In1, HIGH);
  digitalWrite(In2, LOW);
  digitalWrite(In3, HIGH);
  digitalWrite(In4, LOW);
}</code></pre></pre>
</div>
<p>To reverse, just logically reverse the function above, keeping the same duty cycle for EnA and EnB.</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-cpp" data-lang="C++"><pre><code class="language-cpp">// Function to move in reverse
void reverse ()
{
  analogWrite(EnA, 100);
  analogWrite(EnB, 100);
  digitalWrite(In1, LOW);
  digitalWrite(In2, HIGH);
  digitalWrite(In3, LOW);
  digitalWrite(In4, HIGH);
}</code></pre></pre>
</div>
<p>To move left, rotate the right motor forward and the left motor backward. Moving left logically requires the inverse of moving left.</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-cpp" data-lang="C++"><pre><code class="language-cpp">// Function to move left
void left ()
{
  analogWrite(EnA, 100);
  analogWrite(EnB, 100);
  digitalWrite(In1, LOW);
  digitalWrite(In2, HIGH);
  digitalWrite(In3, HIGH);
  digitalWrite(In4, LOW);
}

// Function to move right
void right ()
{
  analogWrite(EnA, 100);
  analogWrite(EnB, 100);
  digitalWrite(In1, HIGH);
  digitalWrite(In2, LOW);
  digitalWrite(In3, LOW);
  digitalWrite(In4, HIGH);
}</code></pre></pre>
</div>
<p>Now we have all five functions to control our motors! Simply call them inside the <em>loop()</em> method.</p>
<h4><strong>Example Code</strong></h4>
<p>You can find an <a href="https://github.com/EngrRolandPelayo/pico_dc_motor_control_serial">example code in this repository</a> where you can control the direction of the motors via a serial monitor. For example, if you type “forward”, the motors will move forward, and so on.</p>
<h3><strong>Connecting L298N to Raspberry Pi Pico and DC Motors</strong></h3>
<p>The L298N can also control stepper motors, specifically bipolar stepper motors. This time, the enable-pin jumpers must be on. The four pins from the stepper motor then connect to the motor output pins of the L298N module. Here is a wiring diagram featuring the Raspberry Pi Pico as the microcontroller:</p>
<p><img loading="lazy" decoding="async" src="https://www.teachmemicro.com/wp-content/uploads/2024/01/raspberry-pi-pico-l298n-stepper-motor.png" alt="" width="658" height="379" class="size-full wp-image-7060 aligncenter" srcset="https://www.teachmemicro.com/wp-content/uploads/2024/01/raspberry-pi-pico-l298n-stepper-motor.png 658w, https://www.teachmemicro.com/wp-content/uploads/2024/01/raspberry-pi-pico-l298n-stepper-motor-300x173.png 300w" sizes="auto, (max-width: 658px) 100vw, 658px" /></p>
<p>To rotate the stepper motor, the motor output pins must provide power in a specific sequence. The four pins of the stepper motor are the end of the coils in this diagram:</p>
<p><img loading="lazy" decoding="async" src="https://www.teachmemicro.com/wp-content/uploads/2024/01/bipolar-stepper-motor.jpg" alt="" width="474" height="377" class="size-full wp-image-7061 aligncenter" srcset="https://www.teachmemicro.com/wp-content/uploads/2024/01/bipolar-stepper-motor.jpg 474w, https://www.teachmemicro.com/wp-content/uploads/2024/01/bipolar-stepper-motor-300x239.jpg 300w" sizes="auto, (max-width: 474px) 100vw, 474px" /></p>
<p>When powering the coils in sequence, the permanent magnet rotor rotates according to that sequence. For simplicity, we will implement what is called a half-step drive:</p>
<p><img loading="lazy" decoding="async" src="https://www.teachmemicro.com/wp-content/uploads/2024/01/half-step-drive.gif" alt="" width="198" height="198" class="size-full wp-image-7062 aligncenter" /></p>
<h4><strong>Writing Arduino Code for Stepper Motor Control</strong></h4>
<p>The Arduino platform contains a built-in stepper library called Stepper. To use, include <em>&lt;Stepper.h&gt;</em> <stepper.h> and initiate the Stepper object using the number of steps per revolution and the GPIO pins for IN1 to IN4.</stepper.h></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-cpp" data-lang="C++"><pre><code class="language-cpp">#include &lt;Stepper.h&gt;

#define In1 24
#define In2 25
#define In3 26
#define In4 27

const int stepsPerRevolution = 64;

// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, In1, In2, In3, In4);</code></pre></pre>
</div>
<p>Set the stepper motor speed inside <em>setup()</em></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-cpp" data-lang="C++"><pre><code class="language-cpp">void setup() {
//Set the speed at 60 rpm:
  myStepper.setSpeed(60);
// initialize the serial port:
  Serial.begin(9600);
}</code></pre></pre>
</div>
<p>To move the stepper motor, call the step() function with an argument equal to the steps per revolution.</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-cpp" data-lang="C++"><pre><code class="language-cpp">myStepper.step(stepsPerRevolution);</code></pre></pre>
</div>
<p>Here is a simple sketch that rotates the stepper in one direction and then in the other direction.</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-cpp" data-lang="C++"><pre><code class="language-cpp">#include &lt;Stepper.h&gt;

const int stepsPerRevolution = 64; // change this to fit the number of steps per revolution
// for your motor

// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);

void setup() {
// set the speed at 60 rpm:
  myStepper.setSpeed(60);
// initialize the serial port:
  Serial.begin(9600);
}

void loop() {
// step one revolution in one direction:
  Serial.println(&quot;clockwise&quot;);
  myStepper.step(stepsPerRevolution);
  delay(500);

// step one revolution in the other direction:
  Serial.println(&quot;counterclockwise&quot;);
  myStepper.step(-stepsPerRevolution);
  delay(500);
}</code></pre></pre>
</div>
<p>The disadvantage of using the built-in stepper library is that there’s no option to change the stepping mode as it defaults to wave drive only. When the stepper motor is moving, it blocks other Arduino functions. Also, the built-in library is limited to one stepper motor.</p>
<p>A better library for controlling stepper motors is the <a href="https://www.airspayce.com/mikem/arduino/AccelStepper/">AccelStepper library by AirSpayce</a>. Besides support for half-step driving and multiple motors, the library also offers acceleration and deceleration functions, among other things.</p>
<p>I hope that this tutorial, in some way, helps makers like you and me. For any questions, reactions, or concerns, feel free to drop comments below. You can also follow our Facebook, TikTok, and Instagram accounts. As always, happy building!</p>
<p>The post <a href="https://www.teachmemicro.com/raspberry-pi-pico-l298n-motor-control/">Raspberry Pi Pico L298N Motor Control</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Interfacing HC-SR04 Ultrasonic Sensor with Raspberry Pi Pico</title>
		<link>https://www.teachmemicro.com/interfacing-hc-sr04-ultrasonic-sensor-with-raspberry-pi-pico/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=interfacing-hc-sr04-ultrasonic-sensor-with-raspberry-pi-pico</link>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Sat, 13 Jan 2024 01:54:05 +0000</pubDate>
				<category><![CDATA[Raspberry Pi Tutorial]]></category>
		<category><![CDATA[Sensor Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=6963</guid>

					<description><![CDATA[<p>Introduction Beginner tutorials on the web often use the HC-SR04 ultrasonic sensor. Why? Because it’s easy to use and requires a few short lines of code. So when I tried it with the Raspberry Pi Pico, I expected it to work immediately. Until it didn’t. Fortunately, I made it to work, thanks to a few &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/interfacing-hc-sr04-ultrasonic-sensor-with-raspberry-pi-pico/">Interfacing HC-SR04 Ultrasonic Sensor with Raspberry Pi Pico</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h3 id="h.60d3zkbp4gzp" class="c9"><span class="c12">Introduction</span></h3>
<p class="c2"><span class="c0">Beginner tutorials on the web often use the <a href="https://www.teachmemicro.com/hc-sr04-arduino-interfacing/">HC-SR04 ultrasonic sensor</a>. Why? Because it’s easy to use and requires a few short lines of code. So when I tried it with the Raspberry Pi Pico, I expected it to work immediately. Until it didn’t.</span></p>
<p class="c2"><span class="c1">Fortunately, I made it to work, thanks to a few days of scouring the internet. I made this tutorial hoping that you will not spend the same time as me.</span></p>
<p><span id="more-6963"></span></p>
<p class="c2"><span class="c1">The code in this tutorial uses the </span><span class="c8 c1"><a class="c11" href="https://github.com/earlephilhower/arduino-pico">Raspberry Pi Pico Arduino core by Earle F. Philhower</a></span><span class="c1">. Head over to </span><span class="c8 c1"><a class="c11" href="https://www.teachmemicro.com/raspberry-pi-pico-with-arduino/">this tutorial</a></span><span class="c1"> on how to set it up.</span></p>
<h3 id="h.xh0a8a22c12a" class="c9"><span class="c12">How the HC-SR04 Ultrasonic Sensor Works</span></h3>
<p class="c2"><span class="c0">I always assume every one of my readers is a beginner. So I have to give every detail including how the sensor works. If you already know this, kindly skip to the <a href="https://www.teachmemicro.com/interfacing-hc-sr04-ultrasonic-sensor-with-raspberry-pi-pico/#h.j7ny5wpg0nmb">next section</a>.</span></p>
<p class="c2"><span class="c0">The ultrasonic sensor works by knowing the time between sending a sound and having that sound reflected to its source. The distance then between the sound source and the reflector is half that time multiplied by the speed of sound. The sound is above the hearing range of humans hence it’s called "ultra" sonic.</span></p>
<p class="c6"><img loading="lazy" decoding="async" class="size-full wp-image-6967 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2024/01/ultrasonic-sensor-how-it-works.gif" alt="ultrasonic sensor how it works" width="640" height="360" /></p>
<p class="c2"><span class="c0">The HC-SR04 has four pins: VCC, GND, TRIG, and ECHO. VCC and GND are where you will apply the 5V DC source. TRIG, short for trigger is where you enable the sensor to send an ultrasonic signal. ECHO is where a pulse can be measured that is proportional to the distance between the sensor and the obstacle.</span></p>
<p class="c6"><img loading="lazy" decoding="async" class="aligncenter" title="" src="https://lh7-us.googleusercontent.com/WJPNCzLWJIcV-9SPgt2ud-gPSAHeIR6glEJQMtDD8y5U9tOerXorE0bWv5TNrsFXD9gLkOR4weyzgdZZZ3WvycIQlMDbuFb9As30pM4aCSKaOEFb9UlbuFabR-J2ndM-3yBvAaFd415o9HycZJHprUg" alt="" width="431" height="431" /></p>
<p class="c2"><span class="c0">The TRIG pin requires a 10 µs pulse for it to start emitting 8 cycles of signal. After the ultrasonic signal is sent, the ECHO pin goes from LOW to HIGH and stays HIGH. The ECHO pin only goes LOW when the ultrasonic signal is reflected to the sensor (hence, the word “echo”). Reflection only happens when the signal is obstructed, hence the distance traveled by the signal from the sensor and back is known if the time between the the ECHO pin going HIGH then going LOW is known. If <em>t</em> is that time, then the distance from the sensor to the obstacle is:</span></p>
<pre class="c2"><span class="c15 c17 c13">distance = speed of sound * t / 2;</span></pre>
<p class="c2"><span class="c0">The HC-SR04 can measure the distance from an obstruction if it’s within 2 centimeters to 4 meters (unverified, probably less) and 15 degrees of the viewing angle.</span></p>
<h4><strong>Some Tips</strong></h4>
<p class="c2"><span class="c0">If in case your ultrasonic sensor is not working as intended, take note of the following scenarios:</span></p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-6968 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2024/01/ultrasonic-sensor-obstacle-types.png" alt="ultrasonic sensor obstacle " width="571" height="303" srcset="https://www.teachmemicro.com/wp-content/uploads/2024/01/ultrasonic-sensor-obstacle-types.png 571w, https://www.teachmemicro.com/wp-content/uploads/2024/01/ultrasonic-sensor-obstacle-types-300x159.png 300w" sizes="auto, (max-width: 571px) 100vw, 571px" /></p>
<p class="c2">
<p class="c2"><span class="c0">An upgrade of the HC-SR04 is the 5-pin HY-SRF05. When the fifth pin is grounded, you can use the TRIG pin as the ECHO pin. This reduces the number of pins used. The HY-SRF05 also claims to have a longer range than the HC-SR04. I will verify this as soon as I get my hands on one.</span></p>
<h3 id="h.xrxnowsjfybk" class="c9 c10"></h3>
<h3 id="h.j7ny5wpg0nmb" class="c9"><span class="c7">Wiring Diagram</span></h3>
<p class="c6"><img loading="lazy" decoding="async" class="size-full wp-image-6964 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2024/01/raspberry-pi-pico-ultrasonic-sensor.png" alt="raspberry pi pico hc-sr04 ultrasonic sensor wiring" width="558" height="447" srcset="https://www.teachmemicro.com/wp-content/uploads/2024/01/raspberry-pi-pico-ultrasonic-sensor.png 558w, https://www.teachmemicro.com/wp-content/uploads/2024/01/raspberry-pi-pico-ultrasonic-sensor-300x240.png 300w" sizes="auto, (max-width: 558px) 100vw, 558px" /></p>
<p class="c2"><span class="c0">The TRIG and ECHO pin may be connected to any GPIO pin of the Raspberry Pi Pico. I choose GPIO15 for the TRIG and GPIO14 for the ECHO. The HC-SR04 needs 5V to turn on so we use the VBUS pin. Note that the VBUS pin gets the 5V DC power from the USB connection of the Pico. We add a voltage divider between the ECHO and GPIO14 since the HC-SR04 sends a 5V signal and the Pico pin is only 3.3V tolerant. An optional (3V) buzzer can be connected to GPIO19. This buzzer’s sound changes with the distance of the obstacle from the sensor.</span></p>
<h3 id="h.j2e157vefkc" class="c9"><span class="c12">Code Explanation</span></h3>
<h4>Sending Pulse</h4>
<p class="c2"><span class="c1">The HC-SR04 is a common sensor for interfacing with an Arduino.  Using the code that is easily found in the internet didn't work initially. I found out that a voltage divider is needed because the HC-SR04 sends 5V pulses from the echo pin to the 3.3V GPIO pins of the Pico. </span></p>
<p class="c2"><span class="c0">First, we send a 10 µs pulse to the trigger pin. This will make HC-SR04 send out 8 pulses of ultrasonic signal.</span></p>
<pre class="c2"><span class="c4">  digitalWrite(trig_pin, LOW);</span>
<span class="c4">  delayMicroseconds(2);</span>
<span class="c4">  digitalWrite(trig_pin, HIGH);</span>
<span class="c4">  delayMicroseconds(TRIG_PULSE_DURATION_US);</span>
<span class="c4">  digitalWrite(trig_pin, LOW);</span></pre>
<h4><strong>Measuring Distance</strong></h4>
<p class="c2"><span class="c0">After sending the pulse, the echo pin will now be in the high state. We note this as the start of the travel of the ultrasonic signal. We use the pulseIn() function to measure the time between HIGH and LOW state of the echo pin</span></p>
<pre class="c2"><span class="c4"> echo_time = pulseIn(echo_pin, HIGH);</span></pre>
<pre class="c2"></pre>
<p class="c2"><span class="c0">The distance traveled by the signal is then:</span></p>
<pre class="c2"><span class="c15 c1 c13">distance  = speed * echo_time</span></pre>
<p class="c2"><span class="c0">Speed here would be the speed of sound and time is the difference between the time the echo pin going high and then the time it went low. Also, we need to convert the speed of sound to centimeters per microsecond since the measured time was in microseconds. Also, since the HC-SR04’s range is from 2 to 4 centimeters only, it makes sense to use centimeters for the distance.</span></p>
<pre class="c2"><span class="c15 c1 c13">distance = 331.3 * echo_time * 0.0001 (in cm)</span></pre>
<p class="c2"><span class="c0">This distance is the distance traveled by the signal from the sensor, to the obstacle and back to the sensor. We want to know only the distance between the sensor and the obstacle. So, we divide the total distance in half.</span></p>
<pre class="c2"><span class="c15 c1 c13">distance = (331.3 * echo_time * 0.0001) / 2 (in cm)</span></pre>
<p class="c2"><span class="c1">Btw, an optional buzzer can be connected to GPIO19. The buzzer’s sound will change with the distance of the obstacle from the front of the sensor. That part is inside the </span><span class="c1 c13">loop()</span><span class="c0">:</span></p>
<pre class="c2"><span class="c4"> analogWrite(buzz_pin, distance_cm * 10000.00);</span></pre>
<h3 id="h.u8xtq0xhssg5" class="c9"><span class="c12">Effect of Temperature</span></h3>
<p class="c2"><span class="c1">The speed of sound is </span><span class="c8 c1"><a class="c11" href="https://www.google.com/url?q=https://en.wikipedia.org/wiki/Speed_of_sound%23Dependence_on_the_properties_of_the_medium&amp;sa=D&amp;source=editors&amp;ust=1705112273209723&amp;usg=AOvVaw33G8ztkmcnV2MJXrBZtxKY">not constant in every environment</a></span><span class="c0">. Its speed is different in the desert compared to a freezing tundra, for example.</span></p>
<p class="c6"><img loading="lazy" decoding="async" class="size-full wp-image-6966 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2024/01/speed_of_sound_temperature.jpg" alt="speed of sound temperature" width="350" height="400" srcset="https://www.teachmemicro.com/wp-content/uploads/2024/01/speed_of_sound_temperature.jpg 350w, https://www.teachmemicro.com/wp-content/uploads/2024/01/speed_of_sound_temperature-263x300.jpg 263w" sizes="auto, (max-width: 350px) 100vw, 350px" /></p>
<p class="c2"><span class="c0">The formula for the speed of sound considering temperature is:</span></p>
<p class="c2" style="text-align: center;"> <img decoding="async" src="https://latex.codecogs.com/svg.image?%20v_{sound}=331\frac{m}{s}+0.6\frac{\frac{m}{s}}{C}*T" /></p>
<p class="c2"><span class="c0">Thus, in the code, I used the internal temperature sensor of the Raspberry Pi Pico to <a href="https://www.teachmemicro.com/ultrasonic-sensor-temperature-compensation/">compensate for temperature changes</a>:</span></p>
<pre class="c2"><span class="c4">  float comp_sound_speed = SOUND_SPEED + 0.606 * analogReadTemp();</span>
<span class="c4">  float distance_cm = 0.0001 * ((receiveTime - delayTime) * comp_sound_speed) / 2;</span></pre>
<p class="c2"><span class="c1">Here’s the </span><span class="c1 c8"><a class="c11" href="https://www.google.com/url?q=https://github.com/kurimawxx00/pico_ultrasonic_proximity_sensor&amp;sa=D&amp;source=editors&amp;ust=1705112273210767&amp;usg=AOvVaw0CfNLbSt4UxiKmujRFnX1x">link to download</a></span><span class="c0"> the full sketch/code.</span></p>
<h3><strong>Video Results</strong></h3>
<p><iframe loading="lazy" src="https://drive.google.com/file/d/19JuK7kdR3tlrDX1_jdzb_d0DcXwxXh8p/preview" width="640" height="480"></iframe></p>
<p>The post <a href="https://www.teachmemicro.com/interfacing-hc-sr04-ultrasonic-sensor-with-raspberry-pi-pico/">Interfacing HC-SR04 Ultrasonic Sensor with Raspberry Pi Pico</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Automating Video Uploads to TikTok Using Raspberry Pi</title>
		<link>https://www.teachmemicro.com/automating-video-uploads-to-tiktok-using-raspberry-pi/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=automating-video-uploads-to-tiktok-using-raspberry-pi</link>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Tue, 12 Sep 2023 09:00:39 +0000</pubDate>
				<category><![CDATA[Raspberry Pi Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=6499</guid>

					<description><![CDATA[<p>The Raspberry Pi, a versatile and affordable single-board computer, has gained immense popularity among hobbyists, makers, and tech enthusiasts. While it's often used for educational and DIY projects, its capabilities can extend to more complex tasks, such as automating video uploads to popular social media platforms like TikTok. In this article, we will explore how &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/automating-video-uploads-to-tiktok-using-raspberry-pi/">Automating Video Uploads to TikTok Using Raspberry Pi</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The Raspberry Pi, a versatile and affordable single-board computer, has gained immense popularity among hobbyists, makers, and tech enthusiasts. While it's often used for educational and DIY projects, its capabilities can extend to more complex tasks, such as automating video uploads to popular social media platforms like TikTok. In this article, we will explore how a Raspberry Pi can be used to automatically upload recorded videos to TikTok, simplifying your content creation process.</p>
<p><span id="more-6499"></span></p>
<h3><strong>Prerequisites</strong></h3>
<p>Before diving into the process of automating video uploads to Tiktok (or other <a href="https://vottak.app/">video apps,</a> provided they have their own API) using a Raspberry Pi, make sure you have the following:</p>
<ol>
<li>Raspberry Pi (any model with Wi-Fi capabilities)</li>
<li>A Raspberry Pi camera module or USB webcam for recording videos</li>
<li>A TikTok account</li>
<li>Python knowledge</li>
</ol>
<h3><strong>Setting Up the Raspberry Pi</strong></h3>
<ol>
<li><strong>Raspberry Pi Setup</strong>: Begin by setting up your Raspberry Pi with an operating system (e.g., Raspberry Pi OS). Ensure that it is connected to the internet, either via Wi-Fi or Ethernet.</li>
<li><strong>Camera Module/USB Webcam</strong>: If you're using a camera module, make sure it's correctly connected to the Raspberry Pi's camera interface. If you're using a USB webcam, plug it into one of the available USB ports.
<p>If your USB webcam is from Logitech, you can check if it is properly connected using the ff. bash script:</li>
</ol>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">lsusb | grep &quot;Logitech&quot;</code></pre></pre>
</div>
<p style="padding-left: 30px;">  The response to the above command would be:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">Bus 001 Device 004: ID 046d:0825 Logitech, Inc. Webcam C270</code></pre></pre>
</div>
<p style="padding-left: 30px;">   If using a Raspberry Pi camera, the command is:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">vcgencmd get_camera </code></pre></pre>
</div>
<p style="padding-left: 30px;"><span>  </span><span></span>The response should be:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">supported=1 detected=1</code></pre></pre>
</div>
<p style="padding-left: 30px;"><span>3. </span><strong>Python Libraries</strong>: You'll need to install Python libraries such as <em>tiktokapi</em>, <em>selenium,</em> and <em>pyautogui</em>. These libraries play crucial roles in automating the TikTok video upload process.</p>
<p style="padding-left: 60px;"><strong>tiktokapi</strong>: This library allows you to interact programmatically with TikTok's services, enabling actions such as logging in and uploading videos.</p>
<p style="padding-left: 60px;"><strong>selenium</strong>: Selenium is a powerful web automation tool that helps you control web browsers programmatically. It's used to navigate the TikTok website, interact with its elements, and automate the login and video upload processes.</p>
<p style="padding-left: 60px;"><strong>pyautogui</strong>: PyAutoGUI is a library for automating keyboard and mouse input. It's useful for simulating user interactions, such as selecting files to upload during the video upload process.</p>
<p style="padding-left: 60px;">You can install these libraries using the following commands:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">pip install tiktokapi
pip install selenium
pip install pyautogui</code></pre></pre>
</div>
<h3><strong>Recording Videos Using Raspberry Pi Camera</strong></h3>
<p>To record videos using the Raspberry Pi camera module and Python, you can use the picamera library. Here's a simple code snippet to get you started:</p>
<p>import picamera<br />
import time</p>
<p># Initialize the camera<br />
with picamera.PiCamera() as camera:<br />
camera.resolution = (1920, 1080) # Set the resolution<br />
camera.start_recording('my_video.h264') # Start recording<br />
camera.wait_recording(10) # Record for 10 seconds<br />
camera.stop_recording() # Stop recording</p>
<h3><strong>Automating TikTok Login with Selenium</strong></h3>
<p>Below is an example of how to automate the TikTok login process using Selenium in Python:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-python" data-lang="Python"><pre><code class="language-cpp">from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time

# Initialize the Chrome web driver (you may need to install the driver separately)
driver = webdriver.Chrome()

# Navigate to TikTok login page
driver.get(&quot;https://www.tiktok.com/login&quot;)

# Fill in login credentials
username = driver.find_element_by_name(&quot;email&quot;)
password = driver.find_element_by_name(&quot;password&quot;)

username.send_keys(&quot;your_username&quot;)
password.send_keys(&quot;your_password&quot;)

# Submit the login form
password.send_keys(Keys.RETURN)

# Wait for the login to complete (you may need to adjust the sleep duration)
time.sleep(5)

# Close the browser when done
driver.quit()</code></pre></pre>
</div>
<h3><strong>Automating Video Uploads to TikTok with Selenium</strong></h3>
<p>Here's an example of how to automate video uploads to TikTok using Selenium in Python:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-python" data-lang="Python"><pre><code class="language-cpp"># Continue from the previous code
# ... (login code)

# Navigate to the upload page
driver.get(&quot;https://www.tiktok.com/upload&quot;)

# Select the video file to upload
video_input = driver.find_element_by_css_selector(&quot;input[type=&#039;file&#039;]&quot;)
video_input.send_keys(&quot;/path/to/your/video.mp4&quot;) # Replace with the actual video file path

# Add captions, hashtags, and other video details (you may need to adjust the selectors)
caption = driver.find_element_by_css_selector(&quot;.caption-textarea textarea&quot;)
caption.send_keys(&quot;Check out my video!&quot;)

hashtags = driver.find_element_by_css_selector(&quot;.input.hashtag-input input&quot;)
hashtags.send_keys(&quot;#tiktokautomation #raspberrypi&quot;)

# Submit the video for uploading
submit_button = driver.find_element_by_css_selector(&quot;.upload-ui-bottombar .upload-btn&quot;)
submit_button.click()

# Wait for the upload to complete (you may need to adjust the sleep duration)
time.sleep(10)

# Close the browser when done
driver.quit()</code></pre></pre>
</div>
<p>Note on the code above, you may replace the URL to other <a href="https://vottak.app/">video app</a> provided it supports API-based uploading of videos.</p>
<h3><strong>Scheduling Script Execution with Cron</strong></h3>
<p>To schedule your Python script to run every day at midnight, you can use the cron scheduler. Open the cron configuration with the following command:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">crontab -e</code></pre></pre>
</div>
<p>Then, add the following line to schedule your script:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">0 0 * * * /usr/bin/python3 /path/to/your/python/script.py</code></pre></pre>
</div>
<p>Replace <em>/path/to/your/python/script.py</em> with the actual path to your Python script. This cron job will run your script every day at midnight.</p>
<h3><strong>Conclusion</strong></h3>
<p>With a Raspberry Pi, Python scripting, and the essential libraries such as selenium and pyautogui, you can automate the process of recording videos, logging into TikTok, and uploading videos. These libraries play a pivotal role in streamlining the automation process, allowing for consistent and scheduled video uploads.</p>
<p>Automating video uploads with a Raspberry Pi showcases the creative ways you can leverage technology for content creation. It's just one example of the many possibilities this versatile single-board computer offers to enthusiasts and tinkerers. Remember to abide by TikTok's terms of service and guidelines when automating uploads and ensure that your content aligns with their policies.</p>
<p>The post <a href="https://www.teachmemicro.com/automating-video-uploads-to-tiktok-using-raspberry-pi/">Automating Video Uploads to TikTok Using Raspberry Pi</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 

Served from: www.teachmemicro.com @ 2026-07-21 17:00:58 by W3 Total Cache
-->