Gå til innhold
  • Bli medlem
Støtt hjemmeautomasjon.no!

Styring av Gardiner!


Anbefalte innlegg

Jeg driver å bygger styring av lamell gardinene min (fra Jysk). La ut noe i hva-har-du-gjort-i-dag-tråden men fant ut at jeg heller vil ha en egen tråd. Særlig fordi det er andre her som både har lyst og erfaring.

 

Her er proof-of-concept på snortrekket og strammeren:

 

image.png

 

Her er step 2 i prototype utviklingen:


image.png

 

Siden jeg modellerer i Onshape er alle modellene mine public tilgjengelige:
(Onshape er gratis om du deler modellene)
 

image.png

 


Målet er at automatikken skal ligge "bak" skinna slik at skinna skal kunne monteres helt oppe i karmen. Det gir en utfordring med høyden på snortrekke-hjulet slik at det ikke tar ned i lamellene.

 

For øyeblikket er det to små steppere og tanken er å telle omdrininger slik at jeg slipper endestopp. Bygges da slik at mekanikken tåler å "hoppe over" om det ikke stemmer helt. Skal kunne kjøres manuellt og konfigureres (omtrent som en "Rollertrol") med en "joy stick" som denne (3 klikk for Learn-mode :)  )
 

image.png
og en RGB-Led for å melde tilbake :)

 

Blir nok en Arduino MKR 1010 WiFi siden jeg har en liggende og brukte en slik på "Ventil prosjketet"

 

Tar imot ALLE råd og kommentarer med stor takk!
Fint om andre gardin prosjekter også postes her 👇

 

  • Like 3
Lenke til kommentar
Del på andre sider

Bruker disse reed-switchene. De er litt store, så de vil nok bli byttet ut med noen mindre, men det var det eneste jeg fant som var hvite. Har så bare hekta på en magnet på strammeskrua for tråden (bruker også skinne fra jysk). Trekking av kabel til brytere gjorde jeg enkelt ved å henge en liten kabelkanal på siden mot veggen, da er det mer eller mindre usynlig. 

 

Jeg testa også en del med å telle steps og tid for å stoppe i hver ende, men jeg syns det ble for stor variasjon. Så jeg syns fordelene med endestopp og kabling utveier ulempene mtp kompleksitet og driftsikkerhet. Feks ved strømbrudd, så er det enkelt å selv-kalibrere posisjon. Det var hvertfall det jeg landet på den gang, men det kan jo ha litt å gjøre med programmerings kunnskapen min.😄

 

Følger spent med på hvordan du velger å løse dette 🙂

  • Like 1
Lenke til kommentar
Del på andre sider

Ja du har et poeng med strømstans. Har lest en del om det å rekke å lagre posisjonen i EEPROM'en til Arduinoen akkurat idet strømmen går.

Tenker at det at strømmen går MENS den beveger seg er ekstrems lite sannsynlig og at da får jeg heller justere den oppigjen på nytt.

Kanskje det holder å ta vare på posisjonen i hver ende så den husker om den var åpen eller lukket når strømmen kommer tilbake.

 

Dersom jeg klarer å lage det slik at mekanikken ikke slurer i vanlig bruk men tåler å "hoppe over" dersom den er feil vil den jo "korrigere seg selv" også :)

 

Jobber mest med det mekaniske nå men skal straks i gang med programmeringen. Tenker å kikke på MQTT siden WEB server programmeringen er ganske slitsom.

 

Men jeg har ingen erfaring med MQTT. 

Hvilken broaker er det HomeSeer folket kjører?
(Hvilken kjører du @Moskus ? )

Og hvilken MQTT plugin er den beste for HS?

Lenke til kommentar
Del på andre sider

1 minutt siden, Fermate skrev:

Hvilken broaker er det HomeSeer folket kjører?

Mosquitto. https://mosquitto.org/download/

 

1 minutt siden, Fermate skrev:

(Hvilken kjører du @Moskus ? )

Mosquitto.

 

1 minutt siden, Fermate skrev:

Og hvilken MQTT plugin er den beste for HS?

mscMQTT. Det er vel den eneste nå...?

 

Merk at mscMQTT kan faktisk være broker selv, hvis du ikke har en fra før. :) 

På kontoret kjører jeg noen WLED-striper og dingser, som styres fra en HS-instans på en Pi der. Fungerer utmerket uten egen broker.

  • Like 1
Lenke til kommentar
Del på andre sider

Og her er status på det mekaniske nå:

 

Er kommet meg ned i 30mm høyde på "snor motoren". Klaringen ned til lamellene er 35mm.
Ende-motoren må sitte der den sitter pga stanga.


image.png

 

