Hirdetés

2024. május 12., vasárnap

Gyorskeresés

Hozzászólások

(#40) schawo válasza tvamos (#38) üzenetére


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;

}

evDirect villanyautós töltőhálózat

Copyright © 2000-2024 PROHARDVER Informatikai Kft.