Dammit ChatGPT

Sure is fun to play with ChatGPT.

It helped me optimize my wavetable generator speed 1000x. Very nice.

Today, I’m ChatGPT and I are writing ESP32 arduino software to output the positions of two analog joysticks as 14-bit midi over USB.

Summary
It builds, but is not tested yet.

/*
Arduino on ESP32-C3-DevKitM-1
*/


#include <Adafruit_TinyUSB.h>
#include <MIDI.h>
#include "PCF8575.h"

struct Joystick {
  int objectNumber;
  String objectName;
  int analogInputPort;
  int muxAaddress;
  int muxBaddress;
  int CCnumberMSB;
  int CCnumberLSB;
  float previousValue;
};

// Create an array of joystick objects
Joystick joysticks[] = {
  {1, "Joystick A X", 34, 0, 0, 1, 33, 0.0000},
  {2, "Joystick A Y", 34, 1, 0, 2, 34, 0.0000},
  {3, "Joystick B X", 34, 2, 0, 3, 35, 0.0000},
  {4, "Joystick B Y", 34, 4, 0, 4, 36, 0.0000}
};

// Create a PCF8575 object
PCF8575 pcf8575;

// USB MIDI object
Adafruit_USBD_MIDI usb_midi;

// Create a new instance of the Arduino MIDI Library,
// and attach usb_midi as the transport.
MIDI_CREATE_INSTANCE(Adafruit_USBD_MIDI, usb_midi, MIDI);


void setup() {
  // Initialize the PCF8575
  pcf8575.begin();
  // Initialize the MIDI interface
  MIDI.begin();
}

void loop() {
  for (int i = 0; i < sizeof(joysticks)/sizeof(joysticks[0]); i++) {
    // Select the pot
    pcf8575.write(joysticks[i].muxAaddress, joysticks[i].muxBaddress);

    // Read the joystick value
    int joystickValue = analogRead(joysticks[i].analogInputPort);
    // Filter noise
    joystickValue = filterNoise(joystickValue, i);

    // Normalize the value to a float in the range 0-1
    float normalizedValue = (float)joystickValue / 1023.0;

    if (normalizedValue != joysticks[i].previousValue) {
      // Send MIDI message MSB
      MIDI.sendControlChange(joysticks[i].CCnumberMSB,normalizedValue * 127, 1);
      // Send MIDI message LSB
      MIDI.sendControlChange(joysticks[i].CCnumberLSB, map(normalizedValue, 0, 1, 0, 127), 1);
      // Blink the LED
      digitalWrite(LED_BUILTIN, HIGH);
      delay(50);
      digitalWrite(LED_BUILTIN, LOW);
      // Update the previous value
      joysticks[i].previousValue = normalizedValue;
    }
  }
}

// Function to filter noise
float filterNoise(int value, int objectIndex) {
    // State variables
    static float x_est_last = 0;
    float x_temp_est;
    static float P_last = 0;
    float P_temp;

    // Measurement variables
    float z = value;
    float R = 0.01; // Measurement noise

    // Kalman gain
    float K;

    // Time update
    x_temp_est = x_est_last;
    P_temp = P_last + 0.01;

    // Measurement update
    K = P_temp / (P_temp + R);
    x_est_last = x_temp_est + K * (z - x_temp_est);
    P_last = (1 - K) * P_temp;

    // Update the previous value
    joysticks[objectIndex].previousValue = x_est_last;

    return x_est_last;
}