Använder veckarklockor operatorer för att jämföra tid?

Permalänk

Använder veckarklockor operatorer för att jämföra tid?

Hej!

Jag har ett litet problem. Jag försöker bygga en klocka som ska öppna en grind vid en viss tidpunkt och stänga griden vid en viss tidpunkt.
Men då är problemen dessa:

  • Om man sätter Close_time efter midnatt

  • Om apparaten startar efter ett strömavbrott

Här är en del av min kod

// read the eeprom memory int open_hour = EEPROM.read(0); int open_minute = EEPROM.read(1); int close_hour = EEPROM.read(2); int close_minute = EEPROM.read(3); // Get real time DateTime current = RTC.now(); int hours = current.hour(); int minutes = current.minute(); if ((hours >= open_hour && minutes >= open_minute) || (hours < close_hour && minutes < close_minute)) { Gate_Open = 1; // Open the gate now! } else { Gate_Open = 0; // Close the gate now! }

Det blir inte exakt som jag har tänkt mig. För tanken med denna kodbilt är att:

(hours >= open_hour && minutes >= open_minute)

ska representera tiden mellan t.ex 08:00 till 23:59, fär 08:00 är tiden som grinden ska öppnas.

och denna kodbit ska representera mellan t.ex. 00:00 till 03:15 där tiden 03:15 är som grinden ska stängas.

hours < close_hour && minutes < close_minute

Det blir bara fel hur jag än vrider och vänder på det för kravspecifikationen är att:

  1. Griden ska öppnas vid en speciell angiven tid

  2. Grinden ska stängas vid en speciell angiven tid

  3. Om strömavbrott förekommit och strömavbrottet upphör men tiden är mellan öppning och stängdning så ska grinden öppnas

Typ som att mellan öppning t.ex. 08:15 och stägning t.ex. 20:00 eller 01:30 så ska griden vara öppen. Annars inte.
Då är min fråga på denna tråd: Är det lämpligt att använda operatorer eller måste man göra på något annat sätt?

Permalänk
99:e percentilen

Jag har löst samma problem i Better SweClockers genom att skriva en funktion timeIsBetween(time, start, end) som returnerar true om och endast om time är mellan start och end.

Du kan se i koden precis hur jag har gjort.

Visa signatur

Skrivet med hjälp av Better SweClockers

Permalänk
Medlem

Bara om hours = openhour måste minutes >= openminute. Annars returneras False för tiden 9:29 och öppningstid 8:30 (eftersom 29 < 30) när du egentligen vill att all tid över 8:30 fram till closetime ska vara True.

Är det inte lättare att omvandla samtliga tidsangivelser till en och samma typ så kan man enklare jämföra? Sedan får man visst skilja på om öppning kommer före stängning eller vice versa under dygnet.

// read the eeprom memory int open_hour = EEPROM.read(0); int open_minute = EEPROM.read(1); int close_hour = EEPROM.read(2); int close_minute = EEPROM.read(3); // Get real time DateTime current = RTC.now(); int hours = current.hour(); int minutes = current.minute(); // convert to minutes for easier comparison int open_in_minutes = 60 * open_hour + open_minute int close_in_minutes = 60 * close_hour + clos_minute int now_in_minutes = 60 * hours + minutes if (open_in_minutes > close_in_minutes) //Skriver som flera if-satser för läsbarhetens skull { if (now_in_minutes >= open_in_minutes) || (now_in_minutes < close_in_minutes) { Gate_Open = 1; // Open the gate now! } else { Gate_Open = 0; // Close the gate now! } } if (open_in_minutes <= close_in_minutes) { if (now_in_minutes >= open_in_minutes) && (now_in_minutes < close_in_minutes) { Gate_Open = 1; // Open the gate now! } else { Gate_Open = 0; // Close the gate now! } }

la till kodexempel
Permalänk
Skrivet av windblownsnow:

Bara om hours = openhour måste minutes >= openminute. Annars returneras False för tiden 9:29 och öppningstid 8:30 (eftersom 29 < 30) när du egentligen vill att all tid över 8:30 fram till closetime ska vara True.

Är det inte lättare att omvandla samtliga tidsangivelser till en och samma typ så kan man enklare jämföra? Sedan får man visst skilja på om öppning kommer före stängning eller vice versa under dygnet.

// read the eeprom memory int open_hour = EEPROM.read(0); int open_minute = EEPROM.read(1); int close_hour = EEPROM.read(2); int close_minute = EEPROM.read(3); // Get real time DateTime current = RTC.now(); int hours = current.hour(); int minutes = current.minute(); // convert to minutes for easier comparison int open_in_minutes = 60 * open_hour + open_minute int close_in_minutes = 60 * close_hour + clos_minute int now_in_minutes = 60 * hours + minutes if (open_in_minutes > close_in_minutes) //Skriver som flera if-satser för läsbarhetens skull { if (now_in_minutes >= open_in_minutes) || (now_in_minutes < close_in_minutes) { Gate_Open = 1; // Open the gate now! } else { Gate_Open = 0; // Close the gate now! } } if (open_in_minutes <= close_in_minutes) { if (now_in_minutes >= open_in_minutes) && (now_in_minutes < close_in_minutes) { Gate_Open = 1; // Open the gate now! } else { Gate_Open = 0; // Close the gate now! } }

Mycket bra!
Detta är nog löst. Jag har ändrat lite och lagt in kommentarer. Är det så här det ska fungera? Är det rätt kommenterat?

// convert to minutes for easier comparison int open_in_minutes = 60 * open_hour + open_minute; int close_in_minutes = 60 * close_hour + close_minute; int now_in_minutes = 60 * hours + minutes; int Gate_Open; if (open_in_minutes > close_in_minutes) // Exemple: 08:30 > 01:20 { if ((now_in_minutes >= open_in_minutes) || (now_in_minutes < close_in_minutes)) { // Example: Gate is open between e.g 09:30 >= 8:00 or 00:03 < 01:00 Gate_Open = 1; // Open the gate now! } else { Gate_Open = 0; // Close the gate now! } } if (open_in_minutes <= close_in_minutes) // Example: 08:30 < 23:00 { if ((now_in_minutes >= open_in_minutes) && (now_in_minutes < close_in_minutes)) { // Example: Gate is open between e.g 09:30 >= 08:30 and 09:30 < 23:45 Gate_Open = 1; // Open the gate now! } else { Gate_Open = 0; // Close the gate now! } }

