4977

As I started to delve a little into the possibilities of AI, I wondered if ChatGPT could help me with unfinished old hardware and software projects.

The new hammer in the software hobbyist’s toolbox: ChatGPT
Who doesn’t know the long reverberations of hardware and software projects? Building and programming was fun and it works quite well. But actually you wanted to change or add this and that in the software … and then never got around to it, because there were so many other things to do.

This was also the case with the Arduino C++ code for my old project “Magnetic Levitation – The Digital Way “, which I described in [1] and [2]. The hardware works fine – but the Arduino code was programmed “quick and dirty”, just to show that it works in principle. But finished and beautiful is actually different!

When I recently started to look a little bit into the possibilities of AI, the thought of whether ChatGPT [3] could help me quickly came up. In initial experiments, I was very quickly able to have small snippets of code and complete Arduino C++ programs generated that matched my rough specifications formulated in simple technical language.

Encouraged, I then went to a colloquial description of my levitation setup in need of embellishment and the desired software functions … and was very amazed at how good the result was.

To anticipate my result:
For me, as an occasional and hobby programmer, some doors that were previously only half open or even completely closed are suddenly opening up.
This almost makes one forget the undoubtedly dark aspects of the use of AI systems.
The well-functioning MagLev system in the photo above is a visible result of AI-assisted work.

Take a look at the attached files   with a photo and the  circuit diagram of my old  MagLev project., or read it here [2] with embedded media. .

This  was my dialog with ChatGPT:

USER:
The following magnetic levitation setup is to be controlled with an ESP32 and a C++ Arduino program.
Pin 23 controls an electromagnet with iron core, pin 33 is the ADC input to which an analog Hall sensor is connected.Below the electromagnet is the analog HALL sensor.
The electromagnet is initially switched on. A permanent magnet approaches the electromagnet and its iron core, as well as the Hall sensor, from below. The magnet is attracted by the core. However, it is to be held in suspension. For this purpose, the electromagnet is to be switched off briefly.
The Hall sensor generates a voltage of about 2.4V in the floating state and about 1.5V without the permanent magnet .
If the magnet comes very close to the sensor, the voltage rises to a maximum of 3 volts.
During the program run, the trigger value for the floating state should be corrected upwards in small steps via the serial interface (115200Baud, 8N1 ) when “T” is received. With “t” it is corrected downwards. Additionally, like the trigger value, a hysteresis value of approx. 50mV should also be set and corrected accordingly by keyboard commands.
The manually corrected values of trigger and hysteresis are both to be output if they have been changed. Both values are to be stored safely in the non-volatile memory of the ESP32 when “S” or “s” is entered. Only if there are already old values in the non-volatile memory, these should be used as program start values.
A very brief description of the operation should be displayed at startup.

Write the Arduino program very compact and with reasonably less comments so that it can be output completely in the response.



ChatGPT’s answer, that still amazes me and even scares me a little:

#include <EEPROM.h>

const int magnetPin = 23;
const int hallSensorPin = 33;
const int triggerAddr = 0;
const int hysteresisAddr = 1;

float triggerValue = 2.4;
float hysteresisValue = 0.05;

void setup() {
  Serial.begin(115200);
  pinMode(magnetPin, OUTPUT);
  pinMode(hallSensorPin, INPUT);
  
  // Load trigger and hysteresis values from EEPROM if available
  EEPROM.begin(2);
  float storedTriggerValue = EEPROM.readFloat(triggerAddr);
  float storedHysteresisValue = EEPROM.readFloat(hysteresisAddr);
  
  if (storedTriggerValue != 0x00)
    triggerValue = storedTriggerValue;
    
  if (storedHysteresisValue != 0x00)
    hysteresisValue = storedHysteresisValue;
  
  Serial.println("Magnetic Levitation Setup");
  Serial.println("Commands:");
  Serial.println("T - Increase trigger value");
  Serial.println("t - Decrease trigger value");
  Serial.println("H - Increase hysteresis value");
  Serial.println("h - Decrease hysteresis value");
  Serial.println("S or s - Save trigger and hysteresis values");
  Serial.println();
  Serial.print("Trigger Value: ");
  Serial.println(triggerValue);
  Serial.print("Hysteresis Value: ");
  Serial.println(hysteresisValue);
}

