- Yettel topik
- OFFTOPIK: Earfun-lányok Sencsenben
- Akciófigyelő: Kedvezményekkel nyílt új Xiaomi Partner üzlet a Westendben
- Netfone
- EarFun Air Pro 4 - a cél a csúcs
- Samsung Galaxy Watch7 - kötelező kör
- Poco F7 – bajnokesélyes
- Samsung Galaxy A56 - megbízható középszerűség
- Ilyen vékony lesz a Huawei Mate 70 Air
- Milyen hagyományos (nem okos-) telefont vegyek?
Új hozzászólás Aktív témák
-
schawo
titán
Itt egy kód. Nem a végleges, mert azt most valamiért nem találom (asszem notin fejeztem be, az meg most nincs velem), de a lényeg megvan itt is.
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>
#include <Metro.h>
#include <PID_v1.h>
#include <PID_AutoTune_v0.h>
#define ONE_WIRE_BUS_PIN 0
#define TIME_INTERVAL 100
#define INITIAL_INTERVAL 800
#define REPEAT_INTERVAL 100
Metro keyboardTimer(100); // keyboard timer intervals
Metro cookingTimer(1000); // confirm timer
Metro powerTimer(100);
OneWire oneWire(ONE_WIRE_BUS_PIN);
DallasTemperature sensors(&oneWire);
DeviceAddress Probe01 = { 0x28, 0x2C, 0xBA, 0xE6, 0x03, 0x00, 0x00, 0x83 };
DeviceAddress Probe02 = { 0x28, 0xEA, 0xD8, 0xE6, 0x03, 0x00, 0x00, 0x3C };
DeviceAddress Probe03 = { 0x28, 0xE6, 0xD7, 0xE6, 0x03, 0x00, 0x00, 0x2E };
DeviceAddress Probe04 = { 0x28, 0xEB, 0xBD, 0xE6, 0x03, 0x00, 0x00, 0xC8 };
LiquidCrystal lcd(8, 9, 10, 11, 12, 13); // setup LCD
#define keyboardAnalogInput 0 // keyboard analog pin
// #define MAX_STRING_LEN = 32;
// #define MAX_WORDS = 10;
// lang definitions
const char* TEXT_WELCOME_L1 = "Sous Viduino";
const char* TEXT_WELCOME_L2 = "Udvozollek!";
const char* TEXT_TEMP_LONG = "Homerseklet";
const char* TEXT_TEMP = "H";
const char* TEXT_DEG = "C";
const char* TEXT_TIME_LONG = "Fozesi ido";
const char* TEXT_TIME = "I";
const char* TEXT_MINUTE = "perc";
const char* TEXT_CURRENT_TEMP_L1 = "Pillanatnyi";
const char* TEXT_CURRENT_TEMP_L2 = "homerseklet";
const char* TEXT_TIME_REMAINING = "Hatralevo ido";
const char* TEXT_ARE_YOU_SURE = "Egeszen biztos?";
const char* TEXT_YES = "IGEN";
const char* TEXT_NO = "NEM";
const char* TEXT_BACK = "Vissza";
const char* TEXT_START_COOKING = "Fozes inditasa";
const char* TEXT_PREHEATING = "Elomelegites";
const char* TEXT_COOKING = "Fozes";
const char* TEXT_TURN_OFF = "Kikapcsolas";
const char* TEXT_BYE_L1 = "Sous Viduino";
const char* TEXT_BYE_L2 = "Viszlat!";
const char* TEXT_ERROR = "Hijnye, baj van.";
const char* TEXT_SENSOR_FAIL = "Homero hiba.";
// keyboard button definitions
#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnENTER 4
#define confNONE 5
#define confNO 0
#define confYES 1
int keyIn = 0; // keyboard analog value
int buttonPressed; // keyboard digital value
int i = 0;
int prevButton = confNONE; // stores previous digital value
int counter = 0; // for keyoard repeats
int Temp = 50;
int Time = 240;
int menuItem = 1;
int menuSize = 3;
int confValue = confNO;
int Confirm = 0;
int Cooking = 0;
int Error = 0;
int tempError = 0;
const char* Status = TEXT_PREHEATING;
float temp1;
float temp2;
float temp3;
float temp4;
float tempAvg;
unsigned int timeRemaining = 0;
int tempSetting = 0;
//////////////////////
byte ATuneModeRemember = 2;
double input = 40, output = 1000, setpoint = 30;
double kp = 1000, ki = 0.0, kd = 0.0;
double kpmodel = 1.5, taup = 100, theta[50];
double outputStart = 5;
double aTuneStep = 50, aTuneNoise = 1, aTuneStartValue = 400;
unsigned int aTuneLookBack = 20;
boolean tuning = false;
unsigned long modelTime, serialTime;
PID myPID(&input, &output, &setpoint, kp, ki, kd, DIRECT);
PID_ATune aTune(&input, &output);
//set to false to connect to the real world
boolean useSimulation = false;
///////////////////////
void setup()
{
sensors.begin();
sensors.setResolution(Probe01, 12);
sensors.setResolution(Probe02, 12);
sensors.setResolution(Probe03, 12);
sensors.setResolution(Probe04, 12);
delay(500);
lcd.begin(16, 2); // init LCD
lcd.print(TEXT_WELCOME_L1);
lcd.setCursor(0, 1);
lcd.print(TEXT_WELCOME_L2);
delay(3000);
lcd.clear();
lcd.print(TEXT_TEMP_LONG);
lcd.setCursor(0, 1);
lcd.print("50 C");
////////////////////////
myPID.SetOutputLimits(0, 1000);
if(useSimulation) {
for(byte i = 0; i < 50; i++) {
theta[i] = outputStart;
}
modelTime = 0;
}
//Setup the pid
myPID.SetMode(AUTOMATIC);
if(tuning) {
tuning = false;
changeAutoTune();
tuning = true;
}
//////////////////////
}
void loop()
{
if (keyboardTimer.check() == 1 && !Error) {
lcd.setCursor(0, 1);
buttonPressed = readKeyboard(); // read digital value
if (buttonPressed == confNONE) counter = 0; // if button released, reset counter
if (prevButton == buttonPressed) { // if button kept pressed
++counter;
if (counter < (INITIAL_INTERVAL / TIME_INTERVAL) || counter % (REPEAT_INTERVAL / TIME_INTERVAL)) buttonPressed = confNONE; // if repeat timer not active, drop keyboard value
} else if (buttonPressed == confNONE) prevButton = buttonPressed;
if (buttonPressed != confNONE) // if new key or repeat active
{
switch(buttonPressed) {
int result;
case btnUP:
if(menuItem > 3) break; // draw only for main menu
menuItem = (menuItem == 1) ? menuSize : menuItem - 1; // move in the main menu
showMenu(menuItem);
break;
case btnDOWN:
if(menuItem > 3) break; // draw only for main menu
menuItem = (menuItem == menuSize) ? 1 : menuItem + 1; // move in main menu
showMenu(menuItem);
break;
case btnRIGHT:
switch(menuItem) {
case 1:
showValue(++Temp, TEXT_DEG); // increase temp
break;
case 2:
if(Time < 999) showValue(++Time, TEXT_MINUTE); // increase time
break;
case 4:
showConfirm(confValue = ((confValue == confYES) ? confNO : confYES)); // select reply
break;
}
break;
case btnLEFT:
if (menuItem == 1 && Temp > 0) showValue(--Temp, TEXT_DEG); // decrease temp, stay above zero
if (menuItem == 2 && Time > 0) showValue(--Time, TEXT_MINUTE); // decrease time, stay above zero
if (menuItem == 4) showConfirm(confValue = ((confValue == confYES) ? confNO : confYES)); // select reply
break;
case btnENTER:
switch(menuItem) {
case 3: // show confirm menu
Confirm = 1;
confValue = confNO;
showConfirm(confValue);
menuItem = 4;
break;
case 4:
Confirm = 0;
if(confValue == confYES) { // start cooking
Cooking = 1;
menuItem = 5;
timeRemaining = Time * 60;
tempSetting = Temp;
setpoint = tempSetting;
lcd.clear();
}
else {
menuItem = 1; // return to main menu
showMenu(menuItem);
}
}
break;
}
prevButton = buttonPressed; // store
}
}
if (cookingTimer.check() == 1 && Cooking && !Error) {
// showStatus(Status);
if (Status == TEXT_COOKING) timeRemaining--;
sensors.requestTemperatures();
temp1 = sensors.getTempC(Probe01);
temp2 = sensors.getTempC(Probe02);
temp3 = sensors.getTempC(Probe03);
temp4 = sensors.getTempC(Probe04);
if (temp1 > 0 && temp1 < 110 && temp2 > 0 && temp2 < 110 && temp3 > 0 && temp3 < 110 && temp4 > 0 && temp4 < 110) {
tempError = 0;
tempAvg = (temp1 + temp2 + temp3 + temp4) / 4;
/* lcd.setCursor(0, 1);
lcd.print(TEXT_TEMP);
lcd.print(":");
lcd.print(tempAvg);
lcd.print(" ");
lcd.setCursor(8, 1);
lcd.print(TEXT_TIME);
lcd.print(":");
lcd.print(timeRemaining / 60);
lcd.print(":");
if (timeRemaining % 60 < 10) lcd.print("0");
lcd.print(timeRemaining % 60); */
/////////////////////////
if(!useSimulation) input = tempAvg;
if(tuning) {
byte val = (aTune.Runtime());
if (val != 0) {
tuning = false;
}
if(!tuning) { //we're done, set the tuning parameters
kp = aTune.GetKp();
ki = aTune.GetKi();
kd = aTune.GetKd();
myPID.SetTunings(kp, ki, kd);
AutoTuneHelper(false);
}
}
else myPID.Compute();
if(useSimulation) {
theta[30] = output;
DoModel();
}
//// else analogWrite(0,output);
//send-receive with processing if it's time
SerialSend();
//////////////////
} else {
if (++tempError > 10) {
lcd.clear();
lcd.print(TEXT_ERROR);
lcd.setCursor(0, 1);
lcd.print(TEXT_SENSOR_FAIL);
Error = 1;
}
}
}
}
int showStatus(const char* currStatus) {
lcd.setCursor(0, 0);
lcd.print(currStatus);
}
int readKeyboard()
{
keyIn = analogRead(keyboardAnalogInput);
// read the value from the sensor
// buttons when read are centered at these values: 0, 144, 329, 504, 741
// add approx 70 to those values and check to see if we are close
if (keyIn > 1000) return confNONE;
if (keyIn < 70) return btnLEFT;
if (keyIn < 215) return btnUP;
if (keyIn < 400) return btnDOWN;
if (keyIn < 575) return btnRIGHT;
if (keyIn < 810) return btnENTER;
return confNONE; // when all others fail, return this...
}
void showValue(int Value, const char* Unit) {
lcd.setCursor(0, 1);
lcd.print(Value);
lcd.print(" ");
lcd.print(Unit);
lcd.print(" "); // to clear
}
void showMenu(int Menu) {
lcd.clear();
switch(Menu) {
case 1:
lcd.print(TEXT_TEMP_LONG); // temp
showValue(Temp, TEXT_DEG);
break;
case 2:
lcd.print(TEXT_TIME_LONG); // time
showValue(Time, TEXT_MINUTE);
break;
case 3:
lcd.print(TEXT_START_COOKING);
break;
// default:
// lcd.print(TEXT_ERROR);
}
}
void showConfirm(int Value)
{
if (Confirm == 1) {
lcd.clear(); // reset screen for first use only
lcd.print(TEXT_ARE_YOU_SURE);
Confirm++;
}
lcd.setCursor(0, 1); // draw selection
if (Value == confYES) lcd.print("#"); else lcd.print(" ");
lcd.print(TEXT_YES);
if (Value == confYES) lcd.print("#"); else lcd.print(" ");
if (Value == confNO) lcd.print("#"); else lcd.print(" ");;
lcd.print(TEXT_NO);
if (Value == confNO) lcd.print("#"); else lcd.print(" ");;
}
void printTemperature(DeviceAddress deviceAddress, byte pos)
{
float tempC = sensors.getTempC(deviceAddress);
switch(pos) {
case 1:
lcd.setCursor(0, 0);
break;
case 2:
lcd.setCursor(8, 0);
break;
case 3:
lcd.setCursor(0, 1);
break;
case 4:
lcd.setCursor(8, 1);
break;
}
if (tempC == -127.00) lcd.print("Error"); else lcd.print(tempC);
}
/////////////////////////////
void changeAutoTune()
{
if(!tuning)
{
//Set the output to the desired starting frequency.
output = aTuneStartValue;
aTune.SetNoiseBand(aTuneNoise);
aTune.SetOutputStep(aTuneStep);
aTune.SetLookbackSec((int)aTuneLookBack);
AutoTuneHelper(true);
tuning = true;
}
else
{ //cancel autotune
aTune.Cancel();
tuning = false;
AutoTuneHelper(false);
}
}
void AutoTuneHelper(boolean start)
{
if(start)
ATuneModeRemember = myPID.GetMode();
else
myPID.SetMode(ATuneModeRemember);
}
void SerialSend()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("i"); lcd.print(input); lcd.print(" ");
lcd.print("o"); lcd.print(output); // lcd.print(" ");
lcd.setCursor(0, 1);
// if(tuning){
// lcd.print("tuning mode");
// } else {
lcd.print("p"); lcd.print(myPID.GetKp()); // lcd.print(" ");
lcd.print("i"); lcd.print(myPID.GetKi()); // lcd.print(" ");
lcd.print("d"); lcd.print(myPID.GetKd());
// }
}
void DoModel()
{
//cycle the dead time
for(byte i=0;i<49;i++)
{
theta[i] = theta[i+1];
}
//compute the input
input = (kpmodel / taup) *(theta[0]-outputStart) + input*(1-1/taup) + ((float)random(-10,10))/100;
} -
schawo
titán
Legyen valamilyen öntanuló elektronikája, a relé kimenő teljesítménye elegendő legyen (ezzel nem lesz gond), és az elektronika tényleg tudja, amit ráírtak (ez valószínű)
Továbbá szüksége lesz egy vízmozgatóra is (keverő vagy szivattyú), különben nagyon egyenetlen lesz a vízhőmérséklet. Az én itteni példámból hiányzik a vízmozgató, de van 4 hőmérő és 2 forraló. Viszont ez így ebben a formában működésképtelen volt. Amikor viszont belekerült a vízmozgató, utána elég volt egy forraló és egy hőmérő (van az említett csomagban).
-
schawo
titán
válasz
sing1ep1ayer #13 üzenetére
-
schawo
titán
válasz
sing1ep1ayer #11 üzenetére
A kész étel fagyasztás nélkül hetekig eláll a hűtőben, tehát bármikor előre elkészítheted. Tálalás előtt csak át kell sütni egy pillanatra, hogy sültes kérge keletkezzen. Tehát az ebéd elkészítése a fogyasztás előtt csak pár percet vesz igénybe, ennél gyorsabban nem lehet ételt készíteni. A bonyolultabb ételek így készülnek a jobb éttermekben, ellenkező esetben szegény vendégnek órákat kellene várnia.
A fűtőszállal nem lesz gond, nem megy az folyamatosan, a PWM vezérléssel kábé 5-10%-on fűt, hogy tartsa a hőmérsékletet.
-
schawo
titán
Az alapmenüt megszakításokkal fogom vezérelni, egy megszakításrutinban a delay pedig maga a halál
(#3) lapa
1. Minden húsfajtának megvan a maga receptje (hőmérséklet, idő). Ha az összes mérési ponton eléri a kívánt hőmérsékletet a víz, akkor indul a főzési idő.2. Igen, a főzési időre van hatással. De az állaga is más egy kuktás ételnek, mint egy nem kuktásnak. Ugyanígy különbözik állagában a 100 fokon és az 50-70 fokon készített étel. Ezen kívül az étel nem érintkezik sem vízzel, sem oxigénnel.
3. Valóban nincs effektív vákuum. Azért kell vákuumfóliázni, mert így a zacskóban nincs jelen hőszigetelő levegőbuborék, ami miatt nem lenne garantálható a maghőmérséklet, továbbá se a főzés során, sem pedig a későbbi tárolás során nincs jelen levegő, így az étel nem oxidálódik, jobb az íz, és tovább eltartható.
Ez első rész, a cikk következő részében lesznek képek, Arduino kód, videó.
(#4) hcl
Az ábrák painttel készültek(#5) sonar
Olyan nincs, hogy valami nem sörnyitó
Új hozzászólás Aktív témák
- Apple iPhone 15 Pro, 128Gb, független, fekete, 1 év garancia
- AMD Ryzen 5 5600X 6-Core 3.7GHz AM4
- Bomba ár! HP ProBook 430 G3 - i3-6GEN I 4GB I 128SSD I HDMI I 13,3" HD I Cam I W10 I Garancia!
- Bomba ár! HP ProBook 430 G5 - i3-7GEN I 4GB I 128GB SSD I HDMI I 13,3" FHD I Cam I W11 I Garancia!
- Bomba ár! HP EliteBook 845 G11 - Ryzen 5 8540U I 16GB I 512SSD I 14,1" Touch I Cam I W11 I NBD Gari!
- Acer TravelMate P214 i3-1115G4 16GB 512GB 14" FHD 1év garancia
- HIBÁTLAN APPLE WATCH ULTRA 2 NATURAL TITANIUM 49MM -1 ÉV GARANCIA - MS3714, 100% AKKUMULÁTOR
- 20 GB-os RTX 4000 SFF ADA Generation
- GYÖNYÖRŰ iPhone 13 mini 128GB Midnight -1 ÉV GARANCIA - Kártyafüggetlen, MS3332
- Apple iPhone 11 Pro Max / 64GB / Kártyafüggetlen / 12Hó Garancia / 100% akku
Állásajánlatok
Cég: Promenade Publishing House Kft.
Város: Budapest
Cég: NetGo.hu Kft.
Város: Gödöllő