Borde inte

open_in_minutes <= close_in_minutes)

stå istället så som

open_in_minutes < close_in_minutes) // removed =

?

Permalänk
Medlem

Precis så! Sen så går logiken att kondensera ihop såsom i Allings exempel i koden han länkade till (mycket elegant gjort!).

Angående sista "<= vs ==" så var det bara av ren omtanke att inte lämna "Gate_Open" odefinerat utifall att en användare skulle sätta open_time = close time. För allt jag vet kan detta vara user input och det skadar inte att ha i åtanke och veta vad som kommer att ske vid alla tänkbara angivna värden. Detta har förståss ingen praktisk betydelse om man enbart är intresserad av om Gate_Open = True, men vi behöver inte begränsa oss till ett sådant antagande - du kanske rent av vill lägga till flera kommandon som ska utföras om grinden inte ska vara öppen direkt i if-satsen, kod som du inte vill ska hoppas över bara för att open_time är varken större eller mindre än close_time.

Permalänk
Skrivet av windblownsnow:

Precis så! Sen så går logiken att kondensera ihop såsom i Allings exempel i koden han länkade till (mycket elegant gjort!).

Angående sista "<= vs ==" så var det bara av ren omtanke att inte lämna "Gate_Open" odefinerat utifall att en användare skulle sätta open_time = close time. För allt jag vet kan detta vara user input och det skadar inte att ha i åtanke och veta vad som kommer att ske vid alla tänkbara angivna värden. Detta har förståss ingen praktisk betydelse om man enbart är intresserad av om Gate_Open = True, men vi behöver inte begränsa oss till ett sådant antagande - du kanske rent av vill lägga till flera kommandon som ska utföras om grinden inte ska vara öppen direkt i if-satsen, kod som du inte vill ska hoppas över bara för att open_time är varken större eller mindre än close_time.

Detta tänkte jag inte på, om att open och close kan vara lika med varandra.

Detta var kanon. Jag tänkte lägga dit en analog tempgivare, TMP36. Den skulle se till så att grinden ej kan öppnas vid minusgrader eller stängas vid minusgrader när det är öppningstid. Men då kom jag på att temperaturen varierar ganska krafitgt på våren och hösten. Kan hända 20 grader plus minus på hösten.

Det är en hönsbursöppnare.

Hela min kod ser ut så här om du är nyfiken Den har även 7-segmentsdisplayer som styrs via LedControl.h

