/* return distance in centimeters */ float AP_RangeFinder_analog::distance_cm(void) { if (!_enabled) { return 0.0f; } /* first convert to volts */ float v = voltage(); float dist_m = 0; switch ((AP_RangeFinder_analog::RangeFinder_Function)_function.get()) { case FUNCTION_LINEAR: dist_m = (v - _offset) * _scaling; break; case FUNCTION_INVERTED: dist_m = (_offset - v) * _scaling; break; case FUNCTION_HYPERBOLA: if (v <= _offset) { dist_m = 0; } dist_m = _scaling / (v - _offset); if (isinf(dist_m) || dist_m > _max_distance_cm) { dist_m = _max_distance_cm * 0.01; } break; } if (dist_m < 0) { dist_m = 0; } return dist_m * 100.0f; }
void AP_BattMonitor::check_failsafes(void) { if (hal.util->get_soft_armed()) { for (uint8_t i = 0; i < _num_instances; i++) { if (drivers[i] == nullptr) { continue; } const BatteryFailsafe type = drivers[i]->update_failsafes(); if (type <= state[i].failsafe) { continue; } int8_t action = 0; const char *type_str = nullptr; switch (type) { case AP_BattMonitor::BatteryFailsafe_None: continue; // should not have been called in this case case AP_BattMonitor::BatteryFailsafe_Low: action = _params[i]._failsafe_low_action; type_str = "low"; break; case AP_BattMonitor::BatteryFailsafe_Critical: action = _params[i]._failsafe_critical_action; type_str = "critical"; break; } gcs().send_text(MAV_SEVERITY_WARNING, "Battery %d is %s %.2fV used %.0f mAh", i + 1, type_str, (double)voltage(i), (double)consumed_mah(i)); _has_triggered_failsafe = true; AP_Notify::flags.failsafe_battery = true; state[i].failsafe = type; // map the desired failsafe action to a prioritiy level int8_t priority = 0; if (_failsafe_priorities != nullptr) { while (_failsafe_priorities[priority] != -1) { if (_failsafe_priorities[priority] == action) { break; } priority++; } } // trigger failsafe if the action was equal or higher priority // It's valid to retrigger the same action if a different battery provoked the event if (priority <= _highest_failsafe_priority) { _battery_failsafe_handler_fn(type_str, action); _highest_failsafe_priority = priority; } } } }
void main (void) { long command, left, right; int rec, i; P0_5=1; while (1) { printf("%ld\n", travelled); rec = 1; for (i = 0; i < 4; i++){ if (voltage(0) > MIN){ rec = 0; } } if (!rec){ right = getDistance(2); left = getDistance(1); if (orientation == REVERSE){ long temp = left; left = right; right = temp; } if (autonomous){ if (left > right + 300){ motorRight.power = 0; motorLeft.power = totalpower; } else if (right > left + 300){ motorLeft.power = 0; motorRight.power = totalpower; } else if (left > distance * ERROR){ motorLeft.direction = FORWARD; motorRight.direction = FORWARD; motorLeft.power = totalpower; motorRight.power = totalpower; } else if (left < distance / ERROR){ motorLeft.direction = REVERSE; motorRight.direction = REVERSE; motorLeft.power = totalpower; motorRight.power = totalpower; } else { motorLeft.power = 0; motorRight.power = 0; } } } else { motorLeft.power = 0; motorRight.power = 0; waitms(10); //this makes sure that the power change takes effect before shutting off the interrupt command = rx_byte(); implement_command(command); waitms(200); //prevents receiving commands back to back } } }
unsigned char rx_byte ( float min ) { unsigned char j; unsigned char val = 0; float v; int c; wait_one_and_half_bit_time(); for(j=0; j<8; j++) { v = voltage(0); if (j == 0) { volt_right = v; volt_left = voltage(1); } c = (v>min); P2_0 = c; val |= (c)?(0x01<<j):0x00; wait_bit_time(); } return val; }
void SurfaceCurrent::Update() { delete pcg_; delete amg_; delete S0_; delete PSI_; delete RHS_; delete K_; psi_->Update(); *psi_ = 0.0; s0_->Update(); s0_->Assemble(); s0_->Finalize(); S0_ = s0_->ParallelAssemble(); amg_ = new HypreBoomerAMG(*S0_); amg_->SetPrintLevel(0); pcg_ = new HyprePCG(*S0_); pcg_->SetTol(1e-12); pcg_->SetMaxIter(200); pcg_->SetPrintLevel(0); pcg_->SetPreconditioner(*amg_); // Apply piecewise constant voltage boundary condition Array<int> vbc_bdr_attr(H1FESpace_->GetParMesh()->bdr_attributes.Max()); for (int i=0; i<vbcs_->Size(); i++) { ConstantCoefficient voltage((*vbcv_)[i]); vbc_bdr_attr = 0; vbc_bdr_attr[(*vbcs_)[i]-1] = 1; psi_->ProjectBdrCoefficient(voltage, vbc_bdr_attr); } PSI_ = psi_->ParallelProject(); RHS_ = new HypreParVector(H1FESpace_); K_ = new HypreParVector(HCurlFESpace_); s0_->ParallelEliminateEssentialBC(ess_bdr_, *S0_, *PSI_, *RHS_); }
int ButtonPin::readButtons() { float volts = voltage(); // None pressed if( volts < .1 ) { BPIN_SELECT = 0; BPIN_UP = 0; BPIN_DOWN = 0; BPIN_LEFT = 0; BPIN_RIGHT = 0; return 0; } if( volts > 4 ) BPIN_SELECT = 1; else if( volts > 3 ) BPIN_UP = 1; else if( volts > 2 ) BPIN_DOWN = 1; else if( volts > 1 ) BPIN_LEFT = 1; else if( volts > .1 ) BPIN_RIGHT = 1; return 1; }
/** * Returns the current voltage as a string, this function ensures that * the voltage will always display two decimals, even if the number is * an integer (e.g. this function will return "12.00 V") */ QString DriverStation::voltageString() const { /* Round voltage to two decimal places */ qreal volt = roundf (voltage() * 100) / 100; /* Avoid this: http://i.imgur.com/iAAi1bX.png */ if (volt > maximumBatteryVoltage()) volt = maximumBatteryVoltage(); /* Separate voltage into natural and decimal numbers */ int integer = static_cast<int> (volt); int decimal = static_cast<qreal> (volt - integer) * 100; /* Convert the obtained numbers into strings */ QString integer_str = QString::number (integer); QString decimal_str = QString::number (decimal); /* Prepend a 0 to the decimal numbers if required */ if (decimal < 10) decimal_str.prepend ("0"); /* Construct final string */ return integer_str + "." + decimal_str + " V"; }
val |= (c)?(0x01<<j):0x00; wait_bit_time(); } return val; } void pwmcounter (void) interrupt 1 { float f; volatile char b; struct QueueItem* item; EA = 0; f = voltage(0); //printf("%f %f", f, minimum_logic_voltage); if (f > minimum_logic_voltage) { P2_0 = 0; b = rx_byte((f*0.25)); if (b != NOTHING_BYTE && b != DISTANCE_BYTE) { item = newItem(b); append(q, item); zeroCount = 0; } else if (b == NOTHING_BYTE) { zeroCount++; } else { zeroCount = 0;
void VoltaSolver::Solve() { if (myid_ == 0) { cout << "Running solver ... " << endl << flush; } // Initialize the electric potential with its boundary conditions *phi_ = 0.0; if ( dbcs_->Size() > 0 ) { if ( phiBCCoef_ ) { // Apply gradient boundary condition phi_->ProjectBdrCoefficient(*phiBCCoef_, ess_bdr_); } else { // Apply piecewise constant boundary condition Array<int> dbc_bdr_attr(pmesh_->bdr_attributes.Max()); for (int i=0; i<dbcs_->Size(); i++) { ConstantCoefficient voltage((*dbcv_)[i]); dbc_bdr_attr = 0; dbc_bdr_attr[(*dbcs_)[i]-1] = 1; phi_->ProjectBdrCoefficient(voltage, dbc_bdr_attr); } } } // Initialize the RHS vector HypreParVector *RHS = new HypreParVector(H1FESpace_); *RHS = 0.0; // Initialize the volumetric charge density if ( rho_ ) { rho_->ProjectCoefficient(*rhoCoef_); HypreParMatrix *MassH1 = h1Mass_->ParallelAssemble(); HypreParVector *Rho = rho_->ParallelProject(); MassH1->Mult(*Rho,*RHS); delete MassH1; delete Rho; } // Initialize the Polarization HypreParVector *P = NULL; if ( p_ ) { p_->ProjectCoefficient(*pCoef_); P = p_->ParallelProject(); HypreParMatrix *MassHCurl = hCurlMass_->ParallelAssemble(); HypreParVector *PD = new HypreParVector(HCurlFESpace_); MassHCurl->Mult(*P,*PD); Grad_->MultTranspose(*PD,*RHS,-1.0,1.0); delete MassHCurl; delete PD; } // Initialize the surface charge density if ( sigma_ ) { *sigma_ = 0.0; Array<int> nbc_bdr_attr(pmesh_->bdr_attributes.Max()); for (int i=0; i<nbcs_->Size(); i++) { ConstantCoefficient sigma_coef((*nbcv_)[i]); nbc_bdr_attr = 0; nbc_bdr_attr[(*nbcs_)[i]-1] = 1; sigma_->ProjectBdrCoefficient(sigma_coef, nbc_bdr_attr); } HypreParMatrix *MassS = h1SurfMass_->ParallelAssemble(); HypreParVector *Sigma = sigma_->ParallelProject(); MassS->Mult(*Sigma,*RHS,1.0,1.0); delete MassS; delete Sigma; } // Apply Dirichlet BCs to matrix and right hand side HypreParMatrix *DivEpsGrad = divEpsGrad_->ParallelAssemble(); HypreParVector *Phi = phi_->ParallelProject(); // Apply the boundary conditions to the assembled matrix and vectors if ( dbcs_->Size() > 0 ) { // According to the selected surfaces divEpsGrad_->ParallelEliminateEssentialBC(ess_bdr_, *DivEpsGrad, *Phi, *RHS); } else { // No surfaces were labeled as Dirichlet so eliminate one DoF Array<int> dof_list(0); if ( myid_ == 0 ) { dof_list.SetSize(1); dof_list[0] = 0; } DivEpsGrad->EliminateRowsCols(dof_list, *Phi, *RHS); } // Define and apply a parallel PCG solver for AX=B with the AMG // preconditioner from hypre. HypreSolver *amg = new HypreBoomerAMG(*DivEpsGrad); HyprePCG *pcg = new HyprePCG(*DivEpsGrad); pcg->SetTol(1e-12); pcg->SetMaxIter(500); pcg->SetPrintLevel(2); pcg->SetPreconditioner(*amg); pcg->Mult(*RHS, *Phi); delete amg; delete pcg; delete DivEpsGrad; delete RHS; // Extract the parallel grid function corresponding to the finite // element approximation Phi. This is the local solution on each // processor. *phi_ = *Phi; // Compute the negative Gradient of the solution vector. This is // the magnetic field corresponding to the scalar potential // represented by phi. HypreParVector *E = new HypreParVector(HCurlFESpace_); Grad_->Mult(*Phi,*E,-1.0); *e_ = *E; delete Phi; // Compute electric displacement (D) from E and P if (myid_ == 0) { cout << "Computing D ... " << flush; } HypreParMatrix *HCurlHDivEps = hCurlHDivEps_->ParallelAssemble(); HypreParVector *ED = new HypreParVector(HDivFESpace_); HypreParVector *D = new HypreParVector(HDivFESpace_); HCurlHDivEps->Mult(*E,*ED); if ( P ) { HypreParMatrix *HCurlHDiv = hCurlHDiv_->ParallelAssemble(); HCurlHDiv->Mult(*P,*ED,-1.0,1.0); delete HCurlHDiv; } HypreParMatrix * MassHDiv = hDivMass_->ParallelAssemble(); HyprePCG * pcgM = new HyprePCG(*MassHDiv); pcgM->SetTol(1e-12); pcgM->SetMaxIter(500); pcgM->SetPrintLevel(0); HypreDiagScale *diagM = new HypreDiagScale; pcgM->SetPreconditioner(*diagM); pcgM->Mult(*ED,*D); *d_ = *D; if (myid_ == 0) { cout << "done." << flush; } delete diagM; delete pcgM; delete HCurlHDivEps; delete MassHDiv; delete E; delete ED; delete D; delete P; if (myid_ == 0) { cout << " Solver done. " << flush; } }
SurfaceCurrent::SurfaceCurrent(ParFiniteElementSpace & H1FESpace, ParFiniteElementSpace & HCurlFESpace, ParDiscreteGradOperator & Grad, Array<int> & kbcs, Array<int> & vbcs, Vector & vbcv) : H1FESpace_(&H1FESpace), HCurlFESpace_(&HCurlFESpace), Grad_(&Grad), kbcs_(&kbcs), vbcs_(&vbcs), vbcv_(&vbcv) { // Initialize MPI variables MPI_Comm_rank(H1FESpace_->GetParMesh()->GetComm(), &myid_); s0_ = new ParBilinearForm(H1FESpace_); s0_->AddBoundaryIntegrator(new DiffusionIntegrator); s0_->Assemble(); s0_->Finalize(); S0_ = s0_->ParallelAssemble(); amg_ = new HypreBoomerAMG(*S0_); amg_->SetPrintLevel(0); pcg_ = new HyprePCG(*S0_); pcg_->SetTol(1e-12); pcg_->SetMaxIter(200); pcg_->SetPrintLevel(0); pcg_->SetPreconditioner(*amg_); ess_bdr_.SetSize(H1FESpace_->GetParMesh()->bdr_attributes.Max()); ess_bdr_ = 0; for (int i=0; i<vbcs_->Size(); i++) { ess_bdr_[(*vbcs_)[i]-1] = 1; } non_k_bdr_.SetSize(H1FESpace_->GetParMesh()->bdr_attributes.Max()); non_k_bdr_ = 1; for (int i=0; i<kbcs_->Size(); i++) { non_k_bdr_[(*kbcs_)[i]-1] = 0; } psi_ = new ParGridFunction(H1FESpace_); *psi_ = 0.0; // Apply piecewise constant voltage boundary condition Array<int> vbc_bdr_attr(H1FESpace_->GetParMesh()->bdr_attributes.Max()); for (int i=0; i<vbcs_->Size(); i++) { ConstantCoefficient voltage((*vbcv_)[i]); vbc_bdr_attr = 0; vbc_bdr_attr[(*vbcs_)[i]-1] = 1; psi_->ProjectBdrCoefficient(voltage, vbc_bdr_attr); } PSI_ = psi_->ParallelProject(); RHS_ = new HypreParVector(H1FESpace_); K_ = new HypreParVector(HCurlFESpace_); s0_->ParallelEliminateEssentialBC(ess_bdr_, *S0_, *PSI_, *RHS_); }
void TestMonodomain3d() throw(Exception) { /* HOW_TO_TAG Cardiac/Problem definition * Generate a slab (cuboid) mesh rather than read a mesh in, and pass it to solver */ /* We will auto-generate a mesh this time, and pass it in, rather than * provide a mesh file name. This is how to generate a cuboid mesh with * a given spatial stepsize h */ TetrahedralMesh<3,3> mesh; double h=0.02; mesh.ConstructRegularSlabMesh(h, 0.8 /*length*/, 0.3 /*width*/, 0.3 /*depth*/); /* (In 2D the call is identical, but without the depth parameter). * * EMPTYLINE * * Set the simulation duration, etc, and create an instance of the cell factory. * One thing that should be noted for monodomain problems, the ''intracellular * conductivity'' is used as the monodomain effective conductivity (not a * harmonic mean of intra and extracellular conductivities). So if you want to * alter the monodomain conductivity call * `HeartConfig::Instance()->SetIntracellularConductivities` */ HeartConfig::Instance()->SetSimulationDuration(5); //ms HeartConfig::Instance()->SetOutputDirectory("Monodomain3dExample"); HeartConfig::Instance()->SetOutputFilenamePrefix("results"); HeartConfig::Instance()->SetOdePdeAndPrintingTimeSteps(0.005, 0.01, 0.1); BenchmarkCellFactory cell_factory; /* Now we declare the problem class, `MonodomainProblem<3>` instead of `BidomainProblem<2>`. * The interface for both is the same. */ MonodomainProblem<3> monodomain_problem( &cell_factory ); /* If a mesh-file-name hasn't been set using `HeartConfig`, we have to pass in * a mesh using the `SetMesh` method (must be called before `Initialise`). */ monodomain_problem.SetMesh(&mesh); /* By default data for all nodes is output, but for big simulations, sometimes this * might not be required, and the action potential only at certain nodes required. * The following code shows how to output the results at the first, middle and last * nodes, for example. (The output is written to the HDF5 file; regular visualisation output * will be turned off. HDF5 files can be read using Matlab). We are not using this in this * simulation however (hence the boolean being set to false). */ bool partial_output = false; if(partial_output) { std::vector<unsigned> nodes_to_be_output; nodes_to_be_output.push_back(0); nodes_to_be_output.push_back((unsigned)round( (mesh.GetNumNodes()-1)/2 )); nodes_to_be_output.push_back(mesh.GetNumNodes()-1); monodomain_problem.SetOutputNodes(nodes_to_be_output); } /* `SetWriteInfo` is a useful method that means that the min/max voltage is * printed as the simulation runs (useful for verifying that cells are stimulated * and the wave propagating, for example) (although note scons does buffer output * before printing to screen) */ monodomain_problem.SetWriteInfo(); /* Finally, call `Initialise` and `Solve` as before */ monodomain_problem.Initialise(); monodomain_problem.Solve(); /* This part is just to check nothing has accidentally been changed in this example */ ReplicatableVector voltage(monodomain_problem.GetSolution()); TS_ASSERT_DELTA(voltage[0], 34.9032, 1e-2); }
int main(int argc, char *argv[]) #endif { #if !defined(SINGLE_PHASE) int ch; static struct phase_parms_s *phase; static struct phase_nv_parms_s const *phase_nv; #endif static int32_t x; int i; #if !defined(__MSP430__) if (start_host_environment(argc, argv) < 0) exit(2); #endif system_setup(); #if !defined(ESP_SUPPORT) && defined(PHASE_CORRECTION_SUPPORT) && !defined(DYNAMIC_PHASE_CORRECTION_SUPPORT) #if !defined(SINGLE_PHASE) for (ch = 0; ch < NUM_PHASES; ch++) { phase = &chan[ch]; phase_nv = &nv_parms.seg_a.s.chan[ch]; #endif #if defined(__MSP430_HAS_ADC12__) || defined(__MSP430_HAS_ADC10__) set_phase_correction(&phase->metrology.current.in_phase_correction[0], phase_nv->current.phase_correction[0]); #if GAIN_STAGES > 1 set_phase_correction(&phase->metrology.current.in_phase_correction[1], phase_nv->current.phase_correction[1]); #endif #if defined(SINGLE_PHASE) && defined(NEUTRAL_MONITOR_SUPPORT) set_phase_correction(&phase->neutral.in_phase_correction[0], nv_parms.seg_a.s.neutral.phase_correction[0]); #if GAIN_STAGES > 1 set_phase_correction(&phase->neutral.in_phase_correction[1], nv_parms.seg_a.s.neutral.phase_correction[1]); #endif #endif #else #if defined(SINGLE_PHASE) set_sd16_phase_correction(&phase->metrology.current.in_phase_correction[0], 0, phase_nv->current.phase_correction[0]); #if defined(NEUTRAL_MONITOR_SUPPORT) set_sd16_phase_correction(&phase->metrology.neutral.in_phase_correction[0], 1, nv_parms.seg_a.s.neutral.phase_correction[0]); #endif #else set_sd16_phase_correction(&phase->metrology.current.in_phase_correction[0], ch, phase_nv->current.phase_correction[0]); #endif #endif #if !defined(SINGLE_PHASE) } #endif #endif #if defined(ESP_SUPPORT) esp_init(); esp_start_measurement(); #endif #if defined(MULTI_RATE_SUPPORT) tariff_initialise(); #endif send_message(0, 1); for (;;) { kick_watchdog(); #if !defined(__MSP430__) /* In the host environment we need to simulate interrupts here */ adc_interrupt(); #endif #if !defined(SINGLE_PHASE) phase = chan; phase_nv = nv_parms.seg_a.s.chan; for (ch = 0; ch < NUM_PHASES; ch++) { #endif /* Unless we are in normal operating mode, we should wait to be woken by a significant event from the interrupt routines. */ ////#if 1 //// 0 //defined(__MSP430__) //// if (operating_mode != OPERATING_MODE_NORMAL) #ifdef USE_LPM _BIS_SR(LPM0_bits); #endif #if defined(POWER_DOWN_SUPPORT) if (operating_mode == OPERATING_MODE_POWERFAIL) switch_to_powerfail_mode(); #endif #if defined(LIMP_MODE_SUPPORT) && defined(IEC1107_SUPPORT) if (nv_parms.seg_a.s.meter_uncalibrated) enable_ir_receiver(); #endif if ((phase->status & NEW_LOG)) { /* The background activity has informed us that it is time to perform a block processing operation. */ phase->status &= ~NEW_LOG; #if defined(MAGNETIC_INTERFERENCE_SUPPORT) if ((meter_status & STATUS_HIGH_MAGNETIC_FIELD)) { /* The meter is suffering magnetic tampering, so continuously charge for a great deal of electricity. */ x = phase->readings.V_rms*MAGNETIC_INTERFERENCE_CURRENT/(10*100); } else #endif //MM Added for LCD Fix; Start #if defined(IHD430_SUPPORT) RF_Tx[12]=total_active_power_array.uint8[0]; RF_Tx[13]=total_active_power_array.uint8[1]; RF_Tx[14]=total_active_power_array.uint8[2]; RF_Tx[15]=total_active_power_array.uint8[3]; RF_Tx[16] =0x28 ^ RF_Tx[12] ^ RF_Tx[13] ^ RF_Tx[14] ^ RF_Tx[15]; for (i=0; i<17; i++) { UCA2TXBUF=RF_Tx[i]; while(!(UCA2IFG&UCTXIFG)); } #endif lcd_display_mode++; switch( lcd_display_mode ) { case DISPLAY_VOLTAGE: change_display=1; temp= phase->readings.V_rms; if (temp <0) temp=0; LCDM1=0xC; LCDM2=0x29; break; case DISPLAY_CURRENT: change_display=1; temp= phase->readings.I_rms; if (temp <0) temp=0; LCDM1=0x9C; LCDM2=0x1; //MM Take care of different decimal. break; case DISPLAY_ACTIVE_POWER: change_display=1; temp= phase->readings.active_power; if (temp <0) temp=0; LCDM1=0xCF; LCDM2=0x1; break; case DISPLAY_REACTIVE_POWER: change_display=1; temp= phase->readings.reactive_power; if (temp <0) temp=0; LCDM1=0xC7; LCDM2=0x3; break; case DISPLAY_APPARENT_POWER: change_display=1; temp= phase->readings.apparent_power; if (temp <0) temp=0; LCDM1=0xB7; LCDM2=0x1; break; case DISPLAY_FREQUENCY: change_display=1; temp= phase->readings.frequency; if (temp <0) temp=0; LCDM1=0x8F; LCDM2=0x1; break; case DISPLAY_POWER_FACTOR: change_display=1; temp= phase->readings.power_factor/10; LCDM1=0x8F; LCDM2=0x50; if (temp < 0) { temp*= -1; LCDM3=0x1C; } else { LCDM3= 0x9C; } LCDM3constant=1; //Take negative and positive case for inductive and capacitive break; case DISPLAY_ACCUMULATED_POWER_TOTAL: change_display=1; temp= phase->consumed_active_energy/10; LCDM1=0x9F; LCDM2=0x1; break; default: change_display=0; break; } //temp=12345; //total_active_power=0x12345; // MM Comment back in to display active power // if (total_active_power <0) // temp=-(total_active_power); // else // temp=total_active_power; //MM Comment in two lines below for counter test //temp=12345; // temp2++; // temp=temp2; if(change_display) { // LCDM1 = 0; // LCDM2 = 0; if(!LCDM3constant) { LCDM3 = 0; } else { LCDM3constant=0; } LCDM4 = 0; LCDM5 = 0; LCDM6 = 0; LCDM7 = 0; LCDM8 = 0; LCDM9 = 0; LCDM10 = 0; LCDM11 = 0; LCDM12 = 0; LCDM13 = 0; LCDM14 = 0; LCDM15 = 0; LCDM16 = 0; LCDM17 = 0; LCDM18 = 0; LCDM19 = 0; LCDM20 = 0; thou_thou=0; hun_thou=0; ten_thou=0; thou=0; hun=0; ten=0; unit=0; while (temp >=1000000) { thou_thou++; temp-=1000000; } while (temp >=100000) { hun_thou++; temp-=100000; } while (temp >=10000) { ten_thou++; temp-=10000; } while (temp >=1000) { thou++; temp-=1000; } while (temp >=100) { hun++; temp-=100; } while (temp >=10) { ten++; temp-=10; } while (temp >=1) { unit++; temp--; } //MM: LCD fix to display higher active power readings if(thou_thou) { LCDM11 = LCD_Char_Map[hun]; LCDM9 = LCD_Char_Map[thou]; //LCDM8 = 0x1; LCDM7 = LCD_Char_Map[ten_thou]; LCDM5 = LCD_Char_Map[hun_thou]; LCDM3 = LCD_Char_Map[thou_thou]; } else if(hun_thou) { LCDM11 = LCD_Char_Map[ten]; if (lcd_display_mode==DISPLAY_CURRENT) LCDM8 = 0x1; else if(lcd_display_mode!=DISPLAY_ACCUMULATED_POWER_TOTAL) LCDM10 = 0x1; //MM do nothing LCDM9 = LCD_Char_Map[hun]; LCDM7 = LCD_Char_Map[thou]; LCDM5 = LCD_Char_Map[ten_thou]; LCDM3 = LCD_Char_Map[hun_thou]; } else { LCDM11 = LCD_Char_Map[unit]; LCDM9 = LCD_Char_Map[ten]; if (lcd_display_mode==DISPLAY_CURRENT || lcd_display_mode==DISPLAY_POWER_FACTOR) { LCDM6 = 0x1; } else if(lcd_display_mode==DISPLAY_ACCUMULATED_POWER_TOTAL) { LCDM10 = 0x1; } else { LCDM8 = 0x1; } if (lcd_display_mode!=DISPLAY_POWER_FACTOR) { LCDM3 = LCD_Char_Map[ten_thou]; } LCDM7 = LCD_Char_Map[hun]; LCDM5 = LCD_Char_Map[thou]; } if (lcd_display_mode==DISPLAY_ACCUMULATED_POWER_TOTAL) { lcd_display_mode=-2; } } //MM end if (operating_mode == OPERATING_MODE_NORMAL) { /* We can only do real power assessment in full operating mode */ #if !defined(SINGLE_PHASE) x = active_power(phase, phase_nv); #if defined(PRECALCULATED_PARAMETER_SUPPORT) #if defined(IRMS_SUPPORT) phase->readings.I_rms = current(phase, phase_nv, ch); #endif #if defined(VRMS_SUPPORT) phase->readings.V_rms = voltage(phase, phase_nv); #endif #endif #else x = active_power(); #if defined(PRECALCULATED_PARAMETER_SUPPORT) #if defined(IRMS_SUPPORT) phase->readings.I_rms = current(); #endif #if defined(VRMS_SUPPORT) phase->readings.V_rms = voltage(); #endif #endif #endif } #if defined(LIMP_MODE_SUPPORT) else if (operating_mode == OPERATING_MODE_LIMP) { /* In limp mode we must assess estimated power from only the measured current. */ /* We cannot properly determine current reversal in this mode. Also, current imbalance is really just a measure of which lead is still connected. Just treat both the imbalance and reversal conditions as OK */ #if !defined(SINGLE_PHASE) x = current(phase, phase_nv, ch); #if defined(PRECALCULATED_PARAMETER_SUPPORT) && defined(VRMS_SUPPORT) phase->readings.V_rms = voltage(phase, phase_nv); #endif #else x = current(); #if defined(PRECALCULATED_PARAMETER_SUPPORT) && defined(VRMS_SUPPORT) phase->readings.V_rms = voltage(); #endif #endif #if defined(PRECALCULATED_PARAMETER_SUPPORT) && defined(IRMS_SUPPORT) phase->readings.I_rms = x; #endif x = x*MAINS_NOMINAL_VOLTAGE/10; } #endif if (labs(x) < RESIDUAL_POWER_CUTOFF || (phase->status & V_OVERRANGE)) { x = 0; #if defined(PRECALCULATED_PARAMETER_SUPPORT) && defined(IRMS_SUPPORT) /* Avoid displaying a residual current, which is nothing more than integrated noise. */ //phase->I_rms = 0; #endif /* Turn off the LEDs, regardless of the internal state of the reverse and imbalance assessments. */ #if defined(PHASE_REVERSED_DETECTION_SUPPORT) meter_status &= ~STATUS_REVERSED; clr_reverse_current_indicator(); #endif #if defined(POWER_BALANCE_DETECTION_SUPPORT) meter_status &= ~STATUS_EARTHED; clr_earthed_indicator(); #endif } else { if (operating_mode == OPERATING_MODE_NORMAL) { #if defined(PHASE_REVERSED_DETECTION_SUPPORT) && defined(PHASE_REVERSED_IS_TAMPERING) if ((phase->status & PHASE_REVERSED)) { meter_status |= STATUS_REVERSED; set_reverse_current_indicator(); } else { meter_status &= ~STATUS_REVERSED; clr_reverse_current_indicator(); } #endif #if defined(POWER_BALANCE_DETECTION_SUPPORT) if ((phase->status & PHASE_UNBALANCED)) { meter_status |= STATUS_EARTHED; set_earthed_indicator(); } else { meter_status &= ~STATUS_EARTHED; clr_earthed_indicator(); } #endif } #if defined(LIMP_MODE_SUPPORT) else { #if defined(PHASE_REVERSED_DETECTION_SUPPORT) /* We cannot tell forward from reverse current in limp mode, so just say it is not reversed. */ meter_status &= ~STATUS_REVERSED; clr_reverse_current_indicator(); #endif #if defined(POWER_BALANCE_DETECTION_SUPPORT) /* We are definitely in the unbalanced state, but only set the indicator if we have persistence checked, and the current is sufficient to sustain operation. */ if ((phase->status & PHASE_UNBALANCED) && phase->readings.I_rms >= LIMP_MODE_MINIMUM_CURRENT) { meter_status |= STATUS_EARTHED; set_earthed_indicator(); } else { meter_status &= ~STATUS_EARTHED; clr_earthed_indicator(); } #endif /* Only run the IR interface if we are sure there is enough power from the supply to support the additional current drain. If we have not yet been calibrated we had better keep the IR port running so we can complete the calibration. */ #if defined(LIMP_MODE_SUPPORT) && defined(IEC1107_SUPPORT) if (phase->I_rms >= LIMP_MODE_MINIMUM_CURRENT_FOR_IR || nv_parms.seg_a.s.meter_uncalibrated) { enable_ir_receiver(); } else { disable_ir_receiver(); } #endif } #endif } //x /= 10; #if defined(SINGLE_PHASE) && defined(TOTAL_ACTIVE_ENERGY_SUPPORT) total_active_power = x; #else total_active_power += (x - phase->readings.active_power); #endif #if defined(PHASE_REVERSED_DETECTION_SUPPORT) && defined(PHASE_REVERSED_IS_GENERATION) #endif #if defined(IHD430_SUPPORT) total_active_power_array.uint32=total_active_power; #endif phase->readings.active_power = x; #if defined(PRECALCULATED_PARAMETER_SUPPORT) #if defined(REACTIVE_POWER_SUPPORT) #if defined(SINGLE_PHASE) x = reactive_power(); #else x = reactive_power(phase, phase_nv); #endif #if defined(SINGLE_PHASE) && defined(TOTAL_REACTIVE_ENERGY_SUPPORT) total_reactive_power = x; #else total_reactive_power += (x - phase->readings.reactive_power); #endif phase->readings.reactive_power = x; #endif #if defined(APPARENT_POWER_SUPPORT) #if defined(SINGLE_PHASE) phase->readings.apparent_power = apparent_power(); #else phase->readings.apparent_power = apparent_power(phase, phase_nv); #endif #endif #if defined(POWER_FACTOR_SUPPORT) /* The power factor should be calculated last */ #if defined(SINGLE_PHASE) phase->readings.power_factor = power_factor(); #else phase->readings.power_factor = power_factor(phase, phase_nv); #endif #endif #endif #if defined(PER_PHASE_ACTIVE_ENERGY_SUPPORT) // phase->active_energy_counter += x*phase->metrology.dot_prod_logged.sample_count; // while (phase->active_energy_counter > ENERGY_WATT_HOUR_THRESHOLD) // { // phase->active_energy_counter -= ENERGY_WATT_HOUR_THRESHOLD; // phase->consumed_active_energy++; // } #endif #if defined(PRECALCULATED_PARAMETER_SUPPORT) && defined(MAINS_FREQUENCY_SUPPORT) #if defined(SINGLE_PHASE) phase->readings.frequency = frequency(); #else phase->readings.frequency = frequency(phase, phase_nv); #endif #endif #if defined(MAGNETIC_INTERFERENCE_SUPPORT) #if !defined(SINGLE_PHASE) if (ch == 0) #endif { if ((meter_status & STATUS_HIGH_MAGNETIC_FIELD)) { if (phase->sample_count_logged/magnetic_sensor_count_logged < MAGNETIC_INTERFERENCE_SAMPLE_RATIO) { if (--magnetic_interference_persistence <= -MAGNETIC_INTERFERENCE_PERSISTENCE_CHECK) { meter_status &= ~STATUS_HIGH_MAGNETIC_FIELD; magnetic_interference_persistence = 0; } } else { magnetic_interference_persistence = 0; } } else { if (phase->sample_count_logged/magnetic_sensor_count_logged >= MAGNETIC_INTERFERENCE_SAMPLE_RATIO) { if (++magnetic_interference_persistence >= MAGNETIC_INTERFERENCE_PERSISTENCE_CHECK) { meter_status |= STATUS_HIGH_MAGNETIC_FIELD; magnetic_interference_persistence = 0; } } else { magnetic_interference_persistence = 0; } } } #endif } #if defined(LIMP_MODE_SUPPORT) /* The voltage channel DC estimate will never move very much when the meter is operating normally. If it does move, there must be some tampering, such as a diode between the grid and the meter. */ if (operating_mode == OPERATING_MODE_NORMAL) { if (phase->readings.V_rms < LIMP_MODE_VOLTAGE_THRESHOLD*100 || phase->metrology.V_dc_estimate[0] > UPPER_TAMPER_V_DC_ESTIMATE || phase->metrology.V_dc_estimate[0] < LOWER_TAMPER_V_DC_ESTIMATE) { switch_to_limp_mode(); } } else if (operating_mode == OPERATING_MODE_LIMP) { if (phase->readings.V_rms >= NORMAL_MODE_VOLTAGE_THRESHOLD*100 && phase->metrology.V_dc_estimate[1] <= UPPER_LIMP_TAMPER_V_DC_ESTIMATE && phase->metrology.V_dc_estimate[1] >= LOWER_LIMP_TAMPER_V_DC_ESTIMATE) { /* The LCD might need to be revived */ #if defined(__MSP430__) LCDawaken(); #else /* Tell the world we are ready to start */ #endif switch_to_normal_mode(); } } #endif #if !defined(SINGLE_PHASE) phase++; phase_nv++; } #endif #if !defined(SINGLE_PHASE) && defined(NEUTRAL_MONITOR_SUPPORT) && defined(IRMS_SUPPORT) if ((neutral.status & NEW_LOG)) { /* The background activity has informed us that it is time to perform a block processing operation. */ neutral.status &= ~NEW_LOG; neutral.readings.I_rms = neutral_current(); } #endif #if defined(MULTI_RATE_SUPPORT) tariff_management(); #endif /* Do display and other housekeeping here */ if ((meter_status & TICKER)) { /* Two seconds have passed */ /* We have a 2 second tick */ meter_status &= ~TICKER; #if defined(__MSP430__) && defined(BASIC_LCD_SUPPORT) /* Update the display, cycling through the phases */ update_display(); #endif custom_2second_handler(); #if (defined(RTC_SUPPORT) || defined(CUSTOM_RTC_SUPPORT)) && defined(CORRECTED_RTC_SUPPORT) correct_rtc(); #endif } custom_keypad_handler(); custom_mainloop_handler(); #if defined(MESH_NET_SUPPORT) if (rf_service) { rf_service = 0; rf_tick_service(); } #endif } #if !defined(__AQCOMPILER__) && !defined(__IAR_SYSTEMS_ICC__) return 0; #endif }
int32_t current_rms_voltage(int ph) { return voltage(&chan[ph], &nv_parms.seg_a.s.chan[ch]); }
/* * Parse the incoming data for valid messages */ void ControlBoard::parseSerialData(void) { if (serialData.size() < CB_BUFFER_SIZE) { // Not enough data return; } // Check for a full message ending to \n if (serialData.endsWith('\n')) { // Remove \r\n int chop = 1; if (serialData.endsWith("\r\n")) { chop++; } serialData.chop(chop); qDebug() << __FUNCTION__ << "have msg:" << serialData.data(); } else { // Wait for more data return; } // Parse temperature if (serialData.startsWith("tmp: ")) { serialData.remove(0,5); quint16 value = serialData.trimmed().toInt(); qDebug() << __FUNCTION__ << "Temperature:" << value; emit(temperature(value)); } else if (serialData.startsWith("dst: ")) { serialData.remove(0,5); quint16 value = serialData.trimmed().toInt(); qDebug() << __FUNCTION__ << "Distance:" << value; emit(distance(value)); } else if (serialData.startsWith("amp: ")) { serialData.remove(0,5); quint16 value = serialData.trimmed().toInt(); qDebug() << __FUNCTION__ << "Current consumption:" << value; emit(current(value)); } else if (serialData.startsWith("vlt: ")) { serialData.remove(0,5); quint16 value = serialData.trimmed().toInt(); qDebug() << __FUNCTION__ << "Battery voltage:" << value; emit(voltage(value)); } else if (serialData.startsWith("d: ")) { serialData.remove(0,3); QString *debugmsg = new QString(serialData); emit(debug(debugmsg)); } serialData.clear(); }
void Test2dBathMultipleBathConductivities() throw (Exception) { HeartConfig::Instance()->SetSimulationDuration(2.0); //ms HeartConfig::Instance()->SetOutputDirectory("BidomainBath2dMultipleBathConductivities"); HeartConfig::Instance()->SetOutputFilenamePrefix("bidomain_bath_2d"); HeartConfig::Instance()->SetOdeTimeStep(0.001); //ms ??? std::set<unsigned> tissue_ids; tissue_ids.insert(0); // Same as default value defined in HeartConfig std::set<unsigned> bath_ids; bath_ids.insert(2); bath_ids.insert(3); bath_ids.insert(4); HeartConfig::Instance()->SetTissueAndBathIdentifiers(tissue_ids, bath_ids); // need to create a cell factory but don't want any intra stim, so magnitude // of stim is zero. c_vector<double,2> centre; centre(0) = 0.05; // cm centre(1) = 0.05; // cm BathCellFactory<2> cell_factory( 0.0, centre); BidomainWithBathProblem<2> bidomain_problem( &cell_factory ); DistributedTetrahedralMesh<2,2> mesh; mesh.ConstructRegularSlabMesh(0.05, 0.9, 0.9); // set the x<0.25 and x>0.75 regions as the bath region for (AbstractTetrahedralMesh<2,2>::ElementIterator iter = mesh.GetElementIteratorBegin(); iter != mesh.GetElementIteratorEnd(); ++iter) { double x = iter->CalculateCentroid()[0]; double y = iter->CalculateCentroid()[1]; if( (x>0.3) && (x<0.6) && (y>0.3) && (y<0.6) ) { iter->SetAttribute(0); } else { if (y<0.2) { iter->SetAttribute(2); } else if (y<0.7) { iter->SetAttribute(3); } else if (y<0.9) { iter->SetAttribute(4); } } } std::map<unsigned, double> multiple_bath_conductivities; multiple_bath_conductivities[2] = 7.0; multiple_bath_conductivities[3] = 1.0; multiple_bath_conductivities[4] = 0.001; HeartConfig::Instance()->SetBathMultipleConductivities(multiple_bath_conductivities); double boundary_flux = -3.0e3; double start_time = 0.0; double duration = 1.0; // of the stimulus, in ms HeartConfig::Instance()->SetElectrodeParameters(false, 0, boundary_flux, start_time, duration); bidomain_problem.SetMesh(&mesh); bidomain_problem.Initialise(); bidomain_problem.Solve(); DistributedVector distributed_solution = bidomain_problem.GetSolutionDistributedVector(); DistributedVector::Stripe voltage(distributed_solution, 0); /* * We are checking the last time step. This test will only make sure that an AP is triggered. */ bool ap_triggered = false; for (DistributedVector::Iterator index = distributed_solution.Begin(); index!= distributed_solution.End(); ++index) { // test V = 0 for all bath nodes and that an AP is triggered in the tissue if (HeartRegionCode::IsRegionBath( mesh.GetNode(index.Global)->GetRegion() )) // bath { TS_ASSERT_DELTA(voltage[index], 0.0, 1e-12); } else if (voltage[index] > 0.0)//at the last time step { ap_triggered = true; } } TS_ASSERT(PetscTools::ReplicateBool(ap_triggered)); }