00001
00021 #include <stdlib.h>
00022 #include <stdio.h>
00023 #include <errno.h>
00024 #include <math.h>
00025
00026 #include "house_e.h"
00027 #include "dryer.h"
00028
00030
00032 CLASS* dryer::oclass = NULL;
00033 CLASS* dryer::pclass = NULL;
00034 dryer *dryer::defaults = NULL;
00035
00036 dryer::dryer(MODULE *module) : residential_enduse(module)
00037 {
00038
00039 if (oclass==NULL)
00040 {
00041 pclass = residential_enduse::oclass;
00042
00043
00044 oclass = gl_register_class(module,"dryer",sizeof(dryer),PC_PRETOPDOWN|PC_BOTTOMUP|PC_AUTOLOCK);
00045 if (oclass==NULL)
00046 GL_THROW("unable to register object class implemented by %s",__FILE__);
00047
00048
00049 if (gl_publish_variable(oclass,
00050 PT_INHERIT, "residential_enduse",
00051 PT_double,"motor_power[W]",PADDR(motor_power),
00052 PT_double,"dryer_coil_power[W]",PADDR(coil_power[0]),
00053 PT_double,"controls_power[W]",PADDR(controls_power),
00054 PT_double,"circuit_split",PADDR(circuit_split),
00055 PT_double,"queue[unit]",PADDR(enduse_queue), PT_DESCRIPTION, "number of loads accumulated",
00056 PT_double,"queue_min[unit]",PADDR(queue_min),
00057 PT_double,"queue_max[unit]",PADDR(queue_max),
00058 PT_double,"stall_voltage[V]", PADDR(stall_voltage),
00059 PT_double,"start_voltage[V]", PADDR(start_voltage),
00060 PT_complex,"stall_impedance[Ohm]", PADDR(stall_impedance),
00061 PT_double,"trip_delay[s]", PADDR(trip_delay),
00062 PT_double,"reset_delay[s]", PADDR(reset_delay),
00063 PT_double,"total_power[W]",PADDR(total_power),
00064
00065 PT_enumeration,"state", PADDR(state),
00066 PT_KEYWORD,"STOPPED",(enumeration)DRYER_STOPPED,
00067 PT_KEYWORD,"STALLED",(enumeration)DRYER_STALLED,
00068 PT_KEYWORD,"TRIPPED",(enumeration)DRYER_TRIPPED,
00069 PT_KEYWORD,"MOTOR_ONLY",(enumeration)DRYER_MOTOR_ONLY,
00070 PT_KEYWORD,"MOTOR_COIL_ONLY",(enumeration)DRYER_MOTOR_COIL_ONLY,
00071 PT_KEYWORD,"CONTROL_ONLY",(enumeration)DRYER_CONTROL_ONLY,
00072
00073
00074 PT_double,"energy_baseline[kWh]",PADDR(energy_baseline),
00075 PT_double,"energy_used[kWh]",PADDR(energy_used),
00076 PT_double,"next_t",PADDR(next_t),
00077 PT_bool,"control_check",PADDR(control_check),
00078
00079 PT_bool,"motor_only_check1",PADDR(motor_only_check1),
00080 PT_bool,"motor_only_check2",PADDR(motor_only_check2),
00081 PT_bool,"motor_only_check3",PADDR(motor_only_check3),
00082 PT_bool,"motor_only_check4",PADDR(motor_only_check4),
00083 PT_bool,"motor_only_check5",PADDR(motor_only_check5),
00084 PT_bool,"motor_only_check6",PADDR(motor_only_check6),
00085
00086 PT_bool,"dryer_on",PADDR(dryer_on),
00087 PT_bool,"dryer_ready",PADDR(dryer_ready),
00088
00089 PT_bool,"dryer_check",PADDR(dryer_check),
00090
00091 PT_bool,"motor_coil_only_check1",PADDR(motor_coil_only_check1),
00092 PT_bool,"motor_coil_only_check2",PADDR(motor_coil_only_check2),
00093 PT_bool,"motor_coil_only_check3",PADDR(motor_coil_only_check3),
00094 PT_bool,"motor_coil_only_check4",PADDR(motor_coil_only_check4),
00095 PT_bool,"motor_coil_only_check5",PADDR(motor_coil_only_check5),
00096 PT_bool,"motor_coil_only_check6",PADDR(motor_coil_only_check6),
00097
00098 PT_double,"dryer_run_prob", PADDR(dryer_run_prob),
00099 PT_double,"dryer_turn_on", PADDR(dryer_turn_on),
00100
00101 PT_double,"pulse_interval_1[s]", PADDR(pulse_interval[0]),
00102 PT_double,"pulse_interval_2[s]", PADDR(pulse_interval[1]),
00103 PT_double,"pulse_interval_3[s]", PADDR(pulse_interval[2]),
00104 PT_double,"pulse_interval_4[s]", PADDR(pulse_interval[3]),
00105 PT_double,"pulse_interval_5[s]", PADDR(pulse_interval[4]),
00106 PT_double,"pulse_interval_6[s]", PADDR(pulse_interval[5]),
00107 PT_double,"pulse_interval_7[s]", PADDR(pulse_interval[6]),
00108
00109
00110 PT_double,"energy_needed[kWh]",PADDR(energy_needed),
00111 PT_double,"daily_dryer_demand[kWh]",PADDR(daily_dryer_demand),
00112 PT_double,"actual_dryer_demand[kWh]",PADDR(actual_dryer_demand),
00113 PT_double,"motor_on_off",PADDR(motor_on_off),
00114 PT_double,"motor_coil_on_off",PADDR(motor_coil_on_off),
00115
00116
00117 PT_bool,"is_240",PADDR(is_240), PT_DESCRIPTION, "load is 220/240 V (across both phases)",
00118 NULL)<1)
00119 GL_THROW("unable to publish properties in %s",__FILE__);
00120 }
00121 }
00122
00123 dryer::~dryer()
00124 {
00125 }
00126
00127 int dryer::create()
00128 {
00129 int res = residential_enduse::create();
00130
00131
00132 load.name = oclass->name;
00133
00134 load.power = load.admittance = load.current = load.total = complex(0,0,J);
00135 load.voltage_factor = 1.0;
00136 load.power_factor = 0.95;
00137 load.power_fraction = 1;
00138 is_240 = true;
00139
00140 coil_power[0] = -1;
00141
00142 state = DRYER_STOPPED;
00143
00144 energy_used = 0;
00145
00146 last_t = 0;
00147
00148 gl_warning("explicit %s model is experimental", OBJECTHDR(this)->oclass->name);
00149
00150 return res;
00151 }
00152
00153 int dryer::init(OBJECT *parent)
00154 {
00155 OBJECT *hdr = OBJECTHDR(this);
00156 if(parent != NULL){
00157 if((parent->flags & OF_INIT) != OF_INIT){
00158 char objname[256];
00159 gl_verbose("dryer::init(): deferring initialization on %s", gl_name(parent, objname, 255));
00160 return 2;
00161 }
00162 }
00163 int rv = 0;
00164
00165 if (motor_power==0) motor_power = gl_random_uniform(&hdr->rng_state,150,350);
00166 if (heat_fraction==0) heat_fraction = 0.2;
00167 if (is_240)
00168 {
00169 load.config = EUC_IS220;
00170 if (stall_voltage==0) stall_voltage = 1.2*default_line_voltage;
00171 }
00172 else
00173 if (stall_voltage==0) stall_voltage = 0.6*default_line_voltage;
00174
00175 if (trip_delay==0) trip_delay = 10;
00176 if (reset_delay==0) reset_delay = 60;
00177
00178 if (coil_power[0]==-1) coil_power[0] = 5800;
00179
00180 start_time = 0;
00181 dryer_run_prob = 0;
00182
00183 control_check = false;
00184 dryer_check = false;
00185 next_t = 0;
00186
00187 pulse_interval[0] = 21.6;
00188 pulse_interval[1] = 32.4;
00189 pulse_interval[2] = 1287;
00190 pulse_interval[3] = 85.8 ;
00191 pulse_interval[4] = 129;
00192 pulse_interval[5] = 138;
00193 pulse_interval[6] = 60;
00194
00195 controls_power = 10;
00196 motor_power = 200;
00197 coil_power[0] = 5800;
00198
00199 enduse_queue = 0.8;
00200 queue_min = 0;
00201 queue_max = 2;
00202
00203 motor_coil_only_check1 = false;
00204 motor_coil_only_check2 = false;
00205 motor_coil_only_check3 = false;
00206 motor_coil_only_check4 = false;
00207 motor_coil_only_check5 = false;
00208 motor_coil_only_check6 = false;
00209
00210 motor_only_check1 = false;
00211 motor_only_check2 = false;
00212 motor_only_check3 = false;
00213 motor_only_check4 = false;
00214 motor_only_check5 = false;
00215 motor_only_check6 = false;
00216
00217
00218 hdr->flags |= OF_SKIPSAFE;
00219
00220 load.power_factor = 0.95;
00221 load.breaker_amps = 30;
00222 actual_dryer_demand = 0;
00223 energy_needed = 0;
00224
00225 rv = residential_enduse::init(parent);
00226
00227 if (rv==SUCCESS) update_state(0.0);
00228
00229
00230 switch(shape.type){
00231 case MT_UNKNOWN:
00232
00233 gl_warning("This device, %s, is considered very experimental and has not been validated.", get_name());
00234 break;
00235 case MT_ANALOG:
00236 if(shape.params.analog.energy == 0.0){
00237 GL_THROW("dryer does not support fixed energy shaping");
00238
00239 } else if (shape.params.analog.power == 0){
00240
00241 daily_dryer_demand = gl_get_loadshape_value(&shape) / 2.4449;
00242 } else {
00243 daily_dryer_demand = gl_get_loadshape_value(&shape);
00244 }
00245 break;
00246 case MT_PULSED:
00247
00248
00249 if(shape.params.pulsed.pulsetype == MPT_TIME){
00250 ;
00251 } else if(shape.params.pulsed.pulsetype == MPT_POWER){
00252 ;
00253 daily_dryer_demand = gl_get_loadshape_value(&shape) / 2.4449;
00254 }
00255 break;
00256 case MT_MODULATED:
00257 if(shape.params.modulated.pulsetype == MPT_TIME){
00258 GL_THROW("Amplitude modulated dryer usage is nonsensical for residential dryers");
00259
00260
00261
00262
00263 } else if(shape.params.modulated.pulsetype == MPT_POWER){
00264
00265
00266 daily_dryer_demand = gl_get_loadshape_value(&shape) / 2.4449;
00267 }
00268 break;
00269 case MT_QUEUED:
00270 if(shape.params.queued.pulsetype == MPT_TIME){
00271 ;
00272 } else if(shape.params.queued.pulsetype == MPT_POWER){
00273 ;
00274 daily_dryer_demand = gl_get_loadshape_value(&shape) / 2.4449;
00275 }
00276 break;
00277 default:
00278 GL_THROW("dryer load shape has an unknown state!");
00279 break;
00280 }
00281 return residential_enduse::init(parent);
00282
00283
00284
00285
00286
00287 }
00288
00289 int dryer::isa(char *classname)
00290 {
00291 return (strcmp(classname,"dryer")==0 || residential_enduse::isa(classname));
00292 }
00293
00294
00295 TIMESTAMP dryer::sync(TIMESTAMP t0, TIMESTAMP t1)
00296 {
00297 double dt = 0;
00298 TIMESTAMP t3;
00299
00300 if(((t1-start_time)%3600)==0 && start_time>0)
00301 dryer_on = true;
00302 else
00303 dryer_on = false;
00304
00305
00306
00307
00308 TIMESTAMP t2 = residential_enduse::sync(t0,t1);
00309
00310 if ((last_t != t0) && (last_t != 0))
00311 {
00312
00313 dt = gl_toseconds(t0>0?t0-last_t:0);
00314
00315
00316 if (t0>TS_ZERO && dt>0)
00317 {
00318
00319 load.energy += load.total * dt/3600.0;
00320
00321
00322 last_t = t0;
00323 }
00324
00325 dt = update_state(dt);
00326 }
00327 else if (last_t == 0)
00328 {
00329 last_t = t0;
00330 }
00331
00332
00333 t3 = (TIMESTAMP)(dt*TS_SECOND+t0);
00334
00335 if (t3>t2)
00336 return -t3;
00337 else
00338 return t2;
00339 }
00340
00341 TIMESTAMP dryer::presync(TIMESTAMP t0, TIMESTAMP t1){
00342
00343 if(start_time==0)
00344 {
00345 start_time = int32(t0);
00346
00347 }
00348
00349
00350 switch(shape.type){
00351 case MT_UNKNOWN:
00352
00353 break;
00354 case MT_ANALOG:
00355 if(shape.params.analog.energy == 0.0){
00356 GL_THROW("dryer does not support fixed energy shaping");
00357
00358 } else if (shape.params.analog.power == 0){
00359
00360 daily_dryer_demand = gl_get_loadshape_value(&shape) / 2.4449;
00361 } else {
00362 daily_dryer_demand = gl_get_loadshape_value(&shape);
00363 }
00364 break;
00365 case MT_PULSED:
00366
00367
00368 if(shape.params.pulsed.pulsetype == MPT_TIME){
00369 ;
00370 } else if(shape.params.pulsed.pulsetype == MPT_POWER){
00371 ;
00372 daily_dryer_demand = gl_get_loadshape_value(&shape) / 2.4449;
00373 }
00374 break;
00375 case MT_MODULATED:
00376 if(shape.params.modulated.pulsetype == MPT_TIME){
00377 GL_THROW("Amplitude modulated dryer usage is nonsensical for residential dryers");
00378
00379 } else if(shape.params.modulated.pulsetype == MPT_POWER){
00380
00381
00382 daily_dryer_demand = gl_get_loadshape_value(&shape) / 2.4449;
00383 }
00384 break;
00385 case MT_QUEUED:
00386 if(shape.params.queued.pulsetype == MPT_TIME){
00387 ;
00388 } else if(shape.params.queued.pulsetype == MPT_POWER){
00389 ;
00390 daily_dryer_demand = gl_get_loadshape_value(&shape) / 2.4449;
00391 }
00392 break;
00393 default:
00394 GL_THROW("dryer load shape has an unknown state!");
00395 break;
00396 }
00397 return TS_NEVER;
00398 }
00399
00400 double dryer::update_state(double dt)
00401 {
00402 double temp_voltage_magnitude;
00403
00404 OBJECT *hdr = OBJECTHDR(this);
00405
00406 energy_used += total_power/1000 * dt/3600;
00407
00408
00409 temp_voltage_magnitude = (pCircuit->pV->get_complex()).Mag();
00410
00411 switch(state) {
00412
00413 case DRYER_STOPPED:
00414
00415 if (enduse_queue>1)
00416
00417 dryer_run_prob = double(gl_random_uniform(&hdr->rng_state,queue_min,queue_max));
00418
00419 if (enduse_queue > 1 && (dryer_run_prob > enduse_queue))
00420 {
00421 state = DRYER_CONTROL_ONLY;
00422 energy_needed = energy_baseline;
00423 cycle_duration = cycle_time = 1000 * (energy_needed - energy_used) / controls_power * 60 * 60;
00424 cycle_time = pulse_interval[0];
00425
00426 enduse_queue--;
00427
00428 new_running_state = true;
00429
00430 }
00431 else if (temp_voltage_magnitude<stall_voltage)
00432 {
00433 state = DRYER_STALLED;
00434 state_time = 0;
00435 }
00436 break;
00437
00438 case DRYER_CONTROL_ONLY:
00439
00440 if (energy_used >= energy_needed && cycle_time <= 0)
00441 {
00442 state = DRYER_STOPPED;
00443 cycle_time = 0;
00444 energy_used = 0;
00445
00446 control_check = false;
00447
00448 motor_coil_only_check1 = false;
00449 motor_coil_only_check2 = false;
00450 motor_coil_only_check3 = false;
00451 motor_coil_only_check4 = false;
00452 motor_coil_only_check5 = false;
00453 motor_coil_only_check6 = false;
00454
00455 motor_only_check1 = false;
00456 motor_only_check2 = false;
00457 motor_only_check3 = false;
00458 motor_only_check4 = false;
00459 motor_only_check5 = false;
00460 motor_only_check6 = false;
00461
00462 new_running_state = true;
00463
00464
00465 }
00466 else if (cycle_time<=0 && control_check == false)
00467 {
00468 state = DRYER_MOTOR_COIL_ONLY;;
00469 double cycle_t = 1000 * (energy_needed - energy_used) / (motor_power + coil_power[0]) * 60 * 60;
00470 double interval = pulse_interval[1];
00471 control_check = true;
00472 motor_coil_only_check1 = true;
00473
00474 if (cycle_t > interval)
00475 cycle_time = interval;
00476 else
00477 cycle_time = cycle_t;
00478
00479 new_running_state = true;
00480 }
00481
00482
00483 else if (temp_voltage_magnitude<stall_voltage)
00484 {
00485 state = DRYER_STALLED;
00486 state_time = 0;
00487 }
00488 break;
00489
00490
00491 case DRYER_MOTOR_COIL_ONLY:
00492
00493 if (energy_used >= energy_needed && cycle_time <= 0)
00494 {
00495 state = DRYER_STOPPED;
00496 cycle_time = 0;
00497 energy_used = 0;
00498
00499 control_check = false;
00500
00501 motor_coil_only_check1 = false;
00502 motor_coil_only_check2 = false;
00503 motor_coil_only_check3 = false;
00504 motor_coil_only_check4 = false;
00505 motor_coil_only_check5 = false;
00506 motor_coil_only_check6 = false;
00507
00508 motor_only_check1 = false;
00509 motor_only_check2 = false;
00510 motor_only_check3 = false;
00511 motor_only_check4 = false;
00512 motor_only_check5 = false;
00513 motor_only_check6 = false;
00514
00515 new_running_state = true;
00516
00517 }
00518 else if (cycle_time<=0 && motor_coil_only_check1 == true)
00519 {
00520 state = DRYER_MOTOR_ONLY;
00521 double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;
00522 double interval = pulse_interval[0];
00523 motor_coil_only_check1 = false;
00524 motor_coil_only_check2 = true;
00525 if (cycle_t > interval)
00526 cycle_time = interval;
00527 else
00528 cycle_time = cycle_t;
00529
00530 new_running_state = true;
00531 }
00532
00533 else if (cycle_time<=0 && motor_coil_only_check2 == true)
00534 {
00535 state = DRYER_MOTOR_ONLY;
00536 double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;
00537 double interval = pulse_interval[3];
00538 motor_coil_only_check2 = false;
00539 motor_coil_only_check3 = true;
00540 if (cycle_t > interval)
00541 cycle_time = interval;
00542 else
00543 cycle_time = cycle_t;
00544 new_running_state = true;
00545 }
00546
00547 else if (cycle_time<=0 && motor_coil_only_check3 == true)
00548 {
00549 state = DRYER_MOTOR_ONLY;
00550 double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;
00551 double interval = pulse_interval[3];
00552 motor_coil_only_check3 = false;
00553 motor_coil_only_check4 = true;
00554 if (cycle_t > interval)
00555 cycle_time = interval;
00556 else
00557 cycle_time = cycle_t;
00558
00559 new_running_state = true;
00560 }
00561
00562 else if (cycle_time<=0 && motor_coil_only_check4 == true)
00563 {
00564 state = DRYER_MOTOR_ONLY;
00565 double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;
00566 double interval = pulse_interval[3];
00567 motor_coil_only_check4 = false;
00568 motor_coil_only_check5 = true;
00569 if (cycle_t > interval)
00570 cycle_time = interval;
00571 else
00572 cycle_time = cycle_t;
00573 new_running_state = true;
00574 }
00575 else if (cycle_time<=0 && motor_coil_only_check5 == true)
00576 {
00577 state = DRYER_MOTOR_ONLY;
00578 double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;
00579 double interval = pulse_interval[5];
00580 motor_coil_only_check5 = false;
00581 motor_coil_only_check6 = true;
00582 if (cycle_t > interval)
00583 cycle_time = interval;
00584 else
00585 cycle_time = cycle_t;
00586
00587 new_running_state = true;
00588 }
00589
00590 else if (cycle_time<=0 && motor_coil_only_check6 == true)
00591 {
00592 state = DRYER_MOTOR_ONLY;
00593 double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;
00594 motor_only_check6 = false;
00595 new_running_state = true;
00596
00597
00598
00599
00600 }
00601 else if (temp_voltage_magnitude<stall_voltage)
00602 {
00603 state = DRYER_STALLED;
00604 state_time = 0;
00605 }
00606 break;
00607
00608 case DRYER_MOTOR_ONLY:
00609
00610 if (energy_used >= energy_needed)
00611 {
00612 state = DRYER_STOPPED;
00613 cycle_time = 0;
00614
00615 energy_used = 0;
00616 control_check = false;
00617
00618 motor_coil_only_check1 = false;
00619 motor_coil_only_check2 = false;
00620 motor_coil_only_check3 = false;
00621 motor_coil_only_check4 = false;
00622 motor_coil_only_check5 = false;
00623 motor_coil_only_check6 = false;
00624
00625 motor_only_check1 = false;
00626 motor_only_check2 = false;
00627 motor_only_check3 = false;
00628 motor_only_check4 = false;
00629 motor_only_check5 = false;
00630 motor_only_check6 = false;
00631
00632 new_running_state = true;
00633 }
00634
00635 else if (cycle_time<=0 && motor_only_check1 == false)
00636 {
00637 state = DRYER_MOTOR_COIL_ONLY;
00638 double cycle_t = 1000 * (energy_needed - energy_used) / (motor_power + coil_power[0]) * 60 * 60;
00639 double interval = pulse_interval[2];
00640
00641 motor_only_check1 = true;
00642 motor_only_check2 = true;
00643
00644 if (cycle_t > interval)
00645 cycle_time = interval;
00646 else
00647 cycle_time = cycle_t;
00648 new_running_state = true;
00649 }
00650
00651
00652 else if (cycle_time<=0 && motor_only_check2 == true)
00653 {
00654 state = DRYER_MOTOR_COIL_ONLY;
00655 double cycle_t = 1000 * (energy_needed - energy_used) / (motor_power + coil_power[0]) * 60 * 60;
00656 double interval = pulse_interval[4];
00657
00658 motor_only_check2 = false;
00659 motor_only_check3 = true;
00660
00661 if (cycle_t > interval)
00662 cycle_time = interval;
00663 else
00664 cycle_time = cycle_t;
00665
00666 new_running_state = true;
00667 }
00668
00669 else if (cycle_time<=0 && motor_only_check3 == true)
00670 {
00671 state = DRYER_MOTOR_COIL_ONLY;
00672 double cycle_t = 1000 * (energy_needed - energy_used) / (motor_power + coil_power[0]) * 60 * 60;
00673 double interval = pulse_interval[4];
00674
00675 motor_only_check3 = false;
00676 motor_only_check4 = true;
00677
00678 if (cycle_t > interval)
00679 cycle_time = interval;
00680 else
00681 cycle_time = cycle_t;
00682 new_running_state = true;
00683 }
00684
00685 else if (cycle_time<=0 && motor_only_check4 == true)
00686 {
00687 state = DRYER_MOTOR_COIL_ONLY;
00688 double cycle_t = 1000 * (energy_needed - energy_used) / (motor_power + coil_power[0]) * 60 * 60;
00689 double interval = pulse_interval[4];
00690
00691 motor_only_check4 = false;
00692 motor_only_check5 = true;
00693
00694 if (cycle_t > interval)
00695 cycle_time = interval;
00696 else
00697 cycle_time = cycle_t;
00698 new_running_state = true;
00699 }
00700
00701 else if (cycle_time<=0 && motor_only_check5 == true)
00702 {
00703 state = DRYER_MOTOR_COIL_ONLY;
00704 double cycle_t = 1000 * (energy_needed - energy_used) / (motor_power + coil_power[0]) * 60 * 60;
00705 double interval = pulse_interval[6];
00706
00707 motor_only_check5 = false;
00708
00709 if (cycle_t > interval)
00710 cycle_time = interval;
00711 else
00712 cycle_time = cycle_t;
00713 new_running_state = true;
00714 }
00715
00716 else if (temp_voltage_magnitude<stall_voltage)
00717 {
00718 state = DRYER_STALLED;
00719 state_time = 0;
00720 }
00721
00722 break;
00723
00724 case DRYER_STALLED:
00725
00726 if (temp_voltage_magnitude>start_voltage)
00727 {
00728 state = DRYER_MOTOR_ONLY;
00729 state_time = cycle_time;
00730 }
00731 else if (state_time>trip_delay)
00732 {
00733 state = DRYER_TRIPPED;
00734 state_time = 0;
00735 }
00736
00737 break;
00738
00739 case DRYER_TRIPPED:
00740
00741 if (state_time>reset_delay)
00742 {
00743 if (temp_voltage_magnitude>start_voltage)
00744 state = DRYER_MOTOR_ONLY;
00745 else
00746 state = DRYER_STALLED;
00747 state_time = 0;
00748 }
00749
00750 break;
00751 }
00752
00753
00754
00755 if (dryer_on == true)
00756 {
00757 enduse_queue += daily_dryer_demand * dt/24;
00758 }
00759
00760 actual_dryer_demand = actual_dryer_demand + daily_dryer_demand;
00761
00762
00763
00764 switch(state) {
00765 case DRYER_STOPPED:
00766
00767 motor_on_off = motor_coil_on_off = 0;
00768
00769
00770 load.power = load.current = load.admittance = complex(0,0,J);
00771
00772 dt = ((enduse_queue>=1) || (enduse_queue==0)) ? 0 : ((1-enduse_queue)*3600)/(enduse_queue*24);
00773
00774 break;
00775
00776 case DRYER_MOTOR_COIL_ONLY:
00777
00778 motor_on_off = motor_coil_on_off = 1;
00779 cycle_time -= dt;
00780
00781 load.power.SetPowerFactor(motor_power/1000, load.power_factor);
00782 load.admittance = complex((coil_power[0])/1000,0,J);
00783 load.current = complex(0,0,J);
00784
00785 dt = cycle_time;
00786 break;
00787
00788 case DRYER_CONTROL_ONLY:
00789
00790 if(true==new_running_state){
00791
00792 new_running_state = false;
00793
00794 }
00795 else{
00796
00797 cycle_time -= dt;
00798 }
00799
00800
00801 load.power = load.current = complex(0,0,J);
00802 load.admittance = complex(controls_power/1000,0,J);
00803
00804 dt = cycle_time;
00805 break;
00806
00807 case DRYER_STALLED:
00808
00809
00810 load.power = load.current = complex(0,0,J);
00811 load.admittance = complex(1)/stall_impedance;
00812
00813
00814 dt = trip_delay;
00815
00816 break;
00817
00818 case DRYER_TRIPPED:
00819
00820
00821 load.power = load.current = load.admittance = complex(0,0,J);
00822
00823
00824 dt = reset_delay;
00825
00826 break;
00827
00828
00829 case DRYER_MOTOR_ONLY:
00830 motor_on_off = 1;
00831 cycle_time -= dt;
00832
00833
00834 load.power.SetPowerFactor(motor_power/1000, load.power_factor);
00835 load.admittance = complex(0,0,J);
00836 load.current = complex(0,0,J);
00837
00838 dt = cycle_time;
00839 break;
00840
00841 default:
00842
00843 throw "unexpected motor state";
00844
00845
00846
00847
00848 break;
00849 }
00850
00851
00852 load.total = load.power + load.current + load.admittance;
00853 total_power = (load.power.Re() + (load.current.Re() + load.admittance.Re()*load.voltage_factor)*load.voltage_factor) * 1000;
00854
00855
00856 load.heatgain = load.total.Mag() * heat_fraction;
00857
00858
00859 if (dt > 0 && dt < 1)
00860 dt = 1;
00861
00862 return dt;
00863 }
00864
00865
00866
00868
00870
00871
00872 EXPORT TIMESTAMP sync_dryer(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
00873 {
00874 TIMESTAMP tret;
00875 dryer *my = OBJECTDATA(obj, dryer);
00876 if (obj->clock <= ROUNDOFF)
00877 obj->clock = t0;
00878 try {
00879 TIMESTAMP t1 = TS_NEVER;
00880 switch (pass) {
00881 case PC_PRETOPDOWN:
00882 return my->presync(obj->clock, t0);
00883 case PC_BOTTOMUP:
00884 tret = my->sync(obj->clock, t0);
00885 obj->clock = t0;
00886 return tret;
00887 default:
00888 throw "invalid pass request";
00889 }
00890 }
00891 catch (int m)
00892 {
00893 gl_error("%s (dryer:%d) model zone exception (code %d) not caught", obj->name?obj->name:"(anonymous dryer)", obj->id, m);
00894 }
00895 catch (char *msg)
00896 {
00897 gl_error("%s (dryer:%d) %s", obj->name?obj->name:"(anonymous dryer)", obj->id, msg);
00898 }
00899 return TS_INVALID;
00900 }
00901
00902 EXPORT int create_dryer(OBJECT **obj, OBJECT *parent)
00903 {
00904 *obj = gl_create_object(dryer::oclass);
00905 if (*obj!=NULL)
00906 {
00907 dryer *my = OBJECTDATA(*obj,dryer);
00908 gl_set_parent(*obj,parent);
00909 my->create();
00910 return 1;
00911 }
00912 return 0;
00913 }
00914
00915 EXPORT int init_dryer(OBJECT *obj)
00916 {
00917 dryer *my = OBJECTDATA(obj,dryer);
00918 return my->init(obj->parent);
00919 }
00920
00921 EXPORT int isa_dryer(OBJECT *obj, char *classname)
00922 {
00923 if(obj != 0 && classname != 0){
00924 return OBJECTDATA(obj,dryer)->isa(classname);
00925 } else {
00926 return 0;
00927 }
00928 }
00929
00930
00931
00932
00933
00934
00935
00936
00937