#include <LedControl.h> #include <Wire.h> #include <RTClib.h> #include <EEPROM.h> #define SET_TEMP 0 // Define an object RTC_DS1307 RTC; // inputs: DIN pin, CLK pin, LOAD pin. number of chips LedControl mydisplay = LedControl(8, 7, 6, 1); void setup() { mydisplay.shutdown(0, false); // turns on display mydisplay.setIntensity(0, 15); // 15 = brightest Wire.begin(); // Begin connection with SDA, SCL RTC.begin(); // Start RTC-library pinMode(13, OUTPUT); // Green LED pinMode(2, INPUT); digitalWrite(2, 1); // Relay-breake for OPEN pinMode(1, INPUT); digitalWrite(1, 1); // Relay-breake for CLOSE pinMode(9, OUTPUT); // OPEN-relay pinMode(10, OUTPUT); // CLOSE-relay digitalWrite(9, 1); digitalWrite(10, 1); // Two tiny red LED pinMode(5, OUTPUT); digitalWrite(5, 1); // Red LED pinMode(3, OUTPUT); digitalWrite(3, 0); // Red LED OFF // Green LED pinMode(4, OUTPUT); digitalWrite(4, 1); // Green LED ON if (!RTC.isrunning()) // If the RTC-module is not running { RTC.adjust(DateTime(__DATE__, __TIME__)); // Start it blink_LED(13); } } void loop() { /* This is casement state Show a analog value*/ int state = keypad(); // Get a state from keypad static int START; // START is default == 0 at the begining switch (state) { case 100: // Stop/Start ALL! Now we can e.g close/open hatch manualy blink_LED(13); START = stop_start(START); break; case 200: // Set Open hatch-time if (START == 1) { blink_LED(13); SetOpen(); } break; case 300: // Set Close hatch-time if (START == 1) { blink_LED(13); SetClose(); } break; case 400: // Open hatch manualy if (START == 1) { blink_LED(13); Open_Close(); } break; case 500: // Set time if (START == 1) { blink_LED(13); SetTime(); } break; default: // Nothing break; } // START == 0 means that we are in run mode if (START == 0) { show_clock(); // just show the clock check_time(); // if hatch shall open or not } } void SetTime() { mydisplay.setDigit(0, 0, 0, true); // display 0 mydisplay.setDigit(0, 1, 0, true); // -''- mydisplay.setDigit(0, 2, 0, true); // -''- mydisplay.setDigit(0, 3, 0, true); // -''- int abcd[4]; for(int i = 0; i <= 3; i++) { int state = keypad(); while(state == 600) { state = keypad(); // if state is 600, default. Loop this. if (state >= 10) { // Wrong button pressed. Only 0 to 9. state = 600; } delay(500); int tinyLED; if (tinyLED == 0) { digitalWrite(5, 1); // two tiny red LED ON tinyLED = 1; } else { digitalWrite(5, 0); tinyLED = 0; } } mydisplay.setDigit(0, i, state, true); delay(500); abcd[i] = state; // store } // The loop is done! // Set the time now! int hh = arraytoint(abcd[0], abcd[1]); int mm = arraytoint(abcd[2], abcd[3]); char time_str[10]; sprintf(time_str, "%02d:%02d:00", hh, mm); RTC.adjust(DateTime("Jan 01 2000", time_str)); // Start it blink_LED(13); } void Open_Close() { if(digitalRead(1) == 0 && digitalRead(2) == 1) { // Hatch is OPEN. int break_relay = 1; while(break_relay == 1) { digitalWrite(9, 0); // ON break_relay = digitalRead(2);// if 0, then breake } digitalWrite(9, 1); // OFF } else if (digitalRead(1) == 1 && digitalRead(2) == 0) { // Hatch is CLOSE int break_relay = 1; while(break_relay == 1) { digitalWrite(10, 0); // ON break_relay = digitalRead(1);// if 0, then breake } digitalWrite(10, 1); // OFF } else { digitalWrite(9, 1); // OFF digitalWrite(10, 1); // OFF } } void show_clock() { // Get the latest time DateTime current = RTC.now(); int hours = current.hour(); int minutes = current.minute(); if (hours >= 10 && minutes >= 10) { String str_hour = String(hours); String str_minutes = String(minutes); char buf_h[3]; char buf_m[3]; str_hour.toCharArray(buf_h, 3); str_minutes.toCharArray(buf_m, 3); int a = buf_h[0] - '0'; int b = buf_h[1] - '0'; int c = buf_m[0] - '0'; int d = buf_m[1] - '0'; mydisplay.setDigit(0, 0, a, true); mydisplay.setDigit(0, 1, b, true); mydisplay.setDigit(0, 2, c, true); mydisplay.setDigit(0, 3, d, true); } else if (hours < 10 && minutes >= 10) { String str_hour = String(hours); String str_minutes = String(minutes); char buf_h[3]; char buf_m[3]; str_hour.toCharArray(buf_h, 3); str_minutes.toCharArray(buf_m, 3); int a = buf_h[0] - '0'; int c = buf_m[0] - '0'; int d = buf_m[1] - '0'; mydisplay.setDigit(0, 0, 0, true); mydisplay.setDigit(0, 1, a, true); mydisplay.setDigit(0, 2, c, true); mydisplay.setDigit(0, 3, d, true); } else if (hours < 10 && minutes < 10) { String str_hour = String(hours); String str_minutes = String(minutes); char buf_h[3]; char buf_m[3]; str_hour.toCharArray(buf_h, 3); str_minutes.toCharArray(buf_m, 3); int a = buf_h[0] - '0'; int c = buf_m[0] - '0'; mydisplay.setDigit(0, 0, 0, true); mydisplay.setDigit(0, 1, a, true); mydisplay.setDigit(0, 2, 0, true); mydisplay.setDigit(0, 3, c, true); } else if (hours >= 10 && minutes < 10) { String str_hour = String(hours); String str_minutes = String(minutes); char buf_h[3]; char buf_m[3]; str_hour.toCharArray(buf_h, 3); str_minutes.toCharArray(buf_m, 3); int a = buf_h[0] - '0'; int b = buf_h[1] - '0'; int c = buf_m[0] - '0'; mydisplay.setDigit(0, 0, a, true); mydisplay.setDigit(0, 1, b, true); mydisplay.setDigit(0, 2, 0, true); mydisplay.setDigit(0, 3, c, true); } } void check_time() { // read the eeprom memory int open_hour = EEPROM.read(0); int open_minute = EEPROM.read(1); int close_hour = EEPROM.read(2); int close_minute = EEPROM.read(3); // Get real time DateTime current = RTC.now(); int hours = current.hour(); int minutes = current.minute(); // convert to minutes for easier comparison int open_in_minutes = 60 * open_hour + open_minute; int close_in_minutes = 60 * close_hour + close_minute; int now_in_minutes = 60 * hours + minutes; int Gate_Open; static int temp_LOCK; // if the gate is open and temperatur sinks below 0, the gate should not close. if (open_in_minutes > close_in_minutes) // Exemple: 08:30 > 01:20 { if ((now_in_minutes >= open_in_minutes) || (now_in_minutes < close_in_minutes)) { // Example: Gate is open between e.g 09:30 >= 8:00 or 00:03 < 01:00 Gate_Open = 1; // Open the gate now! } else { Gate_Open = 0; // Close the gate now! } } if (open_in_minutes <= close_in_minutes) // Example: 08:30 < 23:00 { if ((now_in_minutes >= open_in_minutes) && (now_in_minutes < close_in_minutes)) { // Example: Gate is open between e.g 09:30 >= 08:30 and 09:30 < 23:45 Gate_Open = 1; // Open the gate now! } else { Gate_Open = 0; // Close the gate now! } } if (Gate_Open == 1) // open time! { int break_relay = digitalRead(1); // if 0, then breake if (break_relay == 1) { digitalWrite(9, 0); // ON } else { digitalWrite(9, 1); // OFF // Now the gate is open } } else // close time! { int break_relay = digitalRead(2); if (break_relay == 1) { digitalWrite(10, 0); // ON } else { digitalWrite(10, 1); // OFF } } } void SetClose() { mydisplay.setDigit(0, 0, 0, true); // display 0 mydisplay.setDigit(0, 1, 0, true); // -''- mydisplay.setDigit(0, 2, 0, true); // -''- mydisplay.setDigit(0, 3, 0, true); // -''- int abcd[4]; for(int i = 0; i <= 3; i++) { int state = keypad(); while(state == 600) { state = keypad(); // if state is 600, default. Loop this. if (state >= 10) { // Wrong button pressed. Only 0 to 9. state = 600; } delay(500); int tinyLED; if (tinyLED == 0) { digitalWrite(5, 1); // two tiny red LED ON tinyLED = 1; } else { digitalWrite(5, 0); tinyLED = 0; } } mydisplay.setDigit(0, i, state, true); delay(500); abcd[i] = state; // store } // The loop is done! // Add the adcd array to EEPROM EEPROM.write(2, arraytoint(abcd[0], abcd[1])); // hour hh EEPROM.write(3, arraytoint(abcd[2], abcd[3])); // minute mm blink_LED(13); } void SetOpen() { mydisplay.setDigit(0, 0, 0, true); // display 0 mydisplay.setDigit(0, 1, 0, true); // -''- mydisplay.setDigit(0, 2, 0, true); // -''- mydisplay.setDigit(0, 3, 0, true); // -''- int abcd[4]; for(int i = 0; i <= 3; i++) { int state = keypad(); while(state == 600) { state = keypad(); // if state is 600, default. Loop this. if (state >= 10) { // Wrong button pressed. Only 0 to 9. state = 600; } delay(500); int tinyLED; if (tinyLED == 0) { digitalWrite(5, 1); // two tiny red LED ON tinyLED = 1; } else { digitalWrite(5, 0); tinyLED = 0; } } mydisplay.setDigit(0, i, state, true); delay(500); abcd[i] = state; // store } // The loop is done! // Add the adcd array to EEPROM EEPROM.write(0, arraytoint(abcd[0], abcd[1])); // hour hh EEPROM.write(1, arraytoint(abcd[2], abcd[3])); // minute mm blink_LED(13); } int stop_start(int START) { if (START == 1) { // Run mode START = 0; digitalWrite(4, 1); // Green LED ON digitalWrite(3, 0); // Red LED OFF } else { // Configuration mode START = 1; digitalWrite(4, 0); // Green LED OFF digitalWrite(3, 1); // Red LED ON } return START; } void blink_LED(int LED) { int A = 1; for (int i = 0; i <= 10; i++) { digitalWrite(LED, A); delay(100); if (A == 1) { A = 0; } else { A = 1; } } } int arraytoint(int x, int y) { String str_x = String(x); String str_y = String(y); String str_x_y = String(str_x + str_y); return str_x_y.toInt(); } int keypad() { int i = analogRead(0); // Get an analog value from keypad if (i < 1000 && i > 970) { // Stop button digitalWrite(13, 1); return 100; } else if (i < 930 && i > 900) { // 0 button digitalWrite(13, 1); return 0; } else if (i < 870 && i > 830) { // "Set Open hatch time" button digitalWrite(13, 1); return 200; } else if (i < 800 && i > 750) { // 9 button digitalWrite(13, 1); return 9; } else if (i < 730 && i > 700) { // 8 button digitalWrite(13, 1); return 8; } else if (i < 670 && i > 620) { // 7 button digitalWrite(13, 1); return 7; } else if (i < 600 && i > 550) { // "Set Close hatch time" button digitalWrite(13, 1); return 300; } else if (i < 530 && i > 480) { // 6 button digitalWrite(13, 1); return 6; } else if (i < 450 && i > 420) { // 5 button digitalWrite(13, 1); return 5; } else if (i < 410 && i > 380) { // Both 4 and 6 are pressed digitalWrite(13, 1); return 500; } else if (i < 360 && i > 320) { // 4 button digitalWrite(13, 1); return 4; } else if (i < 300 && i > 250) { // "Open/Close hatch manaly" button digitalWrite(13, 1); return 400; } else if (i < 200 && i > 150) { // 3 button digitalWrite(13, 1); return 3; } else if (i < 120 && i > 70) { // 2 button digitalWrite(13, 1); return 2; } else if (i < 50 && i >= 0) { // 1 button digitalWrite(13, 1); return 1; } else { // Do nothing digitalWrite(13, 0); return 600; } }

