DIY Arduino Termometer

PID regulator, styringer og programmer.
CarstenM
Indlæg: 162
Tilmeldt: 31. aug 2015, 14:21
Geografisk sted: Vejen - Sydjylland

Re: DIY Arduino Termometer

Indlæg af CarstenM »

Michal skrev:Jo, jeg tænkte på temperaturen inde i køle- eller gærskabet og udenfor det. Jeg ved ikke helt om det er reelt er brugbart i reguleringen, men har set det nævnt flere gange. Og har det en betydning er det jo ikke lige gyldigt hvilken føler der bliver sat på hvor.

Men du har (som sædvanligt) nok ret, i et setup hvor man har flere temperaturer man vil måle nok ikke det store problem at huske hvilken føler der skal i hvor.
Jeg forstår slet ikke hvorfor det er vigtigt at vide temperatur udenfor, eller flere temperaturer i det hele taget når vi snakker gærskab!?. Det må da være temperatur i væsken der er vigtig, det er jo den din regulering styrer efter.
Hvad angår måle i væsker, så må det være mere vigtigt med omrøring/cirkulation i gærtank. At måle på stillestående væske er altså ikke nøjagtigt.

Kan man ikke bare finde og derefter opmærke sådan nogle temperatur følere?

Men jeg føler mig udfordret og nysgerrig på sådan noget arduino. Startede med noget PT-100, men da lidt smartere med arduino. Nu har jeg fået svejst mig nogle dyklommer i rustfri, vil prøve at bestille nogle DS18B20 følere hjem og lege lidt med dem
Brugeravatar
Nimbus39
Indlæg: 3392
Tilmeldt: 27. jun 2010, 09:52
Geografisk sted: Greve (Mosede Strand)
Kontakt:

Re: DIY Arduino Termometer

Indlæg af Nimbus39 »

Jeg skal udelukkende bruge det i stedet for mit håndholdte termometer under brygningen...
Husk at der er tale om et termometer og ikke en styring af temperaturer, det har jeg også bygget: http://haandbrygforum.dk/viewtopic.php? ... =15#p62350" onclick="window.open(this.href);return false;
Hvad angår måling af temperaturer i gærtanken måler jeg den på 0,5 X radius da det må være der det bedste gennemsnit af urtens temperatur ligger.
Temperaturen udenfor tanken vil jeg gerne kende for at kunne se hvor meget varme gæringen frembringer i urten, det skal ikke som sådan bruges til styring.
Logikken er at det vil være varmest i midten og koldest yderst, så derfor måler jeg lige mellem de 2 punkter.
Hvad angår stillestående væsker, så står urten ikke stille under gæringen - der er dels den naturlige konvektion, men også den "bevægelse" gæringen sørger for når CO2 bobler op til overfladen.
Hvis man vil være ekstra sikker kan man jo bare lægge PID softwarepakker ind i Arduinoen, så skulle den ramme temperaturerne mere præcist.
Buy a man a beer and he wastes an hour. Teach a man to brew and he wastes a lifetime.
http://bryggeri.landly.dk
http://www.facebook.com/bryggerilandly
http://beersmithrecipes.com/listrecipes/2810/nimbus39
CarstenM
Indlæg: 162
Tilmeldt: 31. aug 2015, 14:21
Geografisk sted: Vejen - Sydjylland

Re: DIY Arduino Termometer

Indlæg af CarstenM »

Nimbus39 skrev:Jeg skal udelukkende bruge det i stedet for mit håndholdte termometer under brygningen...
Ja, det er jo noget helt andet end gærtank. Tak for at uddybe.
Det er jo noget helt andet at måle på. Jeg kan godt lide dit setup. Tror simpelthen jeg må prøve at bygge noget selv.
Truntebryg
Indlæg: 5319
Tilmeldt: 15. nov 2008, 09:30

Re: DIY Arduino Termometer

Indlæg af Truntebryg »

Nimbus39 skrev:Logikken er at det vil være varmest i midten og koldest yderst, så derfor måler jeg lige mellem de 2 punkter.
Jaaa, hvis der er koldere udenfor tanken ;-)

