Få in skiftschema i arduino.

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43178
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Få in skiftschema i arduino.

Inlägg av sodjan »

En AVR har så klart metoder/intruktioner för att skriva till sitt eget EEPROM.
Arduino har egna rutiner: http://arduino.cc/en/Reference/EEPROM.
Men det var ju så lätt att hitta ("arduino eeprom" i google) så du kanske
menar något annat!?
Användarvisningsbild
orvar-e
EF Sponsor
Inlägg: 5957
Blev medlem: 9 mars 2007, 09:01:32
Ort: Borlänge

Re: Få in skiftschema i arduino.

Inlägg av orvar-e »

Nä jag ställde frågan innan jag googlat (gud förbarma mig). Men googlade strax efter, samt editerade mitt inlägg.
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43178
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Få in skiftschema i arduino.

Inlägg av sodjan »

Fel ordning... :-)
Användarvisningsbild
orvar-e
EF Sponsor
Inlägg: 5957
Blev medlem: 9 mars 2007, 09:01:32
Ort: Borlänge

Re: Få in skiftschema i arduino.

Inlägg av orvar-e »

Ja, så går det ju inte att hålla på!

Ska bli riktigt intressant att testa.
Användarvisningsbild
swapper
Inlägg: 1075
Blev medlem: 14 augusti 2012, 23:18:15
Ort: Helsingborg

Re: Få in skiftschema i arduino.

Inlägg av swapper »

För att slippa sätta klockan rätt i enheten så bör du kunna plocka in den ifrån dcf77.
Hanterar även sommar/vintertid.

http://playground.arduino.cc/Code/DCF77

http://thijs.elenbaas.net/2012/04/ardui ... ardware-2/
Användarvisningsbild
säter
Inlägg: 32547
Blev medlem: 22 februari 2009, 21:16:35
Ort: Säter

Re: Få in skiftschema i arduino.

Inlägg av säter »

Är det fortfarande så att nattskiften börjar 2 timmar tidigare på lördagar?
Användarvisningsbild
orvar-e
EF Sponsor
Inlägg: 5957
Blev medlem: 9 mars 2007, 09:01:32
Ort: Borlänge

Re: Få in skiftschema i arduino.

Inlägg av orvar-e »

Helt rätt, Säter.

Tack för tipset, swapper! :tumupp:
Användarvisningsbild
orvar-e
EF Sponsor
Inlägg: 5957
Blev medlem: 9 mars 2007, 09:01:32
Ort: Borlänge

Re: Få in skiftschema i arduino.

Inlägg av orvar-e »

Nu har jag kommit igång med programmerandet och just nu verkar det gå skit bra, men å andra sidan så har jag inte laddat ner och testat programmet än. Dessutom måste jag göra en enkel simulator så tiden kan snabbas upp några tusen gånger. Så att en dag motsvarar en sekund så att det går att simulera ett års skiftschema på 5 minuter.
Så här ser programmet i stort ut.

Kod: Markera allt

  switch(year){
 case 16:
  leapdays = 1;
  break;
 case 20:
  leapdays = 2;
  break;
 case 24:
  leapdays = 3;
  break; 
 case 28:
  leapdays = 4;
  break; 
 case 32:
  leapdays = 5;
  break;
 case 40:
  leapdays = 6;
  break;
}
Första delen, se om något av åren som varit eller är har något skottår och då lägga värde i "leapdays". Efter tiden räknas från januari 2015 (passade bra med skiftet då).
Nästa steg blir att räkna hur många dagar som har gått det aktuella året "nu", detta sker i 12 steg januari (0 dagar) till december + 31 dagar sista december.
Efter som programmet får aktuell månad från RTC:n så räknar jag inte med januari först utan januari kommer i febuari osv.

Kod: Markera allt

  switch(month){
 case 1:
  c_month = 0 + leapdays; ;
  break;
 case 2:
  c_month = 31 + leapdays;
  break;
  case 3:
  c_month = 59 + leapdays ;
  break;
 case 4:
  c_month = 90 + leapdays;
  break;
  case 5:
  c_month = 120 + leapdays;
  break;
 case 6:
  c_month = 151 + leapdays;
  break;
  case 7:
  c_month = 181 + leapdays;
  break;
 case 8:
  c_month = 212 + leapdays;
  break;
  case 9:
  c_month = 243 + leapdays;
  break;
 case 10:
  c_month = 273 + leapdays;
  break; 
 case 11:
  c_month = 304 + leapdays;
  break;
 case 12:
  c_month = 234 + leapdays;
  break;
}
Man vill ju kunna ställa in vilket lag man tillhör, från A - E. Efter som jag tillhör B-lag så får det bli 0 dagar i skillnad från default. Dvs B-Lag är default inställningen, går man på nått annat lag blir det till att lägga på extra dagar för att komma till samma punkt i 35 dagars perioden. Här är det feltänkt fullständigt ser jag nu. Dagarna stämmer inte. :humm:
Det är dagar som ska tas bort och inte läggas till.......