Var fristet til å la "snortrekk motoren" sitte på veggen under "vri motoren" men valgte å forsøke å minimalisere hvor mye det må kuttes av skinnen for å få den inn i karmen.
Dette betyr at jeg muligens dropper "joystikken" av plasshensyn og kun går for 2 stykk knapper for å kunne åpne og lukke manuellt.
(Manuell kjøring blir jo bare til nødbruk uansett og all daglig manøvrering vil jo skje gjennom ALexa)


Er nok bedre å også kjøre konfigureringen med Alexa og finjustere posisjonene med knappene:

Alexa, Tell Homeseer to configure the Noth Curtain
HS setter den i "learn mode" og kvitterer med lysdiode 
Alexa: Please adjust the curtain to the left end.
Jeg bruker knappene til å kjøre gardinen helt til høyre og finjustere fram og tilbake til jeg er fornøyd.
Alexa, Tell Homeseer to continue the configuration
Alexa: Please adjust the curtain to the right end.
Lysdiode skifter farge og jeg justerer

osv osv til begge endene av begge motorene er konfigurert og lagret.

Så får vi se i praksis da ;)


 

Lenke til kommentar
Del på andre sider

19 minutter siden, Moskus skrev:

Merk at mscMQTT kan faktisk være broker selv, hvis du ikke har en fra før. :) 


Jeg har ingen fra før og ville kanskje kjørt den på samme PC som kjører HS (?)

Er den noen (annen) grunn til å kjøre den separat, kontra å bruke mscMQTT ?

 

Og hva bruker folket til å debugge MQTT med (kjøre manuelle komandoer etc)?

MQTT Explorer?

Lenke til kommentar
Del på andre sider

  • 2 uker senere...

I diskusjonen på hva har du automatiskert i dag kommenterte både @stigvi og @Mathias at 5V Steppermotorene ikke er kraftige.

Jeg mene at de var kraftige nok.

 

Jeg ser jo nå at jeg har kjørt "proof of concept" på en motor type og basert meg på at de stepperne (som jo er noe helt annet) er like bra.
Nå her jeg testet og DET ER DE IKKE :( -De orket ikke å dra gardinene og jeg må nå tenke omigjen på det konseptet som jeg hadde lagt så mange timer ned i :(

 

Jeg har bestillt noen 12V versjoner fra Kina men må nå bestemme meg for hvilken vei jeg skal gå.

 

  • Skal jeg vente på 12V versjonene?
  • Dersom jeg skal ha plass til den andre motoren må jeg gå bort fra ønsket om at alt dette skulle ligge BAK gardin-skinna og heller la den kommen ned på veggen, slik:

image.png

 

Men da har jeg ingen stepper motor lengre som jeg kan telle omdreininger på (så jeg slipper endebrytere)...
Og med denne store boksen her kunne jeg egentlig få plass til dette beistet her:

 

image.png

 

Sukk besluttninger besluttninger...

 

Lenke til kommentar
Del på andre sider

Men jeg har EN positiv nyhet da:

MQTT på Arduino er helt topp!

Jeg er blitt helt forelsket :)
Er ikke usannsynlig at jeg bytter ut softwaren på ventilprosjektet med MQTT versjon.

MEN jeg mener fremdeles at jeg burde få skjerpet meg til å skrive noe standard greier for å sette opp IP, SSID og PWD over et lite Web interface istedenfor å komplilere det inn i selve programmet. Slik som jeg snakker om her.
Er bare det at jeg aldri kom helt i mål med det. Kanskje det blir enklere når resten er MQTT og ikke WEB det også..

 

Lenke til kommentar
Del på andre sider

1 hour ago, Fermate said:

I diskusjonen på hva har du automatiskert i dag kommenterte både @stigvi og @Mathias at 5V Steppermotorene ikke er kraftige.

Jeg mene at de var kraftige nok.

 

Jeg ser jo nå at jeg har kjørt "proof of concept" på en motor type og basert meg på at de stepperne (som jo er noe helt annet) er like bra.
Nå her jeg testet og DET ER DE IKKE :( -De orket ikke å dra gardinene og jeg må nå tenke omigjen på det konseptet som jeg hadde lagt så mange timer ned i :(

 

 

Det var kjipt å høre! Er så fordømt frustrerende når man legger mye arbeid i noe som til slutt viser seg å ikke fungere som planlagt. Føler med deg der :) 

 

Samtidig setter jeg pris på at du oppdaterer oss på det. Nyttig info å få.

 

Jeg for min del fant ut at jeg, etter tilbakemeldinger fra dere, ville teste motoren på nytt med en god 12v-forsyning for å se om motoren ble sterkere. Og det ble den, men oppfatter fortsatt ikke motoren som så sterk at den kan dra noe som gir en del motstand, og iallefall ikke noe som har varierende motstand. Da mister den rakst posisjonen og hopper litt.

 

Jeg har nå noen trekanals releer med ESP-01 liggende og en mer solid 12v "vanlig" motor som jeg har lyst til å teste på et lignende prosjekt. Dog langt i fra like pent utført. For du skal ha for at du legger flid i utførelsen :) Må nok investere i en 3D-printer jeg også snart...

  • Like 1
Lenke til kommentar
Del på andre sider

20 timer siden, Fermate skrev:

MQTT på Arduino er helt topp!

Jepp! :D 

Det er bare enklere enn å måtte lage alt via HTTP calls selv, og dessuten er det realtime. :) 

 

