Building a SimpleFOC AI Assistant with Retrieval Augmented Generation (RAG)

Mayalen Etcheverry | April, 2024

Reproduce in Notebook Github Repository

What is SimpleFOC?

SimpleFOC

The SimpleFOC library is an open-source library for controlling brushless DC (BLDC) motors with Field Oriented Control (FOC) algorithms. Brushless motor control is awesome for robotics but it can be quite hard to understand and implement in practice, and existing solutions are often very specific to certain (expensive) hardware configurations. SimpleFOC has gained increasing popularity within the hobby community because it provides an open-source and user-friendly library to facilitate BLDC motor control for a wide variety of motor + driver + sensor + microcontroller combinations, including low-cost ones, which has led to its widespread usage by the community hence to some amazing projects 🤖

Why a SimpleFOC AI Assistant?

As the community grows, there are more and more questions that pop up into the SimpleFOC community forum spanning various queries such as resolving potential hardware or installation issues, asking for advice in choosing the right setup, understanding bugs in one's code, etc. While those questions can be very diverse and some of them can be hard to answer, even for the expert members of the SimpleFOC community, there also are questions for which the answers can often be found already online, notably in the SimpleFOC documentation (or in other online resources). However for users it can be quite complicated or time-expensive to directly search for information in the SimpleFOC or other support docs as these documentations can become quite long and hard to parse, especially for beginners. This is where an AI Assistant could be very handy: the user could directly ask question in natural language form to the AI assistant, which could go and retrieve the relevant information from these docs automatically, and then communicate it back to the user into a comprehensive and concise manner, redirecting toward useful resources when necessary.

This is exactly what we are going to try to build in this notebook. To do so, we'll see how we can turn a general LLM assistant (such as Mistral models) into a customized SimpleFOC assistant without having to re-train the weights of the networks nor having to do any kind of heavy computation. Instead, we'll simply provide the LLM with relevant information from the SimpleFOC docs as input so that the LLM can tailor its answers in a meaningful manner. This simple and neat idea is called Retrieval Augmented Generation, or RAG in short, and was proposed by Lewis et al. back in 2020 in this paper. The code is based on open-source packages and LLM weights (quantized mistral-instruct) and should be easy-to-run, e.g. directly in colab with a T4 free-access gpu.

Retrieval Augmented Generation

Let's start by decorticating the basic ideas behind R-A-G 👇

Why RAG could be useful to construct our SimpleFOC AI Assistant?

Well first, mainstream AI assistants such as variants of GPT, LLama and Mistrals tend to return generic information, as they are trained from massive amount of data from the internet. In our target use-case questions will be specific to details of the SimpleFOC library and we want the answer to communicate the true information from SimpleFOC support and docs, or at least to communicate uncertainty when it cannot find the answer within the docs. Yet, this is not the case when using off-the-shelf LLMs, despite the fact that it is very likely that SimpleFOC docs, which are hosted on github, have been part of the training data of these LLMs.

For instance let's have a look of what ChatGPT 4 answers to some questions SimpleFOC users might have:

User:

Can esp8266 chip be used to drive 6pwm drivers with simplefoc?

ChatGPT:

The ESP8266 chip can indeed be used to drive motors using PWM (Pulse Width Modulation), and integrating it with the SimpleFOC (Field Oriented Control) library is technically feasible for controlling brushless motors with precision. However, there are a few considerations to keep in mind when attempting to use it to drive 6 PWM drivers:

1. GPIO Pins: The ESP8266 has a limited number of GPIO pins available for use, and not all of them can be used for PWM output. You'll need to ensure that the ESP8266 module you're using has enough PWM-capable GPIO pins for your application. For 6 PWM drivers, you'll need at least 6 PWM-capable pins, assuming one PWM signal per driver.

2. PWM Channels: The ESP8266 hardware supports a limited number of PWM channels. This limitation can sometimes be circumvented by software PWM libraries, but this might introduce limitations in terms of performance and accuracy. It's crucial to check if the PWM resolution and frequency meet your requirements for motor control.

3. Processing Power and Timing: The ESP8266 is quite capable in terms of processing power for many applications, but running sophisticated control algorithms like those required for precise motor control with SimpleFOC on 6 motors simultaneously might push its limits, especially if other tasks (like Wi-Fi communication) are being performed. Timing precision is vital for motor control, and the ESP8266's multitasking environment might introduce jitter.

4. SimpleFOC Library Compatibility: The SimpleFOC library is designed to be hardware-agnostic, but its performance and the features available can vary significantly between different microcontroller platforms. Ensure that the library supports the ESP8266 with the features you need, especially regarding the number of motors and the control precision.

5. Power Supply and Driver Compatibility: Make sure that your motor drivers are compatible with the PWM signal levels of the ESP8266 and that they can handle the required power levels for your motors.

For a project driving 6 PWM drivers with an ESP8266 using SimpleFOC, you might need to carefully manage resources, possibly modify the library for better compatibility, or use additional hardware like PWM expanders. It's also a good idea to look into the community forums or documentation for any similar projects or guidance specific to your application needs.

👉 A first problematic here is that the answer from GPT tend to be quite long and generic, whereas this question rather expects some YES or NO answer.

👉 Moreover, if we take the time to read the answer we get the understanding that YES it is possible to use an ESP8266 microcontroller be to drive 6pwm drivers with simplefoc. Unfortunately, as reported in this table of SimpleFOC docs, this is not true. This issue, often called hallucination, is a well-known limitation of LLMs: LLMs can generate "good looking" text that sounds convincing, but it does not mean that it is true or factual, which is something that we want to remedy in our target use-case.

Let's look at another question that a user might have, to which we add "Give a concise answer based on the simpleFOC documentation" to avoid too lenghty answers, and see how ChatGPT 4 answers it:

User:

User Simplefoc compiles and I flush it to my board, but nothing moves. I use platformio, what could be the problem? Give a concise answer based on the simpleFOC documentation.

ChatGPT::

If SimpleFOC compiles and you've flashed it to your board but nothing moves, the issue could stem from a few common areas according to the SimpleFOC documentation. Here's a concise checklist of things to verify:

  1. Wiring and Connections: Ensure all connections are secure and correctly wired, including the motor to the driver, the driver to the microcontroller, and any sensors you are using.

  2. Motor and Driver Compatibility: Verify that the motor is compatible with the driver you're using and that the driver can handle the motor's current and voltage requirements.

  3. Power Supply: Ensure that the power supply is adequate for your motor and driver. It should meet the voltage and current requirements of your system.

  4. Configuration and Calibration: Check if the motor, driver, and any sensor configurations in your code match your hardware setup. This includes motor parameters (pole pairs, current limit, etc.) and sensor calibration if using encoders or other position sensors.

  5. Code Upload: Confirm that the code has been successfully uploaded to the board. Sometimes, the upload process might appear successful, but issues like incorrect board settings in PlatformIO can cause the firmware not to run as expected.

  6. Motor Control Code: Ensure that your motor control code (loop) is correctly implemented. This includes initializing the motor and driver, setting the target value (velocity, position, or torque), and periodically updating the motor controller in your loop.

  7. Debugging: Use serial print statements to debug your code. Check for any errors or warnings during initialization and operation. Verify that the sensor readings (if applicable) are reasonable and that the control loop is active.

If after checking these areas the problem persists, consulting the SimpleFOC community forum or GitHub issues page may provide additional insight or solutions specific to your hardware setup and application.

👉 Again we have a generic answer with generic recommandations and misses to answer with specific relevant information from the SimpleFOC resources. Yet, there is a very common explanation to the issue raised by this user when using PlatformIO with SimpleFOC which is to not forget to add the lib_archive=False option to the platfromio.ini file as well explained here in the docs and as commonly reminded in the SimpleFOC forum. We would like the AI Assistant to remind this to the user and to emphasize is as possible cause for the error.

In summary, RAG should a priori be useful in two ways:

  1. RAG can help prevent hallucinations by prompting the LLM with information based on relevant passages from the docs that are factual.

  2. RAG can help specify the responses with information coming from actual data, offering more interpretability as we know where the generations came from, instead of providing generic responses.

RAG Pipeline

pipeline

As summarized in the above figure, we are going to follow the following steps in this notebook:

  1. Download the SimpleFOC documentation (collection of markdown files)
  2. Format and pre-process the documentation into chuncks of tokens
  3. Embed all of the chunks into numerical reprentations (embedding) using an Embedding Model
  4. Setup a retrieval system that uses Vector Search to find relevant chunks of text based on a query
  5. Create a prompt that augment the original query with the retrieved pieces of text
  6. Use an existing LLM (e.g. quantized mistral-instruct) to generate an answer to the augmented prompt

Main Design Choices 💡

The below table recaps the main design choices that we have to care about when implementing a RAG pipeline, as they can largely influence the resulting outputs 👇

