void MotorController::handleTick() { MotorControllerConfiguration *config = (MotorControllerConfiguration *)getConfiguration(); //Set status annunciators if(ready) statusBitfield1 |=1 << 15;else statusBitfield1 &= ~(1 <<15); if(running) statusBitfield1 |=1 << 14;else statusBitfield1 &= ~(1 <<14); if(warning) statusBitfield1 |=1 << 10;else statusBitfield1 &= ~(1 <<10); if(faulted) statusBitfield1 |=1 << 9;else statusBitfield1 &= ~(1 <<9); //Calculate killowatts and kilowatt hours mechanicalPower=dcVoltage*dcCurrent/10000; //In kilowatts. DC voltage is x10 if (dcVoltage>nominalVolts && torqueActual>0) {kiloWattHours=1;} //If our voltage is higher than fully charged with no regen, zero our kwh meter if (milliStamp>millis()) {milliStamp=0;} //In case millis rolls over to zero while running kiloWattHours+=(millis()-milliStamp)*mechanicalPower;//We assume here that power is at current level since last tick and accrue in kilowattmilliseconds. milliStamp=millis(); //reset our kwms timer for next check //Throttle check Throttle *accelerator = DeviceManager::getInstance()->getAccelerator(); Throttle *brake = DeviceManager::getInstance()->getBrake(); if (accelerator) throttleRequested = accelerator->getLevel(); if (brake && brake->getLevel() < -10 && brake->getLevel() < accelerator->getLevel()) //if the brake has been pressed it overrides the accelerator. throttleRequested = brake->getLevel(); //Logger::debug("Throttle: %d", throttleRequested); if (!donePrecharge)checkPrecharge(); if(skipcounter++ > 30) //A very low priority loop for checks that only need to be done once per second. { skipcounter=0; //Reset our laptimer //Some test simulations if precharge time is set to 12345 if(config->prechargeR==12345) { dcVoltage--; if (torqueActual < -500) { torqueActual=20; } else { torqueActual=-650; } if (dcCurrent < 0) { dcCurrent=120; } else { dcCurrent=-65; } if (temperatureInverter < config->coolOn*10) { temperatureInverter=(config->coolOn+2)*10; } else { temperatureInverter=(config->coolOff-2)*10; } if (throttleRequested < 500) { throttleRequested=500; } else { throttleRequested=0; } if(testenableinput) { testenableinput=false; } else { testenableinput=true; } if(testreverseinput) { testreverseinput=false; } else { testreverseinput=true; } } coolingcheck(); checkBrakeLight(); checkEnableInput(); checkReverseInput(); checkReverseLight(); //Store kilowatt hours, but only once in awhile. prefsHandler->write(EEMC_KILOWATTHRS, kiloWattHours); prefsHandler->saveChecksum(); } }
void MotorController::handleTick() { uint8_t forwardSwitch, reverseSwitch; MotorControllerConfiguration *config = (MotorControllerConfiguration *)getConfiguration(); gearSwitch = GS_FORWARD; if(ready) statusBitfield1 |=1 << 15;else statusBitfield1 &= ~(1 <<15); if(running) statusBitfield1 |=1 << 14;else statusBitfield1 &= ~(1 <<14); if(warning) statusBitfield1 |=1 << 10;else statusBitfield1 &= ~(1 <<10); if(faulted) statusBitfield1 |=1 << 9;else statusBitfield1 &= ~(1 <<9); mechanicalPower=dcVoltage*dcCurrent/10000; //In kilowatts. DC voltage is x10 efficiency=(speedActual*torqueActual*0.1045)/(mechanicalPower*100000); if (dcVoltage>nominalVolts && torqueActual>-10) {kiloWattHours=1;} //If our voltage is higher than fully charged with no regen, zero our kwh meter if (milliStamp>millis()) {milliStamp=0;} //In case millis rolls over to zero while running kiloWattHours+=(millis()-milliStamp)*mechanicalPower;//We assume here that power is at current level since last tick and accrue in kilowattmilliseconds. milliStamp=millis();//reset our kwms timer for next check Throttle *accelerator = DeviceManager::getInstance()->getAccelerator(); Throttle *brake = DeviceManager::getInstance()->getBrake(); if (accelerator) throttleRequested = accelerator->getLevel(); if (brake && brake->getLevel() < -10 && brake->getLevel() < accelerator->getLevel()) //if the brake has been pressed it overrides the accelerator. throttleRequested = brake->getLevel(); if (!donePrecharge && config->prechargeR>0) { if (millis()> config->prechargeR) //Check milliseconds since startup against our entered delay in milliseconds { donePrecharge=1; //Time's up. Let's don't do ANY of this on future ticks. if (config->mainContactorRelay!=255) //If we HAVE a main contactor, turn it on. { setOutput(config->mainContactorRelay, 1); //Main contactor on statusBitfield2 |=1 << 17; //set bit to turn on MAIN CONTACTOR annunciator statusBitfield1 |=1 << config->mainContactorRelay;//setbit to Turn on main contactor output annunciator //I've commented the below out to leave the precharge relay ON after precharge..see user guide for why. //setOutput(config->prechargeRelay, 0); //ok. Turn off precharge output // statusBitfield2 &= ~(1 << 19); //clearbit to turn off PRECHARGE annunciator //statusBitfield1 &= ~(1<< config->prechargeRelay); //clear bit to turn off PRECHARGE output annunciator Logger::console("Precharge sequence complete after %i milliseconds", config->prechargeR); Logger::console("MAIN CONTACTOR ENABLED...DOUT0:%d, DOUT1:%d, DOUT2:%d, DOUT3:%d,DOUT4:%d, DOUT5:%d, DOUT6:%d, DOUT7:%d", getOutput(0), getOutput(1), getOutput(2), getOutput(3),getOutput(4), getOutput(5), getOutput(6), getOutput(7)); } } else //If time is not up and maybe this is our first tick, let's set the precharge relay IF we have one //and clear the main contactor IF we have one.We'll set PRELAY so we only have to do this once. { if (config->prechargeRelay==255 || config->mainContactorRelay==255){donePrecharge=1;} if(!prelay) { if (config->prechargeRelay!=255) { setOutput(config->prechargeRelay, 1); //ok. Turn on precharge statusBitfield2 |=1 << 19; //set bit to turn on PRECHARGE RELAY annunciator statusBitfield1 |=1 << config->prechargeRelay; //set bit to turn ON precharge OUTPUT annunciator throttleRequested = 0; //Keep throttle at zero during precharge prelay=true; } if (config->mainContactorRelay!=255) { setOutput(config->mainContactorRelay, 0); //Main contactor off statusBitfield2 &= ~(1 << 17); //clear bitTurn off MAIN CONTACTOR annunciator statusBitfield1 &= ~(1 << config->mainContactorRelay);//clear bitTurn off main contactor output annunciator prelay=true; } } } } if(skipcounter++ > 30) //As how fast we turn on cooling is very low priority, we only check cooling every 24th lap or about once per second { if(config->prechargeR==12345) { dcVoltage--; temperatureInverter++; temperatureMotor++; if (torqueActual < -500) {torqueActual=20;} else {torqueActual=-650;} } coolingcheck(); prefsHandler->write(EEMC_KILOWATTHRS, kiloWattHours); //store kilowatt hours to EEPROM prefsHandler->saveChecksum(); // memCache->Write(63000,kiloWattHours); } }