Bestill noen NodeMCU'er eller ESP32'er også, hvis du likevel bare skal bruke wifi. Ingen vits i å bruke "dyre" Arduinoer... ;) 

  • Like 1
Lenke til kommentar
Del på andre sider

Men jeg trenger litt oppstarts hjelp på MQTT fra HS.
Finnes det noen guide her på forumet?

Er det foresten greit å kjøre Mosquitto Broakeren på samme PC som HS?

Bør jeg heller da la MQTT HS plugin'en være broaker?

Lenke til kommentar
Del på andre sider

Akkurat nå, Fermate skrev:

Er det foresten greit å kjøre Mosquitto Broakeren på samme PC som HS?

Ja, jeg gjør det.

 

Akkurat nå, Fermate skrev:

Bør jeg heller da la MQTT HS plugin'en være broaker?

Jeg har tenkt at det kan være greit å ha en egen broker i tilfelle det skulle gå mye data gjennom den, men jeg har ingen erfaringer om hvorfor...

 

 

1 minutt siden, Fermate skrev:

Men jeg trenger litt oppstarts hjelp på MQTT fra HS.
Finnes det noen guide her på forumet?

Nei, dessverre. Men det er bare å spørre.

 

Bartenderen min kjører på en NodeMCU med MQTT:

image.png

 

Det samme gjør den enkle lydmåleren min:

image.png

  • Like 1
Lenke til kommentar
Del på andre sider

På 1.5.2021 den 10.28, Moskus skrev:

Bestill noen NodeMCU'er eller ESP32'er også, hvis du likevel bare skal bruke wifi. Ingen vits i å bruke "dyre" Arduinoer...


Skal vi se: 2 Stepper motorer (det er 4 pinner hver) en RGB led (det er 3 til) og to trykkbrytere (det er 2 til) blir 13 
(Pluss jeg tenker egentlig 4 trykkbrytere kanskje så altså 15)
Hvilken Node MCU eller Esp32 modell tenker du på?

Lenke til kommentar
Del på andre sider

Jeg fikk inn 12V versjonen av den lille stepper moteren i dag og den er IKKE sterk nok til å dra gardinen.

Jeg har derfor foreløpig gått for DC Motor.

Da må jeg også ta tiden på den siden jeg ikke kan telle omdreininger så det blir en ekstra morsom utfordring :)

 

image.png

 

Fant ut at den tar ENDA litt mindre plass om jeg legger den på siden.

 

Det å tre snorene er noe pirk så jeg legger en del arbeid i at det skal bli så enkelt og tilgjengelig som mulig etter at greia er skrudd opp på veggen.

Regner jo med at det må justeres noen ganger....

 

Har fått igang MQTT på HS. Det var gøy. Må skrive en liten getting startet guide på det etterhvert..

 

image.png

  • Like 1
Lenke til kommentar
Del på andre sider

  • 3 uker senere...

For noen uker siden var neste prototype klar til test.
Den var super optimalisert på plass og hadde fått plass til trykk knapper for å styre den manuelt. (De henger i kablene på dette bildet)

Boksen som elektronikken skulle pakkes inn i var ikke klar men den var tiltenkt å ligge separat bak skinnen som en lang lav boks og kunne lages senere. Alt ble hektet sammen på en gardin som er montert på "braketter" slik at jeg kan teste: 

image.png

 

Alt ble kjørt med MQTT og devicer i HomeSeer og hadde følgende funksjoner:


image.png

 

Learn Devicen hadde følgende to funksjoner (men jeg har ikke funnet ut hvordan jeg får knapper på dem enda):

 

image.png

 

På de trykk-knappene kunne en da i "learn turn_start" mode, kjøre stepper motoren + / - til start punkt.
Når posisjonen var korrekt kvitetrte en med den 3dje knappen.
Antall stepp til det andre endepunktet kunne like godt hardkodes siden det ikke endret seg.

