/* * TODO: * bestehende steuerung aus espcontroller übernehmen und testen * topics und handler implementieren */ #include "Ethernet.h" #include "PubSubClient.h" //Ethernet and MQTT String ip = ""; uint8_t mac[6] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x06}; #define CLIENT_ID "Mixer" EthernetClient ethClient; PubSubClient mqttClient; #define PUBLISH_DELAY 10000 long last_send=0; //Serial long last_serialdebug=0; #define INTERVAL_SERIALDEBUG 200 //Inputs #define PIN_BUTTON 9 #define PIN_ENCA 7 #define PIN_ENCB 8 #define BUTTON_RELEASE_DEBOUNCE 100 //minimum time after button release to reenable triggering boolean button_flag=false; //true if button pressed boolean button_released=true; long last_button_released=0; //last time button has been released (for debounce) //Shift Register 595 //connections: https://www.arduino.cc/en/tutorial/ShiftOut #define SRLATCH 4 #define SRCLOCK 5 #define SRDATA 6 uint16_t srbits=0; #include Encoder volEnc(PIN_ENCA,PIN_ENCB); float encoderMultiplier=4.0; //Servo stuff #define SRPIN_MOTOR_IN1 1 //L293(pin2) Motor IN1 #define SRPIN_MOTOR_IN2 2 //L293(pin7) Motor IN2 #define PIN_POT A0 //reference potentiometer wiper #define DEADZONE_POTI 5 //maximum allowed error. stop when reached this zone #define POT_MIN 10 //minimum value pot can reach #define POT_MAX 1010 //maximum value pot can reach #define POTIFILTER 0.8 //0 to 1. 1 means old value stays forever int poti_set=512; //set value int poti_read=0; //read value from poti boolean poti_reachedposition=true; //set to true if position reached. after that stop turning #define MOTOR_STOP(); srWrite(SRPIN_MOTOR_IN1,LOW); srWrite(SRPIN_MOTOR_IN2,LOW); #define MOTOR_LEFT(); srWrite(SRPIN_MOTOR_IN1,LOW); srWrite(SRPIN_MOTOR_IN2,HIGH); #define MOTOR_RIGHT(); srWrite(SRPIN_MOTOR_IN1,HIGH); srWrite(SRPIN_MOTOR_IN2,LOW); #define MOTOR_TURNING() (srRead(SRPIN_MOTOR_IN1) != srRead(SRPIN_MOTOR_IN2)) //Motorcheck long last_motorcheck=0; #define INTERVAL_MOTORCHECK 100 //check motor movement every x ms int poti_read_last=0; int motor_vel=0; //analog read units per second #define MINIMUM_MOTORVEL 20 //minimum velocity motor should turn wenn active #define MOTOR_FAILTIME 500 //in ms. if motor did not turn fox x amount of time at least with MINIMUM_MOTORVEL an error will initiate long last_motorTooSlow=0; //typically 0 //error uint8_t error=0; #define NOERROR 0 #define MOTORDIDNOTTURN 1 void setup() { pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN,HIGH); pinMode(PIN_BUTTON,INPUT_PULLUP); pinMode(PIN_POT,INPUT); pinMode(SRLATCH, OUTPUT); pinMode(SRCLOCK, OUTPUT); pinMode(SRDATA, OUTPUT); Serial.begin(9600); while (!Serial) {}; Serial.println("Booting"); if (Ethernet.begin(mac) == 0) { // setup ethernet communication using DHCP Serial.println("Unable to configure Ethernet using DHCP"); Serial.flush(); delay(200); for (;;); } Serial.println("Ethernet configured via DHCP"); Serial.print("IP address: "); Serial.println(Ethernet.localIP()); Serial.println(); ip = String (Ethernet.localIP()[0]); ip = ip + "."; ip = ip + String (Ethernet.localIP()[1]); ip = ip + "."; ip = ip + String (Ethernet.localIP()[2]); ip = ip + "."; ip = ip + String (Ethernet.localIP()[3]); //Serial.println(ip); // setup mqtt client mqttClient.setClient(ethClient); mqttClient.setServer("10.0.0.1", 1883); Serial.println("MQTT client configured"); mqttClient.setCallback(callback); Serial.println("Ready"); last_send = millis(); } void reconnect() { // Loop until reconnected while (!mqttClient.connected()) { Serial.print("Attempting MQTT connection..."); // Attempt to connect if (mqttClient.connect(CLIENT_ID)) { Serial.println("connected"); mqttClient.publish("audiomixer/ip", ip.c_str()); //Publish own ip mqttClient.subscribe("audiomixer/main/volume/set"); //subscribe to /set, republish without /set } else { Serial.print("failed, rc="); Serial.print(mqttClient.state()); Serial.println(" try again in 5 seconds"); delay(5000);// Wait 5 seconds before retrying } } } void loop() { long loopmillis=millis(); if (!mqttClient.connected()) { reconnect(); } mqttClient.loop(); //Serial Input ############################################## while (Serial.available() > 0) { int _value = Serial.parseInt(); if (Serial.read() == '\n') { Serial.print("value="); Serial.println(_value); //poti_set=_value; //poti_reachedposition=false; //aim for new position srWrite(_value,!srRead(_value)); } } //Inputs ################################################### poti_read=poti_read*POTIFILTER + (1.0-POTIFILTER)*analogRead(PIN_POT); //read poti if (!digitalRead(PIN_BUTTON)){ //button pressed if (button_released){ button_released=false; //flag: not released if(loopmillis-last_button_released > BUTTON_RELEASE_DEBOUNCE){ button_flag=true; } } }else if(!button_flag && !button_released){ //button released and flag has been cleared last_button_released=loopmillis; button_released=true; } //Read Encoder to velocity "volEncVel" int volEncVel=0; int _volEnc=volEnc.read(); if (_volEnc!=0){ //encoder moved volEncVel=_volEnc; volEnc.write(0); //reset value } //Input Handling if (volEncVel!=0){ //knob moved poti_set+=volEncVel*encoderMultiplier; //change poti set value poti_set=constrain(poti_set, POT_MIN,POT_MAX); poti_reachedposition=false; } //Motor Movement Routine ################# if (error==0){ //no errors if (!poti_reachedposition && abs(poti_read-poti_set)>DEADZONE_POTI){ //error too high digitalWrite(LED_BUILTIN,HIGH); if (poti_read-poti_set < 0){ MOTOR_LEFT(); }else{ MOTOR_RIGHT(); } }else if(!poti_reachedposition){ //position reached but flag not set MOTOR_STOP(); Serial.print("reached:"); Serial.print(" set="); Serial.print(poti_set); Serial.print(" is="); Serial.print(poti_read); Serial.print(" vel="); Serial.println(); poti_reachedposition=true; //position reached digitalWrite(LED_BUILTIN,LOW); } if ( loopmillis > last_motorcheck+INTERVAL_MOTORCHECK){ last_motorcheck=loopmillis; motor_vel=(poti_read-poti_read_last)*1000 /INTERVAL_MOTORCHECK ; //calculate current motor velocity poti_read_last=poti_read; //motor fail check if (MOTOR_TURNING() && abs(motor_vel) MOTOR_FAILTIME){ error=MOTORDIDNOTTURN; Serial.println("MOTORDIDNOTTURN"); } }else if (last_motorTooSlow>0){ //was recognized too slow but is now turning fast again last_motorTooSlow=0; //reset } } }else{ //an error occured. error!=0 MOTOR_STOP(); } if ( loopmillis > last_serialdebug+INTERVAL_SERIALDEBUG){ last_serialdebug=loopmillis; Serial.print(" set="); Serial.print(poti_set); Serial.print(" is="); Serial.print(poti_read); Serial.print(" vel="); Serial.print(motor_vel); Serial.println(""); if (button_flag){ //TODO: remove hier if correct behaviour implemented Serial.println("BUTTON Pressed"); button_flag=false; //clear flag to reenable button triggering. } } } void sendData() { char msgBuffer[20]; float h = 50; float testvalue = 42; /* Serial.print("testvalue: "); Serial.print(testvalue); Serial.println(); if (mqttClient.connect(CLIENT_ID)) { mqttClient.publish("audiomixer/messwert/parameter", dtostrf(testvalue, 6, 2, msgBuffer)); //mqttClient.publish(DEVICENAME+"/br/nb/deur", (statusBD == HIGH) ? "OPEN" : "CLOSED"); }*/ } void callback(char* topic, byte* payload, unsigned int length) { Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] ");//MQTT_BROKER for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } Serial.println(); //if (strncmp((const char*)payload, "ON", 2) == 0) { //} if (strncmp((const char*)topic, "audiomixer/main/volume/set",sizeof(topic)) == 0) { //Serial.println("republish"); mqttClient.publish("audiomixer/main/volume", payload, length ); } } void srWrite(uint8_t pin, boolean state){ if (state==true){ srbits |= 1UL << pin; //set bit }else{ srbits &= ~(1UL << pin); //clear bit } digitalWrite(SRLATCH, LOW); shiftOut(SRDATA, SRCLOCK, MSBFIRST, srbits>>8); shiftOut(SRDATA, SRCLOCK, MSBFIRST, srbits); digitalWrite(SRLATCH, HIGH); } boolean srRead(uint8_t pin){ return (srbits >> pin) & 1U; }