diff --git a/platformio.ini b/platformio.ini index 21dd64b..6ca6f95 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,11 +9,12 @@ ; https://docs.platformio.org/page/projectconf.html [env:esp32] -platform = espressif32 +platform = espressif32 @ ^6.10.0 board = esp32dev framework = arduino -lib_deps = +lib_deps = FastAccelStepper PubSubClient ArduinoJson + RotaryEncoder diff --git a/src/main.cpp b/src/main.cpp index 3511903..bf8d095 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,92 +2,75 @@ #include #include #include +#include +#include const uint8_t bottom_dir_pin = 5, top_dir_pin = 18; const uint8_t bottom_step_pin = 4, top_step_pin = 17; const uint8_t bottom_en_pin = 12, top_en_pin = 16; const uint8_t encoder_a = 19, encoder_b = 21; -const char* ssid = "IOT-pecan"; -const char* password = "aaaaaaaa"; -const char* mqttServer = "192.168.1.110"; -const int mqttPort = 1883; -const char* mqttHeightTopic = "/jc/height"; -const char* mqttAngleTopic = "/jc/angle"; -const char* mqttStopTopic = "/jc/stop"; +#define EEPROM_SIZE 4 -const char* mqttHeightLogTopic = "/jc/height/log"; -const char* mqttAngleLogTopic = "/jc/angle/log"; -const char* mqttRPMLogTopic = "/jc/rpm/log"; +const char *ssid = "IOT-pecan"; +const char *password = "aaaaaaaa"; +const char *mqttServer = "192.168.1.110"; +const int mqttPort = 1883; +const char *mqttHeightTopic = "/jc/height"; +const char *mqttAngleTopic = "/jc/angle"; +const char *mqttStopTopic = "/jc/stop"; + +const char *mqttHeightLogTopic = "/jc/height/log"; +const char *mqttAngleLogTopic = "/jc/angle/log"; +const char *mqttRPMLogTopic = "/jc/rpm/log"; // Thread pitch: 11 TPI (0.0909 in/rev) // Steps per revolution: 2000; const int steps_per_thou = 22; FastAccelStepperEngine engine = FastAccelStepperEngine(); -FastAccelStepper *bottom_stepper=nullptr; -FastAccelStepper *top_stepper=nullptr; +FastAccelStepper *bottom_stepper = nullptr; +FastAccelStepper *top_stepper = nullptr; + +RotaryEncoder encoder(encoder_a, encoder_b); WiFiClient wifiClient; PubSubClient mqttClient(wifiClient); -void callback(char* topic, byte* payload, unsigned int length); - -volatile int encoder_count_a = 0, encoder_count_b = 0; -volatile int last_encoder_count_a = 0, last_encoder_count_b = 0; -volatile double rotations_since_last = 0; -volatile float encoder_rpm = 0; -uint16_t ticks_per_rotation = 600; +void callback(char *topic, byte *payload, unsigned int length); volatile long long bottom_step_goal = 0, top_step_goal = 0; volatile bool bottom_step_done = true, top_step_done = true; volatile bool bottom_step_sent = false, top_step_sent = false; volatile bool do_home = false; -auto timer = timerBegin(0, 80, true); - -void setup() { +void setup() +{ Serial.begin(9600); + EEPROM.begin(EEPROM_SIZE); engine.init(); bottom_stepper = engine.stepperConnectToPin(bottom_step_pin); - if (bottom_stepper) { + if (bottom_stepper) + { bottom_stepper->setDirectionPin(bottom_dir_pin); bottom_stepper->setEnablePin(bottom_en_pin, false); bottom_stepper->setSpeedInHz(1000); bottom_stepper->setAcceleration(250); + bottom_stepper->setCurrentPosition(EEPROM.read(0) << 8 | EEPROM.read(1)); } top_stepper = engine.stepperConnectToPin(top_step_pin); - if (top_stepper) { + if (top_stepper) + { top_stepper->setDirectionPin(top_dir_pin); top_stepper->setEnablePin(top_en_pin, false); top_stepper->setSpeedInHz(1000); top_stepper->setAcceleration(250); + top_stepper->setCurrentPosition(EEPROM.read(2) << 8 | EEPROM.read(3)); } - pinMode(encoder_a, INPUT_PULLUP); - pinMode(encoder_b, INPUT_PULLUP); - attachInterrupt(encoder_a, []() { - encoder_count_a++; - double rotations = 0; - if(encoder_count_a > ticks_per_rotation / 100) { - rotations = (double)encoder_count_a / ticks_per_rotation; - rotations_since_last += rotations / 2; - encoder_count_a -= ticks_per_rotation * rotations; - } - }, FALLING); - - attachInterrupt(encoder_b, []() { - encoder_count_b++; - double rotations = 0; - if(encoder_count_b > ticks_per_rotation / 100) { - rotations = (double)encoder_count_b / ticks_per_rotation; - rotations_since_last += rotations / 2; - encoder_count_b -= ticks_per_rotation * rotations; - } - }, FALLING); - WiFi.begin(ssid, password); - while (WiFi.status() != WL_CONNECTED) { + while (WiFi.status() != WL_CONNECTED) + { delay(1000); Serial.println("Connecting to WiFi..."); } @@ -99,15 +82,21 @@ void setup() { Serial.println("Connected to MQTT"); } -void reconnect() { - while (!mqttClient.connected()) { - if (WiFi.status() != WL_CONNECTED) WiFi.reconnect(); +void reconnect() +{ + while (!mqttClient.connected()) + { + if (WiFi.status() != WL_CONNECTED) + WiFi.reconnect(); Serial.println("Attempting MQTT connection..."); - if (mqttClient.connect("ESP32Client")) { + if (mqttClient.connect("ESP32Client")) + { Serial.println("connected"); mqttClient.subscribe(mqttHeightTopic); mqttClient.subscribe(mqttAngleTopic); - } else { + } + else + { Serial.print("failed, rc="); Serial.print(mqttClient.state()); Serial.println(" try again in 5 seconds"); @@ -116,19 +105,22 @@ void reconnect() { } } -volatile int top_angle_difference_steps = steps_per_thou * 188; +volatile int top_angle_difference_steps = steps_per_thou * 188; volatile bool stop = false; -void callback(char* topic, byte* payload, unsigned int length) { +void callback(char *topic, byte *payload, unsigned int length) +{ String topic_str = String(topic); String payload_str = ""; - for (int i = 0; i < length; i++) { + for (int i = 0; i < length; i++) + { payload_str += (char)payload[i]; } int value = payload_str.toInt(); - - if (topic_str == mqttHeightTopic) { + + if (topic_str == mqttHeightTopic) + { value -= 1875 - 210; value *= steps_per_thou; Serial.println(value); @@ -139,74 +131,92 @@ void callback(char* topic, byte* payload, unsigned int length) { top_step_goal = value + top_angle_difference_steps; top_step_done = false; top_step_sent = false; - } else if (topic_str == mqttAngleTopic) { + } + else if (topic_str == mqttAngleTopic) + { stop = false; top_angle_difference_steps = value * steps_per_thou; top_step_goal = bottom_step_goal + top_angle_difference_steps; top_step_done = false; top_step_sent = false; - } else if (topic_str == mqttStopTopic) { + } + else if (topic_str == mqttStopTopic) + { stop = true; - } - if (top_step_goal < -1665 * steps_per_thou) top_step_goal = -1665 * steps_per_thou; - if (bottom_step_goal < -1665 * steps_per_thou) bottom_step_goal = -1665 * steps_per_thou; + } + if (top_step_goal < -1665 * steps_per_thou) + top_step_goal = -1665 * steps_per_thou; + if (bottom_step_goal < -1665 * steps_per_thou) + bottom_step_goal = -1665 * steps_per_thou; - if(top_step_goal > 0) top_step_goal = 0; - if(bottom_step_goal > 0) bottom_step_goal = 0; + if (top_step_goal > 0) + top_step_goal = 0; + if (bottom_step_goal > 0) + bottom_step_goal = 0; } long last_publish_time = 0; bool bot_homed = false, top_homed = false; -void loop() { - if (!mqttClient.connected()) { +void loop() +{ + if (!mqttClient.connected()) + { reconnect(); } mqttClient.loop(); - if (unsigned long elapsed = (millis() - last_publish_time) > 1000) { - encoder_rpm = (float)rotations_since_last * 60 / elapsed; - - // clamp encoder rpm to 0 if below 50 - if (encoder_rpm < 50) { - encoder_rpm = 0; - } + encoder.tick(); - rotations_since_last = 0; + if (unsigned long elapsed = (millis() - last_publish_time) > 1000) + { last_publish_time = millis(); mqttClient.publish(mqttHeightLogTopic, String(1665 + bottom_stepper->getCurrentPosition() / steps_per_thou).c_str()); mqttClient.publish(mqttAngleLogTopic, String((top_stepper->getCurrentPosition() - bottom_stepper->getCurrentPosition()) / steps_per_thou).c_str()); - mqttClient.publish(mqttRPMLogTopic, String(encoder_rpm).c_str()); + mqttClient.publish(mqttRPMLogTopic, String(encoder.getRPM()).c_str()); } - if(stop) { + if (stop) + { bottom_stepper->disableOutputs(); top_stepper->disableOutputs(); - } else { + } + else + { bottom_stepper->enableOutputs(); top_stepper->enableOutputs(); } - if(bottom_stepper->getCurrentPosition() != bottom_step_goal && !bottom_step_done && !bottom_step_sent) { + if (bottom_stepper->getCurrentPosition() != bottom_step_goal && !bottom_step_done && !bottom_step_sent) + { bottom_stepper->moveTo(bottom_step_goal); bottom_step_sent = true; Serial.println("Moving bottom stepper"); } - if(top_stepper->getCurrentPosition() != top_step_goal && !top_step_done && !top_step_sent) { + if (top_stepper->getCurrentPosition() != top_step_goal && !top_step_done && !top_step_sent) + { top_stepper->moveTo(top_step_goal); top_step_sent = true; Serial.println("Moving top stepper"); } - if(bottom_stepper->getCurrentPosition() == bottom_step_goal && !bottom_step_done && bottom_step_sent) { + if (bottom_stepper->getCurrentPosition() == bottom_step_goal && !bottom_step_done && bottom_step_sent) + { bottom_step_done = true; bottom_step_sent = false; + EEPROM.write(0, bottom_stepper->getCurrentPosition() >> 8); + EEPROM.write(1, bottom_stepper->getCurrentPosition() & 0xFF); Serial.println("Bottom stepper done"); } - if(top_stepper->getCurrentPosition() == top_step_goal && !top_step_done && top_step_sent) { + if (top_stepper->getCurrentPosition() == top_step_goal && !top_step_done && top_step_sent) + { top_step_done = true; top_step_sent = false; + EEPROM.write(2, top_stepper->getCurrentPosition() >> 8); + EEPROM.write(3, top_stepper->getCurrentPosition() & 0xFF); Serial.println("Top stepper done"); } + + EEPROM.commit(); }