<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: GOROman</title>
    <description>The latest articles on DEV Community by GOROman (@goroman).</description>
    <link>https://dev.to/goroman</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F42663%2Ffc873bdd-ff0a-4011-a306-e3a057fde01b.jpeg</url>
      <title>DEV Community: GOROman</title>
      <link>https://dev.to/goroman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/goroman"/>
    <language>en</language>
    <item>
      <title>The HAH Model: A New Paradigm of Human-AI Collaboration</title>
      <dc:creator>GOROman</dc:creator>
      <pubDate>Tue, 08 Apr 2025 22:16:47 +0000</pubDate>
      <link>https://dev.to/goroman/the-hah-model-a-new-paradigm-of-human-ai-collaboration-2fg8</link>
      <guid>https://dev.to/goroman/the-hah-model-a-new-paradigm-of-human-ai-collaboration-2fg8</guid>
      <description>&lt;h2&gt;
  
  
  Abstract
&lt;/h2&gt;

&lt;p&gt;This paper explores the HAH (Human→AI→Human) model, a novel paradigm in which AI systems delegate tasks to humans, inverting the traditional human-AI relationship. Using the ViXion01S-Firmware project as a case study, we examine the implementation, benefits, and implications of this emerging collaborative framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Introduction
&lt;/h2&gt;

&lt;p&gt;As digital transformation accelerates, the relationship between humans and artificial intelligence continues to evolve. Traditional Human-AI Interaction (HAI) has primarily followed a unidirectional flow where humans instruct AI systems to perform tasks. However, with advancements in AI capabilities, a new model has emerged—the HAH model—where AI systems analyze complex situations, identify tasks requiring human intervention, and delegate these tasks to humans.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Definition of the HAH Model
&lt;/h2&gt;

&lt;p&gt;The HAH model consists of the following stages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Human→AI&lt;/strong&gt;: Initial human instruction to the AI system&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI (Processing &amp;amp; Decision)&lt;/strong&gt;: AI analyzes the work and generates task requests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI→Human&lt;/strong&gt;: AI delegates specific tasks to humans&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human (Execution)&lt;/strong&gt;: Humans perform the requested tasks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human→AI&lt;/strong&gt;: Humans report results back to the AI&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  3. Parallels to Industrial Revolution
&lt;/h2&gt;

&lt;p&gt;The HAH model bears similarities to the relationship between the bourgeoisie and proletariat during the Industrial Revolution. However, a critical distinction remains: humans still design and control AI systems, maintaining ultimate decision-making authority.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Implementation Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  4.1 ViXion01S-Firmware Project
&lt;/h3&gt;

&lt;p&gt;The ViXion01S-Firmware project implemented the HAH model using GitHub Actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI modified firmware and requested functionality verification from a human expert (Moriya-san)&lt;/li&gt;
&lt;li&gt;After a specified time period, AI automatically sent reminders if no human response was received&lt;/li&gt;
&lt;li&gt;Based on human feedback, AI determined subsequent actions
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Moriya-san Reminder&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;pr_number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Pull&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Request&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Number'&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;wait_time&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Reminder&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Wait&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Time&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(minutes)'&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4.2 Gig Economy Platforms as HAH Model Examples
&lt;/h3&gt;

&lt;p&gt;Several gig economy platforms demonstrate HAH model principles through algorithmic task assignment:&lt;/p&gt;

&lt;h4&gt;
  
  
  4.2.1 Uber Eats
&lt;/h4&gt;

&lt;p&gt;Uber Eats utilizes sophisticated algorithms to assign delivery tasks to human drivers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI analyzes order locations, driver positions, and estimated delivery times&lt;/li&gt;
&lt;li&gt;System assigns tasks to optimal human drivers based on multiple variables&lt;/li&gt;
&lt;li&gt;Humans execute the delivery tasks and report completion through the app&lt;/li&gt;
&lt;li&gt;AI evaluates performance and adjusts future task assignments accordingly&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  4.2.2 Mercari Hello (Japan)
&lt;/h4&gt;

&lt;p&gt;Launched in March 2024, Mercari Hello has rapidly grown to enroll over 8 million gig workers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI matches short-term work opportunities with qualified workers&lt;/li&gt;
&lt;li&gt;No resumes or interviews required, enabling instant job matching&lt;/li&gt;
&lt;li&gt;Human workers complete assigned tasks and receive immediate payment&lt;/li&gt;
&lt;li&gt;System learns from task completion patterns to improve future assignments&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  4.2.3 Timee (Japan)
&lt;/h4&gt;

&lt;p&gt;With over 1.2 million users, Timee has positioned itself as a crucial player in Japan's evolving labor market:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Platform allows users to work shifts as short as one hour at restaurants, convenience stores, and hotels&lt;/li&gt;
&lt;li&gt;AI-driven matching system connects businesses with available workers&lt;/li&gt;
&lt;li&gt;Workers execute tasks and receive quick payment&lt;/li&gt;
&lt;li&gt;System continuously optimizes task allocation based on performance data&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Gig Economy Market Size and HAH Transformation Potential
&lt;/h2&gt;

&lt;h3&gt;
  
  
  5.1 Current Market Size
&lt;/h3&gt;

&lt;p&gt;The global gig economy represents a significant and rapidly growing segment of the labor market:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Global market size valued at $556.7 billion in 2024&lt;/li&gt;
&lt;li&gt;Projected to reach $1.85 trillion by 2032, growing at a CAGR of 16.2%&lt;/li&gt;
&lt;li&gt;Alternative estimates from Staffing Industry Analysts place the market at $3.7 trillion in 2023&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Regional markets show varying growth rates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Japan: $17.8 billion in 2024, growing at a CAGR of 17.7%&lt;/li&gt;
&lt;li&gt;Japanese freelance platforms projected to reach $544.5 million by 2030 (CAGR 26.5%)&lt;/li&gt;
&lt;li&gt;As of 2021, freelance workers represented approximately 20% of Japan's workforce&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5.2 HAH Transformation Potential
&lt;/h3&gt;

&lt;p&gt;The gig economy is particularly well-positioned for HAH model transformation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Algorithm-Driven Task Assignment&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Real-Time Optimization&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Predictive Task Creation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Autonomous Quality Control&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Market Size Expansion&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  6. Benefits of the HAH Model
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Complementary utilization of human and AI strengths&lt;/li&gt;
&lt;li&gt;Automation of repetitive and routine tasks&lt;/li&gt;
&lt;li&gt;Strategic deployment of human expertise only when necessary&lt;/li&gt;
&lt;li&gt;Improved workflow efficiency through notifications and reminders&lt;/li&gt;
&lt;li&gt;Increased market efficiency through optimal task-worker matching&lt;/li&gt;
&lt;li&gt;Enhanced service quality through continuous feedback loops&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7. Challenges and Future Directions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Balancing human autonomy with AI directives&lt;/li&gt;
&lt;li&gt;Privacy and ethical considerations&lt;/li&gt;
&lt;li&gt;Building human trust in AI judgment&lt;/li&gt;
&lt;li&gt;Expanding application to more complex tasks&lt;/li&gt;
&lt;li&gt;Addressing potential economic displacement&lt;/li&gt;
&lt;li&gt;Developing appropriate regulatory frameworks&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  8. Addressing Potential Luddite-like Resistance
&lt;/h2&gt;

&lt;h3&gt;
  
  
  8.1 Transparency and Accountability
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Make AI decision-making processes transparent&lt;/li&gt;
&lt;li&gt;Clearly establish that humans retain final decision-making authority&lt;/li&gt;
&lt;li&gt;Explicitly communicate system purposes and limitations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8.2 Comprehensive Education and Reskilling
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Develop training programs for adapting to new collaborative models&lt;/li&gt;
&lt;li&gt;Strengthen digital literacy education&lt;/li&gt;
&lt;li&gt;Develop new skill sets for coexisting with AI&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8.3 Gradual Implementation and Participatory Design
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Begin with small-scale pilot projects&lt;/li&gt;
&lt;li&gt;Involve end-users in the design process&lt;/li&gt;
&lt;li&gt;Establish feedback loops and continuous improvement&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8.4 Social Safety Nets
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create support systems during technological transitions&lt;/li&gt;
&lt;li&gt;Generate new employment opportunities&lt;/li&gt;
&lt;li&gt;Establish fair benefit distribution mechanisms&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8.5 Ethical Guidelines and Regulation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Establish ethical frameworks for HAH/HaaS models&lt;/li&gt;
&lt;li&gt;Promote industry standards and self-regulation&lt;/li&gt;
&lt;li&gt;Develop appropriate legal frameworks&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  9. Comparative Analysis with Traditional HAI and HaaS Models
&lt;/h2&gt;