Men ellers også et drømme projekt her...
jakobp
Indlæg: 59
Tilmeldt: 28. jul 2011, 22:55
Geografisk sted: 8382 Hinnerup

Re: DIY Arduino Termometer

Indlæg af jakobp »

Truntebryg skrev:
Nimbus39 skrev:Logikken er at det vil være varmest i midten og koldest yderst, så derfor måler jeg lige mellem de 2 punkter.
Jaaa, hvis der er koldere udenfor tanken ;-)
Gæringsprocessen udvikler varme, så derfor vil der være varmere i spanden, end i omgivelserne...
Men i og med at denne varme udvikles i hele spanden, og gæringen jo også sørger for lidt cirkulering, vil jeg da gætte på, at temperaturen er temmelig jævn i hele spanden?


Sent from my iPhone using Tapatalk
Brugeravatar
Nimbus39
Indlæg: 3392
Tilmeldt: 27. jun 2010, 09:52
Geografisk sted: Greve (Mosede Strand)
Kontakt:

Re: DIY Arduino Termometer

Indlæg af Nimbus39 »

Så kom de sidste stumper hjem, og dimsen er nu færdig og klar til brug (hvis jeg ellers havde et 9V batteri)
Jeg har lavet lidt om i opbygningen, således at de 2 trykknapper nu sidder på analoge indgange i stedet for de digitale (det giver mulighed for at korrigere for kontakter der ikke giver en helt modstandsfri overgang)
og derudover har jeg lavet koden så man kan slukke lyset i displayet.
Det fungerer ved at den aflæser værdien for den grønne knap, og hvis den er over 100 tændes lyset når "Setup" løkken afvikles. Det gør selvfølgelig at man ikke kan gøre det undervejs mens man bruger boksen, men det var lige en lille ekstra funktion jeg kom i tanke om at bygge ind i boksen uden at skulle ud i at sætte flere knapper på kassen.
Det hele ser således ud:
BrygTermometer.jpg
BrygTermometer.jpg (119.02 KiB) Vist 12802 gange

Kode: Vælg alt

#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <StopWatch.h>


// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Opløsningen på DS18B20
#define TEMPERATURE_PRECISION 12

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27,16,2);  

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// Antal DS18B20
int numberOfDevices; 

// Variable til opbevaring af DS18B20 adresserne
DeviceAddress tempDeviceAddress; 

//Definer kontaktpins
const int buttonRed = A1;
const int buttonGreen = A0;

//Definer variable
int buttonStateRed = 0;
int buttonStateGreen = 0;
int h = 0;
StopWatch Ur;
float ES, EM, ET;

void setup(void)
{
  //Initialiser input pins
  pinMode(buttonRed, INPUT);     
  pinMode(buttonGreen, INPUT);     

  // initialize the lcd
  lcd.init();  
  lcd.clear(); 
  
  // Turn on the LCD, if analogRead(buttonGreen) higher than 100
  if (analogRead(buttonGreen) > 100)
  {
    lcd.backlight();
  }

  // Start up the ds18b20 library
  sensors.begin();
  
  // Grab a count of devices on the wire
  numberOfDevices = sensors.getDeviceCount();
  
  // Start afvikling af program
  lcd.print("Velkommen til");
  lcd.setCursor(0,1);
  lcd.print("Bryggeri Landly");
  delay(2500);  
  lcd.clear();
  lcd.print("Leder");
  delay(100);
  lcd.print(".");
  delay(100);
  lcd.print(".");
  delay(100);
  lcd.print(".");
  delay(100);
  lcd.print(".");
  delay(100);
  lcd.print(" OK!");
  delay(350); 
  lcd.setCursor(0,1);
  lcd.print("Fandt ");
  lcd.print(numberOfDevices, DEC);
  lcd.println(" enheder.");
  delay(1500);
  lcd.clear();
  lcd.print("Starter program");
  lcd.setCursor(0,1);
  lcd.print(".");
  delay(100);
  lcd.print(".");
  delay(100);
  lcd.print(".");
  delay(100);
  lcd.print(".");
  delay(1000);
  lcd.clear();

}

// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  lcd.print(tempC,1);
}

