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;
}