Kod: Markera allt

switch(teamA-E) {
  case 1:                // A-team
  nr_day + 21;          // +21 day from deafault start
  break;
  case 2:                // B-team
  nr_day + 0;           // default
  break;
  case 3:                //C-team
  nr_day + 14;          // +14 day from default start
  break;
  case 4:                //D-team
  nr_day + 28;          // +28 day from default start
  break;  
  case 5:               // E-team
  nr_day + 7;           // +7 day from default start
  break;  
  }
Nästa steg blir att räkna fram antal dagar som gått från 1 januari 2015, och samtidigt dela det med 35 dagar som en hel skiftcykel är. Då får man fram vilket skiftlag som gör vad på inställt datum.

Kod: Markera allt

c_year = year - 15;                                // how many hole year from start year
nr_days = (c_year * 365) + c_month + dayOfMonth; 

if (nr_day != c_days) { 
    c_days++;
    day1_35++; }
if (day1-35 >> 35 ) {
    day1_35 = 1; } 

Och sedan en tabell som säger vilka dagar i den här 35 dagars listan som motsvarar vilka skift utifrån att perioden börjar måndag med två förmiddagsskift.

Kod: Markera allt

// start with two AM shift at monday

if(day1_35 == 1 || 2 || 12 || 13 || 14 || 24) {
  skift = F;} 
if (day1_35 == 3 || 4 || 15 || 16 || 26 || 27 || 28) {
  skift = E;}
if(day1_35 == 5 || 7 || 17 || 18 || 30) {
  skift = N; }
if(day1_35 == 29) {
  skift = SE; }     // short afternon shift
if(day1_35 == 8) {
  skift = LN; }  //Long night shift
if(day1_35 == 8 || 9 || 10 || 11 || 19 || 20 || 21 || 22 || 23 || 31 || 32 || 33 || 34 || 35 ) {
 skift = L; }  // L = Freeshift
    
Där har vi skiftschemat enligt den på första inlägget i arduino tappning. Det finns säkert många sätt att göra detta på och jag har ju som sagt inte testa om det fungerar än.
Detta är den viktigaste delen av koden, för att få till det. Det som fattas är ju såklart vilka tider F,E,N,SE,LN motsvarar temperatur justeringen, och en massa lcd.print();

Om det här fungerar utan allt för mycket ingrepp så kommer jag att säga var det inte krångligare än så här. Varför i h-lvete har jag inte gjort det tidigare.
Användarvisningsbild
orvar-e
EF Sponsor
Inlägg: 5957
Blev medlem: 9 mars 2007, 09:01:32
Ort: Borlänge

Re: Få in skiftschema i arduino.

Inlägg av orvar-e »

Istället för att plussa på dagar beroende på vilket skiftlag man tillhör så är det säkrare att sätta mata in dag direkt. Ingen risk för overflow eller minusvärden då dessa inte existerar i verkligheten.
Värdet måste alltid vara mellan 1 och 35.

Kod: Markera allt

switch(teamA-E) {
  case 1:                // A-team
  day1_35 = 26;          // +21 day from deafault start
  break;
  case 2:                // B-team
  // Reset, recalculate value         = 0 extra day from result
  break;
  case 3:                //C-team
  day1_35 = 33;          // +14 day from default start
  break;
  case 4:                //D-team
  day1_35 = 19;         // +28 day from default start
  break;  
  case 5:               // E-team
  day1_35 = 5;          // +7 day from default start
  break;  
  }
Lite osäker hur jag ska göra om man går från ett lag A,C,D eller E och sedan tillbaka till B. Det lättaste borde vara att begära en ny uträkning.
Användarvisningsbild
orvar-e
EF Sponsor
Inlägg: 5957
Blev medlem: 9 mars 2007, 09:01:32
Ort: Borlänge

Re: Få in skiftschema i arduino.

Inlägg av orvar-e »