//Funktion til opdatering af temp. i display
void UpdateDisplay()
{
  sensors.requestTemperatures(); // Send the command to get temperatures
  lcd.print("                        "); //ryd området med temperaturer.
  // Loop through each device, print out temperature data
  for(int i=0;i<numberOfDevices; i++) // gentag for alle fundne DS18B20
  {
    // Search the wire for address
    if(sensors.getAddress(tempDeviceAddress, i))
	{
                if(i>1) 
                {
                  lcd.setCursor(0,1); // Hvis det er 3. sensor der skal vises sæt cursor i rette position.
                }
                if(i>0 && i<2) //hvis i er lig 1
                {
                  lcd.setCursor(8,0); // Hvis det er 2. sensor der skal vises sæt cursor i rette position.
                }
		// Output the device ID
		lcd.print(i+1,DEC); // Læg 1 til device ID, da den ellers vil starte med 0
		lcd.print(":");
		printTemperature(tempDeviceAddress); // Udskriv temp data for den aktive føler.
	} 
  }
  h=0; // Variable der bestemmer hvornår display skal opdateres, nulstilles inden der vendes tilbage til hovedløkken
}

void loop(void)
{ 
  h++;
  buttonStateRed = analogRead(buttonRed); //Aflæs rød knaps tilstand
  buttonStateGreen = analogRead(buttonGreen);//Aflæs grøn knaps tilstand
  ES = (Ur.elapsed()/1000) % 60; //Sekunder, heltaldivideres og resten vises.
  EM = (Ur.elapsed()/60000) % 60; //Minutter, heltaldivideres og resten vises.
  ET = Ur.elapsed()/3600000; //Timer
  if (h>250) // Ønskes opdatering af display i kortere eller længere interval ændres denne. 250 svarer til ca 8 sekunder.
  { 
    UpdateDisplay();
  }
  lcd.setCursor(15,1); //Sæt cursor til linje 2 position 15
  //Læs knapper
  if (buttonStateRed > 100 && buttonStateGreen < 100) // Stop ur
  {
    lcd.print("R"); // Angiv i display at rød knap er trykket ned
    Ur.stop();
  }
  if (buttonStateGreen > 100 && buttonStateRed < 100) //Start ur
  {
    lcd.print("G"); // Angiv i display at grøn knap er trykket ned
    Ur.start();
  }
  if (buttonStateGreen > 100 && buttonStateRed > 100) //Nulstil ur
  {
    lcd.print("B"); // Angiv i display at rød og grøn knap er trykket ned
    Ur.reset();
  }
  //Print ur
  lcd.setCursor(8,1); //Sæt Curson til den position hvor tiden skal skrives.
  lcd.print(ET,0);
  lcd.print(":");
  if(EM<10) // Hvis EM er på 1 tal skal der tilføjes et "0" foran
  {
    lcd.print("0");
  }
  lcd.print(EM,0);
  lcd.print(":");
    if(ES<10) // Hvis ES er på 1 tal skal der tilføjes et "0" foran
  {
    lcd.print("0");
  }
  lcd.print(ES,0);
  delay(10); // Vent et kort øjeblik, så der er tid til at opdage knappen evt. er trykket ned.
  lcd.setCursor(15,1);
  lcd.print(" "); // Tøm cellen der angiver knap-tilstand
}
EDIT:
Et opdateret diagram over løsningen.
BrygTermometer_bb.png
BrygTermometer_bb.png (134.28 KiB) Vist 12749 gange
Senest rettet af Nimbus39 5. nov 2015, 16:01, rettet i alt 1 gang.
Buy a man a beer and he wastes an hour. Teach a man to brew and he wastes a lifetime.
http://bryggeri.landly.dk
http://www.facebook.com/bryggerilandly
http://beersmithrecipes.com/listrecipes/2810/nimbus39
Brugeravatar
Michal
Indlæg: 330
Tilmeldt: 22. jul 2014, 10:17
Geografisk sted: Vejen - Sydjylland

Re: DIY Arduino Termometer

Indlæg af Michal »

Lækker!