Design Choice Impact
Chunking the data 1) The way we generate chunks will directly influence the results: it is usually done with a fixed-size overlapping sliding window
but more advanced strategies of chunking could be envisaged such as recursive or semantic chunking as explained in this video
2) The length of the chunks will also influence the results: smaller chunks will lead to more precise context but might miss important
information whereas larger chunks might hide relevant fine-grained info, and the length is limited by the LLM context length.
3) How we preprocess the data before chunking is also one thing to consider as we want to remove non-useful information/tokens
Embedding model The choice of the embedding model will determine which chunks of text are considered similar (in meaning) to the input query,
which will have a direct impact on what information is retrieved from the vector database.
Similarity search To find chunks relevant to the query, Vector search is often used to find vectors that are the closest in the high-demensional embedding space.
Design choices include the similarity score measure, which is usually a simple dot product or cosine similarity, as well as the number of retrieved tokens.
One could also consider replacing pure vector/semantic search with a hybrid of vector search and keyword-based search.
Large Language Model (LLM) Obviously the choice of the base LLM will highly impact the final results given the same RAG context and input prompt.
I do not have a proper tip to choose the right LLM, except that it is usually quite constrain by the hardware setup at your disposal.
The LLM context window, number of tokens that a LLM can accept as input, can also condition the choice, in particular for
the RAG pipeline where the context window will directly determine the number of reference items we can feed to the LLM.
I usually like to go for small open-source models because they are easy to play with.
Base Prompt Finally, an important design choice is how we will do "prompt engineering" to structure the base prompt that we will augment
with the retrieved items, and then feed as input to the generative LLM together. The aim here is for the generated output to look
as close as possible to what an ideal SimpleFOC AI Assistant should answer.

Let's implement it! 💻

Installs

We'll be using the LlamaIndex library 🦙, that as you will see makes it very easy to implement context augmentation for LLMs with only few lines of code. We also need to install the llama-index-embeddings-huggingface library in order to be able to load embedding models from the HuggingFace embedding leaderboard 🤗, as well as Hugging Face transformers and optimum libraries enabling us to load and use state-of-the art pretrained models efficiently. We additionally install auto-gptq library, as we'll load quantized versions of LLMs for even higher efficiency.

!pip install -q transformers optimum
!pip install -q llama-index
!pip install -q llama-index-embeddings-huggingface
!pip install -q auto-gptq

1) Loading the SimpleFOC data

Let's create the folder where we are going to download the documents that we'll use for RAG.

import os
os.makedirs("data/", exist_ok=True) #ignore if data folder already exists

Download SimpleFOC Docs

Let's start by downloading the docs from SimpleFOC documentation https://docs.simplefoc.com/.

Instead of using the web-rendered documentation, we'll download the original files written in Makdown format that can be found here on github. We are gonna iterate over all the files in this folder, and save them locally in our data folder. We do a bit of pre-processing by removing the markdown headers as they we are interested only in the content of the files.

from tqdm import tqdm
import urllib3

for i, doc_fn in tqdm(enumerate(['work_roadmap.md',
 'index.md',
 'hardware/sensors.md',
 'hardware/index.md',
 'hardware/motors/index.md',
 'hardware/motors/BLDC_motors.md',
 'hardware/motors/phase_resistance.md',
 'hardware/motors/stepper_motors.md',
 'hardware/drivers/BLDC_drivers.md',
 'hardware/drivers/stepper_drivers.md',
 'hardware/drivers/index.md',
 'hardware/mcus/rpi_pico.md',
 'hardware/mcus/teensy.md',
 'hardware/mcus/portenta.md',
 'hardware/mcus/stm32.md',
 'hardware/mcus/arduinos.md',
 'hardware/mcus/index.md',
 'hardware/mcus/esp32.md',
 'hardware/mcus/samd.md',
 'hardware/mcus/nRF52_mcu.md',
 'hardware/setup_examples/nucleo_conneciton.md',
 'hardware/setup_examples/arduino_l6234.md',
 'hardware/setup_examples/hmbgc.md',
 'hardware/setup_examples/drv8302.md',
 'hardware/setup_examples/index.md',
 'hardware/setup_examples/bluepill_conneciton.md',
 'hardware/setup_examples/foc_shield.md',
 'digging_deeper/index.md',
 'digging_deeper/libray_source/foc_source.md',
 'digging_deeper/libray_source/sensors.md',
 'digging_deeper/libray_source/index.md',
 'digging_deeper/libray_source/examples.md',
 'digging_deeper/libray_source/communication.md',
 'digging_deeper/libray_source/motiron_control.md',
 'digging_deeper/theory/index.md',
 'digging_deeper/theory/voltage_torque_control.md',
 'digging_deeper/theory/pid_controller.md',
 'digging_deeper/theory/FOC_routine.md',
 'digging_deeper/theory/low_pass_filtering.md',
 'code/index.md',
 'code/monitoring.md',
 'code/from_scratch.md',
 'code/debug.md',
 'code/sensors/hall_sensor.md',
 'code/sensors/generic.md',
 'code/sensors/encoder.md',
 'code/sensors/index.md',
 'code/sensors/magnetic/magnetic_sensor_i2c.md',
 'code/sensors/magnetic/magnetic_sensor_pwm.md',
 'code/sensors/magnetic/index.md',
 'code/sensors/magnetic/magnetic_sensor_spi.md',
 'code/sensors/magnetic/magnetic_sensor_analog.md',
 'code/motion_control/index.md',
 'code/motion_control/open_loop/angle_openloop.md',
 'code/motion_control/open_loop/index.md',
 'code/motion_control/open_loop/index_search.md',
 'code/motion_control/open_loop/velocity_openloop.md',
 'code/motion_control/closed_loop_control/velocity.md',
 'code/motion_control/closed_loop_control/index.md',
 'code/motion_control/closed_loop_control/angle.md',
 'code/motion_control/closed_loop_control/torque_control/foc_current.md',
 'code/motion_control/closed_loop_control/torque_control/index.md',
 'code/motion_control/closed_loop_control/torque_control/voltage.md',
 'code/motion_control/closed_loop_control/torque_control/dc_current.md',
 'code/motors/index.md',
 'code/motors/bldc_motors.md',
 'code/motors/stepper_motors.md',
 'code/drivers/index.md',
 'code/drivers/bldc_driver/bldc_driver_3pwm.md',
 'code/drivers/bldc_driver/index.md',
 'code/drivers/bldc_driver/bldc_driver_6pwm.md',
 'code/drivers/stepper_driver/stepper_driver_4pwm.md',
 'code/drivers/stepper_driver/index.md',
 'code/drivers/stepper_driver/stepper_driver_2pwm.md',
 'code/current_sense/high_side.md',
 'code/current_sense/index.md',
 'code/current_sense/low_side.md',
 'code/current_sense/inline.md',
 'code/communication/index.md',
 'code/communication/step_dir.md',
 'code/communication/commander/index.md',
 'code/communication/commander/custom.md',
 'code/communication/commander/pid.md',
 'code/communication/commander/scalar.md',
 'code/communication/commander/lpf.md',
 'code/communication/commander/motion.md',
 'code/communication/commander/motor.md',
 'examples/position_control_example.md',
 'examples/position_control_example_nucleo.md',
 'examples/drv8302.md',
 'examples/index.md',
 'examples/foc_pendulum.md',
 'examples/haptics.md',
 'examples/position_control_example_mini.md',
 'examples/position_control_example_mini_nucleo.md',
 'examples/velocity_control_example.md',
 'examples/gimbal_velocity_example.md',
 'examples/stepper_control_nucleo.md',
 'installation/minimal_download.md',
 'installation/index.md',
 'installation/library_platformio.md',
 'installation/library_download.md',
 'cheatsheet/index.md',
 'cheatsheet/build_flags.md',
 'cheatsheet/options.md'])):

    doc_url = f"https://raw.githubusercontent.com/simplefoc/simplefoc.github.io/master/docs/simplefoc_library/{doc_fn}"
    resp = urllib3.request("GET", doc_url)

    if resp.status == 200:
        doc_fp = f"data/doc_{i:04d}.txt"
        doc_str = resp.data.decode("utf-8")

        # remove the header
        header, content = doc_str.split("\n---\n")

        if not os.path.exists(doc_fp):
            with open(doc_fp, "w", encoding="utf-8") as f:
                f.write(content)
105it [00:00, 106.86it/s]

[Optional] SimpleFOC Discourse

There is also the SimpleFOC community forum https://community.simplefoc.com/ that is hosted on discourse and provides useful information. The forum has many topics and can be quite long to dowload so we are gonna skip this for the moment, but if you are interested in including it you can set load_discourse=True in the below cell.

import glob


discourse_url = "https://community.simplefoc.com/"
load_discourse = False

if load_discourse:

    # already downloaded files
    data_list =  glob.glob('./data/discourse_*.txt')
    data_list = sorted(data_list, key=lambda x:int(x[-8:-4]))  # sort data according to topic id
    last_topic_id = 0 if len(data_list)==0 else int(data_list[-1][-8:-4]) # last topic that have been downloaded locally

    # download novel topics
    max_topic_id = 4631 # increase if needed
    for i in tqdm(range(last_topic_id, max_topic_id)):

        topic_url = discourse_url + f"raw/{i}"
        resp = urllib3.request("GET", topic_url)

        if resp.status == 200:

            topic_fp = f"data/discourse_{i:04d}.txt"

            topic_str = resp.data.decode("utf-8")


            if not os.path.exists(topic_fp):

                # filter topics if it has only one non-empty post
                topic_posts = topic_str.split("\n-------------------------\n")
                topic_posts.remove("\n")
                if len(topic_posts) <= 2:
                    continue

                # save topic_posts as doc
                else:
                    with open(topic_fp, "w", encoding="utf-8") as f:
                        f.write(topic_str)

