コード例 #1
0
ファイル: control.c プロジェクト: derkling/adcontrol
// The task to process SMS events
static void sms_task(iptr_t timer) {
	//Silence "args not used" warning.
	(void)timer;
	int8_t smsIndex = 0;

	DB(LOG_INFO("\r\nChecking SMS...\r\n"));

	// Update signal level
	GSM(updateCSQ());

	// Flush SMS buffer
	GSM(gsmBufferCleanup(&msg));

	// Retrive the first SMS into memory
	GSM(smsIndex = gsmSMSByIndex(&msg, 1));
	if (smsIndex==1) {
		command_parse(&dbg_port.fd, msg.text);
		DELAY(500);
		GSM(gsmSMSDel(1));
	}

	// Process SMS commands
	smsSplitAndParse(msg.from, msg.text);

	// Restart GSM at each countdown
	if (--gsmRestartCountdown == 0) {
		LOG_INFO("\r\nRestarting GSM...");
		GSM(gsmPowerOff());
		gsmRestartCountdown = GSM_RESTART_COUNTDOWN;
	}

	// Reschedule this timer
	synctimer_add(&sms_tmr, &timers_lst);
}
コード例 #2
0
ファイル: control.c プロジェクト: derkling/adcontrol
//=====[ Control Loop ]=========================================================
void controlSetup(void) {

	// Init list of synchronous timers
	LIST_INIT(&timers_lst);

	// Schedule SMS handling task
	GSM(gsmSMSDelRead());
	timer_setDelay(&sms_tmr, ms_to_ticks(SMS_CHECK_SEC*1000));
	timer_setSoftint(&sms_tmr, sms_task, (iptr_t)&sms_tmr);
	synctimer_add(&sms_tmr, &timers_lst);

	// Schedule Console handling task
	timer_setDelay(&cmd_tmr, ms_to_ticks(CMD_CHECK_SEC*1000));
	timer_setSoftint(&cmd_tmr, cmd_task, (iptr_t)&cmd_tmr);
	synctimer_add(&cmd_tmr, &timers_lst);

	// Setup Button handling task
	timer_setDelay(&btn_tmr, ms_to_ticks(BTN_CHECK_SEC*1000));
	timer_setSoftint(&btn_tmr, btn_task, (iptr_t)&btn_tmr);

	// Setup console RX timeout
	console_init(&dbg_port.fd);
	ser_settimeouts(&dbg_port, 0, 1000);

	// Dump ADE7753 configuration
	meter_ade7753_dumpConf();

	// Get bitmask of enabled channels
	chEnabled = ee_getEnabledChMask();

	// Get bitmask of enabled channels
	chCritical = ee_getCriticalChMask();

	// Enabling calibration only for enabled channels
	chCalib = chEnabled;

	// Setup channels calibration data
	for (uint8_t ch=0; ch<16; ch++)
		loadCalibrationData(ch);

	// Update signal level
	GSM(updateCSQ());

	// Setup Re-Calibration Weeks
	resetCalibrationCountdown();

	// Enabling the watchdog for the control loop
	WATCHDOG_ENABLE();

	// Initi the analog MUX to current channel
	switchAnalogMux(curCh);


}
コード例 #3
0
ファイル: M_XFER.CPP プロジェクト: abcweizhuo/Test3
void MN_Xfer::EvalProducts(CNodeEvalIndex & NEI)
  {
  if (NoProcessJoins()>0)
    {
    switch (SolveMethod())
      {
      case SM_Direct:
        if (NoProcessJoins()>0)
          Xfer_EvalProducts(0, Joins[0].Pressure(), &m_QFeed, &m_QProd, GSM(), &m_PCtrl0, &m_BlkEval);
        break;
      case SM_Inline:
      case SM_Buffered:
        {
        if (NoProcessJoins()>=1)
          Xfer_EvalProducts(0, Joins[0].Pressure(), &m_QFeed, &m_QProd, GSM(), NULL, &m_BlkEval);
        }
        break;
      }                
    }
  };
