Using Generative AI to Write and Run Embedded Code

Ari Mahpour
|  Created: May 15, 2024  |  Updated: July 1, 2024
Using Generative AI to Write and Run Embedded Code

In How to Build a Custom GPT Action to Talk to Your Hardware and Building an AI Lab Assistant, we learned how to control our hardware using Generative AI. By utilizing custom GPT Actions within ChatGPT we were able to give ChatGPT the ability to not only blink LEDs off a Raspberry Pi but also control and acquire data from lab instruments. This meant that we could use artificial intelligence as our lab assistant and also process data for us that it acquired from our instruments. In this article we’re taking it one step further by having Generative AI not only write code for us but also execute it on embedded targets and receive feedback in the process.

Background

Using Generative AI to write code, even for embedded systems, isn’t brand new. There are a myriad of tools out there  already suggesting or completely writing code from scratch. Most popular Large Language Models, such as ChatGPT, Gemini, and Claude, have all become pretty good at writing code (see Gemini vs. ChatGPT: Who Writes Better Code? for a comparison). I've been writing about ChatGPT generating code for over a year now (see Using ChatGPT for Automated Testing) and preaching that it’s the only way to develop these days. The real challenge is getting AI in the loop of your development.

Code generation only gets you so far but being able to validate and ensure it works requires a different approach when it comes to Generative AI. Code Interpreter with ChatGPT provides an encapsulated Python environment that can, to a certain extent, run generated code and validate that it works for you. I wanted to take it a step further and see if we could achieve the same thing with embedded systems. There are two routes that one could take with OpenAI’s ChatGPT. The most common route is to create a closed loop application that uses the OpenAI API. It would prompt and fetch the code from the Large Language Model (LLM) using the API, compile it, load it onto the Arduino, and use additional custom code to validate the functionality of the generated code. I decided to take a different approach using GPT Actions in order to make it more of a “code pairing experience.” This is what that experience looks like:

Example of GPT Action

Figure 1: Example of GPT Action

While the example may be trivial (i.e. blinking an onboard LED) the demonstration above sums it all up. I was able to give clear instructions to my custom GPT and it followed the directions exactly as I expected. I was also able to confirm that it did, indeed, upload to my device and blink the LED at a rate of 1s. The nice thing about using a custom GPT versus a closed loop system is that I can iterate pretty easily within the prompt:

Iterating on the Arduino Sketch

Figure 2: Iterating on the Arduino Sketch

Now that you've seen some examples, let's take a look at how this all works.

How it Works

Just like we’ve seen with other custom GPT articles, the GPT Actions setup for this project is, more or less, the same. The Dockerfile, Docker Compose, SSL certificates, and general structure of the repository hasn’t changed much. Of course the design code itself and the OpenAPI YAML file are significantly different (as to be expected). 

The biggest change that happens in this code (versus previous examples) is that we introduce a “subprocess” in Python to call an external program, in this case the Arduino IDE. Our OpenAPI YAML file (openapi.yaml) is what provides the structure to ChatGPT on what information should be delivered and how that it should be delivered. Looking at the “components” section at the end of the YAML file you’ll notice the different pieces of the return object that we’re expecting:

  

components:

  schemas:

    CodeSnippet:

      type: object

      properties:

        language:

          type: string

        code:

          type: string

        description:

          type: string

          nullable: true

      required:

        - language

        - code

We’ve asked ChatGPT to not only deliver the code but also the language and, optionally, a description of that code. We process that payload in app.py. More important than just processing the command is that we also return meaningful HTTP responses if something breaks in the process. This helps provide context and speak the same “language” as ChatGPT’s web server/AI bot.

The implementation, while somewhat crude, is very simple: we dump the code snippet to a temporary INO file, verify and/or upload it to the Arduino, and delete the temporary INO file. There are, obviously, so many ways that this can go wrong including an insurmountable amount of security risks. It’s extremely important, as always, to limit your development environment and, if opening it up to the outside world, implement all the necessary security measures to ensure your environment is safe.

Just for fun I’ve also implemented a very basic serial read command that gives our custom GPT Action the ability to read from the Arduino serial port. This allows us to validate that the serial port is working without checking manually from our machine. A sample scenario may be if you’re asking ChatGPT to write and upload code to your Arduino from your smartphone. This, of course, can be extended to a more formal get/set type of serial implementation where you send commands and read back responses over serial (as implemented in Configuring a Hardware in the Loop Project).

Conclusion

In this article, we showed how AI can do more than just write code - it can also make sure the code works by running it on actual devices. This is like having a developer that not only writes your project for you but also tests it to make sure it's right. With the examples we used, you can see how this could change the way we create and test our projects, making things faster and easier. All the steps and code we used are shared, so anyone interested can try it out and see how AI might help in their work.

Discover more about this pioneering project and join the evolution at: https://gitlab.com/ai-examples/ai-arduino-code-builder.

About Author

About Author

Ari is an engineer with broad experience in designing, manufacturing, testing, and integrating electrical, mechanical, and software systems. He is passionate about bringing design, verification, and test engineers together to work as a cohesive unit.

Related Resources

Related Technical Documentation

Back to Home
Thank you, you are now subscribed to updates.