Så begynder det at trække igen, jeg SKAL altså snart have min færdig også.
Udstyr:
2 x Nimbus 29 el-gryder
2 x modstrøms køler
2 x cirkulations pumper
rasmusa
Indlæg: 17
Tilmeldt: 14. feb 2014, 23:25
Geografisk sted: Strandby, Nordjylland

Re: DIY Arduino Termometer

Indlæg af rasmusa »

Mit almindelige termometer gik i stykker sidste gang jeg bryggede, hvilket resulterede i for høj mæske temperatur og en alt for sød øl. I min jagt efter et bedre alternativ stødte jeg på denne tråd og blev vældig begejstret for Nimbus' ide. Stumperne blev bestilt hjem fra Kina, og jeg fik bygget et termometer magen til.
Efter at have fået det op at køre fik jeg blod på tanden, og bestemte mig for at forsøge at udvide funktionaliteten, så jeg kunne sætte alarmer på de tre prober og timeren. Efter en del aftener og to totale omskrivninger af koden fordi der gik total spaghetti i den, er jeg ved at være tilfreds med resultatet.

Hardwaren er den samme som i den oprindelige version, bortset fra at jeg har tilføjet en buzzer som alarm.

Koden er skrevet om som en Finite State Machine, som gør det nemt at styre flowet. Funktionaliteten kan ses i diagrammet her:
Termometer FSM.png
Termometer FSM.png (68.36 KiB) Vist 12673 gange
Kort beskrevet:
Et kort tryk på timerknappen stopper/starter timeren. Et langt tryk resetter den.
Et langt tryk på alarm knappen tænder/slukker baggrundslyset i LCD'en.
Et kort tryk på alarm knappen skifter til alarm mode, hvor der kan sættes alarmer på alle tre prober samt timeren.
Et kort tryk på alarm knappen her skifter cursoren til næste position. Et kort tryk på timer knappen tæller værdien ved cursoren op. Et langt tryk på alarm knappen aktiverer/deaktiverer alarmen cursoren står ved. Efter 5 sek. uden tryk skifter displayet tilbage til at vise målte temperaturer.
Der vises et lille 'A' ud for de aktive alarmer. Når en alarm aktiveres vil buzzeren give lyd og 'A' markeringen vil blinke ved den alarm der er gået.
Et kort tryk på alarm knappen stopper den aktuelle alarm.

Kode: Vælg alt

#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <SM.h>
#include <StopWatch.h>

struct Button {
  uint8_t pin;
  unsigned long timer;
};

struct TemperatureAlarm {
  uint8_t target;
  uint8_t lastValue;
  bool set;
  bool alertOnHigher;
  bool triggered;
};

struct TimerAlarm {
  uint8_t h;
  uint8_t m;
  uint8_t s;
  bool set;
  bool triggered;
};

//Initialize temp probes
#define ONE_WIRE_BUS 2 //probes connected on pin 2
#define TEMPERATURE_PRECISION 12 // DS18B20 probe resolution - 9=0,5 10=0,25, 11=0,125, 12=0,0625
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

uint8_t numberOfDevices; //number of probes found on the wire
DeviceAddress probes[3]; //Array of addresses to the probes

// Initialize LCD on address 0x27
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

//custom alarm symbol
byte alarmSymbol[8] = {
  B00100,
  B01010,
  B01110,
  B01010,
  B00000,
  B00000,
  B00000,
  B00000
};

const unsigned long updateTimerInterval       = 1000; //update timer every 1 sec.
const unsigned long updateTemperatureInterval = 2000; //update temperatures every 2 sec.
const unsigned long buttonLongPressTime       = 1000; //1 sec press to reset timer

unsigned long timerLastUpdated = 0;
unsigned long tempLastUpdated = 0;

StopWatch timer;

//Buttons
Button buttonTimer = {A0, 0};
Button buttonAlarm = {A1, 0};

//buzzer connected on pin 3
uint8_t buzzer = 3;

//State prototype - needed because of a change introduced in Arduino 1.6.6
void sDefault();

//Define StateMachine
SM sm(sDefault);

//Alarms
TemperatureAlarm tempAlarms[] = {{0,0,false,false,false},
                                 {0,0,false,false,false},
                                 {0,0,false,false,false}};