I "Learn pull_time" modus kom en føst i en mode for å justere startpunktet (altså + / - på DC motoren som drar gardinene) og så trykket en på den 3dje knappen som kjørte gardinen over mens den målte opp tiden det tok før du kvitterte igjen når den var helt over. Denne tiden ble lagret.

 

I drift modus var knappene:
1 Vri høyre
2 Vri venstre
3 Toggle åpne / lukke (ikke mulig å la gardinen stå halvåpen da det ikke gir noe mening for meg på panelgardiner)

 

Fra HS kunne en Åpne og Lukke og anngi vridning i %

 

Alle statuser ble lagret i Flash memony slik at dersom strømmen gikk kunne det hentes oppigjen når den kom tilbake.
(Dette vil da IKKE fungere dersom strømmen går akkurat når du kjører men det er akseptebelt (du må da kjøre LEARN på nytt))
 

Alt fungerte kjempefint bortsett fra EN liten ting:

59 sekrunder kjøring (skinna er ca 250 cm) av DC motor fra venstre til høyre var IKKE det samme som 59 sekunder andre veien :( :(  :(  
Det manglet 2-3 sekunder på tilbaketuren hver gang. Skitt!!!

Det var såpass regelmessig at det var fristende å bare kode inn 3 sekunder ekstra men perfeksjonisten i meg måtte bare innrømme:

Å bruke TIDEN som parameter holder desverre ikke.
Og jeg regner med at det å bruke en steppermotor og telle stepps vil gi samme problemet; det ligger i snora og friksjon og sånn. Synd!


OK Da må jeg inn med endebrytere i begge ender.
Back to the drawingboard...

brb

Lenke til kommentar
Del på andre sider

Jeg slenger alikevel ut kode for denne løsningen i tilfelle noen ønsker å se på den eller bruke den til noe annet. Den er 98% ferdig men ikke ryddet for å se profesjonell ut ... ;)
(Det er også lov å kommentere spørre eller kritisere)

Fikk 2 ESP32 av @Moskus i posten (han bestikker meg for at koden min skal bli kjørbar på hans billigere prosessorer ;) ) så det kan også hende at koden nå blir skrevet om til å kjøre mer rettet mot disse...

 

Sitat


#include <Stepper.h>
#include <ArduinoMqttClient.h>
#include <WiFiNINA.h>
#include <FlashStorage.h>

// Flash storage
FlashStorage(lastStatePull, int);
FlashStorage(lastStepperPos, int);
FlashStorage(lastStepperMaxPos, int);
FlashStorage(lastTimeForTotalPullMillis, unsigned long );

int lastSavedStatePull;
int lastSavedStepperPos;
int lastSavedStepperMaxPos;
unsigned long lastSavedTimeForTotalPullMillis;

unsigned long lastSaveTimeMillis=0;

// Buttons
const int buttonPin1 = A1;  
const int buttonPin2 = A2; 
const int buttonPin3 = A3;  
bool buttonUp = false; 
bool buttonDown = false;
bool buttonConfirm = false; 

// LED
const int ledPinRED =  6;       
const int ledPinGREEN =  7;       
const int ledPinBLUE =  13;       

// DC Motor
const int Motor1PinH =  0;       
const int Motor1PinV =  1;       

// Stepper
const int stepperPin1 =  2;       
const int stepperPin2 =  4;       
const int stepperPin3 =  3;       
const int stepperPin4 =  5;       
const int stepsPerRevolution = 32;   
Stepper Motor2(stepsPerRevolution, stepperPin1, stepperPin2, stepperPin3, stepperPin4);

int stepperPos = 0;
int targetStepperPos =0;
int stepperMaxPos = 3000; //minPos =0

//WiFi
char ssid[] = "espeland_ac";
char pass[] = "espelandnett";
WiFiClient wifiClient;

//MQTT
MqttClient mqttClient(wifiClient);
const char broker[]    = "192.168.232.8";
int        port        = 1883;
const char willTopic[] = "panelCurtain/will";
const char pullTopic[]   = "panelCurtain/pull"; // OPEN CLOSE
const char turnTopic[]   = "panelCurtain/turn"; // % 0 -100
const char learnTopic[]   = "panelCurtain/learn"; //  PULL_TIME SET_TURN_START SET_TURN_STOP TURN_ADJUST WRITE_FLASH READ_FLASH
const char statusTopic[]  = "panelCurtain/status"; // Open Close IsClosing ISOPENING
const char positionTopic[]  = "panelCurtain/position"; // 0-100


String willPayload = "oh no!";
bool willRetain = true;
int willQos = 1;
int subscribeQos = 1;

String payload;
bool retained = false;
int qos = 1;
bool dup = false;

// DIV
float x;
unsigned long startMillis;
unsigned long timeForTotalPullMillis =3000;

// States
enum _PullStates {
  ISOPEN,
  ISCLOSED,
  ISOPENING,
  ISCLOSING,
  WAIT_STARTTIMER,
  WAIT_STOPPTIMER
};

enum _TurnStates {
  TURNING_UP,
  TURNING_DOWN,
  TURN_ADJUST,
  TURNING_STOPPED
};

enum _motorCommandsTurn {
  TURN_UP,
  TURN_DOWN,
  TURN_STOP
};
enum _motorCommandsPull {
  PULL_OPEN,
  PULL_CLOSE,
  PULL_STOP
};

enum _PullStates statePull = ISOPEN;
enum _TurnStates stateTurn = TURNING_STOPPED;
enum _motorCommandsTurn motorTurn = TURN_STOP;
enum _motorCommandsPull motorPull = PULL_STOP;

// ********************************************************
void setup() {
// LED
  pinMode(ledPinRED, OUTPUT);
  pinMode(ledPinGREEN, OUTPUT);
  pinMode(ledPinBLUE, OUTPUT);
  ledAll();
// Serial
  Serial.begin(9600);
  startMillis=millis();
  while (!Serial && millis() - startMillis<3000) {
    delay(100);
  }
  Serial.println("begin init");
// Buttons 
  pinMode(buttonPin1, INPUT_PULLUP);
  pinMode(buttonPin2, INPUT_PULLUP);
  pinMode(buttonPin3, INPUT_PULLUP);
// DC Motor
  pinMode(Motor1PinH, OUTPUT);
  pinMode(Motor1PinV, OUTPUT);
// Stepper
  Motor2.setSpeed(1000);
  ledOff();
// Flash
  readFromFlash();  
  Serial.println("End init");
}

// ********************************************************

void loop() {
  //Save pos if changed
  testWriteToFlash();
  // Test WiFi
  connect_wifi();
  // Test MQTT
  connect_MQTT();
  //OK
  ledOff();
  // Poll MQTT
  mqttClient.poll();

  // read buttons 
  readButtons();

  // Update states for PULL
  if (statePull == WAIT_STOPPTIMER) {
    if (buttonConfirm && millis() - startMillis > 3000) { // stop the timing but after minimum 3 sek
      motorPull = PULL_STOP;
      timeForTotalPullMillis = millis() - startMillis;
      statePull = ISCLOSED;
      Serial.print("Button confirm pressed, Total pull time set to: "); Serial.println(timeForTotalPullMillis); Serial.println("Pull state = ISCLOSED");
    } // ignorer alle andre buttons
  } else if (statePull == WAIT_STARTTIMER) { 
    if (buttonUp) {
      Serial.println("Button H pressed");
      motorPull = PULL_CLOSE;
    } else if (buttonDown) {
      motorPull = PULL_OPEN;
      Serial.println("Button V pressed");
    } else if (buttonConfirm) { // start the timing
      motorPull = PULL_CLOSE;
      statePull = WAIT_STOPPTIMER;
      Serial.println("Button confirm pressed, Stating timer"); Serial.println("Pull state = WAIT_STOPPTIMER");
      startMillis = millis();
    } else  {
      motorPull = PULL_STOP;
    }
  } else { // da er vi i åpne lukke prod
    if (buttonConfirm && statePull == ISOPEN) { 
      motorPull = PULL_CLOSE;
      statePull = ISCLOSING;
      publishPullState();
      Serial.println("Button confirm pressed, Stating timer"); Serial.println("Pull state = ISCLOSING");
      startMillis = millis();    
    } else  if (buttonConfirm && statePull == ISCLOSED) {
      motorPull = PULL_OPEN;
      statePull = ISOPENING;
      publishPullState();
      Serial.println("Button confirm pressed, Stating timer"); Serial.println("Pull state = ISOPENING");
      startMillis = millis();    
    } // else er vi underveis og skal ikke gjøre noe
  }

  // Update states for Turning
  if (stateTurn == TURN_ADJUST) {
    if (buttonUp) {
      motorTurn = TURN_UP;
    } else if (buttonDown) {
      motorTurn = TURN_DOWN;
    } else if (buttonConfirm) {
      motorTurn = TURN_STOP;
      stepperPos =0;
      stateTurn=TURNING_STOPPED;
      publishTurnPos();
    } else {
      motorTurn = TURN_STOP;
    }
  } else if (stateTurn == TURNING_STOPPED) {
    if (buttonUp && stepperPos < stepperMaxPos) {
      motorTurn = TURN_UP;
    } else if (buttonDown && stepperPos > 0) {
      motorTurn = TURN_DOWN;
    } else {
      motorTurn = TURN_STOP;
    }
  } // else NOP as we are truning after an MQTT command

    
  // Execute Turn 
  ioMotorTurn();

  // Execute Pull
  ioMotorPull();

  // Check for Pull Stop
  if (statePull == ISCLOSING) {
    if (millis() - startMillis > timeForTotalPullMillis) {
      statePull = ISCLOSED;
      motorPull = PULL_STOP;
      publishPullState();
    }
  } else if (statePull == ISOPENING) {
    if (millis() - startMillis > timeForTotalPullMillis) {
      statePull = ISOPEN;
      motorPull = PULL_STOP;
      publishPullState();
    }
  }

  
  // Check for TURN stop
  if (stateTurn == TURNING_DOWN) {
    if (stepperPos <= 0 || stepperPos == targetStepperPos) {
      motorTurn = TURN_STOP;
      stateTurn = TURNING_STOPPED;
      publishTurnPos();
    }
  } else if (stateTurn == TURNING_UP) {
    if (stepperPos >= stepperMaxPos || stepperPos == targetStepperPos) {
      motorTurn = TURN_STOP;
      stateTurn = TURNING_STOPPED;
      publishTurnPos();
    }
  } else if (stateTurn == TURNING_STOPPED) {   
    motorTurn = TURN_STOP; // just in case :)
  }
}

// *************************************************************


void connect_wifi() {
  int wstatus;
  // WIFI
if (WiFi.status() != WL_CONNECTED) {
    
    Serial.print("Attempting to connect as wifi status is: ");
    Serial.println(WiFi.status());
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    delay(1000);
    ledRed();
    wstatus= WiFi.begin(ssid, pass);
    while (WiFi.status() != WL_CONNECTED) {
      // failed, retry
      delay(2000);
      ledOff();
      delay(1000);
      ledRed();
      wstatus= WiFi.begin(ssid, pass);
    Serial.print("Retried status:");
    Serial.println(wstatus); 
    }
    Serial.println("You're connected to the network");
  } 
}

void connect_MQTT() {
  if (!mqttClient.connected()) {
     ledBlue();
    // Will
    mqttClient.beginWill(willTopic, willPayload.length(), willRetain, willQos);
    mqttClient.print(willPayload);
    mqttClient.endWill();
    Serial.print("Attempting to connect to the MQTT broker: ");

    if (!mqttClient.connect(broker, port)) {
      Serial.print("MQTT connection failed! Error code = ");
      Serial.println(mqttClient.connectError());
    } else {
      Serial.println("You're connected to the MQTT broker!");
  
      mqttClient.onMessage(onMqttMessage); // set the message receive callback
  
      Serial.println("Subscribing to topics");
  
      mqttClient.subscribe(pullTopic, subscribeQos);
      mqttClient.subscribe(turnTopic, subscribeQos);
      mqttClient.subscribe(learnTopic, subscribeQos);
    } 
  } 
}
  

void onMqttMessage(int messageSize) {
  String buff;
  String topic;
  int i;
  Serial.print("Received a message with topic '");
  topic=mqttClient.messageTopic();
  Serial.print(topic);
  Serial.print("', duplicate = ");
  Serial.print(mqttClient.messageDup() ? "true" : "false");
  Serial.print(", QoS = ");
  Serial.print(mqttClient.messageQoS());
  Serial.print(", retained = ");
  Serial.print(mqttClient.messageRetain() ? "true" : "false");
  Serial.print("', length ");
  Serial.print(messageSize);
  Serial.println(" bytes:");

  // use the Stream interface to print the contents
  buff="";
  while (mqttClient.available()) {    
    buff+=(char)mqttClient.read();
  }
  Serial.print(topic);
  Serial.print("=");
  Serial.println(buff);

  // Turn
  if (topic.equalsIgnoreCase(turnTopic)) {
    i=buff.toInt();
    i=i*stepperMaxPos;
    targetStepperPos=i/100;
    if (targetStepperPos>stepperPos) {
      motorTurn = TURN_UP;
      stateTurn = TURNING_UP;
    } else if (targetStepperPos<stepperPos) {
      motorTurn = TURN_DOWN;
      stateTurn = TURNING_DOWN;
    } else { // equal
      motorTurn = TURN_STOP;
      stateTurn = TURNING_STOPPED;
    }
  }

// Pull
  if (topic.equalsIgnoreCase(pullTopic)) {
     if (buff.equalsIgnoreCase("STOPP")) {
       motorPull = PULL_STOP;
     } else if (buff.equalsIgnoreCase("OPEN")) {
       motorPull = PULL_OPEN;
       statePull= ISOPENING;
     } else if (buff.equalsIgnoreCase("CLOSE")) {
       motorPull = PULL_CLOSE;
       statePull= ISCLOSING;
     }
  }

// Learn  
  if (topic.equalsIgnoreCase(learnTopic)) {
    if (buff.equalsIgnoreCase("PULL_TIME")) {
       statePull = WAIT_STARTTIMER;
     } else if (buff.equalsIgnoreCase("TURN_ADJUST")) {
       Serial.println("Start Turning Adjust");
       stateTurn = TURN_ADJUST;
     } else if (buff.equalsIgnoreCase("SET_TURN_START")) {
       Serial.println("Start Turn pos set");
       stepperPos=0;
       stateTurn = TURNING_STOPPED;
     } else if (buff.equalsIgnoreCase("SET_TURN_STOP")) {
       stepperMaxPos = stepperPos;
       Serial.println("Turn Maxpos set to: ");
       Serial.println(stepperMaxPos);
       stateTurn = TURNING_STOPPED;
     }else if (buff.equalsIgnoreCase("READ_FLASH")) {
       readFromFlash();
     }else if (buff.equalsIgnoreCase("WRITE_FLASH")) {
       writeToFlash();
     }
  }

 }

void ioMotorPull() {
  if (motorPull == PULL_OPEN) {
    digitalWrite(Motor1PinH,HIGH);
    digitalWrite(Motor1PinV,LOW);
  } else if (motorPull == PULL_CLOSE){
    digitalWrite(Motor1PinH,LOW);
    digitalWrite(Motor1PinV,HIGH);
  } else {
    digitalWrite(Motor1PinH,HIGH);
    digitalWrite(Motor1PinV,HIGH);
  }
}

void ioMotorTurn(){
/*    Serial.print("Max ");
    Serial.println(stepperMaxPos);
    Serial.print("Target ");
    Serial.println(targetStepperPos);
    Serial.print("Current ");
    Serial.println(stepperPos);*/

  if (motorTurn == TURN_UP) {
      Motor2.step(1);
      stepperPos+=1;
  } else if (motorTurn == TURN_DOWN){
      Motor2.step(-1);
      stepperPos-=1;
  } else {
    digitalWrite(stepperPin1,LOW);
    digitalWrite(stepperPin2,LOW);
    digitalWrite(stepperPin3,LOW);
    digitalWrite(stepperPin4,LOW);
  }
}

 void led(int red, int green, int blue) {
  digitalWrite(ledPinRED, red);
  digitalWrite(ledPinGREEN, green);
  digitalWrite(ledPinBLUE, blue);
 }

 void ledOff() {
  led(LOW,LOW,LOW);
 }
 void ledRed() {
  led(HIGH,LOW,LOW);
 }
 void ledGreen() {
  led(LOW,HIGH,LOW);
 }
 void ledBlue() {
  led(LOW,LOW,HIGH);
 }
 void ledAll() {
  led(HIGH,HIGH,HIGH);
 }

void readButtons() {
  buttonDown = digitalRead(buttonPin1) == LOW; // bool
  buttonUp = digitalRead(buttonPin2) == LOW;
  buttonConfirm = digitalRead(buttonPin3) == LOW;
/*  if (buttonDown)   Serial.println("Button V");
  if (buttonUp)   Serial.println("Button H");
  if (buttonConfirm)   Serial.println("Button C");
*/
}

void publishPullState() {
  switch (statePull) {
    case ISOPEN: payload="ISOPEN"; break;
    case ISCLOSED: payload="ISCLOSED"; break;
    case ISOPENING: payload="ISOPENING"; break;
    case ISCLOSING: payload="ISCLOSING"; break;
    case WAIT_STARTTIMER: payload="WAIT_STARTTIMER"; break;
    case WAIT_STOPPTIMER: payload="WAIT_STOPPTIMER"; break;
  }
  mqttClient.beginMessage(statusTopic, payload.length(), retained, qos, dup);
  mqttClient.print(payload);
  mqttClient.endMessage();
  Serial.print("Publish Pull status: ");
  Serial.println(payload);
}

void publishTurnPos() {
  x=stepperPos;
  x=x/stepperMaxPos;
  x=x*100;
  payload=String(int(x));
  mqttClient.beginMessage(positionTopic, payload.length(), retained, qos, dup);
  mqttClient.print(payload);
  mqttClient.endMessage();
  Serial.print("Publish Stepper pos: ");
  Serial.print(stepperPos);
  Serial.print(" = %: ");
  Serial.println(x);
}

void readFromFlash() {
  if (lastStatePull.read() == 0) {
    statePull = ISOPEN;
  } else {
    statePull = ISCLOSED;
  }
  lastSavedStatePull = statePull ;
  Serial.print("Reading flash statePull ");
  Serial.println(statePull);
  if (statePull == 0) statePull=ISOPEN; // first time init
 
  stepperPos = lastStepperPos.read();
  lastSavedStepperPos = stepperPos ;
  Serial.print("Reading flash StepperPos ");
  Serial.println(stepperPos);
 
  stepperMaxPos = lastStepperMaxPos.read();
  lastSavedStepperMaxPos = stepperMaxPos ;
  Serial.print("Reading flash StepperMaxPos ");
  Serial.println(stepperMaxPos);
  if (stepperMaxPos == 0) stepperMaxPos=3000; // first time init
  
  timeForTotalPullMillis = lastTimeForTotalPullMillis.read();
  lastSavedTimeForTotalPullMillis = timeForTotalPullMillis;
  Serial.print("Reading flash TimeForTotalPullMillis ");
  Serial.println(timeForTotalPullMillis);
  if (timeForTotalPullMillis == 0) timeForTotalPullMillis=5000; // first time init

  lastSaveTimeMillis=millis(); // start counting from now
}

void testWriteToFlash() {
  if (motorTurn == TURN_STOP && motorPull == PULL_STOP) { // dont save whilie moving
    if (millis() - lastSaveTimeMillis > 120000) { // 2 minutes
      writeToFlash();
      lastSaveTimeMillis=millis();
    } 
  } 
}
void writeToFlash() {
  if (statePull != lastSavedStatePull) {
    if (statePull == ISOPEN) {
      lastStatePull.write(0);
    } else {
      lastStatePull.write(1);
    }
    lastSavedStatePull=statePull;
    Serial.print("Saving to flash statePull ");
    Serial.println(statePull);
  }

  if (stepperPos != lastSavedStepperPos) {
    lastStepperPos.write(stepperPos);
    lastSavedStepperPos=stepperPos;
    Serial.print("Saving to flash StepperPos ");
    Serial.println(stepperPos);
  }

  if (stepperMaxPos != lastSavedStepperMaxPos) {
    lastStepperMaxPos.write(stepperMaxPos);
    lastSavedStepperMaxPos=stepperMaxPos ;
    Serial.print("Saving to flash StepperMaxPos ");
    Serial.println(stepperMaxPos);
  }

  if (timeForTotalPullMillis != lastSavedTimeForTotalPullMillis) {
    lastTimeForTotalPullMillis.write(timeForTotalPullMillis);
    lastSavedTimeForTotalPullMillis=timeForTotalPullMillis ;
    Serial.print("Saving to flash TimeForTotalPullMillis ");
    Serial.println(timeForTotalPullMillis);
  } 
}

 

  • Like 1
  • Thanks 1
Lenke til kommentar
Del på andre sider

Du skrev tidligere om WiFi-konfigurasjon. Det er vel stor sannsynlighet for at du vet dette, men bare sånn i tilfelle... En av fordelene med NodeMCU, er jo at her har noen smarte folk kommet med løsninger som håndterer WiFi omtrent sånn du beskrev. Når devicen er nyprogrammert, eller resatt, oppretter den eget AP, som du kan koble opp mot og sette WiFi-parametere. Her kan du også ha config-mulighet for alle andre parametere, som MQTT broker osv. -Og firmware upgrade uten å måtte koble fra enheten. Den mest komplette implementasjonen jeg har sett, som selvfølgelig også bruker MQTT, er denne: GitHub - 1technophile/OpenMQTTGateway: MQTT gateway for ESP8266, ESP32, Sonoff RF Bridge or Arduino with bidirectional 433mhz/315mhz/868mhz, Infrared communications, BLE, beacons detection, mi flora, mi jia, LYWSD02, LYWSD03MMC, Mi Scale compatibility, SMS & LORA.

Den er modulær, og jeg tipper du kunne modifisert koden, for eksempel ved å lage en helt egen modul, til å passe til din bruk til gardinprosjektet.

Lenke til kommentar
Del på andre sider

Bli med i samtalen

Du kan publisere innhold nå og registrere deg senere. Hvis du har en konto, logg inn nå for å poste med kontoen din.

Gjest
Skriv svar til emnet...

×   Du har limt inn tekst med formatering.   Lim inn uten formatering i stedet

  Du kan kun bruke opp til 75 smilefjes.

×   Lenken din har blitt bygget inn på siden automatisk.   Vis som en ordinær lenke i stedet

×   Tidligere tekst har blitt gjenopprettet.   Tøm tekstverktøy

×   Du kan ikke lime inn bilder direkte. Last opp eller legg inn bilder fra URL.

×
×
  • Opprett ny...

Viktig informasjon

Vi har plassert informasjonskapsler/cookies på din enhet for å gjøre denne siden bedre. Du kan justere dine innstillinger for informasjonskapsler, ellers vil vi anta at dette er ok for deg.