└── ghetto_sous_vide.pde /ghetto_sous_vide.pde: -------------------------------------------------------------------------------- 1 | /* 2 | Ghetto Sous Vide controller 3 | copyright 2010 Erik DeBill (erik@debill.org) 4 | 5 | License to use this code is granted under the 6 | Creative Commons Attribution-ShareAlike 3.0 Unported License 7 | http://creativecommons.org/licenses/by-sa/3.0/ 8 | 9 | If you do something with it, please leave my name in the code 10 | comments, and I'd appreciate it if you'd met me know. 11 | */ 12 | 13 | // http://code.google.com/p/max6675-arduino-library/ 14 | #include 15 | 16 | int SO = 13; // SO pin of MAX6675 17 | int CS = 12; // CS pin on MAX6675 18 | int SCK = 11; // SCK pin of MAX6675 19 | int units = 0; // Units to readout temp (0 = ˚F, 1 = ˚C) 20 | float max6675_error = 0.0; // Temperature compensation error 21 | float temperature = 0.0; 22 | 23 | // Initialize the MAX6675 Library 24 | 25 | MAX6675 temp0(CS, SO, SCK, units, max6675_error); 26 | 27 | #include 28 | //create object to control an LCD. 29 | // (RS, Enable, d4-d7) 30 | LiquidCrystal lcd(6, 5, 7, 8, 9, 10); 31 | 32 | 33 | // pins for controlling setpoint 34 | #define UP_PIN 3 35 | #define DOWN_PIN 2 36 | 37 | 38 | // pin for controlling the cooker 39 | // HIGH is on, LOW is off 40 | #define COOKER_PIN 4 41 | 42 | 43 | // how do we identify ourselves to the logging application? 44 | #define source "ghetto sous vide" 45 | 46 | // what temperature are we trying to keep the food at? 47 | int setpoint = 120; 48 | 49 | 50 | void setup(void) { 51 | lcd.begin(16,2); 52 | 53 | // initialize inputs/outputs 54 | // start serial port 55 | Serial.begin(9600); 56 | 57 | error("booting"); 58 | 59 | 60 | // temperature control pins 61 | init_button(UP_PIN); 62 | init_button(DOWN_PIN); 63 | 64 | // cooker control 65 | pinMode(COOKER_PIN, OUTPUT); 66 | 67 | delay(100); 68 | } 69 | 70 | int loop_count = 0; 71 | void loop(void) { 72 | adjust_setpoint(); 73 | 74 | temperature = temp0.read_temp(5); 75 | Serial.println((int)temperature); 76 | 77 | // if reading is outside range (probably DEVICE_DISCONNECTED) don't log it 78 | if (temperature > -67) { 79 | 80 | lcd.clear(); 81 | lcd.setCursor(0,0); // technically redundant, but clarifies things 82 | lcd.print("set:"); 83 | lcd.setCursor(0,1); 84 | lcd.print("current:"); 85 | lcd.setCursor(10,0); 86 | lcd.print(setpoint); 87 | lcd.setCursor(10,1); 88 | lcd.print((int)temperature); 89 | 90 | control_relay(COOKER_PIN, (int)temperature, setpoint); 91 | } 92 | 93 | loop_count++; 94 | delay(200); 95 | } 96 | 97 | // how many readings since last change? don't want to toggle relay too quickly 98 | void control_relay(int pin, int temperature, int setpoint) { 99 | int ideal_pin = LOW; 100 | if(temperature < setpoint) { 101 | ideal_pin = HIGH; 102 | } else { 103 | ideal_pin = LOW; 104 | } 105 | 106 | if(time_to_change(ideal_pin)){ 107 | digitalWrite(pin, ideal_pin); 108 | } 109 | } 110 | 111 | int count_at_last_change = 0; 112 | int prev_setting = LOW; 113 | bool time_to_change(int ideal_pin) { 114 | 115 | if (ideal_pin == prev_setting) { 116 | return false; 117 | } 118 | 119 | if (((loop_count - count_at_last_change) > 25) || // 5 seconds 120 | (loop_count < count_at_last_change)) { // we wrapped around 121 | count_at_last_change = loop_count; 122 | prev_setting = ideal_pin; 123 | 124 | return true; 125 | } 126 | 127 | } 128 | 129 | void adjust_setpoint() { 130 | if(button_pressed(UP_PIN)) { 131 | setpoint++; 132 | } 133 | 134 | if(button_pressed(DOWN_PIN)) { 135 | setpoint--; 136 | } 137 | } 138 | 139 | void init_button(int button) { 140 | pinMode(button, INPUT); 141 | digitalWrite(button, HIGH); 142 | } 143 | 144 | bool button_pressed(int button) { 145 | if (digitalRead(button) == LOW) { 146 | return true; 147 | } else { 148 | return false; 149 | } 150 | } 151 | 152 | 153 | void error(char *msg) { 154 | Serial.print(source); 155 | Serial.print(" - "); 156 | Serial.println(msg); 157 | } 158 | 159 | 160 | --------------------------------------------------------------------------------