Skifttabellen med "ELLER" logik fungerade skit dåligt. Jag fick lägga in 35 "IF" satser istället för att avgöra skift-status och det har fungerat felfritt. Har simulerat 4000 dagar, skiftdagen är rätt men den räknar ut att det är en dag mer än de hjälpmedlen på webben. Men det betyder inget bara skiftdagen är rätt, för det är ju den som ska styra när motorvärmaren ska gå på och av i grova drag.
Så här ser koden ut för tillfället, lite tunt med kommentarer, jag vet.

Kod: Markera allt

#include "Wire.h"
#include <LiquidCrystal.h>
#define DS3231_I2C_ADDRESS 0x68
int skift;
int c_days = 0; int s_days; int day1_35 = 0; int disp1; int nr_days = 0;
int leapyear = 0;
int leapdays = 0;
int c_year = 0;
int interval = 1000;
int c_month = 0;
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return( (val/16*10) + (val%16) );
}
void setup()
{
  Wire.begin();
  lcd.begin(16, 2);
  Serial.begin(9600);
  // set the initial time here:
  // DS3231 seconds, minutes, hours, day, date, month, year
//setDS3231time(30,58,19,3,29,12,15);
}
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte
dayOfMonth, byte month, byte year)
{
  // sets time and date data to DS3231
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}
void readDS3231time(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}
void displayTime()
{
  // retrieve data from DS3231
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
  &year);
  // send it to the serial monitor
  
  
  if (hour<10) {
    lcd.setCursor(5,1);
  lcd.print(hour, DEC);
  lcd.setCursor(4,1);
  lcd.print("0");
  } else if (hour>9) {
   lcd.setCursor(4,1);
  lcd.print(hour, DEC);}
  lcd.setCursor(6,1);
  lcd.print(":");
   
  // convert the byte variable to a decimal number when displayed
  

  if (minute<10) {
    lcd.setCursor(8,1);
  lcd.print(minute, DEC);
  lcd.setCursor(7,1);
  lcd.print("0");
  } else if (minute >9) {
  lcd.setCursor(7,1);
  lcd.print(minute, DEC);}
    lcd.setCursor(9,1);
  lcd.print(":");
  


   
  if (second<10) {
    lcd.setCursor(11,1);
  lcd.print(second, DEC);
  lcd.setCursor(10,1);
  lcd.print("0");
  } else if (second >9) {
  lcd.setCursor(10,1);
  lcd.print(second, DEC);} 
  
  }