コード例 #4
0
ファイル: FLOT.CPP プロジェクト: abcweizhuo/Test3
void Flot::EvalProducts()
  {
  double Tc;
  SigmaQInPMin(QFd, som_ALL, Id_2_Mask(idFeed));
  int iFl = IOWithId_Self(idFlot);
  int iTl = IOWithId_Self(idTails);
  rSpConduit Fl =*IOConduit(iFl);
  rSpConduit Tl =*IOConduit(iTl);

  SpMArray Mix, flot, sink;
  CDArray  TTemp, Feed, FTemp, YTemp, ATemp, 
			     FlotRec, MassSizeInt, entrain, solids;
  Eff = Range(0.01, Eff, 1.0);

  switch (SolveMode())
    {
    case PBMODE:
    case SSMODE:
      {
      if (GSM.Enabled())
        {
        if (NJoins()>=1)
          Xfer_EvalProducts(0, Joins[0].Pressure(), NULL, NULL, RB(), GSM(), NULL);
        return;
        }
      double Solids, FMass, Entrain, gangue;
      Solids = QFd.QMass(som_Sol);
      
      RB.EvalProducts(QFd);
      Tc  = QFd.Temp();
      Mix = *QFd.Model();
      
			if (Solids < 1e-6)
				{
        Tl.QCopy(QFd);
        Fl.QZero();
        return;
        }
      
      /* Move the required % of the specie to be floated to the flotation stream, 
	    together with the required recovery of aqueous components.
      Calculate the amount of solids to report to the flotation stream based on 
      the user specified grade.  If recovery has been specified as a function of
      size, then this has to be carried out for each size fraction. */
      flot = Mix;
      sink = Mix;
      if (!RM)  // Recovery is NOT a function of size.
        {
				Grd    = Range(0.01, Grd, 1.0);
				Grade2 = Range(0.001, Grade2, 1.0 - Grd);

				// Calculate mass of floated specie and mass of gangue in floats
        FMass   = Mix[(int)iFlot] * Eff;
        flot[(int)iFlot] = FMass;
		    sink[(int)iFlot] = Mix[(int)iFlot] - flot[(int)iFlot];
        Entrain = FMass * (1.0/Grd - 1.0);
        Solids  = Solids - Mix[(int)iFlot];
        gangue  = Entrain / GTZ(Solids);

        
        /* If a second specie is also floated, calculate the amount of this specie
				   reporting to the floats */ 
				if (SecFlot)
					{
					double FlotMass, SecMass;
					FlotMass = FMass / Grd;
					SecMass  = FlotMass * Grade2;
					if (Mix[(int)iSec] < SecMass)
						{
						SecMass = Mix[(int)iSec];
						LogNote(Tag(), 0, "Insufficient Secondary specie in Flotation");
						}
					flot[(int)iSec] = SecMass;
					sink[(int)iSec] = Mix[(int)iSec] - flot[(int)iSec];

					Entrain = Entrain - SecMass;
					Solids  = Solids - Mix[(int)iSec];
					gangue  = Entrain / GTZ(Solids);
					}
				

				for (int i=0; i<SDB.No(); i++)
          {
					if (!SecFlot)
						iSec = iFlot;
					if ((i != (int)iFlot) && (i != (int)iSec) )
		        {
            if (SDB[i].IsLiq())  // Reqd liquid split to floats
		          {
              flot[i] = Mix[i] * Rec;
		          sink[i] = Mix[i] - flot[i];
		          }
            if (SDB[i].IsSol())
		          {
							double masscheck = Mix[i] * gangue;
							if (masscheck > Mix[i])
							  {
							  flot[i] = Mix[i];
                sink[i] = 0.0;
								}
              else
							  {
                flot[i] = Mix[i] * gangue;
		            sink[i] = Mix[i] - flot[i];
								}
		          }
		        if (SDB[i].IsVap()) // Allow all gases to escape
			        {
              flot[i] = 0.0;
		          sink[i] = 0.0;
		          }
		        }
	        }
          
          SetProdMakeup(PMU_IOId |PMU_Image, idFlot,  flot, Tc, Std_P, QFd.Model());
          SetProdMakeup(PMU_IOId |PMU_Image, idTails, sink, Tc, Std_P, QFd.Model());
        }

      if (RM)   // Recovery IS a function of size
				{
        SigmaQInPMin(QFd, som_ALL, Id_2_Mask(idFeed));
				double TonsTotal = QFd.QMass(som_Sol);
        const double TonsLimit = 1e-6;

        SQSzDist1 &Sz   =*SQSzDist1::Ptr(QFd.Model());
        SQSzDist1 &SzFl =*SQSzDist1::Ptr(Fl.Model());
        SQSzDist1 &SzTl =*SQSzDist1::Ptr(Tl.Model());
        
				// Transfer All Qualities / Solids to Tails and Liquids 50/50
				Fl.QSetF(QFd, SetMass_Frac, 0.0, 0.5, 0.0, Std_P);
				Tl.QSetF(QFd, SetMass_Frac, 1.0, 0.5, 0.0, Std_P);

				double FlSol = 0.0;
				double TlSol = 0.0;
				flag NoSize  = True;
				for (int d=0; d<Sz.NDistributions(); d++)
          if (Sz.DistExists(d))
            {
            SzFl.AllocDist(d);
            SzTl.AllocDist(d);
            CSD_Distribution &D  = Sz.Dist(d);
            CSD_Distribution &DT = SzTl.Dist(d);
            CSD_Distribution &DF = SzFl.Dist(d);

    				// Find the total mass in each size interval
						//=============================================

						CDArray & Size = D.PriSp[0]->FracPass;
						int len = Size.GetSize();
						if (len>0)
							{
							MassSizeInt.SetSize(len);
				  	  for(int i=0 ; i<len ; i++)
							  MassSizeInt[i] = 0.0;
							}

            for (int s=0; s<D.NPriIds(); s++)
							{
							CDArray & Size = D.PriSp[s]->FracPass;
              
							int len=Size.GetSize();
							if (len>0)
								{
								CDArray SInt;
								SInt.SetSize(len);
								double Fractions, x1, y1, tmpF;
								Fractions = 0.0;
								for(long i=0 ; i<len ; i++)
									Fractions += Size[i];
								if (Fractions <= 0.0)
									Fractions = 1.0;

								for(i=0 ; i<len ; i++)
									SInt[i] = Size[i] / Fractions;

								double TonsS = 0.0;
								for (int s1=0; s1<D.NSecIds(s); s1++)
										TonsS+= QFd.Qm(D.SzId(s,s1));
								for(i=0 ; i<len ; i++)
									{
									x1      = D.Intervals()[i];
									y1      = SInt[i];
      						tmpF    = y1 * TonsS;
									MassSizeInt[i] += tmpF;
									}
								}
							}
								//============================================

						/* First calculate the mass of each specie floated in each size interval.
						   Note: This code is hard wired for Cleveland.*/
						    
            for (s=0; s<D.NPriIds(); s++)
							{
								CDArray & Size = D.PriSp[s]->FracPass;
								CDArray & ASizeRec = SizeRec.Curve(s);
								flag  flot = False;

              
								int len = Size.GetSize();
								if (len>0)
									{
									NoSize = False;
									CDArray & Float   = DF.PriSp[s]->FracPass;
									CDArray & Tailing = DT.PriSp[s]->FracPass;
									TTemp.SetSize(len);
									Feed.SetSize(len);
									FTemp.SetSize(len);
									YTemp.SetSize(len);
                  FlotRec.SetSize(len);
                  entrain.SetSize(len);
									solids.SetSize(len);

									double Fractions, x1, y1, tmpF, tmpO;
									Fractions = 0.0;
									for(long i=0 ; i<len ; i++)
										Fractions += Size[i];
									if (Fractions <= 0.0)
										Fractions = 1.0;

									for(i=0 ; i<len ; i++)
										YTemp[i] = Size[i] / Fractions;

									double TonsS = 0.0;
									for (int s1=0; s1<D.NSecIds(s); s1++)
											TonsS+= QFd.Qm(D.SzId(s,s1));
										for(i=0 ; i<len ; i++)
											{
											x1      = D.Intervals()[i];
											y1      = YTemp[i];
      								tmpF    = y1 * TonsS;
											Feed[i] = tmpF;
											}
            
										double SpcTlSol = 0.0;
										double SpcFlSol = 0.0;
										for (i=0; i<len; i++)
        							{
											Float[i] = Range(0.0, ASizeRec[i], 1.0);
											tmpO = Float[i];
											tmpF = Feed[i];
											FTemp[i]  = Float[i] * Feed[i];
											SpcFlSol += FTemp[i];
											TTemp[i]  = Feed[i] - FTemp[i];
											SpcTlSol += TTemp[i];
											}

										if (SpcTlSol < TonsLimit)
											{
											SpcFlSol   = GTZ(SpcFlSol);
											Tailing[0] = 0.0;
											Float[0]   = FTemp[0] / SpcFlSol;
											for(i=1 ; i<len ; i++)
      									{
												Tailing[i] = 0.0;
												Float[i]   = (FTemp[i] / SpcFlSol);// + Float[i-1];
												}
											}
										if (SpcFlSol < TonsLimit)
											{
											SpcTlSol   = GTZ(SpcTlSol);
											Tailing[0] = TTemp[0] / SpcTlSol;
											Float[0]   = 0.0;
											for(i=1 ; i<len ; i++)
      									{
												Float[i]   = 0.0;
												Tailing[i] = (TTemp[i] / SpcTlSol);// + Tailing[i-1];
												}
											}
										if ((SpcTlSol > TonsLimit) && (SpcFlSol > TonsLimit))
											{
											for(i=0 ; i<len ; i++)
      									{
												Tailing[i] = (TTemp[i] / SpcTlSol);
												Float[i]   = (FTemp[i] / SpcFlSol);
												}
											}

										double TotSol    = GTZ(SpcTlSol + SpcFlSol);
										double TlSolFrac = SpcTlSol/TotSol;
										double FlSolFrac = SpcFlSol/TotSol;

										int Id;
										if (s == 0)
											Id = KCl.si();
										if (s == 1)
											Id = NaCl.si();
										if (s == 2)
											Id = InSols.si();
 
 											Tl.SetQm(Id, QFd.Qm(Id) * TlSolFrac);
											Fl.SetQm(Id, QFd.Qm(Id) * FlSolFrac);

										TlSol += SpcTlSol;
										FlSol += SpcFlSol;
									}
              }
				//=========================================================
				// Calculate the grade and recovery of the desired specie.

				double MassFloat, MassIn, MassSpecie;
				MassFloat  = Max(1e-6, Fl.QMass(som_Sol));
				MassIn     = Max(1e-6, QFd.Qm((int)iFlot));
				MassSpecie = Fl.Qm((int)iFlot);
				
				TotRecover = MassSpecie/MassIn;
				Grade      = MassSpecie/MassFloat; 

				//---------------------------------------------------------
				// Now calculate the amount of liquids reporting to the float stream
											       
        double FlLiq, TlLiq;
        double QmSIn = QFd.QMass(som_Sol);
        double QmLIn = QFd.QMass(som_Liq);
        if (QmLIn > 1.0e-6)
          {

          if (Rec>1.0e-12)
            {
            Rec = Range(0.0, Rec, 0.999);
            FlLiq = FlSol / (1.0 - Rec) - FlSol;
            FlLiq = Range(0.0, FlLiq, QmLIn);
            }
          else
            FlLiq = 0.0;
          TlLiq = QmLIn - FlLiq;

          // Convert Liquids to % of feed
          FlLiq = FlLiq / QmLIn;
          TlLiq = TlLiq / QmLIn;
          }
        else
          {
          FlLiq = 0.0;
          TlLiq = 0.0;
          }
        // Convert Solids to % of feed
        TlSol = TlSol / TonsTotal;  
        FlSol = FlSol / TonsTotal;

        for (s=0; s<SDB.No(); s++)
          if (SDB[s].IsLiq())
            {
            Fl.SetQm(s, QFd.Qm(s) * FlLiq);
            Tl.SetQm(s, QFd.Qm(s) * TlLiq);
            }

        Fl.SetTemp(QFd.Temp());
        Tl.SetTemp(QFd.Temp());

        if (NoSize)
          {
          LogNote(Tag(), 0, "No Size distr. in Flotation feed");
          Tl.QCopy(QFd);
          Fl.QZero();
          }
        }
       }
      break;
      } 
    case DYNMODE:
      {
      Contents.ZeroDeriv();
      RB.EvalProducts(QFd);
      Tc  = Contents.Temp();
      Mix = (*Contents.Model());

      double MolConc, Liquid;
      Liquid  = Contents.Mass(som_Liq);
      if (Liquid >= 1.0)
        MolConc = Contents.SpMass(iColl)/SDB[iColl].MoleWt() / Liquid;
      else
        MolConc = 0.0;
      /* Determine flotation efficiency as a function of collector
         molar concentration. */
      Eff = Range(0.0, FlotFn.Yx(MolConc), 1.0);

      /*Move the required % of the specie to be floated to the flotation stream, 
	    together with the collector.*/
      flot = Mix;
      sink = Mix;
      for (int i=0; i<SDB.No(); i++)
        {
        if (i == (int)iFlot || i == iColl)
		      {
          flot[i] = Mix[i] * Eff;
		      sink[i] = Mix[i] - flot[i];
		      } 
        else   
  	      if (SDB[i].IsSol())  // Solids report to tails
		        {
            flot[i] = 0.0;
		        sink[i] = Mix[i];
		        }
		      else  // Allow all gases to escape
			      {
            flot[i] = 0.0;
		        sink[i] = 0.0;
		        }
		    } 

      for (i=0; i<NoFlwIOs(); i++)
        if (IO_Out(i))
          switch (IOId_Self(i))
            {
            case idFlot : SetProdMakeup(PMU_IOId |PMU_Image, i, flot, Tc, Std_P, QFd.Model()); break;
            case idTails: SetProdMakeup(PMU_IOId |PMU_Image, i, sink, Tc, Std_P, QFd.Model()); break;
            default:      SetProdMakeup(PMU_IOId |PMU_Image, i, Mix,  Tc, Std_P, QFd.Model()); break;
            }  
	    break;
      }
	  }
  };    