void loop() {
  // Read the analog value from the Hall sensor
  int hallSensorValue = analogRead(hallSensorPin);
  
  // Check if magnet is close to the sensor
  if (hallSensorValue > (triggerValue + hysteresisValue) * 1023) {
    // Magnet is close, turn off the electromagnet
    digitalWrite(magnetPin, LOW);
  } else {
    // Magnet is far, turn on the electromagnet
    digitalWrite(magnetPin, HIGH);
  }
  
  // Check for serial input
  if (Serial.available() > 0) {
    char command = Serial.read();
    if (command == 'T') {
      triggerValue += 0.01;
    } else if (command == 't') {
      triggerValue -= 0.01;
    } else if (command == 'H') {
      hysteresisValue += 0.01;
    } else if (command == 'h') {
      hysteresisValue -= 0.01;
    } else if (command == 'S' || command == 's') {
      // Save trigger and hysteresis values to EEPROM
      EEPROM.writeFloat(triggerAddr, triggerValue);
      EEPROM.writeFloat(hysteresisAddr, hysteresisValue);
      EEPROM.commit();
      Serial.println("Trigger and hysteresis values saved.");
    }
    
    // Output trigger and hysteresis values
    Serial.print("Trigger Value: ");
    Serial.println(triggerValue);
    Serial.print("Hysteresis Value: ");
    Serial.println(hysteresisValue);
  }
}
Note: This is a compact version of the code without extensive comments. It assumes you have the necessary libraries installed, including the EEPROM library. Make sure to include that library in your Arduino IDE if you don’t have it already.

USER:: Give a brief description of the code for documentation purpose

ChatGPT:

The provided code is a compact Arduino program written in C++ for controlling a magnetic levitation setup using an ESP32 microcontroller. The setup consists of an electromagnet with an iron core and an analog Hall sensor.

At startup, the program initializes the serial communication with a baud rate of 115200. Pin 23 is used to control the electromagnet, and pin 33 is configured as an analog input to read the Hall sensor’s output voltage.

The program retrieves the trigger and hysteresis values from the non-volatile memory (EEPROM) if they were previously stored. If no values are found, it uses default values. The trigger value represents the voltage threshold for switching off the electromagnet, and the hysteresis value defines the voltage range within which the electromagnet remains off even if the magnet is slightly distant from the sensor.

The program then displays a brief description of the operation and the available commands on the serial monitor. The commands allow adjusting the trigger and hysteresis values by incrementing or decrementing them. The updated values are immediately displayed on the serial monitor. To save the trigger and hysteresis values in the non-volatile memory, the user can enter “S” or “s” command.

In the main loop, the program reads the analog value from the Hall sensor and compares it with the trigger value plus the hysteresis value. If the sensor reading is above this threshold, indicating that the magnet is close, the electromagnet is turned off by setting pin 23 low. Otherwise, if the magnet is far, the electromagnet is turned on by setting pin 23 high.

The program continuously checks for incoming commands from the serial monitor. If a command is received, it adjusts the trigger or hysteresis value accordingly. If the “S” or “s” command is entered, the trigger and hysteresis values are saved in the non-volatile memory.

The current trigger and hysteresis values are outputted to the serial monitor whenever they are changed or at program startup.

This program provides a simple and compact solution for controlling a magnetic levitation setup using an ESP32 microcontroller.

USER:  Make three brief suggestions to improve the control loop

ChatGPT:

  • Implement PID Control: Consider implementing a PID (Proportional-Integral-Derivative) control loop to enhance the stability and responsiveness of the magnetic levitation system. By using feedback from the Hall sensor and applying appropriate control gains, the PID controller can dynamically adjust the electromagnet’s power to maintain the desired levitation distance. This will improve the system’s ability to handle disturbances and provide smoother control.
  • Use a Moving Average Filter: To reduce noise and fluctuations in the Hall sensor readings, apply a moving average filter. Instead of relying solely on individual readings, calculate the average value over a small window of recent readings. This will help provide a more stable and reliable measurement for determining the magnet’s position and adjusting the electromagnet’s power accordingly.
  • Incorporate a Safety Timeout: Add a safety timeout mechanism to the control loop to ensure that the electromagnet is not continuously powered if the magnet or the sensor is absent or fails. If the system does not receive a valid Hall sensor reading within a specified period, it can assume that something is wrong and take appropriate action, such as turning off the electromagnet or triggering an error condition.
By implementing these suggestions, you can enhance the control loop’s performance, noise immunity, and safety features, resulting in more precise and reliable magnetic levitation control.

My conclusions:
I admit that my initial question above came about after some lengthy dialogs in which in which I also had to learn how to set up my questions in a ChatGPT AI-friendly way.

By the way: ChatGPT’s answers were often simply cut off abruptly. A specific request for a possible limitation of the length of the answer resulted in a very wordy and here very abbreviated “Yes, 2048 characters”. Therefore I have included in my “order” also clues for a suitable shortening of the answer.

However, if one has familiarized oneself a little with the reaction of the system, the results are also very good after a single somewhat more complex block of questions, requirements and instructions. Targeted inquiries add further also more extensive functions.
If the result seems technically incorrect, it is interesting to see that the same question that has been repeated several times is answered differently each time, which manifests itself here in code that is sometimes completely differently structured, but mostly functional. It is then extremely helpful, perhaps even essential, to at least be able to read the generated code well and to be able to check that all requirements are observed. ChatGPT quickly omits one or the other aspect!