void loop()
{
displayTime(); 
  
switch(year){
 case 16:
  leapdays = 1;
  break;
 case 20:
  leapdays = 2;
  break;
 case 24:
  leapdays = 3;
  break; 
 case 28:
  leapdays = 4;
  break; 
 case 32:
  leapdays = 5;
  break;
 case 40:
  leapdays = 6;
  break;
}

  switch(month){
 case 1:
  c_month = 0 + leapdays; ;
  break;
 case 2:
  c_month = 31 + leapdays;
  break;
  case 3:
  c_month = 59 + leapdays ;
  break;
 case 4:
  c_month = 90 + leapdays;
  break;
  case 5:
  c_month = 120 + leapdays;
  break;
 case 6:
  c_month = 151 + leapdays;
  break;
  case 7:
  c_month = 181 + leapdays;
  break;
 case 8:
  c_month = 212 + leapdays;
  break;
  case 9:
  c_month = 243 + leapdays;
  break;
 case 10:
  c_month = 273 + leapdays;
  break; 
 case 11:
  c_month = 304 + leapdays;
  break;
 case 12:
  c_month = 334 + leapdays;
  break;
}

c_year = year - 15;                                // how many hole year from start year
nr_days = ((c_year * 365) + c_month + (dayOfMonth - 4 ));   // how many days from start date


if(nr_days  != c_days) {
     day1_35++; c_days++; }
if(day1_35 >= 35){ 
    day1_35 = 0; }
if(nr_days == c_days) {
     disp1++; }
if(disp1 >= 5) {
    disp1 = 5; } 
if(nr_days != c_days){   
    disp1 = 0; }

//Skift tabell 
             if(day1_35 == 1 )  {         // Morgon skift
  skift = 1;}if(day1_35 == 2 )  {         // Morgon skift
  skift = 1;}if(day1_35 == 12 ) {         // Morgon skift
  skift = 1;}if(day1_35 == 13 ) {         // Morgon skift
  skift = 1;}if(day1_35 == 14 ) {         // Morgon skift
  skift = 1;}if(day1_35 == 24 ){          // Morgon skift
  skift = 1;}if(day1_35 == 25 ){          // Morgon skift
  skift = 1;}
  
             if(day1_35 == 3 ) {          // Eftermiddagsskift
  skift = 2;}if(day1_35 == 4 ) {          // Eftermiddagsskift
  skift = 2;}if(day1_35 == 15 ) {         // Eftermiddagsskift
  skift = 2;}if(day1_35 == 16 ) {         // Eftermiddagsskift
  skift = 2;}if(day1_35 == 26 ) {         // Eftermiddagsskift
  skift = 2;}if(day1_35 == 28 ) {         // Eftermiddagsskift
  skift = 2;}  
             
             if(day1_35 == 5  ) {         // Natt
  skift = 3;}if(day1_35 == 7  ) {         // Natt
  skift = 3;}if(day1_35 == 17  ) {        // Natt
  skift = 3;}if(day1_35 == 18  ) {        // Natt
  skift = 3;}if(day1_35 == 29  ) {        // Natt
  skift = 3;}if(day1_35 == 30  ) {        // Natt
  skift = 3;}
  
             if(day1_35 == 8  ) {        // Ledig
  skift = 0;}if(day1_35 == 9  ) {        // Ledig
  skift = 0;}if(day1_35 == 10 ) {        // Ledig
  skift = 0;}if(day1_35 == 11 ) {        // Ledig
  skift = 0;}if(day1_35 == 19 ) {        // Ledig
  skift = 0;}if(day1_35 == 20 ) {        // Ledig
  skift = 0;}if(day1_35 == 21 ) {        // Ledig
  skift = 0;}if(day1_35 == 22 ) {        // Ledig
  skift = 0;}if(day1_35 == 23 ) {        // Ledig
  skift = 0;}if(day1_35 == 31 ) {        // Ledig
  skift = 0;}if(day1_35 == 32 ) {        // Ledig
  skift = 0;}if(day1_35 == 33 ) {        // Ledig
  skift = 0;}if(day1_35 == 34 ) {        // Ledig
  skift = 0;}if(day1_35 == 35 ) {        // Ledig
  skift = 0;}if(day1_35 == 27 ) {        // short afternon shift
  skift = 4;}if(day1_35 == 6  ) {        //Long night shift
  skift = 5;}                            

if ((nr_days == c_days) && (disp1 == 1)) { 
if(skift == 0) {
  lcd.setCursor(0,0);
  lcd.print("Ledig"); }  
if(skift == 1) {
  lcd.setCursor(0,0);
  lcd.print("Formiddag");}
if(skift == 2) {
    lcd.setCursor(0,0);
    lcd.print("Eftermiddag");  }  
if(skift == 3) {
    lcd.setCursor(0,0);
    lcd.print("Natt-skift");  }
    if(skift == 4) {
    lcd.setCursor(0,0);
    lcd.print("Kort eftermiddag"); }   
if(skift == 5) {
    lcd.setCursor(0,0);
    lcd.print("Lang-natt"); } }

                         
if((nr_days == c_days) && (disp1 == 2)) {    
    Serial.print("c_day = ");
    Serial.print(c_days);
    Serial.print("  ");
    Serial.print("Dag nr = ");
    Serial.print(day1_35); 
    Serial.print("  ");
    Serial.print(skift);
    Serial.print("  ");
    Serial.print("  ");

 
 
if(skift == 0) {
    Serial.print("Fri-");
    Serial.println("Skift");  }  
if(skift == 1) {
    Serial.print("Formiddad-");
    Serial.print("Skift");  }
if(skift == 2) {
    Serial.print("Eftermiddag- ");
    Serial.print("Skift");  }  
if(skift == 3) {
    Serial.print("Natt-");
    Serial.println("Skift");  }
    if(skift == 4) {
    Serial.print("Kort eftermiddag ");
    Serial.println("Skift"); }   
if(skift == 5) {
    Serial.print("Langnatt ");
    Serial.println("Skift");  }}
    
    
  
    
} 
Användarvisningsbild
Icecap
Inlägg: 26139
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Få in skiftschema i arduino.

Inlägg av Icecap »

Jag har haft något liknande i tankarna men ville välja en annan väg.

I ditt fall finns 5 olika skift - men deras skift-följd är ganska säkert det samma. Alltså om en total skift-kalender är t.ex. 5 veckor startar skift A på dag 0, B på dag 7, C på dag 14 osv.