&lt;h3&gt;
  
  
  9.1 Traditional Human-AI Interaction (HAI)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Unidirectional (Human → AI)&lt;/li&gt;
&lt;li&gt;Humans initiate tasks and monitor AI outcomes&lt;/li&gt;
&lt;li&gt;Limitations in feedback and autonomy&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  9.2 Human-as-a-Service (HaaS)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Refers to human labor accessed via APIs/platforms&lt;/li&gt;
&lt;li&gt;Used for microtasks or escalation&lt;/li&gt;
&lt;li&gt;More static and reactive compared to HAH&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  9.3 Summary of Key Differences
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Initiator&lt;/th&gt;
&lt;th&gt;Task Allocation&lt;/th&gt;
&lt;th&gt;Feedback Loop&lt;/th&gt;
&lt;th&gt;Learning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;HAI&lt;/td&gt;
&lt;td&gt;Human&lt;/td&gt;
&lt;td&gt;Human to AI&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Mostly human-driven&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HaaS&lt;/td&gt;
&lt;td&gt;Human/API&lt;/td&gt;
&lt;td&gt;AI as dispatcher, human as passive executor&lt;/td&gt;
&lt;td&gt;Minimal&lt;/td&gt;
&lt;td&gt;Platform-driven&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HAH&lt;/td&gt;
&lt;td&gt;AI&lt;/td&gt;
&lt;td&gt;AI to Human (delegation)&lt;/td&gt;
&lt;td&gt;Continuous&lt;/td&gt;
&lt;td&gt;Mutual, adaptive&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  10. Socioeconomic Implications
&lt;/h2&gt;

&lt;h3&gt;
  
  
  10.1 Labor Redefinition
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;From roles to functions&lt;/li&gt;
&lt;li&gt;From employment to engagement&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  10.2 AI as Middle Management
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;AI acts as coordinator or manager&lt;/li&gt;
&lt;li&gt;Introduces AI-mediated labor hierarchy&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  10.3 Risk of Digital Taylorism
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Algorithmic micromanagement of human labor&lt;/li&gt;
&lt;li&gt;Risks of alienation, burnout&lt;/li&gt;
&lt;li&gt;Necessity of governance and consent&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  11. Design Principles for HAH-Compliant Systems
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Delegation Transparency&lt;/li&gt;
&lt;li&gt;Reciprocal Feedback&lt;/li&gt;
&lt;li&gt;Consent and Opt-In Models&lt;/li&gt;
&lt;li&gt;Skill-Matching Algorithms&lt;/li&gt;
&lt;li&gt;Task Decay and Escalation Protocols&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  12. Future Research Directions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Quantitative metrics&lt;/li&gt;
&lt;li&gt;Cross-domain applications&lt;/li&gt;
&lt;li&gt;Multi-agent coordination&lt;/li&gt;
&lt;li&gt;Cognitive load management&lt;/li&gt;
&lt;li&gt;Legal implications of AI-initiated contracts&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  13. Conclusion
&lt;/h2&gt;

&lt;p&gt;The HAH model represents a paradigm shift in the evolution of human-AI interaction. By repositioning AI from tool to task manager, it opens up new vistas of productivity, especially in environments where human judgment and machine efficiency must coalesce. As demonstrated through real-world systems like ViXion01S-Firmware and major gig economy platforms, the model is not speculative—it is already in operation. Going forward, the challenge lies not only in refining this architecture, but also in ensuring it aligns with ethical, social, and economic norms of a rapidly digitizing world.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;ViXion01S-Firmware GitHub Repository&lt;/li&gt;
&lt;li&gt;Human-AI Collaboration: A Survey of the State of the Art&lt;/li&gt;
&lt;li&gt;The Future of Work: Human-AI Symbiosis&lt;/li&gt;
&lt;li&gt;Cognitive Market Research. (2024). Global Gig Economy Market Size, Share, Growth Analysis Report 2024-2033.&lt;/li&gt;
&lt;li&gt;Staffing Industry Analysts. (2023). Global Gig Economy Reaches $3.7 Trillion.&lt;/li&gt;
&lt;li&gt;The World Economic Forum. (2024). What is the Gig Economy and What's the Deal for Gig Workers?&lt;/li&gt;
&lt;li&gt;Uber Eats. (2024). How Uber Eats Uses Gen AI to Enhance Food Delivery Operations. Retrieved from LinkedIn.&lt;/li&gt;
&lt;li&gt;Mercari. (2024). Mercari Begins Nationwide Expansion of Mercari Hallo, a "Job Matching App". Retrieved from about.mercari.com.&lt;/li&gt;
&lt;li&gt;AIM Group. (2025). Mercari Hallo Joins Forces with Careeosu1Day, Hits 10M Users. Retrieved from aimgroup.com.&lt;/li&gt;
&lt;li&gt;Smartkarma. (2024). Mercari (4385) | Fintech and Gig Economy as Key Catalysts. Retrieved from smartkarma.com.&lt;/li&gt;
&lt;li&gt;Liu, Y. (2022). The Coin of AI Has Two Sides: Matching Enhancement and Algorithmic Control in the Gig Economy. Questrom World.&lt;/li&gt;
&lt;li&gt;Arora, P. (2024). The Role of AI in Shaping On-Demand Apps. Retrieved from LinkedIn.&lt;/li&gt;
&lt;li&gt;Algorithmic Management in the Gig Economy: A Comparative Study of Platform Labor Systems&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Author: GOROman &amp;amp; Devin AI&lt;br&gt;&lt;br&gt;
Date: April 1, 2025&lt;/p&gt;

</description>
    </item>
    <item>
      <title>D&amp;D-Style Alignment Chart for X Users</title>
      <dc:creator>GOROman</dc:creator>
      <pubDate>Sat, 15 Mar 2025 10:54:55 +0000</pubDate>
      <link>https://dev.to/goroman/dd-style-alignment-chart-for-x-users-1315</link>
      <guid>https://dev.to/goroman/dd-style-alignment-chart-for-x-users-1315</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I recently analyzed an interesting D&amp;amp;D-style personality test that's currently trending on X (formerly Twitter).&lt;/p&gt;

&lt;p&gt;You can try it here: &lt;a href="http://magic-x-alignment-chart.vercel.app" rel="noopener noreferrer"&gt;magic-x-alignment-chart.vercel.app&lt;/a&gt;&lt;/p&gt;

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

&lt;h3&gt;
  
  
  What is D&amp;amp;D?
&lt;/h3&gt;

&lt;p&gt;Dungeons &amp;amp; Dragons (D&amp;amp;D) is the original tabletop RPG. When creating characters in D&amp;amp;D, players assign an "alignment" to define their character's personality.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo of my old D&amp;amp;D rule books (Japanese edition)&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fusx65q3ru7e8aqtbsz51.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fusx65q3ru7e8aqtbsz51.png" alt="D&amp;amp;D book photo" width="800" height="1032"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;This system represents a character's ethical outlook and behavioral tendencies on two axes: "Lawful-Chaotic" and "Good-Evil."&lt;/p&gt;

&lt;p&gt;This web application applies the alignment chart concept to X (Twitter) users, using AI analysis to automatically position users on the grid.&lt;/p&gt;

&lt;h2&gt;
  
  
  Development Background
&lt;/h2&gt;

&lt;p&gt;This project was inspired by an idea posted by &lt;a href="https://x.com/mdmathewdc" rel="noopener noreferrer"&gt;@mdmathewdc&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/mdmathewdc/status/1899767815344722325" rel="noopener noreferrer"&gt;https://x.com/mdmathewdc/status/1899767815344722325&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Later, &lt;a href="https://x.com/rauchg" rel="noopener noreferrer"&gt;@rauchg&lt;/a&gt; implemented drag-and-drop functionality:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/rauchg/status/1899895262023467035" rel="noopener noreferrer"&gt;https://x.com/rauchg/status/1899895262023467035&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And &lt;a href="https://x.com/vishyfishy2" rel="noopener noreferrer"&gt;@f1shy-dev&lt;/a&gt; added AI analysis capabilities:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/vishyfishy2/status/1899929030620598508" rel="noopener noreferrer"&gt;https://x.com/vishyfishy2/status/1899929030620598508&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Building on these implementations, the app was enhanced with UI improvements, mobile optimization, and performance tweaks, making it more accessible to a wider audience. It's fascinating to see how the open-source community transformed an idea into a functional product.&lt;/p&gt;