コード例 #5
0
ファイル: HYDROCYC.CPP プロジェクト: abcweizhuo/Test3
void HydroCyclone::EvalProducts()
  {
  if (GSM.Enabled())
    {
    if (NJoins()>0)
      switch (SolveMode())
        {
        case PBMODE:
        case SSMODE:
          if (NJoins()>=1)
            Xfer_EvalProducts(0, Joins[0].Pressure(), NULL, NULL, NULL, GSM(), NULL);
          break;
        case DYNMODE:
          for (int j=0; j<NJoins(); j++)
            Xfer_EvalProducts(j, Joins[j].Pressure(), NULL, NULL, NULL, GSM(), NULL);
          break;
        }
    }
  else
    {
    Feed.QZero();
    Feed.SetPress(Std_P);
    double  Liq_in=0.0, Solids_in=0.0;
    for (int i = 0; i < NoFlwIOs(); i++)
      if (IO_In(i))
        {
        Solids_in+=IOConduit(i)->QMass(som_Sol);
        Liq_in+=IOConduit(i)->QMass(som_Liq);
        Feed.QAddF(*IOConduit(i), som_ALL, 1.0);
        }

    int ioFines=IOWithId_Self(ioidFines);
    int ioGrits=IOWithId_Self(ioidGrits);

    if (ioFines>=0 && IO_Out(ioFines))// && ioGrits>=0 && IO_Out(ioGrits))
      {
      double QmOre2Grit=Solids_in*Ore2Grit;
      double QmOre2Fine=Solids_in-QmOre2Grit;
      double QmLiq2Grit=Liq_in*Liq2Grit;
      double QmLiq2Fine=Liq_in-QmLiq2Grit;

      SpConduit & Fines = *IOConduit(ioFines);
      SpConduit & Grits = *IOBuffer(ioGrits);

      Fines.QSetM(Feed, som_Liq, QmLiq2Fine, IOP_Self(ioFines));
      Fines.QAddM(Feed, som_Sol, QmOre2Fine);
      Grits.QSetM(Feed, som_Liq, QmLiq2Grit, IOP_Self(ioGrits));
      Grits.QAddM(Feed, som_Sol, QmOre2Grit);

      if (SQSzDist1::Ptr(Feed.Model(), False))
        {
        SQSzDist1 &SzFeed=*SQSzDist1::Ptr(Feed.Model());
        SQSzDist1 &SzFine=*SQSzDist1::Ptr(Fines.Model());
        SQSzDist1 &SzGrit=*SQSzDist1::Ptr(Grits.Model());

        SzFine.SetFinesFraction(PartCrv, 0.0, ByePass2Grits);
        SzGrit.SetGritsFraction(PartCrv, 0.0, ByePass2Grits);
        }
      }
    }
  }
