<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Electronics - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Electronics - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 16 May 2026 22:23:07 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/electronics/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Connect, Read, and Process Sensor Data on Microcontrollers – A Beginner's Guide ]]>
                </title>
                <description>
                    <![CDATA[ In today’s world, computers are ubiquitous and generally serve two primary purposes. The first is general-purpose computing, where they handle a wide range of tasks, including running diverse applications and programs. Examples include laptops, deskt... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/connect-read-process-sensor-data-on-microcontrollers-for-beginners/</link>
                <guid isPermaLink="false">67d45997c9e7f2d42bb1c540</guid>
                
                    <category>
                        <![CDATA[ embedded systems ]]>
                    </category>
                
                    <category>
                        <![CDATA[ microcontroller ]]>
                    </category>
                
                    <category>
                        <![CDATA[ embedded software ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ADC ]]>
                    </category>
                
                    <category>
                        <![CDATA[ I2C ]]>
                    </category>
                
                    <category>
                        <![CDATA[ real-time data processing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Signal Processing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ sensors ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Electronics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ hardware ]]>
                    </category>
                
                    <category>
                        <![CDATA[ electrical engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ MathJax ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Soham Banerjee ]]>
                </dc:creator>
                <pubDate>Fri, 14 Mar 2025 16:30:15 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1741902732575/fd41a2d5-ed4f-445d-b186-936625837c8d.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In today’s world, computers are ubiquitous and generally serve two primary purposes.</p>
<p>The first is general-purpose computing, where they handle a wide range of tasks, including running diverse applications and programs. Examples include laptops, desktops, servers, and supercomputers.</p>
<p>The second is embedded systems, which are specialized computers designed for specific functions. Commonly found in devices such as thermostats, refrigerators, cars, and other smart appliances, they rely on sensors to collect environmental data and execute their tasks efficiently.</p>
<h3 id="heading-the-role-of-sensors"><strong>The Role of Sensors</strong></h3>
<p>Sensors play a critical role in both types of computing. In embedded systems, sensors gather environmental data to help devices like autonomous vehicles, home appliances, and industrial machines perform tasks. In general-purpose computers, sensors primarily monitor internal conditions such as temperature and voltage, ensuring safe operation and preventing issues like overheating or electrical faults.</p>
<p>As Artificial Intelligence (AI) and the Internet of Things (IoT) evolve, sensors have become indispensable for gathering real-world data to support intelligent decision-making. Embedded systems leverage sensors to perceive their environment, transforming raw data into actionable insights that power automation and improve efficiency across industries.</p>
<p>This means that understanding sensor interfacing and designing robust sensor-driven software has become a vital skill for engineers and hobbyists alike.</p>
<p>Whether you're a beginner or experienced engineer, this guide will help you build a solid understanding of sensor interfacing software.</p>
<h2 id="heading-what-youll-learn-and-article-scope"><strong>What You’ll Learn and Article Scope</strong></h2>
<p>In this article, you’ll learn how to connect sensors to microcontrollers (MCUs) and design sensor software pipelines that turn raw data into meaningful, usable information. You’ll also explore practical techniques for processing sensor data accurately and efficiently in embedded systems.</p>
<p>Here’s a breakdown of what we’ll cover:</p>
<ul>
<li><p>What sensors are and how they work – An introduction to sensors, common types, and how sensor pipelines help process sensor data.</p>
</li>
<li><p>Key sensor characteristics – Important parameters like sensitivity, accuracy, precision, range, drift, and response time to help you choose the right sensor for your project.</p>
</li>
<li><p>How to interface sensors with microcontrollers – Hardware connections and communication protocols like SPI, I²C, and GPIO that allow microcontrollers to read sensor data.</p>
</li>
<li><p>Software architecture for sensor data – A high-level overview of the software pipeline that processes sensor data, including drivers, ADC support, scaling, calibration, and post-processing.</p>
</li>
<li><p>Detailed design of pipeline components – A closer look at each step in the pipeline, focusing on scaling raw data, calibrating sensors, and applying filters to clean up noisy signals.</p>
</li>
<li><p>Practical tips for power management – Best practices for handling power efficiently using low-power modes, FIFO buffers, and DMA when working with sensor data in embedded systems.</p>
</li>
</ul>
<p>By the end of this article, you’ll know how to design and implement a complete sensor data pipeline for an embedded system, from reading raw sensor data to preparing it for real-world use in intelligent, connected devices.</p>
<p><strong>Note</strong>: Advanced data processing, high-resolution ADCs, and hardware circuit design for sensors are outside the scope of this article.</p>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>To get the most out of this article, you should have:</p>
<ol>
<li><p>Basic knowledge of microcontrollers: Understanding of common peripherals like ADCs (Analog-to-Digital Converters), SPI (Serial Peripheral Interface), I2C (Inter-Integrated Circuit) and GPIO (General Purpose Input/Output). If you’re new to these protocols, <a target="_blank" href="https://www.parlezvoustech.com/en/comparaison-protocoles-communication-i2c-spi-uart/">this article provides a great overview</a>.</p>
</li>
<li><p>Basic knowledge of electronics: Familiarity with circuits and signals, including analog and digital interfaces.</p>
</li>
<li><p>Programming in C: Familiarity in embedded software development, including driver development.</p>
</li>
<li><p>(Optional) Basic knowledge of sensors: Understanding different types of sensors (like temperature, pressure, motion) is helpful but not required.</p>
</li>
</ol>
<p>Also, this article assumes the following:</p>
<ul>
<li><p>You are working with a microcontroller equipped with the peripherals needed for sensor integration. The details of microcontroller peripherals can be found in a <a target="_blank" href="https://pdf.xab3.ro/manual/reference-manual-for-stm32f405415-stm32f407417-stm32f427437-and-stm32f429439-mcus-100">reference manual for example for an STM32F4</a> series microcontroller will have all the details :</p>
</li>
<li><p>You are familiar with compilers, debuggers, and IDEs used in embedded systems. Some common tools include:</p>
<ul>
<li><p>Compilers: <a target="_blank" href="https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads">GCC</a>, <a target="_blank" href="https://developer.arm.com/documentation/dui0773/l/Introducing-the-Toolchain/Toolchain-overview?lang=en">Clang</a>,</p>
</li>
<li><p>Debuggers: <a target="_blank" href="https://sourceware.org/gdb/">GDB</a>, <a target="_blank" href="https://lldb.llvm.org/use/tutorial.html">LLDB</a></p>
</li>
<li><p>IDEs: <a target="_blank" href="https://code.visualstudio.com">Visual Studio Code</a> (VSCode) is a popular choice, especially with extensions for embedded development and debugging.</p>
</li>
</ul>
</li>
<li><p>You aim to build reliable, sensor-driven embedded systems, capable of collecting and processing real-world data efficiently.</p>
</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-a-sensor-and-sensor-pipeline">What is a Sensor and Sensor Pipeline?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-sensor-characteristics">Sensor Characteristics</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-interface-with-a-microcontroller">How to Interface with a Microcontroller</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-software-architecture">Software Architecture</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-high-level-overview-of-components">High-Level Overview of Components</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-accessing-data-from-the-sensor">Accessing Data from the Sensor</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-sensor-power-management">Sensor Power Management</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-detailed-design-of-components">Detailed Design of Components</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-1-sensor-driver">1. Sensor Driver</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-adc-support">2. ADC Support</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-3-scaling">3. Scaling</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-4-calibration">4. Calibration</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-5-data-post-processing">5. Data Post-Processing</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-a-sensor-and-sensor-pipeline"><strong>What is a Sensor and Sensor Pipeline?</strong></h2>
<p>A sensor detects changes in physical properties such as temperature, pressure, or light and converts them into electrical signals that can be measured or interpreted. For example, a thermistor is a type of resistor whose resistance changes with temperature. As the temperature varies, the resistance of the thermistor changes, altering the voltage across it. The system then interprets this voltage change to determine the temperature.</p>
<p>To better understand sensors, consider the natural sensors in the human body: the eyes, ears, skin, nose, and tongue. These natural sensors constantly send signals about the environment to the brain for processing. Different regions of the brain interpret these signals and use the information to drive actions and responses. Just like the brain processes signals from natural sensors, a microcontroller processes signals from electronic sensors using a sensor pipeline.</p>
<p>Sensors come in many types, each designed to detect specific physical properties. Some sensors have a sensing element that changes its properties in response to conditions like heat, light, or pressure. Examples include thermistors, infrared receivers, and photodiodes.</p>
<p>For detecting movement, such as acceleration and rotation, MEMS (Microelectromechanical Systems) sensors—like accelerometers and gyroscopes—are widely used.</p>
<p>To measure distance, sensors like sonars, ultrasonic sensors, and radars are common. These are just a few examples of the many types of sensors available.</p>
<p>Beyond the types of physical properties they detect, sensors also differ in their levels of integration. Some sensors are raw sensors, consisting only of a sensing element and a transducer with simple leads for direct connection to an external circuit.</p>
<p>Others, known as smart sensors, include additional components such as an ADC (analog-to-digital converter) and onboard processing capabilities, enabling them to handle more of the data processing independently.</p>
<p>The choice between a raw sensor and a smart sensor depends on your application requirements, including factors like cost, size, and the processing load on the interfacing microcontroller.</p>
<p>Returning to our human analogy, consider how vision works as a sensor pipeline. When light enters our eyes, photoreceptor cells (rods and cones) in the retina act as sensing elements, converting the light into electrical signals. These signals travel via the optic nerve to the brain’s visual cortex, where they undergo processing to form a recognizable image. The brain then interprets this information and initiates a response, like smiling when you see a beautiful scenery.</p>
<p>Similarly, a sensor pipeline for an embedded system can be defined as shown in the picture below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738828676916/75137176-c9ba-432d-bf44-bb3da093e18d.png" alt="Figure 1: A Sensor Pipeline showing analogue to digital conversion, calibration, filtering, and then processing." class="image--center mx-auto" width="918" height="183" loading="lazy"></p>
<p>Each of these steps may have different requirements based on the application. Creating a requirements document for the sensor is helpful when selecting the appropriate sensor and configuring the pipeline.</p>
<h2 id="heading-sensor-characteristics"><strong>Sensor Characteristics</strong></h2>
<p>Before you dive into the blocks of the sensor pipeline, let’s review some important characteristics of a sensor.</p>
<h3 id="heading-sensitivity"><strong>Sensitivity</strong></h3>
<p>Sensitivity is the ability of a sensor to detect small changes in the physical property it’s designed to measure.</p>
<p>Sensitivity can vary based on factors like manufacturing processes, cost, and the design of the sensing element.</p>
<p>Sensors designed for a specific property often come in different sensitivity levels, allowing users to select an appropriate sensitivity based on the application requirements.</p>
<h3 id="heading-accuracy"><strong>Accuracy</strong></h3>
<p>Accuracy is the degree to which a sensor’s measurement matches the true value of the physical property it’s measuring. Testing a sensor’s accuracy typically requires comparing its readings to those of a reference instrument.</p>
<p>A sensor may have gain and offset errors—issues that calibration can help correct. Calibration adjusts for these systematic errors, which are often due to manufacturing tolerances or design factors.</p>
<p>Once calibrated, the sensor’s output can be verified against a reference to confirm its accuracy. The required level of accuracy should be determined based on the application’s needs.</p>
<h3 id="heading-precision"><strong>Precision</strong></h3>
<p>Precision refers to the consistency or repeatability of a sensor's measurements, regardless of how close those measurements are to the true value. It indicates the sensor's ability to produce the same output under identical conditions and how finely it can resolve and report values.</p>
<p>For example, if the true temperature of an object is 12.53°C:</p>
<ul>
<li><p>A precise sensor will consistently measure values like 12.52°C, 12.53°C, or 12.54°C, even if those values are slightly offset from the true temperature.</p>
</li>
<li><p>A highly accurate sensor, on the other hand, will measure values close to 12.53°C but may lack precision if those readings vary widely (e.g., 12.50°C, 12.53°C, and 12.56°C).</p>
</li>
</ul>
<p>For applications requiring exact measurements, a sensor with both high accuracy (closeness to the true value) and high precision (low variability) is essential. This is especially important in distinguishing small differences, such as between 12.5°C and 12.53°C.</p>
<p>In contrast, applications with less stringent requirements might use sensors with broader tolerances, such as ±1°C, which are sufficient for general monitoring purposes.</p>
<h3 id="heading-range"><strong>Range</strong></h3>
<p>The range of a sensor refers to the span between the maximum and minimum values of the physical property it can measure while maintaining its specified precision and accuracy. A sensor's operating range may extend beyond its measurement range, but the measurement range defines the limits within which the sensor reliably adheres to its specified sensitivity, accuracy, and response time.</p>
<h3 id="heading-drift"><strong>Drift</strong></h3>
<p>Drift is when a sensor's output changes over time due to conditions like temperature or humidity. Components within the sensor, including the sensing element, may be sensitive to these conditions, leading to gradual shifts in measurements.</p>
<p>For example, many components are affected by temperature and humidity changes, which can alter sensor readings. Also, sensors with internal oscillators may experience time-based drift, impacting accuracy.</p>
<p>Regular calibration with an accurate external reference (such as a precise clock) can help correct for drift and maintain reliable measurements. For certain applications, selecting a sensor with acceptable drift characteristics is crucial.</p>
<h3 id="heading-response-time"><strong>Response Time</strong></h3>
<p>Response time is the duration a sensor takes to detect and reflect a change in the measured physical property. For example, if the temperature rises by 5°C, the response time indicates how long the temperature sensor takes to reflect this change in its output.</p>
<p>Response time depends on the sensor’s design, manufacturing quality, and internal components, such as the ADC (Analog-to-Digital Converter), averaging circuits, and filters within the sensor pipeline.</p>
<p>All the parameters mentioned above are thoroughly documented in the sensor’s data-sheet. In practice, it’s a good idea to create a sensor requirements document for each specific application, detailing these key parameters as a baseline for sensor selection.</p>
<p>Now that you’ve examined the key characteristics of sensors, let’s explore how you can connect them to a microcontroller for real-world applications.</p>
<h2 id="heading-how-to-interface-with-a-microcontroller"><strong>How to Interface with a Microcontroller</strong></h2>
<h3 id="heading-choosing-a-communication-protocol">Choosing a Communication Protocol</h3>
<p>Another essential aspect of sensor requirements is specifying the communication interface between the sensor and the MCU or processor in the system. It’s important to understand how the sensor will be interfaced based on its output signal type and the available pins on the microcontroller.</p>
<p>For instance, certain sensors may connect directly to an analog or digital input pin on a microcontroller. A raw sensor, such as a temperature sensor, typically connects to an analog input pin, which is then read by the microcontroller’s internal ADC (Analog-to-Digital Converter).</p>
<p>In contrast, a digital-output sensor connects to a digital GPIO (General Purpose Input/Output) pin. For instance, speed sensors generate square waves with variable pulse widths to indicate speed. These signals are usually connected to a GPIO pin configured as an external interrupt or timer capture input, allowing the microcontroller to measure pulse width accurately.</p>
<p>A smart sensor, on the other hand, often supports communication protocols like SPI (Serial Peripheral Interface) or I2C (Inter-Integrated Circuit). These interfaces enable the microcontroller to configure the sensor, check its status, and retrieve data through register reads and writes.</p>
<p>Choosing the appropriate communication protocol for interfacing a sensor depends on the available pins in the system and the specific requirements of the application.</p>
<p><strong>Tip</strong>: When working with protocols like I²C or SPI, using tools such as <a target="_blank" href="https://www.saleae.com">Saleae</a> logic analyzers can greatly simplify debugging and validation. Logic analyzers capture and visualize communication signals, and tools like Saleae offer built-in protocol interpreters to help you decode sensor communication in real time. This can be especially helpful when troubleshooting configuration issues, timing problems, or communication errors during sensor interfacing.</p>
<p>Figure 2 below shows an example of a microcontroller connected to 4 sensors having different interfaces.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738828730915/25e62db6-a583-427a-bd77-c61c33990cdf.png" alt="Figure 2: A microcontroller interfacing with different sensors using different communication interfaces." class="image--center mx-auto" width="921" height="356" loading="lazy"></p>
<h3 id="heading-determining-power-requirements">Determining Power Requirements</h3>
<p>Power requirements are another key consideration when interfacing a sensor. Sensors may operate at different voltages (for example, 3.3V or 5V), so ensuring the microcontroller can accommodate these levels is essential. Level converters can bridge voltage mismatches, ensuring compatibility between the sensor and microcontroller voltage levels.</p>
<p>Timing and sampling requirements must also be evaluated, especially for sensors generating high-frequency data. Configuring external interrupts on GPIO pins can ensure timely data capture, while techniques like using DMA can streamline data transfer for sensors sampling at high frequencies without CPU involvement.</p>
<p>Now that you’ve learned about communication protocols and hardware connections, let’s focus on designing the software architecture that acquires, processes, and prepares sensor data for use. Designing effective software is crucial for obtaining clean, reliable data from the sensor.</p>
<h2 id="heading-software-architecture"><strong>Software Architecture</strong></h2>
<p>Now that we’ve chosen the sensor and communication protocol, let’s design the software architecture for the sensor pipeline. This software runs on the microcontroller connected to the sensor and processes raw data to make it clean and usable.</p>
<p>While application-level data processing is beyond the scope of this article, let’s focus on interfacing with the sensor and preparing the data for application use.</p>
<p>The sensor processing pipeline can be broken into the following components:</p>
<ol>
<li><p>Sensor Driver</p>
</li>
<li><p>Analog-to-Digital Conversion (ADC) Support</p>
</li>
<li><p>Scaling</p>
</li>
<li><p>Calibration</p>
</li>
<li><p>Data Post-Processing</p>
</li>
</ol>
<p>Let’s examine a high-level overview of these components for both smart and raw sensors.</p>
<h3 id="heading-high-level-overview-of-components"><strong>High-Level Overview of Components</strong></h3>
<ol>
<li><p><strong>Sensor Driver</strong></p>
<ol>
<li><p>Smart sensors: The driver configures the sensor, manages power, and handles read and write operations to the sensor registers over a communication protocol like SPI, I2C.</p>
</li>
<li><p>Raw sensors: The driver may only control GPIOs for power management, as raw sensors typically lack registers.</p>
</li>
</ol>
</li>
<li><p><strong>Analog-to-Digital Conversion (ADC) Support</strong></p>
<ol>
<li><p>Smart sensors: Include an onboard ADC, which is configured through the sensor driver.</p>
</li>
<li><p>Raw sensors: Requires an external ADC, an ADC driver implemented in software to configure the ADC, initiate conversions, and retrieve data.</p>
</li>
</ol>
</li>
<li><p><strong>Scaling</strong>: Scaling is necessary for both smart and raw sensors. It converts digital counts after the analog to digital conversion into meaningful physical quantities using formulas provided in the sensor data sheet. For example, a temperature sensor will use a formula to convert digital counts to degree Celsius.</p>
</li>
<li><p><strong>Calibration</strong>: Once the measured physical quantity is obtained, calibration adjusts the value by applying offsets, gains, or both to correct errors. This process ensures the sensor output aligns with reference values across its entire measurement range. A detailed discussion of the calibration process will follow in the next section.</p>
</li>
<li><p><strong>Data Post-Processing</strong>: Post-processing techniques, such as filtering are applied to improve data quality and reduce noise. Common filters such as low-pass or high-pass filters can remove unwanted frequency components.</p>
</li>
</ol>
<h3 id="heading-accessing-data-from-the-sensor"><strong>Accessing Data from the Sensor</strong></h3>
<p>The method of accessing data depends on the whether it’s a raw sensor or a smart sensor. Smart sensors will have onboard ADCs and FIFOs. Before delving into how data is accessed, it’s important to first understand sampling frequency.</p>
<h4 id="heading-sampling-frequency">Sampling Frequency:</h4>
<p>The frequency of taking a measurement from the sensor must follow the <a target="_blank" href="https://www.allaboutcircuits.com/technical-articles/nyquist-shannon-theorem-understanding-sampled-systems/">Nyquist-Shannon sampling theorem</a>. It states that the sampling rate must be twice the highest frequency component of the signal to be measured to accurately reconstruct the measured data.</p>
<p>The sampling frequency defines how often the sensor captures data, which affects how the data is accessed. Depending on whether the sensor is a raw sensor or a smart sensor, the approach to handling this sampled data varies.</p>
<p><strong>Smart Sensors:</strong></p>
<ol>
<li><p>Data register: The sensor writes sampled data directly into a register based on the set sample frequency updated during setup. The microcontroller reads this data register based on a data conversion completion interrupt.</p>
</li>
<li><p>FIFObBuffer: Some sensors include FIFO (First-In, First-Out) buffers to store multiple data points. When enabled, the FIFO updates at the configured sampling frequency and trigger interrupts when it becomes full or reaches a predefined level.<br> The benefits of FIFO include:</p>
<ol>
<li><p>Power efficiency: The MCU can process data in batches, reducing CPU overhead and allowing it to enter low-power mode during data collection.</p>
</li>
<li><p>Sampling and processing rate matching: FIFO buffers help reconcile differences between the sensor’s sampling rate and the MCU’s data processing rate.</p>
</li>
<li><p>For MCUs with Direct Memory Access (DMA), data transfer from the sensor to MCU memory can occur without CPU intervention, further reducing power consumption.</p>
</li>
</ol>
</li>
</ol>
<p><strong>Raw Sensors:</strong></p>
<p>For raw sensors, the MCU triggers ADC conversions at the sampling frequency, often using a timer interrupt. Data is read upon the ADC conversion complete interrupt, allowing the MCU to sleep during conversions and between samples to save power.</p>
<h3 id="heading-sensor-power-management"><strong>Sensor Power Management</strong></h3>
<p>Power management is critical for energy-sensitive applications. Strategies include:</p>
<ol>
<li><p>Low-power modes: Many sensors support low-power modes configurable through sensor registers.</p>
</li>
<li><p>GPIO-controlled power cycling (Duty-Cycling): For sensors without built-in low-power modes, the microcontroller can toggle the sensor’s power line using a GPIO pin, reducing power consumption further. Figure 3 below shows the diagram of a raw temperature sensor whose power is controlled using a GPIO from the MCU. For example, a temperature sensor in sleep mode can be activated only when temperature readings are required.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739042040654/1f2d4bbd-f15a-417a-9c79-3b93384e95bd.png" alt="Figure 3: Raw Temperature Sensor Interfacing a MCU" class="image--center mx-auto" width="549" height="557" loading="lazy"></p>
<p>The above techniques ensure efficient use of power while maintaining the required data sampling rate and sensor responsiveness.</p>
<p>With the high-level architecture in mind, we’ll now dive into the detailed design of each pipeline component.</p>
<h2 id="heading-detailed-design-of-components"><strong>Detailed Design of Components</strong></h2>
<p>In this section, you’ll delve into the key components of the sensor pipeline outlined in the Software Architecture section.</p>
<h3 id="heading-1-sensor-driver"><strong>1. Sensor Driver</strong></h3>
<p>The sensor driver is responsible for managing communication, configuration, power, and data acquisition for both smart and raw sensors.</p>
<h4 id="heading-smart-sensor-driver">Smart Sensor Driver:</h4>
<ol>
<li><p>Communication driver: Generic I2C or SPI drivers on the MCU can be adapted using wrapper functions to handle sensor-specific requirements, such as 1-byte, 2-byte, or 4-byte transfers.</p>
</li>
<li><p>Configuration: Typical tasks include setting the sampling rate, configuring interrupts, managing FIFO buffers, and, if needed, clock settings.</p>
</li>
<li><p>Power management: APIs should allow higher software layers to transition sensors between power modes by writing to specific registers or controlling GPIO lines for sensors without built-in power modes.</p>
</li>
</ol>
<h4 id="heading-raw-sensor-driver">Raw Sensor Driver:</h4>
<p>For raw sensors, the driver primarily manages power, often through GPIO-controlled toggling.</p>
<h3 id="heading-2-adc-support"><strong>2. ADC Support</strong></h3>
<p>ADC support is required only for raw sensors. In this article, we’re focusing on SAR ADCs, which are commonly embedded in microcontrollers.</p>
<h4 id="heading-how-sar-adcs-work">How SAR ADCs Work?</h4>
<p>A SAR ADC converts an analog signal to a digital value over multiple clock cycles, with the number of cycles equal to its bit resolution (for example, 10 cycles for a 10-bit ADC).</p>
<h4 id="heading-key-terms-related-to-adcs">Key terms related to ADCs:</h4>
<ol>
<li><p>Reference Voltage (VRef): Represents the maximum voltage the ADC can measure. Analog signals exceeding this limit must be scaled down.</p>
</li>
<li><p>Resolution: Determines the smallest detectable voltage change. For example, a 10-bit ADC with a 3.3V VRef has a resolution of 3.22 mV</p>
</li>
</ol>
<p>$$V_{\text{Res}} = V_{\text{Ref}} /2^{10}$$</p><p>The ADC result is stored in a data register, which can then be scaled to meaningful physical units.</p>
<h3 id="heading-3-scaling"><strong>3. Scaling</strong></h3>
<p>Scaling converts ADC counts into meaningful physical values, such as temperature (°C) or acceleration (g) depending on the sensor type. Sensor datasheets typically provide the necessary formulas or lookup tables.</p>
<p>For example, the method to convert a voltage measured by a raw temperature sensor to temperature value is shown below:</p>
<p>$$V_{\text{Measured}} = Counts_{\text{ADC}} / 2^{10} * V_{\text{Ref}} \quad \text{(Get V_Measured from ADC Counts)}$$</p><p>$$Temperature_{\text{Measured}} = V_{\text{Measured}} * T_{\text{C/mV}} \quad \text{(Get Temperature physical value)}$$</p><p>Similarly, a 3-axis accelerometer maps counts on the X, Y, and Z axes to acceleration values in g or milli-g.</p>
<h3 id="heading-4-calibration"><strong>4. Calibration</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738829686302/bfa643dc-5e01-4b24-b885-b682acdb11cb.png" alt="Figure 4a: Calibration with gain &amp; offset | Figure 4b: Calibration with fixed offset" class="image--center mx-auto" width="1149" height="421" loading="lazy"></p>
<p>The figure above on the left (4a) is showing Calibration with gain and offset, while the figure above on the right (4b) is showing calibration with fixed offset.</p>
<p>$$x_{\text{calibrated}} = Gain * x_{\text{raw}} + Offset \quad \text{(Figure 4a - Linear Calibration)}$$</p><p>$$x_{\text{calibrated}} = x_{\text{raw}} + Offset \quad \text{(Figure 4b - Fixed offset Calibration)}$$</p><p>Calibration ensures the sensor’s output aligns with reference measurements, correcting for errors introduced by design, materials, or manufacturing.</p>
<h4 id="heading-types-of-errors">Types of Errors:</h4>
<ol>
<li><p>Offset error: A constant deviation of the sensor’s output from the true reference value, regardless of input magnitude.</p>
</li>
<li><p>Gain error: A proportional error where the sensor’s output scale deviates from the expected value, causing the output to increase or decrease incorrectly relative to the input.</p>
</li>
</ol>
<h4 id="heading-calibration-methods">Calibration Methods:</h4>
<ol>
<li><p>2/3-Point calibration: This type of calibration may involve either applying a fixed offset to the raw value or applying both gain and offset. Figure 4a illustrates an example of a gain/offset calibration, while Figure 4b depicts offset calibration. In both figures, the y-axis represents the reference value measured by an accurate instrument, while the x-axis represents the raw value measured by the sensor after ADC.</p>
</li>
<li><p>N-Point calibration: Involves multiple points for more complex, non-linear error correction.</p>
</li>
</ol>
<h4 id="heading-implementation">Implementation:</h4>
<ol>
<li><p>Calibration points shall cover the sensor’s entire measurement range for accuracy.</p>
</li>
<li><p>Parameters like gain and offset once estimated shall be stored in a non-volatile memory in the system for persistence to be used across power cycles.</p>
</li>
</ol>
<h3 id="heading-5-data-post-processing"><strong>5. Data Post-Processing</strong></h3>
<p>Post-processing covered in this section talks about removing noise and unwanted signal components, which improves data reliability.</p>
<h4 id="heading-filtering">Filtering</h4>
<p>Filtering is the process of removing unwanted frequency components from a signal to improve data quality. There are several different types of filters:</p>
<ul>
<li><p>Low-Pass Filters: Allows low-frequency signals to pass while attenuating high-frequency noise.</p>
</li>
<li><p>High-Pass Filters: Allows high-frequency signals to pass while attenuating low-frequency noise. (for example, gravitational acceleration in accelerometer data).</p>
</li>
<li><p>Band-Pass Filters: Retains only signals within a specific frequency range, removing both lower and higher frequencies outside the desired band.</p>
</li>
</ul>
<p>These filters are often implemented as FIR (Finite Impulse Response) or IIR (Infinite Impulse Response) filters. IIR filters are easy to implement and computationally efficient while FIR filters are computationally intensive but have better control over the frequency response.</p>
<p>Here, we will explore a simple low-pass filter known as the Exponential Moving Average (EMA), a type of IIR filter. A moving average filter is a mathematical technique that smooths short-term fluctuations while highlighting longer-term trends.</p>
<p>Unlike other moving average filters, EMA does not require maintaining a buffer, making it more memory-efficient. It is also more responsive to data changes while still providing smoothing, making it well-suited for real-time filtering. EMA assigns greater weight to recent data samples than older ones, allowing it to adapt quickly to changes in sensor readings.</p>
<p>EMA can be calculated like this:</p>
<p>$$EMA_{\text{t}} = \alpha * x_{\text{t}} + (1 - \alpha) * EMA_{\text{t - 1}}$$</p><p>$$\alpha = 2 / (N + 1) \quad \text{(Smoothening Factor, N - filter window size)}$$</p><p>$$EMA_{\text{t}} \quad \text{(Exponential Moving Average in current iteration)}$$</p><p>$$x_{\text{t}} \quad \text{(New Data Sample in Current Iteration)}$$</p><p>$$EMA_{\text{t - 1}} \quad \text{(Exponential Moving Average in the last iteration)}$$</p><p>Now that we understand the Exponential Moving Average (EMA) filter, here are two key factors to consider when tuning it for an application:</p>
<ul>
<li><p>Smoothing vs. Responsiveness: A higher smoothing factor (closer to 1, smaller filter window size) gives more weight to recent data, making the filter more responsive to changes but less effective at noise reduction. A lower smoothing factor (closer to 0, larger filter window size) provides better noise reduction but reacts more slowly to data changes.</p>
</li>
<li><p>Application-Specific Tuning: The smoothing factor should be chosen based on the sampling rate, sensor sensitivity, and application requirements. Real-time systems often require a balance between quick responsiveness and stable output.</p>
</li>
</ul>
<p>Here’s a code sample for EMA:</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdint.h&gt;</span></span>

<span class="hljs-comment">// Exponential Moving Average (EMA) filter implementation</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> FILTER_WINDOW 5</span>

<span class="hljs-comment">// Function to calculate EMA</span>
<span class="hljs-function"><span class="hljs-keyword">float</span> <span class="hljs-title">calculateEMA</span><span class="hljs-params">(<span class="hljs-keyword">float</span> ema, <span class="hljs-keyword">float</span> new_value, <span class="hljs-keyword">float</span> alpha)</span> </span>{
    <span class="hljs-keyword">return</span> (alpha * new_value) + (<span class="hljs-number">1</span> - alpha) * ema;
}

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">float</span> sensorReadings[] = {<span class="hljs-number">26.0</span>, <span class="hljs-number">27.5</span>, <span class="hljs-number">28.2</span>, <span class="hljs-number">27.0</span>, <span class="hljs-number">26.8</span>, <span class="hljs-number">26.5</span>, <span class="hljs-number">27.2</span>};
    <span class="hljs-keyword">int</span> numReadings = <span class="hljs-keyword">sizeof</span>(sensorReadings) / <span class="hljs-keyword">sizeof</span>(sensorReadings[<span class="hljs-number">0</span>]);

    <span class="hljs-keyword">float</span> alpha = <span class="hljs-number">2.0f</span> / (FILTER_WINDOW + <span class="hljs-number">1</span>); <span class="hljs-comment">// Standard EMA formula</span>
    <span class="hljs-keyword">float</span> ema = sensorReadings[<span class="hljs-number">0</span>];  <span class="hljs-comment">// Initialize EMA with the first reading</span>

    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"EMA Filtered Sensor Data:\n"</span>);

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; numReadings; i++) {
        ema = calculateEMA(ema, sensorReadings[i], alpha);
        <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Reading %d: Raw = %.2f, EMA = %.2f\n"</span>, i + <span class="hljs-number">1</span>, sensorReadings[i], ema);
    }

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>In summary, sensors are the backbone of modern smart devices, bridging the gap between the physical world and digital systems. From consumer electronics to industrial automation and medical devices, they enable devices to perceive and interact with their environments.</p>
<p>Understanding how sensors work, the components of their data pipeline, and their integration with microcontrollers is essential for engineers and hobbyists alike. By designing effective pipelines, developers can ensure accurate, clean, and reliable data, enabling systems to meet performance and power efficiency goals.</p>
<p>If you have questions or want to talk more about this topic, feel free to reach out on <a target="_blank" href="https://x.com/sohamstars">Twitter</a> or <a target="_blank" href="https://x.com/sohamstars">Lin</a><a target="_blank" href="https://www.linkedin.com/in/sohambanerjee2/">kedIn</a>. Always happy to connect.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Setup an LED Light and Make it Blink with Code ]]>
                </title>
                <description>
                    <![CDATA[ Coding an LED Light is introductory project that shows you how software and hardware interact with each other. It's a simple project you can complete in a weekend that'll help you learn some basic aspects of hardware. By the end of the project, you w... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/code-behind-an-led-light/</link>
                <guid isPermaLink="false">66d45f33230dff0166905811</guid>
                
                    <category>
                        <![CDATA[ Electronics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ hardware ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ilknur Eren ]]>
                </dc:creator>
                <pubDate>Mon, 08 Jun 2020 21:50:21 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-25-at-4.15.01-PM-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Coding an LED Light is introductory project that shows you how software and hardware interact with each other. It's a simple project you can complete in a weekend that'll help you learn some basic aspects of hardware.</p>
<p>By the end of the project, you will code your own LED light, have the knowledge to manipulate the LED to on/off in intervals you choose, and learn basic principles of hardware.</p>
<p>The <a target="_blank" href="https://www.amazon.com/ELEGOO-Project-Tutorial-Controller-Projects/dp/B01D8KOZF4">Elegoo Uno</a> starter kit has all the hardware as well as instructions you need to make a simple LED Light. The LED Light is the first project offered with their kit.</p>
<p>Elegoo Uno comes with many other projects and takes you through from beginner to advanced projects. Each project in the box advances your skills in a simple, easy to follow way.</p>
<h2 id="heading-components-youll-need">Components You'll Need</h2>
<h3 id="heading-elegoo-uno-r3">Elegoo Uno R3</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-24-at-7.49.14-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Elegoo Uno R3</em></p>
<p>The Elogoo Uno R3 is a microcontroller board. Microcontrollers are embedded inside devices to control the actions and features of a product. They are compact integrated circuits designed to control operations.</p>
<p>The microcontroller that is included in the Elogoo Uno R3 has 14 digital input/output pins, 6 analog inputs, a USB connection, a power jack, and a reset button. This board has everything you need to support the microcontroller. Simply plug in the USB Cable to turn the microcontroller on.</p>
<h3 id="heading-usb-cable">USB Cable</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-24-at-7.49.22-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>USB Cable</em></p>
<p>You need a USB Cable to connect the Elegoo Uno R3 to your computer and turn it on. USB stands for Universal Serial Bus. The USB is used to connect your computer to devices such as digital cameras, printers, scanners, and external hard drives.</p>
<p>In our project, we will use a USB cable to connect our microcontroller to our computer.</p>
<h3 id="heading-leds">LEDs</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/image-161.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>LED Light</em></p>
<p>LED stands for light emitting diode. It has a positive and negative lead. The longer side is the positive lead.</p>
<h2 id="heading-how-to-assemble-the-components">How to assemble the components</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-25-at-4.15.01-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In this project, we are only going to make the LED blink.</p>
<p>First, we need to plug in the USB Cable to the board and then the computer.</p>
<p>Then we need to plug in the LED to GND (GND is the reference point in an electrical circuit from which voltages are measured, and is a common return path for electric current) and the 13 input on the board.</p>
<h3 id="heading-code-to-make-the-led-flash-onoff">Code to make the LED flash on/off:</h3>
<p>After the microcontroller board is plugged into the computer and the LED is on the board itself, we need to write some simple code to make the LED blink.</p>
<pre><code class="lang-php"><span class="hljs-comment">// the setup function runs once when you press reset or power the board</span>

<span class="hljs-keyword">void</span> setup() {
  <span class="hljs-comment">// initialize digital pin LED_BUILTIN as an output.</span>
  pinMode(LED_BUILTIN, OUTPUT);
}

<span class="hljs-comment">// the loop function runs over and over again forever</span>
<span class="hljs-keyword">void</span> loop() {
  digitalWrite(LED_BUILTIN, HIGH);   <span class="hljs-comment">// turn the LED on </span>
  delay(<span class="hljs-number">1000</span>);                       <span class="hljs-comment">// wait for a second</span>
  digitalWrite(LED_BUILTIN, LOW);    <span class="hljs-comment">// turn the LED off</span>
  delay(<span class="hljs-number">1000</span>);                       <span class="hljs-comment">// wait for a second</span>
}
</code></pre>
<p>The code above basically turns the LED on for 1 second and then turns it off for one second.</p>
<p>This function is in a continuous loop. The <code>digitalWrite</code> is a function that takes in 2 parameters, <code>LED_BUILTIN</code> and <code>HIGH || LOW</code> . The loop basically takes in the LED, and then turns the volt to <code>HIGH</code> which turns it on. Then after 1 second it turns the same LED off by turning the volt to <code>LOW</code> .</p>
<h3 id="heading-heres-the-final-product">Here's the Final Product:</h3>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/D6IkSkKcY5s" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p>The goal of this little LED Light Coding project was to introduce you to elementary principles of how hardware and software can be combined. I hope you enjoyed it!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What's The Best Way To Prototype Circuits? ]]>
                </title>
                <description>
                    <![CDATA[ By Jared Wolff This post is originally from www.jaredwolff.com There’s something that always goes wrong with a first revision circuit board design. No matter how long you spend imagining how a circuit will work, it will bork in the most unexpected wa... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/whats-the-best-way-to-prototype-circuits/</link>
                <guid isPermaLink="false">66d85069f6b5e038a1bde7fc</guid>
                
                    <category>
                        <![CDATA[ Electronics ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 04 Jun 2019 00:07:25 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/06/Copy-of-Dashboard-2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Jared Wolff</p>
<p><strong>This post is originally from <a target="_blank" href="https://www.jaredwolff.com/circuit-boards-versus-breadboarding/">www.jaredwolff.com</a></strong></p>
<p>There’s something that always goes wrong with a first revision circuit board design. No matter how long you spend imagining how a circuit will work, it will bork in the most unexpected ways.</p>
<p>In the case of my <a target="_blank" href="https://www.jaredwolff.com/dimming-ac-lights-with-a-microcontroller/">latest project</a>, I overlooked a critical pice of circuitry. My revelation? Turns out you can’t reliably shunt 375mW of power into a 100mW resistor. ? Unfortunately, as you guessed it, this would require rework.</p>
<p>So, in my quest to make the right prototyping solution, I thought: “Why not share the things going through my head right now”</p>
<p>And thus, this blog post was born. ?</p>
<h2 id="heading-the-solder-less-breadboard">The (Solder-less) Breadboard</h2>
<p>When you are time constrained the solder-less breadboard is a go-to. This type of electronic prototyping is painless but there are some drawbacks. Most notably, it does not play well with analog optimization. I’ll get into that a little later in this post.</p>
<p>I recently assembled an indoor air quality PM2.5 sensor and interfaced it with a Particle Argon. I assembled it using <a target="_blank" href="https://www.jaredwolff.com/prototype-with-wire-wrap/">wire wrap</a>. but it was a complete disaster. In comparison, the solder-less breadboard kept things organized and good looking to boot.</p>
<p><img src="https://www.jaredwolff.com/circuit-boards-versus-breadboarding/images//DSC01299.jpeg" alt="Solderless Breadboard and Partile" width="730" height="487" loading="lazy"></p>
<p>Electrical engineers come to  love (or hate) bread boards early in their educational pursuits. For some it can be an outlet to get creative and make beautiful layouts. Many first year computer engineering students take pride in their breadboard designs. So much so that their breadboards looked as if assembled by a robot.</p>
<p>These days though, I don’t wire together huge digital logic circuits like in college. I do use solder-less breadboards though to make solid connections to development modules. As you can see int the above picture, I’ve used 3 separate boards which are all available across the web. Connecting them together took approximately 10 minutes as most. It took me approximately 15 minutes to assemble the wire wrap version.</p>
<h2 id="heading-the-breadboard">The Breadboard ?</h2>
<p>Sometimes a solder-less breadboard is great but it isn’t meant for every situation. What if you need something to be reliable? What if you’re working with high voltages? If you’re looking for more but don’t want to jump to making your own PCB, this is your next stop.</p>
<p>Creating a solderable breadboard is not too dissimilar to a solder-less version. It took me about 20 minutes to assemble the circuit in the picture below.</p>
<p><img src="https://www.jaredwolff.com/circuit-boards-versus-breadboarding/images//DSC01301.jpeg" alt="Breadboarded Zero Cross Circuit" width="730" height="487" loading="lazy"></p>
<p>The breadboard above is the replacement zero-cross circuit mentioned earlier. Considering I was working with line voltage I was very cautious about the assembly.</p>
<p>So after triple checking my work. I plugged it in and you know what?</p>
<p><em>It worked like a charm.</em></p>
<p>Breadboards take some time to plan but when you get them right, they’re as good as a normal circuit board.</p>
<p>Furthermore, you don’t always have to solder every single connection together. I created this JTAG level shifter board about a year ago. That way I could run my circuit boards in ranges from 1.8V to 5V and have it work with the standard 3.3V programmer.</p>
<p><img src="https://www.jaredwolff.com/circuit-boards-versus-breadboarding/images//DSC01287.jpeg" alt="Breadboard and Wirewrap" width="730" height="487" loading="lazy"></p>
<p>In this case, I used solder and <a target="_blank" href="https://www.jaredwolff.com/prototype-with-wire-wrap/">wire wrap</a>. connections. For future projects I plan on using the JTAG level shifter board I designed not too long ago. It’s 1/5 the size and as functional as the one above.</p>
<h2 id="heading-going-beyond-the-breadboard">Going Beyond The Breadboard</h2>
<p>I am definitely not afraid of <a target="_blank" href="https://www.jaredwolff.com/how-to-self-assemble-circuit-boards/">assembling my own circuit boards</a>. There’s a time and a place for that. There are still some things you can do before ever having to open up your schematic capture program.</p>
<p><em>Always consider the use of circuits and development platforms that already exist!</em></p>
<p>Being smart about your design process pays dividends to your future self. It helps you focus on the sticky problems rather than the trivial distraction. If you are in need of a pre-designed circuit board Sparkfun and Adafruit are great resources. They’ve already created the breakout boards for ICs that interest most makers.</p>
<p>To put the icing on the cake, in most cases, these circuit boards are <strong>diiiiirt cheap.</strong></p>
<p>Companies like TI also make development boards. The board are reasonably priced and usually in stock on Digikey and their web store. Some of my favorite manufacturer development boards include the NRF52DK and the LT3092EDD. I use them both often and for some very good reasons.</p>
<p><img src="https://www.jaredwolff.com/circuit-boards-versus-breadboarding/images//DSC01288.jpeg" alt="LT3092EDD Development Board" width="730" height="487" loading="lazy"></p>
<p>The LT3092EDD is my go to for regulating current from a variable voltage source. No mater what the input voltage, it will shunt the current anywhere from 0-200mA. You can place several LT3092 in parallel increasing the current capability. I use it for static discharge tests and validation that have a need for constant current sinks.</p>
<p>As for the NRF52DK, not only can I develop on this board but I can use it as a programmer too. With tons of ways to expand off the board, it’s doesn’t leave my desk very often.</p>
<p><img src="https://www.jaredwolff.com/circuit-boards-versus-breadboarding/images//DSC01297.jpeg" alt="NRF52DK" width="730" height="487" loading="lazy"></p>
<p><em>But what if there isn’t a development board?</em></p>
<p>Sometimes neither type of breadboard is great.  This is especially true if you’re prototyping is dependent on the shape and form of the copper on your board.  I’d expect if you did breadboard a switching power supply you may get some very unintended operation.</p>
<p>Laying out a power supply circuitry tends to be a bit more complex than say a digital signal. Yes, it will work with a tiny trace connecting two parts, will it work well? Unlikely.</p>
<p>Below is a design which allows for current transfer to the inner power layer. As you could imagine, a skinny trace and one via may work. In reality,  they’d act more like a resistor high current situations.</p>
<p><img src="https://www.jaredwolff.com/circuit-boards-versus-breadboarding/images//powercircuit.png" alt="Eagle Power Layout" width="730" height="538" loading="lazy"></p>
<p>Although you may get better connections, you run the risk of higher costs. Plus is much harder to change your circuitry down the road.  Things get more complicated when the parts get smaller and the signals pushed inside. It’s not impossible though..</p>
<p>When changes are necessary, my most used tools are wire wrap wire or coil wire and my trusty X-acto knife. You can use the former to make the connections and the later to break connections. This does require a steady hand and patience but it’s possible.</p>
<p><img src="https://www.jaredwolff.com/circuit-boards-versus-breadboarding/images//DSC01295.jpeg" alt="PCB Rework" width="730" height="487" loading="lazy"></p>
<p>In the picture above, I cut away thermal traces around pads and reconnected to another set of traces. You may have to take my word on this one considering it’s hard to tell from the picture! I did all the work under a microscope to avoid error.</p>
<h2 id="heading-you-can-du-it">You can du it ?</h2>
<p>There’s a handful of ways to assemble a circuit. It’s all up to you how you want to get it done. I’ve seen some very cool <a target="_blank" href="https://hackaday.com/2018/11/19/flywire-circuits-at-the-next-level/">circuit art</a> out there that accomplishes the same thing as a bread board.</p>
<p>If you haven't already noticed, I ended up going with a breadboard design. It was faster to assemble and test versus ordering a whole new circuit board. I will likely spin another board in the future. In the meantime this little breadboard should do fine.</p>
<p>I use all these techniques when it comes to working with my clients. No technique is off the table and it always usually benefits everyone. In reality, a breadboard always evolves into a circuitboard of some kind. It’s good to know though that the circuit <strong>will work</strong> before turning it into a costly prototype.</p>
<p>So until next time, when you find yourself with the same quandry remember your options.</p>
<p>Have fun!</p>
<p><a target="_blank" href="https://www.jaredwolff.com/about/">Jared</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Save Money and Assemble Your Own Circuit Boards ]]>
                </title>
                <description>
                    <![CDATA[ By Jared Wolff Self assembling circuit boards is the cheapest way to get components on circuit boards. Period. Don’t believe me? Believe these screenshots:   Self assembled: $143.84 + Tax & Shipping Professionally assembled: $362.83 + Tax & Shipp... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-save-money-and-assemble-your-own-circuit-boards/</link>
                <guid isPermaLink="false">66d8505429e30bc0ad47757d</guid>
                
                    <category>
                        <![CDATA[ Electronics ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 03 Jun 2019 20:33:36 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/06/Assemble-Circuit-Board-3-2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Jared Wolff</p>
<p>Self assembling circuit boards is <strong>the</strong> cheapest way to get components on circuit boards.</p>
<p>Period.</p>
<p>Don’t believe me? Believe these screenshots:  </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-02-09_at_5.25.41_PM_copy-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-02-09_at_5.08.49_PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-02-09_at_5.09.57_PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Self assembled: <strong>$143.84 + Tax &amp; Shipping</strong></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-02-09_at_5.37.30_PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Professionally assembled: <strong>$362.83 + Tax &amp; Shipping</strong></p>
<p>That’s about $50 per board versus  $120 per board. That’s <strong>huge.</strong> Plus 18 days is a <strong>long time</strong> to wait for three circuit boards.</p>
<p>In this post, I’m going to to talk about the biggest tips and tricks I’ve learned over the years on how to assemble my own circuit boards.  I have no doubt they’ll be immediately useful for your current and future projects.</p>
<p>So, to start with let’s talk about CAD.</p>
<h2 id="heading-export-your-cad">Export Your CAD</h2>
<p>The golden standard for the industry is the Gerber file. Gerber files are the  translation of all the pretty shapes, traces, pads, silkscreen and drills into something useful for a board fabricator.  There are other formats out there like ODB++. If you’ve ever looked inside an ODB++ file though, it’s just a bunch of Gerbers packaged up. ?‍♂️</p>
<p>If you’re interested in learning more about Gerbers and my process of checking them, <a target="_blank" href="https://www.circuitdojo.org/fundamentals/#reviewing-your-gerbers">go watch this video</a> and then come back. No worries, I’ll be right here.</p>
<p>Fortunately, most vendors will take the raw CAD files especially if you use something like Eagle CAD. For instance, when I go to purchase a circuit board on <a target="_blank" href="https://www.oshpark.com">OSH Park</a>, I’ll upload my <code>.brd</code> file. In most cases, it gets promptly processed, and spits a price back.</p>
<p>These same files can also be used for the purchase of a <strong>solder paste stencil.</strong> Solder paste stencils allow you to applicate solder paste only to the openings in the solder mask on your circuit board. Yes, you can assemble a circuitboard without using solder paste or a solder stencil but I highly recommend it especially if you care about the aesthetics of your board.</p>
<p>A side note about aesthetics: I recommend for early prototypes to include reference designators that can be visible <strong>when the board is fully assembled</strong>. It makes hand placement of parts 1000 times easier. See what I’m talking about below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/DSC01271.jpeg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>See all the reference designators in white? They’ll come in handy very soon..</p>
<p>For stencils, my go-to is <a target="_blank" href="https://www.oshstencils.com">OSH Stencils</a>. Their cost is reasonable and saves a ton of time when assembly is underway. Plus, as you may have guessed, circuit board assembly lines use large metal stencils to accomplish the same thing.</p>
<p>Finally, you want to export your bill of materials. I use the <code>bom.ulp</code> script that comes with Eagle. I always export by <em>value</em> so all the parts of the same attributes get binned together. This results in a clean and compact BOM that can be easily imported into something like Octopart. I often use Octopart to research prices. If it’s a particularly large bill of materials, I may split orders between say Mouser and Digikey. Sometimes even <a target="_blank" href="https://www.arrow.com">Arrow</a> has parts for dollars less than the other two.</p>
<p>When ordering, all vendors allow you to import a <code>.xlsx</code> file or <code>.csv</code>. When importing, sometimes you get choice of putting in a customer part number (or similar). You can use this to store the reference designator. That will get printed out onto the label that they stick to the bag.</p>
<p>As long as your parts are not too heavy you can typically use the First Class mail option that Digikey offers. It looks like they have recently raised their shipping prices (used to be $3.5 now it’s ~$4.5 to Connecticut) Parts usually arrive within 2-3 business days. Which is not to bad! ??</p>
<p>Pro tip: Once you get the parts, double check your inventory. I’ve made the mistake of not ordering enough parts for multiple assemblies. If you do find yourself short, just make another order. If you don’t you could be unpleasantly surprised when build day comes and your short components.</p>
<h2 id="heading-placing-parts-on-your-board">Placing Parts On Your Board</h2>
<p>Set up your assembly location. Use the plastic cutouts and place them around your circuit board. Then tape them down as a permanent frame to your desktop. You can make them yourself by using a service like Ponoko or just buy the ones that OSH Stencils offers.</p>
<p>Then, tape the stencil over the top aligning all the holes. This takes some time and finesse. Make sure you tape it down so it doesn’t move.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/DSC00558.jpeg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Place the stencil flat on the board. Then, take your solder syringe and glob some solder across the top of the stencil. Use an old credit card or the plastic card that comes with a stencil to spread the solder. Try to spread away from where the stencil is attached to your work surface. Otherwise if you move the stencil you’ll make a mess and have to start over.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/DSC00561.jpeg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once the paste is down, like the picture above, place the board on a flat surface. There is nothing to hold the parts on the board so it’s best to place it on a larger unpopulated circuit board. That way you have a movable base and there is less risk of destroying your hard work. Plus it protects the surface underneath once you get to the next step.</p>
<p>Remember, use the reference designators on the circuit board and compare with the reference designator on the packaging of your parts. As long as you exported your BOM correctly there’s no reason to go back and check part numbers. See an example of packaging with the reference designator below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/DSC01272.jpeg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Finally, bake your circuit board. I typically using my hot air gun at about 380°C and slowly go around the whole board soldering all the parts.  My airflow is set to very low when I do this otherwise the parts go flying. This applies to any hot air gun setup.</p>
<p>This also can be accomplished by using a hot plate or old toaster oven. Remember, you do not want to use the same oven that you use to toast your toast!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/DSC00564.jpeg" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/DSC00568.jpeg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Extra precaution: some salty engineers out there think there’s nothing wrong with breathing in fumes from soldering. I’m very much so in the opposite camp. Not only are you handling heavy metals (less of an issue with lead free solder) one way or another but the fumes from the solder flux are noxious. Best way to fix this is to run a fan out the window or use a fume extractor.</p>
<h2 id="heading-time-to-play">Time to Play</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/DSC00570.jpeg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>So you’ve ordered all your parts, stencils and boards. You’ve patiently and dutifully assembled and soldered all the components. Congrats, you’ve made it to the big times! Next stop is testing, firmware development or <a target="_blank" href="https://www.jaredwolff.com/getting-started-in-product-development/#show1">whatever else you need to do with your design</a>.</p>
<p>Also, to be fair, I actually have nothing against companies like Macrofab. They provide a great service and I’ve actually used them before for <a target="_blank" href="https://www.circuitdojo.org/iot-motion-light/#introduction">other projects</a>. Just remind yourself of the cost/time benefit of someone else doing the work for you. Is it worth it? Only you can decide.</p>
<p>Building your own circuit board on the cheep no only saves money but it’s rewarding when it’s all done. When building new devices and prototypes for my clients, I always keep this process as an option. It allows me to get a better idea of how a circuit may work before ever having to plunk down a ton of cash for a machine assembled board.</p>
<p>Looking for some help on your project? <a target="_blank" href="https://www.jaredwolff.com/about/">Got to the bottom of this page and send me a line.</a></p>
<p>You can also check out my other articles on my blog at <a target="_blank" href="https://www.jaredwolff.com/how-to-self-assemble-circuit-boards/">www.jaredwolff.com</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build an Affordable Air Quality Sensor for Your Home ]]>
                </title>
                <description>
                    <![CDATA[ By Jared Wolff This post is originally from www.jaredwolff.com I got my hands on some of the mesh based Particle boards not too long ago. I’ve been itching to try them out but haven’t quite figured out the project. One thing has been bothering me tho... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-an-affordable-and-proven-air-quality-sensor/</link>
                <guid isPermaLink="false">66d8504be86088251dd27bb9</guid>
                
                    <category>
                        <![CDATA[ Electronics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Google Docs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iot ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 03 Jun 2019 20:10:44 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/06/Copy-of-Particle-Sensor-3.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Jared Wolff</p>
<p><strong>This post is originally from <a target="_blank" href="https://www.jaredwolff.com/homemade-indoor-air-quality-sensor">www.jaredwolff.com</a></strong></p>
<p>I got my hands on some of the mesh based Particle boards not too long ago. I’ve been itching to try them out but haven’t quite figured out the project.</p>
<p>One thing has been bothering me though: air quality. I spend a good amount of time in my office tinkering, soldering, coding and writing. I sneeze occasionally so I always wondered, how bad is it? The house is also prone to mold exposure during the hot months which had me concerned.</p>
<p>So why not cook something up?</p>
<h2 id="heading-whats-needed">What’s needed</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/ingredients.jpg" alt="All the parts needed" width="600" height="400" loading="lazy"></p>
<p>The most important sensor is the <a target="_blank" href="https://www.honeywellscportal.com/honeywell-sensing-hpm-series-particle-sensors-datasheet-32322550-e-en.pdf">Honeywell HPM series</a> PM2.5/PM10 sensor. This tells you how many micrograms of material is floating around in a cubic volume of space. i.e. it counts the little particles flying around in your air.</p>
<p>Second to that, is the <a target="_blank" href="https://ams.com/documents/20143/36005/CCS811_DS000459_7-00.pdf">AMS CCS811</a>. This sensor tells you the total amount of volatile organic compounds are in the air along with things like C02. It’s another datapoint which is interesting to see. I’ve previously placed this sensor in our basement only to be surprised and see huge spikes in VOC and C02 levels from our (oil burning) furnace turning on in the morning. Time for better ventilation!</p>
<p>Finally,  the <a target="_blank" href="https://www.silabs.com/documents/public/data-sheets/Si7021-A20.pdf">Silicon Labs Si7021</a> temperature and humidity sensor. These two bits of environmental data are useful. More importantly they’re used by the algorithm in the CCS811 to compute the TVOC and C02.  Considering the cost of the CCS811, I’m surprised it doesn’t have these measurements on board but maybe in their next revision..</p>
<h2 id="heading-wiring-it-all-together">Wiring it all together</h2>
<p>It’s time to wire everything together. At the very least you’ll need:</p>
<ol>
<li>Solder-less breadboard hookup wire</li>
<li>A solder-less breadboard</li>
<li>A <a target="_blank" href="https://www.adafruit.com/product/3566">CCS811 breakout board</a> from Adafruit (<a target="_blank" href="https://learn.adafruit.com/adafruit-ccs811-air-quality-sensor?view=all">more details here</a>)</li>
<li>A <a target="_blank" href="https://www.adafruit.com/product/3251">Si7021 breakout  from Adafruit</a>(<a target="_blank" href="https://learn.adafruit.com/adafruit-si7021-temperature-plus-humidity-sensor?view=all">more details here</a>)</li>
<li><a target="_blank" href="https://www.particle.io/mesh/">A Particle board of your choice.</a></li>
<li>A <a target="_blank" href="https://www.jaredwolff.com/store/dust-sensor/">HPMA115 Particle sensor</a></li>
<li>Pre assembled Molex cable for the HPMA115 (Molex P/N 0151340803 or similar)</li>
<li>Some 0.1” pitch headers</li>
</ol>
<p>I’ve included a Fritzing example with this project. There’s also a hookup image below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/particle-squared-hookup-diagram.jpg" alt="Fritzing Hookup Diagram" width="600" height="400" loading="lazy">
<strong>Note:</strong> the original Fritzing diagram was incorrect. Both Vin of the CCS811 and Si7021 should be connected to the 3.3V on the Particle</p>
<p>An Adafruit Feather is used to represent the Particle Argon. Particle does not have Fritzing models quite yet.</p>
<p>As you can see everything is hooked up except for the PM2.5 sensor. The pinout is included below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-03-23_at_12.31.03_PM.png" alt="Particle sensor pinout" width="600" height="400" loading="lazy"></p>
<p>The most important pins are the 5V, GND, RX and TX pins. The other ones can stay disconnected if you choose. Here are the connections called out:</p>
<p>    5V     -&gt; USB
    GND    -&gt; GND
    RX     -&gt; TX (on the Argon)
    TX     -&gt; RX (on the Argon).</p>
<p>Here’s a picture of everything assembled on a solder-less breadboard.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/DSC01397.jpg" alt="Everything assembled on breadboard" width="600" height="400" loading="lazy"></p>
<p>Another important note is that I modified the cable for the HPMA so they had male pins on the end. That made it easy to insert into the solder-less breadboard. Here’s a zoomed in shot:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/DSC01370.jpg" alt="Soldered pin" width="600" height="400" loading="lazy"></p>
<p>When you purchase the cable for the PM2.5 sensor it came pre-populated with 8 wires. To make things simpler, you can remove 4 of the wires that are not used. The best way to do that is take a sharp tipped tool (dental pick, sewing needle, etc) and stick it under the clips I’ve pointed out in red below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/DSC01371.jpg" alt="Clips holding the wires in" width="600" height="400" loading="lazy"></p>
<p>Then, once you have your sharp implement underneath, tug on the wire and it should slide out.</p>
<p>Now you have less wire and less headache. You can use this technique to modify any Molex-like connector.</p>
<h2 id="heading-plumbing-the-firmware">Plumbing the firmware</h2>
<p>For this project I decided to keep my code consistent with the Wiring/Arduino-like API. That means object oriented C++. It’s been a while where I’ve coded in C++ so when you’re looking at the codebase and wondering “why the hell did he do that!?” Sorry, not sorry. ?</p>
<p>The best way to get started is to use Visual Code with the Particle plugins for this project. <a target="_blank" href="https://www.particle.io/workbench/">Click here to get started if you're not already setup.</a></p>
<h3 id="heading-si7021">Si7021</h3>
<p>The Si7021 is super simple. It only has 4 active pins out of the 6 on the chip.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-03-23_at_1.18.21_PM.png" alt="Si7021 pinout" width="600" height="400" loading="lazy">
(Copied directly from the Si7021 documentation)</p>
<p>The best say to read the temperature/humidity sensor is to issue a blocking read command. In an embedded world, this is not ideal. Unfortunately, there’s no way to know when the readings are ready because there is no interrupt pin.</p>
<p>As described in the data-sheet, you first write the command and then attempt to read directly from the device. The code looks something like this:</p>
<pre><code>    <span class="hljs-comment">// Si7021 Temperature</span>
    Wire.beginTransmission(SI7021_ADDRESS);
    Wire.write(SI7021_TEMP_HOLD_CMD); <span class="hljs-comment">// sends one byte</span>
    Wire.endTransmission();           <span class="hljs-comment">// stop transaction</span>
    Wire.requestFrom(SI7021_ADDRESS, <span class="hljs-number">2</span>);

    <span class="hljs-comment">// Get the raw temperature from the device</span>
    uint16_t temp_code = (Wire.read() &amp; <span class="hljs-number">0x00ff</span>) &lt;&lt; <span class="hljs-number">8</span> | (Wire.read() &amp; <span class="hljs-number">0x00ff</span>);
</code></pre><p>Wire the address of the device, write the command and then subsequently read the number of bytes necessary (Two in this case) The Si7021 will then stretch the clock until the reading has completed.</p>
<p>I didn’t mess around with other settings. Depending on your environment you may have to tweak how much current to feed the heater. You’re mileage may vary so prepare accordingly!</p>
<p>Finally, these readings are read on a reoccurring timer. I originally was using the <code>millis()</code> call and calculating the different of the start and current time but this eventually breaks (in 50 or so days). Instead I decided to use a system timer (similar to if not the same as the APP_TIMER in the NRF SDK)</p>
<pre><code>Timer timer(MEASUREMENT_DELAY_MS, timer_handler);
</code></pre><p>That way you get your interrupt always at <code>MEASUREMENT_DELAY_MS</code> no matter what! (In my case <code>MEASUREMENT_DELAY_MS</code> = 60000 ms == 60s)</p>
<h3 id="heading-the-ccs811">The CCS811</h3>
<p>The CCS811 gives you a bit more freedom to play but it comes with it’s own <em>specialness</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-03-23_at_2.34.14_PM.png" alt="CCS811 pinout" width="600" height="400" loading="lazy"></p>
<p>In most cases the ADDR pin is set low. This pin modifies one bit of the address. This is useful if you have two of the same device or two devices with the same address on the same I2C bus.</p>
<p>The CCS811 also has a few handy input and output pins. The most important is the interrupt pin. Whenever a reading is complete, this open drain pin will be pulled low. It will only get reset once you read the status  register. This is great for asynchronous reads that way you’re not locking up your MCU.</p>
<p>One important point is that the CCS811 does require you to issue a “start” command. This forces the internal MCU to start executing the TVOC/CO2 sensing algorithm. If you attempt to read the data registers before the application is started you will get bogus data. (The command is 0x90)</p>
<p>In the firmware, the CSS811 is processed in the same loop as the Si7021. The code pulls the available data from the CSS811 asynchronous readings. No blocking code!</p>
<h3 id="heading-the-hpma115">The HPMA115</h3>
<p>The particle sensor is a bit more tricky. When it is turned on, the device starts sending particulate data on a regular interval. i.e. it’s in auto-send mode every time it powers up.</p>
<p>I tried previously to configure the device but sometimes I wouldn’t get a response back. It was always hit and miss. It drove me crazy.</p>
<p>So, in order to turn the device off wen you’re not using it I highly suggest using a load switch of some kind. Not only will this save power but according to Honeywell, it will also increase the lifespan of the fan.</p>
<p>The flow of the readings:</p>
<ul>
<li>Every minute turn it on</li>
<li>Wait for data to be sent</li>
<li>Read the reading asynchronously via UART</li>
<li>Turn it off</li>
<li>Bundle that data into the JSON blob to be sent to the server</li>
</ul>
<p>This way there’s no need to mess with any registers. All the more reason why I2C and even SPI are better data buses than UART. I just want it to work!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/DSC01372.jpg" alt="Holding HPMA115S0" width="600" height="400" loading="lazy"></p>
<p>I originally chose this sensor a while back for it’s enclosed nature. In my option, it’s easier to integrate. My electrical engineer brain doesn’t want to deal with complex stuff. Give me a box and lets go.</p>
<h2 id="heading-getting-everything-working">Getting everything working</h2>
<p>During the development phase of this project I happened to be traveling abroad. The crappy wifi was not cutting it and it was taking forever to iterate on the code. The Argon also had a hard time connected to my iPhone’s AP so I gave up on that idea early on.</p>
<p>So, in order to develop the code that didn’t require the internet I placed the device into manual mode. What does manual mode do? It allows the code to start execution despite not being connected to the Particle cloud. That way you can take readings all day but you don’t have to be connected to Wifi.  You can put the device in manual mode by putting this define in your <code>.ino</code> file:</p>
<pre><code>SYSTEM_MODE(MANUAL);
</code></pre><p>In battery powered applications, this is ideal. Wifi is expensive power-wise and you don’t need to be running it if you don’t have to!</p>
<p>In a previous experiment, I found that it took about 10-15 seconds from nothing to sending data to the Particle cloud. That’s a <strong>long time</strong> in the embedded world. That’s one of the main reasons I suspect Particle came out with their mesh system. This allows sleepy end nodes (or nodes that are taking data and periodically sending it to a central point) to run much longer than their Wifi based cousins.</p>
<p>Remember you will have to run the <code>Particle.connect()</code> function in order to connect to wifi in manual mode. Or if you’re ready for it to re-connect, remove <code>SYSTEM_MODE(MANUAL);</code> from your <code>.ino</code> file.</p>
<h3 id="heading-changing-wifi-credentials">Changing Wifi Credentials</h3>
<p>During my experiment in trying to get my wifi to work I did discover a few handy Particle tools to change wifi credentials etc. By holding the mode button during operation, the device eventually starts blinking blue. Once blinking blue, you can issue a <code>particle serial wifi</code> which will walk you through the process of changing the credentials.</p>
<p>The above process is light years faster than using the iPhone/Android app. I thought the app was cool at first but man does it take a long time to scan and get your devices connected.</p>
<p><a target="_blank" href="https://docs.particle.io/tutorials/device-os/led/argon/#network-reset-fast-blinking-blue-">More info on this procedure go here.</a></p>
<h3 id="heading-recovering-when-things-go-awry">Recovering when things go awry</h3>
<p>I had to recover my Argon during my development process. I did some digging and found that re-programming the OS, App and Bootloader seemed to do the trick.</p>
<p>Get the files here: <a target="_blank" href="https://github.com/particle-iot/device-os/releases/tag/v0.9.0">Release 0.9.0 (Gen 3) · particle-iot/device-os · GitHub</a> (As of this writing the latest is 0.9.0)</p>
<p>Then program these files in <a target="_blank" href="https://docs.particle.io/tutorials/device-os/led/photon/#dfu-mode-device-firmware-upgrade-">DFU mode</a> by holding the <code>mode</code> button after tapping the <code>reset</code> button once.</p>
<pre><code>particle flash --usb system-part1<span class="hljs-number">-0.9</span><span class="hljs-number">.0</span>-argon.bin
particle flash --usb tinker<span class="hljs-number">-0.9</span><span class="hljs-number">.0</span>-argon.bin
</code></pre><p>Program this one in <a target="_blank" href="https://docs.particle.io/tutorials/device-os/led/photon/#listening-mode">Listening mode:</a></p>
<pre><code>particle flash --serial bootloader<span class="hljs-number">-0.9</span><span class="hljs-number">.0</span>-argon.bin
</code></pre><p><em>Note:</em> the <code>-argon</code> suffix may be different depending on what you’re programming to. Other options are <code>-boron</code> and <code>-xenon</code>.</p>
<h2 id="heading-monitoring-on-the-command-line">Monitoring on the command line</h2>
<p>Finally, one of the most useful commands is this one:</p>
<p><code>particle serial monitor --follow</code></p>
<p>This allows you to use the USB <code>Serial</code> interface to receive debug messages from he device. This is akin to connecting an FTDI device to an Arduino.</p>
<p>For instance, I may be debugging part of the code so I want to see some data. In the <code>Setup()</code> function I’ll be sure to run <code>Serial.begin()</code>, then later on I’ll make a <code>Serial.printf(“data: %d”,data.tvoc);</code> in order for it to be sent over the USB Serial interface.</p>
<p>Serial UART for debugging, it’s a beautiful thing.</p>
<h2 id="heading-publishing">Publishing</h2>
<p>One thing I did discover during the development process was the publishing limits of the Particle platform. For a single device, you cannot <code>Particle.Publish</code> more than 4 pieces of data in one second. Even though I was taking data every minute, I was sending 6 pieces of individual data to the server at the same time. After testing I soon started to wonder why the heck my C02 and TVOC readings disappeared.</p>
<p>I had found the culprit.</p>
<p>So, in order to make things work, I had to format it as a JSON blob. See how I did it exactly below:</p>
<pre><code><span class="hljs-built_in">String</span> out = <span class="hljs-built_in">String</span>::format(<span class="hljs-string">"{\"temperature\":%.2f,\"humidity\":%.2f,\"pm25\":%d,\"pm10\":%d,\"tvoc\":%d,\"c02\":%d}"</span>,si7021_data.temperature,si7021_data.humidity,hpma115_data.pm25,hpma115_data.pm10,ccs811_data.tvoc,ccs811_data.c02);
Particle.publish(<span class="hljs-string">"blob"</span>, out , PRIVATE, WITH_ACK);
</code></pre><p>I created a JSON structure and then used <code>String::format</code> to insert each piece where they needed to be. If you are running your device over LTE this will cause you to send more data than necessary. There are better options like <a target="_blank" href="https://www.jaredwolff.com/how-to-define-your-own-bluetooth-low-energy-configuration-service-using-protobuf/">Protocol Buffers</a> or using <a target="_blank" href="https://msgpack.org">MessagePack</a>. If you’re dealing with complex data, I recommend the former because of its programatic nature. Plus, you can use it with just about any programming language. So web to embedded? No problem.</p>
<p>After every minute, I only send the data when all three sensors have been read. I use three separate boolean values to determine the state of the sensor readings. Once they have all been set to <code>true</code> do I invoke the <code>Particle.Publish</code>call.</p>
<p>Then after publishing, I reset all variables like so:</p>
<pre><code>ccs811_data_ready = <span class="hljs-literal">false</span>;
si7021_data_ready = <span class="hljs-literal">false</span>;
hpma115_data_ready = <span class="hljs-literal">false</span>;
</code></pre><p>Then, everything starts all over again. You can also create a status struct which has each of these flags neatly inside. Considering I only have three data points, I didn’t go the extra mile there.</p>
<h2 id="heading-using-adafruit-io">Using Adafruit IO</h2>
<p>One way to publish is by using Adafruits IO platform. Here's how to get started.</p>
<ol>
<li>Create an account here: https://io.adafruit.com</li>
<li><p>Next is to create feeds for each of the data types. We’ll need 6 in total.
<img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-03-19_at_6.47.38_PM.png" alt="Create a feed in Adafruit IO" width="600" height="400" loading="lazy"></p>
</li>
<li><p>For each feed, add a Webhook.
<img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-03-19_at_6.45.27_PM.png" alt="Add a webhook for data" width="600" height="400" loading="lazy"></p>
</li>
<li>Take each webhook address and create a new Webhook in the Particle console</li>
<li>Change the <code>Request format</code> to JSON</li>
<li>Then under <code>Advanced Settings</code> click on <code>Custom</code> for the <strong>JSON DATA</strong></li>
<li><p>Replace what’s there using <a target="_blank" href="https://docs.particle.io/reference/device-cloud/webhooks/#variable-substitution">mustache templates</a>. Adafruit IO is looking for a JSON key called <code>value</code>. So set it like this:</p>
<pre><code>{
 “value”:”{{{c02}}}”
}
</code></pre><p>You can replace <code>c02</code> with any of the keys in your JSON blob. As a reminder the current JSON blob looks something like this:</p>
<pre><code>{
 “temperature”:<span class="hljs-number">21.2</span>,
 “humidity”:<span class="hljs-number">30</span>,
 “pm10”:<span class="hljs-number">2</span>,
 “pm25”:<span class="hljs-number">1</span>,
 “tvoc”:<span class="hljs-number">650</span>,
 “c02”:<span class="hljs-number">1001</span>
}
</code></pre></li>
<li>Repeat this as necessary until all feeds have a corresponding Webhook configured.</li>
<li>Finally, you can create a dashboard to see them all in one place. This is straight forward just follow the on screen prompts. :)</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-03-19_at_7.04.16_PM.png" alt="List of Feeds" width="600" height="400" loading="lazy">
<img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-03-19_at_7.16.17_PM.png" alt="Graphs of Feeds" width="600" height="400" loading="lazy"></p>
<p>You can check out my <a target="_blank" href="https://io.adafruit.com/jaredwolff/dashboards/air-quality-sensor">live dashboard here</a>. It’s nifty and just another way to display your data.</p>
<p><strong>Sidenote:</strong> My first impressions on Adafruit IO are good. It was easy to setup and start using. The main drawback that it’s tedious especially if you have more than a handful of data points. But maybe they’ll fix that in the future!</p>
<p><strong>Update:</strong> If you have multiple pieces of data. You can point your Particle integration to a single endpoint. Just make sure the data is in the same group! Here's an example of multiple values sent to the same group:</p>
<pre><code>{
  <span class="hljs-string">"feeds"</span>: [
    {
      <span class="hljs-string">"key"</span>: <span class="hljs-string">"tvoc"</span>,
      <span class="hljs-string">"value"</span>: <span class="hljs-string">"{{{tvoc}}}"</span>
    },
    {
      <span class="hljs-string">"key"</span>: <span class="hljs-string">"c02"</span>,
      <span class="hljs-string">"value"</span>: <span class="hljs-string">"{{{c02}}}"</span>
    },
    {
      <span class="hljs-string">"key"</span>: <span class="hljs-string">"temperature"</span>,
      <span class="hljs-string">"value"</span>: <span class="hljs-string">"{{{temperature}}}"</span>
    },
    {
      <span class="hljs-string">"key"</span>: <span class="hljs-string">"humidity"</span>,
      <span class="hljs-string">"value"</span>: <span class="hljs-string">"{{{humidity}}}"</span>
    },
    {
      <span class="hljs-string">"key"</span>: <span class="hljs-string">"pm2-dot-5"</span>,
      <span class="hljs-string">"value"</span>: <span class="hljs-string">"{{{pm25}}}"</span>
    },
    {
      <span class="hljs-string">"key"</span>: <span class="hljs-string">"pm10"</span>,
      <span class="hljs-string">"value"</span>: <span class="hljs-string">"{{{pm10}}}"</span>
    }
  ]
}
</code></pre><p>Where your URL should look something like:</p>
<pre><code>https:<span class="hljs-comment">//io.adafruit.com/api/v2/&lt;USERNAME&gt;/groups/&lt;GROUPNAME&gt;/data</span>
</code></pre><p>That should keep your Particle integration page a little more sane!</p>
<h2 id="heading-making-sense-of-the-readings">Making sense of the readings</h2>
<p>The readings can be confusing. Here’s the breakdown of how they work:</p>
<ol>
<li>Humidity is showing in relative percentage points. This is the relative humidity we know and love. Remember it may differ with what’s outside. This depends on if your house is air conditioned or if you’re running a heater etc.</li>
<li>Temperature is in degrees C (can be modified in firmware if you so choose)</li>
<li>TVOC is in ppb (parts per billion). VOCs can be in the form of harmful chemicals you have around the house. More information about VOCs check out this<a target="_blank" href="https://www.epa.gov/indoor-air-quality-iaq/volatile-organic-compounds-impact-indoor-air-quality">link from the EPA</a>.</li>
<li>C02 is in ppm (parts per million). We breathe in oxygen and exhale carbon dioxide. You may find your VOC and C02 levels rising when you’re in the room. C02 does correlate to VOCs as well. <a target="_blank" href="https://ams.com/documents/20143/36005/CCS811_DS000459_7-00.pdf">More info in the data sheet.</a></li>
<li>PM10. Is in µg/m3 (micrograms per meter cubed). The particle sensor uses a scattered laser when then shines across the air chamber to a sensor on the other side. The more the rays are blocked, the more particles in the air. The particle sensor then does some calculations to determine the amount of particles in a certain volume and thus your µg/m3.</li>
<li>PM2.5 is the same as above but it tracks much smaller particles. (Less than or equal to 2.5µm in size!) <a target="_blank" href="https://www.epa.gov/pm-pollution/particulate-matter-pm-basics">More information on the EPA’s website here.</a></li>
</ol>
<h2 id="heading-dont-care-for-something-you-have-no-control-over">Don't care for something you have no control over?</h2>
<p><a target="_blank" href="https://www.jaredwolff.com/how-to-make-an-amazing-looking-iot-dashboard-in-no-time/">Check out my tutorial on creating your own amazing looking IoT dashboard.</a></p>
<h2 id="heading-you-did-it">You did it!</h2>
<p>Congrats. You've made it this far. You deserve a day at the spa. Or maybe some chocolate ice cream. Or if you're really feeling adventurous, both, at the same time?? ?</p>
<p>After building one of these you may feel like your time is worth investing elsewhere. Maybe you want to build a cool web backend with fancier charts and algorithms. Maybe even use some machine learning (why not!)</p>
<p>If you want something already assembled and available you should check out the Particle^2 (Pronounced Particle Squared). It has everything here including the ability to switch on and off the HPM particle sensor. You can even run it on batteries! So put that sucker anywhere you want. <a target="_blank" href="https://www.jaredwolff.com/store/particle-squared/">Check it out here.</a></p>
<p>Here's the full video on the Particle Squared.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/IR2W0GmRKk8" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-code-and-source">Code and Source</h2>
<p>This whole project is released under the Creative Commons Share-Alike license. <a target="_blank" href="https://www.jaredwolff.com/files/air-quality/#main">Get the source code and hardware files here.</a></p>
<h2 id="heading-get-ready-for-the-ultimate-guide">Get Ready for the Ultimate Guide</h2>
<p>This post is an excerpt from my upcoming Ultimate Guide on Particle Mesh. Early subscribers get a discount when it becomes available! <a target="_blank" href="https://www.jaredwolff.com/the-ultimate-guide-to-particle-mesh/">Click here to get signed up.</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to monitor your air quality with this DIY setup ]]>
                </title>
                <description>
                    <![CDATA[ By Bert Carremans With a Raspberry Pi, low-cost gas sensors, and a remote-controlled switch, you can control the air quality in your house. The air we breathe indoors is not always healthier than the air outside. According to a study of the E.U. Join... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-monitor-your-air-quality-with-this-diy-setup-3399793137c3/</link>
                <guid isPermaLink="false">66d45ddb51f567b42d9f8441</guid>
                
                    <category>
                        <![CDATA[ Electronics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Raspberry Pi ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 19 Feb 2019 16:02:04 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*d43dkbPP_oxPGy6o0WWvnw.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Bert Carremans</p>
<h4 id="heading-with-a-raspberry-pi-low-cost-gas-sensors-and-a-remote-controlled-switch-you-can-control-the-air-quality-in-your-house">With a Raspberry Pi, low-cost gas sensors, and a remote-controlled switch, you can control the air quality in your house.</h4>
<p>The air we breathe indoors is not always healthier than the air outside.</p>
<p>According to a study of the <a target="_blank" href="http://europa.eu/rapid/press-release_IP-03-1278_en.htm">E.U. Joint Research Centre</a>, you can find a wide range of air pollutants indoors. Some of them are toxic, or can cause genetic mutations or cancer. Factors that influence indoor air quality are:</p>
<ul>
<li>ambient air, or the air outdoors</li>
<li>air tightness and ventilation of the building</li>
<li>indoor sources like tobacco smoke, heating gases, consumer products, etc.</li>
</ul>
<p>Do you know how much time you spend indoors? According to the Environmental Protection Agency, Americans spend <a target="_blank" href="https://www.nature.com/articles/7500165">87% of their time indoors</a>. In Europe, this average percentage is 90%, according to the JRC. And the more time we spent indoors, the more pollutants we inhale.</p>
<p>So it would be interesting if we track the indoor air quality. In this article, I will explain how I did this with a <a target="_blank" href="https://www.raspberrypi.org/">Raspberry Pi</a>, a <a target="_blank" href="https://www.dexterindustries.com/grovepi/">GrovePi</a> and some sensors. We will upload the sensor data to a <a target="_blank" href="https://firebase.google.com/">Firebase</a> database and visualize trends with <a target="_blank" href="https://dash.plot.ly/">Dash</a>.</p>
<p>When pollutant levels reach an unhealthy level, we can send an alert notification to warn us.</p>
<p>Moreover, it would be great if we could automatically start up the ventilation to purify the air. This can be done with a <a target="_blank" href="https://www.raspberrypi.org/blog/controlling-electrical-sockets-with-energenie-pi-mote/">remote-controlled switch from Energenie</a>.</p>
<h4 id="heading-raspberry-pi-and-grovepi">Raspberry Pi and GrovePi</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/A50dJjzt1x9eSTy0qoMm8trrsQ0M3GiAGM1t" alt="Image" width="350" height="278" loading="lazy">
<em>Raspberry Pi model 2B</em></p>
<p>In this project, I will use a Raspberry Pi model 2B. The Raspberry Pi is a low-cost small computer. It enables programmers and makers to build anything they can imagine.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/M4xPtxNXeO6K2NCIA6WXpHLMQvGdG77xAd10" alt="Image" width="600" height="400" loading="lazy">
<em>GrovePi (blue board) attached to a Raspberry Pi</em></p>
<p>The GrovePi is an electronics board that we attach to the Raspberry Pi. It makes connecting a wide range of sensors easy. As such, you don’t need to bother about a breadboard, resistors, soldering or jumper wires. You can plug in a connector and start working with it.</p>
<h4 id="heading-data-flow">Data flow</h4>
<p>In the illustration below you see how the sensor data will flow from the sensors to the charts on a web page. We’ll be using Python to do all that.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/fNyezC61-WH5nzRtVLodEZriNHkihVwLQz9c" alt="Image" width="800" height="211" loading="lazy">
<em>Data flow from a GrovePi and a Raspberry Pi to Firebase to a web page hosted on PythonAnywhere.</em></p>
<p>The first step is to pull in the data from the Grove sensors. Then we process the data on the Raspberry Pi and send them to a Firebase database. This data is also used to switch on or off a ventilation unit via a remote controlled switch.</p>
<p>We can get the stored data with a script running on PythonAnywhere.com. With the Dash package, we can build a dashboard to follow up the indoor air quality.</p>
<h4 id="heading-gas-sensors">Gas sensors</h4>
<p>We will use a set of three different gas sensors for this project. I use Grove gas sensors and connect them to the GrovePi.</p>
<p>It is not necessary to use all three sensors in your own project. Feel free to choose sensors that fit your needs. You can do that in the <code>config.py</code> file by keeping the sensors you need in the Python dictionary <code>MQ_SENSORS.</code></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ZYw4C3gJXMR1SOZ5cdz81uJkdfQejUdxiy3y" alt="Image" width="760" height="244" loading="lazy">
<em>Grove gas sensors</em></p>
<p>Each sensor detects a specific set of gases. There is quite some overlap between the sensors with regard to the gases they detect. But, the range in which the sensors detect a gas can differ. You can find the ranges on the <a target="_blank" href="http://wiki.seeedstudio.com/How_to_Chose_A_Gas_Sensor/">website of Seeedstudio</a>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/aXpnoZufynmqRnxESFGV9LiKPJGQ0fm2OAmV" alt="Image" width="800" height="498" loading="lazy">
<em>Gases detected per sensor type</em></p>
<h4 id="heading-temperature-and-humidity-sensor">Temperature and Humidity sensor</h4>
<p>Temperature and humidity influence the readings from the gas sensors. So, it is interesting to measure temperature and humidity as well. We use the Grove BME680 sensor for that.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/8PZoW1BkZtV2xNa3nHXAxT5-xfV1p2ltalSv" alt="Image" width="259" height="194" loading="lazy">
<em>Grove BME680 to measure temperature and humidity</em></p>
<h3 id="heading-working-with-sensor-data">Working with sensor data</h3>
<p>In short, a gas sensor will output a higher voltage when the concentration of a gas is higher. This is because the built-in resistor varies its resistance (Rs) according to the concentration of the gas.</p>
<p>The sensor value only reflects an approximation of a trend in the gas concentration. This means that you can use it to show whether the gas concentration increases or decreases. It does not give the exact gas concentration. If you want to measure the actual concentration, you would need a more expensive sensor.</p>
<p>For learning purposes, we will use the sensor value to approximate the gas concentration. You should keep that in mind. <strong>You should not use these scripts in real-life situations to prevent intoxication by these gases!</strong></p>
<p>On the datasheets listed below, you find a graph with the relation between the gas concentration and sensor resistor values. The gas concentration is expressed in parts per million (ppm). The resistor values as the ratio Rs/R0.</p>
<ul>
<li><a target="_blank" href="https://raw.githubusercontent.com/SeeedDocument/Grove-Gas_Sensor-MQ2/master/res/MQ-2.pdf">MQ2 datasheet</a></li>
<li><a target="_blank" href="https://raw.githubusercontent.com/SeeedDocument/Grove-Gas_Sensor-MQ5/master/res/MQ-5.pdf">MQ5 datasheet</a></li>
<li><a target="_blank" href="https://raw.githubusercontent.com/SeeedDocument/Grove-Gas_Sensor-MQ9/master/res/MQ-9.pdf">MQ9 datasheet</a></li>
</ul>
<p>The curves below correspond to the standard conditions of:</p>
<ul>
<li>a temperature of 20°C</li>
<li>a humidity of 65%</li>
<li>an oxygen concentration of 21%</li>
<li>a load resistance of 5 kilo-Ohm. The load resistance is the total resistance of an electronic circuit.</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ISA1CBYm5WM3hWuxAU5wsSXEhZ87aQv54Kr8" alt="Image" width="600" height="400" loading="lazy">
<em>Curves displaying the relation between gas concentrations and sensor resistance values. Both the x-axis and y-axis are on a log scale.</em></p>
<p>We can assume that the load resistance and oxygen concentration are stable over time. Yet, the temperature and humidity indoors can vary. Both factors have an influence on the sensor readings, as you can see in the graph below.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/QgM73v0r-BeZXMFVFb9PW9rttlbEKOlbPnCh" alt="Image" width="800" height="406" loading="lazy">
<em>Influence of different temperatures and humidities (RH) on sensor resistance values in the MQ2 sensor for a hydrogen (H2) concentration of 1.000 ppm.</em></p>
<p>To get accurate readings, you should have a graph or look-up table for various temperature-humidity combinations. Unfortunately, these graphs are not provided by the manufacturer.</p>
<p>Another approach is to correct the sensor readings for the temperature-humidity influence.</p>
<p>We can do this with artificial neural networks, as proposed in the <a target="_blank" href="https://www.uni-obuda.hu/journal/Nenova_Dimchev_41.pdf">paper by Nenova &amp; Dimchev</a>. That approach requires ground-truth measurements of the gas concentrations. This is out of scope for this article.</p>
<h4 id="heading-defining-the-r0-value">Defining the R0 value</h4>
<p>First, we need to compute the R0 value. R0 stands for the sensor resistance value of 1.000 ppm of hydrogen (H2)in clean air. The ratio for clean air (black line with blue crosses) is constant. It remains at 9.8 regardless of the concentration of clean air. So, we can compute R0 by reading the sensor value (Rs) in clean air and dividing it by 9.8.</p>
<p>The value we get from the sensor is a value between 0 and 1.023 and has no measurement unit. So, to get the output voltage we divide the sensor value by 1.023. We multiply this value with the circuit voltage, which is usually 5V.</p>
<p>From the sensor voltage, we can derive the sensor resistance by applying <a target="_blank" href="https://en.wikipedia.org/wiki/Ohm%27s_law">Ohm’s law</a>. The sensor resistance is equal to</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/HipHVSJozj6CkZ3TKlEHQlAJTdb5D-dsmsLZ" alt="Image" width="600" height="400" loading="lazy">
<em>Vc is the circuit voltage and Vs is the sensor voltage</em></p>
<p>Let’s see how we do that with Python. The complete code and more documentation can be found on <a target="_blank" href="https://github.com/bertcarremans/air_quality_monitoring">Github</a> in the script <code>get_R0_values.py</code>.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> config <span class="hljs-keyword">as</span> cfg
<span class="hljs-keyword">import</span> grovepi
<span class="hljs-keyword">import</span> time
</code></pre>
<p>First, we import some packages. The <code>config</code> package is a Python script I made to store all configuration parameters.</p>
<p>Throughout the code, you’ll notice that I sometimes refer to <code>cfg.PARAMETER_NAME</code>. We set the<code>PARAMETER_NAME</code> value in that <code>config.py</code> file. It also contains some passwords and API tokens.</p>
<p>For security reasons, I will not save that file on <a target="_blank" href="https://github.com/bertcarremans/air_quality_monitoring">Github</a>. Instead, I’ll provide a clean template <code>config_template.py</code> that you can use for your own project.</p>
<p>Next, we import the <code>grovepi</code> package. You can install it from the <a target="_blank" href="https://github.com/DexterInd/GrovePi/tree/master/Software/Python">Github page of Dexter Industries</a> on your Raspberry Pi. It allows us to work with the GrovePi and the connected sensors.</p>
<p>Finally, we use the <code>time</code> package to pause the program during sensor readings.</p>
<pre><code>mq_values = {}

<span class="hljs-keyword">for</span> sensor, data <span class="hljs-keyword">in</span> cfg.MQ_SENSORS.items():
    grovepi.pinMode(data[<span class="hljs-string">'pin'</span>],<span class="hljs-string">"INPUT"</span>)
    mq_values[sensor] = <span class="hljs-number">0</span>
</code></pre><p>We will store the sensor values for the different sensors in the dictionary <code>mq_values</code>. But first, we initialize the values to zero in a loop over the sensors defined in <code>MQ_SENSORS</code>.</p>
<p>With the <code>pinMode</code> method, you can define the pin as <code>INPUT</code> or <code>OUTPUT.</code> In our case, we’ll use it as <code>INPUT</code>.</p>
<p>The <code>pin</code> tells us to which pin on the GrovePi the sensor is connected. We use the analog pins (or ports) which are labeled as A0, A1 and A2 on the GrovePi. Make sure you connect the right sensor to the port described in the <code>config.py</code> file.</p>
<pre><code><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(cfg.NB_R0_READ):
    <span class="hljs-keyword">for</span> sensor, value <span class="hljs-keyword">in</span> mq_values.items():
        mq_values[sensor] += grovepi.analogRead(cfg.MQ_SENSORS[sensor][<span class="hljs-string">'pin'</span>])
    time.sleep(cfg.R0_INTERVAL)
</code></pre><p>We then read the sensor value in a loop for <code>cfg.NB_R0_READ</code> times and sum it up in <code>mq_value[sensor]</code>. We read the sensor value with the <code>analogRead</code> method of the <code>grovepi</code> package.</p>
<p>As described in the <a target="_blank" href="https://www.dexterindustries.com/GrovePi/programming/python-library-documentation/">documentation</a>, this will return a value between 0 and 1.023. In fact, it converts an analog sensor value to a digital value.</p>
<p>After one reading for all sensors, we pause the program at <code>cfg.R0_INTERVAL</code> seconds. To get the average value, we divide the cumulated value by <code>cfg.NB_RO_READ.</code></p>
<pre><code><span class="hljs-keyword">for</span> sensor, value <span class="hljs-keyword">in</span> mq_values.items():
    mq_values[sensor] = mq_values[sensor]/cfg.NB_R0_READ
    mq_values[sensor] = mq_values[sensor]/cfg.AR_MAX * cfg.VC
    mq_values[sensor] = (cfg.VC - mq_values[sensor])/mq_values[sensor]
    mq_values[sensor] = mq_values[sensor]/cfg.MQ_SENSORS[sensor][<span class="hljs-string">'r0_rs_air'</span>]
</code></pre><p>We compute the sensor voltage by dividing the averaged sensor value by <code>cfg.AR_MAX</code>. Then we multiply it by the circuit voltage <code>cfg.VC</code>.</p>
<p>From that voltage, we can apply Ohm’s law and compute the sensor resistance value. Dividing that by the ratio for clean air <code>cfg.MQ_SENSORS[sensor]['r0_rs_air']</code> gives us R0.</p>
<p>It is better to have the sensor working at least for 24 hours before you measure the R0 value. This will give more stable sensor readings.</p>
<h4 id="heading-linear-interpolation-of-gas-concentration">Linear interpolation of gas concentration</h4>
<p>Now that we know the R0 value, we can compute the Rs/R0 ratio with the sensor value. With that ratio, we can derive the gas concentration with <a target="_blank" href="https://en.wikipedia.org/wiki/Linear_interpolation">linear interpolation</a>.</p>
<p>For that, we assume that we are working in the standard conditions described for the first graph. In that case, the curves are nearly linear.</p>
<p>For linear interpolation, we need two known points of each curve to calculate its slope. Suppose we have two points with the coordinates (x1, y1) and (x2, y2). The y-values stand for the Rs/R0 values and the x-values for the gas concentrations. For a linear curve, the slope is then calculated as:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/JadXCd-aISp-O16p2TcXsGD8kMaCGptYIwIs" alt="Image" width="600" height="400" loading="lazy"></p>
<p>When we know the slope, we can find the gas concentration(x) for any given Rs/R0 value (y). The formula for this is:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/nSsOuEVNkeRnpvWPOPNKm0z-iuK8Z4QTyNpK" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The code snippets below come from the script <code>get_sensor_values.py</code> which you can find on <a target="_blank" href="https://github.com/bertcarremans/air_quality_monitoring">Github</a>.</p>
<p>We put the formula in a function <code>get_ppm.</code> <code>curve['y']</code> and <code>curve['x']</code> are the known points on the curve for a gas. <code>curve['slope']</code> is what we calculated with the previous formula.</p>
<p>You can find these values in the <code>config_template.py</code> file. I derived these values with <a target="_blank" href="https://automeris.io/WebPlotDigitizer/">Webplotdigitizer</a> from the graphs on the data sheets. As a result, these values are not completely accurate. Use them with caution.</p>
<p>Note the use of <code>np.log10</code> and <code>np.power.</code> This reason for this is that the axes on the graph are in a log-scale.</p>
<pre><code>def get_ppm(Rs_R0_ratio, curve):
    x_val = (np.log10(Rs_R0_ratio) - curve[<span class="hljs-string">'y'</span>])/curve[<span class="hljs-string">'slope'</span>] + curve[<span class="hljs-string">'x'</span>]
    ppm_val = np.power(x_val, <span class="hljs-number">10</span>)
    <span class="hljs-keyword">return</span> ppm_val
</code></pre><p>We calculate the <code>Rs_R0_ratio</code> in the same manner as when calculating the R0 value. So I will not repeat this. To calculate this ratio, we loop over all gases and sensors and store this in <code>ppm_values[mq_sensor][gas].</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> gas, curve <span class="hljs-keyword">in</span> cfg.CURVES[mq_sensor].items():
                ppm_values[mq_sensor][gas] = get_ppm(mq_values[mq_sensor], curve)
</code></pre>
<h4 id="heading-temperature-humidity-and-pressure">Temperature, humidity and pressure</h4>
<p>Besides the gas sensors, we read the temperature, humidity and pressure with the BME680 sensor. The BME680 sensor is connected to the GrovePi via an I2C port. To use the sensor, we import the package which can be installed from the <a target="_blank" href="https://github.com/pimoroni/bme680-python">Pimoroni repo</a> on Github.</p>
<pre><code><span class="hljs-keyword">import</span> bme680
</code></pre><p>The <code>set_..._oversample</code> methods specify how many samples we take to calculate the average value. We also did that for the gases. With <code>get_sensor_data</code> we read the sensor values.</p>
<pre><code class="lang-python">bme680_sensor = bme680.BME680(bme680.I2C_ADDR_PRIMARY)
bme680_sensor.set_humidity_oversample(bme680.OS_2X)
bme680_sensor.set_pressure_oversample(bme680.OS_4X)
bme680_sensor.set_temperature_oversample(bme680.OS_8X)
bme680_sensor.get_sensor_data()
</code></pre>
<pre><code>bme680_sensor.get_sensor_data()
</code></pre><h3 id="heading-storing-and-retrieving-sensor-data-in-cloud-firestore">Storing and retrieving sensor data in Cloud Firestore</h3>
<p>Some sensors provide new readings very fast. Other (less expensive) sensors will take more time. For this project, we will read the data every minute. This is set in the config file with <code>FIREBASE_INTERVAL = 60</code>.</p>
<p>In the free Spark plan of Firebase, the <a target="_blank" href="https://firebase.google.com/docs/firestore/quotas">Cloud Firestore quota</a> allow for 20K writes per day. With a one-minute interval, we will be well below that quota. The limit for reading documents in the Firestore is 50K per day.</p>
<p>You’ll need to create a Firebase project and <a target="_blank" href="https://firebase.google.com/docs/firestore/quickstart">create a Cloud Firestore</a>. After that, make sure to <a target="_blank" href="https://firebase.google.com/docs/admin/setup">generate the credentials</a> to authenticate your application. Save the credentials file in a secure location.</p>
<p>To work with Firebase via Python, we need to import the <code>firebase_admin</code> package. This package needs to be installed on your Raspberry Pi first, if needed.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> firebase_admin
<span class="hljs-keyword">from</span> firebase_admin <span class="hljs-keyword">import</span> credentials
<span class="hljs-keyword">from</span> firebase_admin <span class="hljs-keyword">import</span> firestore
</code></pre>
<p>After that, we can initialize the Firebase app with credentials. I store the location to the credentials file in <code>cfg.FIREBASE_CREDS_JSON</code>. When the app is initialized, we create a Firestore object <code>db</code>.</p>
<pre><code class="lang-python">firebase_path = Path.cwd() / cfg.FIREBASE_CREDS_JSON
cred = credentials.Certificate(str(firebase_path))
firebase_admin.initialize_app(cred)
</code></pre>
<p>After processing the gas values, it is time to store them in the Cloud Firestore. We will create a dictionary <code>firebase_values</code> to gather all the data. With a dict comprehension, we add the values for all gases for all MQ sensors. The BME680 values and timestamp are also added.</p>
<p>With the <code>add</code> method of the Firestore object <code>db</code>, it is easy to store the data in the Firestore.</p>
<p>The name of the collection in the Firestore is <code>cfg.FIREBASE_DB_NAME</code>. Learn more about the <a target="_blank" href="https://firebase.google.com/docs/firestore/data-model">data model of Firestore</a> on the Firebase website.</p>
<pre><code class="lang-python">firebase_values = {mq_sensor + <span class="hljs-string">'_'</span> + gas + <span class="hljs-string">'_ppm'</span>: ppm
                            <span class="hljs-keyword">for</span> mq_sensor, gases <span class="hljs-keyword">in</span> ppm_values.items()
                            <span class="hljs-keyword">for</span> gas, ppm <span class="hljs-keyword">in</span> gases.items()
                          }
firebase_values[<span class="hljs-string">'temperature'</span>] = bme680_sensor.data.temperature
firebase_values[<span class="hljs-string">'pressure'</span>] = bme680_sensor.data.pressure
firebase_values[<span class="hljs-string">'humidity'</span>] = bme680_sensor.data.humidity
firebase_values[<span class="hljs-string">'date'</span>] = datetime.now()
db.collection(cfg.FIREBASE_DB_NAME).add(firebase_values)
</code></pre>
<p>After storing the data, we wait a minute to start over with the following line of code.</p>
<pre><code>time.sleep(cfg.FIREBASE_INTERVAL)
</code></pre><h3 id="heading-improving-the-air-quality">Improving the air quality</h3>
<p>If the air quality indoors is not good we should take measures to improve it. Before we can do that, we need to be notified about critical gas concentrations.</p>
<p>One possibility is to send an alert notification by email, which we’ll discuss below.</p>
<p>Sometimes the source of indoor air pollution comes from outdoor air. For example, when your neighbors have wood-burning stoves or when you live near a factory.</p>
<p>In that case, you could install your measurement station outside and turn off the ventilation unit in your house if outdoor air quality is bad. With a remote-controlled switch, this can be done easily.</p>
<p>All code for this section is in <code>improve_air_quality.py</code> on Github.</p>
<h4 id="heading-sending-notifications-when-air-quality-reaches-a-critical-level">Sending notifications when air quality reaches a critical level</h4>
<p>We do not want to send an email each time the sensor outputs critical values (here, each minute).</p>
<p>Let’s say we want to check each hour whether there were critical values in the last hour. For that, we need to keep track of a <code>reference_time.</code> We initialize this when the program for readings sensor values starts. The interval at which we check again for critical gas concentrations is defined in <code>cfg.ALERT_INTERVAL</code>.</p>
<pre><code>reference_time = datetime.now()
</code></pre><p>When an hour has passed since <code>reference_time</code>, we can start to check if there were critical air pollutant values. We update <code>reference_time</code> with the current time.</p>
<p>With the <code>pytz</code> package, we can take into account our timezone. In my case, that is <code>Europe/Brussels.</code> We compute <code>one_hour_ago</code> by subtracting 60 minutes from the current time.</p>
<pre><code><span class="hljs-keyword">if</span> datetime.now() &gt; reference_time + timedelta(minutes=cfg.ALERT_INTERVAL):
    reference_time = datetime.now()
    brussels_tz = pytz.timezone(<span class="hljs-string">'Europe/Brussels'</span>)
    prev_check_time = brussels_tz.localize(datetime.now()) - timedelta(minutes=cfg.ALERT_INTERVAL)
</code></pre><p>With <code>prev_check_time</code> we extract the sensor readings from Firebase of the last hour. We do that by applying a <code>where</code> clause to the data that we <code>get</code> from the Cloud Firestore.</p>
<p>In this script, we will only use one gas sensor and a limited set of gases. The sensor is selected in <code>cfg.ALERT_SENSOR.</code> The gases are selected in <code>cfg.ALERT_GASES.</code> The data per gas is appended to <code>ppm_vals</code> as well as the <code>timestamps.</code></p>
<pre><code>timestamps = []
ppm_vals = {}
<span class="hljs-keyword">for</span> gas <span class="hljs-keyword">in</span> cfg.ALERT_GASES:
    ppm_vals[gas] = []

docs = db.collection(cfg.FIREBASE_DB_NAME).order_by(u<span class="hljs-string">'date'</span>).where(u<span class="hljs-string">'date'</span>, <span class="hljs-string">'&gt;='</span>, one_hour_ago).get()

<span class="hljs-keyword">for</span> doc <span class="hljs-keyword">in</span> docs:
    data = doc.to_dict()
    <span class="hljs-keyword">for</span> gas <span class="hljs-keyword">in</span> cfg.ALERT_GASES:
        ppm_vals[gas].append(data[cfg.ALERT_SENSOR + gas + <span class="hljs-string">'_ppm'</span>])

    timestamps.append(data[<span class="hljs-string">'date'</span>].strftime(<span class="hljs-string">'%H:%M:%S'</span>))
</code></pre><p>We look for critical values with the function <code>find_crit_val.</code> We will only check if the value surpassed an upper bound <code>ubound</code>. These upper bounds need to be specified in the config file.</p>
<p>The data are in ascending chronological order. Thus, we can use the <code>next</code> method to find the first timestamp for which <code>v &gt; ubound</code>. We return a tuple containing the timestamp of the critical value and the critical value itself.</p>
<p>If there is no critical value, we return the tuple <code>(None, None).</code></p>
<pre><code>def find_crit_val(timestamps, val_list, ubound):
    <span class="hljs-keyword">try</span>:
        (crit_time, crit_value) = next(((i,v) <span class="hljs-keyword">for</span> i, v <span class="hljs-keyword">in</span> zip(timestamps, val_list) <span class="hljs-keyword">if</span> v &gt; ubound))          
    <span class="hljs-attr">except</span>:
        (crit_time, crit_value) = (None,None)
    <span class="hljs-keyword">return</span> (crit_time, crit_value)
</code></pre><p>The critical tuples are stored in a dictionary <code>crit_dict.</code> As the key, we use the gas name. We then check for gas-sensor combinations with a critical timestamp and critical value. In that case, we add an alert message to <code>critical_msg.</code></p>
<pre><code>crit_dict = {}
<span class="hljs-keyword">for</span> gas <span class="hljs-keyword">in</span> cfg.ALERT_GASES:
    (crit_time, crit_value) = find_crit_val(timestamps, ppm_vals[gas], cfg.UPPERBOUNDS[gas])
    crit_dict[gas] = (crit_time, crit_value)
critical_msg = <span class="hljs-string">''</span>
    <span class="hljs-keyword">for</span> k, v <span class="hljs-keyword">in</span> crit_dict.items():
        <span class="hljs-keyword">if</span> v[<span class="hljs-number">0</span>] is not None and v[<span class="hljs-number">1</span>] is not None:
            critical_msg += <span class="hljs-string">'\nCritical value for '</span> + k + <span class="hljs-string">' of '</span> + str(v[<span class="hljs-number">1</span>]) + cfg.UNITS[k] + <span class="hljs-string">' at '</span> + str(v[<span class="hljs-number">0</span>])
</code></pre><p>If <code>critical_msg</code> is not empty, we send an email. Sending an email is done with the <code>smtplib</code> package. How to send an email with Python is explained on <a target="_blank" href="https://automatetheboringstuff.com/chapter16/">AutomateThe BoringStuff.com</a>.</p>
<p>You need to generate an <a target="_blank" href="https://support.google.com/mail/?p=InvalidSecondFactor">application-specific password</a> for your email if you are using Google’s two-factor authentication.</p>
<pre><code><span class="hljs-keyword">if</span> critical_msg != <span class="hljs-string">''</span>:
    <span class="hljs-keyword">try</span>:
        msg = MIMEText(critical_msg, _charset=<span class="hljs-string">'utf-8'</span>)
        msg[<span class="hljs-string">'Subject'</span>] = Header(<span class="hljs-string">'Air Quality Alert'</span>, <span class="hljs-string">'utf-8'</span>)
        smtpObj = smtplib.SMTP(<span class="hljs-string">'smtp.gmail.com'</span>, <span class="hljs-number">587</span>)
        smtpObj.ehlo()
        smtpObj.starttls()
        smtpObj.login(cfg.EMAIL, cfg.EMAIL_PW)
        smtpObj.sendmail(cfg.EMAIL, cfg.EMAIL, msg.as_string())
        smtpObj.quit()  
    except smtplib.SMTPException:
        print(<span class="hljs-string">'Something went wrong while sending the email'</span>)
</code></pre><h4 id="heading-automatically-control-your-ventilation-unit">Automatically control your ventilation unit</h4>
<p>With a remote-controlled switch, we can turn on or off any device that is connected to it. Thus, also a ventilation unit. <a target="_blank" href="https://energenie.com/">Energenie</a> creates the PiMote add-on specifically for the Raspberry Pi. To control the Energenie switch, you need to install the <code>energenie</code> package and import it.</p>
<p>Note that you can not attach the PiMote on top of the GrovePi. So you’ll need a second Raspberry Pi.</p>
<p>When starting the script, the first thing we do is define a boolean variable <code>ventilation_on.</code> We set it to <code>False</code> because this is the first time we run the script.</p>
<pre><code><span class="hljs-keyword">import</span> energenie
ventilation_on = False
</code></pre><p>If <code>critical_msg</code> is not empty, there was a critical gas concentration in the last alert interval. In that case, we turn on the ventilation with the <code>switch_on</code> method of the energenie package.</p>
<p>If there was no critical gas concentration and the ventilation was switched on in the last alert interval, we can switch it off.</p>
<p>You might need to set another interval before switching your ventilation off. That depends on the flow rate of your ventilation unit, the gases measured and whether the pollution source has been disabled.</p>
<pre><code><span class="hljs-keyword">if</span> critical_msg != <span class="hljs-string">''</span>:
    <span class="hljs-keyword">if</span> not ventilation_on:
        energenie.switch_on(<span class="hljs-number">1</span>)
        ventilation_on = True
<span class="hljs-attr">else</span>:
    <span class="hljs-keyword">if</span> ventilation_on:
        energenie.switch_off(<span class="hljs-number">1</span>)
        ventilation_on = False
</code></pre><h3 id="heading-visualization-of-air-quality-with-dash">Visualization of air quality with Dash</h3>
<p>A notification with critical gas concentrations can help to take immediate action. But it is also interesting to track the gas concentrations over time. By visualizing the sensor values in a dashboard, we can look at the trend of the gas concentrations. This can be done with Dash. On the website of Dash, you can find a <a target="_blank" href="https://dash.plot.ly/">great tutorial</a> on how to get started.</p>
<p>In this project, we will build a dashboard and host it on <a target="_blank" href="https://www.pythonanywhere.com/">PythonAnyWhere.com</a>. To use Dash on PythonAnywhere, you need to create a <a target="_blank" href="https://help.pythonanywhere.com/pages/Virtualenvs/">virtual environment</a>. You can follow the steps of <a target="_blank" href="https://github.com/conradho/dashingdemo">this demo</a> on how to set-up a Dash app on PythonAnyWhere.</p>
<p>Below I will show how I built the dashboard for our air quality station. The full script can be found in plot_sensor_values.py on <a target="_blank" href="https://github.com/bertcarremans/air_quality_monitoring">Github</a>.</p>
<p>First of all, you need to import the <code>dash</code> package.</p>
<pre><code><span class="hljs-keyword">import</span> dash
<span class="hljs-keyword">import</span> dash_core_components <span class="hljs-keyword">as</span> dcc
<span class="hljs-keyword">import</span> dash_html_components <span class="hljs-keyword">as</span> html
</code></pre><p>In the demo on the Dash website, they use a link to a Cascading Style Sheet (CSS) to provide a nice page design. If you want to <a target="_blank" href="https://dash.plot.ly/external-resources">use a local CSS</a> on your laptop or web server, you can add an assets folder. In that folder you can add your CSS and Dash will pick it up from there.</p>
<p>Then you’ll need to get the data from Firebase. This can be done similarly as we did for sending the alert notifications. So we will not go over that again.</p>
<p>With the data collected from Firebase, we can fill the graphs in our dashboard. We first create a Dash object <code>app</code> and give it a <code>title.</code></p>
<pre><code>app = dash.Dash(__name__)
app.title = <span class="hljs-string">'Indoor Air Quality Dashboard'</span>
</code></pre><p>Then we create the <code>layout</code> of the dashboard. A <code>H1</code> heading component, a <code>container</code> div and a div containing the <code>graphs.</code></p>
<pre><code>app.layout = html.Div([
    html.H1(style={<span class="hljs-string">'textAlign'</span>:<span class="hljs-string">'center'</span>}, children=<span class="hljs-string">'Indoor Air Quality Dashboard'</span>),
    html.Div(id=<span class="hljs-string">'container'</span>),
    html.Div(graphs)
])
</code></pre><p><code>graphs</code> is a list that contains the info per graph. Below you can see how the graph for temperature is set up. You can add the <code>dcc.Graph</code> for humidity and pressure as well by appending them to <code>graphs.</code></p>
<pre><code>graphs = [
    dcc.Graph(
        id=<span class="hljs-string">'temperature'</span>,
        figure={
            <span class="hljs-string">'data'</span>:[{
                <span class="hljs-string">'x'</span>:timestamps,
                <span class="hljs-string">'y'</span>:temperatures,
                <span class="hljs-string">'type'</span>:<span class="hljs-string">'line'</span>,
                <span class="hljs-string">'name'</span>: <span class="hljs-string">'Temperature'</span>,
                <span class="hljs-string">'line'</span>: {<span class="hljs-string">'width'</span>:<span class="hljs-number">2</span>, <span class="hljs-string">'color'</span>: <span class="hljs-string">'#542788'</span>}
                }],
            <span class="hljs-string">'layout'</span>:{
                <span class="hljs-string">'title'</span>: <span class="hljs-string">'Temperature'</span>,
                <span class="hljs-string">'yaxis'</span>: {<span class="hljs-string">'title'</span>: <span class="hljs-string">'Celsius'</span>},
                <span class="hljs-string">'xaxis'</span>: {<span class="hljs-string">'title'</span>: <span class="hljs-string">'Timestamp'</span>, <span class="hljs-string">'tickvals'</span>:timestamps}
            }
        }
    )
]
</code></pre><p>The graphs for the MQ sensors can be appended in a for loop.</p>
<pre><code><span class="hljs-keyword">for</span> mq_sensor <span class="hljs-keyword">in</span> cfg.MQ_SENSORS.keys():
    <span class="hljs-keyword">for</span> gas <span class="hljs-keyword">in</span> cfg.CURVES[mq_sensor].keys():
        sensor_gas_key = mq_sensor + <span class="hljs-string">'_'</span> + gas + <span class="hljs-string">'_ppm'</span>
        title = gas + <span class="hljs-string">' concentration on '</span>+ mq_sensor + <span class="hljs-string">' sensor'</span>
        data = ppm_values[mq_sensor][gas]
        data.reverse()

        graphs.append(dcc.Graph(
            id=sensor_gas_key,
            figure={
                <span class="hljs-string">'data'</span>: [{
                    <span class="hljs-string">'x'</span>: timestamps,
                    <span class="hljs-string">'y'</span>: data,
                    <span class="hljs-string">'type'</span>:<span class="hljs-string">'line'</span>,
                    <span class="hljs-string">'name'</span>: title,
                    <span class="hljs-string">'line'</span>: {<span class="hljs-string">'width'</span>:<span class="hljs-number">2</span>}
                }],
                <span class="hljs-string">'layout'</span>: {
                    <span class="hljs-string">'title'</span>: title,
                    <span class="hljs-string">'yaxis'</span>: {<span class="hljs-string">'title'</span>: <span class="hljs-string">'ppm'</span>},
                    <span class="hljs-string">'xaxis'</span>: {<span class="hljs-string">'title'</span>: <span class="hljs-string">'Timestamp'</span>, <span class="hljs-string">'tickvals'</span>:timestamps}
                }
            }
        ))
</code></pre><p>As a result, you will have a dashboard with graphs like the one below.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/XhmuZyEJBLsJ1eUuTWb80qkmI99ptztNyiF7" alt="Image" width="600" height="400" loading="lazy">
<em>Graph with MQ2 sensor data for methane (ch4)</em></p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>With a few low-cost gas sensors and a Raspberry Pi (and GrovePi) it is easy to build an air quality measurement station. You can then act on the data by sending alert notifications when air quality is bad or switch on the ventilation. With Dash you can build beautiful visualizations to monitor the air quality over time.</p>
<p>Below I noted some ideas to take this project further.</p>
<ul>
<li>make a mobile app for the visualizations and receiving notifications</li>
<li>add LEDs, a buzzer and an OLED display to the Raspberry Pi to get instant feedback on air quality</li>
<li>install measurement stations at your family and friends' place and <a target="_blank" href="https://towardsdatascience.com/visualizing-air-pollution-with-folium-maps-4ce1a1880677">visualize it on an interactive map</a>.</li>
<li>once you have enough data, <a target="_blank" href="https://towardsdatascience.com/forecasting-air-pollution-with-recurrent-neural-networks-ffb095763a5c">build a time-series model</a> to predict the indoor air quality</li>
</ul>
<p>Hopefully, this story motivates you to start building your own measurement station. If you have questions or suggestions let me know.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ An elegant LED illustration of a mathematical identity ]]>
                </title>
                <description>
                    <![CDATA[ By Chris Lam I am a big fan of science toys. I have been looking for one that combines the elegance of math and programming for a while. However, there was not much success in the search. So, I decided to make one myself. Here is a demo. The flashing... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/an-elegant-led-illustration-of-a-mathematical-identity-de88ee88c963/</link>
                <guid isPermaLink="false">66c343d74f1fc448a3678f90</guid>
                
                    <category>
                        <![CDATA[ arduino ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Electronics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mathematics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 23 Nov 2018 19:10:21 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*jtP8OiDRsdDAdwBjyN5DGA.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Chris Lam</p>
<p>I am a big fan of science toys. I have been looking for one that combines the elegance of math and programming for a while. However, there was not much success in the search. So, I decided to make one myself.</p>
<p>Here is a demo. The flashing LEDs are used to illustrate a mathematical identity visually.</p>
<h3 id="heading-math">Math</h3>
<p>The mathematical identity is the following. The left side of the equation is an arithmetic sum from 1 to <em>n-1</em> and the right side of the equation is “<a target="_blank" href="https://en.wikipedia.org/wiki/Combination">n choose 2</a>”, the number of unique ways to choose 2 items from <em>n</em> items.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*XZUYnypW2Qb9XLxW7VIC7g.png" alt="Image" width="600" height="400" loading="lazy">
<em>Mathematical identity</em></p>
<p>It is not the identity itself that is elegant, but the visual proof itself. Let’s look at the diagram below. There are <em>n=4</em> green dots in the illustration.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*jtP8OiDRsdDAdwBjyN5DGA.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>LED illustration</em></p>
<p>For every two green dots on the bottom row, there is always a unique red dot in the triangle above that corresponds to them. That red dot is the tip of an equilateral triangle with the base specified by the green dots.</p>
<p>Therefore, the number of ways to choose 2 green dots out of <em>n</em> green dots is equal to the sum of the red dots, 1 +2 + 3 + … + (<em>n</em>-1).</p>
<p>In this case, it is 1 + 2 + (4 –1) = 6.</p>
<p>This observation was originally made by Loren C. Larson in <a target="_blank" href="https://www.tandfonline.com/doi/abs/10.1080/07468342.1985.11972910?journalCode=ucmj20&amp;">this article</a>.</p>
<h3 id="heading-programming">Programming</h3>
<p>While it is easy to trace the red dot from the green dots visually, it is more fun and challenging to specify the relationship in code.</p>
<p>Let us assume that we know the indices of the green dots (say, i and j). The programming challenge is to specify the corresponding index of the red dot that forms the equilateral triangle with the green dots.</p>
<p>It looks difficult at first glance.</p>
<p>But the problem can be simplified a lot when we tweak the way that we label the red dots. We can label the red dots from bottom-up instead of top-down.</p>
<p>With that indexing scheme, we can then specify the index of the red dots by the following formula.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*cNwsj8hBqeC6HF1pz1dotg.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>An illustration of how to index the red dots using the indices of the green dots.</em></p>
<p>Here is the complete code used to flash the LEDs using Arduino.</p>
<h3 id="heading-electronics">Electronics</h3>
<p>I solder the LEDs on a board and connect the LEDs to Arduino output pins through 1k resistors. It is very important to use the resistors because they protect the LEDs.</p>
<p>The connection is as follows.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*AGo0vjfM8z5LmZmtOXMiJQ.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>Schematics</em></p>
<p>And when you put them together and load the software to Arduino, it will start flashing like below.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*xggk2l3AY4vi5ZtN-KZYgw.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>Final result</em></p>
<p>Hope you enjoy this gadget!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to use Arduino to check your web server’s response status ]]>
                </title>
                <description>
                    <![CDATA[ By Harshita Arora Last year, I created Crypto Price Tracker (an app which was acquired by Redwood City Ventures this year). A back end member of my team had been using an Arduino setup to check web server response statuses continuously to get updates... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-arduino-to-check-your-web-servers-response-status-9e47e02a61cc/</link>
                <guid isPermaLink="false">66c35597a6c3eebadae8d2dd</guid>
                
                    <category>
                        <![CDATA[ arduino ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Electronics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Tutorial ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 19 Sep 2018 21:13:47 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*bQ91iaTCYt1SEHw-S3Rmxg.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Harshita Arora</p>
<p>Last year, I created <a target="_blank" href="https://itunes.apple.com/us/app/crypto-price-tracker/id1333696099?ls=1&amp;mt=8">Crypto Price Tracker</a> (an app which was acquired by Redwood City Ventures this year). A back end member of my team had been using an Arduino setup to check web server response statuses continuously to get updates all the time. I found that setup to be pretty useful and interesting.</p>
<p>I researched about it and recreated the setup for myself. In this article, I’ll show you how you can build it yourself, too.</p>
<h4 id="heading-things-that-you-need">Things that you need:</h4>
<ol>
<li><a target="_blank" href="https://store.arduino.cc/usa/arduino-uno-rev3">Arduino Uno</a></li>
<li><a target="_blank" href="http://a.co/d/cLNijNF">Ethernet Shield for Arduino</a> (to connect the Arduino to the Internet)</li>
<li>Ethernet Cable</li>
<li>A/B Type USB 2.0 Cable (Power cable for Arduino)</li>
<li>Male-to-Male Jumper Cables (x2)</li>
<li>Breadboard</li>
<li>LED (x1, any color)</li>
<li>Resistor (x1, &gt;100 ohms works)</li>
</ol>
<h4 id="heading-setting-it-up">Setting It Up</h4>
<ol>
<li>Mount/Insert the Ethernet shield on the Arduino.</li>
<li>Insert the positive (longer) end of the LED into the breadboard slot 6a and the negative (shorter) end into slot 5a.</li>
<li>Insert one end of the <strong>resistor</strong> into the breadboard slot 1b and the other into slot 5b.</li>
<li>Insert one end of the <strong>first</strong> jumper cable into the breadboard slot 1e. Insert the other end into the GND slot of the Ethernet shield.</li>
<li>Insert one end of the <strong>second</strong> jumper cable into the breadboard slot 6e. Insert the other end into pin slot 2 of the Ethernet shield.</li>
<li>Connect the <strong>Ethernet</strong> cable from your router to your Ethernet shield.</li>
</ol>
<p>This is what my setup looks like:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*qbA3umNhKDiZy1bBrQZy1g.jpeg" alt="Image" width="600" height="400" loading="lazy"></p>
<ol start="7">
<li><p>Open a command line interface on your machine and check and note your default gateway. This can be done using <code>ipconfig</code> command on Windows or the <code>netstat -nr | grep default</code> command on Linux/Mac.</p>
</li>
<li><p>Download and install the Arduino IDE if you haven’t already.</p>
</li>
<li><p>Open the IDE and go to Files <code>-&amp;</code>gt; Exampl<code>es</code> -&gt; Eth<code>er</code>net -&gt; WebClientRepeating. You should see the following code:</p>
</li>
<li><p>Edit the <strong>line 37</strong> to be an IP address in the range (1–254) of your default gateway IP. So for example, if my default gateway is 10.0.0.1, then I can use an IP address from 10.0.0.2 to 10.0.0.254. It is, however, important to make sure that the IP that you’re using doesn’t conflict with any other IP addresses on your network.</p>
</li>
</ol>
<p>For this example, I changed the line of code to be:</p>
<p><code>**IPAddress ip(10, 0, 0, 2);**</code></p>
<ol start="11">
<li>Change the DNS in <strong>line 40</strong> to be <strong>8.8.8.8</strong> (this is the Google Public DNS and is just something I prefer, you may use a DNS that you prefer).</li>
</ol>
<p>For this example, I changed the line of code to be:</p>
<p><code>**IPAddress myDns(8, 8, 8, 8);**</code></p>
<ol start="12">
<li>Change the URL in <strong>line 45</strong> to a URL matching your web server. If you would like to use an IP address instead, then comment <strong>line 45</strong> and uncomment <strong>line 46</strong>. Since I am using a web server that I’m hosting locally, for this example, I will use an IP address.</li>
</ol>
<p>For this example, I changed the line of code to be:</p>
<p><code>//char server[] = “[www.arduino.cc](http://www.arduino.cc)";</code><br><code>IPAddress server(127,0,0,1);</code></p>
<p>Note that the port or the path here is not important yet. Just the IP Address<br>is needed. If you would like to change the port that is used for the GET<br>request, you may change it on <strong>line 94</strong>.</p>
<p>For this example, I have hosted my local webserver on port 3000. Thus, I will change the code in <strong>line 94</strong> to something like this:</p>
<p><code>if (client.connect(server, 3000)) {</code></p>
<ol start="13">
<li>Edit the <strong>GET</strong> request that is pre-written in <strong>lines 97 - 100</strong> to follow this pattern:</li>
</ol>
<p><code>client.println(“GET /path_to_url HTTP/1.1”);</code><br><code>client.println(“Host: 127.0.0.1”);</code><br><code>client.println(“Connection: close”);</code><br><code>client.println();</code></p>
<ol start="14">
<li>We can now start programming the behaviour of the LED depending on the web server status and response. To do this, we must first declare the pin we’re using for the LED on our Ethernet shield.</li>
</ol>
<p>Add the following line of code after the first two <strong>include</strong> statements of the program:</p>
<p><code>int LED = 2;</code></p>
<ol start="15">
<li>Add the following lines of code at the beginning of the <em>setup()</em> function.</li>
</ol>
<p><code>pinMode(LED, OUTPUT);</code></p>
<p><code>digitalWrite(LED, LOW); //program starts with the LED turned off</code></p>
<ol start="16">
<li>Add the following line of code after the GET request line that we previously edited:</li>
</ol>
<p><code>digitalWrite(LED, LOW);</code></p>
<ol start="17">
<li>Finally, add this line of code at the beginning of the <strong>else</strong> statement of the same conditional:</li>
</ol>
<p><code>digitalWrite(LED, HIGH);</code></p>
<p>And voilà, you’re done!</p>
<p>Upload the program to your Arduino. Open the serial monitor from the top right part of the IDE and watch the response. If your server doesn’t respond, the LED glows, if it does, the LED stays off :)</p>
<p>You can check out my final code <a target="_blank" href="https://gist.github.com/harshitaarora/1e096fe2ba7915964742e3f324f15184">here</a>.</p>
<h4 id="heading-checking-response">Checking Response</h4>
<p>If you would also like to <strong>validate</strong> the response that you receive from your<br>web server, then you may add them inside the following conditional of the<br>program.</p>
<p><code>if (client.available()) {</code><br><code>char c = client.read();</code><br><code>Serial.write(c);</code><br><code>}</code></p>
<p>The variable <strong>c</strong> is where the response is stored.<br>You could check it like this:</p>
<p><code>if (client.available()) {</code></p>
<p><code>char c = client.read();</code><br><code>if(c == “arduino is great”){</code><br> <code>digitalWrite(LED, LOW); //correct response</code><br><code>}</code><br><code>else{</code><br><code>digitalWrite(LED, HIGH); //wrong response</code><br><code>}</code><br><code>Serial.write(c);</code><br><code>}</code></p>
<p>Do note that, if you’re trying to do this, then it’s best to get rid of the<br>digitalWrite statement after the GET request. Depending on your response,<br>you may also have to parse JSON values. There are several ways to do this<br>and plenty of tutorials/articles around for it too! Make sure to check them<br>out!</p>
<p>Have fun! Feel free to email me at <code>harshita (at) harshitaapps.com</code> for any questions, feedback, or ideas!</p>
<p>Make sure to check out <a target="_blank" href="https://itunes.apple.com/us/app/crypto-price-tracker/id1333696099?ls=1&amp;mt=8">Crypto Price Tracker</a> app if you’re interested/invested in cryptocurrencies! :)</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to make a digital voltmeter using Arduino ]]>
                </title>
                <description>
                    <![CDATA[ By Harshita Arora Last Sunday, while I was explaining the basics of electronics and Arduino to my roommate, she challenged me to understand how a voltmeter works and build one from scratch just using the stuff I own already. I accepted the challenge,... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-make-a-digital-voltmeter-using-arduino-b4dbf5b94d6f/</link>
                <guid isPermaLink="false">66c3533fd58e4fdd567d51b5</guid>
                
                    <category>
                        <![CDATA[ arduino ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Electronics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Tutorial ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 23 May 2018 17:34:47 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*Vnn6OGrwT4RHyHEwHBQI7Q.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Harshita Arora</p>
<p>Last Sunday, while I was explaining the basics of electronics and Arduino to my roommate, she challenged me to understand how a voltmeter works and build one from scratch just using the stuff I own already. I accepted the challenge, started hacking, coding, testing, re-coding, and re-testing, and finally I had my voltmeter ready and working by dinner time!</p>
<p>I used Arduino Uno (to collect voltage in analog and to power the LCD), a small LCD screen that I got in my Arduino starter kit (to display the voltage), a breadboard (to connect everything), and jumper wires.</p>
<p>If you’re looking for an easy project to learn electronics, then making a digital voltmeter will be fun. Let’s get started!</p>
<h3 id="heading-the-electric-circuit"><strong>The Electric Circuit</strong></h3>
<h4 id="heading-step-1">Step 1</h4>
<p>Take a breadboard (I used a small one with 30 rows) and connect an LCD screen to it. Then using a wire, connect one wire from the GND pin (ground state) on the Arduino to the negative charge on breadboard, and one wire from the 5V pin to the positive charge. This provides electric current to the columns on the breadboard, which we can now connect to the LCD.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/SNHrp53F6h8pqVjr2-VY80Gs2Zhq44lZY8rU" alt="Image" width="600" height="400" loading="lazy">
<em>This is the basic setup after Step 1.</em></p>
<h4 id="heading-step-2">Step 2</h4>
<p>Now we’ll connect the pins on the LCD to the breadboard so we can get current to it. Connect Pin 1 of the LCD to a negative charge, Pin 2 to a positive charge, Pin 3 to a negative charge, Pin 5 to a negative charge, Pin 15 to a positive charge, and Pin 16 to a negative charge. Plug in your Arduino to test and see if the LCD turns on!</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/T0WP8iFl9qbX-VnI0GYUhcL6OAhA8iSUYhOa" alt="Image" width="600" height="400" loading="lazy">
<em>The LCD lights up!</em></p>
<h4 id="heading-step-3">Step 3</h4>
<p>Let’s connect the LCD to the Arduino so that we can display the voltage (which we will collect from an analog pin) on the LCD. Connect Pins 4, 6, 11, 12, 13, and 14 of the LCD to any digital pin on Arduino (for example, Pin 2). Then put a wire in the GND and another in an analog pin, like A5. The two wires are now your probe leads.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/NW8m7mJlEFP7xsorvz6EW9Y35KRTDN1bjXTM" alt="Image" width="600" height="400" loading="lazy">
<em>Finished electric circuit!</em></p>
<p>We’re now done with the electronics/hardware. Let’s move on to the code.</p>
<h3 id="heading-the-code"><strong>The Code</strong></h3>
<p>The code is pretty simple. We just want to collect the analog signal that the Arduino receives at Pin A5 (or any other analog pin) and convert it to digital. We then want to display the results on the LCD screen.</p>
<p>This is the code that you can copy-paste.</p>
<pre><code>#include &lt;LiquidCrystal.h&gt; int Vpin=A5;float voltage;float volts;LiquidCrystal lcd(<span class="hljs-number">12</span>, <span class="hljs-number">11</span>, <span class="hljs-number">5</span>, <span class="hljs-number">4</span>, <span class="hljs-number">3</span>, <span class="hljs-number">2</span>);
</code></pre><pre><code><span class="hljs-keyword">void</span> setup() {Serial.begin(<span class="hljs-number">9600</span>);lcd.begin(<span class="hljs-number">16</span>,<span class="hljs-number">2</span>);}
</code></pre><pre><code><span class="hljs-keyword">void</span> loop() {
</code></pre><pre><code>voltage = analogRead(Vpin); volts = voltage/<span class="hljs-number">1023</span>*<span class="hljs-number">5.0</span>; Serial.println(volts);lcd.print(“voltage = “);lcd.print(volts);delay(<span class="hljs-number">200</span>);lcd.clear();}
</code></pre><p>What’s going on here?</p>
<p>So we’re first importing the LCD library, then creating a variable named Vpin (which will be the voltage collected from A5). Next, we create two more variables for the voltage, and then a variable of type LiquidCrystal. Finally, we do setup with the Serial monitor (which is a really useful tool in Arduino! Sort of like debug console), convert the analog voltage to digital voltage, and print (display) that value to the LCD screen.</p>
<p>And that’s it! Go and test out various batteries and points! Here are photos from some tests I did:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/VOnX6XrnL4cNqEZ-aBzU0Aj8AtRiEYuf5YQb" alt="Image" width="600" height="400" loading="lazy">
<em>Neutral wires.</em></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/IUX4cbowtANkEPD2YBOzWv7tQUN63NJ0WNc3" alt="Image" width="600" height="400" loading="lazy">
<em>Testing a 1.5V AA battery.</em></p>
<p>Also, if you want to make the reading on the LCD more legible, put a 1k ohm resistor in the path to Pin 3 (which is for contrast adjustments). By limiting the electric current flowing to that pin, you’ll improve the contrast of the screen.</p>
<p><strong>Also important note</strong>: In this voltmeter, whatever voltage you test will go as a direct input to the Arduino, so you should only test stuff that is in the range of volts that Arduino can safely handle (0–5V). Testing with a 9V battery will fry your Arduino.</p>
<p>Thanks to this <a target="_blank" href="https://youtu.be/OZM6wm16uPU">video tutorial</a> for helping me figure out the electric circuit. Special thanks to my friends <a target="_blank" href="https://twitter.com/nickarner">Nick Arner</a> and <a target="_blank" href="https://twitter.com/johnny___wang">Johnny Wang</a> for helping me fix stuff. And thanks to <a target="_blank" href="https://twitter.com/LauraDeming">Laura Deming</a> for the challenge! :)</p>
<p>More articles and tutorials on electronics/hardware and brain-computer interfaces on the way! :D</p>
<p>If you have feedback to share, feel free to email me at harshita@harshitaapps.com. I look forward to hearing from you!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The hardware behind Otto: a monkey plush which became my vocal assistant ]]>
                </title>
                <description>
                    <![CDATA[ By Flavio De Stefano Otto is a monkey plush that we found in a highway store during a trip with my girlfriend in February 2017. Its ability, while being extremely cute, was to listen to you, then walk and repeat all things with a higher pitch. My goa... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-hardware-behind-otto-a-monkey-plush-which-became-my-vocal-assistant-96a25c634021/</link>
                <guid isPermaLink="false">66c361851a1cf73cbc81f101</guid>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Electronics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Raspberry Pi ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 13 Apr 2018 07:36:32 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*PiGGkpQ-b6g5yj5wb1-fLQ.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Flavio De Stefano</p>
<p>Otto is a monkey plush that we found in a highway store during a trip with my girlfriend in February 2017.</p>
<p>Its ability, while being extremely cute, was to listen to you, then walk and repeat all things with a higher pitch.</p>
<p>My goal was to make it more powerful by transforming it into a vocal assistant.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/COJTbvLC2I42BpC0vSMkIT6k4NBhl0UU18SY" alt="Image" width="600" height="400" loading="lazy">
<em>SkeletOtto and Otto</em></p>
<p>This is the first part of a series about Otto.</p>
<p>Originally, it was composed by the following hardware:</p>
<ul>
<li>A motor connected to his legs for allowing him to walk</li>
<li>A simple, closed (for modifications), built-in board</li>
<li>A microphone and a speaker</li>
<li>A push button to start the listening phase</li>
<li>Four AA batteries</li>
<li>A switch to completely power off the circuit</li>
</ul>
<p>I wanted to replace all these things with fresh and <strong>programmable</strong> hardware.</p>
<p>The real challenge here was to find the rights components that fitted in the original enclosure. The available space wasn’t much, so every choice had to be done conscientiously.</p>
<h4 id="heading-base-board">Base board</h4>
<p>The preferred hardware for this project are Raspberry PI boards.</p>
<p>They are tiny and powerful enough to allow developers to use a high-level programming language and built-in libraries without flashing the software every-time.</p>
<p>Furthermore, you can debug your application in a more comfortable environment.</p>
<p>The best hardware at the time was the Raspberry Pi Zero W. Launched at the end of February 2017, the Pi Zero W has all the functionality of the original Pi Zero but with added connectivity.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/W3wJFAEqo4qznGUNqgsRJ378nCWaqhKJnzTS" alt="Image" width="600" height="400" loading="lazy">
<em>Raspberry Pi Zero W</em></p>
<p>The board was not enough for such a project, so I added additional hardware.</p>
<h4 id="heading-audio-components">Audio components</h4>
<p>To build a vocal assistant, we need audio components. The requirements for these components are, of course, a speaker and a microphone.</p>
<p>For the microphone, I tried a USB microphone. The problem with this accessory was that it was not sensible as I wished. Furthermore an additional USB hub was required to connect it.</p>
<p>Moreover, I couldn’t connect a raw speaker easily.</p>
<p>For this reason, I opted to buy an additional board that accomplished this task very well: <a target="_blank" href="https://www.seeedstudio.com/ReSpeaker-2-Mics-Pi-HAT-p-2874.html"><strong>ReSpeaker 2-Mics Pi HAT.</strong></a></p>
<p>ReSpeaker 2-Mics Pi HAT is a dual-microphone expansion board for Raspberry Pi designed for AI and voice applications.</p>
<p>The board is developed based on WM8960, a low power stereo codec. There are 2 microphones on both sides of the board for collecting sounds. It also provides 3 APA102 RGB LEDs, 1 User Button and 2 on-board Grove interfaces.</p>
<p>I did not plan to connect LEDs to my board, but the fact that this HAT has built-in LEDs made me think to use them.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/k7MQ4agg2sWiQDawXk6cYrlQClwDRRoO42LX" alt="Image" width="600" height="400" loading="lazy">
<em>ReSpeaker 2-Mics Pi HAT — Hardware specifications</em></p>
<p>Then I took an old Bluetooth mini-speaker, disassembled it, and connected it to the JST 2.0 Speaker Out port.</p>
<p>To make it work, you have to install their drivers on your board. Drivers are also used to control LEDs within your application via a standard protocol.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/8mM4GG3AQTMy-g7eQnJL0c20uTuvHnSjxSOl" alt="Image" width="600" height="400" loading="lazy">
<em>ReSpeaker 2-Mics Pi HAT</em></p>
<p><em>Hint: when you install a shield, all your GPIO pins are covered. It’s useful to know which pins are <strong>really used</strong> by your board. To accomplish that, use <a target="_blank" href="https://pinout.xyz/">https://pinout.xyz/</a></em></p>
<p>For example, for this board, check out this link: <a target="_blank" href="https://pinout.xyz/pinout/respeaker_2_mics_phat">https://pinout.xyz/pinout/respeaker_2_mics_phat</a></p>
<h4 id="heading-powering-the-board">Powering the board</h4>
<p>The Raspberry Pi board can be easily powered via USB 5V input. The problem with this approach is that you have to buy a battery pack and connect it via USB.</p>
<p>I didn’t find any battery pack small enough to fit my plush, then my unique alternative was using LiPo batteries.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/HfXn7YZnmt89j10xAtkQAe94r7pu4wXWbM24" alt="Image" width="600" height="400" loading="lazy">
<em>LiPo Battery — 3.7V 2000mAh</em></p>
<p>You can’t connect your LiPo battery to your board, you have to use a converter. It can be powered by any 3.7V LiIon/LiPoly battery, and then it converts the battery output to 5.2V DC.</p>
<p>Initially I bought a <a target="_blank" href="https://shop.pimoroni.com/products/lipo-shim"><strong>LiPo SHIM</strong></a>, but I didn’t notice that this controller provides power to your board without charging your batteries.</p>
<p>For this reason I switched to <a target="_blank" href="https://shop.pimoroni.com/products/powerboost-500-charger-rechargeable-5v-lipo-usb-boost-500ma"><strong>Adafruit PowerBoost 500 Charger.</strong></a> It has a built-in battery charger circuit. You’ll be able to keep your project running even while charging the battery!</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/4XO2X19DkFrdmMQjjPtDySyPnBs38Fqkc2bV" alt="Image" width="600" height="400" loading="lazy">
<em>Adafruit PowerBoost 500 Charger</em></p>
<h4 id="heading-additional-hardware">Additional hardware</h4>
<p>The software uses the “hotword” concept to start the interaction. Basically, it continuously listens for an hotword, like “Hey Otto”, then you just talk and say commands.</p>
<p>For having an alternative method to start the interaction, I installed a <strong>push button</strong> connected directly to the GPIO board, at GPIO8 pin.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/AbfTw6DM4xshozwQGOlgqUg-avN-5skzEFEy" alt="Image" width="600" height="400" loading="lazy">
<em>Push button</em></p>
<p>Now only one thing was missing: <strong>the power on-off switch.</strong></p>
<p>I connected this simple component to the PowerBoost Charger via its ENABLE port. The purpose of the ENABLE port is to disconnect the output completely.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/4CoVDgx6OzOzkkcFBVKqGLQSmRmIQKCdRVPZ" alt="Image" width="600" height="400" loading="lazy">
<em>Power on-off switch</em></p>
<h4 id="heading-connect-everything-together">Connect everything together</h4>
<p>Here you can see in details the complete circuit diagram (<a target="_blank" href="https://www.circuit-diagram.org/circuits/0d85ce05">https://www.circuit-diagram.org/circuits/0d85ce05</a>)</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/LE5xX5LHgXWFVDpDIr3iWDPXvdztUmTgt0WC" alt="Image" width="600" height="400" loading="lazy">
<em>Otto Circuit diagram</em></p>
<p>And here a snapshot of the work:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/mk8sBTQqHDokaq1MrbGo6PGXnWdnnKTUjq6x" alt="Image" width="600" height="400" loading="lazy">
<em>The hardware behind Otto</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Controlling an External LED using a Raspberry Pi and GPIO pins ]]>
                </title>
                <description>
                    <![CDATA[ By Shahbaz Ahmed In this post we’ll explore Raspberry Pi GPIO pins by creating a “Hello World” GPIO program that results in a blinking red LED. We’ll be using the Python programming language. I am using a headless Raspberry Pi Zero WH (wireless with ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/hello-gpio-blinking-led-using-raspberry-pi-zero-wh-65af81718c14/</link>
                <guid isPermaLink="false">66c34c3893db2451bd441474</guid>
                
                    <category>
                        <![CDATA[ Electronics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Raspberry Pi ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sat, 07 Apr 2018 00:00:00 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/0*xch19X3RFpIZdFXw.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Shahbaz Ahmed</p>
<p>In this post we’ll explore Raspberry Pi GPIO pins by creating a “Hello World” GPIO program that results in a blinking red LED. We’ll be using the Python programming language. I am using a headless Raspberry Pi Zero WH (wireless with soldered headers) with Raspbian Stretch Lite (Raspberry Pi operating system with a minimal image based on Debian Stretch).</p>
<p>I will talk to my headless Pi using <code>ssh</code> and transfer necessary files from my Mac to Pi using <code>scp</code> commands. I am assuming you have your Raspberry Pi up and running with Raspbian OS installed. If not, then there are lot of articles on the Internet describing how to setup your Pi and install Raspbian, including the official <a target="_blank" href="https://www.raspberrypi.org/documentation/">Raspberry Pi documentation</a>.</p>
<p>Things you’ll need:</p>
<ul>
<li>1 x Raspberry Pi (I am using the Pi Zero WH model)</li>
<li>1 x bread board</li>
<li>1 x red LED light</li>
<li>1 x 330 ohm resistor</li>
<li>2 x female to male jumper cable</li>
</ul>
<h3 id="heading-gpio-pins-configuration">GPIO pins configuration</h3>
<p><strong>GPIO</strong> stands for <strong>General Purpose Input Output</strong>. With the help of GPIO pins, a Raspberry Pi can connect and interact with external electronic components. Recent Raspberry Pi models (Pi 3, Pi Zero, Pi W and Pi WH models, and so on) contain 40 GPIO pins. Each pin can turn on or off, or go <code>HIGH</code> or <code>LOW</code> in electronic terms. If the pin is <code>HIGH</code> it outputs 3.3 volts, if the pin is <code>LOW</code> it is off.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*Zpa1YOQcMlvu-Sxs.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In our example, we’ll be using <code>pin 6</code> (ground) and <code>pin 25</code>. To know more about the GPIO pins in Raspberry Pi, checkout <a target="_blank" href="https://pinout.xyz/">pinout.xyz</a>.</p>
<h3 id="heading-setting-up-the-circuit">Setting up the circuit</h3>
<p>You should turn the Pi off while building the circuit. We’ll create a circuit as depicted in the diagram below:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*xch19X3RFpIZdFXw.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><strong>Note</strong>: The resistor in the image is of 220 Ohm, but I have used 330 Ohm in my circuit.</p>
<ol>
<li>Use a female to male jumper cable to connect <code>pin 6</code> (Ground) (black cable in the image above) to the breadboard negative row.</li>
<li>Use another female to male jumper to connect to connect GPIO <code>pin 25</code> to point represented by row <code>A</code> and column <code>12</code> on the breadboard as shown above (blue cable in the image above).</li>
<li>Connect one end of a 330 ohm <strong>resistor</strong> to the negative row (the row that is highlighted in green where the black cable above earlier connected) and connect the other end to the point represented by row <code>C</code> column <code>11</code> on the breadboard as shown above.</li>
<li>The shorter end of the <strong>LED</strong> is the negative end and the longer is the positive end. The longer end should always be connected to the point in the circuit with higher voltage (that is, higher potential). The shorter end of the <strong>LED</strong> is connected to a GPIO <code>pin 25</code> (which can output 3.3V) via the blue cable and the longer end is connected to the ground <code>pin 6</code> (which is 0V and acts like the negative terminal of the battery) via the black cable with a resistor in between them.</li>
</ol>
<h3 id="heading-resistor">Resistor</h3>
<p>Keeping in mind that I had taken introductory classes on electrical and electronics engineering quite some time ago (4 to 5 years approx.), I had two questions that I needed answers for. Please bear with me for being naive in this context.</p>
<ol>
<li>Why do we need a resistor in our circuit?</li>
<li>How do we determine how many Ohms (the measure of electrical resistance) the resistor should be?</li>
</ol>
<p>A resistor is required to dissipate the extra electrical energy (voltage) from the Raspberry Pi. Raspberry Pi is rated to supply 50mA at 3.3V. Let’s say our red LED can have a forward voltage (forward voltage is the “negative voltage,” used by the LED when it’s on) of around 2V and consumes 4mA current. So the remaining 1.3V should be dissipated by the resistor.</p>
<p>Using Ohm’s law, <code>V = IR</code>, <code>R</code> = <code>(3.3V - 2V) / (4/1000)</code> which comes to around <code>325 ohms</code> — so I recommend using a <strong>330 ohm resistor</strong>.</p>
<p>I discovered this from a <a target="_blank" href="https://www.raspberrypi.org/forums/viewtopic.php?t=84240">Raspberry Pi forum discussion</a>.</p>
<h3 id="heading-making-the-led-blink-using-python">Making the LED blink using Python</h3>
<p>Now that we have a complete circuit, the next part is to program the GPIO ports to make the magic happen: to get the LED to blink. We will be using the output of GPIO <code>pin 25</code> to make the LED blink.</p>
<p>Start your Pi and connect to it using ssh. In the terminal, use the following command to install the Python library <code>gpiozero</code>. The <code>gpiozero</code> library makes working with GPIO pins and connected external components very simple.</p>
<p>To install the Python library, type <code>sudo apt-get install python3-gpiozero</code>.</p>
<p>Now we will run some Python code. Save the code below onto your your Pi file system in a file named <code>blink1.py</code>. The script basically turns on the LED connected to <code>pin 25</code>, sleeps for 1 second, then turns off the LED, and again sleeps for 1 second. And this is done continuously in a loop until the program is terminated (pressing <code>ctrl</code> + <code>c</code>).</p>
<p>Now from terminal, go the the directory where the script is saved and run it using the command: <code>python3 blink1.py</code>.</p>
<p>You will see the red LED blinking like this:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*5v09jlygdroPzBCF.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We can build lots of fun stuff using <code>gpiozero</code> using a similar setup. Check out <a target="_blank" href="https://gpiozero.readthedocs.io/en/stable/recipes.html">the documentation</a> for <code>gpiozero</code> which demonstrates some interesting examples. Try building a traffic light system.</p>
<p><em>Originally published at <a target="_blank" href="http://shahbaz.co">shahbaz.co</a> on April 7, 2018.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to get started with FreeRTOS and ESP8266 ]]>
                </title>
                <description>
                    <![CDATA[ By Denis Nuțiu Recently, I purchased a NodeMCU from AliExpress for about $4. The reason I did this was to find out what all the fuss is about with ESP8266. NodeMCU is an open source IoT platform. It includes firmware which runs on the ESP8266 Wi-Fi S... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-get-started-with-freertos-and-esp8266-7a16035ddd71/</link>
                <guid isPermaLink="false">66c35249bc39b1419091be4b</guid>
                
                    <category>
                        <![CDATA[ Electronics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ESP8266 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ wifi ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sat, 03 Feb 2018 15:57:54 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*2fa1eXR1ZEeWUA54bbY3Ag.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Denis Nuțiu</p>
<p>Recently, I purchased a NodeMCU from AliExpress for about $4. The reason I did this was to find out what all the fuss is about with ESP8266.</p>
<p>NodeMCU is an open source IoT platform. It includes firmware which runs on the ESP8266 Wi-Fi SoC from Espressif Systems, and hardware which is based on the ESP-12 module.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/WWQgoFxzsaqMPtrLF33j93TOcM5hBstHKqON" alt="Image" width="600" height="400" loading="lazy">
<em>Source: ESP8266 Datasheet</em></p>
<p>Compared to the Arduino UNO, my ESP8266 totally knocks it out of the park when it comes to CPU power and price.</p>
<p>The ESP8266 is 500% faster and 82% cheaper than the Arduino. The ESP8266 also has WiFi connectivity.</p>
<p>I was very surprised when I visited the <a target="_blank" href="https://www.espressif.com/en/products/hardware/esp8266ex/overview">Espressif website</a> for the ESP8266. There’s lots of documentation and resources that you can use. For example, there’s an Android application which tells your ESP8266 to connect to your WiFi. The app sends the SSID and password as packets, the ESP8266 sniffs them, and then it connects to your WiFi. This is called SmartConfig, and was invented by Texas Instruments.</p>
<p>In this article, I will guide you to setup and run the Smart Config example from the Espressif RTOS SDK.</p>
<h4 id="heading-heres-the-things-youll-need">Here’s the things you’ll need:</h4>
<ul>
<li>A modern computer.</li>
<li>A NodeMCU board with ESP12-E</li>
<li>VirtualBox (<a target="_blank" href="https://www.virtualbox.org/wiki/Downloads">https://www.virtualbox.org/wiki/Downloads</a>)</li>
<li>Ubuntu Server LTS (<a target="_blank" href="https://www.ubuntu.com/download/server">https://www.ubuntu.com/download/server</a>)</li>
</ul>
<h3 id="heading-configuring-virtualbox-for-development">Configuring VirtualBox for development</h3>
<ol>
<li>Download VirtualBox and install Ubuntu Server. This should be easy to do, but if you don’t know how, Google it or have a look at this graphic <a target="_blank" href="https://dalanzg.github.io/tips-tutorials/ubuntu/2016/04/15/install-ubuntu-server-on-virtualbox/">step by step guide</a>. Installing an OS is a nice skill to have. <em>(Tip: When VirtualBox prompts you to select the disk, make it dynamically allocated and at least 50GB in size. This will save you some headaches further down the line.)</em></li>
<li>Make sure that you can access the internet from within the virtual machine and configure the DNS server:</li>
</ol>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1VXQI9xykHzqgT9nDFIjTeUU5M0GasTMjVkS" alt="Image" width="600" height="400" loading="lazy">
<em>Right click the machine then Settings -&gt; Network</em></p>
<p>To configure the DNS server, have a look at this <a target="_blank" href="https://askubuntu.com/questions/346838/how-do-i-configure-my-dns-settings-in-ubuntu-server">example</a>.</p>
<blockquote>
<p>Example: <code>dns-nameservers 8.8.8.8 8.8.4.4</code> If you can ping Google, then you’re good to go!</p>
</blockquote>
<ol start="3">
<li><p>(Optional) Install <a target="_blank" href="https://help.ubuntu.com/lts/serverguide/openssh-server.html">OpenSSH</a> and <a target="_blank" href="https://help.ubuntu.com/lts/serverguide/samba-fileserver.html">Samba</a> server. This will make your life much easier.</p>
</li>
<li><p><strong>(Optional)</strong> Enable port forwarding. In order to SSH directly into your virtual machine, you need to enable port forwarding. For example, to map the <strong>port 2222</strong> on your <strong>host machine</strong> to the <strong>port 22</strong> of your <strong>virtual machine</strong>.</p>
</li>
</ol>
<p><img src="https://cdn-media-1.freecodecamp.org/images/vxD8ttK0h7T3Rqr9-wsA0dEXaizQ84Zdc9CX" alt="Image" width="600" height="400" loading="lazy">
<em>Enable Port forwarding: Settings -&gt; Network <strong>-&gt; Port Forw</strong>arding</em></p>
<p>If you have enabled port forwarding, you can now SSH into your virtual machine from your Host machine as in the figure below.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/iZh3PIg0ZdEnaSqoCvfa8us076gknELpRYRX" alt="Image" width="600" height="400" loading="lazy">
<em>FIG1: ssh -p 2020 denis@localhost</em></p>
<p>Note: If you’re on Windows, you need <strong>Putty</strong> in order to SSH into the virtual machine.</p>
<ol start="5">
<li>Plug in your NodeMCU and execute the following command:</li>
</ol>
<p><code>tail -f /var/log/kern.log</code></p>
<p>This should reveal to you that the device has been identified as /dev/ttyUSB0. If nothing happens, then you need to add the USB to the virtual machine. After adding the USB, unplug and plug your device in again.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/rBbsqsBd84y-dgnFeS6phDTXlM-tOCaXyPiU" alt="Image" width="600" height="400" loading="lazy">
<em>Adding USB: Settings -&gt; Ports -&gt; USB</em></p>
<p>If you’ve reached this point and every thing is working, <strong>congratulations</strong>! You’re now ready to compile the SDK and run the SmartConfig example. You can even shoot me a tweet at <a target="_blank" href="https://twitter.com/metonymyqt">https://twitter.com/metonymyqt</a></p>
<h3 id="heading-compiling-the-sdk-and-flashing-the-board"><strong>Compiling the SDK and flashing the board</strong></h3>
<ol>
<li>Install the required packages (as below). This info is also available on the SDK’s readme.md.</li>
</ol>
<pre><code>sudo apt-get install make unrar-free autoconf automake libtool gcc g++ gperf flex bison texinfo gawk ncurses-dev libexpat-dev python-dev python python-serial sed git unzip bash help2man wget bzip2 libtool-bin
</code></pre><ol start="2">
<li><p>Create a new folder and navigate into it: <code>mkdir Development &amp;&amp; cd Development</code></p>
</li>
<li><p>Clone the Open SDK: <a target="_blank" href="https://github.com/pfalcon/esp-open-sdk">https://github.com/pfalcon/esp-open-sdk</a></p>
</li>
</ol>
<p><code>git clone --recursive https://github.com/pfalcon/esp-open-sdk.git</code></p>
<ol start="3">
<li>Run make: <code>make</code></li>
</ol>
<p><strong>Warning: This step will take a while to finish so please be patient.</strong> On my virtual machine it completed after 50 minutes. On yours it might take more or less, but before you run, make make sure that you’re <strong>connected to the internet</strong> and <strong>DNS is properly configured</strong>. The best way to check this is to execute a ping to Google or some other site if Google is blocked in your region.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/rqBC76LdfeK2PStc1YiC1RCFArzHF4IjXXdi" alt="Image" width="600" height="400" loading="lazy">
<em>Successful ping command: $ ping medium.com</em></p>
<p>If your ping is successful, you can minimize the windows and watch an episode of your favorite TV show. Come back after about 40 minutes (but make sure your computer doesn’t go to sleep).</p>
<p>After the SDK has been built successfully, you’ll see a message telling you to put something in your path. To do so, execute the following:</p>
<pre><code>echo <span class="hljs-string">'export PATH=/home/denis/Development/esp-open-sdk/xtensa-lx106-elf/bin:$PATH'</span> &gt;&gt; ~/.profile
</code></pre><p>The command will append the string to the <strong>~/.profile</strong> file. Now please run the following command:</p>
<p><code>xtensa-lx106-elf-gcc --version</code></p>
<p>If the command executes successfully, then you’re good to go!</p>
<ol start="4">
<li>Test your board</li>
</ol>
<p>Plug your NodeMCU and run <strong>lsusb</strong> to verify that your device is connected. After that, run <strong>esptool.py chip_id</strong>. You should now see the board’s chip id.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/lf0BJC2bys9XbFPVEzc0B9LsUGtw6dbJtoOl" alt="Image" width="600" height="400" loading="lazy">
_esptool.py chip<em>id</em></p>
<ol start="5">
<li>Clone <a target="_blank" href="https://github.com/espressif/ESP8266_RTOS_SDK">ESP8266_RTOS_SDK</a></li>
</ol>
<pre><code>git clone https:<span class="hljs-comment">//github.com/espressif/ESP8266_RTOS_SDK.git</span>
</code></pre><ol start="6">
<li>Export the SDK path and SDK/BIN path using the commands below.</li>
</ol>
<pre><code>echo <span class="hljs-string">'export SDK_PATH=/home/denis/Development/ESP8266_RTOS_SDK'</span> &gt;&gt; ~/.profile
</code></pre><pre><code>echo <span class="hljs-string">'export BIN_PATH=/home/denis/Development/ESP8266_RTOS_SDK/bin'</span> &gt;&gt; ~/.profile
</code></pre><ol start="7">
<li>Compile the SmartConfig example</li>
</ol>
<pre><code>cd /home/denis/Development/ESP8266_RTOS_SDK/examples/smart_config/
</code></pre><pre><code>chmod +x ./gen_misc.sh
</code></pre><pre><code>./gen_misc.sh
</code></pre><p>Now accept the default values until you’re asked for <strong>SPI_SIZE_MAP.</strong> This is where you select <strong>4</strong> because the NodeMCU has a flash size of 32Mbit and this translates to 4MB. _You can also select SPI<em>SPEED 3=80Mhz</em></p>
<p>You’ll see something like this:</p>
<pre><code>!!!SDK_PATH: <span class="hljs-regexp">/home/</span>denis/Development/ESP8266_RTOS_SDKBIN_PATH: <span class="hljs-regexp">/home/</span>denis/Development/ESP8266_RTOS_SDK/bin
</code></pre><pre><code>No boot needed.Generate eagle.flash.bin and eagle.irom0text.bin successully <span class="hljs-keyword">in</span> BIN_PATHeagle.flash.bin — — — →<span class="hljs-number">0x00000ea</span>gle.irom0text.bin — →<span class="hljs-number">0x20000</span>!!!
</code></pre><ol start="8">
<li>Flash the board</li>
</ol>
<pre><code>cd $BIN_PATH
</code></pre><pre><code>esptool.py erase_flash
</code></pre><pre><code>esptool.py write_flash <span class="hljs-number">0x00000</span> $BIN_PATH/eagle.flash.bin <span class="hljs-number">0x20000</span> $BIN_PATH/eagle.irom0text.bin <span class="hljs-number">0x3FC000</span> $BIN_PATH/esp_init_data_default.bin
</code></pre><p>Now, if you reset the board, you should see no LED blinking.</p>
<ol start="9">
<li><p>Use the Phone Application</p>
</li>
<li><p><a target="_blank" href="https://play.google.com/store/apps/details?id=com.cmmakerclub.iot.esptouch&amp;hl=en">Android Application</a></p>
</li>
<li><a target="_blank" href="https://itunes.apple.com/us/app/ti-wifi-smartconfig/id580969322?mt=8">iPhone Application</a></li>
</ol>
<p><img src="https://cdn-media-1.freecodecamp.org/images/xoDqT7zXJ7toeEl8Jm-ymdZQvmg7YnzeGwBM" alt="Image" width="600" height="400" loading="lazy">
<em>ScreenShot from my Android Device</em></p>
<p>Open the Application, make sure that you’re connected to a WiFi AP, enter your password, and press confirm. After a few seconds the ESP8266 should connect to your AP. That’s it. Congratulations for reaching the end!</p>
<p>If you want to develop more using the ESP8266-RTOS-SDK, please visit the official websites. You’ll find a lot of resources and documentation there. Also, please take a look at the other examples found in the SDK folder.</p>
<p>Thank you very much for your time reading this. If you want to reach out to me, you can do so on Twitter: <a target="_blank" href="https://twitter.com/metonymyqt">MetonymyQT</a></p>
<h4 id="heading-resources">Resources</h4>
<ul>
<li><a target="_blank" href="https://www.espressif.com/en/products/hardware/esp8266ex/overview">ESP8266 Overview</a></li>
<li><a target="_blank" href="https://www.espressif.com/en/products/hardware/esp8266ex/resources">ESP8266 Resources</a></li>
<li><a target="_blank" href="https://www.freertos.org/">FreeRTOS Website</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