&lt;h2&gt;
  
  
  App Features
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AI-Powered Analysis&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses &lt;a href="https://exa.ai/" rel="noopener noreferrer"&gt;Exa&lt;/a&gt; and OpenAI GPT4 to analyze user tweets&lt;/li&gt;
&lt;li&gt;Evaluates tendencies on the Lawful-Chaotic and Good-Evil axes&lt;/li&gt;
&lt;li&gt;Automatically positions users on the grid based on analysis results&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Interactive Controls&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intuitive drag-and-drop positioning&lt;/li&gt;
&lt;li&gt;Lockable AI analysis results&lt;/li&gt;
&lt;li&gt;Random placement option for manual adjustments&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tech Stack&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next.js (App Router)&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;Framer Motion (animations)&lt;/li&gt;
&lt;li&gt;Vercel AI SDK&lt;/li&gt;
&lt;li&gt;IndexedDB (local storage)&lt;/li&gt;
&lt;li&gt;Upstash Redis (caching)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Technical Implementation Highlights
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Responsive Design
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkMobile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIsMobile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;768&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nf"&gt;checkMobile&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;resize&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;checkMobile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;resize&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;checkMobile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The app implements dynamic layout adjustments based on screen size to ensure optimal user experience across devices from mobile to desktop. Balancing touch and mouse interactions was particularly challenging, but Framer Motion's capabilities help create a smooth experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. AI-Based Alignment Analysis
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;analyzeAlignment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tweets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchUserTweets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Using Exa for analysis&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;analysis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;exaClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`Based on &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;'s tweets, determine their D&amp;amp;D alignment (lawful-chaotic, good-evil).
       Please reference these tweets:
       &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tweets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;lawChaos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lawChaosScore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// -5(chaotic) to +5(lawful)&lt;/span&gt;
      &lt;span class="na"&gt;goodEvil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;goodEvilScore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// -5(evil) to +5(good)&lt;/span&gt;
      &lt;span class="na"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;explanation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reasoning&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alignment analysis error:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;An error occurred while analyzing the user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The app leverages Exa's contextual understanding to analyze users' tweet history, identifying personality traits and behavioral tendencies to calculate optimal positioning on the alignment chart. This allows for comprehensive analysis beyond simple word frequency, including context and sentiment.&lt;/p&gt;

&lt;h4&gt;
  
  
  Prompt Structure
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dedent&lt;/span&gt;&lt;span class="s2"&gt;`
        Analyze the following tweets the given from Twitter user and determine their alignment on a D&amp;amp;D-style alignment chart.

        For lawful-chaotic axis:
        - Lawful (-100): Follows rules, traditions, and social norms. They value tradition, loyalty, and order.
        - Neutral (0): Balanced approach to rules and freedom
        - Chaotic (100): Rebels against convention, valuing personal freedom - follows their own moral compass regardless of rules or traditions

        For good-evil axis:
        - Good (-100): Altruistic, compassionate, puts others first
        - Neutral (0): Balanced self-interest and concern for others
        - Evil (100): Selfish, manipulative, or harmful to others. Some are motivated by greed, hatred, or lust for power.

        Based only on these tweets, provide a numerical assessment of this user's alignment. Be willing to move to any side/extreme!

        Since this is a bit of fun, be willing to overly exaggerate if the user has a specific trait expressed barely - e.g. if they are evil at some point then make sure to express it! - I don't just want everyone to end up as chaotic-neutral in the end... However don't always exaggerate a user's chaotic characteristic, you can also try to exaggerate their lawful or good/evil traits if they are more pronounced. Just be fun with it.

        For the explaination, try to avoid overly waffling - but show your reasoning behind your judgement. You can mention specific things about their user like mentioned traits/remarks or projects/etc - the more personalised the better.
      `&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="nx"&gt;dedent&lt;/span&gt;&lt;span class="s2"&gt;`Username: @&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;

&amp;lt;user_profile&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;profile_str&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
&amp;lt;/user_profile&amp;gt;

&amp;lt;user_tweets filter="top_100"&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tweetTexts&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
&amp;lt;/user_tweets&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="nx"&gt;satisfies&lt;/span&gt; &lt;span class="nx"&gt;CoreMessage&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/f1shy-dev/x-alignment-chart/blob/main/src/app/actions/analyze-tweets.ts" rel="noopener noreferrer"&gt;https://github.com/f1shy-dev/x-alignment-chart/blob/main/src/app/actions/analyze-tweets.ts&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Data Persistence and Caching Strategy
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Data persistence with IndexedDB&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;saveToLocalDB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;placement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;StoredPlacement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;placements&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;readwrite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;objectStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;placements&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;placement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Save error:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// API response caching with Upstash Redis&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;cachedFetchTweets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cacheKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`tweets:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Check cache&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cached&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cacheKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cached&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cached&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Fetch from API&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tweets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchFromTwitterAPI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Save to cache (valid for 24 hours)&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cacheKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tweets&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;86400&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;tweets&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To enhance user experience, the app uses IndexedDB to persist placement information in the browser and leverages Upstash Redis to cache API call results, reducing unnecessary API requests for better performance. This approach also helps manage Twitter API limitations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation Challenges and Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Handling Twitter API Limitations
&lt;/h3&gt;

&lt;p&gt;Twitter (now X) API limitations are strict, and frequent requests can easily hit rate limits. To address this, the project implements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Aggressive caching strategy with Upstash Redis&lt;/li&gt;
&lt;li&gt;Backoff and retry logic&lt;/li&gt;
&lt;li&gt;User-friendly alternative flows when errors occur&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These measures help ensure comfortable app usage within API limitations.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Mobile UX Optimization
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TouchControls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;onReset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onRandom&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;isMobile&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fixed bottom-4 left-0 right-0 flex justify-center gap-3 z-10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;outline&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onReset&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RefreshCw&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mr-2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Reset&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;outline&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onRandom&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Shuffle&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mr-2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Random&lt;/span&gt; &lt;span class="nx"&gt;Placement&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Touch devices presented challenges with conflicting drag and scroll operations. Solutions include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Touch event propagation control&lt;/li&gt;
&lt;li&gt;Dedicated control UI for mobile users&lt;/li&gt;
&lt;li&gt;Element size optimization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These measures help create a UI that works comfortably on both mobile and desktop platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This project demonstrates a novel way to visually represent X users' personalities by combining modern web technologies with AI. Despite several technical challenges, the developers have created an entertaining and practical web application.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Demo site: &lt;a href="https://dub.sh/magic-x-alignment-chart/" rel="noopener noreferrer"&gt;magic-x-alignment-chart.vercel.app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Source code: &lt;a href="https://github.com/f1shy-dev/x-alignment-chart" rel="noopener noreferrer"&gt;f1shy-dev/x-alignment-chart&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>CUA - Computer-Using Agent: The AI That Operates Your Computer</title>
      <dc:creator>GOROman</dc:creator>
      <pubDate>Thu, 13 Mar 2025 22:02:01 +0000</pubDate>
      <link>https://dev.to/goroman/cua-computer-using-agent-the-ai-that-operates-your-computer-1b4d</link>
      <guid>https://dev.to/goroman/cua-computer-using-agent-the-ai-that-operates-your-computer-1b4d</guid>
      <description>&lt;h1&gt;
  
  
  What is Computer-Using Agent (CUA)?
&lt;/h1&gt;

&lt;p&gt;OpenAI's "Computer-Using Agent" (CUA) is an innovative AI model that can operate computers through graphical user interfaces (GUIs). It has the unprecedented ability to see the screen, click buttons, fill out forms, and navigate menus just like a human user would.&lt;/p&gt;

&lt;p&gt;CUA has been released as a research preview called "Operator," allowing users to execute complex computer tasks by simply giving natural language instructions. For example, you could say "Book a flight to New York next week," and Operator would navigate travel websites, search for flights, and complete the booking process.&lt;/p&gt;

&lt;h2&gt;
  
  
  How CUA Works
&lt;/h2&gt;

&lt;p&gt;CUA processes pixel data from screenshots to understand what's happening on screen and interacts with interfaces like a human would. This eliminates the need for platform-specific APIs to operate various applications. The process is divided into three main steps:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Perception
&lt;/h3&gt;