コード例 #6
0
ファイル: control.c プロジェクト: derkling/adcontrol
int8_t controlNotifyBySMS(const char *dest, const char *buff) { 
	int8_t result;
	uint8_t try;
	uint8_t timeout;

	LOG_INFO("Notify by SMS\nDest: %s\nText: %s\r\n", dest, buff);

	// Checking for Network availability
	try = 0; timeout = 10;
	result = gsmRegisterNetwork();
	while (result != OK) {
		LOG_WARN("Network not available\r\n");
		if (try % timeout) {
			LOG_WARN("Trying again in 60s\r\n");
			DELAY(60000);
		} else {
			// Resetting modem once every (10*timeout) mins
			gsmPowerOn();
			timeout += 10;
			if (timeout >= 250)
				timeout = 10;
		}
		result = gsmRegisterNetwork();
		try++;
	}
	
	// Checking for signal quality
	try = 0; timeout = 20;
	result = gsmUpdateCSQ();
	while (result != OK ||
			gsmCSQ() == 99 || gsmCSQ() == 0) {
		LOG_WARN("Low network signal [%d]\r\n", gsmCSQ());
		if (try % timeout) {
			LOG_WARN("Trying again in 60s\r\n");
			DELAY(60000);
		} else {
			// Resetting modem once every (20*timeout) mins
			gsmPowerOn();
			timeout += 20;
			if (timeout >= 240)
				timeout = 20;
		}
		result = gsmRegisterNetwork();
		try++;
	}

	// Trying to send the SMS
	result = 0;
	GSM(result = gsmSMSSend(dest, buff));
	return result;
}
void smsSplitAndParse(char const *from, char *sms) {
	char *cmd = sms;
	char *cmdEnd = sms;

	// Reset response buffer
	cmdBuff[0] = '\0';

	while (*cmdEnd) {
		
		// Find command separator, or end of SMS
		for ( ; (*cmdEnd && *cmdEnd != ';'); ++cmdEnd)
			;// nop
		
		// 
		if (*cmdEnd == ';') {
			*cmdEnd = '\0';
		}

		// lowercase current command
		for (char *p = cmd; *p != ' ' && *p; ++p) {
			if (*p >= 'A' && *p <= 'Z')
				*p += 'a'-'A';
		}

		//DB2(LOG_INFO("CMD: %s\r\n", cmd));

		// Parse current command
		command_parse(&dbg_port.fd, cmd);

		// Go on with next command
		*cmdEnd = ';';
		for ( ; *cmdEnd; ++cmdEnd) {
			if ((*cmdEnd != ';') && (*cmdEnd != ' '))
				break;
		}
		cmd = cmdEnd;

	}

	// If a non empty buffer has been setup: send it as response
	if (cmdBuff[0] == '\0')
		return;

	controlNotifyBySMS(from, cmdBuff);

	// Wait for SMS being delivered
	DELAY(10000);

}