TimerAlarm timerAlarm = {0,0,0,false,false};

bool alarmActive =    false;
bool alarmTriggered = false;
uint8_t alarmCursor = 1;
uint8_t buzzerState = LOW;

unsigned long alarmLastChecked = 0;
unsigned long buzzerTimer = 0;

uint8_t lcdBacklightState = HIGH;

void setup() {
  //initialize input/output pins
  pinMode(buttonTimer.pin, INPUT); 
  pinMode(buttonAlarm.pin, INPUT); 
  pinMode(buzzer, OUTPUT);

  // initialize the lcd
  lcd.begin(2,16);  
  lcd.createChar(0, alarmSymbol);
  lcd.clear(); 
  lcd.setBacklight(lcdBacklightState);

  // Start up the ds18b20 library
  sensors.begin();
  sensors.setWaitForConversion(false); //run in async mode - don't wait for probes
  numberOfDevices = sensors.getDeviceCount();
  for(int i=0;i<numberOfDevices;i++)
  {
    sensors.getAddress(probes[i], i);
    sensors.setResolution(probes[i],TEMPERATURE_PRECISION);
  }
  sensors.requestTemperatures();

  //Print start values to LCD
  lcd.setCursor(0,0);
  lcd.print(F("Initialiserer..."));
  lcd.setCursor(0,1);
  lcd.print(F("Fandt "));
  lcd.print(numberOfDevices,DEC);
  lcd.print(F(" prober."));
  delay(5000);
  lcd.clear();
  lcd.setCursor(8,1);
  lcd.print(F("0:00:00"));

}

void loop() {
  //Run state machine
  EXEC(sm);
}

//////////////////////////
//Functions 
//////////////////////////
void updateTimer() {
  int s = (timer.elapsed()/1000) % 60;
  int m = (timer.elapsed()/60000) % 60;
  int h = (timer.elapsed()/3600000);
  char buf[10];
  sprintf(buf,"%d:%02d:%02d",h,m,s);
  lcd.setCursor(8,1);
  lcd.print(buf);
  if(timerAlarm.set) {
    lcd.write((uint8_t)0); //custom alarm symbol
  }
}

void updateTemperatures() {
  //place cursor depending on probe number
  for(uint8_t i=0;i<numberOfDevices; i++) {
    if(i == 0) lcd.setCursor(0,0);
    if(i == 1) lcd.setCursor(8,0);
    if(i == 2) lcd.setCursor(0,1);
    //Print temperature
    float tempC = sensors.getTempC(probes[i]);
    lcd.print(i+1,DEC);
    lcd.print(F(":"));
    lcd.print(tempC,1);
    if(tempAlarms[i].set) {
      lcd.write((uint8_t)0); //custom alarm symbol
    }
    tempAlarms[i].lastValue = int(tempC);
  }
  // Send the command to get temperatures for next reading.
  sensors.requestTemperatures(); 
}

void resetTimer() {
  timer.stop();
  timer.reset();
  lcd.setCursor(8,1);
  lcd.print(F("0:00:00"));
}

void toggleTimer() {
  if(timer.isRunning()) {
    timer.stop();
  } else {
    timer.start();
  }
}

void toggleLCDBacklight() {
  lcdBacklightState = !lcdBacklightState;
  lcd.setBacklight(lcdBacklightState);
}

void updateAlarmScreen() {
  char buf[10];
  for(uint8_t i=0;i<numberOfDevices; i++) {
    if(i == 0) lcd.setCursor(0,0);
    if(i == 1) lcd.setCursor(8,0);
    if(i == 2) lcd.setCursor(0,1);
    sprintf(buf, "%d:%02d", i+1, tempAlarms[i].target);
    lcd.print(buf);
    if(tempAlarms[i].set) {
      lcd.write((uint8_t)0); //custom alarm symbol
    }
  }
  lcd.setCursor(8,1);
  sprintf(buf,"%d:%02d:%02d",timerAlarm.h,timerAlarm.m,timerAlarm.s);
  lcd.print(buf);
  if(timerAlarm.set) {
    lcd.write((uint8_t)0); //custom alarm symbol
  }
  setAlarmCursorPos();
  lcd.blink();
}