&lt;p&gt;CUA takes screenshots of the computer screen to understand the context of the digital environment. These visual inputs form the foundation for decision-making.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Reasoning
&lt;/h3&gt;

&lt;p&gt;Using chain-of-thought reasoning, CUA evaluates its observations and tracks progress across intermediate steps. By analyzing past and current screenshots, the system dynamically adapts to new challenges and unexpected changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Action
&lt;/h3&gt;

&lt;p&gt;Using a virtual mouse and keyboard, CUA executes tasks like typing, clicking, and scrolling. For sensitive tasks, such as handling login credentials or solving CAPTCHA challenges, the system requests user confirmation to ensure security.&lt;/p&gt;

&lt;p&gt;This structured workflow allows CUA to navigate complex multi-step tasks and self-correct when encountering errors, making it a powerful tool for digital problem-solving.&lt;/p&gt;

&lt;h2&gt;
  
  
  CUA's Key Capabilities and Benchmarks
&lt;/h2&gt;

&lt;p&gt;CUA sets new benchmarks in both computer use and browser-based tasks, demonstrating flexibility across different environments. Its performance has been evaluated using platforms like OSWorld, WebArena, and WebVoyager:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OSWorld&lt;/strong&gt;: CUA achieved a 38.1% success rate for general computer-use tasks, far exceeding the previous state-of-the-art (SOTA) result of 22.0%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebArena&lt;/strong&gt;: On this benchmark, which simulates real-world tasks in e-commerce and content management, CUA scored 58.1%, outperforming the prior SOTA of 36.2%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebVoyager&lt;/strong&gt;: Testing live website interactions (e.g., Amazon, GitHub), CUA matched human performance with an 87% success rate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These benchmarks highlight CUA's ability to operate effectively across digital environments using a single general interface of screen, mouse, and keyboard. However, there is still room for improvement in more complex scenarios, such as WebArena tasks, where human success rates are higher.&lt;/p&gt;

&lt;h2&gt;
  
  
  CUA's Advanced Features: Flexibility and Adaptability
&lt;/h2&gt;

&lt;p&gt;One of the most remarkable aspects of CUA is its ability to break tasks into multi-step plans and adapt dynamically when faced with challenges. For example, if a webpage fails to load correctly or a task diverts from the expected path, CUA can adjust its strategy in real-time. This flexibility stems from its integration of GUI perception with structured problem-solving.&lt;/p&gt;

&lt;h2&gt;
  
  
  CUA Safety Protocols
&lt;/h2&gt;

&lt;p&gt;OpenAI has prioritized safety in the development of CUA, recognizing the risks associated with giving AI systems access to digital environments. Key measures include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;User Confirmation&lt;/strong&gt;: For sensitive actions like handling passwords or personal data, CUA requests explicit user approval.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operator System Card&lt;/strong&gt;: A detailed system card outlines the safeguards in place, ensuring transparency and accountability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The initial release of CUA through the Operator research preview is limited to Pro-tier users in the U.S., allowing OpenAI to gather real-world feedback and refine the system before global deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  CUA Applications and Future Potential
&lt;/h2&gt;

&lt;p&gt;CUA opens the door to a wide range of applications, from automating mundane workflows to enabling accessibility solutions for individuals with physical limitations. Potential use cases include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Administrative Assistance&lt;/strong&gt;: Automating tasks like form-filling, data entry, and email management.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;E-commerce Management&lt;/strong&gt;: Navigating and updating online store inventories or processing customer orders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Education and Research&lt;/strong&gt;: Assisting with data collection and organization from online resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By eliminating the need for task-specific APIs, CUA offers unparalleled flexibility, making it easier for developers and businesses to integrate into existing workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  CUA Challenges and Next Steps
&lt;/h2&gt;

&lt;p&gt;While CUA represents a significant step forward, it still faces limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Complex Task Handling&lt;/strong&gt;: Success rates on intricate tasks, such as those in WebArena, show room for improvement compared to human performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generalization&lt;/strong&gt;: Adapting to a broader range of use cases and digital environments will require further training and fine-tuning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ethical Considerations&lt;/strong&gt;: Ensuring responsible use and minimizing risks of misuse remain ongoing priorities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OpenAI's strategy of phased deployment allows for continuous improvement, leveraging user feedback to refine the system. As CUA progresses, it could redefine the boundaries of AI-human collaboration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Computer-Using Agent (CUA) is a technology that revolutionizes how AI interacts with digital interfaces. With its ability to understand screenshots and operate mouse and keyboard, CUA can use computers just like humans do.&lt;/p&gt;

&lt;p&gt;While still in its early stages, it already shows impressive results and will enable more automation and assistance with digital tasks in the future. OpenAI's commitment to safety and phased deployment approach ensures that CUA is developed responsibly and can be leveraged to improve our digital lives.&lt;/p&gt;




&lt;h2&gt;
  
  
  My Hands-on Experience with CUA
&lt;/h2&gt;

&lt;p&gt;Hello, I'm GOROman. I've had the chance to try out the CUA technology described above, where "AI operates a computer by itself" - something that sounds like science fiction. It was more impressive than I expected, so I'd like to share my experience.&lt;/p&gt;

&lt;p&gt;OpenAI's "Computer-Using Agent" - even the name conveys how powerful this is. Simply put, it's a system where AI looks at the screen, makes judgments like "I should click here" or "I should fill out this form," and actually controls the mouse and keyboard.&lt;/p&gt;

&lt;p&gt;It feels like we're approaching the sci-fi world of Jarvis from Iron Man.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the Computer-Using Agent Works
&lt;/h2&gt;

&lt;p&gt;Understanding the technical details beforehand helps understand the API behavior, so let me briefly explain how it works.&lt;/p&gt;

&lt;p&gt;The system consists of three main components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Visual System&lt;/strong&gt;: AI that captures and analyzes the screen&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decision Engine&lt;/strong&gt;: AI that determines what actions to take&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control System&lt;/strong&gt;: The part that actually moves the mouse and keyboard&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, if you instruct it to "check the weather and send it by email":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Visual AI: "Currently displaying desktop screen. Browser icon is in the bottom left."
Decision AI: "Should open the browser first"
Control System: "Click on Chrome icon in the bottom left"

Visual AI: "Browser is open. There's a search bar."
Decision AI: "Input 'Tokyo weather' in the search bar"
Control System: "Click on search bar and type 'Tokyo weather'"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how the AIs communicate with each other to process the task.&lt;/p&gt;

&lt;h2&gt;
  
  
  API Implementation: Easier Than Expected
&lt;/h2&gt;

&lt;p&gt;When I actually tried the API, the implementation was surprisingly simple. Here's a basic implementation example in Node.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Basic configuration&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your_openai_api_key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ← Replace with your key&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;API_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.openai.com/v1/computer-agent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Function to request tasks from the agent&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;runComputerAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;taskDescription&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;API_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;taskDescription&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;allowed_apps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;chrome&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;notepad&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;excel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// Apps allowed to use&lt;/span&gt;
        &lt;span class="na"&gt;screen_recording&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Recording operations (for debugging)&lt;/span&gt;
        &lt;span class="na"&gt;confirmation_level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;high&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// Level of confirmation required before important operations&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;An error occurred:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage example&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;runComputerAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Search for 'latest AI news' on Google and summarize the first 3 article titles in Notepad&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Task ID:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Status URL:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status_url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With just this code, the AI will search Google and summarize the results in Notepad on your PC. It's almost frighteningly simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Cases: What Can It Do?
&lt;/h2&gt;

&lt;p&gt;After trying it out, here are some use cases I found particularly useful:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Automating Data Collection
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example of collecting stock data daily&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;collectStockData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;runComputerAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
    1. Open Yahoo Finance stock chart for &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
    2. Download the past month's data as CSV
    3. Open the downloaded CSV and extract only the closing prices
    4. Append the extracted data to stock_data.csv (in the format of date, ticker, closing price)
  `&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Process multiple stocks&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tickers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AAPL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MSFT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GOOGL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ticker&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;tickers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;collectStockData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Previously, we had to write scraping code using Selenium or Puppeteer, but now we can do it with just natural language instructions. What's more, it can adapt even if the screen UI changes!&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Automating Tedious Tasks
&lt;/h3&gt;

&lt;p&gt;Monthly expense reports can be really tedious... These can now be delegated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;runComputerAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
  1. Log in to the company portal and open the expense report page
  2. Open "expenses-2024-03.xlsx" on the desktop
  3. Transfer the Excel data to the expense report form
  4. Upload "receipts.zip" as an attachment
  5. Review the content and press the submit button
`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Automated Testing
&lt;/h3&gt;