Suggestions from the AI ​​that contradict your own technical expertise and knowledge can be specifically questioned. This often leads to apologetic wording and improved suggestions. Or it gives you new technical knowledge yourself.

All in all, using ChatGPT to create software based on a colloquial problem description has proven very useful here. Perhaps not as a hammer, but rather as a fine-tunable and controllable tool.

Even a less experienced C++ programmer, such as myself, can now quickly create more complex parts of programs that would have taken me at least significantly longer in the past. Documentation is now very easy. And one can even expect a kind of deeper understanding of the problem mentioned, which opens the horizon for unexpected technically well-founded and detailed peripheral areas.

However: Currently AI, especially ChatGPT, is a helpful but by no means infallible tool for the casual programmer and it still needs a human controller!
I’m very excited about more projects with this new screwdriver set in my toolbox.


As if my conclusions needed any further proof:
When testing the generated code, I noticed that there are two problems in the code. ..
OK ... let's ask the machine about it:

USER:  Correct two problems.
1.  The hall sensor value is always compared to a fixed value without a hysteresis.
2. This code does not correctly store the values to the nv-ram of my ESP32 .  Use an other method to store and read

Rewrite the above code very compact and with reasonably less comments so that it can be output completely in the response.

ChatGPT:
Apologies for the oversight.

#include <Preferences.h>

const int magnetPin = 23;
const int hallSensorPin = 33;
const char* prefNamespace = "levitation";
const char* triggerKey = "trigger";
const char* hysteresisKey = "hysteresis";

float triggerValue = 2.4;
float hysteresisValue = 0.05;

Preferences preferences;

void setup() {
  Serial.begin(115200);
  pinMode(magnetPin, OUTPUT);
  pinMode(hallSensorPin, INPUT);
  
  preferences.begin(prefNamespace, false);
  if (preferences.getBool("initialized", false)) {
    triggerValue = preferences.getFloat(triggerKey, triggerValue);
    hysteresisValue = preferences.getFloat(hysteresisKey, hysteresisValue);
  } else {
    preferences.putBool("initialized", true);
  }
  
  Serial.println("Magnetic Levitation Setup");
  Serial.println("Commands:");
  Serial.println("T - Increase trigger value");
  Serial.println("t - Decrease trigger value");
  Serial.println("H - Increase hysteresis value");
  Serial.println("h - Decrease hysteresis value");
  Serial.println("S or s - Save trigger and hysteresis values");
  Serial.println();
  Serial.print("Trigger Value: ");
  Serial.println(triggerValue);
  Serial.print("Hysteresis Value: ");
  Serial.println(hysteresisValue);
}

void loop() {
  int hallSensorValue = analogRead(hallSensorPin);
  
  if (hallSensorValue > (triggerValue * 1023) && digitalRead(magnetPin) == HIGH) {
    digitalWrite(magnetPin, LOW);
  } else if (hallSensorValue < ((triggerValue - hysteresisValue) * 1023) && digitalRead(magnetPin) == LOW) {
    digitalWrite(magnetPin, HIGH);
  }
  
  if (Serial.available() > 0) {
    char command = Serial.read();
    if (command == 'T') {
      triggerValue += 0.01;
    } else if (command == 't') {
      triggerValue -= 0.01;
    } else if (command == 'H') {
      hysteresisValue += 0.01;
    } else if (command == 'h') {
      hysteresisValue -= 0.01;
    } else if (command == 'S' || command == 's') {
      preferences.putFloat(triggerKey, triggerValue);
      preferences.putFloat(hysteresisKey, hysteresisValue);
      preferences.end();
      Serial.println("Trigger and hysteresis values saved.");
    }
    
    Serial.print("Trigger Value: ");
    Serial.println(triggerValue);
    Serial.print("Hysteresis Value: ");
    Serial.println(hysteresisValue);
  }
}



This version addresses the two issues mentioned:

  1. The code now includes hysteresis in the comparison by checking the magnetPin state in both conditions. If the electromagnet is already in the desired state, the condition for turning it on or off is not evaluated.
  2. Instead of using the EEPROM library, this code uses the Preferences library provided by the ESP32 core. The preferences are stored in the non-volatile memory of the ESP32 using the Preferences API. The values are saved when the 'S' or 's' command is received and are read from the memory during setup. The preferences namespace and keys are specified for the levitation setup to avoid conflicts with other preferences. 



Well, that worked very well now. During testing, however, my human brain discovered another rather small problem!
But now, in this state, I have come to the conclusion that this should also remain an unfinished software project :-)..
So I ended the chat and had a coffee with my wife :-)).



[1] ELEKTOR LABS: MagLev -The Digital Way
[2] MagLev at PeterNeufeld.wordpress.com
[3] ChatGPT