@@ -390,43 +390,43 @@ void Simulator::updateParts(QSet<ItemBase *> itemBases, int timeStep) {
390390 QString family = part->family ().toLower ();
391391
392392 if (family.contains (" capacitor" )) {
393- updateCapacitor (part);
393+ updateCapacitor (timeStep, part);
394394 continue ;
395395 }
396396 if (family.contains (" diode" )) {
397- updateDiode (part);
397+ updateDiode (timeStep, part);
398398 continue ;
399399 }
400400 if (family.contains (" led" )) {
401- updateLED (part);
401+ updateLED (timeStep, part);
402402 continue ;
403403 }
404404 if (family.contains (" resistor" )) {
405- updateResistor (part);
405+ updateResistor (timeStep, part);
406406 continue ;
407407 }
408408 if (family.contains (" multimeter" )) {
409- updateMultimeter (part);
409+ updateMultimeter (timeStep, part);
410410 continue ;
411411 }
412412 if (family.contains (" dc motor" )) {
413- updateDcMotor (part);
413+ updateDcMotor (timeStep, part);
414414 continue ;
415415 }
416416 if (family.contains (" line sensor" ) || family.contains (" distance sensor" )) {
417- updateIRSensor (part);
417+ updateIRSensor (timeStep, part);
418418 continue ;
419419 }
420420 if (family.contains (" battery" ) || family.contains (" voltage source" )) {
421- updateBattery (part);
421+ updateBattery (timeStep, part);
422422 continue ;
423423 }
424424 if (family.contains (" potentiometer" ) || family.contains (" sparkfun trimpot" )) {
425- updatePotentiometer (part);
425+ updatePotentiometer (timeStep, part);
426426 continue ;
427427 }
428428 if (family.contains (" oscilloscope" )) {
429- updateOscilloscope (part, timeStep );
429+ updateOscilloscope (timeStep, part );
430430 continue ;
431431 }
432432 }
@@ -593,12 +593,14 @@ void Simulator::removeSimItems(QList<QGraphicsItem *> items) {
593593 * @param[in] defaultValue value to return on empty vector
594594 * @returns the first vector element or the given default value
595595 */
596- double Simulator::getVectorValueOrDefault (const std::string & vecName, double defaultValue) {
596+ double Simulator::getVectorValueOrDefault (unsigned long timeStep, const std::string & vecName, double defaultValue) {
597597 auto vecInfo = m_simulator->getVecInfo (vecName);
598- if (vecInfo.empty ()) {
598+ if (vecInfo.empty ()) {
599599 return defaultValue;
600600 } else {
601- return vecInfo[vecInfo.size ()-1 ];
601+ if (timeStep < 0 || timeStep >= vecInfo.size ())
602+ return defaultValue;
603+ return vecInfo[timeStep];
602604 }
603605}
604606
@@ -608,7 +610,7 @@ double Simulator::getVectorValueOrDefault(const std::string & vecName, double de
608610 * @param[in] c1 the second connector
609611 * @returns the voltage between the connector c0 and c1
610612 */
611- double Simulator::calculateVoltage (ConnectorItem * c0, ConnectorItem * c1) {
613+ double Simulator::calculateVoltage (unsigned long timeStep, ConnectorItem * c0, ConnectorItem * c1) {
612614 int net0 = m_connector2netHash.value (c0);
613615 int net1 = m_connector2netHash.value (c1);
614616
@@ -621,12 +623,12 @@ double Simulator::calculateVoltage(ConnectorItem * c0, ConnectorItem * c1) {
621623 if (net0 != 0 ) {
622624 auto vecInfo = m_simulator->getVecInfo (net0str.toStdString ());
623625 if (vecInfo.empty ()) return 0.0 ;
624- volt0 = vecInfo[0 ];
626+ volt0 = vecInfo[timeStep ];
625627 }
626628 if (net1 != 0 ) {
627629 auto vecInfo = m_simulator->getVecInfo (net1str.toStdString ());
628630 if (vecInfo.empty ()) return 0.0 ;
629- volt1 = vecInfo[0 ];
631+ volt1 = vecInfo[timeStep ];
630632 }
631633 return volt0-volt1;
632634}
@@ -767,13 +769,13 @@ double Simulator::getMaxPropValue(ItemBase *part, QString property) {
767769 * @param[in] subpartName The name of the subpart. Leave it empty if there is only one spice line for the device. Otherwise, give the suffix of the subpart.
768770 * @returns the power that a part is consuming/producing.
769771 */
770- double Simulator::getPower (ItemBase* part, QString subpartName) {
772+ double Simulator::getPower (unsigned long timeStep, ItemBase* part, QString subpartName) {
771773 // TODO: Handle devices that do not return the power
772774 QString instanceStr = part->instanceTitle ().toLower ();
773775 instanceStr.append (subpartName.toLower ());
774776 instanceStr.prepend (" @" );
775777 instanceStr.append (" [p]" );
776- return getVectorValueOrDefault (instanceStr.toStdString (), 0.0 );
778+ return getVectorValueOrDefault (timeStep, instanceStr.toStdString (), 0.0 );
777779}
778780
779781/* *
@@ -787,7 +789,7 @@ double Simulator::getPower(ItemBase* part, QString subpartName) {
787789 * @param[in] subpartName The name of the subpart. Leave it empty if there is only one spice line for the device. Otherwise, give the suffix of the subpart.
788790 * @returns the current that a part is consuming/producing.
789791 */
790- double Simulator::getCurrent (ItemBase* part, QString subpartName) {
792+ double Simulator::getCurrent (unsigned long timeStep, ItemBase* part, QString subpartName) {
791793 QString instanceStr = part->instanceTitle ().toLower ();
792794 instanceStr.append (subpartName.toLower ());
793795
@@ -820,15 +822,15 @@ double Simulator::getCurrent(ItemBase* part, QString subpartName) {
820822 break ;
821823
822824 }
823- return getVectorValueOrDefault (instanceStr.toStdString (), 0.0 );
825+ return getVectorValueOrDefault (timeStep, instanceStr.toStdString (), 0.0 );
824826}
825827
826828/* *
827829 * Returns the current that flows through a transistor.
828830 * @param[in] spicePartName The name of the spice transistor.
829831 * @returns the current that the transistor is sinking/sourcing.
830832 */
831- double Simulator::getTransistorCurrent (QString spicePartName, TransistorLeg leg) {
833+ double Simulator::getTransistorCurrent (unsigned long timeStep, QString spicePartName, TransistorLeg leg) {
832834 if (spicePartName.at (0 ).toLower ()!=QChar (' q' )) {
833835 // TODO: Add tr()
834836 throw QString (" Error getting the current of a transistor. The device is not a transistor, its first letter is not a Q. Name: %1" ).arg (spicePartName);
@@ -848,7 +850,7 @@ double Simulator::getTransistorCurrent(QString spicePartName, TransistorLeg leg)
848850 throw QString (" Error getting the current of a transistor. The transistor leg or property is not recognized. Leg: %1" ).arg (leg);
849851 }
850852
851- return getVectorValueOrDefault (spicePartName.toStdString (), 0.0 );
853+ return getVectorValueOrDefault (timeStep, spicePartName.toStdString (), 0.0 );
852854}
853855
854856/* *
@@ -1015,9 +1017,9 @@ void Simulator::removeItemsToBeSimulated(QList<QGraphicsItem*> & parts) {
10151017 * Updates and checks a diode. Checks that the power is less than the maximum power.
10161018 * @param[in] diode A part that is going to be checked and updated.
10171019 */
1018- void Simulator::updateDiode (ItemBase * diode) {
1020+ void Simulator::updateDiode (unsigned long timeStep, ItemBase * diode) {
10191021 double maxPower = getMaxPropValue (diode, " power" );
1020- double power = getPower (diode);
1022+ double power = getPower (timeStep, diode);
10211023 if (power > maxPower) {
10221024 drawSmoke (diode);
10231025 }
@@ -1028,15 +1030,15 @@ void Simulator::updateDiode(ItemBase * diode) {
10281030 * and updates the brightness of the LED in the breadboard view.
10291031 * @param[in] part An LED that is going to be checked and updated.
10301032 */
1031- void Simulator::updateLED (ItemBase * part) {
1033+ void Simulator::updateLED (unsigned long timeStep, ItemBase * part) {
10321034 LED* led = dynamic_cast <LED *>(part);
10331035 if (led) {
10341036 // Check if this an RGB led
10351037 QString rgbString = part->getProperty (" rgb" );
10361038
10371039 if (rgbString.isEmpty ()) {
10381040 // Just one LED
1039- double curr = getCurrent (part);
1041+ double curr = getCurrent (timeStep, part);
10401042 double maxCurr = getMaxPropValue (part, " current" );
10411043
10421044 std::cout << " LED Current: " <<curr<<std::endl;
@@ -1050,9 +1052,9 @@ void Simulator::updateLED(ItemBase * part) {
10501052 }
10511053 } else {
10521054 // The part is an RGB LED
1053- double currR = getCurrent (part, " R" );
1054- double currG = getCurrent (part, " G" );
1055- double currB = getCurrent (part, " B" );
1055+ double currR = getCurrent (timeStep, part, " R" );
1056+ double currG = getCurrent (timeStep, part, " G" );
1057+ double currB = getCurrent (timeStep, part, " B" );
10561058 double curr = std::max ({currR, currG, currB});
10571059 double maxCurr = getMaxPropValue (part, " current" );
10581060
@@ -1077,7 +1079,7 @@ void Simulator::updateLED(ItemBase * part) {
10771079 * and reverse voltage in electrolytic and tantalum capacitors (unidirectional capacitors).
10781080 * @param[in] part A capacitor that is going to be checked and updated.
10791081 */
1080- void Simulator::updateCapacitor (ItemBase * part) {
1082+ void Simulator::updateCapacitor (unsigned long timeStep, ItemBase * part) {
10811083 QString family = part->getProperty (" family" ).toLower ();
10821084
10831085 ConnectorItem * negLeg, * posLeg;
@@ -1090,7 +1092,7 @@ void Simulator::updateCapacitor(ItemBase * part) {
10901092 return ;
10911093
10921094 double maxV = getMaxPropValue (part, " voltage" );
1093- double v = calculateVoltage (posLeg, negLeg);
1095+ double v = calculateVoltage (timeStep, posLeg, negLeg);
10941096 std::cout << " MaxVoltage of the capacitor: " << maxV << std::endl;
10951097 std::cout << " Capacitor voltage is : " << QString (" %1" ).arg (v).toStdString () << std::endl;
10961098
@@ -1111,9 +1113,9 @@ void Simulator::updateCapacitor(ItemBase * part) {
11111113 * Updates and checks a resistor. Checks that the power is less than the maximum power.
11121114 * @param[in] part A resistor that is going to be checked and updated.
11131115 */
1114- void Simulator::updateResistor (ItemBase * part) {
1116+ void Simulator::updateResistor (unsigned long timeStep, ItemBase * part) {
11151117 double maxPower = getMaxPropValue (part, " power" );
1116- double power = getPower (part);
1118+ double power = getPower (timeStep, part);
11171119 std::cout << " Power: " << power <<std::endl;
11181120 if (power > maxPower) {
11191121 drawSmoke (part);
@@ -1125,10 +1127,10 @@ void Simulator::updateResistor(ItemBase * part) {
11251127 * for the two resistors "A" and "B".
11261128 * @param[in] part A potentiometer that is going to be checked and updated.
11271129 */
1128- void Simulator::updatePotentiometer (ItemBase * part) {
1130+ void Simulator::updatePotentiometer (unsigned long timeStep, ItemBase * part) {
11291131 double maxPower = getMaxPropValue (part, " power" );
1130- double powerA = getPower (part, " A" ); // power through resistor A
1131- double powerB = getPower (part, " B" ); // power through resistor B
1132+ double powerA = getPower (timeStep, part, " A" ); // power through resistor A
1133+ double powerB = getPower (timeStep, part, " B" ); // power through resistor B
11321134 double power = powerA + powerB;
11331135 if (power > maxPower) {
11341136 drawSmoke (part);
@@ -1139,12 +1141,12 @@ void Simulator::updatePotentiometer(ItemBase * part) {
11391141 * Updates and checks a battery. Checks that there are no short circuits.
11401142 * @param[in] part A battery that is going to be checked and updated.
11411143 */
1142- void Simulator::updateBattery (ItemBase * part) {
1144+ void Simulator::updateBattery (unsigned long timeStep, ItemBase * part) {
11431145 double voltage = getMaxPropValue (part, " voltage" );
11441146 double resistance = getMaxPropValue (part, " internal resistance" );
11451147 double safetyMargin = 0.1 ; // TODO: This should be adjusted
11461148 double maxCurrent = voltage/resistance * safetyMargin;
1147- double current = getCurrent (part); // current that the battery delivers
1149+ double current = getCurrent (timeStep, part); // current that the battery delivers
11481150 std::cout << " Battery: voltage=" << voltage << " , resistance=" << resistance <<std::endl;
11491151 std::cout << " Battery: MaxCurr=" << maxCurrent << " , Curr=" << current <<std::endl;
11501152 if (abs (current) > maxCurrent) {
@@ -1162,7 +1164,7 @@ bool Simulator::isSimulating()
11621164 * and that the current of the output is less than the maximum.
11631165 * @param[in] part A IR sensor that is going to be checked and updated.
11641166 */
1165- void Simulator::updateIRSensor (ItemBase * part) {
1167+ void Simulator::updateIRSensor (unsigned long timeStep, ItemBase * part) {
11661168 double maxV = getMaxPropValue (part, " voltage (max)" );
11671169 double minV = getMaxPropValue (part, " voltage (min)" );
11681170 double maxIout = getMaxPropValue (part, " max output current" );
@@ -1184,16 +1186,16 @@ void Simulator::updateIRSensor(ItemBase * part) {
11841186 if (!gnd || !vcc || !out )
11851187 return ;
11861188
1187- double v = calculateVoltage (vcc, gnd); // voltage applied to the motor
1189+ double v = calculateVoltage (timeStep, vcc, gnd); // voltage applied to the motor
11881190 double i;
11891191 if (part->family ().contains (" line sensor" )) {
11901192 // digital sensor (push-pull output)
11911193 QString spicename = part->instanceTitle ().toLower ();
11921194 spicename.prepend (" q" );
1193- i = getTransistorCurrent (spicename, COLLECTOR); // voltage applied to the motor
1195+ i = getTransistorCurrent (timeStep, spicename, COLLECTOR); // voltage applied to the motor
11941196 } else {
11951197 // analogue sensor (modelled by a voltage source and a resistor)
1196- i = getCurrent (part, " a" ); // voltage applied to the motor
1198+ i = getCurrent (timeStep, part, " a" ); // voltage applied to the motor
11971199 }
11981200 std::cout << " IR sensor Max Iout: " << maxIout << " , current Iout " << i << std::endl;
11991201 std::cout << " IR sensor Max V: " << maxV << " , current V " << v << std::endl;
@@ -1209,7 +1211,7 @@ void Simulator::updateIRSensor(ItemBase * part) {
12091211 * TODO: The number of arrows are proportional to the voltage applied.
12101212 * @param[in] part A DC motor that is going to be checked and updated.
12111213 */
1212- void Simulator::updateDcMotor (ItemBase * part) {
1214+ void Simulator::updateDcMotor (unsigned long timeStep, ItemBase * part) {
12131215 double maxV = getMaxPropValue (part, " voltage (max)" );
12141216 double minV = getMaxPropValue (part, " voltage (min)" );
12151217 std::cout << " Motor1: " << std::endl;
@@ -1222,7 +1224,7 @@ void Simulator::updateDcMotor(ItemBase * part) {
12221224 if (!terminal1 || !terminal2 )
12231225 return ;
12241226
1225- double v = calculateVoltage (terminal1, terminal2); // voltage applied to the motor
1227+ double v = calculateVoltage (timeStep, terminal1, terminal2); // voltage applied to the motor
12261228 if (abs (v) > maxV) {
12271229 drawSmoke (part);
12281230 return ;
@@ -1279,7 +1281,7 @@ void Simulator::updateDcMotor(ItemBase * part) {
12791281 * Calculates the parameter to measure and updates the display of the multimeter.
12801282 * @param[in] part A multimeter that is going to be checked and updated.
12811283 */
1282- void Simulator::updateMultimeter (ItemBase * part) {
1284+ void Simulator::updateMultimeter (unsigned long timeStep, ItemBase * part) {
12831285 QString variant = part->getProperty (" variant" ).toLower ();
12841286 ConnectorItem * comProbe = nullptr , * vProbe = nullptr , * aProbe = nullptr ;
12851287 QList<ConnectorItem *> probes = part->cachedConnectorItems ();
@@ -1306,7 +1308,7 @@ void Simulator::updateMultimeter(ItemBase * part) {
13061308 }
13071309 if (comProbe->connectedToWires () && vProbe->connectedToWires ()) {
13081310 std::cout << " Multimeter (v_dc) connected with two terminals. " << std::endl;
1309- double v = calculateVoltage (vProbe, comProbe);
1311+ double v = calculateVoltage (timeStep, vProbe, comProbe);
13101312 updateMultimeterScreen (part, v);
13111313 }
13121314 return ;
@@ -1317,7 +1319,7 @@ void Simulator::updateMultimeter(ItemBase * part) {
13171319 updateMultimeterScreen (part, " ERR" );
13181320 return ;
13191321 }
1320- updateMultimeterScreen (part, getCurrent (part));
1322+ updateMultimeterScreen (part, getCurrent (timeStep, part));
13211323 return ;
13221324 } else if (variant.compare (" ohmmeter" ) == 0 ) {
13231325 std::cout << " Ohmmeter found. " << std::endl;
@@ -1326,8 +1328,8 @@ void Simulator::updateMultimeter(ItemBase * part) {
13261328 updateMultimeterScreen (part, " ERR" );
13271329 return ;
13281330 }
1329- double v = calculateVoltage (vProbe, comProbe);
1330- double a = getCurrent (part);
1331+ double v = calculateVoltage (timeStep, vProbe, comProbe);
1332+ double a = getCurrent (timeStep, part);
13311333 double r = abs (v/a);
13321334 std::cout << " Ohmmeter: Volt: " << v <<" , Curr: " << a <<" , Ohm: " << r << std::endl;
13331335 updateMultimeterScreen (part, r);
@@ -1340,7 +1342,7 @@ void Simulator::updateMultimeter(ItemBase * part) {
13401342 * Calculates the parameter to measure and updates the display of the multimeter.
13411343 * @param[in] part An oscilloscope that is going to be checked and updated.
13421344 */
1343- void Simulator::updateOscilloscope (ItemBase * part, int currTimeStep ) {
1345+ void Simulator::updateOscilloscope (unsigned long timeStep, ItemBase * part ) {
13441346 std::cout << " updateOscilloscope: " << std::endl;
13451347 ConnectorItem * comProbe = nullptr , * v1Probe = nullptr , * v2Probe = nullptr , * v3Probe = nullptr , * v4Probe = nullptr ;
13461348 QList<ConnectorItem *> probes = part->cachedConnectorItems ();
@@ -1423,7 +1425,7 @@ void Simulator::updateOscilloscope(ItemBase * part, int currTimeStep) {
14231425
14241426 // Draw the signal
14251427 QString pathId = QString (" ch%1-path" ).arg (channel+1 );
1426- QString signalPath = generateSvgPath (v, vCom, currTimeStep , pathId, m_simStartTime, m_simStepTime, hPos, timeDiv, divisionSize/voltsDiv[channel], chOffsets[channel],
1428+ QString signalPath = generateSvgPath (v, vCom, timeStep , pathId, m_simStartTime, m_simStepTime, hPos, timeDiv, divisionSize/voltsDiv[channel], chOffsets[channel],
14271429 screenHeight, screenWidth, lineColor[channel], " 20" );
14281430 bbSvg += signalPath.arg (bbScreenOffsetX).arg (bbScreenOffsetY);
14291431 schSvg += signalPath.arg (schScreenOffsetX).arg (schScreenOffsetY);
0 commit comments