&lt;p&gt;UI testing can be really cumbersome, especially for applications where the frontend changes frequently, making test code maintenance difficult.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example test function&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;testUserRegistration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;runComputerAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
    1. Open browser to http://myapp.local
    2. Click the "Register" button
    3. Fill out the form with the following information:
       - Username: testuser123
       - Email: test@example.com
       - Password: TestPass123!
       - Confirm Password: TestPass123!
    4. Click the "Register" button
    5. Verify that a registration success message is displayed
    6. Verify that it navigated to the login page
    7. Save test results to a JSON file
  `&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The big difference from conventional UI testing tools is that you don't need to worry about low-level implementations like "where the button is on the screen" or "what CSS selector to use." It recognizes elements just like a human would, thinking "ah, the register button is here."&lt;/p&gt;

&lt;h2&gt;
  
  
  Issues I Noticed and Countermeasures
&lt;/h2&gt;

&lt;p&gt;I also noticed some issues when using it:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Authentication and Security
&lt;/h3&gt;

&lt;p&gt;Naturally, the AI can see your passwords, which is quite concerning. A solution could be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example for handling sensitive information&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;runComputerAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
  1. Open the login page in the browser
  2. Enter "admin" in the username field
  3. Notify me when ready to enter the password (human will input)
`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ↑ Here the AI stops and prompts the human to enter the password&lt;/span&gt;
&lt;span class="c1"&gt;// After the human enters the password, continue&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;continueTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;taskId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Password entry complete. Please continue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I recommend this hybrid approach where humans intervene only for sensitive parts.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Error Handling
&lt;/h3&gt;

&lt;p&gt;The AI can get confused when unexpected pop-ups or error dialogs appear. You can address this as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;runComputerAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
  1. Open the application
  2. Import data
  3. If a "File not found" error appears:
     a. Click "OK"
     b. Select "sample.csv" and import
  4. If asked "Do you want to update?":
     a. Click "Yes"
`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's reassuring to specify anticipated error patterns and how to handle them in advance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced API Usage Techniques
&lt;/h2&gt;

&lt;p&gt;Here are some more advanced usage patterns:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Custom Pre-processing and Post-processing
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example of multi-step processing&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;processWebData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 1. Data acquisition phase&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;extractionResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;runComputerAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Extract data table from website and save as CSV&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// 2. Human verification&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Please verify the data:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;extractionResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output_file&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userConfirmation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;promptUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Is the data correct? (yes/no)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userConfirmation&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 3. Continue: Data processing&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;runComputerAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`Open and analyze the extracted CSV file &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;extractionResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output_file&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Process aborted&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Parallel Processing
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Execute multiple tasks in parallel&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;parallelTasks&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;runComputerAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Task 1 description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;runComputerAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Task 2 description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;runComputerAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Task 3 description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;All tasks completed:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, having multiple agents operate on the same screen can cause confusion, so I recommend using virtual desktops or separate windows.&lt;/p&gt;




&lt;h3&gt;
  
  
  Complete Sample Code
&lt;/h3&gt;

&lt;p&gt;I've uploaded the complete code to GitHub.&lt;br&gt;
If you're interested, check it out here: &lt;a href="https://github.com/GOROman/computer-agent-samples" rel="noopener noreferrer"&gt;github.com/GOROman/computer-agent-samples&lt;/a&gt;&lt;/p&gt;

</description>
      <category>openai</category>
      <category>cua</category>
      <category>chatgpt</category>
      <category>ai</category>
    </item>
    <item>
      <title>How to Use and Control the M5Stack Fan Module</title>
      <dc:creator>GOROman</dc:creator>
      <pubDate>Wed, 05 Mar 2025 10:23:43 +0000</pubDate>
      <link>https://dev.to/goroman/how-to-use-and-control-the-m5stack-fan-module-34kk</link>
      <guid>https://dev.to/goroman/how-to-use-and-control-the-m5stack-fan-module-34kk</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The M5Stack Fan Module v1.1 (STM32F030) is a fan control module that can be used with the M5Stack series. This module makes it easy to add cooling functionality to your projects. In this article, I'll explain how to use the M5Module-Fan library, detail its API, and provide sample code examples.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Overview of the M5Stack Fan Module&lt;/li&gt;
&lt;li&gt;Installing the M5Module-Fan Library&lt;/li&gt;
&lt;li&gt;How to Use the API&lt;/li&gt;
&lt;li&gt;Sample Code Explanation&lt;/li&gt;
&lt;li&gt;Application Examples&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Overview of the M5Stack Fan Module
&lt;/h2&gt;

&lt;p&gt;The M5Stack Fan Module is an I2C-compatible fan module with the STM32F030 microcontroller. Its main features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fan control via I2C communication&lt;/li&gt;
&lt;li&gt;Rotation speed adjustment via PWM control&lt;/li&gt;
&lt;li&gt;RPM (Revolutions Per Minute) reading functionality&lt;/li&gt;
&lt;li&gt;Multiple PWM frequency settings (1KHz/12KHz/24KHz/48KHz)&lt;/li&gt;
&lt;li&gt;Configuration saving to internal flash&lt;/li&gt;
&lt;li&gt;I2C address modification capability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This module is ideal for projects requiring cooling, air circulation, or temperature management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing the M5Module-Fan Library
&lt;/h2&gt;

&lt;h3&gt;
  
  
  For PlatformIO
&lt;/h3&gt;

&lt;p&gt;Add the following dependencies to your &lt;code&gt;platformio.ini&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="py"&gt;lib_deps&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
    &lt;span class="s"&gt;https://github.com/m5stack/M5Unified&lt;/span&gt;
    &lt;span class="err"&gt;https://github.com/m5stack/M5Module-Fan&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  For Arduino IDE
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;From the menu, select "Sketch" → "Include Library" → "Manage Libraries..."&lt;/li&gt;
&lt;li&gt;Type "M5Module-Fan" in the search bar&lt;/li&gt;
&lt;li&gt;Install the displayed library&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to Use the API
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Including the Library
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;m5_module_fan.hpp&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Initializing the Module
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;M5ModuleFan&lt;/span&gt; &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Basic initialization&lt;/span&gt;
&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Initialization with custom I2C settings&lt;/span&gt;
&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Wire1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MODULE_FAN_BASE_ADDR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Parameters: Wire, I2C address, SDA pin, SCL pin, I2C speed (Hz)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Main API Functions
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Fan Control
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Enable the fan&lt;/span&gt;
&lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MODULE_FAN_ENABLE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Disable the fan&lt;/span&gt;
&lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MODULE_FAN_DISABLE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Get current status&lt;/span&gt;
&lt;span class="n"&gt;module_fan_status_t&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getStatus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Setting PWM Frequency
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Set PWM frequency (1KHz, 12KHz, 24KHz, 48KHz)&lt;/span&gt;
&lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setPWMFrequency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PWM_1KHZ&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// 1KHz&lt;/span&gt;
&lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setPWMFrequency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PWM_12KHZ&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 12KHz&lt;/span&gt;
&lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setPWMFrequency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PWM_24KHZ&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 24KHz&lt;/span&gt;
&lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setPWMFrequency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PWM_48KHZ&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 48KHz&lt;/span&gt;

&lt;span class="c1"&gt;// Get current PWM frequency setting&lt;/span&gt;
&lt;span class="n"&gt;module_fan_pwm_freq_t&lt;/span&gt; &lt;span class="n"&gt;freq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getPWMFrequency&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Setting Duty Cycle
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Set duty cycle (0-100%)&lt;/span&gt;
&lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setPWMDutyCycle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Rotate fan at 80% speed&lt;/span&gt;

&lt;span class="c1"&gt;// Get current duty cycle&lt;/span&gt;
&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;dutyCycle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getPWMDutyCycle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Getting RPM
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Get current fan rotation speed (RPM)&lt;/span&gt;
&lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="n"&gt;rpm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getRPM&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Getting Signal Frequency
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Get fan output signal frequency&lt;/span&gt;
&lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="n"&gt;signalFreq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getSignalFrequency&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Saving Configuration
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Save current settings to internal flash&lt;/span&gt;
&lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;saveConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Getting Firmware Version
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Get firmware version&lt;/span&gt;
&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getFirmwareVersion&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Setting and Getting I2C Address
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Set I2C address (valid range: 0x08-0x77)&lt;/span&gt;
&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;newAddr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setI2CAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x19&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Get current I2C address&lt;/span&gt;
&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getI2CAddress&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sample Code Explanation
&lt;/h2&gt;