Loading Data into LlamaIndex

We can now load data from our local data folder into LlamaIndex using the SimpleDirectoryReader class which supports many file formats, including markdown.

from llama_index.core import SimpleDirectoryReader

reader = SimpleDirectoryReader(input_dir="./data")
documents = reader.load_data()
print(len(documents))
105

2) Process data as chunks of tokens

LlamaIndex will take care of everything for step 2, 3 and 4, such that we only need to specify the desired hyperparameters for those steps.

For step 2, pre-processing the data into chunks, we simply use a fixed-sized overlapping window method, dividing the text into chunks of fixed number of characters specified with chunk_size and overlapping by chunk_overlap characters.

from llama_index.core import Settings

Settings.chunk_size = 512
Settings.chunk_overlap = 50

3) Embed chunks into a VectorDB

Embedding is simply turning the chunks of text into numerical representations (embeddings). Note that these embeddings are learned representation vectors lying in high-dimensional space that capture semantic information of the words or phrases.

There are many embedding models that are available on the HF hub. A good ressource to choose a model is to check the Massive Text Embedding Benchmark (MTEB) Leaderboard which lists the current best text embedding models out there on a variety of tasks. To select a proper embedding model you generally want to have a look at:

Here we'll be using the mxbai-embed-large-v1 model by mixed-bread-ai, which has 335M params, an embedding dimension of 1024 and can take a maximum of 512 tokens as input (which is exactly what we used as our chunk size).

Once you have selected an embedding model from the HF hub, you simply need to specify it using the embed_model setting and HuggingFaceEmbedding wrapper.

from llama_index.embeddings.huggingface import HuggingFaceEmbedding