void setAlarmCursorPos() {
  //blink cursor on active alarm digit
  switch(alarmCursor) {
    case 1: lcd.setCursor(2,0); break;
    case 2: lcd.setCursor(3,0); break;
    case 3: lcd.setCursor(10,0); break;
    case 4: lcd.setCursor(11,0); break;
    case 5: lcd.setCursor(2,1); break;
    case 6: lcd.setCursor(3,1); break;
    case 7: lcd.setCursor(8,1); break;
    case 8: lcd.setCursor(10,1); break;
    case 9: lcd.setCursor(11,1); break;
    case 10: lcd.setCursor(13,1); break;
    case 11: lcd.setCursor(14,1); break;
  }
}

void increaseAlarmValue() {
  switch(alarmCursor) {
    case 1: tempAlarms[0].target += 10; break;
    case 2: tempAlarms[0].target ++;    break;
    case 3: tempAlarms[1].target += 10; break;
    case 4: tempAlarms[1].target ++;    break;
    case 5: tempAlarms[2].target += 10; break;
    case 6: tempAlarms[2].target ++;    break;
    case 7: timerAlarm.h ++;     break;
    case 8: timerAlarm.m += 10;  break;
    case 9: timerAlarm.m ++;     break;
    case 10: timerAlarm.s += 10; break;
    case 11: timerAlarm.s ++;    break;
  }
  //make sure values are still within valid range
  for(uint8_t i = 0;i<numberOfDevices;i++) {
    if(tempAlarms[i].target > 99) tempAlarms[i].target = tempAlarms[i].target % 10;
  }
  if(timerAlarm.h > 9) timerAlarm.h = timerAlarm.h % 10;
  if(timerAlarm.m > 59) timerAlarm.m = timerAlarm.m % 10;
  if(timerAlarm.s > 59) timerAlarm.s = timerAlarm.s % 10;
  updateAlarmScreen();
}

void moveAlarmCursor() {
  if (alarmCursor < numberOfDevices*2) {
    alarmCursor++; //next probe digit
  } else if (alarmCursor == numberOfDevices*2) {
    alarmCursor = 7; //no more probes - jump to alarm time
  } else if (alarmCursor < 11) {
    alarmCursor++; //next timer value
  } else {
    alarmCursor = 1; //back to first digit
  }
  setAlarmCursorPos();
}

void toggleAlarmState() {
  if(alarmCursor <= 6) {
    //cursor is at one of the temp alarms - find out which
    uint8_t i = 0;
    if(alarmCursor == 1 || alarmCursor == 2) {
      i = 0;
    } else if(alarmCursor == 3 || alarmCursor == 4) {
      i = 1;
    } else if(alarmCursor == 5 || alarmCursor == 6) {
      i = 2;
    }
    if(tempAlarms[i].set == false) {
      tempAlarms[i].set = true;
      if(tempAlarms[i].lastValue < tempAlarms[i].target) {
        tempAlarms[i].alertOnHigher = true;
      } else {
        tempAlarms[i].alertOnHigher = false;
      }
      alarmActive = true;
    } else {
      tempAlarms[i].set = false;
    }
  } else {
    //timer alarm
    timerAlarm.set = !timerAlarm.set;
    if(timerAlarm.set) alarmActive = true;
  }
  updateAlarmScreen();
}

void checkAlarm() {
  for(uint8_t i=0;i<numberOfDevices; i++) {
    if(tempAlarms[i].set) {
      float tempC = sensors.getTempC(probes[i]);
      if((tempAlarms[i].alertOnHigher && tempC >= tempAlarms[i].target) || (!tempAlarms[i].alertOnHigher && tempC <= tempAlarms[i].target)) {
        tempAlarms[i].triggered = true;
        alarmTriggered = true;
      }
    }
  }
  if(timer.isRunning() && timerAlarm.set) {
    uint8_t s = (timer.elapsed()/1000) % 60;
    uint8_t m = (timer.elapsed()/60000) % 60;
    uint8_t h = (timer.elapsed()/3600000);
    if(h == timerAlarm.h && m == timerAlarm.m && s >= timerAlarm.s) {
      timerAlarm.triggered = true;
      alarmTriggered = true;
    }
  }
}