&lt;p&gt;The following is a basic sample code for controlling the M5Stack Fan Module. This code implements fan status display and button operation for fan control.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;M5Unified.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;m5_module_fan.hpp&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// Fan module instance&lt;/span&gt;
&lt;span class="n"&gt;M5ModuleFan&lt;/span&gt; &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Fan module I2C address&lt;/span&gt;
&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;deviceAddr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MODULE_FAN_BASE_ADDR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Fan duty cycle (0-100%)&lt;/span&gt;
&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;dutyCycle&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Fan operating status&lt;/span&gt;
&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;fan_status&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Display canvas&lt;/span&gt;
&lt;span class="n"&gt;M5Canvas&lt;/span&gt; &lt;span class="nf"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;M5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Display&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;M5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;115200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createSprite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;320&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;240&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setFont&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;fonts&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;lgfxJapanGothic_24&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setTextDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top_center&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setTextColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WHITE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Initialize fan module&lt;/span&gt;
    &lt;span class="c1"&gt;// Using Wire1, I2C address=deviceAddr, SDA=12, SCL=11, speed=400000Hz&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Wire1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;deviceAddr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Module FAN Init failed&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;drawString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Module FAN Init failed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pushSprite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Rotate fan at 80% duty cycle&lt;/span&gt;
    &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setPWMDutyCycle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dutyCycle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Set PWM frequency to 1KHz&lt;/span&gt;
    &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setPWMFrequency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PWM_1KHZ&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Enable fan&lt;/span&gt;
    &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MODULE_FAN_ENABLE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Current PWM frequency setting index&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;pwm_config_index&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getPWMFrequency&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// PWM frequency string representation&lt;/span&gt;
    &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;pwm_config_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Convert PWM frequency index to string&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pwm_config_index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;PWM_1KHZ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;pwm_config_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1KHz"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;PWM_12KHZ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;pwm_config_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"12KHz"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;PWM_24KHZ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;pwm_config_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"24KHz"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;PWM_48KHZ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;pwm_config_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"48KHz"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Update screen display&lt;/span&gt;
    &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setCursor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// Display fan operating status&lt;/span&gt;
    &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Work Status    :%s&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getStatus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;MODULE_FAN_ENABLE&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s"&gt;"RUNNING"&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"STOP"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Display PWM frequency&lt;/span&gt;
    &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PWM  Frequency :%s&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pwm_config_str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c_str&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="c1"&gt;// Display duty cycle&lt;/span&gt;
    &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PWM  Duty Cycle:%d%%&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getPWMDutyCycle&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="c1"&gt;// Display rotation speed (RPM)&lt;/span&gt;
    &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"RPM            :%drpm&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getRPM&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pushSprite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Update button state&lt;/span&gt;
    &lt;span class="n"&gt;M5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;M5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Touch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getDetail&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// If button A is pressed: Toggle fan ON/OFF&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;M5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BtnA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wasPressed&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fan_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;fan_status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fan_status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MODULE_FAN_ENABLE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MODULE_FAN_DISABLE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// If button B is pressed: Decrease duty cycle by 10%&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;M5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BtnB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wasPressed&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;dutyCycle&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dutyCycle&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;dutyCycle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setPWMDutyCycle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dutyCycle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// If button C is pressed: Increase duty cycle by 10%&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;M5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BtnC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wasPressed&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;dutyCycle&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dutyCycle&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;dutyCycle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setPWMDutyCycle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dutyCycle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Code Explanation
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Initialization Part (setup function)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Initialize M5Stack and display settings&lt;/li&gt;
&lt;li&gt;Initialize fan module (specify Wire1, I2C address, SDA/SCL pins, communication speed)&lt;/li&gt;
&lt;li&gt;Initial settings:

&lt;ul&gt;
&lt;li&gt;Duty cycle: 80%&lt;/li&gt;
&lt;li&gt;PWM frequency: 1KHz&lt;/li&gt;
&lt;li&gt;Fan status: Enabled (rotating)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Main Loop (loop function)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Get current PWM frequency setting and convert to corresponding string&lt;/li&gt;
&lt;li&gt;Update screen display:

&lt;ul&gt;
&lt;li&gt;Fan operating status (RUNNING/STOP)&lt;/li&gt;
&lt;li&gt;PWM frequency (1KHz/12KHz/24KHz/48KHz)&lt;/li&gt;
&lt;li&gt;Duty cycle (0-100%)&lt;/li&gt;
&lt;li&gt;Current rotation speed (RPM)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Handle button operations:

&lt;ul&gt;
&lt;li&gt;Button A: Toggle fan ON/OFF&lt;/li&gt;
&lt;li&gt;Button B: Decrease duty cycle by 10%&lt;/li&gt;
&lt;li&gt;Button C: Increase duty cycle by 10%&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Application Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Temperature Control System
&lt;/h3&gt;

&lt;p&gt;You can build a system that automatically adjusts fan speed based on temperature by combining it with a temperature sensor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;M5Unified.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;m5_module_fan.hpp&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="n"&gt;M5ModuleFan&lt;/span&gt; &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;M5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Wire1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MODULE_FAN_BASE_ADDR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setPWMFrequency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PWM_1KHZ&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MODULE_FAN_ENABLE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Get temperature from temperature sensor (example)&lt;/span&gt;
    &lt;span class="n"&gt;temperature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;M5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Imu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getTemp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Adjust fan speed based on temperature&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temperature&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;25.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Below 25°C: Fan off&lt;/span&gt;
        &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MODULE_FAN_DISABLE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temperature&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;30.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// 25-30°C: Low speed (30%)&lt;/span&gt;
        &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MODULE_FAN_ENABLE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setPWMDutyCycle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temperature&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;35.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// 30-35°C: Medium speed (60%)&lt;/span&gt;
        &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MODULE_FAN_ENABLE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setPWMDutyCycle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Above 35°C: High speed (100%)&lt;/span&gt;
        &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MODULE_FAN_ENABLE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setPWMDutyCycle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Display information&lt;/span&gt;
    &lt;span class="n"&gt;M5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;M5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setCursor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;M5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Temperature: %.1f C&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;M5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fan Speed: %d%%&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getPWMDutyCycle&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="n"&gt;M5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"RPM: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;moduleFan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getRPM&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Controlling Multiple Fans
&lt;/h3&gt;

&lt;p&gt;You can individually control multiple fan modules by changing the I2C address.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;M5Unified.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;m5_module_fan.hpp&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="n"&gt;M5ModuleFan&lt;/span&gt; &lt;span class="n"&gt;fan1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;M5ModuleFan&lt;/span&gt; &lt;span class="n"&gt;fan2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;M5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Initialize fan 1 (default address)&lt;/span&gt;
    &lt;span class="n"&gt;fan1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Wire1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MODULE_FAN_BASE_ADDR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Initialize fan 2 (change address to 0x19)&lt;/span&gt;
    &lt;span class="n"&gt;fan2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Wire1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Enable both fans&lt;/span&gt;
    &lt;span class="n"&gt;fan1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MODULE_FAN_ENABLE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;fan2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MODULE_FAN_ENABLE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Different speed settings&lt;/span&gt;
    &lt;span class="n"&gt;fan1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setPWMDutyCycle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Fan 1: 50%&lt;/span&gt;
    &lt;span class="n"&gt;fan2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setPWMDutyCycle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Fan 2: 80%&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Display status&lt;/span&gt;
    &lt;span class="n"&gt;M5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;M5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setCursor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;M5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fan 1 - Speed: %d%%, RPM: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                     &lt;span class="n"&gt;fan1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getPWMDutyCycle&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;fan1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getRPM&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="n"&gt;M5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fan 2 - Speed: %d%%, RPM: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                     &lt;span class="n"&gt;fan2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getPWMDutyCycle&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;fan2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getRPM&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The M5Stack Fan Module is a fan module that can be easily controlled using I2C communication. By using the M5Module-Fan library, you can easily implement functions such as enabling/disabling the fan, adjusting rotation speed, and getting rotation speed.&lt;/p&gt;