Då hade jag lagt in själva skift-schemat i EEPROM så att man kan ändra det.
Sedan hade jag lagt in förskjutningen för de olika skift (A = 0, B = 7, C = 14 osv).
Och till slut ett datum för dag noll på skiftet.

Skottår:

Kod: Markera allt

_UBYTE Date_Time_Is_Leapyear(_UWORD Year)
  {
  _UBYTE Century, Year_NC;
  Century = Year / 100;
  Year_NC = Year % 100;
  if(!(Year_NC & 3) && (Year_NC || !(Century & 3))) return(1);
  return(0);
  }
Jag har en del rutiner för räkning på DST (sommar/vintertid), skottår osv. så de klockor jag gör program till (tid, temp osv) räknar internt i UTC och sedan lägger jag till en tidzon samt DST-regel.

På detta vis kan du enkelt lägga in vilket skift du går bara vid att mata in A, B, C, D eller E, datum och tid är redan känd och en snabb räkning på skift-schemat ger var ditt skift är.

Overheaden är tyngre - men när den väl är klar är resten hur enkelt som helst.
Användarvisningsbild
hawkan
Inlägg: 2620
Blev medlem: 14 augusti 2011, 10:27:40

Re: Få in skiftschema i arduino.

Inlägg av hawkan »

Om tabellen för skiftschema inte ändras så lägg det i flash-minne med PROGMEM.

En ds3231 är nästan gratis http://www.ebay.com/itm/For-Arduino-DS3 ... SwniRWNyWo behövs ett laddningsbart batteri som kostar mer.

ds3231 libary: http://www.rinkydinkelectronics.com/library.php?id=73 Du sätter tiden en gång så håller den ju tiden, det är det den gör.
Användarvisningsbild
orvar-e
EF Sponsor
Inlägg: 5957
Blev medlem: 9 mars 2007, 09:01:32
Ort: Borlänge

Re: Få in skiftschema i arduino.

Inlägg av orvar-e »

Det kanske inte framgått med önskad tydlighet, men jag använder mig av en DS3231 (som jag dock betalat avsevärt mer för). Jag får datum/tid ifrån den och räknar sedan ut antalet dagar sedan dag 0, när jag har antalet dagar från dag 0 så delar jag det med 35 och får då dagens skift eller friskift om det vill sig väl. Koden för skillnad mellan lagen finns inte med i senaste upplägget. Men koden ser ut som följande. Den är inte klar eller testad, fokus ligger på andra områden just nu. B-lag har jag satt till värde 0 på antalet dagar att plussa på, på totala antalet dagar sedan dag 0.
Det fina med denna kod var att den var ganska enkel och är totalt framtid säker, iaf till 2040 då jag går i pension och inte behöver dylikt längre. Vart fjärde år så plussas det på en extra dag.
Jag kan varken c eller C++ så, därför ser det ut som en liten skolunge gjort det.


Kod: Markera allt

switch(teamA-E) {
  case 1:                // A-team
  day1_35 = 26;          //day 26 from default start
  break;
  case 2:                // B-team
  // Reset, recalculate value         = 0 extra day default start
  break;
  case 3:                //C-team
  day1_35 = 33;          // day 33 from default start
  break;
  case 4:                //D-team
  day1_35 = 19;         // day 19 from default start
  break;  
  case 5:               // E-team
  day1_35 = 5;          // day 5 from default start
  break;  
  }

hawkan .... hur göra om klockan i DS3231 börjar avvika lite för mycket med åren, därför vill jag ha möjlighet att justera den. Men att lägga in schemat i RTC:n kan ju vara ideé, och ännu viktigare skulle det vara att de personliga inställningarna hamnar i RTC:n eller arduinons EEPROM så man slipper knappa i dem vid varje ström avbrott.
Användarvisningsbild
Icecap
Inlägg: 26139
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Få in skiftschema i arduino.

Inlägg av Icecap »

Självklart ska inställningarna sparas i lämpligt minne!!!

Ett tips med DS3231 är att använda SQW-utgången kopplat till en interrupt-ingång och sätta den till 1 puls/sek.
Då kan man läsa datum & tid vid uppstart och sedan tillåter interrupten kan man släppa att hela tiden kolla RTC'n, man räknar tiden upp internt för varje interrupt istället.
Användarvisningsbild
orvar-e
EF Sponsor
Inlägg: 5957
Blev medlem: 9 mars 2007, 09:01:32
Ort: Borlänge

Re: Få in skiftschema i arduino.

Inlägg av orvar-e »

Vad vinner man på det, går det inte att ha fler moduler på bussen annars?
Skriv svar