void soundAlarm() {
  if(millis() - buzzerTimer > 500) {
    buzzerTimer = millis();
    buzzerState = !buzzerState;
    digitalWrite(buzzer,buzzerState);

    //blink alarm symbol
    for(uint8_t i=0;i<numberOfDevices;i++) {
      if(tempAlarms[i].triggered) {
        if(i == 0) lcd.setCursor(6,0);
        if(i == 1) lcd.setCursor(14,0);
        if(i == 2) lcd.setCursor(6,1);
        if(buzzerState == HIGH) {
          lcd.write((uint8_t)0);
        } else {
          lcd.print(F(" "));
        }
      }
    }
    if(timerAlarm.triggered) {
       lcd.setCursor(15,1);
      if(buzzerState == HIGH) {
        lcd.write((uint8_t)0);
      } else {
        lcd.print(F(" "));
      }
    }
  }
}

void silenceAlarm() {
  digitalWrite(buzzer, LOW);
  alarmTriggered = false;
  for(byte i=0;i<numberOfDevices; i++) {
    if(tempAlarms[i].triggered) {
      tempAlarms[i].triggered = false;
      tempAlarms[i].set = false;
      if(i == 0) lcd.setCursor(6,0);
      if(i == 1) lcd.setCursor(14,0);
      if(i == 2) lcd.setCursor(6,1);
      lcd.print(F(" "));
    }
  }
  if(timerAlarm.triggered) {
    timerAlarm.triggered = false;
    timerAlarm.set = false;
    lcd.setCursor(15,1);
    lcd.print(F(" "));
  }
}

//////////////////////////
// States
//////////////////////////
State sDefault() {
  if(millis() - timerLastUpdated > updateTimerInterval) {
    timerLastUpdated = millis();
    updateTimer();
  } 
  if(millis() - tempLastUpdated > updateTemperatureInterval) {
    tempLastUpdated = millis();
    updateTemperatures();
  }
  if(alarmActive && (millis() - alarmLastChecked > 500)) {
    alarmLastChecked = millis();
    if(!alarmTriggered) {
      checkAlarm();
    }
  }
  if(alarmTriggered) {
    soundAlarm();
  }
  if(analogRead(buttonTimer.pin) > 100) {
    buttonTimer.timer = millis();
    sm.Set(sTimerWait);
  }
  if(analogRead(buttonAlarm.pin) > 100) {
    buttonAlarm.timer = millis();
    sm.Set(sAlarmWait);
  }
}

State sTimerWait() {
  if(millis() - buttonTimer.timer > buttonLongPressTime) {
    //long press
    resetTimer();
    sm.Set(sTimerReleaseWait);
  } else if(analogRead(buttonTimer.pin) < 100) {
    //button released
    toggleTimer();
    sm.Set(sDefault);
  }
}

State sTimerReleaseWait() {
  //wait for button release
  if(analogRead(buttonTimer.pin) < 100) {
    buttonTimer.timer = 0;
    sm.Set(sDefault);
  }
}

State sAlarmWait() {
  if(alarmTriggered) {
    silenceAlarm();
    sm.Set(sAlarmReleaseWait);
  } else {
    if(millis() - buttonAlarm.timer > buttonLongPressTime) {
      toggleLCDBacklight();
      sm.Set(sAlarmReleaseWait);
    }
    if(analogRead(buttonAlarm.pin) < 100) {
      lcd.clear();
      alarmCursor = 1;
      updateAlarmScreen();
      sm.Set(sShowAlarm);
    }
  }
}

State sAlarmReleaseWait() {
  if(analogRead(buttonAlarm.pin) < 100) {
    sm.Set(sDefault);
  }
}

State sShowAlarm() {
  if(sm.Timeout(5000)) {
    //no activity for 5 sec - return to default state
    lcd.noBlink();
    updateTimer();
    updateTemperatures();
    sm.Set(sDefault);
  }
  if(analogRead(buttonTimer.pin) > 100) {
    buttonTimer.timer = millis();
    sm.Set(sTimerWait1);
  }
  if(analogRead(buttonAlarm.pin) > 100) {
    buttonAlarm.timer = millis();
    sm.Set(sAlarmWait1);
  }
}