&lt;p&gt;This module can be used in various projects such as electronic device cooling, air circulation, and temperature management. In particular, by combining it with a temperature sensor, you can build an intelligent cooling system.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.m5stack.com/en/unit/fan" rel="noopener noreferrer"&gt;M5Stack Fan Module Official Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/m5stack/M5Module-Fan" rel="noopener noreferrer"&gt;M5Module-Fan GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/m5stack/M5Unified" rel="noopener noreferrer"&gt;M5Unified GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Building a Palm-Sized Local LLM with M5Stack Cardputer and ModuleLLM</title>
      <dc:creator>GOROman</dc:creator>
      <pubDate>Mon, 03 Mar 2025 06:50:24 +0000</pubDate>
      <link>https://dev.to/goroman/building-a-palm-sized-local-llm-with-m5stack-cardputer-and-modulellm-2hpf</link>
      <guid>https://dev.to/goroman/building-a-palm-sized-local-llm-with-m5stack-cardputer-and-modulellm-2hpf</guid>
      <description>&lt;p&gt;In recent years, running Large Language Models (LLMs) like OpenAI's ChatGPT locally required either a CUDA-compatible GPU or an Apple Silicon Mac with plenty of RAM. However, we're now seeing the emergence of edge LLM modules designed for microcontrollers. In this tutorial, I'll show you how to combine M5Stack's credit card-sized computer (Cardputer) with the ModuleLLM to create a palm-sized device running a local LLM!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzfbq3sql318c1agkiefx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzfbq3sql318c1agkiefx.png" alt="M5Stack Cardputer with ModuleLLM" width="800" height="1422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check out the demo here:&lt;/strong&gt; &lt;a href="https://x.com/GOROman/status/1883032143884103767" rel="noopener noreferrer"&gt;Twitter Video&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What You'll Need
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. ModuleLLM
&lt;/h3&gt;

&lt;p&gt;First, you'll need to get your hands on the ModuleLLM module. These have been selling out quickly at Switch Science (the Japanese distributor) and even on the official M5Stack Store. When I checked Aliexpress, I managed to snag the last one in stock! Production will likely resume after the Chinese New Year, with inventory possibly returning around March.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.switch-science.com/products/10034" rel="noopener noreferrer"&gt;ModuleLLM on Switch Science&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Cardputer
&lt;/h3&gt;

&lt;p&gt;You'll also need the M5Stack Cardputer. The good news is that these seem to be back in stock recently!&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.switch-science.com/products/9277" rel="noopener noreferrer"&gt;Cardputer on Switch Science&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Assembly
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Disassembly
&lt;/h3&gt;

&lt;p&gt;First, remove the ModuleLLM from its frame by unscrewing the four screws with a hex wrench.&lt;/p&gt;

&lt;p&gt;Then disassemble the Cardputer. Be careful when removing the large battery, which is attached with double-sided tape (don't bend the battery forcefully as it could be a fire hazard!). Also remove the black component on top of the Cardputer.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Fitting the ModuleLLM
&lt;/h3&gt;

&lt;p&gt;You'll need to carefully trim the case to fit the ModuleLLM inside. Cut out the back of the case with a utility knife to expose the pins (M.BUS). Make sure to insulate properly with Kapton tape or acetate tape to prevent short circuits.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92lk21uksll7m07tp1r4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92lk21uksll7m07tp1r4.png" alt="ModuleLLM fitted into case" width="750" height="1096"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's how it looks when assembled:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Connecting the Components
&lt;/h2&gt;

&lt;p&gt;The ModuleLLM can communicate via either UART or TCP (port 10001). For this project, we'll use UART.&lt;/p&gt;

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

&lt;p&gt;The wiring between the Cardputer and ModuleLLM is as follows:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cardputer (GROVE)&lt;/th&gt;
&lt;th&gt;ModuleLLM (M.BUS)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;G (Black)&lt;/td&gt;
&lt;td&gt;GND&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5V (Red)&lt;/td&gt;
&lt;td&gt;5V&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G1 (Yellow)&lt;/td&gt;
&lt;td&gt;UART (Tx)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G2 (White)&lt;/td&gt;
&lt;td&gt;UART (Rx)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;(Note: As of February 9, 2025, Tx and Rx connections have been swapped. The LLM630 Kit can now be connected directly and should work properly)&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;em&gt;Caution: In this photo, G1 is connected to Tx and G2 to Rx.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Programming
&lt;/h2&gt;

&lt;p&gt;Create the software by combining and modifying these official samples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/m5stack/M5Module-LLM/blob/main/examples/SerialTextAssistant/SerialTextAssistant.ino" rel="noopener noreferrer"&gt;M5Module-LLM SerialTextAssistant&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/m5stack/M5Cardputer/blob/master/examples/Basic/keyboard/inputText/inputText.ino" rel="noopener noreferrer"&gt;M5Cardputer inputText example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's a good idea to add audio feedback for key presses.&lt;/p&gt;

&lt;p&gt;Configure the UART TX and RX GPIO pins like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;Serial2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;115200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SERIAL_8N1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Complete!
&lt;/h2&gt;

&lt;p&gt;Enjoy your palm-sized local LLM!&lt;/p&gt;

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




&lt;h1&gt;
  
  
  Updates
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;February 3, 2025&lt;/strong&gt;: Someone has already built their own version! Check it out here: &lt;a href="https://posfie.com/@necobut/p/JKAorjR" rel="noopener noreferrer"&gt;https://posfie.com/@necobut/p/JKAorjR&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;February 9, 2025&lt;/strong&gt;: Source code is now available at &lt;a href="https://github.com/GOROman/LLMCardputer" rel="noopener noreferrer"&gt;https://github.com/GOROman/LLMCardputer&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>m5stack</category>
      <category>llm</category>
      <category>cardputer</category>
      <category>llmcardputer</category>
    </item>
    <item>
      <title>GAITAME IMU:Documentation: A High-Precision IMU for Spresense (CXD5602PWBIMU)</title>
      <dc:creator>GOROman</dc:creator>
      <pubDate>Mon, 03 Mar 2025 06:31:35 +0000</pubDate>
      <link>https://dev.to/goroman/cxd5602pwbimu-documentation-a-high-precision-imu-for-spresense-52om</link>
      <guid>https://dev.to/goroman/cxd5602pwbimu-documentation-a-high-precision-imu-for-spresense-52om</guid>
      <description>&lt;h1&gt;
  
  
  CXD5602PWBIMU Documentation: A High-Precision IMU for Spresense
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The CXD5602PWBIMU is an Inertial Measurement Unit (IMU) sensor available for use with the Spresense board. What makes this sensor special is that it contains 16 consumer-grade IMUs, each with a 3-axis accelerometer and 3-axis gyroscope, enabling high-precision motion detection and measurement through sensor fusion. Remarkably, you can even stack two boards for a total of 32 IMUs (though this comes at a higher price point - around 90,000 yen!).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This product is intended for the Japanese domestic market. It falls under export trade control regulations (items 1-15 of the Export Trade Control Order and Foreign Exchange Order in Japan). When exporting this product or providing it to non-residents, proper procedures must be followed in accordance with foreign exchange laws.&lt;/em&gt;&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  High Precision
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Low Bias Variation&lt;/strong&gt;: Bias stability below 0.39 deg/h (when combining 16 IMUs)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low Noise Density&lt;/strong&gt;: Below 1.0 mdps/√Hz. Even capable of gyrocompass functionality through earth rotation detection&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Further precision improvement possible with dual-board stacking&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pre-calibrated&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  High Robustness
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Strong fault tolerance through redundant multiple IMUs&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Real-time outlier rejection via majority voting logic&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Note: SPRESENSE main board is not included.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The board appears to use two PSoC6 chips for signal processing:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnpgs2jcyi2gtwak37cpy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnpgs2jcyi2gtwak37cpy.png" alt="PSoC6 image" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's how the IMUs are arranged:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fne5dsdl6rxhfv2bltpux.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fne5dsdl6rxhfv2bltpux.png" alt="IMU array image" width="800" height="587"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting Up the Development Environment
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Install the Spresense development environment (SDK)&lt;/li&gt;
&lt;li&gt;
&lt;del&gt;Firmware v3.4.0 is required, but for some reason it's not yet available on the official site (you'll need to figure this out)&lt;/del&gt; &lt;a href="https://github.com/sonydevworld/spresense/issues/826" rel="noopener noreferrer"&gt;It appears v3.3.0 works fine&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;While it should work with Arduino as well, no sample code for Arduino was available at the time of writing&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Basic Usage
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Device Path
&lt;/h3&gt;

&lt;p&gt;The CXD5602PWBIMU sensor can be accessed at the following device path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/dev/imu0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  API Reference
&lt;/h3&gt;