Permalänk
Medlem

Har kondenserat ner det lite (om jag inte är ute och cyklar med syntaxen? )
Exemplet nedan ger gate_open = true om now_m är "mellan" open_m och close_m

int now_m = hour() * 60 + minute(); int open_m = EEPROM.read(0) * 60 + EEPROM.read(1); int close_m = EEPROM.read(2) * 60 + EEPROM.read(3); bool gate_open = ((open_m > close_m) && ((now_m >=open_m) || (now_m < close_m))) || ((open_m < close_m) && (now_m >=open_m) && (now_m < close_m)); bool temp_ok = ("avläst temperatur" > "tröskelvärdet"); if (gate_open && temp_ok) { ; // Öppna grinden, skriv ner status för grinden vid ev. strömavbrott, osv }

Säg mig, jag kan inte så mycket om hönor men vill man inte själv vara närvarande när grinden stängs så ingen höna blir utelåst t.ex. om det blir kallt ute? I så fall är det ju endast väsentligt om det är tillräckligt varmt ute för att öppna automatiskt (trots att det är öppningstid).

Permalänk
Skrivet av windblownsnow:

Har kondenserat ner det lite (om jag inte är ute och cyklar med syntaxen? )
Exemplet nedan ger gate_open = true om now_m är "mellan" open_m och close_m

int now_m = hour() * 60 + minute(); int open_m = EEPROM.read(0) * 60 + EEPROM.read(1); int close_m = EEPROM.read(2) * 60 + EEPROM.read(3); bool gate_open = ((open_m > close_m) && ((now_m >=open_m) || (now_m < close_m))) || ((open_m < close_m) && (now_m >=open_m) && (now_m < close_m)); bool temp_ok = ("avläst temperatur" > "tröskelvärdet"); if (gate_open && temp_ok) { ; // Öppna grinden, skriv ner status för grinden vid ev. strömavbrott, osv }

Säg mig, jag kan inte så mycket om hönor men vill man inte själv vara närvarande när grinden stängs så ingen höna blir utelåst t.ex. om det blir kallt ute? I så fall är det ju endast väsentligt om det är tillräckligt varmt ute för att öppna automatiskt (trots att det är öppningstid).

Hmm...det blir lite svårt med just temperaturen. Om temperaturen går ned någon grad t.ex 1 grad så stängs grinden. Det är inte bra. Grinden måste öppnas en gång per dag när temperaturen är TRUE. Men om temperaturen blir FALSE så ska grinden inte stängas.

Jag tror att blanda in temperatur i detta kommer bara resultera svårigheter. Kan ju vara frost på morgonen, lite värme på förmiddagen och sedan uppsvägningar.

Höns är det bästa djuren som finns. Dom har en inbyggt klocka i sig och kliver upp och går och lägger sig vid en bestämmd tid. Dessa djur sköter verkligen sig själva. Bara släppa ut dem ut i skogen så går dem självmant och lägger sig på kvällen

Temperatur ska ju alltid bevakas. Och denna apparat ska ju inte bevakas något.

Permalänk
Medlem

Det är väl inga konstigheter egentligen, eller har jag missuppfattat grindens konstruktion? Måste den aktivt hållas öppen hela tiden? Har apparaten persisterande lagringsmedium för att skriva ner diverse olika saker?

if (gate_open && temp_ok) { ; // Dags att öppna } if (!gate_open) { ; // Dags att stänga }

Sedan undrar jag lite över delen där tiderna anges, vad jag kan se saknas begränsningar för felaktiga tidsangivelser som t.ex. 25:70 (hh:mm)

också undrar jag om man inte kan förenkla klockan som följande

void show_clock() { // Convert time to strings and add a leading "0" time_t t = now(); // store the current time in time variable t String str_hour = "0" + String(hour(t)); String str_minutes = "0" + String(minute(t)); // Take the last two digits from time / minutes, for example 023 -> 23, 09 -> 09 int a = str_hour.charAt(str_hour.length() - 1); int b = str_hour.charAt(str_hour.length()); int c = str_minutes.charAt(str_minutes.length() - 1); int d = str_minutes.charAt(str_minutes.length()); mydisplay.setDigit(0, 0, a, true); mydisplay.setDigit(0, 1, b, true); mydisplay.setDigit(0, 2, c, true); mydisplay.setDigit(0, 3, d, true); }

Permalänk

[QUOTE="windblownsnow;15112393"]Det är väl inga konstigheter egentligen, eller har jag missuppfattat grindens konstruktion? Måste den aktivt hållas öppen hela tiden? Har apparaten persisterande lagringsmedium för att skriva ner diverse olika saker?

if (gate_open && temp_ok) { ; // Dags att öppna } if (!gate_open) { ; // Dags att stänga }

[QUOTE]

Tanken är att om grinden har öpnnats ska den inte direkt stängas om en måln åker förbi och "kyler" ner temperatursensoren.
Om

break_relay = digitalRead(2);// if break_relay = 0, then breake

så betyder det att griden är fullt öppen. Är griden stängd så är digitalRead(2) = 1.

Citat:

Sedan undrar jag lite över delen där tiderna anges, vad jag kan se saknas begränsningar för felaktiga tidsangivelser som t.ex. 25:70 (hh:mm)

också undrar jag om man inte kan förenkla klockan som följande

void show_clock() { // Convert time to strings and add a leading "0" time_t t = now(); // store the current time in time variable t String str_hour = "0" + String(hour(t)); String str_minutes = "0" + String(minute(t)); // Take the last two digits from time / minutes, for example 023 -> 23, 09 -> 09 int a = str_hour.charAt(str_hour.length() - 1); int b = str_hour.charAt(str_hour.length()); int c = str_minutes.charAt(str_minutes.length() - 1); int d = str_minutes.charAt(str_minutes.length()); mydisplay.setDigit(0, 0, a, true); mydisplay.setDigit(0, 1, b, true); mydisplay.setDigit(0, 2, c, true); mydisplay.setDigit(0, 3, d, true); }

Jag har kopplat in en DS1307 RTC som sköter tiden åt mig
Den är superexakt! Dessutom så har den ett in byggt minne också så den kommer ihåg senaste tiden, än fast batteriet tog slut

Jag tror jag löste problemet

// check temperature boolean temp = getTemp(); if (Gate_Open == 1 && temp == true && LOCK == 0) { // It's opening time, the temp is OK and the gate is not open Gate_Open = 1; // Gate should be open } else // if temp is not true and gate is open { if (LOCK == 1 && Gate_Open == 1) // gate is already open { Gate_Open == 1; // Gate should be open } else // Gate is not already open { Gate_Open = 0; // Gate should be closed } }

Jag har placerat denna kod i min stora kod. Tror du att denna fungerar? Jag har skapat nu en linjärisering i getTemp();

Notera

LOCK = 0; // The gate is now 100 % closed

#include <LedControl.h> #include <Wire.h> #include <RTClib.h> #include <EEPROM.h> #define SET_TEMP 0 // Define an object RTC_DS1307 RTC; // inputs: DIN pin, CLK pin, LOAD pin. number of chips LedControl mydisplay = LedControl(8, 7, 6, 1); void setup() { mydisplay.shutdown(0, false); // turns on display mydisplay.setIntensity(0, 15); // 15 = brightest Wire.begin(); // Begin connection with SDA, SCL RTC.begin(); // Start RTC-library pinMode(13, OUTPUT); // Green LED pinMode(2, INPUT); digitalWrite(2, 1); // Relay-breake for OPEN pinMode(1, INPUT); digitalWrite(1, 1); // Relay-breake for CLOSE pinMode(9, OUTPUT); // OPEN-relay pinMode(10, OUTPUT); // CLOSE-relay digitalWrite(9, 1); digitalWrite(10, 1); // Two tiny red LED pinMode(5, OUTPUT); digitalWrite(5, 1); // Red LED pinMode(3, OUTPUT); digitalWrite(3, 0); // Red LED OFF // Green LED pinMode(4, OUTPUT); digitalWrite(4, 1); // Green LED ON if (!RTC.isrunning()) // If the RTC-module is not running { RTC.adjust(DateTime(__DATE__, __TIME__)); // Start it blink_LED(13); } } void loop() { /* This is casement state Show a analog value*/ int state = keypad(); // Get a state from keypad static int START; // START is default == 0 at the begining switch (state) { case 100: // Stop/Start ALL! Now we can e.g close/open hatch manualy blink_LED(13); START = stop_start(START); break; case 200: // Set Open hatch-time if (START == 1) { blink_LED(13); SetOpen(); } break; case 300: // Set Close hatch-time if (START == 1) { blink_LED(13); SetClose(); } break; case 400: // Open hatch manualy if (START == 1) { blink_LED(13); Open_Close(); } break; case 500: // Set time if (START == 1) { blink_LED(13); SetTime(); } break; default: // Nothing break; } // START == 0 means that we are in run mode if (START == 0) { show_clock(); // just show the clock check_time(); // if hatch shall open or not } } void SetTime() { mydisplay.setDigit(0, 0, 0, true); // display 0 mydisplay.setDigit(0, 1, 0, true); // -''- mydisplay.setDigit(0, 2, 0, true); // -''- mydisplay.setDigit(0, 3, 0, true); // -''- int abcd[4]; for(int i = 0; i <= 3; i++) { int state = keypad(); while(state == 600) { state = keypad(); // if state is 600, default. Loop this. if (state >= 10) { // Wrong button pressed. Only 0 to 9. state = 600; } delay(500); int tinyLED; if (tinyLED == 0) { digitalWrite(5, 1); // two tiny red LED ON tinyLED = 1; } else { digitalWrite(5, 0); tinyLED = 0; } } mydisplay.setDigit(0, i, state, true); delay(500); abcd[i] = state; // store } // The loop is done! // Set the time now! int hh = arraytoint(abcd[0], abcd[1]); int mm = arraytoint(abcd[2], abcd[3]); char time_str[10]; sprintf(time_str, "%02d:%02d:00", hh, mm); RTC.adjust(DateTime("Jan 01 2000", time_str)); // Start it blink_LED(13); } void Open_Close() { if(digitalRead(1) == 0 && digitalRead(2) == 1) { // Hatch is OPEN. int break_relay = 1; while(break_relay == 1) { digitalWrite(9, 0); // ON digitalWrite(10, 1); // OFF break_relay = digitalRead(2);// if 0, then breake } digitalWrite(9, 1); // OFF } else if (digitalRead(1) == 1 && digitalRead(2) == 0) { // Hatch is CLOSE int break_relay = 1; while(break_relay == 1) { digitalWrite(10, 0); // ON digitalWrite(9, 1); // OFF break_relay = digitalRead(1);// if 0, then breake } digitalWrite(10, 1); // OFF } else { digitalWrite(9, 1); // OFF digitalWrite(10, 1); // OFF } } void show_clock() { // Get the latest time DateTime current = RTC.now(); int hours = current.hour(); int minutes = current.minute(); if (hours >= 10 && minutes >= 10) { String str_hour = String(hours); String str_minutes = String(minutes); char buf_h[3]; char buf_m[3]; str_hour.toCharArray(buf_h, 3); str_minutes.toCharArray(buf_m, 3); int a = buf_h[0] - '0'; int b = buf_h[1] - '0'; int c = buf_m[0] - '0'; int d = buf_m[1] - '0'; mydisplay.setDigit(0, 0, a, true); mydisplay.setDigit(0, 1, b, true); mydisplay.setDigit(0, 2, c, true); mydisplay.setDigit(0, 3, d, true); } else if (hours < 10 && minutes >= 10) { String str_hour = String(hours); String str_minutes = String(minutes); char buf_h[3]; char buf_m[3]; str_hour.toCharArray(buf_h, 3); str_minutes.toCharArray(buf_m, 3); int a = buf_h[0] - '0'; int c = buf_m[0] - '0'; int d = buf_m[1] - '0'; mydisplay.setDigit(0, 0, 0, true); mydisplay.setDigit(0, 1, a, true); mydisplay.setDigit(0, 2, c, true); mydisplay.setDigit(0, 3, d, true); } else if (hours < 10 && minutes < 10) { String str_hour = String(hours); String str_minutes = String(minutes); char buf_h[3]; char buf_m[3]; str_hour.toCharArray(buf_h, 3); str_minutes.toCharArray(buf_m, 3); int a = buf_h[0] - '0'; int c = buf_m[0] - '0'; mydisplay.setDigit(0, 0, 0, true); mydisplay.setDigit(0, 1, a, true); mydisplay.setDigit(0, 2, 0, true); mydisplay.setDigit(0, 3, c, true); } else if (hours >= 10 && minutes < 10) { String str_hour = String(hours); String str_minutes = String(minutes); char buf_h[3]; char buf_m[3]; str_hour.toCharArray(buf_h, 3); str_minutes.toCharArray(buf_m, 3); int a = buf_h[0] - '0'; int b = buf_h[1] - '0'; int c = buf_m[0] - '0'; mydisplay.setDigit(0, 0, a, true); mydisplay.setDigit(0, 1, b, true); mydisplay.setDigit(0, 2, 0, true); mydisplay.setDigit(0, 3, c, true); } } boolean getTemp() { int reading = analogRead(1); // analog pin 1 float voltage = reading * 5.0; voltage = voltage/1024; float temperatureC = (voltage - 0.5) * 100; if (temperatureC > SET_TEMP) // #definie SET_TEMP 0 { return true; } else { return false; } } void check_time() { // read the eeprom memory int open_hour = EEPROM.read(0); int open_minute = EEPROM.read(1); int close_hour = EEPROM.read(2); int close_minute = EEPROM.read(3); // Get real time DateTime current = RTC.now(); int hours = current.hour(); int minutes = current.minute(); // convert to minutes for easier comparison int open_in_minutes = 60 * open_hour + open_minute; int close_in_minutes = 60 * close_hour + close_minute; int now_in_minutes = 60 * hours + minutes; int Gate_Open; static int LOCK; // if the gate is open and temperatur sinks below 0, the gate should not close. if (open_in_minutes > close_in_minutes) // Exemple: 08:30 > 01:20 { if ((now_in_minutes >= open_in_minutes) || (now_in_minutes < close_in_minutes)) { // Example: Gate is open between e.g 09:30 >= 8:00 or 00:03 < 01:00 Gate_Open = 1; // Open the gate now! } else { Gate_Open = 0; // Close the gate now! } } if (open_in_minutes <= close_in_minutes) // Example: 08:30 < 23:00 { if ((now_in_minutes >= open_in_minutes) && (now_in_minutes < close_in_minutes)) { // Example: Gate is open between e.g 09:30 >= 08:30 and 09:30 < 23:45 Gate_Open = 1; // Open the gate now! } else { Gate_Open = 0; // Close the gate now! } } // check temperature boolean temp = getTemp(); if (Gate_Open == 1 && temp == true && LOCK == 0) { // It's opening time, the temp is OK and the gate is not open Gate_Open = 1; // Gate should be open } else // if temp is not true and gate is open { if (LOCK == 1 && Gate_Open == 1) // gate is already open { Gate_Open == 1; // Gate should be open } else // Gate is not already open { Gate_Open = 0; // Gate should be closed } } if (Gate_Open == 1) // open time! { int break_relay = digitalRead(1); // if 0, then breake if (break_relay == 0) { LOCK = 1; // The gate is full open } else { LOCK = 0; // The gate is not full open } if (break_relay == 1) { digitalWrite(9, 0); // ON digitalWrite(10, 1); // OFF - just for sure } else { digitalWrite(9, 1); // OFF // Now the gate is open } } else // close time! { int break_relay = digitalRead(2); if (break_relay == 1) { digitalWrite(10, 0); // ON digitalWrite(9, 1); // OFF - just for sure } else { digitalWrite(10, 1); // OFF LOCK = 0; // The gate is now 100 % closed } } } void SetClose() { mydisplay.setDigit(0, 0, 0, true); // display 0 mydisplay.setDigit(0, 1, 0, true); // -''- mydisplay.setDigit(0, 2, 0, true); // -''- mydisplay.setDigit(0, 3, 0, true); // -''- int abcd[4]; for(int i = 0; i <= 3; i++) { int state = keypad(); while(state == 600) { state = keypad(); // if state is 600, default. Loop this. if (state >= 10) { // Wrong button pressed. Only 0 to 9. state = 600; } delay(500); int tinyLED; if (tinyLED == 0) { digitalWrite(5, 1); // two tiny red LED ON tinyLED = 1; } else { digitalWrite(5, 0); tinyLED = 0; } } mydisplay.setDigit(0, i, state, true); delay(500); abcd[i] = state; // store } // The loop is done! // Add the adcd array to EEPROM EEPROM.write(2, arraytoint(abcd[0], abcd[1])); // hour hh EEPROM.write(3, arraytoint(abcd[2], abcd[3])); // minute mm blink_LED(13); } void SetOpen() { mydisplay.setDigit(0, 0, 0, true); // display 0 mydisplay.setDigit(0, 1, 0, true); // -''- mydisplay.setDigit(0, 2, 0, true); // -''- mydisplay.setDigit(0, 3, 0, true); // -''- int abcd[4]; for(int i = 0; i <= 3; i++) { int state = keypad(); while(state == 600) { state = keypad(); // if state is 600, default. Loop this. if (state >= 10) { // Wrong button pressed. Only 0 to 9. state = 600; } delay(500); int tinyLED; if (tinyLED == 0) { digitalWrite(5, 1); // two tiny red LED ON tinyLED = 1; } else { digitalWrite(5, 0); tinyLED = 0; } } mydisplay.setDigit(0, i, state, true); delay(500); abcd[i] = state; // store } // The loop is done! // Add the adcd array to EEPROM EEPROM.write(0, arraytoint(abcd[0], abcd[1])); // hour hh EEPROM.write(1, arraytoint(abcd[2], abcd[3])); // minute mm blink_LED(13); } int stop_start(int START) { if (START == 1) { // Run mode START = 0; digitalWrite(4, 1); // Green LED ON digitalWrite(3, 0); // Red LED OFF } else { // Configuration mode START = 1; digitalWrite(4, 0); // Green LED OFF digitalWrite(3, 1); // Red LED ON } return START; } void blink_LED(int LED) { int A = 1; for (int i = 0; i <= 10; i++) { digitalWrite(LED, A); delay(100); if (A == 1) { A = 0; } else { A = 1; } } } int arraytoint(int x, int y) { String str_x = String(x); String str_y = String(y); String str_x_y = String(str_x + str_y); return str_x_y.toInt(); } int keypad() { int i = analogRead(0); // Get an analog value from keypad if (i < 1000 && i > 970) { // Stop button digitalWrite(13, 1); return 100; } else if (i < 930 && i > 900) { // 0 button digitalWrite(13, 1); return 0; } else if (i < 870 && i > 830) { // "Set Open hatch time" button digitalWrite(13, 1); return 200; } else if (i < 800 && i > 750) { // 9 button digitalWrite(13, 1); return 9; } else if (i < 730 && i > 700) { // 8 button digitalWrite(13, 1); return 8; } else if (i < 670 && i > 620) { // 7 button digitalWrite(13, 1); return 7; } else if (i < 600 && i > 550) { // "Set Close hatch time" button digitalWrite(13, 1); return 300; } else if (i < 530 && i > 480) { // 6 button digitalWrite(13, 1); return 6; } else if (i < 450 && i > 420) { // 5 button digitalWrite(13, 1); return 5; } else if (i < 410 && i > 380) { // Both 4 and 6 are pressed digitalWrite(13, 1); return 500; } else if (i < 360 && i > 320) { // 4 button digitalWrite(13, 1); return 4; } else if (i < 300 && i > 250) { // "Open/Close hatch manaly" button digitalWrite(13, 1); return 400; } else if (i < 200 && i > 150) { // 3 button digitalWrite(13, 1); return 3; } else if (i < 120 && i > 70) { // 2 button digitalWrite(13, 1); return 2; } else if (i < 50 && i >= 0) { // 1 button digitalWrite(13, 1); return 1; } else { // Do nothing digitalWrite(13, 0); return 600; } }

Permalänk

Det fungerar halvt.

// check temperature int temp = getTemp(); if (Gate_Open == 1 && temp == 1 && LOCK == 0) { blink_LED(13); // It's opening time, the temp is OK and the gate is not open Gate_Open = 1; // Gate should be open } else // if temp is not true and gate is open { if (LOCK == 1 && Gate_Open == 1) // gate is already open { Gate_Open == 1; // Gate should be open } else // Gate is not already open { Gate_Open = 0; // Gate should be closed } }

Av någon kostig anledning så retunerar getTemp(); alltid 1

Permalänk

Jag har fixat det. Det vara digitalRead som hade fel input. Det skulle vara en 3:a.

Men det är riskabelt att låta temperatur avgöra och ha ett litet lås så att om temperaturen går ned så stängs inte luckan. Det är svårt att programmera in i min kod. Jag får nog nöja mig så här

Jag kommer dock sätta dit en knapp så man kan stänga av den i fall man inte vill att grinden ska åka upp på vintern.

Permalänk
Hedersmedlem

Hade du ingen möjlighet att spara information (ens i globala variabler eller så)? Det räcker väl att kontrollera temperaturen just när klockan passerar öppningstiden och sedan komma ihåg om det var bra eller dåligt?

Permalänk
Medlem

Syftade främst på if-satserna i "void show_clock()" pga en/tvåsiffriga tal för hh:mm, går att använda string.length för att få ut de "sista två" siffrorna, då kan man t.ex. alltid lägga till en ledande nolla i början så att det alltid finns åtminstone två siffror att ta av, t.ex. |08, 0|22 osv.

Du vill skilja på "gate_open = true" som "nu stämmer det att det enligt schemat är dags för grinden att vara öppen" samt själva funktionen som utför själva öppnandet. Därför bör också resultatet av temperaturkollen inte beblandas med resultatet av gate_open (som vi konstaterade enbart var tidsschemat för grindarna) - istället använder vi det som ett ytterligare villkor i själva funktionen som öppnar grinden, utan att omnämnas vid stängningsdags.

Då lyder som följande:

void check_time() { // Check if now is between open / close time int now_m = hour() * 60 + minute(); int open_m = EEPROM.read(0) * 60 + EEPROM.read(1); int close_m = EEPROM.read(2) * 60 + EEPROM.read(3); bool gate_open = ((open_m > close_m) && ((now_m >=open_m) || (now_m < close_m))) || ((open_m < close_m) && ((now_m >=open_m) && (now_m < close_m))); // check that temperature is ok bool temp_ok = getTemp(); // open gate depending on time and temperature if (gate_open && temp_ok) { if (digitalRead(1) == 1 && digitalRead(2) == 0) { // digiRead(1) true && (digiRead(2) false) means that the hatch is CLOSED. int break_relay = 1; while(break_relay == 1) { digitalWrite(10, 0); // ON -> opening hatch until its fully open digitalWrite(9, 1); // OFF break_relay = digitalRead(1);// if 0, then the stop has been reached, escaping while-loop } digitalWrite(10, 1); // OFF -> stops opening the hatch } else { // if the gate is already open, do nothing digitalWrite(9, 1); // OFF -> stops closing the hatch digitalWrite(10, 1); // OFF -> stops opening the hatch } } // close gate based only on time and not temperature if (!gate_open) { if(digitalRead(1) == 0 && digitalRead(2) == 1) { // (digiRead(1) false) && digiRead(2) true means that the hatch is OPEN. int break_relay = 1; while(break_relay == 1) { digitalWrite(9, 0); // ON -> closing hatch until its fully closed digitalWrite(10, 1); // OFF break_relay = digitalRead(2);// if 0, then the stop has been reached, escaping while-loop } digitalWrite(9, 1); // OFF -> stops closing the hatch } else { // if the gate is already closed, do nothing digitalWrite(9, 1); // OFF -> stops closing the hatch digitalWrite(10, 1); // OFF -> stops opening the hatch } } }

Har saxat öppnandet/stängandet från "void Open_Close()", undrar varför 1 står för OFF och 0 för ON, ser bakvänt ut men det kanske är kopplat för att vara så? Eftersom Open_Close() läser av om grinden är öppen/stängd och växlar däremellan vid manuell knapptryckning skulle det nämligen inte märkas på funktionen om 1 och 0 blivit konsekvent inverterade. Jag får dock tillägga att jag är urkass på elektronik och reläer osv

Permalänk
Skrivet av Elgot:

Hade du ingen möjlighet att spara information (ens i globala variabler eller så)? Det räcker väl att kontrollera temperaturen just när klockan passerar öppningstiden och sedan komma ihåg om det var bra eller dåligt?

Jag har fixat det nu!

windblownsnow: Lyssna du också på detta

Jag hade först

if (gate open) { open gate } else { close gate }

Nu har jag

temp(); // get temp if (gate open && temp OK) { open gate } if (gate close) { close gate }

Blev så mycket enklare när jag tog bord else ur if-satsen och bara körde if-sats.

Permalänk
Skrivet av windblownsnow:

Har saxat öppnandet/stängandet från "void Open_Close()", undrar varför 1 står för OFF och 0 för ON, ser bakvänt ut men det kanske är kopplat för att vara så? Eftersom Open_Close() läser av om grinden är öppen/stängd och växlar däremellan vid manuell knapptryckning skulle det nämligen inte märkas på funktionen om 1 och 0 blivit konsekvent inverterade. Jag får dock tillägga att jag är urkass på elektronik och reläer osv

När digitalRead(1) blir 0 så betyder det att det finns slutning.
Det är jag som har gjort det så där.

pinMode(2, INPUT); digitalWrite(2, 1); // Relay-breake for OPEN pinMode(1, INPUT); digitalWrite(1, 1); // Relay-breake for CLOSE pinMode(9, OUTPUT); // OPEN-relay pinMode(10, OUTPUT); // CLOSE-relay digitalWrite(9, 1); digitalWrite(10, 1);

När reläerna får spänning, då är dem OFF. Därför har jag gjort det omvänt så att ON är 0 och OFF är 1. Allt har med reläernas dumhet att göra.

Permalänk
Medlem
Skrivet av heretic16:

När digitalRead(1) blir 0 så betyder det att det finns slutning.
Det är jag som har gjort det så där.

pinMode(2, INPUT); digitalWrite(2, 1); // Relay-breake for OPEN pinMode(1, INPUT); digitalWrite(1, 1); // Relay-breake for CLOSE pinMode(9, OUTPUT); // OPEN-relay pinMode(10, OUTPUT); // CLOSE-relay digitalWrite(9, 1); digitalWrite(10, 1);

När reläerna får spänning, då är dem OFF. Därför har jag gjort det omvänt så att ON är 0 och OFF är 1. Allt har med reläernas dumhet att göra.

Perfekt! Då bör de kodexempel jag bifogat fungera rakt av för både check_time() och show_clock() För läsbarhetens skull kan man väl bryta ut rutinerna för att stänga resp. öppna grinden men annars ska det nog fungera!

glöm det jag editerade bort, nog dags att sova snart
Permalänk
Skrivet av windblownsnow:

Perfekt! Då bör de kodexempel jag bifogat fungera rakt av för både check_time() och show_clock() För läsbarhetens skull kan man väl bryta ut rutinerna för att stänga resp. öppna grinden men annars ska det nog fungera!

Jag är inte så seriöst med detta projekt. Det är en ATmega328P-PU som jag har byggt till en Arduino UNO. Ja, byggt allt själv. Allt från grunden Så ja är duktig ja!

Det är egentligen min far som ska ha den för att underlätta att släppa ut hönsen eller inte. Folk böjar bli bekväma av sig.

Tanken med projektet är att jag ska jämföra det med ett PLC system och göra en rapport på det. Kostnad, tid, svårighetsgrad mer mera. Det är alltså till en kurs på 15 hp. Därför lägger jag inte så mycket tid på att optimera koden. Så länge det fungerar. Med andra ord: Det är skolan - skit in -> skit ut.

Permalänk
Medlem

Hehe Vad skolan beträffar vill jag minnas att det var betydligt lättare att imponera med 20 sidor kod jämfört med 15 rader som fyller samma funktion xP Får medge att jag blev lite väl sugen på att skriva lite själv - inspirerande projekt och det blir nästan som lite sudoku att pussla ihop bitarna på bästa plats. Btw, hur gammal är din signatur!?