State sTimerWait1() {
  if(analogRead(buttonTimer.pin) < 100) {
    increaseAlarmValue();
    sm.Set(sShowAlarm);
  }
}

State sAlarmWait1() {
  if(millis() - buttonAlarm.timer > buttonLongPressTime) {
    //long press
    toggleAlarmState();
    sm.Set(sTimerReleaseWait1);
  } else if(analogRead(buttonAlarm.pin) < 100) {
    //button released
    moveAlarmCursor();
    sm.Set(sShowAlarm);
  }
}

State sTimerReleaseWait1() {
  if(analogRead(buttonAlarm.pin) < 100) {
    sm.Set(sShowAlarm);
  }
}
Forbindelsesdiagram:
Termometer.png
Termometer.png (149.34 KiB) Vist 12673 gange
Håber der er nogen der kan bruge det.

/Rasmus
Brugeravatar
Nimbus39
Indlæg: 3392
Tilmeldt: 27. jun 2010, 09:52
Geografisk sted: Greve (Mosede Strand)
Kontakt:

Re: DIY Arduino Termometer

Indlæg af Nimbus39 »

Fedt at se der er nogen der faktisk kan bruge det man laver og især udvikle videre på det :-)
Buy a man a beer and he wastes an hour. Teach a man to brew and he wastes a lifetime.
http://bryggeri.landly.dk
http://www.facebook.com/bryggerilandly
http://beersmithrecipes.com/listrecipes/2810/nimbus39
rasmusa
Indlæg: 17
Tilmeldt: 14. feb 2014, 23:25
Geografisk sted: Strandby, Nordjylland

Re: DIY Arduino Termometer

Indlæg af rasmusa »

Det var et super fedt 1. projekt på Arduinoen - og det bliver helt sikkert ikke det sidste.

Lige et hurtigt tip, som jeg kæmpede noget med: Som udgangspunkt tager det DallasTemperature bibioloteket laaaaang tid at returnere fra en sensors.requestTemperatures() kommando - op til 1 sek. når man kører med en præcision på 12. Det gjorde at opdateringen af timeren hakkede.

Efter en del søgen rundt fandt jeg en løsning. Hvis man sætter sensors.setWaitForConversion(false) returnerer sensors.requestTemperatures() med det samme, og det er så op til programmet at vente med at læse målingerne til de er klar.

Ved at gøre det på den måde kan jeg uden problemet læse temperaturer hvert sekund, og så slutte af med en sensors.requestTemperatures() - så er de klar til næste iteration et sekund senere. En fuld opdatering på denne måde tog 61ms da jeg målte med tre sensorer på præcision 12.

/Rasmus
Brugeravatar
maseol
Indlæg: 342
Tilmeldt: 10. feb 2010, 09:15
Geografisk sted: Nivå - Nordsjælland

Re: DIY Arduino Termometer

Indlæg af maseol »

når du nu har termometeret, er det så ikke nærliggende at udbygge til en PID?
Bryg hilsner
Thomas

Two beers or not two beers....that's the question
Brugeravatar
Nimbus39
Indlæg: 3392
Tilmeldt: 27. jun 2010, 09:52
Geografisk sted: Greve (Mosede Strand)
Kontakt:

Re: DIY Arduino Termometer

Indlæg af Nimbus39 »

maseol skrev:når du nu har termometeret, er det så ikke nærliggende at udbygge til en PID?
Jo, det er det - man skal blot bruge et par relæer, nogle trykknapper og et par biblioteker mere, men da jeg brygger på gas er det ikke relevant for mig. Jeg håber at nogen vil løbe med ideen for det er sjovt at se "mit" lille projekt udvikle sig :-)
Buy a man a beer and he wastes an hour. Teach a man to brew and he wastes a lifetime.
http://bryggeri.landly.dk
http://www.facebook.com/bryggerilandly
http://beersmithrecipes.com/listrecipes/2810/nimbus39
Besvar

Tilbage til "Microprocessor styring til ølbrygning"