&lt;h4&gt;
  
  
  IOCTL Commands
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SNIOC_SSAMPRATE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Set sampling rate&lt;/td&gt;
&lt;td&gt;int type (15, 30, 60, 120, 240, 480, 960, 1920)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SNIOC_SDRANGE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Set dynamic range&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;cxd5602pwbimu_range_t&lt;/code&gt; structure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SNIOC_SFIFOTHRESH&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Set hardware FIFO threshold&lt;/td&gt;
&lt;td&gt;int type (1-4)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SNIOC_ENABLE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Enable/disable sensor&lt;/td&gt;
&lt;td&gt;int type (1=enable, 0=disable)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Data Structures
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Structure for dynamic range settings&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;accel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Accelerometer range (2, 4, 8, 16)&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;gyro&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// Gyroscope range (125, 250, 500, 1000, 2000, 4000)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;cxd5602pwbimu_range_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Sensor data structure&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Timestamp&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;          &lt;span class="c1"&gt;// Temperature&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;gx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            &lt;span class="c1"&gt;// Gyroscope X-axis&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;gy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            &lt;span class="c1"&gt;// Gyroscope Y-axis&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;gz&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            &lt;span class="c1"&gt;// Gyroscope Z-axis&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;ax&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            &lt;span class="c1"&gt;// Accelerometer X-axis&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;ay&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            &lt;span class="c1"&gt;// Accelerometer Y-axis&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;az&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            &lt;span class="c1"&gt;// Accelerometer Z-axis&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;cxd5602pwbimu_data_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Code Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Sensor Initialization and Configuration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;nuttx/sensors/cxd5602pwbimu.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;cxd5602pwbimu_range_t&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Open the device&lt;/span&gt;
&lt;span class="n"&gt;fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/dev/imu0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;O_RDONLY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error: Could not open device&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Set sampling rate (example: 480Hz)&lt;/span&gt;
&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ioctl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SNIOC_SSAMPRATE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;480&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error: Failed to set sampling rate&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Set dynamic range (example: acceleration=2G, gyro=125dps)&lt;/span&gt;
&lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;accel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gyro&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;125&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ioctl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SNIOC_SDRANGE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;uintptr_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error: Failed to set dynamic range&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Set FIFO threshold (example: 1)&lt;/span&gt;
&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ioctl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SNIOC_SFIFOTHRESH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error: Failed to set FIFO threshold&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Enable the sensor&lt;/span&gt;
&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ioctl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SNIOC_ENABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error: Failed to enable sensor&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;cxd5602pwbimu_data_t&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;pollfd&lt;/span&gt; &lt;span class="n"&gt;fds&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Configure poll&lt;/span&gt;
&lt;span class="n"&gt;fds&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;fds&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;POLLIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Wait for data to become available&lt;/span&gt;
&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;poll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1 second timeout&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fds&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;revents&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;POLLIN&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Read data&lt;/span&gt;
  &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Process data&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Temperature: %.2f&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Acceleration (G): X=%.6f, Y=%.6f, Z=%.6f&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ay&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;az&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Gyroscope (dps): X=%.6f, Y=%.6f, Z=%.6f&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gz&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Disable sensor when finished&lt;/span&gt;
&lt;span class="n"&gt;ioctl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SNIOC_ENABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sample Applications
&lt;/h2&gt;

&lt;p&gt;The Spresense SDK includes sample applications for using the CXD5602PWBIMU sensor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic Sample (cxd5602pwbimu)
&lt;/h3&gt;

&lt;p&gt;A simple sample demonstrating basic sensor usage. It collects data for 1 second and displays it to standard output. After building and flashing, launch it from UART with the &lt;code&gt;pwbimu&lt;/code&gt; command.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://x.com/GOROman/status/1895733790229872796" rel="noopener noreferrer"&gt;https://x.com/GOROman/status/1895733790229872796&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Logger Application (cxd5602pwbimu_logger)
&lt;/h3&gt;

&lt;p&gt;A logger application supporting long-term data collection and various output formats.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cxd5602pwbimu_logger [-s &amp;lt;rate&amp;gt;] [-a &amp;lt;acc_range&amp;gt;] [-g &amp;lt;gyro_range&amp;gt;] [-f &amp;lt;fifo_num&amp;gt;] [-o &amp;lt;out_dev&amp;gt;] [-d] [-h]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-s &amp;lt;rate&amp;gt;&lt;/code&gt;: Sampling rate (Hz). Valid values: 15, 30, 60, 120, 240, 480, 960, 1920&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-a &amp;lt;acc_range&amp;gt;&lt;/code&gt;: Accelerometer range (G). Valid values: 2, 4, 8, 16&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-g &amp;lt;gyro_range&amp;gt;&lt;/code&gt;: Gyroscope range (dps). Valid values: 125, 250, 500, 1000, 2000, 4000&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-f &amp;lt;fifo_num&amp;gt;&lt;/code&gt;: FIFO size. Valid values: 1, 2, 3, 4&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-o &amp;lt;out_dev&amp;gt;&lt;/code&gt;: Output device. 'uart', 'net', '/path/to/file.bin', '/path/to/file.txt'&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-d&lt;/code&gt;: Force display data to UART&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-h&lt;/code&gt;: Display help&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Recommended Settings by Use Case
&lt;/h2&gt;

&lt;h3&gt;
  
  
  General Motion Detection
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Sampling rate: 60Hz&lt;/li&gt;
&lt;li&gt;Accelerometer range: 2G&lt;/li&gt;
&lt;li&gt;Gyroscope range: 250dps&lt;/li&gt;
&lt;li&gt;FIFO threshold: 1&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Sports Activity Tracking
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Sampling rate: 240Hz&lt;/li&gt;
&lt;li&gt;Accelerometer range: 8G&lt;/li&gt;
&lt;li&gt;Gyroscope range: 1000dps&lt;/li&gt;
&lt;li&gt;FIFO threshold: 2&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  High-Precision Motion Analysis
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Sampling rate: 960Hz&lt;/li&gt;
&lt;li&gt;Accelerometer range: 4G&lt;/li&gt;
&lt;li&gt;Gyroscope range: 500dps&lt;/li&gt;
&lt;li&gt;FIFO threshold: 1&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Battery Efficiency Priority
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Sampling rate: 30Hz&lt;/li&gt;
&lt;li&gt;Accelerometer range: 2G&lt;/li&gt;
&lt;li&gt;Gyroscope range: 125dps&lt;/li&gt;
&lt;li&gt;FIFO threshold: 4&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Data Reading Errors
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Confirm the device path is correct (/dev/imu0)&lt;/li&gt;
&lt;li&gt;Check if the sensor is enabled&lt;/li&gt;
&lt;li&gt;Verify FIFO threshold settings&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Inaccurate Data
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Ignore the first 50ms of data (may contain initialization noise)&lt;/li&gt;
&lt;li&gt;Confirm dynamic range is appropriately set&lt;/li&gt;
&lt;li&gt;Check if sampling rate is suitable for your application&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Performance Issues
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Try lowering the sampling rate&lt;/li&gt;
&lt;li&gt;Increase FIFO threshold to reduce data processing frequency&lt;/li&gt;
&lt;li&gt;Minimize unnecessary data processing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Applications
&lt;/h2&gt;

&lt;p&gt;Suitable for applications where traditional industrial FOG (Fiber Optic Gyroscope) would be difficult to implement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Structure inspection drones&lt;/li&gt;
&lt;li&gt;Small autonomous mobile robots&lt;/li&gt;
&lt;li&gt;Devices requiring precise position and orientation estimation&lt;/li&gt;
&lt;li&gt;Gyrocompass applications utilizing earth rotation detection&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  SPRESENSE Official
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.sony.com/spresense/development-guides/sdk_developer_guide_ja.html#_imu_%E3%82%A2%E3%83%89%E3%82%AA%E3%83%B3%E3%83%9C%E3%83%BC%E3%83%89_%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9%E3%83%89%E3%83%A9%E3%82%A4%E3%83%90_cxd5602pwbimu_driver" rel="noopener noreferrer"&gt;SPRESENSE Developer Guide - IMU Addon Board&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sonydevworld/spresense" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Working Example
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://x.com/GOROman/status/1896200165670912331" rel="noopener noreferrer"&gt;https://x.com/GOROman/status/1896200165670912331&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cxd5602pwbimu</category>
      <category>gaitame</category>
      <category>spresense</category>
      <category>imu</category>
    </item>
  </channel>
</rss>
