commit 90b9f179f94fbb6992ac5d50b81cef2b11d6dc93 Author: mwinter Date: Thu Jan 23 17:52:24 2025 +0100 first commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/designs/cad/box_2_no_slats.20250120-200901.FCBak b/designs/cad/box_2_no_slats.20250120-200901.FCBak new file mode 100644 index 0000000..5026d1f Binary files /dev/null and b/designs/cad/box_2_no_slats.20250120-200901.FCBak differ diff --git a/designs/cad/box_2_no_slats.FCStd b/designs/cad/box_2_no_slats.FCStd new file mode 100644 index 0000000..6f33913 Binary files /dev/null and b/designs/cad/box_2_no_slats.FCStd differ diff --git a/designs/cad/chopper_only_v3.20241126-171000.FCBak b/designs/cad/chopper_only_v3.20241126-171000.FCBak new file mode 100644 index 0000000..a3947ef Binary files /dev/null and b/designs/cad/chopper_only_v3.20241126-171000.FCBak differ diff --git a/designs/cad/chopper_only_v3.FCStd b/designs/cad/chopper_only_v3.FCStd new file mode 100644 index 0000000..dfdafc8 Binary files /dev/null and b/designs/cad/chopper_only_v3.FCStd differ diff --git a/designs/cad/esp_holder.20250118-210844.FCBak b/designs/cad/esp_holder.20250118-210844.FCBak new file mode 100644 index 0000000..b30fe52 Binary files /dev/null and b/designs/cad/esp_holder.20250118-210844.FCBak differ diff --git a/designs/cad/esp_holder.FCStd b/designs/cad/esp_holder.FCStd new file mode 100644 index 0000000..0424ffa Binary files /dev/null and b/designs/cad/esp_holder.FCStd differ diff --git a/designs/cad/impeller_chopper_v4.FCStd b/designs/cad/impeller_chopper_v4.FCStd new file mode 100644 index 0000000..5b7c5df Binary files /dev/null and b/designs/cad/impeller_chopper_v4.FCStd differ diff --git a/designs/cad/impeller_only_v3.20250117-002623.FCBak b/designs/cad/impeller_only_v3.20250117-002623.FCBak new file mode 100644 index 0000000..0f1168a Binary files /dev/null and b/designs/cad/impeller_only_v3.20250117-002623.FCBak differ diff --git a/designs/cad/impeller_only_v3.FCStd b/designs/cad/impeller_only_v3.FCStd new file mode 100644 index 0000000..6a4e255 Binary files /dev/null and b/designs/cad/impeller_only_v3.FCStd differ diff --git a/designs/cad/leg.20250115-131731.FCBak b/designs/cad/leg.20250115-131731.FCBak new file mode 100644 index 0000000..99db732 Binary files /dev/null and b/designs/cad/leg.20250115-131731.FCBak differ diff --git a/designs/cad/leg.FCStd b/designs/cad/leg.FCStd new file mode 100644 index 0000000..382c404 Binary files /dev/null and b/designs/cad/leg.FCStd differ diff --git a/designs/cad/magnet_holder.20241204-153014.FCBak b/designs/cad/magnet_holder.20241204-153014.FCBak new file mode 100644 index 0000000..efa00c9 Binary files /dev/null and b/designs/cad/magnet_holder.20241204-153014.FCBak differ diff --git a/designs/cad/magnet_holder.FCStd b/designs/cad/magnet_holder.FCStd new file mode 100644 index 0000000..d98408e Binary files /dev/null and b/designs/cad/magnet_holder.FCStd differ diff --git a/designs/cad/motor_frame.20250103-225514.FCBak b/designs/cad/motor_frame.20250103-225514.FCBak new file mode 100644 index 0000000..9b998b8 Binary files /dev/null and b/designs/cad/motor_frame.20250103-225514.FCBak differ diff --git a/designs/cad/motor_frame.FCStd b/designs/cad/motor_frame.FCStd new file mode 100644 index 0000000..0dfad42 Binary files /dev/null and b/designs/cad/motor_frame.FCStd differ diff --git a/designs/cad/sensor_frame.20241208-155322.FCBak b/designs/cad/sensor_frame.20241208-155322.FCBak new file mode 100644 index 0000000..8917928 Binary files /dev/null and b/designs/cad/sensor_frame.20241208-155322.FCBak differ diff --git a/designs/cad/sensor_frame.FCStd b/designs/cad/sensor_frame.FCStd new file mode 100644 index 0000000..6ed249c Binary files /dev/null and b/designs/cad/sensor_frame.FCStd differ diff --git a/designs/cad/siren.20241126-123307.FCBak b/designs/cad/siren.20241126-123307.FCBak new file mode 100644 index 0000000..0d878cd Binary files /dev/null and b/designs/cad/siren.20241126-123307.FCBak differ diff --git a/designs/cad/siren.FCStd b/designs/cad/siren.FCStd new file mode 100644 index 0000000..f126e5e Binary files /dev/null and b/designs/cad/siren.FCStd differ diff --git a/designs/cad/stator_bottom.20241126-123313.FCBak b/designs/cad/stator_bottom.20241126-123313.FCBak new file mode 100644 index 0000000..cd66149 Binary files /dev/null and b/designs/cad/stator_bottom.20241126-123313.FCBak differ diff --git a/designs/cad/stator_bottom.FCStd b/designs/cad/stator_bottom.FCStd new file mode 100644 index 0000000..028c12f Binary files /dev/null and b/designs/cad/stator_bottom.FCStd differ diff --git a/designs/cad/stator_cap_v3.20241126-170336.FCBak b/designs/cad/stator_cap_v3.20241126-170336.FCBak new file mode 100644 index 0000000..387169d Binary files /dev/null and b/designs/cad/stator_cap_v3.20241126-170336.FCBak differ diff --git a/designs/cad/stator_cap_v3.FCStd b/designs/cad/stator_cap_v3.FCStd new file mode 100644 index 0000000..f2aa56a Binary files /dev/null and b/designs/cad/stator_cap_v3.FCStd differ diff --git a/designs/cad/stator_cap_v3_more_closed.20250117-001022.FCBak b/designs/cad/stator_cap_v3_more_closed.20250117-001022.FCBak new file mode 100644 index 0000000..5979f4e Binary files /dev/null and b/designs/cad/stator_cap_v3_more_closed.20250117-001022.FCBak differ diff --git a/designs/cad/stator_cap_v3_more_closed.FCStd b/designs/cad/stator_cap_v3_more_closed.FCStd new file mode 100644 index 0000000..8040826 Binary files /dev/null and b/designs/cad/stator_cap_v3_more_closed.FCStd differ diff --git a/designs/cad/stator_only.20241126-163958.FCBak b/designs/cad/stator_only.20241126-163958.FCBak new file mode 100644 index 0000000..16890f3 Binary files /dev/null and b/designs/cad/stator_only.20241126-163958.FCBak differ diff --git a/designs/cad/stator_only.FCStd b/designs/cad/stator_only.FCStd new file mode 100644 index 0000000..bee2200 Binary files /dev/null and b/designs/cad/stator_only.FCStd differ diff --git a/designs/cad/stm_holder_2.20250114-233937.FCBak b/designs/cad/stm_holder_2.20250114-233937.FCBak new file mode 100644 index 0000000..220061a Binary files /dev/null and b/designs/cad/stm_holder_2.20250114-233937.FCBak differ diff --git a/designs/cad/stm_holder_2.FCStd b/designs/cad/stm_holder_2.FCStd new file mode 100644 index 0000000..9586278 Binary files /dev/null and b/designs/cad/stm_holder_2.FCStd differ diff --git a/designs/stl/box_2_no_slats.stl b/designs/stl/box_2_no_slats.stl new file mode 100644 index 0000000..ef6be73 Binary files /dev/null and b/designs/stl/box_2_no_slats.stl differ diff --git a/designs/stl/chopper_only_v3.stl b/designs/stl/chopper_only_v3.stl new file mode 100644 index 0000000..887d4f0 Binary files /dev/null and b/designs/stl/chopper_only_v3.stl differ diff --git a/designs/stl/chopper_only_v3_4_port.stl b/designs/stl/chopper_only_v3_4_port.stl new file mode 100644 index 0000000..0b10172 Binary files /dev/null and b/designs/stl/chopper_only_v3_4_port.stl differ diff --git a/designs/stl/chopper_only_v3_6_port.stl b/designs/stl/chopper_only_v3_6_port.stl new file mode 100644 index 0000000..e492804 Binary files /dev/null and b/designs/stl/chopper_only_v3_6_port.stl differ diff --git a/designs/stl/esp_holder.stl b/designs/stl/esp_holder.stl new file mode 100644 index 0000000..692ae4c Binary files /dev/null and b/designs/stl/esp_holder.stl differ diff --git a/designs/stl/impeller_only_v3.stl b/designs/stl/impeller_only_v3.stl new file mode 100644 index 0000000..b835d2b Binary files /dev/null and b/designs/stl/impeller_only_v3.stl differ diff --git a/designs/stl/impeller_only_v3_4_blade.stl b/designs/stl/impeller_only_v3_4_blade.stl new file mode 100644 index 0000000..262f3bc Binary files /dev/null and b/designs/stl/impeller_only_v3_4_blade.stl differ diff --git a/designs/stl/impeller_only_v3_5_blade.stl b/designs/stl/impeller_only_v3_5_blade.stl new file mode 100644 index 0000000..329ced0 Binary files /dev/null and b/designs/stl/impeller_only_v3_5_blade.stl differ diff --git a/designs/stl/impeller_only_v3_6_blade.stl b/designs/stl/impeller_only_v3_6_blade.stl new file mode 100644 index 0000000..2e8e2aa Binary files /dev/null and b/designs/stl/impeller_only_v3_6_blade.stl differ diff --git a/designs/stl/leg.stl b/designs/stl/leg.stl new file mode 100644 index 0000000..812f88b Binary files /dev/null and b/designs/stl/leg.stl differ diff --git a/designs/stl/magnet_holder.stl b/designs/stl/magnet_holder.stl new file mode 100644 index 0000000..9045930 Binary files /dev/null and b/designs/stl/magnet_holder.stl differ diff --git a/designs/stl/motor_frame_threaded.stl b/designs/stl/motor_frame_threaded.stl new file mode 100644 index 0000000..30e07b0 Binary files /dev/null and b/designs/stl/motor_frame_threaded.stl differ diff --git a/designs/stl/sensor_frame.stl b/designs/stl/sensor_frame.stl new file mode 100644 index 0000000..b58ca1b Binary files /dev/null and b/designs/stl/sensor_frame.stl differ diff --git a/designs/stl/stator_6_port.stl b/designs/stl/stator_6_port.stl new file mode 100644 index 0000000..a078ef7 Binary files /dev/null and b/designs/stl/stator_6_port.stl differ diff --git a/designs/stl/stator_bottom.stl b/designs/stl/stator_bottom.stl new file mode 100644 index 0000000..b6d14fc Binary files /dev/null and b/designs/stl/stator_bottom.stl differ diff --git a/designs/stl/stator_cap_v3.stl b/designs/stl/stator_cap_v3.stl new file mode 100644 index 0000000..81c599e Binary files /dev/null and b/designs/stl/stator_cap_v3.stl differ diff --git a/designs/stl/stator_cap_v3_more_closed.stl b/designs/stl/stator_cap_v3_more_closed.stl new file mode 100644 index 0000000..b6611c3 Binary files /dev/null and b/designs/stl/stator_cap_v3_more_closed.stl differ diff --git a/designs/stl/stator_only.stl b/designs/stl/stator_only.stl new file mode 100644 index 0000000..cfa8d5e Binary files /dev/null and b/designs/stl/stator_only.stl differ diff --git a/designs/stl/stator_only_6_port.stl b/designs/stl/stator_only_6_port.stl new file mode 100644 index 0000000..fa6bd07 Binary files /dev/null and b/designs/stl/stator_only_6_port.stl differ diff --git a/designs/stl/stator_only_7_port.stl b/designs/stl/stator_only_7_port.stl new file mode 100644 index 0000000..7e0d575 Binary files /dev/null and b/designs/stl/stator_only_7_port.stl differ diff --git a/designs/stl/stator_only_v3_4_port.stl b/designs/stl/stator_only_v3_4_port.stl new file mode 100644 index 0000000..476e777 Binary files /dev/null and b/designs/stl/stator_only_v3_4_port.stl differ diff --git a/designs/stl/stm_holder.stl b/designs/stl/stm_holder.stl new file mode 100644 index 0000000..ed33f6d Binary files /dev/null and b/designs/stl/stm_holder.stl differ diff --git a/src/B_G431B_ESC1_motor_controller/B_G431B_ESC1_motor_controller.ino b/src/B_G431B_ESC1_motor_controller/B_G431B_ESC1_motor_controller.ino new file mode 100644 index 0000000..5b60934 --- /dev/null +++ b/src/B_G431B_ESC1_motor_controller/B_G431B_ESC1_motor_controller.ino @@ -0,0 +1,145 @@ +/** + * B-G431B-ESC1 position motion control example with encoder + * + */ +#include +#include +#include + +// Motor instance +//BLDCMotor motor = BLDCMotor(7, 0.14, 2450, 0.00003); +//BLDCMotor motor = BLDCMotor(7, 0.15, 940, 0.000125); +BLDCMotor motor = BLDCMotor(7, 0.14, 850, 0.0000425); +BLDCDriver6PWM driver = BLDCDriver6PWM(A_PHASE_UH, A_PHASE_UL, A_PHASE_VH, A_PHASE_VL, A_PHASE_WH, A_PHASE_WL); +// Gain calculation shown at https://community.simplefoc.com/t/b-g431b-esc1-current-control/521/21 +LowsideCurrentSense currentSense = LowsideCurrentSense(0.003f, -64.0f/7.0f, A_OP1_OUT, A_OP2_OUT, A_OP3_OUT); + +// encoder instance +MXLEMMINGObserverSensor sensor = MXLEMMINGObserverSensor(motor); + +HardwareSerial Serial1(PB6, PB7); + +// velocity set point variable +float target = 0; +float targetP = 0; +float targetI = 0; +float targetV = 0; +// instantiate the commander +Commander commandComp = Commander(Serial); +Commander commandESP = Commander(Serial1); +void doTargetP(char* cmd) { commandComp.scalar(&targetP, cmd); } +void doTargetI(char* cmd) { commandComp.scalar(&targetI, cmd); } +void doTargetV(char* cmd) { commandESP.scalar(&targetV, cmd); } + +void setup() { + + //pinMode(LED_RED, OUTPUT); // Set board LED for debugging + //digitalWrite(LED_RED, HIGH); + + // use monitoring with serial + Serial.begin(115200); + Serial1.begin(115200); + + // enable more verbose output for debugging + // comment out if not needed + SimpleFOCDebug::enable(&Serial); + + // initialize encoder sensor hardware + sensor.init(); + + // link the motor to the sensor + motor.linkSensor(&sensor); + + // driver config + // power supply voltage [V] + driver.voltage_power_supply = 12; + driver.init(); + // link the motor and the driver + motor.linkDriver(&driver); + // link current sense and the driver + currentSense.linkDriver(&driver); + + // initialise the current sensing + if(!currentSense.init()){ + Serial.println("Current sense init failed."); + return; + } + // no need for aligning + currentSense.skip_align = true; + motor.linkCurrentSense(¤tSense); + + motor.sensor_direction= Direction::CW; + motor.zero_electric_angle = 0; + + // set motion control loop to be used + motor.controller = MotionControlType::velocity; + motor.torque_controller = TorqueControlType::foc_current; + //motor.torque_controller = TorqueControlType::dc_current; + //motor.foc_modulation = FOCModulationType::SpaceVectorPWM; + + motor.current_sp = motor.current_limit; + + // velocity PI controller parameters + motor.PID_velocity.P = 0.01; + motor.PID_velocity.I = 0.004; + + driver.voltage_limit = 8; + motor.voltage_limit = 4; + //motor.current_limit = 2; + + motor.PID_velocity.limit = motor.voltage_limit; + + // jerk control using voltage voltage ramp + // default value is 300 volts per sec ~ 0.3V per millisecond + motor.PID_velocity.output_ramp = 10; + + // velocity low pass filtering time constant + //motor.LPF_velocity.Tf = 0.1; + + // comment out if not needed + motor.useMonitoring(Serial); + + motor.monitor_downsample = 10000; + //motor.motion_downsample = 4; + + // initialize motor + motor.init(); + // align encoder and start FOC + motor.initFOC(); + + // add target command T + commandComp.add('P', doTargetP, "target P"); + commandComp.add('I', doTargetI, "target I"); + commandESP.add('V', doTargetV, "target V"); + + Serial.println(F("Motor ready.")); + Serial.println(F("Set the target velocity using serial terminal:")); + _delay(1000); +} + +void loop() { + // main FOC algorithm function + motor.loopFOC(); + + //motor.PID_velocity.P = targetP; + //motor.PID_velocity.I = targetI; + + //Serial.println(target); + + // Motion control function + motor.move(targetV); + + if (abs(motor.target) < 20.0f && motor.enabled==1) + motor.disable(); + if (abs(motor.target) >= 20.0f && motor.enabled==0) + motor.enable(); + + // function intended to be used with serial plotter to monitor motor variables + // significantly slowing the execution down!!!! + motor.monitor(); + + // user communication + commandESP.run(); + commandComp.run(); + +} diff --git a/src/B_G431B_ESC1_motor_controller/build_opt.h b/src/B_G431B_ESC1_motor_controller/build_opt.h new file mode 100644 index 0000000..82f3ab8 --- /dev/null +++ b/src/B_G431B_ESC1_motor_controller/build_opt.h @@ -0,0 +1,2 @@ +-DHAL_OPAMP_MODULE_ENABLED +-DHAL_UART_MODULE_ENABLED \ No newline at end of file diff --git a/src/siren_controller_esp32_simple_station/siren_controller_esp32_simple_station.ino b/src/siren_controller_esp32_simple_station/siren_controller_esp32_simple_station.ino new file mode 100644 index 0000000..8b61cf8 --- /dev/null +++ b/src/siren_controller_esp32_simple_station/siren_controller_esp32_simple_station.ino @@ -0,0 +1,222 @@ +#include "WiFi.h" + +#include + +// Display Libraries +#include +#include +#include + +// Other Libraries +#include +#include +#include + +// WiFi stuff +const char* ssid = "sirening"; +const char* pwd = "alarm_11735"; +const IPAddress ip(192, 168, 4, 201); +const IPAddress gateway(192, 168, 4, 1); +const IPAddress subnet(255, 255, 0, 0); + +// for ArduinoOSC +const char* host = "192.168.4.200"; +const int settings_port = 54000; +const int state_port = 54001; + +// Button Defs +bool freqButtonState = false; +AiEsp32RotaryEncoder freqEncoderButton = AiEsp32RotaryEncoder(34, 35, 32, -1, 4); +bool ampButtonState = false; +AiEsp32RotaryEncoder ampEncoderButton = AiEsp32RotaryEncoder(33, 25, 26, -1, 4); + +float frequency = 0; +float amplitude = 0; +const int ports = 6; +const int motorIndex = 0; + +// Display Defs +#define I2C_ADDRESS 0x3C +SSD1306AsciiWire oled; +uint8_t fieldWidth; +uint8_t rowsPerLine; // Rows per line. + +HardwareSerial freqSerial(1); +HardwareSerial ampSerial(2); + +void killAll() { + updateFreq(0.0); + updateAmp(0.0); +} + +float hzToRads(int freq){ + return freq * TWO_PI / ports; +} + +float rpmToRads(int rpm){ + return (rpm / 60) * TWO_PI; +} + +void updateFreq(float val){ + frequency = val; + Serial.println("new freq is: " + String(frequency)); + freqEncoderButton.setEncoderValue(frequency * 10.0); + freqSerial.print("\nV" + String(hzToRads(frequency)) + "\n"); + updateDisplay(); +} + +void updateAmp(float val){ + amplitude = val; + Serial.println("new amp is: " + String(amplitude)); + ampEncoderButton.setEncoderValue(amplitude * 10.0); + ampSerial.print("\nV" + String(hzToRads(amplitude)) + "\n"); + updateDisplay(); +} + +void setupOSC(){ + OscWiFi.publish(host, state_port, "/state", motorIndex, frequency, amplitude)->setFrameRate(10.f); + + OscWiFi.subscribe(settings_port, "/kill", [](const OscMessage& m) { + killAll(); + }); + + OscWiFi.subscribe(settings_port, "/freq", [](const OscMessage& m) { + updateFreq(m.arg(0)); + }); + + OscWiFi.subscribe(settings_port, "/amp", [](const OscMessage& m) { + updateAmp(m.arg(0)); + }); +} + +void IRAM_ATTR readFreqEncoderISR() { + freqEncoderButton.readEncoder_ISR(); +} + +void IRAM_ATTR readAmpEncoderISR() { + ampEncoderButton.readEncoder_ISR(); +} + +void setupEncoderButton(AiEsp32RotaryEncoder& eb, char* val){ + eb.begin(); + if(val == "freq") { + eb.setup(readFreqEncoderISR); + } else { + eb.setup(readAmpEncoderISR); + } + eb.setBoundaries(0, 4000, false); + eb.setAcceleration(1000); +} + +void initWiFi() { + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, pwd); + WiFi.config(ip, gateway, subnet); + Serial.println(); + Serial.print("Connecting to WiFi .."); + while (WiFi.status() != WL_CONNECTED) { + Serial.print('.'); + delay(1000); + } + Serial.println(WiFi.localIP()); +} + +void setup() { + + Serial.begin(115200); + freqSerial.begin(115200, SERIAL_8N1, 16, 17); + ampSerial.begin(115200, SERIAL_8N1, 18, 19); + delay(2000); + + initWiFi(); + + setupOSC(); + + setupEncoderButton(freqEncoderButton, "freq"); + setupEncoderButton(ampEncoderButton, "amp"); + + Wire.begin(); + oled.begin(&Adafruit128x64, I2C_ADDRESS); + //oled.setI2cClock(100000L); + oled.setFont(System5x7); + oled.clear(); + oled.println(); + oled.println(); + oled.println(" frequency: 0"); + oled.print(" amplitude: 0"); + fieldWidth = oled.fieldWidth(strlen(" amplitude: ")); + rowsPerLine = oled.fontRows(); +} + +void encoderButtonUpdate(char* val, float& setting, AiEsp32RotaryEncoder& eb, bool& buttonState, HardwareSerial& ser) { + if (eb.encoderChanged()) { + setting = eb.readEncoder() / 10.0; + ser.print("\nV" + String(hzToRads(setting)) + "\n"); + Serial.println("new " + String(val) + " is: " + String(setting)); + updateDisplay(); + } + + if (eb.isEncoderButtonDown() && !buttonState) { + buttonState = true; + } + + //button is up + if (!eb.isEncoderButtonDown() && buttonState) { + killAll(); + buttonState = false; + } +} + +void loop() +{ + encoderButtonUpdate("freq", frequency, freqEncoderButton, freqButtonState, freqSerial); + encoderButtonUpdate("amp", amplitude, ampEncoderButton, ampButtonState, ampSerial); + + OscWiFi.update(); + + //getSerialData(); + getFreqSerialData(); + getAmpSerialData(); + +} + +void updateDisplay(){ + oled.clearField(fieldWidth, rowsPerLine * 2, 4); + oled.print(frequency); + oled.clearField(fieldWidth, rowsPerLine * 3, 4); + oled.print(amplitude); +} + +bool showSerialData(void *) { + + Serial.print("\nrpm/freq real: "); + Serial.print(frequency); + Serial.print("\t"); + Serial.print(frequency / 60 * ports); + + return true; +} + +void getFreqSerialData() { + while (freqSerial.available()) { + Serial.print(char(freqSerial.read())); + } +} + +void getAmpSerialData() { + while (ampSerial.available()) { + Serial.print(char(ampSerial.read())); + } +} + +void getSerialData() { + if (Serial.available() > 0) { + // ignore line feed and carriage return + if (Serial.peek() == '\n' || Serial.peek() == '\r') { + Serial.read(); // read and discard LF & CR + } else { + frequency = Serial.parseFloat(); + Serial.println(frequency, 4); // print to 4 decimal places + } + } +} diff --git a/src/siren_remote_control_esp32/siren_remote_control_esp32.ino b/src/siren_remote_control_esp32/siren_remote_control_esp32.ino new file mode 100644 index 0000000..f667c2f --- /dev/null +++ b/src/siren_remote_control_esp32/siren_remote_control_esp32.ino @@ -0,0 +1,192 @@ +#include "WiFi.h" + +#include + +// Display Libraries +#include +#include +#include + +// Other Libraries +#include +#include +#include + +// WiFi stuff +const char* ssid = "sirening"; +const char* pwd = "alarm_11735"; +const IPAddress ip(192, 168, 4, 200); +const IPAddress gateway(192, 168, 4, 1); +const IPAddress subnet(255, 255, 0, 0); + +// for ArduinoOSC +const char* hosts[] = {"192.168.4.201", "192.168.4.202", "192.168.4.203"}; +const int settings_port = 54000; +const int state_port = 54001; + +// Button Defs +bool freqButtonState = false; +AiEsp32RotaryEncoder freqEncoderButton = AiEsp32RotaryEncoder(34, 35, 32, -1, 4); +bool ampButtonState = false; +AiEsp32RotaryEncoder ampEncoderButton = AiEsp32RotaryEncoder(33, 25, 26, -1, 4); +int sirenSelect = 0; + +//TODO: These should be bound to a publication of the frequency directly from the siren +float frequencies[] = {0, 0, 0}; +float amplitudes[] = {0, 0, 0}; +const int ports = 5; + +// Display Defs +#define I2C_ADDRESS 0x3C +SSD1306AsciiWire oled; +uint8_t fieldWidth; +uint8_t rowsPerLine; // Rows per line. + +void killAll() { + for (int h = 0; h < 3; h++) { + OscWiFi.send(hosts[h], settings_port, "/kill"); + } +} + +float hzToRads(int freq){ + return freq * TWO_PI / ports; +} + +float rpmToRads(int rpm){ + return (rpm / 60) * TWO_PI; +} + +void setupOSC(char* path){ + OscWiFi.subscribe(state_port, path, [](const OscMessage& m) { + int motorIndex = m.arg(0); + float frequency = m.arg(1); + float amplitude = m.arg(2); + if(frequency != frequencies[motorIndex]){ + frequencies[motorIndex] = frequency; + freqEncoderButton.setEncoderValue(frequency * 10.0); + updateDisplay(); + } + if(amplitude != amplitudes[motorIndex]){ + amplitudes[motorIndex] = amplitude; + ampEncoderButton.setEncoderValue(amplitude * 10.0); + updateDisplay(); + } + }); +} + +void IRAM_ATTR readFreqEncoderISR() { + freqEncoderButton.readEncoder_ISR(); +} + +void IRAM_ATTR readAmpEncoderISR() { + ampEncoderButton.readEncoder_ISR(); +} + +void setupEncoderButton(AiEsp32RotaryEncoder& eb, char* val){ + eb.begin(); + if(val == "freq") { + eb.setup(readFreqEncoderISR); + } else { + eb.setup(readAmpEncoderISR); + } + eb.setBoundaries(0, 4000, false); + eb.setAcceleration(1000); +} + +void setup() { + + // initialize serial communication at 115200 bits per second: + Serial.begin(115200); //used for debugging. + delay(2000); + + WiFi.softAPConfig(ip, gateway, subnet); + WiFi.softAP(ssid, pwd); + + Serial.println(""); + Serial.print("WiFi AP IP = "); + Serial.println(WiFi.softAPIP()); + + setupOSC("/state"); + + setupEncoderButton(freqEncoderButton, "freq"); + setupEncoderButton(ampEncoderButton, "amp"); + + Wire.begin(); + oled.begin(&Adafruit128x64, I2C_ADDRESS); + //oled.setI2cClock(100000L); + oled.setFont(System5x7); + oled.clear(); + oled.println(); + oled.println(); + oled.println(" siren: 0"); + oled.println(" frequency: 0"); + oled.print(" amplitude: 0"); + fieldWidth = oled.fieldWidth(strlen(" amplitude: ")); + rowsPerLine = oled.fontRows(); +} + +void encoderButtonUpdate(AiEsp32RotaryEncoder& eb, bool& buttonState, char* val) { + if (eb.encoderChanged()) { + float setting = eb.readEncoder() / 10.0; + OscWiFi.send(hosts[sirenSelect], settings_port, "/" + String(val), setting); + Serial.print("new " + String(val) + " is: "); + Serial.println(setting); + updateDisplay(); + } + + if (eb.isEncoderButtonDown() && !buttonState) { + buttonState = true; + } + + //button is up + if (!eb.isEncoderButtonDown() && buttonState) { + if(val == "freq"){ + sirenSelect = (sirenSelect + 1) % 3; + } else { + killAll(); + } + updateDisplay(); + buttonState = false; + } +} + +void loop() +{ + encoderButtonUpdate(freqEncoderButton, freqButtonState, "freq"); + encoderButtonUpdate(ampEncoderButton, ampButtonState, "amp"); + + OscWiFi.update(); +} + +void updateDisplay(){ + oled.clearField(fieldWidth, rowsPerLine * 2, 4); + oled.print(sirenSelect + 1); + oled.clearField(fieldWidth, rowsPerLine * 3, 4); + oled.print(frequencies[sirenSelect]); + oled.clearField(fieldWidth, rowsPerLine * 4, 4); + oled.print(amplitudes[sirenSelect]); +} + +bool showSerialData(void *) { + + Serial.print("\nrpm/freq real: "); + Serial.print(frequencies[sirenSelect]); + Serial.print("\t"); + Serial.print(frequencies[sirenSelect] / 60 * ports); + + return true; +} + +/* +void getSerialData() { + if (Serial.available() > 0) { + // ignore line feed and carriage return + if (Serial.peek() == '\n' || Serial.peek() == '\r') { + Serial.read(); // read and discard LF & CR + } else { + frequency[sirenSelect] = Serial.parseFloat(); + Serial.println(frequency[sirenSelect], 4); // print to 4 decimal places + } + } +} +*/