Gå til innhold
  • Bli medlem

Siste blogginnlegg

Viser blogginnlegg skrevet i de siste 365 dager dager.

Denne strømmen auto-oppdateres

  1. Tidligere
  2. Han sa at han brukte 12V versjonen. Er det 5V du snakker om der? Kunne nok muligens gire den anderledes da? (Lage andre 3D tannhjul )
  3. Jeg gjorde en mye enklere variant, 12V PC-vifte, 12V Zigbee dimmer for LED. og styrer hastighet trinnløst via Home Assistant. At 50% på dimmere ikke blir 50%/6V hastighet er ikke sååå nøye. Noctuaene er fine på støynivå og finnes jo i både 12 og 14cm varianter. PWM-sensoren har jeg ikke bruk for. Jeg bruker øra for når vifta er "greit nok" på støy. Trenger ikke vite at den går på 789 rpm... Automasjon ble da ganske enkel. - For varmt (blås ut litt varme). - Inn med friskluft hvis det trengs=snu vifta. - Sier sensorer at det er for tørt inne? Hent inn litt uteluft! Vifta mi blåser ut da vi ikke trenger pollen inn i huset. Her setter da bare fantasien grenser for automasjonen.
  4. Det ser ut som et design som ligger på https://www.thingiverse.com/thing:2392856 Og jeg har laget den med en med en standard 28BYJ-48 stepper motor. Den er IKKE sterk nok
  5. Jon Olav Neset på FB IOT forumet postet dette designet. Jeg må si at det virker som en bedre teknisk løsning enn min:
  6. flott prosjekt.. har tenkt på det samme en stund da jeg har mange lignende gardiner :)
  7. Jeg har en del rullegardiner fra IKEA som er automatisert med Rollertol motorer. Her om dagen gikk en istykker og jeg hadde lite lyst til å bestille en ny fra USA. - Dyre er de også. Men jeg hadde nettop oppdaget hvor lett det er å designe og 3D printe tannhjul (Jeg bruker OnShape men regner med at Fusion 360 er like enkelt) så jeg tenkte at her var et fint byggeprosjekt. Jeg hadde kjøpt noen artige motorer fra Aliexpress for en stund siden som kunne passe til slikt bruk. https://www.aliexpress.com/item/32855724293.html Den jeg bruker her er 50RPM. Disse er giret kraftig ned med planet-gir og har rotasjons sensorer som gir 11 pulser / rotasjon. Dette gjør at de er mye sterkere enn en stepper motor men kan posisjoneres like nøyaktig ved å telle pulser. Fasongen inviterer til å plassere den i et klikk-on stativ som dette: (Slutt-versjonen måtte ha enda en klemme for å holde den helt fast) Tannhjulene ble laget for å kunne settes inn i enden av rullegardinen og et passende veggfeste ble printet: Siden det kun var et museklikk å lage tannhjulene heliske (skrå tenner) måtte jeg prøve dette. (Jeg hadde hørt at en gjorde slikt i girkasser for at de skulle lage mindre lyd) Dette ga meg to raske lærdommer: - Tannhjulene som skal gripe inn i hverandre må ha motsatt vinkling - Når de belastes vil de få en skyvekraft sidelengs Det siste bruker jeg nå aktivt for å forhindre at tannhjulet på motoren trekkes av akslingen når gardinen kjøres opp. Denne L298N motor-driveren tar 12V og er litt overdimensjonert men har også en 5V utgang som er fin å mate ESP32'en med. Jeg hadde bestemt meg for at jeg skulle ha 3 knapper: OPP, NED og SET I drift skulle knappene kjøre gardinen (helt) opp og (helt) ned og SET knappen skulle sette den i SETUP mode. I setup mode skulle knappene kjøre gardinen opp og ned så lenge de ble holdt inne. Først for å finne TOP posistion og så kvittere denne ved å trykke SET og deretter finne BUNN posisjonen og kvittere denne ved å trykke SET på nytt. En RGB LED skulle kommunisere hvilken modus du var i. Så var det bare å printe en passende boks, med skrue hull, for å putte hele greia inn i: Koblingen var sånn: For å unngå at jeg måtte sette oppigjen stopp posisjonene i topp og bunn dersom strømmen forsvant skrev jeg disse (=denne, top er uansett alltid 0) ned i Flash memory. Jeg bestemte derfor også at gardinen ikke skulle kunne stoppes halveis og kun var enten åpen eller lukket. Denne statusen (Oppe eller Nede) ble også skrevet til Flash. Flash tillater kun 100 000 skrivinger så om jeg kjører gardinen 3 ganger om dagen vil den kun holde i ca 100 år... Motor pulsene telles med et Interupt på pinne 25. Knappene bruker også en Interupt-timer for å slippe å håndtere rippel. For hver 100ms sjekker jeg om knappene er av eller på. Er de aktive teller jeg en teller OPP er de passive teller jeg en teller NED. Blir telleren 4 setter jeg knappen som AKTIV, blir den -4 setter jeg den som inaktiv. LED'en fikk kun en motstand felles (latskap) så den tåler ikke at mer enn en farge skrus på om gangen. Selve logikken er en tilstands maskin med disse tilstandene: SETUP_DEFINING_TOP, SETUP_DEFINING_BOTTOM, SETUP_STOP_SET_PRESSED_TOP, SETUP_STOP_SET_PRESSED_BOTTOM, MOVING, STOPPED_TOP, STOPPED_BOTTOM, STOP_SET_PRESSED I tillegg holdes det styr på rettning: MOVING_UP, MOVING_DOWN, STOPPED Da er det også enkelt å vite om pulsene som kommer fra motoren skal telles opp eller ned. Motoren har riktignok 2 sensorer som står i forskjellig vinkel på akslingen så det ville være mulig å måle avstanden mellom pulsene for å avgjøre rettning men dette er MYE lettere. MQTT biblioteket jeg fant var så enkelt å bruke at det nesten var latterlig. Jeg burde selvfølgelig rydde masse i koden og skrive pedagogiske kommentarer for å vise alle hva for en dreven og fantastisk programmerer jeg (egentlig) er men det gidder jeg ikke nå, sorry. Dere får heller spørre om dere lurer på noe. Jeg gadd heller ikke å lage noe fancy setup automatikk med oppstarts AP og Webside for å sette IP og velge SSID. (Post gjerne slik kode som jeg kan stjele til neste gang) Her er koden: #include <Preferences.h> #include <EspMQTTClient.h> Preferences preferanser; EspMQTTClient client( "SSID", "PWD", "192.168.232.8", // MQTT Broker server ip "", // MQTTUsername Can be omitted if not needed "", // MQTTPassword Can be omitted if not needed "rullegardinClient", // Client name that uniquely identify your device 1883 // The MQTT port, default to 1883. this line can be omitted ); // MQTT int receivedCommand=0; // 1=UP 2=Down 0=Executed // Motor int motorPin1 = 14; int motorPin2 = 12; int enablePin = 13; // Interupt portMUX_TYPE sync1 = portMUX_INITIALIZER_UNLOCKED; // External int IntPin1 = 25; // Timer hw_timer_t * timer = NULL; // Switches const int swPinUp = 23; const int swPinDown = 22; const int swPinStopSet = 21; volatile bool swUp = false; volatile bool swDown = false; volatile bool swStopSet = false; // LED const int RED = 5; const int BLUE = 18; const int GREEN = 19; // Modes enum stateType { SETUP_DEFINING_TOP, SETUP_DEFINING_BOTTOM, SETUP_STOP_SET_PRESSED_TOP, SETUP_STOP_SET_PRESSED_BOTTOM, MOVING, STOPPED_TOP, STOPPED_BOTTOM, STOP_SET_PRESSED, }; // Direction enum directionType { MOVING_UP, MOVING_DOWN, STOPPED }; //VARS volatile stateType state; volatile directionType movingDirection; volatile long stepCount=0; //0= På toppen volatile long stepMax=0; volatile int countUpSW =0; volatile int countDownSW = 0; volatile int countStopSetSW = 0; unsigned long lastTime=0; char lastPos; //------------- Interupt Routine Steps ----------------- void IRAM_ATTR isr_steps() { portENTER_CRITICAL(&sync1); if (movingDirection==MOVING_DOWN) { stepCount++; } else if (movingDirection==MOVING_UP) { stepCount--; } if (stepCount<0) stepCount=0 ; // cap on 0 portEXIT_CRITICAL(&sync1); } //------------- Interupt Routine Timer ----------------- void IRAM_ATTR isr_timer() { portENTER_CRITICAL(&sync1); if (digitalRead(swPinUp)==LOW) { countUpSW++; if (countUpSW > 4) { swUp = true; countUpSW=0; } } else { countUpSW--; if (countUpSW < -4) { swUp = false; countUpSW=0; } } if (digitalRead(swPinDown)==LOW) { countDownSW++; if (countDownSW > 4) { swDown = true; countDownSW=0; } } else { countDownSW--; if (countDownSW < -4) { swDown = false; countDownSW=0; } } if (digitalRead(swPinStopSet)==LOW) { countStopSetSW++; if (countStopSetSW > 4) { swStopSet = true; countStopSetSW=0; } } else { countStopSetSW--; if (countStopSetSW < -4) { swStopSet = false; countStopSetSW=0; } } portEXIT_CRITICAL(&sync1); } //************************* INIT ********************* void setup() { // LED pins pinMode(RED, OUTPUT); pinMode(GREEN, OUTPUT); pinMode(BLUE, OUTPUT); digitalWrite(RED, HIGH); preferanser.begin("Prefs",false); stepMax=preferanser.getLong("stepMax",-1); // -1= not init before if (stepMax==-1) { state=SETUP_DEFINING_TOP; } else { lastPos=preferanser.getChar("position",' '); if (lastPos=='T') { state=STOPPED_TOP; client.publish("rullegardin/position", "TOP"); } else if (lastPos=='B') { state=STOPPED_BOTTOM; client.publish("rullegardin/position", "BOTTOM"); } else { // error or default state=SETUP_DEFINING_TOP; } } // Motor pins pinMode(motorPin1, OUTPUT); pinMode(motorPin2, OUTPUT); pinMode(enablePin, OUTPUT); // init interupt pinMode(IntPin1, INPUT); attachInterrupt(IntPin1,&isr_steps,FALLING); // Interupt timer timer = timerBegin(0,240,true); // 240Mhz timerAttachInterrupt(timer,&isr_timer,true); timerAlarmWrite(timer, 100, true); // 100ms ? timerAlarmEnable(timer); // SW pinMode(swPinUp, INPUT_PULLUP); pinMode(swPinDown, INPUT_PULLUP); pinMode(swPinStopSet, INPUT_PULLUP); // Motor Enable digitalWrite(enablePin,HIGH ); // testing Serial.begin(9600); Serial.println("Testing DC Motor..."); client.enableDebuggingMessages(); client.enableLastWillMessage("rullegardin/lastwill", "I am going offline"); digitalWrite(RED, LOW); digitalWrite(GREEN, HIGH); digitalWrite(BLUE, LOW); } //*********************************** ROUTINES void move_down() { movingDirection=MOVING_DOWN; digitalWrite(motorPin1,HIGH); digitalWrite(motorPin2,LOW); } void move_up() { movingDirection=MOVING_UP; digitalWrite(motorPin1,LOW); digitalWrite(motorPin2,HIGH); } void stop_moving() { movingDirection=STOPPED; digitalWrite(motorPin1,LOW); digitalWrite(motorPin2,LOW); } void update_leds() { // LED if (state==SETUP_DEFINING_TOP){ digitalWrite(RED, LOW); digitalWrite(GREEN, HIGH); digitalWrite(BLUE, LOW); } if (state==SETUP_DEFINING_BOTTOM){ digitalWrite(RED, LOW); digitalWrite(GREEN, LOW); digitalWrite(BLUE, HIGH); } else { digitalWrite(RED, LOW); digitalWrite(GREEN, LOW); digitalWrite(BLUE, LOW); } } // ************************ LOOP *********************** void loop() { // MQTT client.loop(); // Debug if (millis()-lastTime>200) { Serial.print("State:"); Serial.print(state); Serial.print(" moving:"); Serial.print(movingDirection); Serial.print(" Cnt:"); Serial.print(stepCount); Serial.print(" Max:"); Serial.print(stepMax); Serial.print(" UP:"); Serial.print(swUp); Serial.print(" Dwn:"); Serial.print(swDown); Serial.print(" StopSet:"); Serial.print(swStopSet); Serial.println(""); lastTime=millis(); } update_leds(); // Final state machine // SETUP if (state==SETUP_DEFINING_TOP) { // -------------- if ((movingDirection==STOPPED) && swStopSet) { // Set top pos stepCount=0; state=SETUP_STOP_SET_PRESSED_TOP; } else if (swUp) { move_up(); } else if (swDown) { move_down(); } else { // no buttons pressed stop_moving(); } } else if (state==SETUP_DEFINING_BOTTOM) { // -------------- if ((movingDirection==STOPPED) && swStopSet) { // Set bottom pos stepMax=stepCount; preferanser.putLong("stepMax",stepMax); //save for next boot Serial.println("Saving stepMax"); state=SETUP_STOP_SET_PRESSED_BOTTOM; } else if (swUp) { move_up(); } else if (swDown) { move_down(); } else { // no buttons pressed stop_moving(); } } else if (state==SETUP_STOP_SET_PRESSED_TOP) { // -------------- if (!swStopSet) { // released state=SETUP_DEFINING_BOTTOM; } } else if (state==SETUP_STOP_SET_PRESSED_BOTTOM) { // -------------- if (!swStopSet) { // released move_up(); state=MOVING; } // NOT SETUP } else if (state==MOVING) { // -------------- if (swStopSet) { stop_moving(); state=SETUP_DEFINING_TOP; } else if (swUp) { move_up(); state=MOVING; } else if (swDown) { move_down(); state=MOVING; } // Ende stop? if (stepCount<=0 && movingDirection==MOVING_UP) { stop_moving(); preferanser.putChar("position",'T'); Serial.println("Saving Position = T"); state=STOPPED_TOP; client.publish("rullegardin/position", "TOP"); } else if (stepCount>stepMax && movingDirection==MOVING_DOWN) { stop_moving(); preferanser.putChar("position",'B'); Serial.println("Saving Position = B"); state=STOPPED_BOTTOM; client.publish("rullegardin/position", "BOTTOM"); } } else if (state==STOPPED_TOP) { // -------------- if (swDown) { move_down(); state=MOVING; } else if (swStopSet) { state=STOP_SET_PRESSED; } else if (receivedCommand==2) { move_down(); state=MOVING; receivedCommand=0; } } else if (state==STOPPED_BOTTOM) { // -------------- if (swStopSet) { state=STOP_SET_PRESSED; } else if (swUp) { move_up(); state=MOVING; } else if (receivedCommand==1) { move_up(); state=MOVING; receivedCommand=0; } } else if (state==STOP_SET_PRESSED) { // -------------- if (!swStopSet) { // release button state=SETUP_DEFINING_TOP; } } else { Serial.println("ERROR Unknown state"); } } void onConnectionEstablished() { // Subscribe to "mytopic/test" and display received message to Serial client.subscribe("rullegardin/command", [](const String & payload) { Serial.println(payload); receivedCommand=payload.toInt(); }); /* // Subscribe to "mytopic/wildcardtest/#" and display received message to Serial client.subscribe("mytopic/wildcardtest/#", [](const String & topic, const String & payload) { Serial.println("(From wildcard) topic: " + topic + ", payload: " + payload); }); */ // Publish a message to "mytopic/test" client.publish("rullegardin/position", "startUp"); // You can activate the retain flag by setting the third parameter to true /* // Execute delayed instructions client.executeDelayed(5 * 1000, []() { client.publish("mytopic/wildcardtest/test123", "This is a message sent 5 seconds later"); }); */ }
  8. Artig lite prosjekt. Har lenge vært inne på samme tanken og kom tilfeldig over denne nå. Jeg har også tenkt tanken på å bruke vifte men er fortsatt innstilt på å bruke servo til å åpne/lukke vinduet på soverommet da det er i kjelleretasjen med 25cm leca +10cm isolasjon med sponplater på innsiden og har ingen ventilåpning i veggen. For meg så er ikke sommerhalvåret et problem da husmor vinduet alltid står i luftestilling når jeg sover. Min utfordring er når det er kaldere en -5 om vinteren da har det en tendens til å bli litt for kaldt på soverommet. Har nå en esp8266 med 2 18B20 temp sensorer kjørende. Bruker Blynk (legacy) til å les av på mobilen plus at data sendes til thingspeak hvor jeg kan lese av temperatur historikken. Driver eksperimenterer for å finne ut hvordan jeg skal styre servoen for å åpne å lukke vinduet ut fra utvendig temperatur og innvendig temperatur. Vurderer også en løsning hvor vinduet åpnes og lukkes med jevne mellomrom også når det er kaldere en ønsket for å få frisk luft. en ting jeg lot merke til i din video var at du kjørte full fart på servoen. jeg har ikke planer om å kjøre høyere hastighet en jeg må for å få nok torque til å åpne og lukke vinduet. Du kan lett styre servo hastighet ved å trippe serven så den bare går en og en grad med en liten delay. Jeg har brukt det på mine persienner med kun små micro servoer som er skjult inni profilen. til å begynne med kjørte jeg ful speed og skremte vettet av både den ene og den andre under mine eksperiment eller skal jet si ekskeriment. Når servoene vrei persiennene kom det et vræl av en annen verden og kona trodde det var kommet inn en kat som noen hadde tråkka på. Men nå med tripping så hører du de knapt og bare ser de beveger seg. Har bestilt noen 26kg servoer som jeg har tenkt å bruke til å åpne soverom vinduet, regner med å få de til uka så da får vi se om de er sterke nok med lang nok servoarm til å greie å åpne til maks luftestilling. Har du noe automasjon på ditt opplegg eller er det bare stemmestyrt?
  9. Det vil ha klare fordeler å kunne velge mellom avtrekk og tilførsel. Det mest nærliggende behovet er koblet til høye verdier av radon og VOC på kontor og soverom. I utgangspunktet tenkte jeg veldig lokalt: det aktuelle rommet, men muligheten skal være der i å anlegge et slags balansert ventilasjonsanlegg med flere smarte vifter
  10. Hva er behovet du ønsker å løse? -fuktighet? -temperatur? -friskluft? -loft/kjeller? -soverom? -kjøkken? -bad? -stue? Disse har alle litt forskjellige utfordringer
  11. Mens vi venter på det eller tid til diy-prosjekter: har noen gode anbefalinger til vifte? Smart, eller som kan kobles på en kjekk smartifiseringsings? Ideelt, skal viften kunne gå begge veier. Eller er det vel bare å ha en vifte av enkleste sort, og montere av/på-smart-bryter på den.
  12. Jeg har effektivisert det der ved å slå sammen vaskerommet og garderoben til samme rom som en walk-in løsning, så forsvant den arbeids operasjonen der
  13. Jeg tror jeg ville klart det, ved å bruke god tid. Problemet er at det tar alt for mye tid. I hverdagen har jeg så vidt tid en gang i månefasen til å rydde bort rene klær på vaskerommet, så dette er ikke noe jeg prioriterer å fikle med med det første. Men veldig fascinerende!
  14. Hehe Som du sier er det såpass tidskrevende at det nok da vil bli for dyrt Men HVA av dette er det du ikke fikser selv? (Kanskje jeg bare trenger å bidra med noe av det?)
  15. Stilig! Noe slikt kunne jeg ønske meg, men det blir for avansert/tidkrevende for meg. Si ifra om du åpner for salg! 😁 Eeeventuelt: Hva vil folk anbefale av ferdigprodukter?
  1. Last inn mer aktivitet
×
×
  • Opprett ny...