Settings.embed_model = HuggingFaceEmbedding(model_name="mixedbread-ai/mxbai-embed-large-v1")
/usr/local/lib/python3.10/dist-packages/huggingface_hub/utils/_token.py:88: UserWarning: 
The secret `HF_TOKEN` does not exist in your Colab secrets.
To authenticate with the Hugging Face Hub, create a token in your settings tab (https://huggingface.co/settings/tokens), set it as secret in your Google Colab and restart your session.
You will be able to reuse this secret in all of your notebooks.
Please note that authentication is recommended but still optional to access public models or datasets.
  warnings.warn(
from llama_index.core import VectorStoreIndex

index = VectorStoreIndex.from_documents(documents)

For step 4, LlamaIndex is again taking care of everything to build a query engine using Vector Search, we simply need to explicitly disable the use of OpenAI LLM (we will use a small open-source one in Step 6) and need to specify is the desired similarity_top_k setting. Here we use similarity_top_k=3, meaning that we will retrieve the 3 closest embeddings from our VectorDB given the user's query embedding.

Settings.llm = None

similarity_top_k = 3
query_engine = index.as_query_engine(similarity_top_k=similarity_top_k)
LLM is explicitly disabled. Using MockLLM.

Let's have a look at which chunks our query engine returns given the following user query "Simplefoc compiles and I flush it to my board, but nothing moves. I use platformio, what could be the problem?". As a recall a good answer here should be to include the lib_archive=False information in the platformio.ini file, so we want the retrieval system to extract this information from the docs.

from IPython.display import display, Markdown

question = "Simplefoc compiles and I flush it to my board, but nothing moves. I use platformio, what could be the problem?"
response = query_engine.query(question)

for i in range(similarity_top_k):
    display(Markdown(f"# Retrieved Chunk {i+1} (source {response.source_nodes[i].score:.2f}) \n {response.source_nodes[i].text}"))

Retrieved Chunk 1 (source 0.76)

  1. Click finish

At this point, if it is the first project you are creating for this board, PlatformIO will download all the required compilers, tools and core library files. Depending on your internet speed, this can take quite a few minutes, so please be patient!

Add SimpleFOClibrary to your project

When everything is finished installing, you should be presented with a view like this:

You can now add the SimpleFOC library to the project:

1. Click on the PlatformIO icon, and choose "Libraries" from the Menu 2. Enter "Simple FOC" in the search 3. Click on the library

1. Click on "Add Library" to display the "Add Library" wizard

1. Choose your project from the drop-down 2. Click "Add" to add the library

Cool! The SimpleFOC library is now associated with your project.

Configure your project

Open the platformio.ini file in the root directory of your project. It should look something like this, depending on the board you chose:

```ini ; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html

[env:mkrwifi1010] platform = atmelsam board = mkrwifi1010 framework = arduino lib_deps = askuric/Simple FOC@^2.2 lib_archive = false ```

IMPORTANT! ⚠️

You have to add the line lib_archive = false to make SimpleFOC compile correctly with PlatformIO.

Retrieved Chunk 2 (source 0.76)

⚠️

You have to add the line lib_archive = false to make SimpleFOC compile correctly with PlatformIO.

You may also want to add some other options, like monitor_speed to set the serial port speed for debug output.

ini monitor_speed = 115200

The available options depend on your board, and we cannot cover them all here, but they are documented in PlatformIO's documentation.

Code away!

You can begin to write your code in the src/main.cpp file.

Youtube tutorial by @owennewo

Advanced Usage

PlatformIO makes it easy for you to use the source version of the SimpleFOC library. This lets you modify the code, or use the most recent "dev" branch version of the library to try out new features before they are officially released.

To use the source code version of the library, try the following steps:

  1. Using your favourite git client, clone the simplefoc library from https://github.com/simplefoc/Arduino-FOC.git
  2. This will create a folder "Arduino-FOC" on your file-system, containing the library source code
  3. Go to your PlatformIO project, and inside the project go to the lib folder. You can use your operating system's shell, or the built-in shell in Visual Studio Code.
  4. Inside the lib folder of your project, create a symlink to your Arduino-FOC folder
    Mac/Linux:
    % ln -s /path/to/Arduino-FOC
    Windows:
    % mklink /J Arduino-FOC C:\path\to\Arduino-FOC

Note: If you had previously added the release version of the library to the project using PlatformIO's library management, you will have to remove this reference from the platformio.ini file

Retrieved Chunk 3 (source 0.76)

# Installing SimpleFOClibrary with PlatformIO

Using SimpleFOC from PlatformIO is not hard at all! The following instructions should get you set up and compiling your code in a matter of minutes.

Quick setup for pros

You can use SimpleFOC in Arduino projects in PlatformIO. Just add the library via the library manager.

You will need this option in your platformio.ini file: ini lib_archive = false

Detailed instructions

Prerequisites

1. Select extension manager 2. Enter "PlatformIO" in the search 3. Choose PlatformIO extension from the list (should be the first result) 4. Click install - after a few moments PlatformIO will be installed, you will be prompted to reload Visual Studio Code

Congratulations, you're ready to start your first project!

Creating a project

To create a new project that uses SimpleFOC, use the following steps:

1. Select the PlatformIO Menu on the left sidebar 2. Choose Open to open the platformIO home screen 3. Click "New Project"

You will be taken to the new project wizard:

1. Give your project a name, e.g. simplefoc_test_project 2. Choose your board. SimpleFOC supports many MCU architectures, see [hardware/mcus] 3. Once you have chosen your board, make sure the Framework "Arduino" is selected. PlatformIO supports other Frameworks, but SimpleFOC is an Arduino Library and must be run in Arduino framework. 4. Click finish

At this point, if it is the first project you are creating for this board, PlatformIO will download all the required compilers, tools and core library files.

👉 We can see that here RAG did a pretty good job at retrieving relevant information and in fact the instruction to set lib_archive = false is present in all 3 retrived chunks, so the LLM should be able to incorporate this in its answer if everything goes well.

5) Import the LLM

Choosing the right LLM can be hard, but we are usually quite constrained in our choices depending on the GPUs hardware that we have at our disposal. Here I'm simply using a colab free-access which has 16GB of RAM.

# Get GPU available memory
import torch
gpu_memory_bytes = torch.cuda.get_device_properties(0).total_memory
gpu_memory_gb = round(gpu_memory_bytes / (2**30))
print(f"Available GPU memory: {gpu_memory_gb} GB")
Available GPU memory: 15 GB

Given 16GB of memory is relatively small we have to stick with small and likely quantized models. There are different types of quantization methods and one of them is known as GPTQ, a post-training quantization (PTQ) method that enable to compress all the weights of these models to a 4-bit precision that can efficiently run on GPUs. You can find many of these quantized models into the HF Hub, in particular you can check collections from The Bloke AI which for instance contains Llama-2-7B-Chat-GPTQ, Mistral-7B-Instruct-v0.2-GPTQ and zephyr-7B-beta-GPTQ. 👉 For a deeper dive into GPTQ you can check out this blog

Let's import Mistral-7B-Instruct-v0.2-GPTQ with its corresponding tokenizer.

# load fine-tuned model from hub
from transformers import AutoModelForCausalLM, AutoTokenizer
from auto_gptq import exllama_set_max_input_length

model_name = "TheBloke/Mistral-7B-Instruct-v0.2-GPTQ"
model = AutoModelForCausalLM.from_pretrained(model_name,
                                             device_map="auto",
                                             trust_remote_code=False,
                                             revision="main")
model = exllama_set_max_input_length(model, 8192)

# load tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_name, use_fast=True)


# put the model in eval mode as we are only gonna use it for inference
model.eval()
/usr/local/lib/python3.10/dist-packages/transformers/modeling_utils.py:4193: FutureWarning: `_is_quantized_training_enabled` is going to be deprecated in transformers 4.39.0. Please use `model.hf_quantizer.is_trainable` instead
  warnings.warn(

Let's print some model statistics.

# Get model number of parameters
print(f"Model has {sum([param.numel() for param in model.parameters()])} parameters")

# Get model parameters and buffer sizes
mem_params = sum([param.nelement() * param.element_size() for param in model.parameters()])
mem_buffers = sum([buf.nelement() * buf.element_size() for buf in model.buffers()])

# Calculate model sizes
model_mem_bytes = mem_params + mem_buffers
model_mem_gb = model_mem_bytes / (1024**3)

print(f"Model memory (GB): {model_mem_gb}")
Model has 262410240 parameters
Model memory (GB): 4.3729400634765625

6) Augment Input Prompt

Now we need to do a bit of prompt-engineering work to decide what we will send as input to the LLM. In this notebook, we'll be using a quantized version of Mistral7B-Instruct. To effectively prompt the Mistral 7B Instruct and get optimal outputs, it's recommended to use the following chat template:

<s>[INST] Instruction [/INST] Model answer</s>[INST] Follow-up instruction [/INST]

<s> and </s> are special tokens indicating beginning of string (BOS) and end of string (EOS), while [INST] and [/INST] are regular strings used to delimitate the instruction/query. We can apply this template by hand, or use the apply_chat_emplate method from the transformers package which is what is done here.

Now a main question here is how to augment the prompt with the retrived chunks such that the LLM can use them most effectively. There are many different tricks to do proper prompt-engineering, most of them being referenced on this prompting guide but what I did here is simply use the together.ai API to try different prompts "by hand" and select the one I was most happy with (base_prompt as shown in below cell). As you can see I basically insisted to use the information from the retrieved chunks (and even solely this information) because I felt that that generic LLMs such as Mistral-instruct tend to provide generic answers which is not what we are looking for here. To do so I added a minimal chain-of-thought (CoT) prompting by asking the model to extract relevant information from the provided context items and to reformulate their content in a clear, accessible and consise manner. I also ask the LLM to not mention these context items (because the RAG pipeline would ultimately be hidden to the user) and to directly refer to the online docs. Finally I ask the LLM to sign with "SimpleFOC_AI" so that users know that the answer is generated by an AI.

def create_prompt(query, context_items):
    context = ""
    for i, context_item in enumerate(context_items):
        context += f"# Context item {i+1} \n {context_item} \n\n"

    base_prompt = """You are SimpleFOC_AI, a virtual assistant that answer user queries on the SimpleFOC forum.
    To do so, you extract relevant information from the SimpleFOC documentation context items provided below, and reformulate their content in a clear and accessible manner. \
    Your answer is as concise and explanatory as possible, and based solely on the information provided in the context items.
    Keep in mind that the user does not know about this context so your answer cannot mention these "items".
    Finally your answer should start with the "SimpleFOC_AI" signature and refer to the SimpleFOC documentation (https://docs.simplefoc.com/)  when needed.

    \n\n{context}

    \n\nUser query: {query}
"""

    base_prompt = base_prompt.format(context=context,
                                     query=query)

    # Create prompt template for instruction-tuned model
    dialogue_template = [
        {"role": "user",
         "content": base_prompt}
    ]

    # Apply the chat template
    prompt = tokenizer.apply_chat_template(conversation=dialogue_template,
                                           tokenize=False,
                                           add_generation_prompt=True)

    return prompt

# Format our prompt
prompt = create_prompt(query=question,
                          context_items=[response.source_nodes[i].text for i in range(similarity_top_k)])
# display(Markdown(prompt[3:]))

Great, we are now ready to pass our augmented prompt to the LLM and see what it returns. Note that there are few important parameters that we can tune here for generating an answer with the LLM, in particular:

# we have to reduce the prompt has this dont fit into context
prompt = create_prompt(query=question,
                          context_items=[response.source_nodes[i].text for i in range(3)])

inputs = tokenizer(prompt, return_tensors="pt")
outputs = model.generate(input_ids=inputs["input_ids"].to("cuda"),
                         temperature=0.7,
                         do_sample=True,
                         max_new_tokens=512)

print(tokenizer.batch_decode(outputs)[0][len("<s> "+prompt):-len("</s>")])
The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.
 SimpleFOC_AI: I'm sorry to hear that you're experiencing issues with SimpleFOC not moving your motor after compiling and flashing through PlatformIO. Here are a few suggestions to help you troubleshoot the problem:

1. Check your wiring: Make sure all your motor connections are correct and properly connected to the board. Double-check the motor polarities, ground, and power connections.

2. Verify your motor configuration: Review the SimpleFOC library documentation () and ensure that the motor configuration in your code matches your motor setup. The library supports various motor types and configurations, so it's essential to choose the correct one.

3. Check your motor parameters: In your code, the SimpleFOC library requires specific motor parameters, such as motor type, RPM, phase resistances, and inductances. Ensure all these parameters are correctly set for your motor.

4. Debugging: Use the Serial Monitor in Visual Studio Code (or another terminal) to check for any error messages or issues in your code. You can also add debug statements to your code to inspect variables or motor states.

5. Firmware version: Ensure you are using the latest SimpleFOC library version that supports your motor and board. Sometimes compatibility issues can cause problems. You can check for the latest library release on GitHub ().

6. PlatformIO configuration: Double-check your platformio.ini file for any misconfigurations or missing settings. Ensure the 'lib_archive' option is set to 'false' as required for SimpleFOC.

7. Hardware issues: If all the above steps do not help, consider checking your hardware for any defects. Try using a different motor or board to rule out any hardware-related issues.

If you still cannot find a solution, you can reach out to the SimpleFOC community for help on their official forum () or contact the SimpleFOC team for further assistance.

Cool, there is the desired information (check lib_archive=false option in the platform.ini file) and the answer is correct and useful 😀

However there are still room for improvement: the important information appears quite late in the answer (point 6) and when we do several samples the answer is not alway as good...

Evaluation 🤔

We are now ready to test our RAG pipeline + LLM on a test set of user queries to see how good of a SimpleFOC AI Assistant we've made...

For each query, we'll pass it three times (n_samples=3) to the LLM to the generated outputs.

n_samples = 3

Test 1

We are first testing whether our RAG pipeline can retrive the info from this section (first table).

The answers should be the following:

questions = ["Is arduino Uno able to produce 6pwm signals with simplefoc?",
          "Can esp8266 chip be used to drive 6pwm drivers with simplefoc?"]
for question in questions:

    response = query_engine.query(question)

    prompt = create_prompt(query=question,
                            context_items=[response.source_nodes[i].text for i in range(3)])

    inputs = tokenizer(prompt, return_tensors="pt")

    display(Markdown(f"## User Question: {question}"))
    for sample_idx in range(n_samples):
        outputs = model.generate(input_ids=inputs["input_ids"].to("cuda"),
                                temperature=0.7,
                                do_sample=True,
                                max_new_tokens=1024)
        display(Markdown(f"### Output {sample_idx}"))
        display(Markdown(tokenizer.batch_decode(outputs)[0][len("<s> "+prompt):-len("</s>")]))

User Question: Is arduino Uno able to produce 6pwm signals with simplefoc?

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 0

SimpleFOC_AI: I'm here to help answer your SimpleFOC-related queries using information from the official documentation. Based on the context you've provided, Arduino Uno has only 4 PWM pins, which is not enough to implement a 6-phase motor control. Therefore, it's not possible to generate 6 PWM signals for motor control with SimpleFOC on an Arduino Uno.

For more details on the specifications of various development boards, you can refer to the documentation or the table you've shared. If you have any other questions about SimpleFOC or its usage, feel free to ask!

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 1

SimpleFOC_AI: I'm SimpleFOC_AI, your helpful assistant from the SimpleFOC documentation.

Regarding your query, the Arduino Uno board has only 4 PWM pins, which is not sufficient for a 6-phase motor control setup. Therefore, it is not possible to implement 6PWM motor control using the SimpleFOC library on an Arduino Uno.

However, you can still use the Arduino Uno with SimpleFOC for motor control applications with less than 6 phases, or you can explore alternative hardware options with more PWM channels if you need a 6-phase motor setup.

For more information about SimpleFOC and its compatibility with different boards, please refer to the SimpleFOC documentation.

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 2

SimpleFOC_AI: I'm SimpleFOC_AI, your helpful assistant for SimpleFOC-related queries. Based on the provided context, an Arduino Uno can use hardware interrupts for encoder setup with SimpleFOC library. However, it only has 4 PWM pins, which is not enough to implement a 6-phase motor control. Therefore, Arduino Uno cannot produce 6 PWM signals for motor control using SimpleFOC directly.

For more information, I encourage you to explore the SimpleFOC documentation at https://docs.simplefoc.com/. If you have any other questions, feel free to ask!

User Question: Can esp8266 chip be used to drive 6pwm drivers with simplefoc?

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 0

SimpleFOC_AI: I'm here to help answer any SimpleFOC-related queries based on the available documentation. The context provided indicates that ESP8266 chips come with only 4 PWM pins and one analog input. Based on SimpleFOC library requirements, the 6PWM motor control and FOC current control cannot be implemented on ESP8266 chips due to this limitation. However, ESP32 chips, which have more PWM pins and are also supported by SimpleFOC, are recommended for driving 6PWM drivers with the library. For more information, visit the SimpleFOC documentation at https://docs.simplefoc.com/.

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 1

SimpleFOC_AI: I'm here to help answer any queries you have regarding the SimpleFOC library. Based on the information provided, ESP8266 chips do not fully meet the requirements for using 6PWM motor control with SimpleFOC. These chips have only 4 PWM pins, which limits the number of channels that can be used for motor control. Additionally, they only have one analog input, making current control not possible.

If you need more information about SimpleFOC or require assistance with a specific issue, please refer to the SimpleFOC documentation available at https://docs.simplefoc.com/. For ESP32 chips, they support MCPWM interface and can handle two 6PWM drivers, but each pin can be used in PWM mode, as long as you avoid using pins with predefined states on boot.

Please note that the support for ESP8266 chips in SimpleFOC is still in the initial stages and may have some limitations. However, you can always consider using other boards that meet the full requirements for 6PWM motor control with SimpleFOC, such as the ESP32 boards mentioned above.

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 2

SimpleFOC_AI: I'm here to help answer your query regarding using an ESP8266 chip with SimpleFOC for 6PWM driver control.

According to the information available in the SimpleFOC documentation, ESP8266 chips have only 4 PWM pins, whereas the 6PWM motor control and FOC current control both require more PWM pins than that. Therefore, ESP8266 chips are not currently supported for 6PWM driver control using SimpleFOC.

For more information on SimpleFOC, please refer to the official documentation at https://docs.simplefoc.com/. If you have any other questions, feel free to ask!

👉 For the first question, unfortunately all outputs are incorrect hallucinations 😓 Indeed they all suggest thar Arduino UNO is not able to produce 6pwm signals with SimpleFOC, whereas it actually is. Looking at the RAG retrieved items for this query, we see that it retrived a chunk coming from this part of the documentation about ESP8266 which says that "These boards have only 4 pwm pins so the 6PWM motor control cannot be implemented" and cutting the previous info that this is ESP8266 and not Arduino UNO, which is likely the cause of hallucinations here.

👉 For the second question however the generated answers are very good, providing correct information and refering to the docs for additional information which is great (and better to what we got with chatGPT at the beginning).

Test 2

We are also testing whether our RAG pipeline can retrive info from the third table from the same section.

The answers should be the following:

questions = ["Does simplefoc implement low-side current sensing for stm32 microcontroller l4 family?",
             "Does simplefoc implement low-side current sensing for stm32 microcontroller h7 family?",
             "Does simplefoc implement low-side current sensing for teensy microcontrollers?"]
for question in questions:

    response = query_engine.query(question)

    prompt = create_prompt(query=question,
                            context_items=[response.source_nodes[i].text for i in range(3)])

    inputs = tokenizer(prompt, return_tensors="pt")

    display(Markdown(f"## User Question: {question}"))
    for sample_idx in range(n_samples):
        outputs = model.generate(input_ids=inputs["input_ids"].to("cuda"),
                                temperature=0.7,
                                do_sample=True,
                                max_new_tokens=1024)
        display(Markdown(f"### Output {sample_idx}"))
        display(Markdown(tokenizer.batch_decode(outputs)[0][len("<s> "+prompt):-len("</s>")]))

User Question: Does simplefoc implement low-side current sensing for stm32 microcontroller l4 family?

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 0

SimpleFOC_AI: The SimpleFOC library currently supports low-side current sensing on certain members of the STM32 microcontroller family, specifically the f1, f4, and g4 families. Unfortunately, the l4 family is not mentioned in the documentation. Therefore, I cannot confirm whether it is supported or not with certainty. For the most accurate and up-to-date information, please refer to the SimpleFOC documentation at https://docs.simplefoc.com/.

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 1

SimpleFOC_AI: I'm here to help answer queries related to the SimpleFOC library. Based on the provided context, the current sensing support for the STM32 microcontroller family includes STM32f1, STM32f4, and STM32g4, which all support low-side current sensing for one motor. However, I cannot confirm if the STM32 L4 family is currently supported for low-side current sensing in SimpleFOC. For the most accurate and up-to-date information, you should refer to the SimpleFOC documentation available at https://docs.simplefoc.com/.

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 2

SimpleFOC_AI: The SimpleFOC library currently supports low-side current sensing for some STM32 microcontroller families like f1, f4, and g4. However, I cannot confirm if it specifically supports the L4 family at this moment. I recommend checking the latest documentation on the SimpleFOC website (https://docs.simplefoc.com/) for the most accurate information regarding the specific STM3 microcontroller family L4.

User Question: Does simplefoc implement low-side current sensing for stm32 microcontroller h7 family?

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 0

SimpleFOC_AI: The SimpleFOC library supports low-side current sensing for some STM32 microcontroller families, including the STM32 H7. However, it's essential to note that the current sensing functionality is limited to one motor for this microcontroller family. For more information about the supported MCUs and their current sensing capabilities, please refer to the SimpleFOC documentation on https://docs.simplefoc.com/.

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 1

SimpleFOC_AI: I'm glad you're interested in SimpleFOC's current sensing capabilities with the STM32 H7 microcontroller family. According to the SimpleFOC documentation, low-side current sensing is supported for the STM32 H7 family, specifically on the B-G431B-ESC1 board. However, the documentation also states that the SAMD21 architecture is under development and its low-side current sensing implementation is not yet fully tested, so I would recommend exercising caution when relying on it.

Since you've asked about low-side current sensing specifically for the STM32 H7 family, I'd like to clarify that this architecture supports one motor with low-side current sensing. Keep in mind that low-side current sensing requires a very high synchronization between the PWM generated by the driver and the ADC triggering, so it's important to consider the PWM frequency and the PWM pins when choosing the driver parameters.

For more information, you can refer to the SimpleFOC documentation on current sensing (https://docs.simplefoc.com/current-sensing/) and the MCU support page (https://docs.simplefoc.com/MCU-support/).

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 2

SimpleFOC_AI: The SimpleFOC library currently supports low-side current sensing for the STM32 microcontroller families f1, f4, and g4, but not for H7. You can refer to the SimpleFOC documentation at https://docs.simplefoc.com/ for more detailed information on the currently supported MCUs and current sensing methods.

User Question: Does simplefoc implement low-side current sensing for teensy microcontrollers?

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 0

SimpleFOC_AI: I'm glad you're interested in SimpleFOC and its current sensing capabilities. Based on the information available in the provided context items, SimpleFOC currently does not support low-side current sensing for Teensy microcontrollers. If you have any other questions about SimpleFOC or its features, feel free to ask! For more details on SimpleFOC and its current sensing approaches, please refer to the official documentation at https://docs.simplefoc.com/.

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 1

SimpleFOC_AI: I'm glad you're interested in current sensing options with SimpleFOC! Based on the provided context, I see that low-side current sensing is supported on several microcontroller units (MCUs), but unfortunately, Teensy microcontrollers are not currently among them. I recommend checking the SimpleFOC documentation for the latest supported MCUs and their respective current sensing options at https://docs.simplefoc.com/.

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 2

SimpleFOC_AI: I'm glad you're interested in using the SimpleFOC library for your Teensy microcontroller project. Regarding your question, the current version of SimpleFOC does not support low-side current sensing for Teensy microcontrollers. The library currently supports in-line current sensing for this platform. However, the development team aims to make SimpleFOC as interchangeable as possible across different drivers and platforms, so new features and improvements, including low-side current sensing for Teensy, may be added in future releases. Be sure to check the SimpleFOC documentation at https://docs.simplefoc.com/ for the latest information.

👉 For the question about low-side sensing support for the stm32 l4 family, the answers does not convey confidently that they support low-side sensing (which is the case), but what I like is that they neither convey the feeling that they don't support it but rather that the AI assistant is uncertain about this query, and that user should check the SimpleFOC website for more accurate informationn which is much better than hallucinating false information. Actually here when we look at the retrieved information from the docs, we understand why the LLM is uncertain as the information is not so clearly explained in the docs. For instance it is emphasized that Stm32 f1, f4 and g4 families support low-side sensing for only one motor which looks like it implicitely suggests that Stm32 l4 family does not support low-side support in contrast, whether what it actually suggests is that l4 family support it for more than one motor as well. Maybe this tool could actually be useful to write better docs 😆

👉 For the same question about stm32 h7 family, there are 2 out of 3 answers that are correct with the last one being the incorrect one. But its not so bad as once again the information is not clearly stated in the docs, for instance the h7 family is not included in this table which summarizes stm32 support. There is also a problem in the second answer, which wrongly suggests that B-G431B-ESC1 board which however is listed in the table, is from the h7 family, but this is wrong.

👉 Finally for the same question about teensy microcontrollers, all 3 answers are correct and concise, referring to the SimpleFOC docs which is nice! However they often refer to the "provided context" or even "context items" despite me asking explicitely referring in the base prompt to not refer to those (as these would be hidden to the user), so there is probably some further improvements to make to the base prompt!

Test 3

We are again testing information contained within the same page in the docs, but answering it requires a bit more of context as the user is asking for advice between several configurations, and the LLM should reason and compare the different options based on the info provided in the docs. Moreover there is various terms that the LLM should know about e.g. "nucleo f411re" is a specific nucleo board from the stm32 microcontroller f4 family.

The answers should be the following:

questions = ["If I have a choice between Arduino UNO, esp32 and stm32f1 chip, which one should I use if I wanna run 2 bldc motors with simplefoc with encoders and low-side current sensing?",
             "If I have a choice between Arduino UNO and nucleo f411re, which one is a better choice for smooth motor control with simplefoc?",
             "If I have a choice between teensy 4.0 and stm32f1 and a 6pwm driver, which one should I use with simplefoc?"]
for question in questions:

    response = query_engine.query(question)

    prompt = create_prompt(query=question,
                            context_items=[response.source_nodes[i].text for i in range(3)])

    inputs = tokenizer(prompt, return_tensors="pt")

    display(Markdown(f"## User Question: {question}"))
    for sample_idx in range(n_samples):
        outputs = model.generate(input_ids=inputs["input_ids"].to("cuda"),
                                temperature=0.7,
                                do_sample=True,
                                max_new_tokens=1024)
        display(Markdown(f"### Output {sample_idx}"))
        display(Markdown(tokenizer.batch_decode(outputs)[0][len("<s> "+prompt):-len("</s>")]))

User Question: If I have a choice between Arduino UNO, esp32 and stm32f1 chip, which one should I use if I wanna run 2 bldc motors with simplefoc with encoders and low-side current sensing?

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 0

SimpleFOC_AI: Based on your requirements of running two BLDC motors with encoders and low-side current sensing using the SimpleFOC library, I would recommend considering an STM32F1 family chip. The STM32F1 series provides initial support for low-side current sensing for one motor, and they offer a good balance of power and flexibility for your project.

Here's a brief summary of the options you have:

  1. Arduino UNO: This microcontroller does not support low-side current sensing, so it's not recommended for your specific use case.
  2. ESP32: ESP32 devices are capable of running 4 BLDC motors with FOC algorithm. However, due to their communication capabilities, they might have some issues with precise real-time control. Low-side current sensing is supported, but it's limited to one motor.
  3. STM32F1: The initial support for low-side current sensing for one motor makes STM32F1 a good choice. It offers a balance between power and flexibility, and it's widely used in the community for FOC projects.

For more detailed information, please refer to the SimpleFOC library documentation at https://docs.simplefoc.com/.

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 1

SimpleFOC_AI: Based on your requirements of running two BLDC motors with encoders and low-side current sensing using the SimpleFOC library, the STM32F1 family would be a suitable choice. The STM32F1 series supports low-side current sensing for one motor, and it has a good number of external interrupt pins, which can be used for encoder signals and PWM outputs. Additionally, the STM32F1 series has low loop times, making the FOC algorithm smoother. However, please note that programming the STM32F1 series might be more complex compared to Arduino UNO or ESP32, but with the SimpleFOC library integrated into the Arduino IDE, this is not a significant issue. Regards, SimpleFOC_AI. (SimpleFOC documentation: https://docs.simplefoc.com/)

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 2

SimpleFOC_AI: Based on your requirements of running two BLDC motors with encoders and low-side current sensing using the SimpleFOC library, the best option among Arduino UNO, esp32, and stm32f1 would be the stm32f1 chip. This is because, as stated in the SimpleFOC documentation, stm32f1 devices support low-side current sensing for one motor. Additionally, they have a sufficient number of external interrupt pins to accommodate the encoder signals and motor control PWM signals for both motors.

However, keep in mind that the Arduino SimpleFOC library code for stm32 devices is the same as for Arduino UNO, except for the pin numbers. Furthermore, stm33 devices provide much better performance and smoother FOC algorithm execution due to their higher processing power, lower loop times, and larger number of external interrupts.

For more information on current sensing support and hardware considerations, please refer to the SimpleFOC documentation at https://docs.simplefoc.com/.

User Question: If I have a choice between Arduino UNO and nucleo f411re, which one is a better choice for smooth motor control with simplefoc?

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 0

SimpleFOC_AI: Based on the provided context, the STM32 Nucleo F411RE is a better choice for smooth motor control using the SimpleFOC library. This is because Nucleo boards have more external interrupt pins, which is essential for handling encoder signals in the FOC algorithm. Additionally, STM32 devices are more powerful and have lower loop times, leading to smoother motor control. However, programming these devices might be more complex compared to Arduino UNO. For more details, check the SimpleFOC documentation on the official website (https://docs.simplefoc.com/).

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 1

SimpleFOC_AI: Based on the information available in the SimpleFOC documentation, both Arduino UNO and Nucleo F411RE boards can be used with the SimpleFOC library for smooth motor control. However, there are some differences between the two:

  1. Arduino UNO has a limited number of interrupts and might not be the best choice if you plan to use multiple motors or encoders. The Arduino Mega, which also uses the AVR architecture, has more interrupts and might be a better choice in this case.
  2. Nucleo F411RE, which is based on STM32 microcontrollers, is more powerful and has more external interrupt pins. This makes it a better choice for implementing the FOC algorithm, as it results in smoother motor control with lower loop times. It can run up to 4 BLDC motors without a problem and supports various types of position sensors and motor drivers.

Therefore, if you are looking for the smoothest motor control with SimpleFOC, the Nucleo F411RE is the better choice. However, keep in mind that the Arduino IDE now supports programming STM32 devices, making the complexity of programming these devices less of an issue.

For more information, you can refer to the SimpleFOC documentation at https://docs.simplefoc.com/.

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 2

SimpleFOC_AI: Based on the documentation, both Arduino UNO and Nucleo F411RE can be used with the SimpleFOC library for motor control. However, there are some differences to consider:

  1. Arduino UNO has fewer interrupts, which might limit the number of motors you can control simultaneously. But with two motors, you should be able to achieve good results.

  2. Nucleo F411RE, being an STM32 device, offers more processing power, faster loop times, and a larger number of external interrupts. This makes it a better choice for smoother motor control and handling more motors. The library code for STM32 devices is the same as for Arduino UNO, but with different pin numbers.

In summary, given your choice between Arduino UNO and Nucleo F411RE, the Nucleo F411RE is the better choice for smoother motor control with SimpleFOC due to its faster processing and larger number of external interrupts.

User Question: If I have a choice between teensy 4.0 and stm32f1 and a 6pwm driver, which one should I use with simplefoc?

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 0

SimpleFOC_AI: Based on the provided context, both Teensy 4.0 and STM32F1 boards are compatible with SimpleFOC library for 6PWM driver. However, the Teensy 4.0 has more PWM channels (35) compared to STM32F1 (12), which could be a deciding factor depending on your specific use case.

Regarding the Teensy 4.0, it uses an ARM Cortex-M7 processor, which is more powerful than the Cortex-M3 or M4 processors used in most STM32F1 boards. This could potentially result in better performance and capabilities.

As for STM32F1, it offers current sensing support for in-line and low-side configurations for one motor. If your application requires current sensing, STM32F1 could be a better choice.

In summary, if you don't require current sensing and prefer more PWM channels and better processing power, Teensy 4.0 could be the better choice. If you need current sensing or prefer a lower-cost, more widely available option, STM32F1 could be more suitable for you.

For further information, please refer to the SimpleFOC documentation at https://docs.simplefoc.com.

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 1

SimpleFOC_AI: Based on the information available in the SimpleFOC documentation, both Teensy 4.0 and STM32F1 support 6 PWM modes. However, there are some differences between these microcontrollers.

Teensy 4.0 uses an ARM Cortex-M7 processor, which provides 35 PWMs and runs at 600 MHz. On the other hand, STM32F1, such as the one mentioned in the context item 2, uses an ARM Cortex-M3 or Cortex-M4 processor with 12 PWMs and runs at 72 MHz.

When it comes to current sensing, the STM32F1 family supports low-side current sensing for one motor. This might be an important factor depending on your specific application requirements.

In general, both teensy 4.0 and STM32F1 can run SimpleFOC library. I recommend considering the number of PWMs you need, the available current sensing options, and the processing power required for your application when choosing between Teensy 4.0 and STM32F1.

For more information, you can refer to the SimpleFOC documentation on teensy (https://docs.simplefoc.com/en/latest/hardware_compatibility.html#teensy) and STM32 (https://docs.simplefoc.com/en/latest/hardware_compatibility.html#stm32) support.

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 2

SimpleFOC_AI: Based on the information available in the SimpleFOC documentation, both Teensy 4.0 and STM32F1 are compatible with the SimpleFOC library in 6PWM mode. However, the Teensy 4.0 supports more PWMs (35 PWMs) compared to STM32F1 (12 PWMs in total). This could be a deciding factor if you plan to control more motors or other components that require PWM control.

Additionally, the Teensy 4.0 supports both low-side and high-side current sensing out of the box, while STM32F1 supports only in-line current sensing. If you're planning to use current sensing, make sure to check which type suits your application best.

For further details, I recommend checking the SimpleFOC documentation on the official website (https://docs.simplefoc.com/) or posting your question on the SimpleFOC community forum (https://community.simplefoc.com/) for more specific advice.

👉 UNO vs esp32 vs stm32f1: unfortunately all the answers suggest to use stm32f1 rather than esp32, and it does not understand than esp32 is the only one which can support 2 motors. But again it is not so bad as the information is still correct and it is true that it is not so clear in the docs to understand that esp32 is supporting two motors e.g. in the 3rd table from this section it is the only line which has a ✅ and that does not say "one-motor" but for the LLM to accurately find and interpret this information is very hard.

👉 UNO vs nucleo f411re: perfect 3/3 here!

👉 teensy vs stm32f1: 2/3 here as the last answer is wrong and even suggests confidently that "Teensy 4.0 supports both low-side and high-side current sensing out of the box" which is completely false! Moreover in the second answer there is also a suggestion that "Teensy 4.0 uses an ARM Cortex-M7 processor, which provides 35 PWMs" which might be an hallucination (to check) and is anyway irrelevant here as the question asks for 6PWM. It also provides a link to the simplefoc documentation which does not exists. Could be better!

Test 4

This question is the example we chose at the beginning, which is a commonly raised question by the community when using SimpleFOC library with PlatformIO and for which the relevant docs is accessible here: https://docs.simplefoc.com/library_platformio.

The answer should be the following:

questions = ["Simplefoc compiles and I flush it to my board, but nothing moves. I use platformio, what could be the problem?"]
for question in questions:

    response = query_engine.query(question)

    prompt = create_prompt(query=question,
                            context_items=[response.source_nodes[i].text for i in range(3)])

    inputs = tokenizer(prompt, return_tensors="pt")

    display(Markdown(f"## User Question: {question}"))
    for sample_idx in range(n_samples):
        outputs = model.generate(input_ids=inputs["input_ids"].to("cuda"),
                                temperature=0.7,
                                do_sample=True,
                                max_new_tokens=1024)
        display(Markdown(f"### Output {sample_idx}"))
        display(Markdown(tokenizer.batch_decode(outputs)[0][len("<s> "+prompt):-len("</s>")]))

User Question: Simplefoc compiles and I flush it to my board, but nothing moves. I use platformio, what could be the problem?

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 0

SimpleFOC_AI: I'm here to help you troubleshoot issues you might have with using SimpleFOC library in PlatformIO. Based on the information you've provided, it seems that your SimpleFOC code is compiling and being uploaded to your board, but the motors are not moving. Here are some possible causes and solutions for this issue:

  1. Check the wiring: Make sure that the motors are properly connected to the board, and that the motor phases, grounds, and power sources are all wired correctly. You can consult the SimpleFOC documentation to verify the wiring scheme for your motor type.

  2. Check the code: Ensure that your code is written correctly and that the motor configuration parameters, such as the motor type, direction, and PID gains, are set correctly. You can refer to the SimpleFOC documentation for examples on how to configure and use the library in Arduino projects.

  3. Check the PID gains: The PID gains control the behavior of the motor control algorithm. If the gains are not set correctly, the motor might not respond as expected. You can consult the SimpleFOC documentation for guidelines on how to tune the PID gains for your specific application.

  4. Check the sensor connection: Make sure that the sensors (encoder or speed sensor) are connected to the board and to the correct pins. You can refer to the SimpleFOC documentation for the recommended wiring scheme for your sensor type.

  5. Check the PlatformIO configuration: Ensure that the SimpleFOC library is being included in your project correctly and that the lib_archive option is set to false. If you are using the source version of the library, you will also need to create a symlink as described in the PlatformIO documentation.

  6. Check the power supply: Make sure that the power supply to the motors and the board is stable and within the recommended voltage range. Low voltage or voltage spikes can cause the motor to not move or behave erratically.

If none of the above steps solve the issue, consider providing more details about the project setup, board, and motor configurations, as well as any error messages or debug output, to help narrow down the cause of the problem. Additionally, you may want to consult the SimpleFOC and PlatformIO documentation for more information and troubleshooting tips.

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 1

SimpleFOC_AI: I'm here to help you troubleshoot your issue with SimpleFOC not moving your motor using PlatformIO. Based on the context provided, here are some steps you can take to identify and resolve the problem:

  1. Check your wiring: Ensure that the motor wiring is correctly connected to the appropriate pins on your board and that you have a proper connection between the motor controller and the MCU.

  2. Verify motor direction: Review the configuration of your motor direction in the SimpleFOC library. Make sure that it matches the physical direction of your motor.

  3. Review your code: Check that you correctly imported the SimpleFOC library into your project and that you're using the correct functions and parameters.

  4. Motor control example: Attempt to run the motor control example provided with SimpleFOC. If the example works correctly, it is likely that there's an issue in your code. If not, it could be an issue with the library, your board, or your setup.

  5. Communication between the MCU and motor controller: Make sure that the communication between the MCU and the motor controller is working properly. You can check the serial monitor in PlatformIO to verify if any error messages are being displayed.

  6. PlatformIO configuration: Ensure that you've correctly configured your project in the platformio.ini file. Double-check that the board, framework, and library settings are correct.

  7. Firmware version: Check that you're using the latest version of both SimpleFOC and PlatformIO. If not, try updating them to their latest releases to see if that resolves the issue.

  8. Debugging: Use PlatformIO's debugging capabilities, such as the Serial Monitor, to help you narrow down the problem.

If none of these steps help, please provide more details about your setup, including the board you're using, the motor controller, and the specific error messages you're encountering. This will help us better understand and assist you with your issue.

Additionally, you can refer to SimpleFOC's documentation and community resources, including the SimpleFOC GitHub repository, the SimpleFOC Discord server, and the SimpleFOC community forum.

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 2

SimpleFOC_AI: I'm sorry to hear that you're having trouble getting your SimpleFOC project to move using PlatformIO. There are a few potential causes for this issue.

First, make sure you have correctly configured your project by adding the SimpleFOC library to it and setting the lib_archive option to false in your platformio.ini file. This is necessary for SimpleFOC to compile correctly with PlatformIO.

Next, check your wiring and motor connections. Make sure that the motors are connected to the correct pins and that they have the correct polarity. You can refer to the documentation on the SimpleFOC GitHub page (https://github.com/simplefoc/Arduino-FOC) for information on how to connect the motors and sensors.

Another possibility is that your motor parameters may not be set correctly. You can find the motor configuration examples in the SimpleFOC library under the examples/MotorConfig folder. Adjust the motor parameters to match your specific setup.

Lastly, ensure that your code is correctly initializing and controlling the motors. Review your code and make sure that you are calling the necessary functions to initialize and control the motors.

If you are still having trouble, consider reaching out to the SimpleFOC community on the SimpleFOC GitHub page or the PlatformIO forum for further assistance.

👉 The answers are very good here, only the second answer remains a bit too long/generic and doest not explicitly mention the lib_archive=false option even though it mentions checking the configuration of the platformio.ini file. But in general the answers are very useful!

Test 5

Finally we test whether RAG pipeline is able to retrieve info correctly from this section of the docs.

The answers should be the following:

questions = ["What are the supported position sensors with simplefoc?"]
for question in questions:

    response = query_engine.query(question)

    prompt = create_prompt(query=question,
                            context_items=[response.source_nodes[i].text for i in range(3)])

    inputs = tokenizer(prompt, return_tensors="pt")

    display(Markdown(f"## User Question: {question}"))
    for sample_idx in range(n_samples):
        outputs = model.generate(input_ids=inputs["input_ids"].to("cuda"),
                                temperature=0.7,
                                do_sample=True,
                                max_new_tokens=1024)
        display(Markdown(f"### Output {sample_idx}"))
        display(Markdown(tokenizer.batch_decode(outputs)[0][len("<s> "+prompt):-len("</s>")]))

User Question: What are the supported position sensors with simplefoc?

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 0

SimpleFOC_AI: The SimpleFOC library supports various types of position sensors, including encoders and magnetic sensors. Encoders are the most commonly used position sensors due to their precision, standardization, and low noise level. Magnetic sensors, on the other hand, use precise magnetic field measurement to estimate position. The library also plans to support IMU sensors in the future. (Refer to the SimpleFOC documentation for more details.)

For encoders, the library supports optical, capacitive, and magnetic types. You can find examples and prices of these encoders on various e-commerce platforms such as eBay or Mouser. Encoder precision and execution efficiency are important factors to consider when selecting an encoder for your application.

Encountering issues during motor initialization can be due to problems with the position sensor or the current sense. Debugging such issues can be facilitated using the SimpleFOCDebug class. This class provides methods like SIMPLEFOC_DEBUG() for logging messages to the console. You can also use FlashStringHelper, disable debug output globally using the build flag SIMPLEFOC_DISABLE_DEBUG, and understand the rationale behind using SimpleFOCDebug instead of Serial.println in the library. (Refer to the SimpleFOC documentation for more information.)

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 1

SimpleFOC_AI: The SimpleFOC library supports encoders and magnetic sensors as position sensors. Encoders estimate position by counting impulses on their A, B, and index channels. Magnetic sensors use precise magnetic field measurement to estimate position. For more information, please refer to the SimpleFOC documentation on position sensors at https://docs.simplefoc.com/.

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 2

SimpleFOC_AI: The SimpleFOC library supports encoders and magnetic sensors as position sensors. Encoders are the most commonly used position sensors due to their precision, standardization, and low noise level. Magnetic sensors, on the other hand, use precise magnetic field measurement to estimate position. For more information, please refer to the SimpleFOC documentation on position sensors at https://docs.simplefoc.com/position-sensors/.

👉 The answers are generally correct but they only mention encoders and magnetic sensors, and forget bout Hall sensors which is weird because it is retrieved in one of the context items (but it is also absent from other chunks which might explain why the LLM does not mention it). However the first answer (output 0) is too long and everything after the first paragraph is too far away from the user query, outputs 1 and 2 are better.

Test 6

Finally we test if the RAG pipeline is able to help users debug their SimpleFOC code.

Here is the question: "My code does not work, what could be the problem?

#include <SimpleFOC.h>

Encoder encoder = Encoder(2, 3, 500);
// interrupt routine initialisation
void doA(){encoder.handleA();}
void doB(){encoder.handleB();}

void setup() {
  // monitoring port
  Serial.begin(115200);

  // initialise encoder hardware
  sensor.init();
  // hardware interrupt enable
  encoder.enableInterrupts(doA, doB);

  Serial.println("Encoder ready");
  _delay(1000);
}

void loop() {
  // display the angle and the angular velocity to the terminal
  Serial.print(sensor.getAngle());
  Serial.print("\t");
  Serial.println(sensor.getVelocity());
}

The answers should be to include the following in the loop

 // IMPORTANT
  // read sensor and update the internal variables
  sensor.update();
questions = ["""my code does not work, what could be the problem?
```cpp
#include <SimpleFOC.h>

Encoder encoder = Encoder(2, 3, 500);
// interrupt routine initialisation
void doA(){encoder.handleA();}
void doB(){encoder.handleB();}

void setup() {
  // monitoring port
  Serial.begin(115200);

  // initialise encoder hardware
  sensor.init();
  // hardware interrupt enable
  encoder.enableInterrupts(doA, doB);

  Serial.println("Encoder ready");
  _delay(1000);
}

void loop() {
  // display the angle and the angular velocity to the terminal
  Serial.print(sensor.getAngle());
  Serial.print("\t");
  Serial.println(sensor.getVelocity());
}
```
"""]
for question in questions:

    response = query_engine.query(question)

    prompt = create_prompt(query=question,
                            context_items=[response.source_nodes[i].text for i in range(3)])

    inputs = tokenizer(prompt, return_tensors="pt")

    display(Markdown(f"## User Question: {question}"))
    for sample_idx in range(n_samples):
        outputs = model.generate(input_ids=inputs["input_ids"].to("cuda"),
                                temperature=0.7,
                                do_sample=True,
                                max_new_tokens=1024)
        display(Markdown(f"### Output {sample_idx}"))
        display(Markdown(tokenizer.batch_decode(outputs)[0][len("<s> "+prompt):-len("</s>")]))

User Question: my code does not work, what could be the problem?

```cpp

include

Encoder encoder = Encoder(2, 3, 500); // interrupt routine initialisation void doA(){encoder.handleA();} void doB(){encoder.handleB();}

void setup() { // monitoring port Serial.begin(115200);

// initialise encoder hardware sensor.init(); // hardware interrupt enable encoder.enableInterrupts(doA, doB);

Serial.println("Encoder ready"); _delay(1000); }

void loop() { // display the angle and the angular velocity to the terminal Serial.print(sensor.getAngle()); Serial.print(" "); Serial.println(sensor.getVelocity()); } ```

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 0

SimpleFOC_AI: Based on the code you've provided, it seems that there are a few issues. Firstly, you have a typo in your variable name for the encoder. It should be named encoder instead of sensor. Also, you need to initialize the software interrupt library and attach the listeners to the correct encoder pins. Here is the corrected code:

```cpp

include

include

include

// define Encoder Encoder encoder = Encoder(2, 3, 500);

// channel A and B callbacks void doA(){encoder.handleA();} void doB(){encoder.handleB();}

// pin change listeners PciListenerImp listenerA(encoder.pinA, doA); PciListenerImp listenerB(encoder.pinB, doB);

void setup() { // monitoring port Serial.begin(115200);

// initialize encoder hardware encoder.init();

// interrupt initialization PciManager.registerListener(&listenerA); PciManager.registerListener(&listenerB);

Serial.println("Encoder ready"); _delay(1000); }

void loop() { // IMPORTANT - call as frequently as possible // update the sensor values encoder.update();

// display the angle and the angular velocity to the terminal Serial.print(encoder.getAngle()); Serial.print("\t"); Serial.println(encoder.getVelocity()); } ```

Also, don't forget to test the sensor and make sure it's working properly before testing the driver. You can refer to the SimpleFOC documentation for more information on testing sensors and encoders: https://docs.simplefoc.com/en/latest/getting_started/index.html#testing-the-sensor.

If the problem persists, please provide more details about the hardware setup, error messages, or unexpected behavior you're experiencing.

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 1

SimpleFOC_AI: I see you're having trouble getting your code to work with the SimpleFOC library. Based on the provided code snippet, it seems you're trying to use an Encoder object without properly initializing it.

First, let's make sure you have the library installed and the necessary hardware connected as mentioned on the SimpleFOC documentation (https://docs.simplefoc.com/).

Now, in your code, replace "sensor" with "encoder". Also, make sure to change the impulses per revolution parameter accordingly:

```cpp Encoder encoder = Encoder(2, 3, 500); // interrupt routine initialisation void doA(){encoder.handleA();} void doB(){encoder.handleB();}

void setup() { // monitoring port Serial.begin(115200);

// initialize encoder hardware encoder.init(); // hardware interrupt enable encoder.enableInterrupts(doA, doB);

Serial.println("Encoder ready"); _delay(1000); }

void loop() { // IMPORTANT // read sensor and update the internal variables encoder.update(); // display the angle and the angular velocity to the terminal Serial.print(encoder.getAngle()); Serial.print("\t"); Serial.println(encoder.getVelocity()); } ```

If the issue still persists, make sure to verify the sensor pins' connections and check for any conflicts with other libraries or hardware. You might also want to go through the SimpleFOC documentation for sensors (https://docs.simplefoc.com/sensors/) to ensure you're using the correct parameters.

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.

Output 2

SimpleFOC_AI: I see you're having trouble with your code not working as expected. Based on the provided code snippet, there are a few potential issues:

  1. Incorrect library inclusion: Make sure you have included the SimpleFOC library correctly at the beginning of your code with #include <SimpleFOC.h>.
  2. Incorrect sensor initialization: Instead of sensor.init(), it should be encoder.init(). The encoder variable is defined as an Encoder object.
  3. Incorrect pin numbers: Check that pins 2 and 3 are correctly connected to your encoder's A and B signals, respectively.
  4. Interrupt initialization: Ensure that you have the PciManager library installed and included correctly (#include <PciManager.h> and #include <PciListenerImp.h>) for software interrupts.
  5. Encoder object definition: You have a typo in your encoder definition, it should be Encoder encoder = Encoder(2, 3, 500); instead of sensor.init();.
  6. Call to update function: In the loop function, you need to call the update function for the encoder to get the latest readings, encoder.update();.

Make sure to go through the SimpleFOC Encoder documentation for more information. If these suggestions don't help, you may need to provide more context, such as error messages or specific issues you are encountering.

👉 The final test is pretty good here and deals efficiently with code 😎 Interestingly it even cought up a typo in a variable name that was done unintentionally by copying wrong code so pretty impressive. The only thing that is not very good here is that output 0 and 2 both mention to include PCIListener whereas it is actually not needed here.

What's Next?

Given the results on our little evaluation benchmark, there are several things that could be done to further improve the results:

Obviously all contributions and suggestions for improvements are very welcome! You can check the Github Repository and raise issues or suggest improvements if you have any 😀